次の方法で共有


例: Python を使用してカスタム スキルを作成する (アーカイブ済み)

この例はアーカイブされ、サポート対象外です。 Python と Visual Studio Code を使用して Web API カスタム スキルを作成する方法について説明しました。 この例では、カスタム スキル インターフェイスを実装する Azure Function を使用しました。

前提 条件

  • カスタム スキル インターフェイスを確認して、カスタム スキルが実装する必要がある入力と出力を確認します。

  • 環境を設定します。 クイック スタート: Visual Studio Code を使用して Python を使用して Azure で関数を作成し、Visual Studio Code と Python 拡張機能を使用してサーバーレス Azure 関数を設定する方法について説明しました。 このクイック スタートでは、次のツールとコンポーネントのインストールについて説明します。

Azure 関数を作成する

この例では、Azure 関数を使用して Web API をホストする概念を示しますが、他の方法も可能です。 コグニティブ スキルのインターフェイス要件を満たしている限り、取るアプローチは重要ではありません。 ただし、Azure Functions を使用すると、カスタム スキルを簡単に作成できます。

関数のプロジェクトを作成する

Visual Studio Code の Azure Functions プロジェクト テンプレートは、Azure の関数アプリに発行できるローカル プロジェクトを作成します。 関数アプリを使用すると、リソースの管理、デプロイ、共有のための論理ユニットとして関数をグループ化できます。

  1. Visual Studio Code で F1 キーを押してコマンド パレットを開きます。 コマンド パレットで、Azure Functions: Create new project...を検索して選択します。
  2. プロジェクトワークスペースのディレクトリの場所を選択し、を選択してを選択します。 既に別のワークスペースに含まれているプロジェクト フォルダーは使用しないでください。
  3. 関数アプリ プロジェクトの言語を選択します。 このチュートリアルでは、Python 選択します。
  4. Python バージョンを選択します (バージョン 3.7.5 は Azure Functions でサポートされています)。
  5. プロジェクトの最初の関数のテンプレートを選択します。 HTTP トリガー 選択して、新しい関数アプリで HTTP によってトリガーされる関数を作成します。
  6. 関数名を指定します。 この場合は、「連結器」を使いましょう。
  7. 承認レベルとして 関数 を選択します。 関数アクセス キーを使用して、関数の HTTP エンドポイントを呼び出します。
  8. プロジェクトを開く方法を指定します。 この手順では、[ワークスペースに追加] を選択して、現在のワークスペースに関数アプリを作成します。

Visual Studio Code によって、関数アプリ プロジェクトが新しいワークスペースに作成されます。 このプロジェクトには、host.json ファイルと local.settings.jsonconfiguration ファイル、および言語固有のプロジェクト ファイルが含まれています。

新しい HTTP によってトリガーされる関数は、関数アプリ プロジェクトの Concatenator フォルダーにも作成されます。 その中には、次の内容を含む "__init__.py" というファイルがあります。

import logging

import azure.functions as func


def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    name = req.params.get('name')
    if not name:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            name = req_body.get('name')

    if name:
        return func.HttpResponse(f"Hello {name}!")
    else:
        return func.HttpResponse(
             "Please pass a name on the query string or in the request body",
             status_code=400
        )

次に、カスタム スキル インターフェイスに従って、そのコードを変更してみましょう。 既定のコードを次の内容に置き換えます。

import logging
import azure.functions as func
import json

def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    try:
        body = json.dumps(req.get_json())
    except ValueError:
        return func.HttpResponse(
             "Invalid body",
             status_code=400
        )
    
    if body:
        result = compose_response(body)
        return func.HttpResponse(result, mimetype="application/json")
    else:
        return func.HttpResponse(
             "Invalid body",
             status_code=400
        )


def compose_response(json_data):
    values = json.loads(json_data)['values']
    
    # Prepare the Output before the loop
    results = {}
    results["values"] = []
    
    for value in values:
        output_record = transform_value(value)
        if output_record != None:
            results["values"].append(output_record)
    return json.dumps(results, ensure_ascii=False)

## Perform an operation on a record
def transform_value(value):
    try:
        recordId = value['recordId']
    except AssertionError  as error:
        return None

    # Validate the inputs
    try:         
        assert ('data' in value), "'data' field is required."
        data = value['data']        
        assert ('text1' in data), "'text1' field is required in 'data' object."
        assert ('text2' in data), "'text2' field is required in 'data' object."
    except AssertionError  as error:
        return (
            {
            "recordId": recordId,
            "errors": [ { "message": "Error:" + error.args[0] }   ]       
            })

    try:                
        concatenated_string = value['data']['text1'] + " " + value['data']['text2']  
        # Here you could do something more interesting with the inputs

    except:
        return (
            {
            "recordId": recordId,
            "errors": [ { "message": "Could not complete operation for record." }   ]       
            })

    return ({
            "recordId": recordId,
            "data": {
                "text": concatenated_string
                    }
            })

transform_value メソッドは、1 つのレコードに対して操作を実行します。 特定のニーズに合わせてメソッドを変更できます。 操作を完了できない場合は、必要な入力検証を行い、エラーと警告を返してください。

コードをローカルでデバッグする

Visual Studio Code を使用すると、コードを簡単にデバッグできます。 'F5' キーを押すか、デバッグ メニューに移動し、[デバッグの開始] 選択します。

目的の行で 'F9' を押すと、コードにブレークポイントを設定できます。

デバッグを開始すると、関数がローカルで実行されます。 Postman や Fiddler などのツールを使用して、localhost に要求を発行できます。 ターミナル ウィンドウでローカル エンドポイントの場所をメモします。

Azure で関数アプリを作成する

関数の動作に満足したら、公開できます。 ここまでは、ローカルで作業してきました。 このセクションでは、Azure で関数アプリを作成し、作成したアプリにローカル プロジェクトをデプロイします。

Visual Studio Code からアプリを作成する

  1. Visual Studio Code で F1 キーを押してコマンド パレットを開きます。 コマンド パレットで Azure で関数アプリの作成を検索して選択します。

  2. アクティブなサブスクリプションが複数ある場合は、このアプリのサブスクリプションを選択します。

  3. 関数アプリに世界で一意の名前を入力します。 URL に対して有効な名前を入力します。

  4. ランタイム スタックを選択し、ローカルで実行している言語バージョンを選択します。

  5. アプリの場所を選択します。 可能であれば、検索サービスもホストする同じリージョンを選択します。

アプリの作成には数分かかります。 準備ができたら、アクティブなサブスクリプションの ResourcesFunction App の下に新しいアプリが表示されます。

Azure にデプロイする

  1. 引き続き Visual Studio Code で F1 キーを押してコマンド パレットを開きます。 コマンド パレットで「関数アプリにデプロイ...」を検索して選択します。

  2. 作成した関数アプリを選択します。

  3. 続行するかを確認し、その後を選択してをDeployします。 出力ウィンドウでデプロイの状態を監視できます。

  4. Azure portalに切り替え、[すべてのリソース]に移動します。 前の手順で指定したグローバルに一意の名前を使用して、デプロイした関数アプリを検索します。

    アドバイス (or チップ, depending on context)

    Visual Studio Code で関数アプリを右クリックし、[ポータルで開く]を選択することもできます。

  5. ポータルの左側にある Functionsを選択し、作成した関数を選択します。

  6. 関数の概要ページで、上部のコマンド バー [関数 URL の取得] を選択します。 これにより、関数を呼び出す URL をコピーできます。

    Azure portal の [関数 URL の取得] コマンドのスクリーンショット。

Azure で関数をテストする

コピーした既定のホスト キーと URL を使用して、Azure portal 内から関数をテストします。

  1. 左側の [開発者] で、[Code + Test] を選択します。

  2. コマンド バー テスト/実行 を選択します。

  3. 入力には、既定のキー Postを使用し、要求本文に貼り付けます。

    {
        "values": [
            {
                "recordId": "e1",
                "data":
                {
                    "text1":  "Hello",
                    "text2":  "World"
                }
            },
            {
                "recordId": "e2",
                "data": "This is an invalid input"
            }
        ]
    }
    
  4. を選択して実行します。

    入力仕様の のスクリーンショット

この例では、ローカル環境で関数を実行したときに前に見たのと同じ結果が生成されます。

スキルセットに追加する

新しいカスタム スキルが作成されたので、スキルセットに追加できます。 次の例は、スキルを呼び出して、タイトルと文書の作成者を1つのフィールドに連結し、merged_title_authorという名前を付ける方法を示しています。

[your-function-url-here] を新しい Azure 関数の URL に置き換えます。

{
    "skills": [
      "[... other existing skills in the skillset are here]",  
      {
        "@odata.type": "#Microsoft.Skills.Custom.WebApiSkill",
        "description": "Our new search custom skill",
        "uri": "https://[your-function-url-here]",        
          "context": "/document/merged_content/organizations/*",
          "inputs": [
            {
              "name": "text1",
              "source": "/document/metadata_title"
            },
            {
              "name": "text2",
              "source": "/document/metadata_author"
            },
          ],
          "outputs": [
            {
              "name": "text",
              "targetName": "merged_title_author"
            }
          ]
      }
  ]
}

インデクサー定義に "outputFieldMapping" を追加して、検索インデックスの "fullname" フィールドに "merged_title_author" を送信することを忘れないでください。

"outputFieldMappings": [
    {
        "sourceFieldName": "/document/content/merged_title_author",
        "targetFieldName": "fullname"
    }
]