Taste of Tech Topics

Acroquest Technology株式会社のエンジニアが書く技術ブログ

StrandsAgents + Nova 2 Sonic + Bedrock Knowledge Base で対話型アシスタントを作成する

この記事は、以下の Advent Calendar の 18 日目における投稿です。

こんにちは、 YAMALEX の駿です。

今回は re:Invent で発表された Amazon Nova 2 SonicStrandsAgents の新機能である Bidirectional Agent を使って、 音声対話をとおして Bedrock Knowledge Base から情報を取得できるエージェントを作成しました。

Nova 2 Sonic の応答がとても速くて驚きました。 返答までの待ち時間が短く、会話としてほとんどストレスを感じません。

また、アシスタントが話している間にこちらが発話すると、 アシスタント側が自然に話をやめてこちらの発話を優先してくれるため、「あ、違う違う、それじゃなくて……」と割り込むような場面でも快適に使えます。

今回は Bedrock Knowledge Base に AgentCore のドキュメントを入れて、音声で質問してみた様子を紹介します。

1. はじめに

1.1. Nova 2 Sonic とは

Nova 2 Sonic は、 Amazon が新たに発表した Nova 2 シリーズの Speech-to-Speech モデルです。

aws.amazon.com

主なポイントは下記のとおりです。

  1. Speech-to-Speech 特化

    音声入力と音声出力を一つのモデルで扱うため、テキストベースの生成 AI と比べて、待ち時間が少なく、体感のレスポンスが速い

  2. マルチリンガル対応

    Nova Sonic と比べて対応言語が増え、日本語を含む複数言語で対話が可能
    (日本語の発音は若干不自然です)

  3. 1M トークンのコンテキストウィンドウ

    長いドキュメントやソースコード・ナレッジベースのコンテキストを保持した対話が可能

  4. ターンテイキング・クロスモーダルインタラクション

    「話の切れ目」や割り込みの扱い、音声とテキストの切り替えなど、会話に重要な部分がチューニングされている

1.2. StrandsAgents Bidirectional Agent とは

StrandsAgents は AWSOSS として公開している AI エージェント向けフレームワークで、 Bedrock だけでなく OpenAI や Gemini など複数のプロバイダを扱えるのが特徴です。

その中で、今回使ったのが Bidirectional Agent ( BidiAgent )という Strands Agents v1.19.0 から導入された実験的機能です。

「 Bidirectional 」は日本語では「双方向」という意味で、ユーザー→エージェント、エージェント→ユーザーのやり取りが同時に行われることを意味します。

「 Bidirectional Agent 」を略して「 BidiAgent 」と呼ばれています。

strandsagents.com

BidiAgent の特徴は下記のとおりです。

  1. 双方向ストリーミング前提のエージェント

    従来の「リクエスト→レスポンス」型と違い、長時間のセッションを維持しながら、音声・テキストをストリーミングでやり取りする

  2. 途中割り込みが可能

    モデルが話している途中でユーザーが話し始めると、それを検知して応答を中断・更新できる

  3. ツール呼び出しとの連携

    会話中にツールを挟み込み、結果を踏まえた応答を返せる

  4. 対応モデル

    Nova 2 Sonic 、 OpenAI Realtime API 、 Gemini Speech など、リアルタイム系の複数モデルに対応

今回の構成では、 BidiAgent x Nova 2 Sonic x Strands Tools という組み合わせで、「話しながら Bedrock Knowledge Base から情報を引っ張ってきてくれる音声アシスタント」を作りました。

2. 全体構成


構成図

ざっくり構成はこんな流れです。

  1. ユーザーの音声入力

    • PC のマイクから音声を取得
    • BidiAudioIO が音声ストリームとして BidiAgent に渡す
  2. BidiAgent ( Nova 2 Sonic )が処理

    • 音声を理解→必要に応じてツール呼び出し(今回は retrieve
  3. StrandsAgents Tools retrieve

    • Bedrock Knowledge Base に対して検索を実行し、関連するドキュメントのチャンクを取得
  4. BidiAgent が音声&テキスト応答

    • Nova 2 Sonic が検索結果をもとに生成したテキストを音声としてストリーミング出力
    • BidiAudioIO がスピーカーから再生
    • BidiTextIO がコンソールにテキスト字幕を表示

Knowledge Base には、 Amazon Bedrock AgentCore のユーザーガイドや関連ドキュメントを入れており、「 AgentCore Runtime って何?」「セッションってどう管理されてるの?」といった質問に音声で答えてもらう、という構成です。

3. 実装

Bidirectional Agent の部分は、基本的に StrandsAgents 公式ドキュメントのサンプルをベースにしています。

重要な変更点は以下の2点です。

  1. モデルに BidiNovaSonicModel(model_id="amazon.nova-2-sonic-v1:0") を指定する
  2. toolsretrieve を追加し、 KNOWLEDGE_BASE_ID 環境変数でナレッジベースを指定する
import asyncio
from textwrap import dedent

from strands.experimental.bidi import BidiAgent
from strands.experimental.bidi.io import BidiAudioIO, BidiTextIO
from strands.experimental.bidi.models import BidiNovaSonicModel
from strands.experimental.bidi.tools import stop_conversation
from strands_tools import retrieve


async def main():
    agent = BidiAgent(
        model=BidiNovaSonicModel(
            model_id="amazon.nova-2-sonic-v1:0",
            provider_config={"audio": {"voice": "tiffany"}},
        ),
        system_prompt=dedent("""\
            あなたは音声会話アシスタントです。
            [重要]質問内容に対し、可能な限り短く回答してください。 
            詳しい内容がわかったとしても詳細は問われたときに回答するのみとしてください。
        """),
        tools=[retrieve, stop_conversation],
    )

    audio_io = BidiAudioIO()
    text_io = BidiTextIO()

    await agent.run(
        inputs=[audio_io.input()],
        outputs=[audio_io.output(), text_io.output()],
    )


if __name__ == "__main__":
    asyncio.run(main())

このコード量でリアルタイム音声会話+ Bedrock Knowledge Base RAG まで持っていけるのは、かなり驚きです。

会話を終わらせたいときは「 stop conversation 」と発話すると、 stop_conversation ツールが実行され、安全にコネクションを閉じてくれます。

4. 試してみた

4.1. 質問例:「 AgentCore Runtime について教えて」

試しに、以下のように聞いてみました。

「 AgentCore Runtime について教えて」

Amazon Bedrock AgentCore ランタイムは AI エージェントをホストするためのサーバーレス環境を提供します

エージェントコアランタイムのセッションライフサイクルについて説明します

エージェントコアランタイムでは セッションが重要な役割を果たします
セッションは ユーザーとエージェントの間の個別の対話コンテキストを表します
各セッションは 独自の runtimeSessionId で識別され 専用マイクロ VM で実行されます
このマイクロ VM には分離された CPU メモリ ファイル
<後略>

きちんと Bedrock Knowledge Base に検索を行い、その内容を要約して返してくれているのが分かります。
AgentCore Runtime の「セッションごとに microVM を割り当てて分離する」などの特徴も公式ドキュメントの内容に沿った説明が返ってきました。

参考: docs.aws.amazon.com

4.2. レイテンシの計測

それぞれの処理にかかった時間を計測してみました。

No 項目 処理時間(秒)
1 ユーザー発話 0.0
2 ツール引数作成 0.3
3 ツール結果取得 0.1
4 ファーストレスポンス 1.8
合計 2.2

ユーザーが話し終わってから、最初の音声が返ってくるまで、約2秒という結果になりました。

体感としては一呼吸おいてから返事をしている感じで、一番最初に試したときは、本当に検索しているか疑ってしまうほどでした。

5. 使ってみて分かった注意点

5.1. 日本語の発音が怪しいケースがある

日本語の読み上げは、ところどころイントネーションや区切りがおかしい箇所があります。

このため、音声だけでなく、 BidiTextIO でテキストも併用し、字幕のように見ながら使うのがよさそうです。

5.2. 記号の読み上げが苦手

Nova 2 Sonic は、数式や記号を含むテキストの読み上げが少し苦手そうです。

試しに「1+1 は?」と聞いてみたところ、

  • 音声:「いち いち に です。」
  • テキスト:1+1=2 です

という形で、テキスト上は正しく答えているが、音声では演算子が消えてしまっているような挙動が見られました。

数式やコードを読み上げさせる必要がある場合は、プロンプトで「数式や記号は『プラス』『イコール』のように言葉で読む」などの指示を工夫する必要があるのではないかと思います。

5.3. RAG のコンテキスト内のコードのそのまま読む

Knowledge Base に入れているドキュメントの中にコードブロックや設定例が含まれている場合、そのまま音声で読み上げられることがあります。

  • aws bedrock-agentcore ... のような長い CLI コマンド
  • JSONYAML の設定例
  • Python コード

これらを音声で聞いても、上の記号を読み上げられない問題も相まって、正直まったく頭に入ってこないので、

  • ナレッジ側で「読み上げ用」と「参照用」を分ける
  • StrandsAgents のフックでコードや記号をフィルタリングする
  • プロンプトで「回答中にコードは読み上げない」よう誘導する

などの工夫が必要に感じました。

6. 料金

Amazon Nova 2 Sonic の料金は、 Speech と Text 、入力と出力で異なります。

モデル 形式 料金/ 100万 入力トーク 料金/ 100万 出力トーク
Amazon Nova 2 Sonic 音声 $3.0 $12.0
テキスト $0.33 $2.75

今回の例だと、入力の音声、出力の音声とテキストに料金が発生しています。

従来だと、 Amazon Transcribe で文字起こしをして、テキストにした内容を Amazon Nova 2 Lite に入力し、 Nova から出てきたテキストを Amazon Polly で音声に変換、などをしていたと思います。

参考までに、 Nova 2 Sonic の音声は 1,000 出力トークンごとに $0.012 かかりますが、 一般的に 1,000 トークンを読み上げると 2~3 分かかるといわれているため、 1,000 トークン→ 2 分と仮定すると、 Transcribe の料金だけで $0.048 かかることになります。

ここに生成 AI モデルの料金と読み上げサービスの料金が加算されるため、 Amazon Nova 2 Sonic を利用することで安価に音声対話ができている、ということが分かります。

参考:各サービスの単位ごとの料金

サービス 料金
Amazon Transcribe $0.024 /分
Amazon Nova 2 Lite $0.003 / 1,000 入力トーク
$0.025 / 1,000 出力トーク
Amazon Polly $0.004 / 1,000 文字

7. ユースケース

今回の PoC を作りながら、こういう用途に相性がよさそうだと感じました。

  1. リアルタイム翻訳&通訳

    • 入力:音声(日本語)
    • 出力:テキスト(英語) or 音声(英語)

    といった構成にすれば、簡易同時通訳のような体験が実現できます。

  2. 手が離せない状況でのナレッジ取得

    • 料理中に「肉は何グラム入れればいいんだっけ」などレシピを聞く
    • 機械をいじりながら「このエラーコードが出たときの手順を教えて」などマニュアルを検索する

    など、手がふさがっていてキーボードが打てない場面との相性がかなりいいです。

    あるいは、コーディングしながら音声で質問できれば、エディタからフォーカスを外すことなく、「隣に座ってペアプロしてくれる先輩エンジニア」のような体験が作れそうだと感じました。

まとめ

  • Nova 2 Sonic ( Speech-to-Speech モデル)
  • StrandsAgents Bidirectional Agent
  • StrandsAgents Tools retrieve x Bedrock Knowledge Base

を組み合わせて、音声で社内ナレッジにアクセスできるエージェントを作ってみました。

実際に触ってみて感じたポイントは下記3点です。

  1. レスポンスが速く、割り込みにも強いので「会話」としてストレスが少ない
  2. Knowledge Base との組み合わせで、実用的な Q&A ができる
  3. その一方で、記号・コード・数式など音声に向かないコンテンツへの対策は必要

とはいえ、まだまだこの仕組みを活かせるシーンはたくさん眠っていると思うので、 いろいろ試してみたいと思います。

Acroquest Technologyでは、キャリア採用を行っています。

  • Azure OpenAI/Amazon Bedrock等を使った生成AIソリューションの開発
  • ディープラーニング等を使った自然言語/画像/音声/動画解析の研究開発
  • マイクロサービス、DevOps、最新のOSSクラウドサービスを利用する開発プロジェクト
  • 書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長

少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。

www.wantedly.com