例: Python を使用してカスタム スキルを作成する (アーカイブ済み)
この例はアーカイブされ、サポート対象外です。 Python と Visual Studio Code を使用して Web API カスタム スキルを作成する方法について説明しました。 この例では、カスタム スキル インターフェイスを実装する Azure 関数 を使用しました。
前提条件
カスタム スキル インターフェイスを確認して、カスタム スキルで実装する必要がある入力と出力を確認します。
環境を設定します。 「クイック スタート: Visual Studio Code と Python を使用して Azure に関数を作成する」に従い、Visual Studio Code と Python 拡張機能を使用してサーバーレス Azure 関数をセットアップしました。 このクイックスタートでは、次のツールとコンポーネントのインストールについて説明します。
Azure Function の作成
この例では、Azure 関数を使用して、Web API をホストするという概念を示していますが、その他の方法も可能です。 コグニティブ スキルのインターフェイス要件を満たしていれば、どのような方法を使用してもかまいません。 ただし、Azure Functions を使用すると、カスタム スキルを簡単に作成できます。
関数のプロジェクトを作成する
Visual Studio Code の Azure Functions プロジェクト テンプレートでは、Azure の関数アプリに発行できるローカル プロジェクトを作成します。 関数アプリを使用すると、リソースを管理、デプロイ、および共有するための論理ユニットとして関数をグループ化できます。
- Visual Studio Code で、F1 キーを押してコマンド パレットを開きます。 コマンド パレットで、
Azure Functions: Create new project...
を検索して選択します。 - プロジェクト ワークスペースのディレクトリの場所を選択し、 [選択] をクリックします。 既に別のワークスペースの一部になっているプロジェクト フォルダーは使用しないでください。
- 関数アプリ プロジェクトの言語を選択します。 このチュートリアルでは、[Python] を選択します。
- Python のバージョンを選びます (Azure Functions では、バージョン 3.7.5 がサポートされています)。
- プロジェクトの最初の関数のテンプレートを選択します。 [HTTP トリガー] を選択して、HTTP によってトリガーされる関数を新しい関数アプリに作成します。
- 関数名を指定します。 このケースでは、「Concatenator」を使用しましょう。
- 認証レベルとして [関数] を選択します。 関数の HTTP エンドポイントを呼び出すには関数アクセス キーを使用します。
- プロジェクトを開く方法を指定します。 この手順では、[ワークスペースに追加] を選択して、現在のワークスペースに関数アプリを作成します。
Visual Studio Code によって、新しいワークスペースに関数アプリ プロジェクトが作成されます。 このプロジェクトには、host.json ファイルと local.settings.json 構成ファイルと、言語固有のプロジェクト ファイルが含まれています。
新しい 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 からアプリを作成する
Visual Studio Code で、F1 キーを押してコマンド パレットを開きます。 コマンド パレットで、[Azure で関数アプリを作成する] を検索して選びます。
アクティブなサブスクリプションが複数ある場合は、このアプリのサブスクリプションを選びます。
関数アプリのグローバルに一意の名前を入力します。 URL に有効な名前を入力します。
ランタイム スタックを選び、ローカルで実行している言語バージョンを選びます。
アプリの場所を選択します。 可能であれば、検索サービスをホストしているのと同じリージョンを選びます。
アプリの作成には数分かかります。 準備ができたら、アクティブなサブスクリプションの [リソース] と [関数アプリ] の下に新しいアプリが表示されます。
Azure にデプロイ
引き続き Visual Studio Code で F1 キーを押してコマンド パレットを開きます。 コマンド パレットで、[Deploy to Function App...](関数アプリにデプロイする...) を検索して選択します。
作成した関数アプリを選びます。
続行することを確認し、[ デプロイ] を選びます。 デプロイの状態は、出力ウィンドウで監視できます。
Azure portal に切り替え、[すべてのリソース] に移動します。 前の手順で指定したグローバルに一意の名前を使用して、デプロイした関数アプリを検索します。
ヒント
Visual Studio Code で関数アプリを右クリックし、[ポータルで開く] を選ぶこともできます。
ポータルの左側にある [関数] を選び、作成した関数を選びます。
関数の概要ページの上部のコマンド バーで [関数の URL の取得] を選びます。 これにより、関数を呼び出す URL をコピーできます。
Azure で関数をテストする
コピーした既定のホスト キーと URL を使用して、Azure portal 内から関数をテストします。
左側の [開発者] で、[コードとテスト] を選びます。
コマンド バーで [テストと実行] を選びます。
入力には、既定のキーである Post を使用し、要求本文に貼り付けます。
{ "values": [ { "recordId": "e1", "data": { "text1": "Hello", "text2": "World" } }, { "recordId": "e2", "data": "This is an invalid input" } ] }
[実行] を選択します。
この例では、以前にローカル環境で関数を実行したときと同じ結果が得られるはずです。
スキルセットへの追加
新しいカスタム スキルが作成できたので、スキルセットに追加できます。 次の例は、スキルを呼び出して、ドキュメントのタイトルと作成者を連結して、merged_title_author という 1 つのフィールドを作成する方法を示しています。
[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"
}
]