AIエージェントは何から取り組む?社内取り組み紹介

こんにちは!AIソリューショングループの太田です。

このコラムでは生成AIエージェントは知っているが、何から始めるべきか分からない方向けに、生成AIエージェントを使った問い合わせ対応の取り組みを紹介します。

さらに、私たちの生成AIエージェント開発の失敗談や工夫点も紹介しています。

みなさんの今後の開発や検証の参考になれば幸いです。

生成AIエージェントとは?

そもそも生成AIエージェントとは、ユーザーの指示に対して、LLMが目的を達成するためのタスクを考え、自律的に実行するシステムです。LLM単体で完結するわけではありません。

最近主流な生成AIエージェントだと、最初にユーザーから与えられた依頼内容を完了するために、LLMが実行可能な小さなサブタスクに分割する計画をします。次に、LLMがタスクを行うためのツールを選び実行します。さらに、実行結果をLLMが評価し、誤りがあればタスクを修正しやり直すことで最終的にユーザーが意図した結果を得ることができます。

生成AIエージェントは何ができますか?

RAGを用いた質問応答の高度化、繰り返し行う単純作業の自動化、レポート作成など、ビジネスプロセスを 生成AIエージェントで効率化できる可能性があります。

生成AIエージェントの応用については以下のスライドをご覧ください。

speakerdeck.com

最初におすすめの検証

最初にエージェントを取り組むのであれば、RAGアルゴリズムによる質問応答が良いと思います。 いきなり先進的なテーマで検証するのも、もちろんグッドです。

ただ先進的なテーマから始めると課題設定に問題があるのか、エージェントに問題があるのか検証が難しくなります。最初は、精度の肌感がわかりやすい単純なテーマでエージェントの精度検証することをおすすめします。

私は、以下のような検証ステップで順番にタスクの難易度を上げ、エージェントが使用できるツールの数を増やしながら、生成AIエージェントを使用する開発者の知見を蓄積するのが良いと思っています。

エージェントの検証ステップ

実際に検証しながら、社内でユースケースを探すコミュニケーションを取りつつ、エージェントワークフローで解決したらどんな旨みがあるか考えてみるのはいかがでしょうか。

RAGとエージェントの比較記事やエージェント開発記事は今後チームメンバーから公開されます。

電通総研の取り組み紹介

以下では、私たち社内メンバー3名で取り組んだ事例を紹介します。

エージェントの開発は予想以上に難航し、多くの課題に直面しました。しかし、プロンプトの工夫や継続的な改善を通じて、質の高い回答を提供できるエージェントを作り上げることができました。そのノウハウを共有いたします。

現在、開発したエージェントはさらなる改良を行い、弊社の実業務に活用できるようにブラッシュアップを進めています。

後にも出てきますが、エージェント開発で大事なのは「人間ならどう考え、どう判断するのかを常に自問自答すること」です。この考え方が、RAGアルゴリズム開発との最大の違いとなります。

問題設定:ヘルプデスクの一次回答

今回の取り組みでは、過去にKnow Narratorのお客様から頂いた問い合わせに対して、生成AIエージェントが一次回答案を生成できるか検証しました。そして、実際に担当者が回答した内容と、生成AIエージェントが回答した内容を比較し、評価を行いました。

AITCのエージェント検証内容

挑戦的なポイント

  • LLMはKnow Narratorの構成や使用方法、仕様を知らないこと(業務知識の不足)
  • 用意したツールのヘルプサイトと仕様書が類似していること(ツール利用力に影響あり)
  • 問い合わせの中には複数の質問が含まれていること(一問一答ではない)

開発に利用したもの

エージェントのベースとなるLLMはAzure OpenAI Serviceの以下を利用しました。

  • gpt-3.5-turbo-1106
  • gpt-4-turbo-1106
  • gpt-4-turbo-0125

今回のエージェントを開発する上で必要な機能はjsonモードとtool calling(ツール呼び出し)です。 その2つが使えれば、geminiでも、caludeでも問題ありません。

エージェント開発のフレームワークは以下を利用しました。

  • LangChain(LangGraph)
  • azure assistants api v1
  • azure openai tools

エージェントが使うツールは3つ用意しました。

  • Azure AI Search(顧客も見れるヘルプサイト)
  • Azure AI Search(開発者向け仕様書)
  • Bing Search(検索エンジン)

Azure AI Searchはチャンク区切りのハイブリッド検索です。
今回はモデルの違いやライブラリの違いも同時に学んでいました。
スレッド管理やコード生成を使うわけでもないので、Assistants apiである必要も実はありません。

以降は活動の中でエージェント開発に関する重要なポイントを紹介します。

活動1)エージェントのワークフローを準備

まずは回答精度にはこだわらず、エージェントのワークフローを作成しました。

エラーがなく、ワークフローが最後まで実行されることを確認します。トライ&エラーがしやすいように、最初は費用対効果の高いモデル(gpt-3.5-turbo-16k)を使用しました。

実際に実装したエージェントのワークフローは以下の3パターンです。

エージェントワークフロー

まだこのタイミングではどのエージェントワークフローが良いかは判断がつきません。

エージェント開発のフレームワークの3つの異なる種類で同じエージェントワークフローを作成し、比較することで、ライブラリの違いやワークフローの特性を理解することができました。

エラーなく回答できることを確認した後は、評価してチューニングです。

余談

特にアーキテクチャで参考にした論文と実装は以下です。

LangChainのブログ
Plan-and-Execute Agents

論文の実装

ScreenAgentのアーキテクチャ

活動2)評価データセットでの精度検証と課題の洗い出し

エージェントの性能を簡単に確認するために、評価データセットで検証を行いました。評価データセットの作成や難易度の設定にも工夫を凝らしましたが、詳細については省略します。 gpt-3.5-turboを使用して数十の問題を検証した結果、以下の課題が明確になりました。

LLMの推論の課題

  • LLMにKnow Narratorの知識がない(Know Narratorとは何で、どういう提供方法で、何を使って開発されて、顧客は何の設定を変更できるかなど)
  • 顧客の置かれている現状を把握できていない(どういう状況でどんな課題に遭遇したのか理解できていない)

ツール利用の課題

  • ツールの誤用が多い(ツール呼び出しに偏りがある、使ってほしいツールを使わない)
  • パラメータ生成でインデックスの区別ができない(Azure AI Searchのインデックス違いを同じツールにした場合に起こる)
  • パラメータのクエリが英語になる

計画の課題

  • 実行不可能なサブタスクを生成する(エージェントの持つツールでは解決できない計画を立てたり、愚直に顧客のAzure環境での実行手順を書いてしまうなど)
  • 計画のサブタスクの粒度が粗い(サブタスク実行後に正しい結果が得られたか評価できないようなサブタスクを作る)
  • サブタスクの量が無駄に多い(似たようなサブタスクを作ったり、8ステップもサブタスクを作られると終了できない恐れがある)

自己修正の課題

  • 細かすぎる振り返りをする(細かく事実の有無の確認をする)
  • 意味のない改善をする(同じツールで似たようなクエリを使い続ける)

エージェントアーキテクチャの課題

  • サブタスク全て終了後に自己修正する①Plan-and-execute型は、サブタスクが多い中で再計画されると回答時間が長すぎる
  • ③ReAct型だとステップバイステップすぎて回答まで何ラウンドで辿り着けるか事前に判断できず、評価が難しい

この時点で、 以降のチューニングは②Plan-and-execute型の真ん中を使うことにしました。

また以降のチューニングはgpt-4-turboを使います。

活動3)ナレッジのドキュメント化

LLMの推論における課題解決を目指します。 

LLMの推論の課題

  • LLMにKnow Narratorの知識がない(Know Narratorとは何で、どういう提供方法で、何を使って開発されて、顧客は何の設定を変更できるかなど)
  • 顧客の置かれている現状を把握できていない(どういう状況でどんな課題に遭遇したのか理解できていない)

Know Narratorに関する知識がない課題を解決するため、Know Narratorの仕様をsystem promptで与えています。

顧客の置かれている現状の把握に関しては、今回の検証では方針だけ定め、課題として残しました。これはフレーム問題ですね。

しかし、このナレッジの文章化だけでも計画の質も回答の内容も大幅に改善されました。

活動4)各LLMの観測範囲のチューニング

意外と大事なのが各LLMが観測するプロンプトの範囲です。
LLMは、計画、ツール呼び出し、自己修正(振り返り)、サブタスクの回答生成、最終回答生成の5箇所で利用します。

最初は、マルチエージェントのように考えて、メインタスクとサブタスクを完全に独立にして検証しました。 残念ながら、各パートでロールを区別し、責務に関するプロンプトだけ与えても、精度改善にはなりませんでした。 例えば、以下の図のように計画担当とサブタスク担当と最終回答担当を別のエージェントのように区別して考えてみます。

各ロールの観測範囲を間違えるとタスクは失敗する

サブタスク担当者にメインタスクに関する情報を与えないと、サブタスクの回答は明後日の方向にいきます。その後のメインの回答も良くなりません。

大事なのは、各担当者にそもそもの問い合わせは何で、全体の仕事のうちあなたが取り組む仕事は何かを教えてあげる必要があることです。また、担当者に余計な気遣いをさせないために別の人がサブタスクを解いていることも教えてあげます。これがエージェントの観測範囲によるチューニングです。

結果的に、以下のように各担当者のロールごとの観測範囲を定めました。

各ロールの観測範囲(振り返り部分は図が見にくくなるので割愛)

今回の検証ではLLMに与える情報が結果的に増え、各ロールで独立にして消費トークン数を抑え、推論速度の向上につなげることは難しかったです。

活動5)計画のプロンプトエンジニアリング

次に計画の課題に関して対策を講じます。 計画は難しい問題をサブタスクに分解する能力です。

計画の課題

  • 実行不可能なサブタスクを生成する(エージェントの持つツールでは解決できない計画を立てたり、愚直に顧客のAzure環境での実行手順を書いてしまうなど)
  • 計画のサブタスクの粒度が粗い(サブタスク実行後に正しい結果が得られたか評価できないようなサブタスクを作る)
  • サブタスクの量が無駄に多い(似たようなサブタスクを作ったり、8ステップもサブタスクを作られると終了できない恐れがある)

実行不可能なサブタスクに対する課題は、どのツールを使うかサブタスクの中で指定させます。
同時にサブタスクの粒度が粗い課題は、どのツールを使って何を知りたいかを明確にするようプロンプトで指示をします。
サブタスクの生成例としては「ツールAを使って、YのZ方法を知る」ような粒度で考えて生成してもらいます。
こうすることで、サブタスクのゴールが明確になり、LLMが評価しやすくなります。

計画が無駄に長すぎる課題には、サブタスクを3つになるようプロンプトで指示をします。

具体的な生成された計画の例です。

{
  "planning": [
    "search_know_narrator_help_site_docsを使って'Know Narrator Chat データ保存先'を知る",
    "search_know_narrator_developer_docsを使って'Azure OpenAI Service データ取り扱い'を知る",
    "search_microsoft_learn_docsを使って'Azure OpenAI Service オプトアウト申請後のデータ取り扱い'を知る"
  ]
}

余談

計画の質は人間が実行できるかで評価することをお勧めします。 経験の浅い人間が同様の計画をチームリーダーから与えられたときに実行できるかを考えます。 実行できないと思うならば、計画は失敗と考えています。

当たり前ですが、gpt-35-turboからgpt-4-turbo-1106にすると質がかなり良くなります。

活動6)ツール呼び出しのチューニング

サブタスクごとに実行するツール呼び出しでは、関数インターフェースをチューニングすることになります。
LLMが呼び出すツールは以下のようなフォーマットで記述します。

tools = [
        {
            "type": "function",
            "function": {
                "name": "実在するソースコードの関数名(ツール名)",
                "description": "関数(ツール)を呼ぶための関数の概要",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "関数(ツール)の引数名": {
                            "type": "引数の型(string など)",
                            "description": "関数(ツール)の引数の説明"
                        },
                    },
                    "required": ["引数で必須なもの"]
                }
            }
        }
]

具体的には、ツール名、ツールの概要、ツールのパラメータ名とその説明をチューニングする必要があります。 詳しくはAzureのリファレンスをご覧ください。

Azure OpenAI Service の REST API リファレンス - Azure OpenAI | Microsoft Learn

特にツール名とツール概要は慎重に設計する必要があります。

ツール利用の課題

  • ツールの誤用が多い(ツール呼び出しに偏りがある、使ってほしいツールを使わない)
  • パラメータ生成でインデックスの区別ができない(Azure AI Searchのインデックス違いを同じツールにした場合に起こる)
  • パラメータのクエリが英語になる

ツールの誤用が多い課題は、ツール名とツール概要を丁寧に記述し、どんなドキュメント結果が得られ、いつ利用するかを書きます。ツール名や概要を適当に書くと、期待しないツールが間違って呼ばれます。例えば、Microsoftのサイト内しか検索しないのにツール名をweb_searchにするとMicrosoftのサイト以外でも検索できると勘違いされます。

パラメータのクエリが英語になる課題は、パラメータの説明文に日本語で出力するように書きます。

パラメータ生成でインデックスの区別ができない課題は、それぞれ別のツール(関数)に変更しました。

失敗談

gpt-4-turbo-0125があるのに利用してなかったことです。 gpt-4-turbo-1106では、日本語のパラメータ生成がバグりやすかったです。 gpt-4-turbo-1106ではなく、gpt-4-turbo-0125を使うようにしましょう。

活動7)振り返りのプロンプトエンジニアリング

振り返りは、サブタスクの内部でツール選択の実行結果を評価します。 具体的にはサブタスクの目標に対して、ツールの実行結果が期待するドキュメントを検索できたか評価し、ツール選択をやり直すかLLMに判断してもらいます。

ここでも大事なのは人間ならどう評価するかを言語化することです。

自己修正の課題

  • 細かすぎる振り返りをする(細かく事実の有無の確認をする)
  • 意味のない改善をする(同じツールで似たようなクエリを使い続ける)

サブタスクの回答を細かく事実の確認をする課題は、評価内容を変えて、ツール実行結果がサブタスクに必要な情報を取得したかで評価しました。

振り返り後のツール選択で同じツールの似たようなクエリを生成する課題は、プロンプトでツールを変えるときやクエリを変えるときの基準を与えました。

そうすることで、エージェントは、最初にクエリを変更してリトライしたり、クエリが正しそうなのにほしいドキュメントが得られなければ、ツールを変えるような動きになりました。

失敗談

振り返りは最初からエージェントフローに入れていましたが、各プロンプトのチューニングが終わるまではいらないです。 別のプロンプトをチューニング中に自己修正されても、うまくいかないです。

更なる改善と挑戦について

推論やアーキテクチャの効率化

最終的にLLMモデルはすべてgpt-4-turbo-0125を利用しています。 推論時間が一問に対して、平均3分はかかっています。 サブタスクの数は非同期で並列処理していますが、最終回答には全てのサブタスクの結果が入力トークンに含まれ、回答するトークン数も多く推論時間がかかってしまいます。 最近の高性能な別のモデルを使うなどして回答速度が上がるか検証していきます。

ツールを実運用に合わせて変更

今回の検証ではRAGと比較するため、わざわざAzure AI Searchを使用しましたが、普段使いする場合はツールを変更します。 例えばヘルプサイトならBing Searchでドメイン縛りで検索したり、開発仕様書ならconfluence apiを使うなどです。 今回のケースだとKnow Narratorのアップデートの度に、変更された仕様書で参照文書のインデックスを作り直すのは、手間で更新されなくなってしまいます。

人間に依頼する選択

質問の時点ではドキュメントになっておらず、回答できないことがあります。 例えば、バグ改善中にいつ頃対応が終わりそうか聞かれたり、今後の開発予定内容を聞かれても、別アプリで管理されていてエージェントはアクセスできないので分かりません。 そういった場合、人間が回答するべきです。

無理して答えようと試行錯誤してトークンを消費するのではなく、人間に依頼するツールを作るなどが考えられます。

顧客の置かれている状況を理解

顧客が問い合わせでヘルプサイトのURLと一緒にどの手順で詰まったか記載されている場合、相手の状況を理解する必要があります。 そのため、指定されたURLを検索し、どの手順で詰まったか理解した上で計画を立てるような生成AIエージェントのスキルを作る必要があります。

ただし、一般的にはユーザーが悪意のあるURLを送りつける可能性もあるので、センシティブに考える必要もあります。

質問の曖昧さや情報不足に対する対応

相手の情報不足の場合、検証するのにどの情報が不足しているのか理解し、追加で情報を提供するよう返答します。 論文でも指摘されている能力です。 また、相手の理解度に合わせて回答の粒度を調整することも大切です。 相手の質問の仕方から専門用語を使うか、平易な言葉を使うかは分けるべきです。

メモリの準備と自己進化

エージェントの行動を今はloggerで垂れ流しているので、軌跡データを正しくとり今後の精度改善につなげたいと思っています。最近では自己進化といい、エージェントの経験が積もるほど、徐々に精度が高まっていく研究もあります。

ソースコードの検索

質問の難易度で一番難しいのはドキュメントに漏れているソースコードのバグです。 バグを特定するまではいかなくても、あたりをつけるようなスキルがつくれたら良いなと思っています。 最近はリポジトリを探索してエラーの原因を見つけてくれるエージェントもいます。 ソースコードからエラー原因を探索してくれる時代が来ると、バグ特定も早くなり頼もしい限りです。

社内宣伝

社内でエージェントでできることを広く宣伝し、エージェントの活用を社員とディスカッションをしていきます。

最後に

生成AIエージェントはどんなことから取り組めばいいのか分からない方の参考になればと思い執筆しました。

去年の夏に比べ、利用できるトークン数も増え、apiの利用料も安くなり、オープンなモデルも増えました。また、API選択とパラメータ生成が苦手という問題もだいぶ克服しています。 生成AIエージェントに関してご興味がある方は、LangChainのAgentを動かすだけではなく、一歩踏み込んで開発してみてはいかがでしょか?

以上です。ありがとうございました。

執筆
AIソリューショングループ
太田真人