はかせのラボ

なんか好きなこと色々書きます

Alexa AlexaでDynamoDBのデータを取得する

あいさつ

どうも、はかせです。
前回DynamoDBにデータをPutしたので
今回はその読み出しをしてみたいと思います。

前回はこちら
hakase0274.hatenablog.com

Lambdaでやること

下記のコードを追加していつもどおりハンドラー登録をします。

def dbGet(name):
    queryData = table.query(
      KeyConditionExpression = Key("name").eq(name)
    )
    text = '登録されていない人です'
    if(len(queryData['Items']) > 0):
        text = name + 'さんは' + str(int(queryData['Items'][0].get('age'))) + '歳です'
    
    return QuestionSpeech(text).reprompt('他にはなにかありませんか?').build()

DynamoDBのqueryで取得したデータは最初listになっていて
['Items']のインデックスで取得することで
Dictonaryとして各要素にアクセスできるようになります。

Dictonaryにはキー名:値のセットで格納されているので
素直にキー名で取り出してやれば欲しい値が取れます。

Alexaでやること

インテントの追加だけです。
f:id:hakase0274:20190821213735p:plain

実行

前回作ったPutと合わせて使ってみます。
f:id:hakase0274:20190821213855p:plain

データベースの操作は1できれば2もできますね。

Alexaは自由テキストを受け取る仕組みではないらしい

今回テスト用として適当な名前で100件ほどデータPutしてみようと
やってみたら何件か弾かれました。
(よくわからない文字列になるかそもそもエラーになるか)

なんでだろうと思い色々ぐぐってみたら
Alexa的に登録されていないテキストを認識するということは
結構領域外っぽいです。

というのもAlexaは受け取ったテキストを
登録されているインテントに当てはめようとして
どうしても当てはまらない場合のみ
渡されたデータをリテラルとして無理やりあてはめるそうです。
(無理やりなあてはめだからわけわかめな文字列になったわけですね)

こうしているのはおそらくですが、
識字率を上げるためでしょうね。

同じスマートスピーカーであるGoogleHomeなんかでは
似た発音の文字列と誤認識することが結構あるそうですが、
Alexaの場合そういった事例はあまり聞きません。

精度の高さと自由性はトレードオフってことですね。

あとがき

今回はAlexaでデータを取得してみました。
そんな苦戦せずに済みましたね。
(Pythonの文法やらなんやらで少し手間取りましたが)

今回はテストということで自由テキストで投げましたが、
実運用時はAlexaにかける言葉はある程度限定されるはずなので
まぁ問題はないのかなと思っております。

それでは今回はこの辺でノシ

Alexa AlexaからDynamoDBにデータを追加する

あいさつ

どうも、はかせです。
今回は最近ご無沙汰だったAlexaです。
(UnityAWSが予想の右斜め上で難しかったのでしばらくこっちやります)

今回やるのはAlexaからDynamoDBへのデータのPutです。

DynamoDBでやること

DBを作るところからAlexaでやってもいいんですが、
初回ですしまずはあらかじめ用意しておきます。

やり方は簡単でまずDynamoDBのコンソールから「テーブルの作成」ボタンをクリックします。
するとこんな画面になるので
f:id:hakase0274:20190820232507p:plain
テーブル名とか必要なもの入れて下にある「作成」ボタンをクリックします
あとはちょっと待てばテーブルができます。

Lambdaでやること

Lambdaの設定は前回のハローワールドやった時のをそのまま使います。
hakase0274.hatenablog.com

この時に作ったコードに以下のコードを追加

import boto3
from boto3.dynamodb.conditions import Key, Attr

def db(name,age):
    dynamodb = boto3.resource("dynamodb")
    table    = dynamodb.Table('作ったテーブルの名前')

    table.put_item(
      Item = {
        "テーブルのプライマリキーの名前": 'プライマリキーの値として入れたいもの', 
        #以下はテーブル作成の際に用意した場合のみ記述
        "テーブルのソートキーの名前": 'ソートキーの値として入れたいもの', 
      }
    )
    
    return OneSpeech('データベースに追加したよ').build()

#ハンドラーに追加
elif intent_name == 'DataBaseIntent':
        name = request['intent']['slots']['name']
        age = request['intent']['slots']['age']
        return db(name,age)

とりあえずネット上に落ちてるコードを
ガチャガチャくっつけてみました。
作成したテーブルの参照的なものを取得し
そこにクエリを発行しています。

そして作った処理を呼ぶため
ハンドラーに追加しました。

Alexaでやること

インテントとスロットを追加するだけです。
インテントとかスロットとか何?って方はこの辺りを見てもらうと
それとなく雰囲気がつかめると思います。
hakase0274.hatenablog.com
hakase0274.hatenablog.com

今回私はDataBaseIntentというインテント
nameとageというスロットを作りました。
f:id:hakase0274:20190820234045p:plain

nameは適当にはかせとhakaseを入れただけです。
ageはAmazonの数値扱ってくれるビルトインのスロットを使いました。

実行

では実行です。
f:id:hakase0274:20190820234333p:plain
f:id:hakase0274:20190820234342p:plain
はい無事はかせ21歳が登録されました。

あとがき

今回はAlexaを使いDynamoDBにデータをPutしてみた話でした。

いやーUnityや.NETでAWSを使おうとするのに比べて圧倒的に楽ですね。
(Unityとかから使うときもこんだけ楽ならいんだけどなぁ)

最初はなぜかAlexaが吐くJSONが安定せず頭を悩ましてましたが、
再サインインしたら直りました。
(なんか変なキャッシュでも溜まってたんですかね?)

それでは今回はこの辺でノシ