Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What are the problem?

AWSでAIサービスを使ってみる〜第9回lex編〜

Lexとは

AWSのbotのAIサービス。Amazon Lex を使うと、すべてのデベロッパーが Amazon Alexa に採用されている深層学習技術と同じ技術を利用できるため、自然言語での高度な対話ボット (チャットボット) を短時間で簡単に構築できます。

今回はlexを用いてアイスクリームのフレーバーや容器について答えるボットを作成して行きます。
コードの量があるので順番に解説して行きます。

ボット作成ファイルの全体像

lex_create_bot.py
import boto3
import time


iam = boto3.client('iam')
iam.create_service_linked_role(AWSServiceName='lex.amazonaws.com')
lex = boto3.client('lex-models', 'us-east-1')

#フレーバーのスロットタイプの作成
flavor_slot_type = lex.put_slot_type(
  name='FlavorSlotType',
  enumerationValues=[
    {'value': 'vanilla'},
    {'value': 'chocolate', 'synonyms': ['choc']},
    {'value': 'strawberry', 'synonyms': ['berry']}
  ],
  valueSelectionStrategy='TOP_RESOLUTION',
  createVersion=True)
print('slot type:', flavor_slot_type['name'])

#容器のスロットタイプを作成
container_slot_type = lex.put_slot_type(
  name='ContainerSlotType',
  enumerationValues=[
    {'value': 'corn'},
    {'value': 'cup'}
  ],
  valueSelectionStrategy='TOP_RESOLUTION',
  createVersion=True)
print('slot type:', container_slot_type['name'])


#インテントの作成
intent = lex.put_intent(
  name='OrderIntent',
  #インテント内のスロット
  slots=[
    {
      'name': 'Flavor',
      'slotConstraint':'Required',
      'slotType':'FlavorSlotType',
      'slotTypeVersion': '1',
      'valueElicitationPrompt': {
          'messages': [{
              'contentType': 'PlainText',
              'content': 'Vanilla, chocolate or strawberry?'
          }],
          'maxAttempts': 3
      }
    },
    {
      'name': 'Container',
      'slotConstraint': 'Required',
      'slotType': 'ContainerSlotType',
      'slotTypeVersion': '1',
      'valueElicitationPrompt': {
          'messages': [{
              'contentType': 'PlainText',
              'content': 'Corn or cup?'
          }],
          'maxAttempts': 3
      } 
    }
  ],
  #発話例
  sampleUtterances=[
    'I want {Flavor} ice cream in {Container}',
    '{Flavor} ice cream {Container}',
    'ice create'
  ],
  #完了時のセリフ
  conclusionStatement={
      'messages': [{
          'contentType': 'PlainText',
          'content': 'OK, {Flavor} ice cream in {Container}'
      }],
  },
  #完了の動作
  fulfillmentActivity={'type': 'ReturnIntent'},
  createVersion=True)
print('intent:',intent['name'])


#ボットの作成
bot = lex.put_bot(
  name ='MyBot', locale='en-US', childDirected=False,
  #インテント
  intents=[
    {
      'intentName': 'OrderIntent',
      'intentVersion': '1'
    }
  ],
  #中止時のセリフ
  abortStatement={
    'messages':[
      {
        'contentType': 'PlainText',
        'content': 'Please try again.'
      }
    ]
  },
  voiceId='Joanna',
  createVersion=True)
print('bot:', bot['name'])
#ボット作成の進捗表示
start = time.time()
status = ''
while status not in ['READY', 'FAILED']:
  #ボットを取得
  status = lex.get_bot(name='MyBot', versionOrAlias='1')['status']
  time.sleep(10)
  print('{:7.2f} {}'.format(time.time()-start, status))
#作成に失敗した場合は理由を表示
if status == 'FAILED':
  print(lex.get_bot(
    name='Mybot', versionOrAlias='1')['failureReason'])
#ボットエイリアスを作成
bot_alias = lex.put_bot_alias(
  name='MyBotAlias', botName='MyBot', botVersion='1')
print('bot alias:', bot_alias['name'])

①importとサービスクライアント作成

lex_create_bot.py
import boto3
import time

iam = boto3.client('iam')
iam.create_service_linked_role(AWSServiceName='lex.amazonaws.com')
lex = boto3.client('lex-models', 'us-east-1')

boto3とtimeのインポートとiamのロールとlexのサービスクライアントを作成

②スロットタイプ作成

スロットとはユーザーから聞き出す必要のあるパラメーターです。
今回はフレーバーと容器をスロットに設定しています。

lex_create_bot.py
#フレーバーのスロットタイプ
flavor_slot_type = lex.put_slot_type(
  name='FlavorSlotType',
  enumerationValues=[
    {'value': 'vanilla'},
    {'value': 'chocolate', 'synonyms': ['choc']},
    {'value': 'strawberry', 'synonyms': ['berry']}
  ],
  valueSelectionStrategy='TOP_RESOLUTION',
  createVersion=True)
print('slot type:', flavor_slot_type['name'])

#容器のスロットタイプ
container_slot_type = lex.put_slot_type(
  name='ContainerSlotType',
  enumerationValues=[
    {'value': 'corn'},
    {'value': 'cup'}
  ],
  valueSelectionStrategy='TOP_RESOLUTION',
  createVersion=True)
print('slot type:', container_slot_type['name'])

put_slot_typeメソッドでスロットを作成します。
enumerationValuesでスロットが取りうる値を辞書型で指定
valueSelectionStrategyの'TOP_RESOLUTION'はスロットタイプの中からユーザーの言葉に近いものを返します。今回でいえばchocoと入力すると本来の値のchocolateが返ってくる。

③インテントの作成

intentとは意思や意図という意味がありますが、lexの中ではユーザーと会話する台本のイメージになります。
今回をアイスクリーム注文するコマンドを受け取るインテントを作成します。パラメーターとしてアイスクリームのフレーバーと容器を受け取リます。

put_intentメソッドでインテントを作成します。

引数slotsについて

lex_create_bot.py
#インテントの作成
intent = lex.put_intent(
  name='OrderIntent',
  #インテント内のスロット
  slots=[
    {
      'name': 'Flavor',
      'slotConstraint':'Required',
      'slotType':'FlavorSlotType',
      'slotTypeVersion': '1',
      'valueElicitationPrompt': {
          'messages': [{
              'contentType': 'PlainText',
              'content': 'Vanilla, chocolate or strawberry?'
          }],
          'maxAttempts': 3
      }
    },
    {
      'name': 'Container',
      'slotConstraint': 'Required',
      'slotType': 'ContainerSlotType',
      'slotTypeVersion': '1',
      'valueElicitationPrompt': {
          'messages': [{
              'contentType': 'PlainText',
              'content': 'Corn or cup?'
          }],
          'maxAttempts': 3
      } 
    }
  ],


引数slotsはインテント内にスロットを作成するために使います。
・slotConstraint:スロットの制約です。'Required'または'Optinal'で選択。
・slotTypeVersion:スロットのバージョン。最初はバージョン'1'
・valueElicitationPrompt:スロットの値をユーザーから促すためのセリフ

→valueElicitationPromptに指定する辞書の項目
・message:セリフを表す辞書リスト。その中にcontentTypeとcontentが含まれる
・maxAttempts:聞き返す回数の上限

→→messageに指定する辞書の項目
・contentType:セリフのタイプ。'PlainText','SSML','CustomPayload'から指定
・content:セリフの内容

引数sampleUtterances

lex_create_bot.py
 #発話例
  sampleUtterances=[
    'I want {Flavor} ice cream in {Container}',
    '{Flavor} ice cream {Container}',
    'ice create'
  ],

引数sampleUtterancesはインテントに対するユーザーの発話例です。
{スロット名}でスロットを表します。{Flavor}の部分にはフレーバー(chocolate,strawberry,vanilla)が入り、{Container}には(cupなど)が入ります。
今回ユーザーの発話を見ることはなさそうですね。

引数conclusionStatement

lex_create_bot.py
 #完了時のセリフ
  conclusionStatement={
      'messages': [{
          'contentType': 'PlainText',
          'content': 'OK, {Flavor} ice cream in {Container}'
      }],
  },

引数conclusionStatementはボットがユーザーから必要なスロットの情報を聞き出すことができて、インテントが完了したときのセリフです。辞書型の項目として引数slotsのvalueElicitationPromptに指定する辞書の項目と同じです。

引数fulfillmentActivity

lex_create_bot.py
  #完了の動作
  fulfillmentActivity={'type': 'ReturnIntent'},
  createVersion=True)
print('intent:',intent['name'])

引数fulfillmentActivityはインテントが完了したときの動作です。
引数にはキー'type'を含む辞書を指定します。

typeの種類
ReruenIntent:呼び出し元のプログラムにインテントの情報を返します。
CodeHook:Lambda呼び出してLambdaに登録されたプログラムを実行します。

④botの作成

最後にボットとボットエイリアスを作成します。Lexでbotを公開するにはボットエイリアスを作成する必要があります。

lex_create_bot.py
#ボットの作成
bot = lex.put_bot(
  name ='MyBot', locale='en-US', childDirected=False,
  #インテント
  intents=[
    {
      'intentName': 'OrderIntent',
      'intentVersion': '1'
    }
  ],
  #中止時のセリフ
  abortStatement={
    'messages':[
      {
        'contentType': 'PlainText',
        'content': 'Please try again.'
      }
    ]
  },
  voiceId='Joanna',
  createVersion=True)
print('bot:', bot['name'])

put_botメソッドを呼び出してボットを作成します。
引数のnameは名前、localeは今回'en-US'、childDirected(子供向け)は子供向けの場合にはTrue、子供向けではない場合はFalseに指定。
引数intentはnameとintentVersionを辞書型で渡します。
引数abortStatementには中止時のセリフを辞書型のリストにして指定します。
voiceIdは'en-US'の中から'Joanna'に指定します。

作成時の進捗時間表示

lex_create_bot.py
#ボット作成の進捗表示
start = time.time()
status = ''
while status not in ['READY', 'FAILED']:
  #ボットを取得
  status = lex.get_bot(name='MyBot', versionOrAlias='1')['status']
  time.sleep(10)
  print('{:7.2f} {}'.format(time.time()-start, status))
#作成に失敗した場合は理由を表示
if status == 'FAILED':
  print(lex.get_bot(
    name='Mybot', versionOrAlias='1')['failureReason'])
#ボットエイリアスを作成
bot_alias = lex.put_bot_alias(
  name='MyBotAlias', botName='MyBot', botVersion='1')
print('bot alias:', bot_alias['name'])

get_botメソッドでボットの情報を取得しstatusへ、10秒間時間を待ち開始からに時間と取得したボットの情報をstatusに代入して表示します。
作成に失敗した場合は、失敗した理由を取得し表示。
put_bot_aliasメソッドでボットエイリアスを作成し、画面に表示します。

まとめ

ここまで長くなりましたが、lexでのbot作成のコードと解説でした。
次回はbotにテキストを与えて動かしてみます。

参考文献

この記事は以下の情報を参考にして執筆しました
AWSでつくるAIプログラミング入門

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
0
Help us understand the problem. What are the problem?