BEACHSIDE BLOG

MicrosoftとかC#を好むレンジャーの個人メモ

QnA Maker の Web API を Ptyhon + Azure Functions でアクセス

前回は ヨガのポーズとその説明のデータを準備しました。続編の今回は、QnA Maker を使ってヨガのポーズを質問したらポーズの特性を答えてくれる Knowledge Base (KB、質問投げたら回答してくれるFAQチャットみたいなもの) をノーコーディングで作成します。さらにその KB を Web API で公開し、Python でコーディングしてアクセスしてみます。ローカルで実行するだけだとおもろないので Azure Functions を利用します。

目次

QnA Maker のKB作成と Web API 公開

ハンズオン

GitHub でハンズオン資料として作成しました(というか以前にあったやつをバージョンアップしただけですが)。

qna-maker-hands-on/get-started.md at master · beachside-project/qna-maker-hands-on · GitHub

全体的な流れは以下です。

  • (QnA Maker ポータル経由で) Azure ポータルで QnA Maker のリソースを作成する
  • ヨガのポーズのQAペアのデータをアップロードして Knowledge Base (KB) を作成する
  • 軽くテストしてから Web API を公開する
  • Postman で Web API にアクセスしてみる

次は....

手順通り進めると、最後に Web API を公開して終わるので、ここからは Python で公開した API にアクセスしてみましょう。せっかくなので Azure Functions の HTTP トリガーでの実装をします。

Azure Functions とは?感がある場合はこちらを参照するとよいでしょう。
- Azure Functions の概要 | Microsoft Docs
- Azure Functions V2 を利用する際に見ておきたいドキュメント(初学者向け) - BEACHSIDE BLOG

ということで、さっそく作りましょう。

Azure Functions ( Python ) の実装

ローカル環境で開発を進めます。私の環境は以下です。

  • VS Code
  • Python 3.6 ( Azure Functions が 3.6 でって書いてるので、Anaconda で 3.6 の環境を使っています。Anaconda のセットアップはむかーし ここで書いてたり...)
  • Azure Functions Core Tools(インストール方法はこちら ): version 2.7.1505

コマンドでポチポチ作っていきますので、Azure Functions Core Tools がないと動きません。インストールしてない方はすぐ上のリンクからインストールしましょう。

プロジェクトと Function の作成

HTTP トリガーの Azure Functions を作成します。VS Code でプロジェクトを作成するディレクトリを開き、VS Code のターミナルで以下のコマンドをうちます。サンプルっぽく QnAFuncProj というプロジェクト名でプロジェクトを作成するコマンドです。

func init QnAFuncProj

worker runtime を聞かれますので、 `python(preview)' を選択します。

作成した QnAFuncProj ディレクトリに移動します。

cd QnAFuncProj

で、Function を作ります。

func new

template の選択が表示されますので、Http Trigger を選びます。次に関数名の入力になりますので適当に QnaFaq とします。

f:id:beachside:20190812045108p:plain

基本的なファイル構成

code . とコマンドを打って VS Code を開きましょう。以下図のフォルダー構成になっています。デフォルトは最小限のものができてる、つまり全て重要なので、ざっくりと何なのか説明します。

file 説明
QnAFaq > init.py デフォルトではこの中の main メソッドが HTTP Trigger のエントリーポイントになります。function.json でカスタマイズできます。
QnAFaq > functions.json トリガーやバインドの設定、アクセスレベルを制限などの各種変更ができます。こちらの HttpTrigger のバインド構成を参考にしましょう。
host.json 最大の実行時間HTTPの最大並列数など Functions の Host の設定ができます。ガチで利用する際はリファレンスを確認しておきましょう。
local.settings.json ローカルデバッグ時の環境変数を定義します。ここで定義したものと同じキーを Azure Functions の環境変数にも設定する感じですね。
requirements.txt Azure Functions のホストにインストールしたいパッケージがある場合はこの中に定義します。のちほど説明します。

f:id:beachside:20190812045339p:plain:w400

環境変数の設定(ローカルデバッグ用)

local.settings.json を以下のように、QnA から始まる3つを追加しました。

{
  "IsEncrypted": false,
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "python",
    "AzureWebJobsStorage": "{AzureWebJobsStorage}",
    "QnAMakerHost": "",
    "QnAMakerMethod": "",
    "QnAMakerEndpointKey": ""
  }
}

追加した3つの値は、QnA Maker のポータルで作成した KB の SETTINGSを開き情報を取得します。

  • QnAMakerHost には、 Host の値を入力します。
  • QnAMakerMethod には、 /knowledgebase/..../generateAnswer の値を入力します。
  • QnAMakerEndpointKey には、 Authorization の値を入力します("EndpointKey" って文字は不要です)

f:id:beachside:20190812050735p:plain

メイン処理の実装

次は、init.py を以下のように編集します。

6-8 行目は、環境変数を取得しています。デバッグ実行なら local.settings.json、Auzre 上なら Azure Functions の環境変数を見に行ってくれます(もちろん他に独自にも設定はできますが )。

17 行目の get_answers_from_qna メソッドは、QnA Maker の Web API を叩いてます。やってることは、こちらの QnA Maker 作成のハンズオンの手順 の Postman でアクセスしている内容をコードにしたシンプルなコードです。

後は、エントリーポイントの main メソッドで、HTTP request の Body の json から question というキーの値を抜き出しているだけですね。ここは別に (HTTP の) GET メソッドでクエリパラメーターでもいいんでもなんでもいいと思いますが特に理由なくこの実装にしました。

35-36 行目で QnA Maker からの Web API の結果を返しています。

デバッグ実行

F5 キーを押してデバッグしてみましょう。正常であれば、下図のように Function の URL が表示されます。

f:id:beachside:20190812052124p:plain

Postman からアクセスしてみましょう。

  • URL は、上図に表示されている http://localhost:7071/api/QnaFaq です。
  • メソッドは POST にしてます。
  • Body には JSON で {"question": "天地開脚ってどんなポーズ?"} と入力しています。

[ Send ] ボタンをクリックすると、正常にレスポンスが返ってくることが確認できます。実行時エラーが起きた場合は、 VS Code のターミナルにエラーが表示されてると思うので見てみましょう。

f:id:beachside:20190812052342p:plain

デプロイ 前の準備: requirements.txt を編集

Azure 上で Functions に python のパッケージを追加するために requirements.txt に書きます。記載方法は以下の感じで、パッケージ名とバージョンを書きます。

requests==2.22.0

Azure 上で Functions のリソース作成とデプロイ

公式ドキュメントではコマンドで作成しているので、このブログでは Azure Portal から GUI で作成してみます。

Python の Functions 作成時の注意点

2019/8月時点ではプレビューでまだ色んな制約があります。

  • OS が Linux でしか動きません(これもプレビュー中)
  • リージョンが限られます。
  • 同一のリソースグループに Windows OS の Function App は同居できません。

いろいろプレビュー中なので、これ作るなら個別のリソースグループ作ってやってねってところですね。個人的にはいつもこんな条件下での開発なのでなので怯むに値しません。レッツ人柱!

(個人的所感では)人柱ゆーほどの不安定ではありませんが、プロダクションで使う際は要注意くらいです。

Function App の作成

Azure Portal ( https://portal.azure.com/ ) にログインし、左上の [リソースの作成] > Function App と検索します。

f:id:beachside:20190813110144p:plain

Function App で作成をし、以下を参考に入詳細の情報を力します。

  • アプリ名: 任意の名前を入力。URLになるので一意になる必要があります。今回は「yoga-qna-demo」としています。あとでコマンド打つときで使います。
  • サブスクリプション: 自身のサブスクリプションを選択。
  • リソースグループ: 任意に新規に作ります。
  • OS: 「Linux」を選びます。 Windows を選ぶと Python のランタイムを選べません。
  • 公開: 「コード」
  • ホスティングプラン: 「従量課金プラン」を選びます。
  • 場所: 任意の場所を選択
  • ランタイムスタック: 「Python」
  • Storage: 新規作成でデフォルトで記入されているもので問題ないです。
  • Application Insights: 任意のものを選ぶ、または作成します。

作成ボタンをクリックしましょう。

f:id:beachside:20190812124529p:plain:w300

環境変数の設定 on Azure

リソースができたら移動しまし、作成した Function App の 構成 をクリックします。

f:id:beachside:20190812130357p:plain:w600

アプリケーション設定が表示されます。これが環境変数の設定できるところです。+新しいアプリケーション設定 をクリックし、local.settings.json で追加した3つの環境変数を設定しましょう。

設定後、上部の 保存 をクリックします。

f:id:beachside:20190812130858p:plain:w600

デプロイ

拡張で Azure Functions Core Tools さえインストール入ってれば大丈夫なはず...Azure CLI必要かな?入ってない環境を持ってないからわからん...

VS Code に戻って func のコマンドでデプロイします。

VS Code のターミナルで、以下のコマンドで Azure Portal にログインします。ブラウザが立ち上がってくるので先ほど Function App を作成したアカウントでログインします。

az login

ログインした時に、先ほど作成したサブスクリプションの isDefaultture になってることを確認しましょう。

f:id:beachside:20190812132407p:plain:w600

true になってない場合は以下のコマンドで設定を変更・確認します。
- az account set --sbuscription "サブスクリプションの name の値を入力!" とコマンド叩いてデフォルトを変更
- az account list を叩いてデフォルトになっていることを確認

デプロイします。Function App のアプリ名を「yoga-qna-demo」と付けたので、コマンドは以下になります。

func azure functionapp publish yoga-qna-demo

f:id:beachside:20190812133246p:plain:w600

動作確認

Postman で Azure 上の Function にアクセスして動作確認してみましょう。

まず、URL を取得するのに Azure Portal の Functions のリソースを開きます。今回作成した yoga-qna-demo の QnaFaq をクリックします。 右側の [関数の URL の取得] をクリックすると URL が表示されます。

見ておきたい部分として URL の後ろにクエリパラメーターで ?code=.... がついてます。これは、functions.json で authLevel を設定していない = デフォルト値の function になっているため付与された API 固有のキーです。

f:id:beachside:20190813110144p:plain

この URL に Postman でアクセスしてみましょう。URL 以外の設定は デバッグ実行した時と同じです。

f:id:beachside:20190812134550p:plain

エラーが出た場合は、Azure Portal の Functions のリソースで先ほど開いてた yoga-qna-demo の QnaFaq の下の方に ログ という表示があります。これを開くとコンソールのログが表示されますので、エラーを解決しましょう。

参考