Slide 1

Slide 1 text

ChatGPT APIを繋いだ スキルを作ろう VoiceLunchJP #29 2023年3月22日 長田英幸 1

Slide 2

Slide 2 text

自己紹介 長田英幸 大阪でWebプログラマしています。 個人開発は、主にスマートスピーカー関係。 最終目標は、会話AIが作ることです。 note始めました。 https://note.com/hideyukinagata Alexaスキル「サイバーイルカ」(英語名cyber dolphin)を公開しました。 賞をいただいた「耳で聞く水害ハザードマップ」は、まだ開発中です・・・。 ヒーローズ・リーグ 2022 > A.I.VOICE賞 by 株式会社エーアイ https://protopedia.net/event/hl2022 アーバンデータチャレンジ2022 with 土木学会インフラデータチャレンジ2022 > 土木学会インフラデータチャレンジ賞 https://urbandata-challenge.jp/news/udc2022prize 最近の活動 2

Slide 3

Slide 3 text

最近、ChatGPTの話題を聞かない日がない。 Googleトレンド https://trends.google.co.jp/trends/explore?date=today%203-m&geo=JP&q=ChatGPT&hl=ja 3

Slide 4

Slide 4 text

4

Slide 5

Slide 5 text

AlexaにChatGPT APIを繋いだイメージ図 引用元: https://developer.amazon.com/ja-JP/docs/alexa/ask-overviews/what-is-the-alexa-skills-kit.html 8秒の壁 ChatGPT API Alexa-hostedスキルで作りました ☞ 5

Slide 6

Slide 6 text

Alexa-hostedスキルは手間を減らせます。 いわゆる、オウム返しスキルの作り方です。 追加したインテントはAskChatgptIntentです。 スロットタイプは、 AMAZON.SearchQueryです。 自由な文言を取得できます。 6

Slide 7

Slide 7 text

https://github.com/alexa-samples/skill-sample-nodejs-hello-world を元に、色々と追加しました。 package.jsonに追記する "i18next": "^15.1.3", "openai": "^3.2.1" 追加したkeys.jsに、 module.exports.OPEN_AI_KEY = ‘OPEN AIのキー'; 7

Slide 8

Slide 8 text

AskChatgptIntentHandler ポイント 1/3 async handle(handlerInput) { let locale = handlerInput.requestEnvelope.request.locale; console.log('locale:'+locale); // AWSリソースロールは、STS AssumeRoleアクションを使用するとします const STS = new AWS.STS({ apiVersion: '2011-06-15' }); const credentials = await STS.assumeRole({ RoleArn: 'arn:aws:iam::xxxxxxxxxxxxx:role/TranslateForAlexa', RoleSessionName: 'ExampleSkillRoleSession' //任意の名前に変更できます }, (err, res) => { if (err) { console.log('AssumeRole FAILED: ', err); throw new Error('Error while assuming role'); } return res; }).promise(); const Translate = new AWS.Translate({ // region: 'us-east-1', accessKeyId: credentials.Credentials.AccessKeyId, secretAccessKey: credentials.Credentials.SecretAccessKey, sessionToken: credentials.Credentials.SessionToken }); ChatGPT APIで日本語をそのまま渡すと、 Alexaの8秒制限にひっかかってエラーになりました。 その為、日本語の場合は Amazon Translateで 英語に翻訳してから、ChatGPT APIに投げました。 ChatGPT APIから戻ってきたら、英語から日本語に 戻しました。 Alexaはタイムアウトする前に8秒間応答を待ちます。 https://developer.amazon.com/ja- JP/docs/alexa/device-apis/ja-alexa-response.html Alexa-hostedスキルで個人のAWSリソースを使用す る https://developer.amazon.com/ja- JP/docs/alexa/hosted-skills/ja-alexa-hosted- skills-personal-aws.html 8

Slide 9

Slide 9 text

AskChatgptIntentHandler ポイント 2/3 function getAwsTranslate(text,in_Language,out_Language) { return new Promise(((resolve, reject) => { let params = { Text: text, SourceLanguageCode: in_Language, TargetLanguageCode: out_Language } Translate.translateText(params, function(err,data){ if (err) { console.log(err); reject(); } else { console.log(JSON.stringify(data)); resolve(data); } }); })) } 文字列を英語、日本語に翻訳する関数は、 ネット記事を参考にさせていただきました。 https://idealive.jp/blog/2019/10/16/amazo n-translate- %E3%82%92%E4%BD%BF%E7%94%A8%E3 %81%97%E3%81%A6%E3%81%BF%E3%82% 8B/ 9

Slide 10

Slide 10 text

AskChatgptIntentHandler ポイント 3/3 if( locale === 'ja-JP') { // 翻訳 let rs = await getAwsTranslate(question,'ja','en'); const completion = await openai.createChatCompletion({ model: "gpt-3.5-turbo", messages: [ {role: "system", content: "You are a helpful smart speaker assistant. "}, {role: "system", content: "You will give a concise answer of about 100 characters so that it is easy to understand by listening to the voice."}, {role: "user", content: rs.TranslatedText} ], }); console.log(completion); console.log(completion.data.choices[0].message.content); // console.log(completion.data.choices[0].message); // 英語を日本語に翻訳する let en_ja = await getAwsTranslate(completion.data.choices[0].message.content,'en','ja'); console.log(en_ja); speakOutput = en_ja.TranslatedText.trim() + handlerInput.t('REPROMPT_MSG'); ChatGPTに次のように振舞うように指示しています。 あなたは、親切なスマートスピーカーアシスタントです。声 で聴いて理解しやすい簡潔に100文字程度の回答を返します。 8秒制限に引っかからないように、 長すぎる回答を防止するため 10 以上です。ありがとうございます。