Edited at

一日かけて魚へんクイズスキルを作ってみる話 (とりあえず作る編)


いざ申請しようとしたところ・・めっちゃ同名のスキルあるやんけ。。

ちょーショック。。機能的にもほぼ一緒やなぁ。こっちのが問題多いくらい。残念やし、別の漢字にするか?? 2018/11/3



前置き

qiitaはじめてみようと思ったのはいいものの、なかなか一つ目の記事が投稿できないまま毎日が過ぎていっています。どうしたもんか。めんどくさいぞ。

でもなんか今時のエンジニアっぽい事もしていきたいのよねー、と。

そんな最中(もなか)、昨日amazon dev days 2018に行ってまいりました。細かいレポートは先人にぶん投げるとして、個人的な感想としては、


  • もうインフラとサーバとアプリの境界なくなるね

  • サーバレスどんどんやってかんとね

ってあたりでしょうか。

ちなみにわたくしは仕事がインフラ寄り(awsはいまのとこ4冠)のなんでも屋です。なにかインフラが絡むあたりであるとすぐこっちに投げてこられてツライとか思ってるクチですね。

社内でlambda推進してこ。

でもってそれ絡みで一言chaliceのお話がちらっと出てた。この前、hangout chatのbotを作った時に使ってみたけどこれ便利よね。これとか推進できたらいいな。

あとdev days絡みでもう一件。こんなキャンペーンやるのね。

スキル公開でEcho Showやオリジナルグッズをプレゼント


2018年11月1日~12月20日にスキルを公開し、かつキャンペーンにお申し込みをいただいた方には、公開されたスキルの数に応じた豪華特典がもらえます。


ほー。4つ公開でEcho Showとな。すでに2つは公開してたりするのであと2個でええの?やってみんべか。こっちは別にいらん。

そんなわけでchaliceなんかを使いつつ、簡単なスキルを一つ作ってみようと思います。


魚へんクイズ


概要


  • こんにちは

  • 魚へんに秋と書いてなんと読む?

  • 「さんま」

  • 正解!

みたいなもの。


開発の環境


  • (なぜか)GCE

  • ubuntu

  • venv + Python3.6.6


Chalice setup

これだけ

$ pip install chalice

そしたらこんなん言われました。さっそく躓くんかい。

  error: invalid command 'bdist_wheel'

----------------------------------------
Failed building wheel for enum-compat
Running setup.py clean for enum-compat
Failed to build enum-compat
Installing collected packages: typing, six, python-dateutil, jmespath, docutils, urllib3, botocore, click, wheel, enum-compat, attrs, chalice
Running setup.py install for enum-compat ... done
Successfully installed attrs-17.4.0 botocore-1.12.37 chalice-1.6.1 click-6.7 docutils-0.14 enum-compat-0.0.2 jmespath-0.9.3 python-dateutil-2.7.5 six-1.11.0 typing-3.6.4 urllib3-1.24.1 wheel-0.32.2

でも勝手にリトライしたのかわからんけど、enum-compat ... doneってなってて大丈夫っぽい。まあいいや、進もう。


プロジェクトコード

alexa-aroundfish-quiz

にしよう。ちょー適当。英語で魚へんなんてわからん。

chalise new-projectします。ここがプロジェクトフォルダ

$  chalice new-project alexa-aroundfish-quiz

$ cd !$

レポジトリも作ってしまう

$ git add .; git commit -m 'create repo'

$ git remote add origin git@github.com:ikegam1/alexa-aroundfish-quiz.git
$ git push -u origin master

基本いじるのはapp.pyで今はこんなソース


app.py

from chalice import Chalice

app = Chalice(app_name='alexa-aroundfish-quiz')

@app.route('/')
def index():
return {'hello': 'world'}


ちょっと.chalice/config.jsonをいじります。 [^2]: あとこれは念のため.gitignoreに。

と思ったけど特にいじる箇所なかった。。


chalice/config.json

{

"version": "2.0",
"app_name": "alexa-aroundfish-quiz",
"stages": {
"prod": {
"api_gateway_stage": "api",
"lambda_timeout": 120,
"lambda_memory_size": 128
},
"dev": {
"api_gateway_stage": "api",
"lambda_timeout": 120,
"lambda_memory_size": 128
}
},
"environment_variables":
{
}
}

app.pyはひとまずこんなソースにする


app.py

from chalice import Chalice

import logging
import json

app = Chalice(app_name='alexa-aroundfish-quiz')
logger = logging.getLogger('DEBUG')

@app.route('/')
def index():
return {'hello': 'world'}

@app.route('/', methods=['POST'], content_types=['application/json'])
def on_event():
event = app.current_request.json_body
logger.debug(json.dumps(event))
return {'hello': 'world'}


chaliceが使うリソースを勝手にいい感じにしてくれるんだけど、POSTメソッドも使うってのを組み込んでほしいので。

そしてdeployしてみるテスト

$ chalice deploy --stage prod

~/alexa/venv/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.24.1) or chardet (3.0.4) doesn't match a supported version!
Creating deployment package.
Creating IAM role: alexa-aroundfish-quiz-prod
Creating lambda function: alexa-aroundfish-quiz-prod
Creating Rest API
Resources deployed:
- Lambda ARN: arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:alexa-aroundfish-quiz-prod
- Rest API URL: https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/api/

$ curl https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/api/
{"hello": "world"}

なんかurllib3のversionがうんちゃらっていわれたけどdeployはできたっぽい。

chaliceちょーかんたんですわ。

あ、ちなみにawsのcredentialsは~/.awsに作ってます。普通にアクセスキーとシークレットを書いてある。regionはap-northeast-1。逆にいうとこれ設定さえすればあとはだいたいOK.!

設定ファイルと認証情報ファイル


alexaskillの方

お次はalexaskillの方を作っていきます。

まずAlexa Skills Kit開発者コンソールを開きます。

1.png

その後はこんな感じで初期設定します

呼び出し名
魚へんクイズ

インテント
WellcomeIntent
最初に話す。ヘルプも兼ねたい

QuizIntent
クイズを出す

AnswerIntent
答えを判定

FinishIntent
終了

スロットタイプ
startphrase
QuizIntentに入るフレーズ

AMAZON.SearchQuery
Quizの発話を入れるスロット

startphareにはざっとこんな感じの言葉を用意します。


{startphraseSlot} だして

{startphraseSlot} はじめる

{startphraseSlot} やりたい

{startphraseSlot} やります

{startphraseSlot} やる

次の {startphraseSlot}



はじめる

やる

やりたい

..etc


startphraseSlotにはクイズ、問題、くいず、もんだい、Quizなどの名詞を入れています。

でひとまず他のインテントにも適当な発話を入れて、モデルを保存してビルドしておきます。

次にlambdaとつなげておく設定。

lambdaみるとちゃんと関数ができているのでそのARNをコピーします。そして下記にペースト。保存も忘れずに。

2.png

今度はこの画面のスキルIDをコピーしてlambdaに張り付ける。lambdaのトリガーにAlexaSkillsKitを追加してやってそれの設定をします。

2.png

4.png

そして保存。あれ?api gatewayいらんやん。

ちなみにこの状態で再deployしてみたけどトリガーの設定はそのままでした。消えなくてよかった。そのうち.chalice/config.jsonのresoucesの所にalexaskillkitも追加されるんやろか。

これでalexaとlambdaはつながったはず。

・・ちょっとしんどくなってきたのでスクリプトの方に戻ろう


その前に

結局、apigateway使うのやめました。

app.pyにこんなの入れつつ、


app.py

@app.lambda_function()

def default(event, context):

.chalice/config.jsonにこんなのいれたらalexaskillから直接関数叩く感じになった。


chalice/config.json

      "lambda_functions": {

"default": {}
}

あと、回答はAMAZON.SearchQueryのビルトインスロットタイプで何でもかんでも拾おうと思ってたけど、回答のみは拾えないみたい。

要は {answerSlot}とanswerIntentのサンプル発話に書きたかったんだけどビルドしたらなんか怒られたので結局answerSlotは自前で(愚直に)用意することに。

{answerSlot} ですとか答えは{answerSlot}みたいに答えさせるのはありなんだけどそれも微妙かなと。

で、answerSlotはこんな感じに



あじ,,鰺,味,アジ,鯵

くじら,,九時ら,久慈ら,久次良,クジラ,鯨

しゃち,,社地,社地,社畜,シャチ,鯱

なまず,,生図,生巣,鯰尾,ナマズ,鯰

さば,,佐波,サバ,鯖

こい,,来い,故意,濃い,恋,コイ,鯉

...etc


QuizIntentを拾う(程度のつもりだったけど結局最後まで作ってしまった)

で、ひとまずこんな感じになりました。


app.py

from chalice import Chalice

import logging
import json
import random
import re
import os
import sys

app = Chalice(app_name='alexa-aroundfish-quiz')
logger = logging.getLogger()
debug = os.environ.get('DEBUG_MODE')
if debug == '1':
logger.setLevel(logging.INFO)
else:
logger.setLevel(logging.ERROR)

#quiz
import fishes

#mp3
drumrole_mp3 = "soundbank://soundlibrary/musical/amzn_sfx_drum_and_cymbal_01"
question_mp3 = "soundbank://soundlibrary/ui/gameshow/amzn_ui_sfx_gameshow_bridge_02"
correct_mp3 = "soundbank://soundlibrary/ui/gameshow/amzn_ui_sfx_gameshow_positive_response_01"
incorrect_mp3 = "soundbank://soundlibrary/ui/gameshow/amzn_ui_sfx_gameshow_negative_response_01"

class BaseSpeech:
def __init__(self, speech_text, should_end_session, session_attributes=None, reprompt=None):

"""
引数:
speech_text: Alexaに喋らせたいテキスト
should_end_session: このやり取りでスキルを終了させる場合はTrue, 続けるならFalse
session_attributes: 引き継ぎたいデータが入った辞書
reprompt:
"""

if session_attributes is None:
session_attributes = {}

self._response = {
'version': '1.0',
'sessionAttributes': session_attributes,
'response': {
'outputSpeech': {
'type': 'SSML',
'ssml': '<speak>'+speech_text+'</speak>'
},
'shouldEndSession': should_end_session,
},
}

if reprompt is None:
pass
else:
"""リプロンプトを追加する"""
self._response['response']['reprompt'] = {
'outputSpeech': {
'type': 'SSML',
'ssml': '<speak>'+reprompt+'</speak>'
}
}

self.speech_text = speech_text
self.should_end_session = should_end_session
self.session_attributes = session_attributes

def build(self):
return self._response

class OneSpeech(BaseSpeech):
"""1度だけ発話する(ユーザーの返事は待たず、スキル終了)"""

def __init__(self, speech_text, session_attributes=None):
super().__init__(speech_text, True, session_attributes)

class QuestionSpeech(BaseSpeech):
"""発話し、ユーザーの返事を待つ"""

def __init__(self, speech_text, session_attributes=None, reprompt=None):
super().__init__(speech_text, False, session_attributes, reprompt)

@app.lambda_function()
def default(event, context):
logger.info(json.dumps(event))
request = event['request']
request_type = request['type']
session = {}
if 'session' in event:
session = event['session']
if request_type == 'LaunchRequest':
return welcomeIntent()
elif request_type == 'IntentRequest' and 'intent' in request:
return in_intent(request, session)

def in_intent(request, session):
intent = request['intent']
logger.info(str(intent))

if intent['name'] == 'AMAZON.HelpIntent':
return helpIntent()
elif intent['name'] == 'AMAZON.NavigateHomeIntent':
return helpIntent()
elif intent['name'] == 'AMAZON.StopIntent':
return finishIntent()
elif intent['name'] == 'AMAZON.CancelIntent':
return finishIntent()

if 'attributes' not in session:
pass
elif 'current' not in session['attributes']:
pass
elif session['attributes']['current'] != 'quizIntent':
return welcomeIntent()
elif session['attributes']['current'] == 'quizIntent':
return answerIntent(intent, session)

if intent['name'] == 'QuizIntent':
return quizIntent(session)
elif intent['name'] == 'AnswerIntent':
return answerIntent(intent, session)

return fallback()

def welcomeIntent():
return QuestionSpeech('魚ヘンクイズへようこそ!<emphasis level="moderate">クイズはじめる</emphasis>と言ってみてください。魚へんのついた漢字がどれだけ読めるかのクイズです。',{},'クイズはじめると言ってみてくださいね。終わる時は終わると言ってください。').build()

def helpIntent():
return QuestionSpeech('魚へんのついた漢字がどれだけ読めるかのクイズです。<emphasis level="moderate">クイズはじめる</emphasis>と言うとクイズをはじめられます。答えを言うと正解か不正解かを答えるよ。次の問題へ進むときは<emphasis level="moderate">次のクイズ</emphasis>と言ってくださいね').build()

def quizIntent(session):
text = 'ではクイズです。30秒以内で答えてくださいね。<break time="1s"/>'
text += '<audio src="%s" />' % question_mp3

"""quizcsv"""
csv = ''
for q in fishes.quiz:
csv += u'%s,,%s\n' % (q["a"],q["w"])
#logger.info(csv)

quiz = random.choice(fishes.quiz)
logger.info(str(quiz))

text += quiz["q"]
text += '<break time="0.5s" /> %s' % quiz["q"]
text += '<break time="10s"/>あと10秒です。<break time="7s"/>さん。<break time="1s"/>にい。<break time="1s"/>いち。<break time="1s"/>'

text2 = 'もう一度だけ問題を言いますよ。'
text2 += quiz["q"]
text2 += '<break time="1s"/>さん。<break time="1s"/>にい。<break time="1s"/>いち。<break time="1s"/>'
logger.info(text)
logger.info(text2)

session_attributes = {"quiz":quiz,"current":"quizIntent"}
return QuestionSpeech(text, session_attributes,text2).build()

def answerIntent(intent, session):
logger.info(str(intent))
logger.info(str(session))
try:
quiz = session["attributes"]["quiz"]
slots = intent['slots']
answer = slots['answerSlot']['value']
if 'value' in slots['answerSlot']['resolutions']['resolutionsPerAuthority'][0]['values'][0]:
answer = slots['answerSlot']['resolutions']['resolutionsPerAuthority'][0]['values'][0]['value']['name']
except Exception as e:
logger.info( "[x] Type: {type}".format(type=type(e)))
logger.info( "[x] Error: {error}".format(error=e))
session_attributes = {"quiz":quiz,"current":"quizIntent"}
return fallback(session_attributes)

logger.info(answer)
text = '正解は<break time="0.5s"/>'
text += '<audio src="%s" />' % drumrole_mp3

if re.compile("^%s" % quiz['a']).search(answer):
text += u'<audio src="%s" />' % correct_mp3
text += u'<prosody rate="105%"><prosody volume="+1dB">正解は' + quiz['a'] + 'です!すごいですね!</prosody></prosody>'
text += u'次の問題もやるときは<emphasis level="moderate">次のクイズ</emphasis>と言ってください'

else:
text += u'<audio src="%s" />' % incorrect_mp3
text += u'<prosody rate="105%"><prosody volume="+1dB">ざあ<prosody pitch="+5%">んね<prosody pitch="+5%">ん</prosody>!</prosody></prosody></prosody>'
text += u'<break time="0.5s" />正解は<emphasis level="moderate">'+quiz['a']+'</emphasis>でした'
text += u'<break time="0.5s" />次の問題もやるときは<emphasis level="moderate">次のクイズ</emphasis>と言ってください'

return QuestionSpeech(text, {}).build()

def finishIntent():
return OneSpeech('遊んでくれてありがとう!またやってくださいね。').build()

def fallback(session_attribute={}):
ssml = []
ssml.append('すみません。聞き取れませんでした。もう一度お願いします。')
ssml.append('もう一度お願いします。<emphasis level="moderate">はじめから</emphasis>というと最初に戻れます')
ssml.append('ごめんなさい。聞き取れなかったです。')
ssml.append('ハッキリと聞き取れなかったです。もう一度言ってみて。')
return QuestionSpeech(random.choice(ssml),session_attribute).build()


問題は別ファイル

vendor/fishes.py (ホントはもっと件数ある)

quiz = [

{ "q": "魚へんに<emphasis level='moderate'><sub alias='参上のさん'>参</sub></emphasis>を書いて何という魚?", "a": "あじ", "w": "鯵" },

{ "q": "魚へんに<emphasis level='moderate'><sub alias='京都のきょう'>京</sub></emphasis>を書いて何という魚?", "a": "くじら", "w": "鯨" },

{ "q": "魚へんに<emphasis level='moderate'><sub alias='とら'>虎</sub></emphasis>を書いて何という魚?", "a": "しゃち", "w": "鯱" },

{ "q": "魚へんに<emphasis level='moderate'><sub alias='念仏のねん'>念</sub></emphasis>を書いて何という魚?", "a": "なまず", "w": "鯰" }

]

alexaスキルの方もぼちぼちいじくって、jsonがこんな感じ。

殴り書きに近いのでまだまだ調整しないと。

申請やらはまた今度。なんか長くなりすぎたな。作り始めるとqiitaとか無視になってしまう。。

{

"interactionModel": {
"languageModel": {
"invocationName": "魚へんクイズ",
"intents": [
{
"name": "AMAZON.CancelIntent",
"samples": []
},
{
"name": "AMAZON.HelpIntent",
"samples": []
},
{
"name": "AMAZON.StopIntent",
"samples": [
"終わり",
"終わる",
"やめて",
"やめる",
"終了",
"おわる"
]
},
{
"name": "AMAZON.NavigateHomeIntent",
"samples": []
},
{
"name": "WellcomeIntent",
"slots": [
{
"name": "skillnameSlot",
"type": "skillname"
}
],
"samples": [
"さいしょから",
"最初から",
"始めから",
"はじめから",
"{skillnameSlot} を開く",
"{skillnameSlot} につないで",
"{skillnameSlot} を開いて"
]
},
{
"name": "QuizIntent",
"slots": [
{
"name": "startphraseSlot",
"type": "startphrase"
}
],
"samples": [
"つぎの {startphraseSlot}",
"つぎ",
"次",
"次の {startphraseSlot}",
"{startphraseSlot} だして",
"{startphraseSlot} はじめる",
"{startphraseSlot} やりたい",
"{startphraseSlot} やります",
"{startphraseSlot} やる",
"{startphraseSlot} 出して",
"やります",
"やる",
"開始する",
"開始して",
"開始",
"初めて",
"始める",
"始めて",
"はじめる",
"はじめて"
]
},
{
"name": "AnswerIntent",
"slots": [
{
"name": "answerSlot",
"type": "answers"
}
],
"samples": [
"{answerSlot} かな",
"{answerSlot} だよ",
"{answerSlot}",
"答えは {answerSlot}",
"{answerSlot} です"
]
},
{
"name": "HelpIntent",
"slots": [],
"samples": [
"メニューを開いて",
"どうやるの",
"使い方を教えて"
]
}
],
"types": [
{
"name": "startphrase",
"values": [
{
"name": {
"value": "クイズ",
"synonyms": [
"問題を",
"もんだいを",
"くいずを",
"クイズを",
"もんだい",
"問題",
"くいず"
]
}
}
]
},
{
"name": "skillname",
"values": [
{
"name": {
"value": "魚へんクイズ",
"synonyms": [
"魚変クイズ",
"魚辺クイズ",
"魚へんQuiz",
"さかなへんクイズ",
"魚編クイズ",
"さかなへんくいず"
]
}
}
]
},
{
"name": "answers",
"values": [
{
"name": {
"value": "あじ",
"synonyms": [
"鰺",
"味",
"アジ",
"鯵"
]
}
},
{
"name": {
"value": "くじら",
"synonyms": [
"九時ら",
"久慈ら",
"久次良",
"クジラ",
"鯨"
]
}
},
{
"name": {
"value": "しゃち",
"synonyms": [
"社地",
"社地",
"社畜",
"シャチ",
"鯱"
]
}
},
{
"name": {
"value": "なまず",
"synonyms": [
"生図",
"生巣",
"鯰尾",
"ナマズ",
"鯰"
]
}
},
{
"name": {
"value": "さば",
"synonyms": [
"佐波",
"サバ",
"鯖"
]
}
},
{
"name": {
"value": "こい",
"synonyms": [
"来い",
"故意",
"濃い",
"恋",
"コイ",
"鯉"
]
}
},
{
"name": {
"value": "たい",
"synonyms": [
"痛い",
"体",
"隊",
"タイ",
"鯛"
]
}
},
{
"name": {
"value": "うろこ",
"synonyms": [
"うろお",
"うロコ",
"雨露こ",
"うろ後",
"ウロコ",
"鱗"
]
}
},
{
"name": {
"value": "あわび",
"synonyms": [
"泡火",
"泡び",
"あ詫び",
"アワビ",
"鮑"
]
}
},
{
"name": {
"value": "あゆ",
"synonyms": [
"歩む",
"阿諛",
"アユ",
"鮎"
]
}
},
{
"name": {
"value": "さけ",
"synonyms": [
"明け",
"避け",
"酒",
"サケ",
"鮭"
]
}
},
{
"name": {
"value": "さめ",
"synonyms": [
"醒め",
"覚め",
"冷め",
"サメ",
"鮫"
]
}
},
{
"name": {
"value": "すし",
"synonyms": [
"酢し",
"寿し",
"スシ",
"寿司",
"鮨"
]
}
},
{
"name": {
"value": "まぐろ",
"synonyms": [
"魔黒",
"マグロ",
"鮪"
]
}
},
{
"name": {
"value": "たら",
"synonyms": [
"荒",
"ダラ",
"タラ",
"鱈"
]
}
},
{
"name": {
"value": "きす",
"synonyms": [
"椅子",
"kiss",
"キス",
"鱚"
]
}
},
{
"name": {
"value": "ます",
"synonyms": [
"明日",
"マス",
"鱒"
]
}
},
{
"name": {
"value": "ひらめ",
"synonyms": [
"平目",
"平め",
"ヒラメ",
"鮃"
]
}
},
{
"name": {
"value": "ふな",
"synonyms": [
"舟",
"船",
"フナ",
"鮒"
]
}
},
{
"name": {
"value": "いわし",
"synonyms": [
"位和紙",
"鰮",
"言わし",
"岩氏",
"イワシ",
"鰯"
]
}
},
{
"name": {
"value": "うなぎ",
"synonyms": [
"宇名儀",
"ウナギ",
"鰻"
]
}
},
{
"name": {
"value": "かつお",
"synonyms": [
"勝雄",
"勝夫",
"勝男",
"カツオ",
"鰹"
]
}
},
{
"name": {
"value": "ぶり",
"synonyms": [
"舞李",
"振り",
"ブリ",
"鰤"
]
}
},
{
"name": {
"value": "わに",
"synonyms": [
"環に",
"輪に",
"和に",
"ワニ",
"鰐"
]
}
},
{
"name": {
"value": "さわら",
"synonyms": [
"砂原",
"佐原",
"早良",
"サワラ",
"鰆"
]
}
},
{
"name": {
"value": "かじか",
"synonyms": [
"火事か",
"家事か",
"河鹿",
"カジカ",
"鰍"
]
}
},
{
"name": {
"value": "このしろ",
"synonyms": [
"この白",
"この城",
"粉白",
"此代",
"コノシロ",
"鮗"
]
}
},
{
"name": {
"value": "かれい",
"synonyms": [
"加齢",
"華麗",
"彼",
"カレー",
"かれー",
"カレイ",
"家令",
"鰈"
]
}
},
{
"name": {
"value": "すずき",
"synonyms": [
"薄",
"ススキ",
"すすき",
"須々木",
"鈴木",
"スズキ",
"鱸"
]
}
},
{
"name": {
"value": "はも",
"synonyms": [
"派も",
"歯も",
"葉も",
"ハモ",
"鱧"
]
}
},
{
"name": {
"value": "するめ",
"synonyms": [
"する目",
"スルメ",
"鯣"
]
}
},
{
"name": {
"value": "ごり",
"synonyms": [
"5里",
"5里",
"五里",
"ゴリ",
"鮴"
]
}
},
{
"name": {
"value": "たこ",
"synonyms": [
"多胡",
"多古",
"凧",
"タコ",
"鮹"
]
}
},
{
"name": {
"value": "にしん",
"synonyms": [
"二死ん",
"西ん",
"二進",
"二審",
"ニシン",
"鰊"
]
}
},
{
"name": {
"value": "はや",
"synonyms": [
"早",
"歯や",
"葉や",
"ハヤ",
"鮠"
]
}
},
{
"name": {
"value": "はたはた",
"synonyms": [
"端端",
"畑畑",
"羽田羽田",
"旗旗",
"ハタハタ",
"鰰"
]
}
},
{
"name": {
"value": "えび",
"synonyms": [
"絵日",
"江尾",
"海老",
"エビ",
"鰕"
]
}
},
{
"name": {
"value": "こち",
"synonyms": [
"こちら",
"東風",
"故智",
"故地",
"コチ",
"鯒"
]
}
},
{
"name": {
"value": "どじょう",
"synonyms": [
"土場",
"泥鰌",
"土曜",
"土壌",
"ドジョウ",
"オジョウ",
"鰌"
]
}
},
{
"name": {
"value": "なます",
"synonyms": [
"生須",
"膾",
"生酢",
"生巣",
"ナマス",
"鱠"
]
}
},
{
"name": {
"value": "いるか",
"synonyms": [
"射るか",
"入るか",
"海豚",
"入鹿",
"居るか",
"イルカ",
"鯆"
]
}
},
{
"name": {
"value": "かずのこ",
"synonyms": [
"下図の子",
"和の子",
"カズノコ",
"数の子",
"鯑"
]
}
},
{
"name": {
"value": "さより",
"synonyms": [
"佐代里",
"沙代里",
"沙代里",
"差より",
"細魚",
"サヨリ",
"鱵"
]
}
},
{
"name": {
"value": "ふか",
"synonyms": [
"深",
"不可",
"負荷",
"付加",
"フカ",
"鱶"
]
}
},
{
"name": {
"value": "かわはぎ",
"synonyms": [
"皮剥ぎ",
"川萩",
"カワハギ",
"鮍"
]
}
},
{
"name": {
"value": "あさり",
"synonyms": [
"朝李",
"朝里",
"浅利",
"アサリ",
"鯏"
]
}
},
{
"name": {
"value": "うぐい",
"synonyms": [
"鵜具位",
"宇久井",
"売具位",
"ウグイ",
"鯎"
]
}
},
{
"name": {
"value": "さんしょううお",
"synonyms": [
"酸性雨",
"三省魚",
"山荘魚",
"参照魚",
"山椒魚",
"サンショウウオ",
"鯢"
]
}
},
{
"name": {
"value": "すけとうだら",
"synonyms": [
"透け党ダラ",
"助藤ダラ",
"助任ダラ",
"スケトウダラ",
"鯳"
]
}
},
{
"name": {
"value": "まながつお",
"synonyms": [
"茉奈鰹",
"愛勝男",
"愛勝雄",
"生ガツオ",
"マナガツオ",
"鯧"
]
}
},
{
"name": {
"value": "いさざ",
"synonyms": [
"イサザ",
"伊左座",
"伊佐々",
"魦"
]
}
},
{
"name": {
"value": "ぼら",
"synonyms": [
"洞",
"保良",
"鯔",
"ぼら",
"ボラ",
"鰡"
]
}
},
{
"name": {
"value": "あめのうお",
"synonyms": [
"編め野魚",
"飴の魚",
"雨の魚",
"アメノウオ",
"鯇"
]
}
},
{
"name": {
"value": "いわな",
"synonyms": [
"岩魚",
"岩名",
"言わない",
"イワナ",
"鮇"
]
}
},
{
"name": {
"value": "ひがい",
"synonyms": [
"比嘉井",
"干貝",
"肥海",
"日飼",
"日開",
"被害",
"ヒガイ",
"鰉"
]
}
},
{
"name": {
"value": "しいら",
"synonyms": [
"思惟ら",
"思惟裸",
"椎平",
"志伊良",
"シイラ",
"鱪"
]
}
},
{
"name": {
"value": "ふぐ",
"synonyms": [
"河豚",
"不遇",
"フグ",
"鮐"
]
}
},
{
"name": {
"value": "むつ",
"synonyms": [
"六",
"睦",
"陸奥",
"六つ",
"6つ",
"ムツ",
"鱫"
]
}
},
{
"name": {
"value": "わかさぎ",
"synonyms": [
"若狭",
"若さ",
"若鷺",
"公魚",
"ワカサギ",
"鰙"
]
}
},
{
"name": {
"value": "ほっけ",
"synonyms": [
"呆け",
"ホッケ",
"惚け",
"法花",
"北家",
"法華",
"魚花"
]
}
}
]
}
]
},
"dialog": {
"intents": [
{
"name": "AnswerIntent",
"confirmationRequired": false,
"prompts": {},
"slots": [
{
"name": "answerSlot",
"type": "answers",
"confirmationRequired": false,
"elicitationRequired": true,
"prompts": {
"elicitation": "Elicit.Slot.938723155688.1367207618688"
}
}
]
}
]
},
"prompts": [
{
"id": "Elicit.Slot.938723155688.1367207618688",
"variations": [
{
"type": "PlainText",
"value": "答えはなんでしょう?"
}
]
}
]
}
}