CLI を使用してリアルタイム推論用のフローをオンライン エンドポイントにデプロイする

警告

Microsoft Foundry と Azure Machine Learning のプロンプト フローは、2027 年 4 月 20 日に廃止されます。 新しい開発では、プロンプト フローは推奨されなくなりました。 2027 年 4 月 20 日より前に、既存の Prompt フロー アプリケーションとデプロイを Microsoft Agent Framework に移行します。

Prompt Flow コンテナーイメージへの更新 (セキュリティ更新やパッケージ更新を含む) は、今後行われません。 これは、 promptflow-runtimepromptflow-runtime-stablepromptflow-pythonなどのプロンプト フロー ランタイム イメージに適用されます。

2027 年 4 月 20 日以降、Microsoft Foundry と Azure Machine Learning の Web 作成エクスペリエンス、VS Code 拡張機能、関連する Prompt フロー コンテナー イメージなど、プロンプト フローはサポートされなくなり、使用できなくなります。

アプリケーションがプロンプト フローのデプロイまたはランタイム イメージに依存している場合は、提供終了日より前に、サポートされている代替手段 (Microsoft Agent Framework にワークロードを移動することを計画します。 移行ガイダンスについては、プロンプト フロー移行ガイドと移行コード サンプルを参照してください。

この記事では、Azure Machine Learning v2 CLI を使用して、リアルタイム推論に使用するためにフローを マネージド オンライン エンドポイント または Kubernetes オンライン エンドポイント にデプロイする方法について説明します。

開始する前に、フローを適切にテストし、運用環境にデプロイする準備ができていることを確認してください。 フローのテストの詳細については、フローの テストを参照してください。 フローをテストした後、マネージド オンライン エンドポイントとデプロイを作成する方法と、リアルタイム推論にエンドポイントを使用する方法について説明します。

  • この記事では、CLI エクスペリエンスの使用方法について説明します。
  • Python SDK については、この記事では取り上げません。 代わりに、GitHubサンプル ノートブックを参照してください。 Python SDK を使用するには、Azure Machine Learning用の Python SDK v2 が必要です。 詳細については、「 Azure Machine Learningを参照してください。

重要

この記事でマークされている項目 (プレビュー) は、現在パブリック プレビュー段階です。 プレビュー バージョンはサービス レベル アグリーメントなしで提供され、運用環境のワークロードには推奨されません。 特定の機能がサポートされていないか、機能が制限されている可能性があります。 詳細については、「Microsoft Azure プレビューの使用条件を参照してください。

前提 条件

  • Azure CLIおよびAzure CLI用のAzure Machine Learning拡張機能。 詳細については、 CLI (v2) のインストール、セットアップ、および使用を参照してください。
  • Azure Machine Learning ワークスペース。 お持ちでない場合は、「 クイック スタート: ワークスペース リソースを作成 する」の記事の手順に従って作成します。
  • Azureロールベースのアクセス制御 (Azure RBAC) は、Azure Machine Learningの操作へのアクセスを許可するために使用されます。 この記事の手順を実行するには、ユーザー アカウントに、Azure Machine Learning ワークスペースの所有者または共同作成者ロール、または "Microsoft" を許可するカスタム ロールが割り当てられている必要があります。MachineLearningServices/workspaces/onlineEndpoints/". Studio を使用してオンライン エンドポイントとデプロイを作成および管理する場合は、リソース グループの所有者から別途 "Microsoft.Resources/deployments/write" 権限を付与してもらう必要があります。 詳細については、「Azure Machine Learning ワークスペースへのアクセスの管理を参照してください。

メモ

マネージド オンライン エンドポイントは、マネージド仮想ネットワークのみをサポートします。 ワークスペースがカスタム仮想ネットワーク内にある場合は、Kubernetes オンライン エンドポイントにデプロイするか、 Docker などの他のプラットフォームにデプロイできます。

デプロイのための仮想マシン クォータの割り当て

マネージド オンライン エンドポイントの場合、Azure Machine Learningはアップグレードを実行するためにコンピューティング リソースの 20% を予約します。 そのため、デプロイで特定の数のインスタンスを要求する場合は、エラーが発生しないように ceil(1.2 * number of instances requested for deployment) * number of cores for the VM SKU のクォータが必要です。 たとえば、デプロイでStandard_DS3_v2 VM のインスタンス (4 つのコアが付属) を 10 個要求する場合は、48 コア (12 インスタンス 4 コア) のクォータが使用可能である必要があります。 使用量と要求クォータの引き上げを表示するには、「Azure ポータルで使用量とクォータを表示するを参照してください。

フローをデプロイする準備をする

各フローには、フローのコード、プロンプト、定義、およびその他の成果物を含むフォルダーがあります。 UI を使用してフローを開発する場合は、フローの詳細ページからフロー フォルダーをダウンロードできます。 CLI または SDK を使用してフローを開発する場合は、フロー フォルダーが既にあります。

この記事では、例としてサンプル フロー "basic-chat"を使用して、Azure Machine Learning のマネージド オンライン エンドポイントにデプロイする方法を示します。

重要

フローで additional_includes を使用する場合は、最初に pf flow build --source <path-to-flow> --output <output-path> --format docker を使用して、解決済みのバージョンのフロー フォルダーを取得します。

既定のワークスペースを設定する

CLI の既定のワークスペースとリソース グループを設定するには、次のコマンドを使用します。

az account set --subscription <subscription ID>
az configure --defaults workspace=<Azure Machine Learning workspace name> group=<resource group>

フローをモデルとして登録する (省略可能)

オンライン デプロイでは、登録済みのモデルを参照するか、モデル パス (モデル ファイルをアップロードする場所) をインラインで指定できます。 モデルを登録し、デプロイ定義でモデル名とバージョンを指定します。 フォーム model:<model_name>:<version>を使用します。

次の例は、チャット フローのモデル定義を示しています。

メモ

フローがチャット フローでない場合は、これらの propertiesを追加する必要はありません。

$schema: https://azuremlschemas.azureedge.net/latest/model.schema.json
name: basic-chat-model
path: ../../../../examples/flows/chat/basic-chat
description: register basic chat flow folder as a custom model
properties:
  # In AuzreML studio UI, endpoint detail UI Test tab needs this property to know it's from prompt flow
  azureml.promptflow.source_flow_id: basic-chat
  
  # Following are properties only for chat flow 
  # endpoint detail UI Test tab needs this property to know it's a chat flow
  azureml.promptflow.mode: chat
  # endpoint detail UI Test tab needs this property to know which is the input column for chat flow
  azureml.promptflow.chat_input: question
  # endpoint detail UI Test tab needs this property to know which is the output column for chat flow
  azureml.promptflow.chat_output: answer

az ml model create --file model.yamlを使用して、モデルをワークスペースに登録します。

エンドポイントを定義する

エンドポイントを定義するには、次の値を指定します。

  • エンドポイント名: エンドポイントの名前。 Azure リージョンで一意である必要があります。 名前付け規則の詳細については、「 エンドポイントの制限」を参照してください。
  • 認証モード: エンドポイントの認証方法。 キーベースの認証とAzure Machine Learningのトークンベースの認証の間で選択します。 キーの有効期限は切れないが、トークンの有効期限は切れる。 認証の詳細については、「 オンライン エンドポイントに対する認証」を参照してください。 必要に応じて、エンドポイントに説明とタグを追加します。
  • 必要に応じて、エンドポイントに説明とタグを追加します。
  • ワークスペースにアタッチする Kubernetes クラスター (AKS または Arc 対応クラスター) にデプロイする場合は、 Kubernetes オンライン エンドポイントとしてフローをデプロイできます。

次の例は、既定でシステム割り当て ID を使用するエンドポイント定義を示しています。

$schema: https://azuremlschemas.azureedge.net/latest/managedOnlineEndpoint.schema.json
name: basic-chat-endpoint
auth_mode: key
properties:
# this property only works for system-assigned identity.
# if the deploy user has access to connection secrets, 
# the endpoint system-assigned identity will be auto-assigned connection secrets reader role as well
  enforce_access_to_default_secret_stores: enabled
キー 説明
$schema (省略可能)YAML スキーマ。 YAML ファイルで使用可能なすべてのオプションを表示するには、前のコード スニペットのスキーマをブラウザーで表示します。
name エンドポイントの名前。
auth_mode キーベースの認証には key を使用します。 Azure Machine Learning トークン ベースの認証には、aml_token を使用します。 最新のトークンを取得するには、 az ml online-endpoint get-credentials コマンドを使用します。
property: enforce_access_to_default_secret_stores (プレビュー) - 既定では、エンドポイントはシステム割り当て ID を使用します。 このプロパティは、システム割り当て ID に対してのみ機能します。
- このプロパティは、接続シークレット閲覧者アクセス許可がある場合、エンドポイントシステム割り当て ID に、自動的に Azure Machine Learning ワークスペース接続シークレット閲覧者ロールが割り当てられ、推論の実行時にエンドポイントが接続に正しくアクセスできることを意味します。
- 既定では、このプロパティは 'disabled' です。

Kubernetes オンライン エンドポイントを作成する場合は、次の属性を指定する必要があります。

キー 説明
compute エンドポイントをデプロイする Kubernetes コンピューティング ターゲット。

エンドポイントのその他の構成については、 マネージド オンライン エンドポイント スキーマを参照してください。

重要

フローでMicrosoft Entra IDベースの認証接続を使用する場合、システム割り当て ID またはユーザー割り当て ID を使用する場合でも、そのリソースに対して API 呼び出しを行うことができるように、マネージド ID に対応するリソースの適切なロールを常に付与する必要があります。 たとえば、Azure OpenAI 接続で Microsoft Entra ID ベースの認証が使用されている場合は、対応する Azure OpenAI リソースのエンドポイント マネージド ID Cognitive Services OpenAI ユーザーロールまたは Cognitive Services OpenAI 共同作成者ロールを付与する必要があります。

ユーザー割り当て ID を使用する

既定では、オンライン エンドポイントを作成すると、システムによって自動的にシステム割り当てマネージド ID が生成されます。 エンドポイントの既存のユーザー割り当てマネージド ID を指定することもできます。

ユーザー割り当て ID を使用するには、 endpoint.yaml ファイルで次の属性を指定します。

identity:
  type: user_assigned
  user_assigned_identities:
    - resource_id: user_identity_ARM_id_place_holder

また、次の例に示すように、deployment.yaml ファイルの environment_variables の下で、ユーザー割り当て ID の Client ID を指定します。 Client IDは、Azure ポータルのマネージド ID のOverviewにあります。

environment_variables:
  AZURE_CLIENT_ID: <client_id_of_your_user_assigned_identity>

重要

推論を実行するためにAzure リソースにアクセスできるように、エンドポイントを作成する前に、ユーザー割り当て ID に次のアクセス許可を付与する必要があります。 詳細については、 エンドポイント ID にアクセス許可を付与する方法を参照してください

Scope 役割 必要な理由
Azure Machine Learning ワークスペース Azure Machine Learning ワークスペースの接続シークレット閲覧者ロール または "Microsoft.MachineLearningServices/workspaces/connections/listsecrets/action" を持つカスタマイズされたロール。 ワークスペース接続を取得する
ワークスペース コンテナー レジストリ ACR のプル コンテナー イメージのプル
ワークスペースの既定のストレージ ストレージ BLOB データ リーダー ストレージからモデルを読み込む
(省略可能)Azure Machine Learning ワークスペース ワークスペース メトリック ライター エンドポイントをデプロイした後、CPU、GPU、ディスク、メモリの使用率などのエンドポイント関連のメトリックを監視する場合は、ID にこのアクセス許可を付与する必要があります。

デプロイを定義する

デプロイは、実際の推論を行うモデルをホストするために必要なリソースのセットです。

次の例は、デプロイ定義を示しています。 modelセクションは、登録済みのフロー モデルを参照します。 フロー モデルのパスを行で指定することもできます。

$schema: https://azuremlschemas.azureedge.net/latest/managedOnlineDeployment.schema.json
name: blue
endpoint_name: basic-chat-endpoint
model: azureml:basic-chat-model:1
  # You can also specify model files path inline
  # path: examples/flows/chat/basic-chat
environment: 
  image: mcr.microsoft.com/azureml/promptflow/promptflow-runtime:latest
  # inference config is used to build a serving container for online deployments
  inference_config:
    liveness_route:
      path: /health
      port: 8080
    readiness_route:
      path: /health
      port: 8080
    scoring_route:
      path: /score
      port: 8080
instance_type: Standard_E16s_v3
instance_count: 1
environment_variables:
  # for pulling connections from workspace
  PRT_CONFIG_OVERRIDE: deployment.subscription_id=<subscription_id>,deployment.resource_group=<resource_group>,deployment.workspace_name=<workspace_name>,deployment.endpoint_name=<endpoint_name>,deployment.deployment_name=<deployment_name>

  # (Optional) When there are multiple fields in the response, using this env variable will filter the fields to expose in the response.
  # For example, if there are 2 flow outputs: "answer", "context", and I only want to have "answer" in the endpoint response, I can set this env variable to '["answer"]'.
  # If you don't set this environment, by default all flow outputs will be included in the endpoint response.
  # PROMPTFLOW_RESPONSE_INCLUDED_FIELDS: '["category", "evidence"]'
属性 説明
名前 デプロイメントの名前。
エンドポイント名 デプロイを作成するエンドポイントの名前。
モデル デプロイに使用するモデル。 この値には、ワークスペース内の既存のバージョン管理されたモデルへの参照またはインライン モデル仕様のいずれかを指定できます。
環境 モデルとコードをホストする環境。 これには次のものが含まれます。
- image
- inference_config: liveness routereadiness_routescoring_route など、オンライン デプロイ用のサービス コンテナーを構築するために使用されます。
インスタンスの種類 デプロイに使用する VM サイズ。 サポートされているサイズの一覧については、 マネージド オンライン エンドポイント SKU の一覧を参照してください
インスタンス数 デプロイに使用するインスタンスの数。 期待するワークロードに基づいて値を設定します。 高可用性を実現するために、この値を少なくとも 3 に設定します。 このサービスでは、アップグレードを実行するために追加の 20% が予約されます。 詳細については、 オンライン エンドポイントの制限を参照してください。
環境変数 フローからデプロイされたエンドポイントに対して、次の環境変数を設定します。
- (必須) PRT_CONFIG_OVERRIDE: ワークスペースから接続を取得するため
- (省略可能) PROMPTFLOW_RESPONSE_INCLUDED_FIELDS:: 応答に複数のフィールドがある場合は、この env 変数を使用して、応答で公開するフィールドをフィルター処理します。
たとえば、"answer"、"context" という 2 つのフロー出力があり、エンドポイント応答に "answer" のみを含める場合は、この env 変数を '["answer"] に設定できます。

重要

フロー フォルダーに、フローの実行に必要な依存関係を含む requirements.txt ファイルがある場合は、 カスタム環境の手順でデプロイ に従って、依存関係を含むカスタム環境を構築します。

Kubernetes オンライン デプロイを作成する場合は、次の属性を指定します。

属性 説明
タイプ デプロイメントのタイプ。 値を kubernetes に設定します。
インスタンスの種類 デプロイに使用する Kubernetes クラスターで作成したインスタンスの種類。 これは、デプロイの要求と制限コンピューティング リソースを表します。 詳細については、「 インスタンスの種類の作成と管理」を参照してください。

オンライン エンドポイントを Azure にデプロイする

クラウドにエンドポイントを作成するには、次のコードを実行します。

az ml online-endpoint create --file endpoint.yml

エンドポイントの下に blue という名前のデプロイを作成するには、次のコードを実行します。

az ml online-deployment create --file blue-deployment.yml --all-traffic

メモ

このデプロイには 15 分以上かかる場合があります。

ヒント

CLI コンソールをブロックしない場合は、コマンドにフラグ --no-wait を追加します。 ただし、このフラグは、デプロイ状態の対話型表示を停止します。

重要

前の --all-traffic コマンドのaz ml online-deployment create フラグは、新しく作成されたblueデプロイにエンドポイント トラフィックの 100% を割り当てます。 この割り当ては開発とテストの目的で役立ちますが、運用環境では、明示的なコマンドを使用して新しいデプロイへのトラフィックを開く必要があります。 たとえば、 az ml online-endpoint update -n $ENDPOINT_NAME --traffic "blue=100"

エンドポイントとデプロイの状態を確認する

エンドポイントの状態を確認するには、次のコードを実行します。

az ml online-endpoint show -n basic-chat-endpoint

デプロイの状態を確認するには、次のコードを実行します。

az ml online-deployment get-logs --name blue --endpoint basic-chat-endpoint

モデルを使用してエンドポイントを呼び出してデータをスコア付けする

sample-request.json ファイルを作成します。

{
  "question": "What is Azure Machine Learning?",
  "chat_history":  []
}
az ml online-endpoint invoke --name basic-chat-endpoint --request-file sample-request.json

curlなどの HTTP クライアントを使用してエンドポイントを呼び出すこともできます。

ENDPOINT_KEY=<your-endpoint-key>
ENDPOINT_URI=<your-endpoint-uri>

curl --request POST "$ENDPOINT_URI" --header "Authorization: Bearer $ENDPOINT_KEY" --header 'Content-Type: application/json' --data '{"question": "What is Azure Machine Learning?", "chat_history":  []}'

エンドポイント キーとエンドポイント URI を Endpoints>Consume>Basic の消費情報のAzure Machine Learning ワークスペースから取得します。

高度な構成

フロー開発とは異なる接続を使用してデプロイする

デプロイ中にフローの接続を上書きしたい場合があります。

たとえば、flow.dag.yaml ファイルで my_connection という名前の接続が使用されている場合は、次のようにデプロイ yaml の環境変数を追加することでオーバーライドできます。

オプション 1: 接続名をオーバーライドする

environment_variables:
  my_connection: <override_connection_name>

接続の特定のフィールドをオーバーライドする場合は、名前付けパターン <connection_name>_<field_name>を使用して環境変数を追加することでオーバーライドできます。 たとえば、フローで my_connection という構成キーを持つ chat_deployment_name という名前の接続が使用されている場合、サービス バックエンドは既定で環境変数 'MY_CONNECTION_CHAT_DEPLOYMENT_NAME' からchat_deployment_nameを取得しようとします。 環境変数が設定されていない場合は、フロー定義の元の値が使用されます。

オプション 2: 資産を参照してオーバーライドする

environment_variables:
  my_connection: ${{azureml://connections/<override_connection_name>}}

メモ

同じワークスペース内の接続のみを参照できます。

カスタム環境を使用してデプロイする

このセクションでは、Docker と Azure Machine Learning 環境に関する知識があると仮定して、Docker ビルド コンテキストを使用してデプロイの環境を指定する方法について説明します。

  1. ローカル環境で、次のファイルを含む image_build_with_reqirements という名前のフォルダーを作成します。

    |--image_build_with_reqirements
    |  |--requirements.txt
    |  |--Dockerfile
    
    • フロー フォルダーから継承された requirements.txt ファイルは、フローの依存関係を追跡します。

    • 次の例のようなコンテンツを含むDockerfile:

      FROM mcr.microsoft.com/azureml/promptflow/promptflow-runtime:latest
      COPY ./requirements.txt .
      RUN pip install -r requirements.txt
      
  2. デプロイ定義 YAML ファイルの環境セクションを次の内容に置き換えます。

    environment: 
      build:
        path: image_build_with_reqirements
        dockerfile_path: Dockerfile
      # deploy prompt flow is BYOC, so we need to specify the inference config
      inference_config:
        liveness_route:
          path: /health
          port: 8080
        readiness_route:
          path: /health
          port: 8080
        scoring_route:
          path: /score
          port: 8080
    

FastAPI サービス エンジンの使用 (プレビュー)

既定では、プロンプト フロー サービスでは FLASK サービス エンジンが使用されます。 プロンプト フロー SDK バージョン 1.10.0 以降では、FastAPI ベースのサービス エンジンがサポートされています。 環境変数fastapiを指定することで、PROMPTFLOW_SERVING_ENGINE サービス エンジンを使用できます。

environment_variables:
  PROMPTFLOW_SERVING_ENGINE=fastapi

デプロイの同時処理を設定する

フローをオンラインデプロイにデプロイするときは、コンカレンシーのために 2 つの環境変数 ( PROMPTFLOW_WORKER_NUMPROMPTFLOW_WORKER_THREADS) を構成します。 また、 max_concurrent_requests_per_instance パラメーターを設定する必要もあります。

次の例は、 deployment.yaml ファイルでこれらの設定を構成する方法を示しています。

request_settings:
  max_concurrent_requests_per_instance: 10
environment_variables:
  PROMPTFLOW_WORKER_NUM: 4
  PROMPTFLOW_WORKER_THREADS: 1
  • PROMPTFLOW_WORKER_NUM: このパラメーターは、1 つのコンテナーで開始されるワーカー (プロセス) の数を設定します。 既定値は CPU コアの数に等しく、最大値は CPU コアの数の 2 倍です。

  • PROMPTFLOW_WORKER_THREADS: このパラメーターは、1 つのワーカーで開始するスレッドの数を設定します。 既定値は 1 です。

    メモ

    PROMPTFLOW_WORKER_THREADSを 1 より大きい値に設定する場合は、フロー コードがスレッド セーフであることを確認します。

  • max_concurrent_requests_per_instance: デプロイで許可されるインスタンスあたりの同時要求の最大数。 既定値は 10 です。

    max_concurrent_requests_per_instanceの推奨値は、要求時間によって異なります。

    • 要求時間が 200 ミリ秒を超える場合は、 max_concurrent_requests_per_instancePROMPTFLOW_WORKER_NUM * PROMPTFLOW_WORKER_THREADS に設定します。
    • 要求時間が 200 ミリ秒以下の場合は、 max_concurrent_requests_per_instance(1.5-2) * PROMPTFLOW_WORKER_NUM * PROMPTFLOW_WORKER_THREADS に設定します。 この設定では、一部の要求がサーバー側でキューに入れるようにすることで、合計スループットを向上させることができます。
    • リージョンをまたがる要求を送信する場合は、しきい値を 200 ミリ秒から 1 秒に変更できます。

これらのパラメーターを調整しながら、次のメトリックを監視して、最適なパフォーマンスと安定性を確保します。

  • このデプロイのインスタンス CPU とメモリ使用率
  • 200 以外の応答 (4xx、5xx)
    • 429 応答を受け取った場合、通常、この状態コードは、前のガイドに従ってコンカレンシー設定を再調整するか、デプロイをスケーリングする必要があることを示します。
  • Azure OpenAI スロットル ステータス

エンドポイントの監視

一般的なメトリックを収集する

オンライン展開の一般的なメトリック (要求数、要求待機時間、ネットワーク バイト、CPU/GPU/ディスク/メモリ使用率など) を表示できます。

推論時にトレース データとシステム メトリックを収集する

デプロイ yaml ファイルにプロパティ app_insights_enabled: true を追加することで、トレース データを収集し、ワークスペースのリンクされた Application Insights への推論時間中にフローのデプロイ固有のメトリック (トークン消費、フロー待機時間など) を確認できます。 詳細については、プロンプト フロー デプロイのトレースとメトリックを参照してください。

プロンプト フロー固有のメトリックとトレースを指定して、ワークスペースのリンクされたメトリックではない他の Application Insights に指定できます。 デプロイ yaml ファイルには、次のように環境変数を指定できます。 Application Insights の接続文字列は、Azure ポータルの [概要] ページで確認できます。

environment_variables:
  APPLICATIONINSIGHTS_CONNECTION_STRING: <connection_string>

メモ

app_insights_enabled: true設定しただけで、ワークスペースに Application Insights がリンクされていない場合、デプロイは失敗しませんが、データは収集されません。 app_insights_enabled: trueと上記の環境変数の両方を同時に指定すると、トレース データとメトリックがワークスペースのリンクされた Application Insights に送信されます。 別の Application Insights を指定するには、環境変数のみを保持します。

一般的なエラー

エンドポイントを使用するときのアップストリーム要求タイムアウトの問題

このエラーは通常、タイムアウトが原因で発生します。 既定では、 request_timeout_ms 値は 5,000 ミリ秒です。 最大 5 分 (300,000 ミリ秒) を設定できます。 次の例は、デプロイ YAML ファイルで要求タイムアウトを指定する方法を示しています。 デプロイ スキーマの詳細については、「 マネージド オンライン デプロイ スキーマ」を参照してください。

request_settings:
  request_timeout_ms: 300000

重要

300,000 ミリ秒のタイムアウトは、 プロンプト フローからのマネージド オンライン展開でのみ機能します。 プロンプト以外のフローで管理されるオンライン エンドポイントの最大タイムアウトは 180 秒です。

このデプロイがプロンプト フローからのものであることを示すには、次のようにモデルのプロパティを追加します (デプロイ YAML のインライン モデル仕様またはスタンドアロン モデル仕様 YAML)。

properties:
  # indicate a deployment from prompt flow
  azureml.promptflow.source_flow_id: <value>

次の手順