LangGraphの無限の可能性を発見

LangGraphの無限の可能性を発見

著者 | 崔昊

レビュー | Chonglou

まとめ

この記事では、LangChain をベースにした新しいテクノロジーである LangGraph を紹介します。これは循環グラフを通じて大規模なモデルと外部ツールを調整し、複雑なタスクを解決します。まず、単純なタスクを処理するための LangChain の DAG モデルと、循環グラフを使用して複雑なタスクを処理する LangGraph の原理を紹介します。次に、LangGraph の 3 つのコア コンポーネントである StateGraph、ノード、エッジについて詳しく説明します。最後に、エージェントの作成、グラフの状態、ノード、エッジの定義、ワークフローの実行など、LangGraph を使用して 2024 年の春節期間中の北京の観光状況を照会する方法を示す例を使用します。

導入

今日のテクノロジー分野では、大規模言語モデル (LLM) が徐々に私たちの日常生活や仕事における強力なアシスタントになってきています。ライティング支援、プログラミングのデバッグ、簡単な質問応答システムなど、LLM は迅速かつ正確なサービスを提供できます。しかし、より複雑なタスクに直面した場合、LLM ではそのタスクに対処できない可能性があります。これらの課題に対処するために、より複雑なタスクやインタラクションを処理できる AI エージェントと組み合わせた新しいテクノロジーである LangGraph を導入します。

LangGraph は、LangChain 上に構築され、そのエコシステムと完全に互換性のある新しいライブラリです。アプリケーション シナリオにおける複雑な問題を解決するために、大規模なモデルと外部ツールを調整するためのサイクル グラフ メソッドを紹介します。

この記事では、2024 年の春節期間中の北京の観光状況を尋ねるという簡単な例を使用して、独自の LangGraph アプリケーションを作成する方法を説明します。 LangGraph の概念とコンポーネントを理解し、実際のシナリオに適用する方法を段階的に説明します。この例を通して、LangGraph がどのように作業効率を向上させ、複雑な問題を解決できるかを直感的に理解できるようになります。

LangGraph を使用する理由は何ですか?

LangChain を使用したことがある友人は、LangChain の最大のメリットは、有向非巡回グラフ (DAG) に似た、通常は線形のカスタム チェーンを簡単に構築できることであることを知っています。 DAG は、タスクが特定の順序で実行され、各タスクには 1 つの出力と 1 つの後続タスクのみがあり、ループのない線形プロセスを形成するデータ構造です。たとえば、ベクター ライブラリからコンテンツを検索する場合、最初にプロンプ​​ト ワードを入力し、次にベクター比較で検索し、結果を返します。このプロセスは典型的な DAG であり、各ステップは厳密に順番に実行されます。

有向非巡回グラフ (DAG) は、データ オーケストレーションおよびワークフロー管理システムの基本的な概念です。これは、依存関係と関連性を持つタスクのセットを表し、タスクを実行する順序を示します。 DAG では、タスクはノードと見なされ、ノード間の有向エッジはノード間の依存関係を表し、先行タスクが正常に完了した後にのみタスクが実行されるようにします。

たとえば、基本的な有向非巡回グラフでは、タスク A、B、C、D を定義し、それらの実行順序と依存関係を明示的に示すことができます。この構造は、どのタスクを他のタスクの前に実行する必要があるかを示すだけでなく、明日から 5 分ごとに DAG を実行する、または 2024 年 1 月 1 日から 1 日に 1 回 DAG を実行するなどのスケジュール パラメータも指定します。

DAG の主な焦点は、タスクの内部動作メカニズムではなく、実行順序、再試行ロジック、タイムアウト、その他の運用上の問題など、タスクの実行方法です。この抽象化により、管理と監視が容易な複雑なワークフローを簡単に作成できます。

ただし、すべてのタスクがそれほど簡単というわけではありません。最初の検索で目的のものが見つからない場合など、複雑なタスクに遭遇した場合は、2 回目または 3 回目の検索を実行したり、ネットワーク検索を呼び出して完了したりする必要がある場合もあります。この場合、順次実行されるタスク (DAG) では明らかに要件を満たすことができません。この時点で、依頼者と検索者は複数回のコミュニケーションを行う必要があります。依頼者は、フィードバックに基づいて検索戦略を調整するよう検索者に依頼する場合があります。複数回のコミュニケーションサイクルを通じてのみ、最終的な答えに徐々に近づくことができます。

この場合、必要なのは DAG ではなく、最終的な答えを確認するために複数の参加者間で行われる複数回の会話とやり取りを記述できるサイクル グラフです。このループ図では、システムがフィードバックに基づいて適応および反復できるため、より曖昧で複雑なユースケースを処理できます。そして、サイクルグラフにおける動作モードはインテリジェントエージェント、つまりAIである。 エージェント。

AI エージェント、または人工知能エージェントは、強化学習理論に基づいて設計されたシステムです。下の図に示すように、強化学習は、エージェントが環境のさまざまな状態に基づいてアクションを実行し、最大の報酬を獲得できるようにする機械学習手法です。この学習プロセスでは、エージェントが環境と常に対話し、試行錯誤を通じてどのアクション戦略が最良の結果につながるかを学習します。

たとえば、WeChat の Jump Jump ゲームでは、エージェントはプラットフォームにジャンプするたびに報酬を受け取り、プラットフォームにジャンプできなかった場合はペナルティを受けます。この報酬と罰のメカニズムを通じて、エージェントはジャンプの力と方向を調整してより高いスコアを獲得する方法を学習できます。このプロセスは強化学習の単純な表現であり、インテリジェント エージェントは継続的なインタラクションを通じてアクション戦略を最適化します。

LangGraph では、AI エージェントは同様に動作します。 LLM (大規模言語モデル) は、実行するアクションとユーザーに提供する応答を決定し、それらのアクションを実行して最初のステップに戻るために使用されます。このプロセスは、最終的な応答が生成されるまで繰り返されます。これは、LangChain のコア AgentExecutor の動作サイクルの原則です。

しかし、実際のアプリケーションでは、インテリジェントエージェントに対するさらなる制御が必要であることがわかりました。たとえば、エージェントが常に特定のツールを最初に呼び出すようにしたり、ツールの呼び出し方法をより細かく制御したり、エージェントの状態に応じて異なるプロンプトを使用したりしたい場合があります。これらの問題を解決するために、LangGraph は「ステート マシン」の概念を提案しました。この方法では、グラフに対応するステート マシンを作成することで、インテリジェント エージェントのアクション フローをより適切に制御し、複雑なタスクをより柔軟かつ効率的に処理できるようになります。

LangGraphのコンポーネント

LangGraph が「ステート マシン」を適用して AI エージェント機能を実装する方法を紹介する際には、理解しておく必要のある重要な概念がいくつかあります。これらは LangGraph の重要なコンポーネントでもあります。

ステートグラフ

まず、StateGraph のコアコンセプトを理解する必要があります。 StateGraph は、グラフ全体の構造を表す役割を担うクラスです。実行中に更新される中心的な状態オブジェクトを表す状態定義を渡すことによって、このクラスを初期化します。この状態オブジェクトはグラフ内のノードによって更新され、ノードはキーと値のペアの形式で状態プロパティに対する操作を返します。

状態オブジェクトのプロパティは、次の 2 つの方法で更新できます。

1. 上書き更新: 属性を新しい値に置き換える必要がある場合は、ノードに新しい値を返すようにすることができます。

2. 増分更新: プロパティがアクション (または同様の操作) のリストである場合、元のリストに新しいアクションを追加できます。

状態定義を作成するときは、プロパティを上書きするか増分するかのいずれかで更新する方法を指定する必要があります。

StateGraph の概念が理解しにくい場合は、旅行を計画していると想像してください。目的地の決定、フライトの予約、ホテルの予約など、旅行の基本を設定します。この情報は、計画の進行に応じて継続的に更新される中央状態オブジェクトのように機能します。たとえば、旅程に新しいアクティビティを追加したり、予算を変更したりすることができます。これらの更新はグラフ内のノードのようなもので、旅行計画の状態オブジェクトに対して動作します。

LangGraph では、StateGraph クラスはそのような旅行計画であり、ノードは目的地の決定、フライトの予約、ホテルの予約など、旅行計画のさまざまなステップのようなものです。各ステップでは、旅行計画が更新され、古い計画が完全に置き換えられるか、既存の計画に新しい情報が追加されます。

ノード

StateGraphについて説明した後、グラフのノード部分に焦点を当てましょう。 StateGraph を作成したら、それにノードを追加する必要があります。ノードの追加は、`graph.add_node(name, value)` 構文で行います。

`name` パラメータは、エッジを追加するときにこのノードを参照するために使用される文字列です。 `value` パラメータは、ノードが呼び出されたときに実行される関数または LCEL (LangChain Expression Language) 実行可能インスタンスのいずれかである必要があります。これらは、State オブジェクトと同じ形式の辞書を入力として受け入れることができ、実行後に辞書を出力します。辞書内のキーは、State オブジェクトで更新される属性です。簡単に言えば、ノードの役割は「実行」することであり、実行後は StateGraph の状態が更新されます。

次に、上記の旅行計画の例では、ノードはフライトの予約やホテルの予約など、旅行計画で完了する必要があるタスクのようなものです。ノードは旅行の旅程 (State オブジェクト) を入力として受け取り、更新されたタスク状態 (完了したホテル予約など) を出力します。

つまり、複雑なタスクを完了するために、StateGraph に多数のノードを追加します。各ノードはタスクを表し、その実行結果は StateGraph の状態に影響します。これらのノードはエッジを介して相互に接続され、有向非巡回グラフ (DAG) を形成し、タスクの正しい実行順序を保証します。

エッジ

StateGraph について話した後は、Edge について言及する必要があります。 LangGraph では、エッジはノードを接続し、StateGraph 内のノードの実行順序を定義する重要な部分です。ノードを追加した後、エッジを追加してグラフ全体を構築できます。エッジにはいくつかの種類があります。

  • 開始エッジ: このエッジはグラフの始まりを決定します。たとえば、旅行計画では、開始エッジによって目的地が決まります。目的地が決まったら、旅行計画の実行を開始できます。
  • 通常のエッジ: これらのエッジは、常に別のノードの後に​​呼び出されるノードを表します。旅行計画では、共通エッジはタスクが実行される順序を決定するようなものです。たとえば、適切なフライトを見つけた後、ホテルを予約することにするかもしれません。この順序により、タスクが秩序正しく実行されることが保証されます。
  • 条件付きエッジ: 関数 (通常は LLM によって提供される) を使用して、最初に呼び出すノードを決定します。旅行計画において、条件付きエッジは、好みや天候条件に基づいて次の行動を決定するようなものです。たとえば、適切なフライトがないことがわかった場合は、ホテルの予約を延期して、代わりに電車のチケットを探すことを選択するかもしれません。条件付きエッジは柔軟性を提供し、システムがさまざまな状況に基づいて実行順序を調整できるようにします。

LangGraph では、エッジはノードを接続し、グラフ内のノードの実行順序を定義する重要な部分です。エッジは、グラフ内のタスクが事前に決められた順序で実行されることを保証する、ノードへのコントロールおよびリンクとして考えることができます。

LangGraph では、エッジはノード間の依存関係と実行順序を定義します。開始エッジはグラフの開始を決定し、通常エッジはタスクの正しい実行順序を保証し、条件エッジは特定の条件に基づいて次の操作を決定します。

LangGraph の活用

LangGraph の設計原則と基本コンポーネントについて簡単に理解できたので、実際に LangGraph を使用して北京2024 年春節の観光情報を照会する方法を例で見てみましょう。ビッグモデルに精通している友人は、ビッグモデルの欠点はリアルタイムの情報について何も知らないことだということを知っているかもしれません。新しい知識を吸収したい場合は、新しいデータセットでトレーニングする必要があります。そこで、LangGraphを使用してネットワーク検索機能を呼び出し、リアルタイムの情報を取得します。

LangChainプロキシを作成する

LangChain では、エージェントは大規模なモデルを推論エンジンとして使用して、実行するアクションのシーケンスを決定します。これは、チェーンにハードコードされた一連のアクションとは異なります。端的に言えば彼はこの任務を遂行する上での「キーパーソン」です。彼は「 2024年春節の北京の観光状況を調査する」という任務の全体責任者であり、最終的にユーザーに結果を提供します。

 # 从langchain包中导入hub对象,该对象用于内容管理和检索from langchain import hub # 从langchain包中导入创建OpenAI函数代理的函数from langchain.agents import create_openai_functions_agent # 从langchain_openai包中导入ChatOpenAI类,用于与OpenAI聊天模型交互from langchain_openai.chat_models import ChatOpenAI # 从langchain_community包中导入TavilySearchResults类,提供搜索功能from langchain_community.tools.tavily_search import TavilySearchResults # 创建一个工具列表,其中包含TavilySearchResults实例,限制最大搜索结果为1 tools = [TavilySearchResults(max_results=1)] # 通过hub对象的pull方法检索语句提示,langchain hub 维护了很多prompt,这些prompt 是针对不同应用场景而创建的# 作为用户,你也可以在hub中上传你构建的prompt prompt = hub.pull("hwchase17/openai-functions-agent") # 打印获取的提示print(prompt) # 初始化一个Large Language Model(LLM)聊天实例,使用GPT-3.5 Turbo模型,并启用流模式和自定义API基础URL llm = ChatOpenAI(model="gpt-3.5-turbo-1106", streaming=True) # 使用LLM,工具和提示信息创建OpenAI函数代理,形成一个可运行的代理agent_runnable = create_openai_functions_agent(llm, tools, prompt)

上記のコードの説明は次のとおりです。

1. `from langchain import hub` - `langchain` パッケージから `hub` オブジェクトをインポートします。langchain hub は、さまざまなアプリケーション シナリオ用に作成された多数のプロンプトを維持しますユーザーは、作成したプロンプトをハブにアップロードすることもできます

2. `from langchain.agents import create_openai_functions_agent` - OpenAI 関数に基づいてエージェントを作成するために使用される `langchain` パッケージから `create_openai_functions_agent` 関数をインポートします。

3. `from langchain_openai.chat_models import ChatOpenAI` – OpenAI チャット モデルと対話するために使用される `langchain_openai` パッケージから `ChatOpenAI` クラスをインポートします。

4. `from langchain_community.tools.tavily_search import TavilySearchResults` - 検索結果機能を提供するために使用される `langchain_community` パッケージから `TavilySearchResults` クラスをインポートします。

5. `tools = [TavilySearchResults(max_results=1)]` - 検索結果の数を最大 1 に制限する `TavilySearchResults` インスタンスを含むリスト `tools` を作成します。ここでは、Tavily のツールを使用してインターネット検索を実装する必要があります。

6. `prompt = hub.pull("hwchase17/openai-functions-agent")` - `hub` オブジェクトの `pull` メソッドを通じて `hwchase17/openai-functions-agent` という名前のプロンプトを取得します。

7. `print(prompt)` - 取得したプロンプトを出力します。

8. `llm = ChatOpenAI(model="gpt-3.5-turbo-1106", streaming=True)` - Large Language Model (LLM) チャットインスタンスを初期化し、`gpt-3.5-turbo-1106` モデルの使用を指定し、ストリーミングモードを有効にします。

9. `agent_runnable = create_openai_functions_agent(llm, tools, prompt)` – LLM インスタンス、ツールのリスト、およびプロンプトを指定して実行できる OpenAI 関数エージェントを作成します。

このコードの目的は、OpenAI Chat モデルと対話するための環境を初期化して構成することです。まず、コンテンツ管理用の `hub` オブジェクト、OpenAI 関数エージェントを作成するための `create_openai_functions_agent` 関数、OpenAI チャット モデルと対話するための `ChatOpenAI` クラス、検索機能を提供する `TavilySearchResults` クラスなど、必要なモジュールとクラスをインポートします。次に、コードはツール リストを作成し、langchain ハブから定義済みのプロンプトを取得します。

ここでプロンプトを表示します 印刷結果は以下のようになります。

このプロンプトはLangChainから来ています さまざまな大規模モデルプロンプトを検出して共有するために使用されるハブここで使用するのは、他の人が定義したプロンプト ワード テンプレートです。エージェント操作の生成に使用される入力変数とメッセージを定義します。表示される「プロンプト」の内容を一つずつ説明します。

1. `input_variables=['agent_scratchpad', 'input']` - これは、`agent_scratchpad` と `input` を含む入力変数リストを指定します。

2. `input_types` - これは、次のキーとそれに対応する型を含むさまざまな入力タイプを定義する辞書です。

  • chat_history: チャット履歴を記述するタイプ。さまざまなメッセージ タイプを含むリストです。これらのメッセージ タイプには、AI メッセージ、人間が送信したメッセージ、チャット メッセージ、システム メッセージ、関数メッセージ、ツール メッセージが含まれる場合があります。
  • `agent_scratchpad`: エージェントの「スクラッチパッド」を表します。これは、プロセス中に情報を記録するために使用されます。そのタイプは `chat_history` と同じで、複数の可能なメッセージ タイプが含まれます。

3. `messages` - これはいくつかの異なるタイプのテンプレートを含むリストです:

  • `SystemMessagePromptTemplate` - システム メッセージを定義するための `SystemMessage` タイプのテンプレートが含まれています。ここで、「あなたは役に立つアシスタントです」は、エージェントの役割と期待される動作を示すリマインダーです。
  • `MessagesPlaceholder` - `chat_history` 変数に関連付けられたプレースホルダーであり、オプションです。つまり、入力時にチャット履歴を必ずしも提供する必要はありません。
  • `HumanMessagePromptTemplate` - ユーザーからの入力を定義するために使用される `HumanMessage` タイプのテンプレートが含まれています。ここで、テンプレート `{input}` は、ユーザーが実際に入力したテキストに置き換えられます。
  • `MessagesPlaceholder` - `agent_scratchpad` 変数に関連付けられた別のプレースホルダー。

エージェントがメッセージと対話を処理する方法を定義します。エージェントを使用してタスクを実行する場合、このテンプレートを使用して、事前設定された形式に準拠した入力が生成され、エージェントの正しい応答とアクションが容易になります。

langchain hub.pull("hwchase17/openai-functions-agent") を使用してこのプロンプト テンプレートを langchain ハブからプルすると、このテンプレートを使用して、定義された入力タイプとメッセージ形式を理解して処理し、効率的で便利なアシスタントとして機能するようにエージェントを構成できます。ユーザーは、ニーズに応じて新しいプロンプトを作成し、ハブにアップロードしてさまざまなシナリオに適応することもできます。

グラフ状態を作成する

エージェントを作成した後、次のステップはグラフの状態を定義することです。従来の LangChain エージェントの状態には、次のプロパティがあります。

  • 入力: これは、入力として渡される、ユーザーからの主なリクエストを表す入力文字列です。
  • チャット履歴: これは以前の会話メッセージであり、入力としても渡されます。
  • 中間ステップ: エージェントが実行するアクションと対応する観察。このリストはエージェントが反復するたびに更新されます。
  • エージェントの結果: エージェントの応答。AgentAction または AgentFinish になります。これが AgentFinish の場合、AgentExecutor は終了する必要があり、それ以外の場合は要求されたツールが呼び出される必要があります。

コードは次のとおりです。

 from typing import TypedDict, Annotated, List, Union from langchain_core.agents import AgentAction, AgentFinish from langchain_core.messages import BaseMessage import operator # 定义一个类型字典,用于表示代理的状态信息class AgentState(TypedDict): # 输入字符串input: str # 对话中之前消息的列表chat_history: list[BaseMessage] # 代理调用产生的结果,可能为None表示开始时没有结果agent_outcome: Union[AgentAction, AgentFinish, None] # 动作和对应观察结果的列表,使用operator.add注释说明这些状态应该被添加到现有值上intermediate_steps: Annotated[list[tuple[AgentAction, str]], operator.add]

上記のコードでは以下の点を説明する必要があります。

  • agent_outcome: Union[AgentAction, AgentFinish, None]: このフィールドには、特定の通話後のエージェントの結果状態が格納されます。つまり、 AgentAction オブジェクト (エージェントがアクションを実行したことを示す) AgentFinish オブジェクト (エージェントがタスクを完了したことを示す)、および Noneオブジェクト (エージェントがまだタスクの処理を開始していないか、返す結果がないことを示す) に注意を払う必要があります。
  • 中間ステップ: Annotated[list[tuple[AgentAction, str]], operator.add]: これは、Annotated と operator.add で注釈が付けられたアクションと観測のタプルのリストです。これは、intermediate_steps フィールドを更新するときに、既存のリストを上書きするのではなく、新しいアクションと観察をリストに追加する必要があることを示しています。 operator.add は、このフィールドの更新操作が加算的な性質を持つことを示すために使用されます。

ノードの定義

グラフ状態を作成する方法を紹介した後、次に注目すべきはノードを定義する方法です。 LangGraph では、ノードは関数または実行可能なエンティティのいずれかになります。私たちのタスクでは、2 つのメイン ノードを定義する必要があります。

  • エージェント ノード: 実行するアクションを決定する責任を負います。
  • ツールの機能を呼び出します。エージェントがアクションを実行することを決定した場合、このノードはそのアクションを実行します。ここでの行動は、 Tavilyを通じてオンライン検索を行い、「北京の2024年春節の観光状況を取得するものと理解できます

ノードを定義することに加えて、いくつかのエッジも定義する必要があります。これらのエッジの一部は条件付きである可能性があります。エッジは条件付きです。これは、ノードの出力に応じて複数の異なるパスが実行される可能性があるためです。ノードを実行するときに、特定のパスはビッグモデルによって決定される必要があります。

条件付きエッジ: プロキシが呼び出された後に何を実行するかを決定します。エージェントがアクションを実行する必要があるときはツールを呼び出す必要があります。エージェントがタスクを完了したと判断した場合は終了する必要があります。

通常のエッジ: ツールを呼び出した後は、常にエージェントに戻って次に何を行うかを決定する必要があります。

ここで、ノードと、どの条件エッジを取るかを決定する関数を定義しましょう。この関数は、エージェント ノードの出力に基づいて、ツールを呼び出すかプロセスを終了するかを決定します。このようにして、さまざまな状況に応じて適切なパスを選択できる柔軟なグラフを構築できます。

 # 导入AgentFinish类,用于标识代理执行完成状态from langchain_core.agents import AgentFinish # 导入ToolExecutor类,用于执行工具和处理代理动作from langgraph.prebuilt.tool_executor import ToolExecutor # 实例化ToolExecutor,它是一个辅助类,能够基于代理动作调用相应的工具并返回结果tool_executor = ToolExecutor(tools) # 定义代理执行逻辑的函数def run_agent(data): # 调用代理的可执行对象,传入数据data,执行代理逻辑并得到结果agent_outcome = agent_runnable.invoke(data) # 将代理的执行结果封装成字典形式返回return {"agent_outcome": agent_outcome} # 定义执行工具的函数def execute_tools(data): # 从数据中获取最新的代理执行结果(agent_outcome) agent_action = data["agent_outcome"] # 调用工具执行器,并基于代理动作执行工具,得到输出结果output = tool_executor.invoke(agent_action) # 将执行的工具及其输出结果作为中间步骤打包成元组,然后封装成字典格式返回return {"intermediate_steps": [(agent_action, str(output))]} # 定义逻辑函数,用于根据数据决定流程是否继续或结束def should_continue(data): # 如果代理的执行结果是AgentFinish,表示结果满意,代表流程结束if isinstance(data["agent_outcome"], AgentFinish): # 返回字符串'end',在设置流程图时用于标识流程的终点return "end" # 如果代理的执行结果不是AgentFinish类的实例,则代表代理流程应继续执行else: # 返回字符串'continue',在设置流程图时用于标识流程的继续点return "continue"

上記のコードからわかるように、3 つの関数が定義されています。

  • run_agent : データを受信して​​エージェントを実行するために使用されます。
  • execute_tools : データを受信し、特定の操作を実行します。この例では、検索エンジンを通じて2024 年春節の北京観光に関連する情報を検索するために使用します。同時に、実行結果middle_stepsを通じて記録されます。実際の職場環境では、エージェントは どちらも命令を出す側であり実際の作業を行うのはツールです。毎回ツール 作業(この場合はウェブ検索)が完了すると、情報が返されます。このとき、エージェントは返された情報を判断します。満足できない場合、ツールは「作業」を続けます。この状況に基づいて、毎回ツール 作業が完了すると、アーカイブまたは参照用に結果がmiddle_stepsに記録されます。
  • should_continue : ワークフローを続行するかどうかを決定するために使用されます。結果データ["agent_outcome"]が取得された場合は作業が終了し、そうでない場合は結果が取得されるまで作業が続行されます。

ワークフローの定義(グラフとエッジ)

この時点で、エージェント、グラフの状態、ノードなどに関する情報が得られます。上記の情報を結び付けるためには、状態ベースのワークフローを構築する必要があります。ワークフローには条件付きノード遷移と線形ノード遷移が含まれており、特定の条件に基づいてプログラム内で次に実行する操作を決定するために使用されます。このプロセスは、さまざまな状態またはノードが特定のロジックに従って遷移できるイベントベースのシステムをシミュレートします。コードは次のとおりです。

 from langgraph.graph import END, StateGraph #通过stategraph 初始化工作流workflow = StateGraph(AgentState) # 定义两个节点,在实际场景中agent下命令,action完成任务返回结果。 # 结果如果不满意,agent 会继续要action完成新任务。 # 看上去它们的交互式不断循环切换的workflow.add_node("agent", run_agent) # 添加节点"agent",其运行函数为run_agent workflow.add_node("action", execute_tools) # 添加节点"action",其运行函数为execute_tools # 设置入口节点为`agent` # 这意味着首先调用的节点是`agent` workflow.set_entry_point("agent") # 接下来添加有条件的边workflow.add_conditional_edges( # 定义起始节点,这里使用`agent` "agent", # 判断是否继续的函数节点,用于决定下一个节点是哪个的函数should_continue, # 定义映射字典# 键为字符串,值为其他节点# END 是结束节点# 调用`should_continue`后,输出将根据这个映射找到匹配的键# 根据匹配结果,接下来会调用相应的节点{ # 如果是`continue`,则调用工具节点`action` "continue": "action", # 否则结束流程"end": END, }, ) # 添加普通边从`action`到`agent` # 这意味着在`action`被调用后,下一个调用的节点是`agent` workflow.add_edge("action", "agent") # 对工作流进行编译# 编译成LangChain 可运行对象# 可以这个对象app = workflow.compile()

コードはかなり長いので、次のように分解して説明します。

  1. ワークフローを定義する: StateGraph を使用して、workflow という新しいワークフロー インスタンスを作成します。このワークフローは、AgentState という状態に基づいています。
  2. ノードの追加: 2 つのノード( 「エージェント」と「アクション」 )がワークフローに追加され、それぞれの処理関数 run_agent と execute_tools に関連付けられます。
  3. エントリ ポイントの設定: 「agent」はワークフローのエントリ ポイントとして設定されます。つまり、ワークフローの実行が開始されたときに最初に呼び出されるノードになります。
  4. 条件付きエッジの追加: add_conditional_edges メソッドを使用して、「エージェント」ノードから始まるエッジに条件が追加されます
  5. should_continue 関数を使用して条件を評価し、戻り値に基づいて次に実行するノードを決定します。
  6. should_continue が「continue」を返す場合、プロセスは「action」ノードに移動します。「end」を返す場合、ワークフローは終了します。
  7. 通常のエッジの追加: add_edge メソッドを通じて、「アクション」から「エージェント」への一方向エッジが追加されます。このエッジは、「アクション」ノードが実行された後、次のステップとして「エージェント」ノードに戻って実行を続行することを表します。
  8. ワークフローをコンパイルする:最後に、compile メソッドを呼び出すことで、以前に定義したワークフローが実行可能なオブジェクト アプリにコンパイルされます。

このコードはワークフローを定義し、ノードを追加し、エッジを設計します。次の図を使用してその原理を理解しましょう。エージェントは、ワークフロー全体が入るノードであり、一番左にあります。エージェントとアクションは共通のエッジを形成し、理解しやすいです。エージェントは検索タスクを開始し、アクションはタスクを完了します。次に、エージェント should_continue関数と同様に、条件を設定することで条件エッジが作成されます。 should_continue関数自体はノードではなく、判定条件です。関数の内容から、アクションが結果を取得した場合はワークフローが終了し (End)、そうでない場合は検索タスクが続行される (continue) ことがわかります。わかりやすくするために、ダイヤモンドで表現しています。Action が実行された後、should_continue によって判断され正しいブランチが選択されます。続行を選択した場合、ワークフロー全体がループを形成することを意味します。アクションの作業が完了できない場合、つまりエージェントを満足できない場合は、実行回数が超過するまで検索作業を繰り返す必要があり、その後終了します。

検索タスクを実行する

以上の操作により、ワークフローが作成され、実行できるようになります。上記のコード:

 inputs = {"input": "2024年春节北京的旅游情况如何", "chat_history": []} for s in app.stream(inputs): print(list(s.values())[0]) print("----")

2024年の春節期間中の北京の観光状況はどうなっているか?」という質問をします。ワークフローインスタンスによる出力結果を次の図に示します。

最初のエージェント_outcome 、明らかにエージェントがコマンドを発行すると、 tavily 検索ツールが動作を開始します。

次はタビリー 検索ツールは、関連情報が取得された Web サイトのアドレスなど、検索の中間ステップを記録します。このとき、2 番目のエージェント_outcomeの内容はAgentFinish としてマークされています。これは、エージェントが結果に満足し、タスクを完了できることを意味します。同時に、検索の最終結果が示され、これは私たちの期待と一致しています。

要約する

LangGraph テクノロジーは、複雑なタスクの処理において明らかな利点があります。円形グラフを使用することで、大規模なモデルと外部ツールを連携させ、複数回の対話と調整を実現し、最終的な答えにより近づくことができます。この技術は幅広い応用が期待でき、作業効率や問題解決能力を大幅に向上させることができます。ただし、Langgraphアプリケーションを作成するには、特定の技術的なしきい値も必要です。将来、Langgraphは複雑なタスクを処理する重要な技術的手段になると予想されています。

著者について

51CTO コミュニティ エディター兼シニア アーキテクトの Cui Hao 氏は、ソフトウェア開発とアーキテクチャで 18 年の経験があり、分散アーキテクチャでは 10 年の経験があります。

<<:  Kubernetes デバッグの究極の武器: K8sGPT

>>:  高性能 LLM 推論フレームワークの設計と実装

ブログ    
ブログ    
ブログ    

推薦する

Metaはオープンソースのビッグモデルを緩和し、開発者が商用利用で利益を得られるよう検討していると報じられている。

6月16日、MetaのCEOマーク・ザッカーバーグ氏とその代理人は、Metaが開発中の新しい人工知...

2020 年の優れた機械学習プロジェクト 23 件 (ソース コード付き)

[[336522]]ビッグデータダイジェスト制作編集者: ルナ教科書で習ったことと実際の業務に乖離...

コンピューティングパワーのコストが急激に上昇したため、AIスタートアップがGoogleやMicrosoftなどの大手に挑戦することが難しくなった。

2月20日のニュースによると、コンピューティングコストが急騰しているため、人工知能業界の新興企業は...

自動運転車は交通事故の3分の1しか解決できない、と研究が示す

自動運転車の主な目標、少なくともこの技術の支持者が推進している目標は、運転手や乗客の利便性を高めるこ...

AIがモノのインターネットをどう変えるのか

AI は、ネットワークとデバイスが過去の決定から学習し、将来のアクティビティを予測し、パフォーマン...

AI の将来とそれがビジネスに与える意味は何でしょうか?

10 年以内に、人々は複雑なデジタル環境において人工知能 (AI) にますます依存するようになるで...

ハードウェアクラッキングに耐えられるハッシュアルゴリズムにはどのようなものがありますか?

序文ブルートフォース クラッキング ツール hashcat を使用したことがある人なら誰でも、このソ...

...

...

...

空中で疫病と戦うドローン

新型コロナウイルス肺炎の流行が始まって以来、多くのハイテク技術がこの疫病との戦いに後方支援を提供して...

ディープラーニングの「記憶喪失」に応えて、科学者たちは類似性に基づく重み付けインターリーブ学習を提案し、PNASに掲載された。

人間とは異なり、人工ニューラル ネットワークは新しいことを学習するときに以前に学習した情報をすぐに忘...

HiLM-D: 自動運転のためのマルチモーダル大規模言語モデル

この記事は、Heart of Autonomous Driving の公開アカウントから許可を得て転...

2020 年の機械学習向け Python ライブラリ トップ 6!

[[328842]] 【51CTO.com クイック翻訳】世の中にはさまざまな種類の Python...