Building Effective agents を読む
Anthropicが公開したの"Building effective agents"を読んでみた。
効果的なエージェントの構築
What are agents?:エージェントとは?
「Agent」は、いくつかの方法で定義できます。一部の顧客は、エージェントを、複雑なタスクを達成するために様々なツールを使用し、長期間にわたって独立して動作する完全自律型システムとして定義しています。
また、事前に定義されたワークフローに従うより規定的な実装を指す言葉として使用する顧客もいます。
Anthropicでは、これらのバリエーションをすべてエージェントシステムとして分類していますが、ワークフローとエージェントの間で重要なアーキテクチャ上の区別を設けています。
- ワークフローとは、LLMとツールが、事前に定義されたコードパスを通して連携するシステムです。
- 一方、エージェントとは、LLMが自身のプロセスとツールの使用を動的に指示し、タスクをどのように達成するかを制御するシステムです。
以下では、両方のタイプのエージェントシステムについて詳しく説明します。「付録1: エージェントの実際の使用例 」では、これらの種類のシステムを使用することで、顧客が特に価値を見出している2つのドメインについて説明します。
ここでは、ワークフローは事前に定義された手順に従うシステムであり、エージェントは、より動的で自律的なシステムであるという違いを強調している。
When (and when not) to use agents:エージェントを使うべき時(とそうでない時)
LLM(大規模言語モデル) を使用したアプリケーションを構築する際には、可能な限り最もシンプルな解決策を見つけ、必要に応じてのみ複雑さを増すことをお勧めします。
これは、エージェントシステム をまったく構築しないことを意味するかもしれません。エージェントシステム は、より良いタスクパフォーマンスのためにレイテンシー(遅延)とコストをトレードオフすることが多く、このトレードオフがいつ理にかなっているかを考慮する必要があります。
より複雑さが必要な場合は、ワークフローは明確に定義されたタスクに対して予測可能性と一貫性を提供しますが、エージェントは、柔軟性とモデル主導の意思決定が大規模に必要な場合に適しています。ただし、多くのアプリケーションでは、検索とインコンテキストの例を用いた単一のLLM呼び出しを最適化するだけで十分なことがほとんどです。
LLM(大規模言語モデル) を用いたアプリケーション開発において、最もシンプルな解決策から検討し、必要に応じて複雑さを増していくことを推奨している。エージェントシステム を導入する前に、まずはシンプルなアプローチで十分かどうかを検討することが重要。
When and how to use frameworks:フレームワークを使う時と方法
エージェントシステムをより簡単に実装するためのフレームワークは数多くあります。例えば、以下のようなものがあります。
- LangChainのLangGraph
- Amazon BedrockのAI Agent framework
- Rivet、ドラッグアンドドロップGUI LLMワークフロービルダー
- Vellum、複雑なワークフローの構築とテストのための別のGUIツール
これらのフレームワークは、LLMの呼び出し、ツールの定義と解析、呼び出しの連結などの標準的な低レベルタスクを簡素化することで、簡単に始めることができます。しかし、これらのフレームワークは、基盤となるプロンプトとレスポンスを不明瞭にする余分な抽象化レイヤーを作り出すことが多く、デバッグを困難にする可能性があります。
また、よりシンプルな設定で十分な場合に、複雑さを追加してしまう誘惑に駆られる可能性もあります。
開発者は、LLM APIを直接使用することから始めることをお勧めします。多くのパターンは数行のコードで実装できます。もしフレームワークを使用する場合は、基盤となるコードを理解していることを確認してください。内部構造に関する誤った仮定は、顧客のエラーの一般的な原因です。
私たちのクックブックで、いくつかのサンプル実装を参照してください。
フレームワークは便利だが、抽象化レイヤーがデバッグを困難にしたり、不必要な複雑さを招く可能性があることを指摘している。そのため、まずはLLM APIを直接使用して、シンプルな実装から始めることを推奨している。また、フレームワークを使用する場合は、内部のコードを理解することが重要であると強調。
フレームワークを使う際には、以下の点に注意する。:
- 抽象化レイヤー: フレームワークは、抽象化レイヤーを追加することで、基盤となるプロンプトやレスポンスを不明瞭にする可能性があり、デバッグを困難にする。
- 不必要な複雑さ: フレームワークは、よりシンプルな設定で十分な場合でも、複雑さを追加してしまう可能性がある。
- 内部コードの誤解: フレームワークの内部コードについて誤った解釈をすると、エラーの原因になる可能性がある。
まず、多くのフレームワークが、エージェントシステムの導入を容易にすると述べている。これらのフレームワークは、LLM(大規模言語モデル) の呼び出し、ツールの定義と解析、呼び出しの連結といった、標準的な低レベルタスクを簡素化することで、開発を容易にしてくれる。
Building blocks, workflows, and agents:構成要素、ワークフロー、そしてエージェント
このセクションでは、本番環境で見られるエージェントシステムの一般的なパターンを探ります。
まず、基礎となる構成要素である拡張されたLLMから始め、シンプルな構成的なワークフローから自律的なエージェントへと、段階的に複雑さを増していきます。
構成要素: 拡張されたLLM
エージェントシステムの基本的な構成要素は、検索、ツール、メモリなどの拡張機能で強化されたLLMです。私たちの現在のモデルは、これらの機能を積極的に利用でき、独自の検索クエリを生成したり、適切なツールを選択したり、保持する情報を決定したりすることができます。
これらの機能を特定のユースケースに合わせて調整し、LLMに簡単で十分に文書化されたインターフェースを提供することに焦点を当てることをお勧めします。
これらの拡張機能を実装する方法はたくさんありますが、1つのアプローチは、最近リリースされたModel Context Protocolを通じて、シンプルなクライアント実装でサードパーティツールのエコシステムと統合できるようにすることです。
この投稿の残りの部分では、各LLMの呼び出しがこれらの拡張機能にアクセスできると仮定します。
ワークフロー:プロンプトチェイニング
プロンプトチェイニングは、タスクを一連のステップに分解し、各LLM呼び出しが前のステップの出力を処理します。中間ステップにプログラムによるチェック(下の図の「ゲート」を参照)を追加して、プロセスがまだ順調に進んでいることを確認できます。
このワークフローを使用するタイミング: このワークフローは、タスクを固定されたサブタスクに簡単かつきれいに分解できる状況に最適です。主な目標は、各LLM呼び出しをより簡単なタスクにすることで、レイテンシーと引き換えに精度を向上させることです。
プロンプトチェイニングが役立つ例:
- マーケティングコピーを生成し、それを別の言語に翻訳する。
- ドキュメントのアウトラインを作成し、そのアウトラインが特定の基準を満たしているかを確認し、そのアウトラインに基づいてドキュメントを作成する。
ワークフロー:ルーティング
ルーティングは、入力を分類し、専門的なフォローアップタスクに誘導します。このワークフローにより、関心の分離と、より専門的なプロンプトの構築が可能になります。このワークフローがないと、ある種類の入力に対して最適化すると、他の入力のパフォーマンスが低下する可能性があります。
このワークフローを使用するタイミング: ルーティングは、個別に処理した方が良い明確なカテゴリがあり、LLMまたはより従来の分類モデル/アルゴリズムのいずれかによって分類を正確に処理できる場合に、複雑なタスクに適しています。
ルーティングが役立つ例:
- さまざまな種類の顧客サービスクエリ(一般的な質問、払い戻しリクエスト、技術サポート)を、さまざまなダウンストリームプロセス、プロンプト、およびツールに誘導する。
- 簡単/一般的な質問をClaude 3.5 Haikuのようなより小さなモデルにルーティングし、難しく/珍しい質問をClaude 3.5 Sonnetのようなより有能なモデルにルーティングして、コストと速度を最適化する。
ワークフロー:並列化
LLMは、タスクを同時に処理し、その出力をプログラムで集計できる場合があります。このワークフローである並列化は、2つの主要なバリエーションで現れます。
セクション化: タスクを並列実行される独立したサブタスクに分割する。
投票: 同じタスクを複数回実行して、多様な出力を得る。
このワークフローを使用するタイミング: 並列化は、分割されたサブタスクを速度のために並列化できる場合、またはより高い信頼性の結果を得るために複数の視点や試行が必要な場合に効果的です。複数の考慮事項がある複雑なタスクの場合、LLMは通常、各考慮事項が個別のLLM呼び出しによって処理される場合に、特定の各側面に焦点を当ててより良いパフォーマンスを発揮します。
並列化が役立つ例:
セクション化:
- 1つのモデルインスタンスがユーザーのクエリを処理し、別のモデルインスタンスが不適切なコンテンツやリクエストをスクリーニングするガードレールを実装する。これは、同じLLM呼び出しにガードレールとコアレスポンスの両方を処理させるよりもパフォーマンスが向上する傾向があります。
- LLMのパフォーマンスを評価するための自動評価を実装し、各LLM呼び出しが特定のプロンプトに対するモデルのパフォーマンスの異なる側面を評価します。
投票: - コードの脆弱性をレビューする場合、複数の異なるプロンプトがコードをレビューし、問題が見つかった場合はフラグを立てます。
- 特定のコンテンツが不適切かどうかを評価する場合、複数のプロンプトが異なる側面を評価したり、偽陽性と偽陰性のバランスを取るために異なる投票しきい値を必要とする。
ワークフロー:オーケストレーターワーカー
オーケストレーターワーカーのワークフローでは、中央のLLMがタスクを動的に分解し、それらをワーカーLLMに委任し、その結果を合成します。
このワークフローを使用するタイミング: このワークフローは、必要なサブタスクを予測できない複雑なタスクに適しています(たとえば、コーディングでは、変更が必要なファイルの数と各ファイルでの変更の性質は、タスクによって異なる可能性があります)。地形的には似ていますが、並列化との主な違いは、その柔軟性です。サブタスクは事前定義されておらず、特定の入力に基づいてオーケストレーターによって決定されます。
オーケストレーターワーカーが役立つ例:
- 毎回複数のファイルに複雑な変更を加えるコーディング製品。
- 関連する可能性のある情報を求めて、複数のソースから情報を収集および分析する検索タスク。
ワークフロー:評価者オプティマイザー
評価者オプティマイザーのワークフローでは、1つのLLM呼び出しが応答を生成し、別のLLM呼び出しがループで評価とフィードバックを提供します。
このワークフローを使用するタイミング: このワークフローは、明確な評価基準があり、反復的な改善が測定可能な価値を提供する場合に特に効果的です。良い適合性の2つの兆候は、まず、人間がフィードバックを明確にするとLLMの応答が明らかに改善されること、そして、LLMがそのようなフィードバックを提供できることです。これは、人間が洗練されたドキュメントを作成するときに経験する反復的な執筆プロセスに似ています。
評価者オプティマイザーが役立つ例:
- 翻訳者LLMが最初は捉えきれないニュアンスがあるが、評価者LLMが役立つ批評を提供できる文学翻訳。
- 包括的な情報を収集するために複数回の検索と分析が必要な複雑な検索タスク。評価者は、さらなる検索が必要かどうかを判断します。
エージェント
LLMの重要な能力(複雑な入力を理解し、推論と計画に取り組み、ツールを確実に使用し、エラーから回復するという重要な能力)において成熟しつつあり、製品として登場してきています。
エージェントは、ユーザーからのコマンドまたは対話型ディスカッションから作業を開始します。タスクが明確になったら、エージェントは独立して計画および実行し、追加の情報や判断のためにユーザーに戻る可能性があります。実行中、エージェントは進捗状況を評価するために、各ステップで環境から「ground truth」を取得することが重要です(ツール呼び出しの結果やコード実行など)。その後、エージェントはチェックポイントまたはブロッカーに遭遇したときに人間のフィードバックを求めるために一時停止できます。タスクは完了時に終了することが多いですが、制御を維持するために停止条件(最大反復回数など)を含めることも一般的です。
エージェントは高度なタスクを処理できますが、その実装はしばしば簡単です。これらは通常、環境フィードバックに基づいてツールを使用するLLMにすぎません。したがって、ツールセットとそのドキュメントを明確かつ慎重に設計することが重要です。ツール開発のベストプラクティスについては、付録2(「ツールのプロンプトエンジニアリング」)で詳しく説明します。
自律エージェント このエージェントを使用するタイミング: エージェントは、必要なステップ数を予測することが困難または不可能で、固定パスをハードコードできないオープンエンドの問題に使用できます。LLMは潜在的に多くのターンで動作するため、その意思決定にある程度の信頼を置く必要があります。エージェントの自律性により、信頼できる環境でのタスクのスケーリングに最適です。
エージェントの自律性とは、コストが高く、エラーが複合的に発生する可能性があることを意味します。サンドボックス環境での広範なテストと、適切なガードレールをお勧めします。
エージェントが役立つ例:
次の例は、私たち自身の実装からのものです。
- タスクの説明に基づいて多くのファイルを編集する、SWE-benchタスクを解決するためのコーディングエージェント。
- Claudeがタスクを達成するためにコンピューターを使用する「computer use」リファレンス実装。
!
これらのパターンの組み合わせとカスタマイズ
これらの構成要素は規範的ではありません。これらは、開発者がさまざまなユースケースに合わせて形作り、組み合わせることができる一般的なパターンです。成功の鍵は、他のLLM機能と同様に、パフォーマンスを測定し、実装を反復することです。繰り返しますが、成果が明らかに向上する場合にのみ複雑さを追加することを検討する必要があります。
まとめ
LLM分野での成功は、最も洗練されたシステムを構築することではありません。それは、ニーズに合った適切なシステムを構築することです。シンプルなプロンプトから始め、包括的な評価で最適化し、よりシンプルなソリューションでは不十分な場合にのみ、複数ステップのエージェントシステムを追加します。
エージェントを実装するときは、次の3つのコア原則に従うように努めています。
- エージェントの設計においてシンプルさを維持する。
- エージェントの計画ステップを明示的に示すことで、透明性を優先する。
- 徹底的なツールのドキュメントとテストを通じて、エージェントコンピューターインターフェイス(ACI)を慎重に作成する。
フレームワークは迅速に開始するのに役立ちますが、本番環境に移行するにつれて、抽象化レイヤーを削減し、基本的なコンポーネントで構築することを躊躇しないでください。これらの原則に従うことで、強力であるだけでなく、信頼性が高く、保守可能で、ユーザーに信頼されるエージェントを作成できます。
まず、最も基本的な構成要素として、拡張されたLLM(大規模言語モデル) が挙げられている。これは、検索、ツール、メモリなどの拡張機能を備えたLLMのこと。現在のモデルは、これらの機能を積極的に利用でき、独自の検索クエリを生成したり、適切なツールを選択したり、保持する情報を決定したりすることができる。
- 検索: 外部情報を取得する機能
- ツール:外部サービスやAPIを利用する機能
- メモリ:過去の情報を保持し、利用する機能
ワークフローは、拡張されたLLMを組み合わせて、より複雑なタスクを実行するためのパターン。ここでは、いくつかの種類のワークフローを紹介している。
プロンプトチェイニング タスクを順番に処理するステップに分解し、各ステップでLLMを呼び出します。
- タスクが固定されたサブタスクに分解できる場合に適しています。
- 各LLM呼び出しをより簡単なタスクにすることで、レイテンシーと引き換えに精度を向上させます。
ルーティング 入力を分類し、専門的な後続タスクに振り分けます。
- 異なるカテゴリの入力を別々に処理する場合に適しています。
- 分類をLLMまたは従来の分類モデル/アルゴリズムで正確に処理できる場合に有効です。
並列化 LLMを同時に動作させ、出力をプログラムで集約します。
- セクション化: タスクを独立したサブタスクに分割し、並列で実行します。
- 投票: 同じタスクを複数回実行し、多様な出力を得ます。
- サブタスクを並列化して速度を上げたり、複数の視点や試行が必要な場合に有効です。
オーケストレーターワーカー 中央のLLMがタスクを動的に分解し、ワーカーLLMに委任し、結果を統合します。
- サブタスクを事前に予測できない場合に適しています。
- サブタスクは事前定義されず、オーケストレーターが特定の入力に基づいて決定します。
評価者オプティマイザー あるLLM呼び出しが応答を生成し、別のLLM呼び出しが評価とフィードバックをループで提供します。
- 明確な評価基準があり、反復的な改善が測定可能な価値を提供する場合に有効です。
- LLMの応答が人間のフィードバックによって明らかに改善され、LLMがそのようなフィードバックを提供できる場合に適しています。
最後に、エージェントは、LLMが自身のプロセスとツールの使用を動的に制御し、タスクをどのように達成するかを決定するシステムです。
- 複雑な入力の理解、推論と計画、ツールの信頼性の高い使用、エラーからの回復などの高度な能力を必要とします。
- 人間との対話や指示に基づいて自律的に動作します。
- オープンエンドな問題や、必要なステップ数を事前に予測できない場合に適しています。
謝辞
Erik Schluntz、Barry Zhangによって書かれました。
Anthropicでエージェントを構築した経験と、お客様から共有された貴重な洞察に基づいています。
付録1: エージェントの実際の使用例
顧客との共同作業により、AIエージェントの特に有望な用途が2つ明らかになり、上述したパターンの実用的価値が実証されました。 どちらのアプリケーションも、会話と行動の両方を必要とし、明確な成功基準があり、フィードバックループを可能にし、有意義な人間の監視を統合するタスクにおいて、エージェントがいかに最大の価値をもたらすかを示しています。
A. カスタマーサポート
カスタマーサポートは、使い慣れたチャットボットのインターフェースと、ツール統合による機能強化を組み合わせています。これは、よりオープンエンドなエージェントに自然にフィットします:
- サポート・インタラクションは、外部情報やアクションへのアクセスを必要としながらも、会話の流れに自然に従うことができる。
- 顧客データ、注文履歴、ナレッジベース記事を引き出すためのツールを統合できる。
- 払い戻しやチケットの更新などのアクションをプログラムで処理することができる。
- ユーザーが定義した解決策を通じて、成功の度合いを明確に測定できる。
いくつかの企業は、このアプローチの実行可能性を実証しており、エージェントの効果に対する自信を示している。
B. コーディングエージェント
ソフトウェア開発分野では、コード補完から自律的な問題解決に至るまで、LLM機能の著しい可能性が示されています。 エージェントが特に効果的なのは、次のような理由からです。:
- コードソリューションは、自動テストによって検証可能である
- エージェントは、テスト結果をフィードバックとして、解決策を反復することができる
- 問題空間が明確に定義され、構造化されている。
- アウトプットの品質を客観的に測定できる。
私たち自身の実装では、エージェントはプルリクエストの説明だけで、SWE-bench Verified benchmarkの実際のGitHubの問題を解決できるようになりました。
しかし、自動化されたテストは機能性の検証に役立ちますが、ソリューションがより広範なシステム要件に合致していることを確認するためには、人間によるレビューが依然として重要です。
付録2: プロンプトエンジニアリングはあなたのツール
どのエージェントシステムを構築するにしても、ツールはエージェントの重要な一部となるでしょう。
ツールは、APIでその正確な構造と定義を指定することで、Claudeが外部のサービスやAPIとやりとりすることを可能にします。
Claudeが応答するとき、ツールを呼び出す予定があれば、API応答にtool_useを含める。
ツールの定義と仕様は、全体的なプロンプトと同じくらい入念なプロンプトエンジニアリングの注意を払う必要があります。この付録では、ツールのプロンプトエンジニアリングの方法について説明します。
同じアクションを指定するには、複数の方法があることがよくあります。
例えば、ファイルの編集は差分を記述するか、ファイル全体を書き直すことで指定できます。
構造化された出力の場合、コードをマークダウンの中に入れるか、JSONの中に入れることができます。
ソフトウェアエンジニアリングでは、このような違いは表面的なもので、一方から他方へ損失なく変換できます。しかし、LLMにとっては、ある形式は他の形式よりもはるかに記述が困難です。差分を書くには、新しいコードを書く前にチャンク・ヘッダーで何行変更されるかを知る必要があります。
コードをJSONの中に書く場合(マークダウンと比較して)、改行や引用符の追加のエスケープが必要です。
ツールの形式を決定する際の提案は以下の通りです:
- モデルが行き詰まる前に「考える」のに十分なトークンを与えること。
- インターネット上のテキストに自然に出現するものに近い形式を保つこと。
- コードの何千行もの正確なカウントを保持する必要がある、または書くコードの文字列エスケープが必要といった、フォーマットの「オーバーヘッド」がないようにすること。
一つの経験則として、ヒューマンコンピュータインターフェース(HCI)にどれだけの労力が費やされているかを考え、良いエージェントコンピュータインターフェース(ACI)を作るのにも同じくらいの労力を投資することを計画すべきです。その方法についていくつかの考えを示します:
- モデルの立場に立ってみてください。説明とパラメータに基づいてこのツールの使い方は明白ですか?それとも慎重に考える必要がありますか?もしそうなら、モデルにとっても同じことが言えるでしょう。良いツールの定義には、使用例、エッジケース、入力形式の要件、他のツールとの明確な境界が含まれることが多いです。
- パラメータ名や説明をどのように変更すれば、より明白になるでしょうか?これはチームの若手開発者のための優れたドキュメント文字列を書くようなものだと考えてください。特に多くの類似したツールを使用する場合に重要です。
- モデルがツールをどのように使用するかテストします:ワークベンチで多くのサンプル入力を実行して、モデルがどのような間違いを起こすかを確認し、改善を重ねます。
ツールにポカヨケを施します。ミスを起こしにくいように引数を変更します。
SWE-benchのエージェントを構築する際、実際には全体的なプロンプトよりもツールの最適化により多くの時間を費やしました。例えば、エージェントがルートディレクトリから移動した後、相対ファイルパスを使用するツールでモデルがミスを起こすことがわかりました。これを修正するため、常に絶対ファイルパスを必要とするようにツールを変更しました—そして、モデルはこの方法を完璧に使用することがわかりました。
Discussion