search
LoginSignup
4

posted at

updated at

Azure復習☆彡 Azureを使ってポケモンの弱点を教えてくれるボット作成

はじめに

最近ポケモンの新作にはまってます。しかしブランクがあるといつも弱点を忘れて返り討ちにあいます。ので、なんだっけ?となったときように弱点を教えてくれるボット(Alexaのスキル)を作成しました。その過程を簡単に紹介しつつ、学んだことをアウトプットしていきます。
※最終的なコードはGitHubに上げているので詳しいコードを見たい方はそちらを確認していただければと思います。

達成したいこと

すごく簡単なイメージ図。スマートスピーカーはAlexa。
image.png

※PokeAPIなるものがありますが、情報量が多いのとAzureの復習というテーマなのであえて作ってみました。

環境と言語

  • windows10
  • Visual Studio Professional 2022
  • SQL Server Management Studio v18.4
  • .NET 6.0
  • C#
  • Azure

今回使用したAzureのリソース

  • Azure Functions
  • Azure App Service
  • Key Vault
  • Azure SQL Server

DBの作成

Azure SQL Databaseのリソース作成

リソース追加で「SQL Database」を選択して作成していきます。
image.png

image.png

👆のサーバーは新規で作成しました。「新規作成」をクリックするとこんな風にサーバーが作れます。
個人的なテスト利用なので認証方法は「SQL認証」にしました。
image.png

データベースの照合順序は仕事でいつもこちらを使用しているのでこちらの設定にしました。

image.png

入力が完了したら「確認および作成」で作成します。

作成が完了したら、作成したSQL Serverのリソースに移動して、「ネットワーク」からアクセス許可を足していきます。
image.png

ファイアーウォール規則に自分が使用しているグローバルIPアドレスを設定します。忘れがちですが、接続する環境が変わるたびに追加は必要です。
image.png

SSMSでつないでみて、データを作成する

私は使い慣れているSSMSから作成していくことにしました。

サーバー名・認証方法はAzureで設定した通りでログインできます。
image.png

こちらでテーブルとタイプを取得するプロシージャを作成。

TypeというタイプIDとタイプ名を保管したテーブルとTypeCompatibilityというポケモンの相性を保管したテーブルを作成しました。

ET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[GetTypeCompatibility]
	@TypeName AS [NVARCHAR](50)
AS
	SELECT 
		T2.TypeName as 'CompatibilityType',
		TC.Power as Power
	FROM
		TypeCompatibility TC
	INNER JOIN [dbo].[Type] T 
		ON TC.AttackTypeId = T.TypeId
	INNER JOIN [dbo].[Type] T2 
		ON TC.DefenseTypeId = T2.TypeId
	Where 
		T.TypeName = @TypeName
	;

弱点を教えてくれるAPI作成

.NET Core 6.0でAPIをつくってApp Serviceに発行しました。
発行方法は公式ドキュメントのこちらから
発行したら構成で接続文字列の設定をするのを忘れないようにしましょう!(忘れていて詰まってた)

接続文字列のKey Vault管理

接続文字列にはパスワードなども含まれています。そのためKey Vaultに保管するのがいいです。
ので、リソースにKey Vaultを追加して、シークレットの作成をします。
image.png

発行したらシークレット識別子を保存しておきます。
image.png

続いて発行したApp Serviceの構成へのアクセスを追加するために「アクセスポリシー」を追加します。
アクセス許可はひとまずシークレットの取得です。
image.png

プリンシパルはApp ServiceのオブジェクトIdで検索をすると、候補に表示されるので追加します。
image.png

※オブジェクトIdはApp Serviceの「ID」のところから見れます。なければ追加します。
image.png

作成を押すと追加されます。
image.png

最後にApp Serviceの構成の値に追加します。
「@Microsoft.KeyVault(SecretUri=)」の=の後にシークレット識別子を貼りつけます。末尾にあるGuid?みたいのは消して大丈夫です。
image.png

接続がうまくいくとソースに「キーコンテナーの参照」と表示され、緑チェックがつきます。
image.png

作成中に困ったこと

.NET 6.0は初めて使用したのですが、そのときに.NET 6.0が参照されなくて困ったので解決した方法をメモしておきます。

発生したエラーメッセージ

.netframework,version=v6.0" の参照アセンブリが見つかりませんでした。.net 5.0 以上をターゲットにするために、古い .net sdk を使用している可能性があります。visual studio と .net sdk のいずれかまたはその両方を更新してください。

このコマンドをながしたところ解決しました。
dotnet new globaljson --sdk-version 6.0.100

Azure Functionsを使ってAlexaで呼び出してみる

基本的に以前Qiitaでかいた記事通りに作成しているので、詳しい作成方法はこちらの記事をご覧ください。

以前の記事ではない任意の言葉(今回でいうとポケモンのタイプ)をFunctions側で取得した方法のみ記載したいと思います。

Alexaの設定

作成したインテントページのインテントスロットに任意の言葉の名前(今回は「type」にした)を入力して保存します。この画像ではスロットタイプが選択されていますが、スロットタイプはこの後作成します。
image.png

スロットタイプを追加します。スロット値に想定される任意の言葉を追加していきます。今回はポケモンのタイプ全16種類をかきました。
image.png

最後にインテントからサンプル発話を追加します。鍵かっこつきでスロットで入力した値を入れてあげると、そこに任意の言葉が入ったサンプル発話となります。
例えば、{いわ}タイプのポケモンの相性をおしえてという感じ。
image.png

すべて完了したらモデルを保存してビルドします。

Functions側の取得方法

「これでタイプ名が取得できるはず」というコメントの下が該当コードです。

case IntentRequest ir:
{
    // これでタイプ名が取得できるはず
    var typeName = ir.Intent.Slots["type"].Value;
    var r = await HandleIntent(ir.Intent.Name, typeName);
                        
    skillResponse.Response.OutputSpeech = new PlainTextOutputSpeech
    {
        Text = r.ResponseMessage
    };
    skillResponse.Response.ShouldEndSession = r.ResponseFinishFlg;
}
break;

AlexaがFunctionsにリクエストしているJsonを見るとより分かりやすいと思います。

"request": {
		"type": "IntentRequest",
		"requestId": "amzn1.echo-api.request.04f1bfe6-5cfe-4b5e-b2ff-d1339841cec3",
		"locale": "ja-JP",
		"timestamp": "2022-12-10T08:58:13Z",
		"intent": {
			"name": "PokemonCompatibility",
			"confirmationStatus": "NONE",
			"slots": {
				"type": {
					"name": "type",
					"value": "ほのお",
					"resolutions": {
						"resolutionsPerAuthority": [
							{
								"authority": "amzn1.er-authority.echo-sdk.amzn1.ask.skill.4fb46ed0-cafa-4977-894b-2388261215fe.TYPE_NAME",
								"status": {
									"code": "ER_SUCCESS_MATCH"
								},
								"values": [
									{
										"value": {
											"name": "ほのお",
											"id": "e95455c77f60d63ec36417a57e51fb9b"
										}
									}
								]
							}
						]
					},
…省略

slotsの中に作成したインテントスロットの「type」がありますね。

余談ですが、Functionsのrouteはちゃんと考えて設定してあげないとポータルの関数のところに何も表示されなくなってしまうので注意が必要ということを学びました。
Azure Functions の HTTP トリガーで、キーが間違っていないのに 401 エラーとなってしまうケース

完成品

呼び出してみるとこんな感じです。タイプ言うだけでも反応しました。
タイプをデータベースにすべてひらがなでいれた(Alexaがどこまで優秀かわからなかった)ので文字としては読みにくいです。
image.png

完成してから効果なしの情報を取得し忘れたことに気づく。。。

おわりに

ボット作成に思ったより時間がかかってしまいました。が久しぶりにAlexaを起動できたのでよかったです。一時期めっちゃカスタムスキルが流行った?気がしましたが、最近の記事はもうほとんど見かけなかったので、もしやもう時代遅れ…?

今年を振り返ってみて

今年特に感じたことは公式ドキュメントをよく見ろです。
公式ドキュメントを隅々までよく見るとだいたい正解がかいてあります。ありがたや。
今年は特にAzureに触れる機会が多かったおかげでだいぶ理解が進んだ年になったと思います。
こうして復習する機会もでき、よいAzureライフを送ることができました。来年もよいAzureライフを送れるように頑張ります。

参考

GitHub

今回作成したコードはGitHubにあげています。
https://github.com/usomaru/pokemon-compatibility

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
4