著者 | アパルナ・ディナカラン 編纂者:岳陽 著者による画像 エージェントは黄金時代を迎えています。数多くの新しいフレームワークの登場と、この分野への継続的な投資[1]により、現代のAIエージェントは初期の不安定な段階[2]を脱し、RAGに取って代わる開発手法として急速に普及しつつあります。では、2024年は、自律型AIシステムがメール作成、航空券の予約、データ分析といったタスクを担う年となるのでしょうか? そうかもしれません。しかし、それを実現するにはまだ多くの課題があります。インテリジェントエージェントを構築する際、開発者はどのモデル、アプリケーションシナリオ、技術アーキテクチャを使用するかだけでなく、どの開発フレームワークを選択するかを決定する必要があります。以前のLangGraphを使い続けるべきか、それとも新興のLlamaIndexワークフローに切り替えるべきか?それとも、従来の方法ですべてのコードを自分で書くべきか? この記事の目的は、皆さんの選択を容易にすることです。ここ数週間、私は複数の主流フレームワークを用いて同じエージェントを構築し、それぞれの長所と短所を技術的な観点から分析してきました。各エージェントのコードはすべて、こちらのコードリポジトリ[3]に掲載されています。 このテストで使用されるインテリジェント エージェントの基本的な概要。 このテストで使用されるエージェントは、関数呼び出しの実行、さまざまなツールやスキルの使用、外部リソースとの接続の確立、状態やメモリの共有など、複数の機能を統合します。 このインテリジェント エージェントは、次のコア機能を備えています。
これらの目標を達成するために、エージェントは3つの基本スキルを習得する必要があります。製品ドキュメントをRAG(Research Aggregator)と統合する能力、関連データベースでSQL文を生成する能力、そしてデータ分析スキルです。エージェントのユーザーインターフェースはGradioを使用して構築され、エージェント自体はチャットボットの形で構築されています。 01 コードベースエージェント(インテリジェントエージェントフレームワークを使用しない)インテリジェントエージェントを開発する際には、フレームワークに依存せず、完全に独立して構築するという選択肢があります。私はこのプロジェクトを開始した当初から、このアプローチを採用しました。 著者による画像 1.1 純粋なコードアーキテクチャ以下は、完全にコードで構築されたエージェントです。その中核を成すのは、OpenAI を搭載したスキルルーターです。スキルルーターは関数呼び出しを通じて使用するスキルを決定します。スキルが実行されると、制御はスキルルーターに戻り、他のスキルを呼び出したり、ユーザーに直接応答したりできるようになります。 エージェントはユーザー メッセージとエージェントの応答を継続的に記録し、呼び出しごとにこの完全なリストをスキル ルーターに渡して、対話全体を通じてコンテキストが保持されるようにします。 各スキルは個別のクラス(例:GenerateSQLQuery)で定義され、これらのクラスはSkillMapに格納されます。スキルルーターはSkillMapとのみ連携し、スキル名、説明、呼び出し可能な関数を読み込みます。この設計思想により、エージェントへの新しいスキルの追加は非常にシンプルになります。スキルを別のクラスとして記述し、SkillMapのスキルリストに追加するだけです。目標は、スキルルーターのコードに影響を与えることなく、新しいスキルを簡単に追加できるようにすることです。 要約すると、この実装方法はシンプルで実装が簡単ですが、克服する必要がある課題がまだいくつか残っています。 1.2 純粋なコードベースのインテリジェントエージェントの使用における課題最初の課題は、スキルルーターのシステムプロンプトの設計でした。上記の例では、スキルルーターはSQL文を対応するスキルモジュールに委譲するのではなく、自ら生成する傾向がありました。大規模な言語モデルによるタスク実行を停止しようとしたことがある人なら、そのフラストレーションをご存知でしょう。適切なプロンプトを見つけるために、私は徹底的にデバッグする必要がありました。さらに、各ステップで生成される異なる出力形式の処理も複雑でした。構造化された出力を使用しないことを選択したため、スキルルーターと各スキル内の大規模な言語モデルの呼び出しの様々な形式を処理するために、複数の戦略を用意する必要がありました。 1.3 純粋なコードベースのインテリジェントエージェントの利点コードベースのアプローチは、確固たる基盤と出発点を提供し、既存のフレームワークが提供するチュートリアルに頼ることなくエージェントの仕組みを理解できる優れた学習パスとなります。大規模な言語モデルを事前に定義された行動パターンに従って動作させるのは確かに困難ですが、コード構造自体は簡潔で明確、そして使いやすいため、特定のユースケースにおいてはこのアプローチは完全に合理的です(詳細な分析は後述します)。 02 ランゲージグラフLangGraphは、最も古いエージェントフレームワークの一つであり、2024年1月に初めてリリースされました。既存のプロセスとチェーンの非循環性の問題に対処するために設計されており、Pregelグラフ構造を採用しています。ノード、エッジ、条件付きエッジの概念を導入することで、LangGraphはエージェント内での循環プロセスの作成を簡素化し、グラフのトラバーサルをより直感的にします。LangGraphはLangChainを基盤としており、そのオブジェクトクラスと型クラスを継承しています。 著者による画像 2.1 LangGraphアーキテクチャLangGraphエージェントは表面的にはコードベースのエージェントに似ているように見えますが、その基盤となるコードは全く異なります。LangGraphも「ルーター」の概念(コード関数を介してOpenAIを呼び出し、その応答を使用して次のステップに進む)を採用していますが、異なるスキル間の切り替え制御メカニズムは全く異なります。 ここで定義されるグラフには、OpenAI呼び出しを初期化するためのノード(上記では「エージェント」)と、ツール処理ステップ用のノード(「ツール」)が含まれています。LangGraphにはToolNodeと呼ばれる組み込みオブジェクトがあり、一連の呼び出し可能なツールを受け取り、ChatMessageの応答に基づいてこれらのツールをトリガーし、操作を完了すると「エージェント」ノードに戻ります。 「エージェント」ノード (コードベースのエージェントではスキル ルーターとも呼ばれます) が呼び出されるたびに、should_continue エッジによって、応答をユーザーに直接返すか、ツール呼び出しを処理する ToolNode に返すかが決定されます。 各ノード内では、「状態」は、コードベースのエージェントがコンテキストを維持する方法と同様に、OpenAI との対話メッセージと応答のリストを保存する役割を担います。 2.2 LangGraphの使用上の課題LangGraph で構築されたスマート エージェントの例を扱うときに遭遇する主な課題は、スムーズなプロセスを保証するために Langchain オブジェクトが必要であることです。 課題1: 関数呼び出しの検証エラー ToolNode オブジェクトを使用するには、Skill コードの大規模なリファクタリングが必要でした。ToolNode は呼び出し可能な関数のリストを必要とするため、当初は既存の関数をそのまま使用できると考えていましたが、関数のパラメータ設定が誤っていたため、処理がブロックされてしまいました。 これらのスキルはクラスとして定義され、それぞれが呼び出し可能なメンバー関数を持ち、最初のパラメータは「self」です。GPT-4oは関数呼び出しを生成する際に「self」パラメータを自動的に除外するほどスマートですが、LangGraphはこれをパラメータ不足と解釈し、検証エラーをスローします。 エラー メッセージで関数の 3 番目のパラメータ (データ分析スキルの「args」) が不足しているパラメータとして誤ってマークされていたため、この問題を理解するのに数時間かかりました。 この誤解を招くエラー メッセージは、実際には LangGraph ではなく Pydantic から送信されていることに注意してください。 最終的に、Langchain の @tool デコレータを使用して、自分のスキルを基本メソッドとして書き直すことを決意し、プログラムは正しく動作しました。 課題2: デバッグ 前述の通り、フレームワーク内でのデバッグは非常に困難です。これは主に、分かりにくく分かりにくいエラーメッセージと、フレームワーク内の抽象的な概念によって変数のトレースや検証が非常に複雑になるためです。 この抽象概念は、主にエージェント間でやり取りされるメッセージを追跡する試みに反映されています。LangGraphはメッセージを状態["messages"]に保存します。グラフ内の一部のノードは、これらのメッセージから自動的に情報を抽出します。この自動処理により、ノードがメッセージにアクセスした際に、メッセージの具体的な内容を把握することが困難になる可能性があります。 エージェントのアクションの連続的なビュー(画像は著者提供) 2.3 LangGraphの利点LangGraphの最大のメリットは、その使いやすさにあります。グラフ構造のコードは簡潔で分かりやすいです。複雑なノードロジックを持つシナリオでも、LangGraphは明確なグラフビューを提供し、エージェント間の接続状況を容易に把握できます。さらに、LangGraphはLangChainで構築された既存のアプリケーションを直接変換できます。 2.4 学んだ教訓LangGraph フレームワークの機能のみを使用すると、すべてが非常にスムーズに実行されます。しかし、フレームワークの外に出ようとすると、頭痛の種となるデバッグを行う準備をする必要があります。 03 LlamaIndexワークフローWorkflowsは、インテリジェントエージェントフレームワーク分野の新参者であり、今年の初夏にデビューしました。LangGraphと同様に、再帰型インテリジェントエージェントの構築プロセスを簡素化するように設計されています。さらに、Workflowsは非同期実行機能に特に重点を置いています。 ワークフローでは、特定の設計要素、特に接続ロジックにエッジや条件付きエッジではなくイベントを使用する点が、LangGraphと直接類似しているように見えます。ワークフローでは、エージェントロジックは「ステップ」(LangGraphの「ノード」に相当)にカプセル化され、イベントの送信と受信は異なるステップ間での情報の受け渡しを担います。 著者による画像 上で説明したフレームワークはLangGraphと構造的に非常に似ていますが、重要な違いが1つあります。ワークフローに初期化ステップを追加し、エージェントの環境コンテキストを準備しています。これについては後ほど詳しく説明します。構造は似ていますが、基盤となるコード実装は大きく異なります。 3.1 ワークフローアーキテクチャ以下のコードスニペットは、ワークフローのアーキテクチャを示しています。LangGraphと同様に、このセクションでは状態情報を設定し、スキルをLLMオブジェクトにバインドしました。 ここでは、「prepare_agent」という追加ステップも定義しています。このステップは、ユーザー入力をChatMessageに変換し、ワークフローのメモリに保存する役割を担います。このプロセスを別のステップとして分離することで、エージェントはワークフローの各ステップを通過する際にこのステップに繰り返し戻ることができるため、ユーザー情報がメモリに繰り返し追加されることを回避できます。 LangGraphの実装では、グラフ外に`run_agent`メソッドを配置することで同じ機能を実現していました。この変更は主にスタイル上の理由によるものですが、このロジックをワークフローとグラフに統合することで、よりクリーンで効率的になると考えています。 ワークフローを構成した後、ルーティング コードの記述を続けました。 ツール呼び出し処理コードは次のとおりです。 実装は、LangGraphエージェントというよりは、純粋なコードベースエージェントに近いようです。これは主に、WorkflowsがLangGraphのような条件付きエッジではなく、各ステップ内で条件付きルーティングロジックを維持することを選択しているためです(18行目から24行目はLangGraphでは条件付きエッジですが、現在はルーティングステップの一部になっています)。さらに、LangGraphのToolNodeオブジェクトは、tool_call_handlerメソッド内のほとんどのタスクを自動的に処理できます。 ルーティングステップの後、純粋なコードベースのエージェントのスキルマップと既存のスキルをワークフローに直接適用できます。これらのスキルはワークフローで一切変更を加えることなく使用できるため、作業が大幅に簡素化されます。 3.2 ワークフロー使用の課題課題1: 同期と非同期 オンラインエージェントの場合は非同期実行の方が適していますが、同期実行されているエージェントのデバッグの方が一般的に容易です。ワークフローは非同期操作用に設計されているため、同期実行に変換するのは非常に困難です。 当初は、単に「async」メソッドマーカーを削除し、関数名「achat_with_tools」を「chat_with_tools」に変更すれば済むと考えていました。しかし、Workflowクラス内のメソッドも非同期マーカーを使用しているため、同期実行を実現するためにこれらのメソッドを再定義する必要がありました。それでも最終的には非同期処理を選択しましたが、幸いなことにデバッグの難易度は上がりませんでした。 エージェントのアクションの連続的なビュー(画像は著者提供) 課題2: ピダンティック検証エラー LangGraphの問題と同様に、Pydanticの検証エラーがエージェントのスキルでも発生し、混乱を招きました。幸いにも、ワークフローはメンバー関数を適切に処理するため、今回はこれらの問題は比較的容易に解決できました。最終的には、エージェントのスキル用のLlamaIndex FunctionToolオブジェクトをより標準化された方法で作成する必要がありました。 FunctionTools をビルドするAgentFlow.initファイルからの抜粋 3.3 ワークフローの利点LangGraphと比べて、Workflowsを使ったエージェントの構築は私にとってはるかに簡単でした。これは主に、Workflowsには組み込み機能がなく、ルーティングロジックとツール操作コードを自分で書かなければならなかったためです。これにより、私のWorkflowエージェントは、純粋なコードベースのエージェントと非常に似たものになりました。 最大の違いはイベントの使い方にあります。エージェント内のステップ間を移動するために、2つのカスタムイベントを使用しています。 このイベント ベースのエミッタ/レシーバ アーキテクチャは、ツール呼び出しハンドラなどのエージェント内の特定のメソッドを直接呼び出す方法に代わるものです。 このアーキテクチャは、より複雑なステップ、非同期トリガー、および複数のイベントを生成する可能性があるシステムで、これらのステップをクリーンかつ効率的に管理するのに非常に役立ちます。 ワークフローのその他の利点としては、軽量であること、過度な構造上の制限がないこと (特定の LlamaIndex オブジェクトを使用する必要があることを除く)、イベント ベースのアーキテクチャなどが挙げられます。イベント ベースのアーキテクチャは、直接関数呼び出しの効果的な代替手段となり、特に複雑な非同期アプリケーション シナリオの処理に役立ちます。 04 これらの方法の比較これら 3 つの方法にはそれぞれ独自の利点があります。 フレームレスアプローチは実装が最も簡単です。すべての抽象化レイヤー(前述の例のSkillMapオブジェクトなど)は開発者によって定義されるため、異なる型やオブジェクトの管理は比較的簡単です。ただし、コードの可読性とユーザビリティは完全に開発者に依存します。エージェント構造に一定の制約を設けないと、エージェントの複雑さが増すにつれて管理が困難になる可能性があることが予想されます。 LangGraphはエージェントアーキテクチャを豊富にサポートしており、エージェントの定義を非常に明確にします。複数の開発者が共同で開発するエージェントの場合、このアーキテクチャはアーキテクチャ標準の統一に役立ちます。LangGraphは、エージェントアーキテクチャにあまり精通していない開発者にも役立ちます。しかし、これには代償が伴います。LangGraphが多くの作業を自動的に行ってくれるため、フレームワークを完全に理解していないと、かなり難しい作業になる可能性があります。コードは非常に簡潔になるかもしれませんが、デバッグ作業が増える可能性があります。 ワークフローはその中間に位置します。イベントベースのアーキテクチャは、一部のプロジェクトでは非常に価値があり、LlamaIndex型の使用要件が低いため、アプリケーションでフレームワークを最大限に活用しない開発者にとって、より大きな自由度を提供します。 著者が作成した画像 最終的に、重要な質問は、「アプリケーションを整理するためにすでに LlamaIndex または LangChain を使用していますか?」となるかもしれません。LangGraph と Workflows はどちらも、依存するフレームワークと緊密に統合されているため、各特定のエージェント フレームワークの追加の利点だけでは、切り替えを正当化するのに十分ではない可能性があります。 純粋なコードアプローチは常に魅力的な選択肢となるかもしれません。作成した抽象化を厳密に文書化し、実行できれば、外部フレームワークが障害にならないようにするのは容易です。 エージェントフレームワークを選択する際に考慮すべき5つの重要な問題もちろん、「具体的な状況によって異なります」という単純な答えでは決して満足のいくものではありません。次の3つの質問は、次のインテリジェントエージェントプロジェクトで使用するフレームワークの選択に役立つかもしれません。 あなたのプロジェクトはすでに LlamaIndex または LangChain と深く統合されていますか? もしそうなら、これら 2 つのオプションを優先することをお勧めします。 一般的なインテリジェント エージェント アーキテクチャに精通していますか? それとも、インテリジェント エージェント構造の構築方法を教えてもらいたいですか? 後者を好む場合は、Workflows が良い選択肢かもしれません。後者を強く好む場合は、LangGraph の方が適しているかもしれません。 構築しているインテリジェントエージェントの参考例はありますか? フレームワークの利点の一つは、各フレームワークに豊富なチュートリアルと参考例が用意されていることです。対照的に、純粋にコードだけでインテリジェントエージェントを構築する例は比較的少ないです。 著者が作成した画像 06 結論エージェントフレームワークの選択は、実稼働環境における生成型人工知能システムのパフォーマンスに影響を与える多くの決定事項の一つに過ぎません。強力なセキュリティ保証を確立し、大規模言語モデル(LLM)[4]を監視することが不可欠です。同時に、新しいエージェントフレームワーク、研究成果、モデルによって従来の技術が破壊されることに対しても、柔軟な姿勢を維持することが重要です。 読んでくれてありがとう! このブログを楽しんで、新しいことを学んでいただければ幸いです。 著者について アパルナ・ディナカラン Arize AIの共同創業者兼CPO。コーネル大学でコンピュータービジョンの博士号を取得し、Uberの機械学習、カリフォルニア大学バークレー校のAI研究にも携わった。 終わり 今週のインタラクティブコンテンツ🍻 ❓インテリジェントエージェントの開発に最も頻繁に使用するアプローチを教えてください。その理由は何ですか? 🔗記事内のリンク🔗 [1]https://foundationcapital.com/goodbye-aiops-welcome-agentsres-the-next-100b-opportunity/ [2]https://arxiv.org/html/2405.13966v1 [3]https://github.com/Arize-ai/phoenix/tree/main/examples/agent_framework_comparison [4]https://docs.arize.com/phoenix/tracing/llm-traces オリジナルリンク: https://towardsdatascience.com/choosing-between-llm-agent-frameworks-69019493b259 |
01 コードベースエージェント(インテリジェントエージェントフレームワークを使用しない)1.1 純粋なコードアーキテクチャ1.2 純粋なコードベースのインテリジェントエージェントの使用における課題1.3 純粋なコードベースのインテリジェントエージェントの利点02 ランゲージグラフ2.1 LangGraphアーキテクチャ2.2 LangGraphの使用上の課題2.3 LangGraphの利点2.4 学んだ教訓03 LlamaIndexワークフロー3.1 ワークフローアーキテクチャ3.2 ワークフロー使用の課題3.3 ワークフローの利点04 これらの方法の比較エージェントフレームワークを選択する際に考慮すべき5つの重要な問題06 結論 |