この記事は Akerun Advent Calendar 2024 - Qiita の20日目の記事です。
こんにちは。Esperna - Qiita です。ファームウェアの開発をしています。 本記事はOpen AIのAPIやAkerun APIを使って遊んでみたいと思ってる方に読んでもらえると嬉しいです。
何故OpenAIのAPIを使って施解錠してみようと思ったか
Function CallingというOpen AIが提供している仕組みが面白そうと思ったからです。 ChatGPTはAIに対して自然言語の入力を渡すと自然言語で応答を返してくれますが、 Function Callingという仕組みは、Open AIのAPIに対して自然言語の入力及び自身が定義した関数の情報を渡すと JSON形式で関数と引数を返してくれるというものです。 Function Callingを使うことで、自然言語の入力に対して自分が呼び出したい関数の呼び出しを行うことができます。
何をしたか
百聞は一見に如かず。以下はCUIからの標準入力に対して、Akerun APIを実行するというデモです。
ご覧の通り、「解錠して」、「施錠して」、「開けごま」、「鍵かけといて」、「鍵開けて」、「鍵閉めて」、「アバカム」など自然言語の入力にばらつきがあっても、 モーター錠の施錠及び解錠という一貫した出力を得ることができます。 「月が綺麗ですね」という文脈を無視した発言に対しては「何を言ってるのか分かりません」という応答を返しています。
今回はシンプルさとデモ作成のスピードを優先するため、Akerun APIとしては内容がシンプルで分かりやすい遠隔操作の施錠及び解錠操作のリクエストを選び 自然言語の入力も音声入力ではなくCUIからの標準入力としました。 オートロックまでの秒数やオートロック開始・終了時刻を指定できる設定変更リクエストAPIなどを使うように、自作の関数及びプロンプトを指定してあげれば もっと複雑なこともできます。
工夫した点
今回のデモの応答パターンは 施錠動作、解錠動作、「何を言ってるのか分かりません」応答 の3つなのですが、冪等性を担保するため(何回やっても同じ応答にする)ために、次のことを行いました。
OpenAIのChat Completions APIを呼び出す際にはユーザからのmessageを渡す必要があります。 デモではアシスタントとユーザー(あなた)のやり取りは延々と繰り返してますが、 Chat Completions APIには全てのmessageを渡すのではなく、system、assistant、userの3つのメッセージのみを渡すことで 応答が安定するようにしました。
今回書いたコードのスニペットは以下です。
function direct(msg) { rl.question(msg, async (answer) => { messages.push({ role: "user", content: answer }); const response = await openai.chat.completions.create({ model: "gpt-4o", messages, tools, }); const toolCall = response.choices[0].message.tool_calls[0]; const args = JSON.parse(toolCall.function.arguments); const request = args.request; const command = getCommand(request); executeCommand(command); messages.pop(); direct("アシスタント:次は何をしますか?\nあなた: "); }); } direct("アシスタント: " + messages[1].content + "\nあなた: ");
function getCommand(request) { switch (request) { case "lock": return Commands.LOCK; case "unlock": return Commands.UNLOCK; default: return Commands.UNKNOWN; } } function executeCommand(command) { switch (command) { case Commands.LOCK: case Commands.UNLOCK: cp.execSync(commandsMap.get(command)); break; case Commands.UNKNOWN: default: console.log("何を言ってるのかわかりません"); break; } } const tools = [ { type: "function", function: { name: "getCommand", description: "Get the command string. Call this whenever you need to know command, for example when a customer asks 'open the door'", parameters: { type: "object", properties: { request: { type: "string", description: "The customer's request regrading smart lock. Possible request is single word request. Possible request shall be 'lock' or 'unlock' or 'unknown'", }, }, required: ["request"], additionalProperties: false, }, }, }, ]; const messages = [ { role: "system", content: "You are a helpful customer support assistant for smart lock. You need to get command by choosing 'lock' or 'unlock' or 'unknown' as single word request from customer message. customer message shall be translated into English and shall be interpreted as lock or unlock", }, { role: "assistant", content: "私はスマートロックのためのサポートアシスタントです。施解錠・錠設定にまつわる指示を承ります", }, ];
今後の予定
既に 【動画あり】Google AssistantでスマートロックAkerunを音声操作する - フォトシンス エンジニアブログで似たようなことやってますが、 音声入力できるようにしてみたいなと思います。 自然言語の入力をCUIからの標準入力ではなく音声入力にすれば、一気に使う人の敷居が下がります。 施解錠や錠設定の処理自体を自然言語で処理できるようにすることが効率化に寄与するとは思いませんが、 自然言語のインターフェースによって実行できる処理が増えていけば、 省人化・人手レスな世の中に繋がっていくと思っています。
参考文献
platform.openai.com developers.akerun.com
株式会社フォトシンスでは、一緒にプロダクトを成長させる様々なレイヤのエンジニアを募集しています。 photosynth.co.jp Akerunにご興味のある方はこちらから akerun.com