勉強会「【LangChainゆる勉強会#12】LangGraphの最新ドキュメントを全体的にざっと読む」を開催しました #StudyCo

ジェネラティブエージェンツの大嶋です。

運営している勉強会コミュニティStudyCoで「【LangChainゆる勉強会#12】LangGraphの最新ドキュメントを全体的にざっと読む」というイベントを開催しました。

studyco.connpass.com

アーカイブ動画はこちらです。

youtube.com

LangGraphは最近アップデートが活発で、ドキュメントも充実してきています。 LangGraphのドキュメントに一通り目を通す時間を作ろうと、この勉強会を開催しました。

今回LangGraphのドキュメントを読んでみて、「この機能はあまり知られていなそうだな」と感じたものを、3つほどピックアップしてこの記事で紹介します。

Send APIによる動的なエッジの構成

まず、Send APIについてです。

LangGraphでは基本的な使い方として、「add_conditional_edges」を使って、条件に応じてノードを選択するエッジを作成します。 しかし、単純にadd_conditional_edgesを使うだけでは、「実行時にノードの数を動的に変更したい」といったことはできません。

そのように、より動的にエッジを構成するために、LangGraphでは「Send API」が提供されています。 Send APIのコンセプトは以下のページで解説されています。

langchain-ai.github.io

上記のページでは、Send APIを使う一般的な例として、map-reduceが挙げられています。 map-reduceでは、mapの処理として「同じ処理を実行するノードを、データの数だけ用意して実行する」ということになり、これはまさに動的にエッジを構成する例です。

map-reduceの実装例は、次のページに掲載されています。

langchain-ai.github.io

ステートの共有

次に、ステートの共有についてです。

チャットボットなどのアプリケーションを提供するうえで、「スレッド内の会話履歴を記憶させたい」というのに加えて、「スレッドをまたいでユーザー単位で記憶を共有したい」といったケースが考えられます。 そのようなケースのサンプルコードが以下のページに掲載されています。

langchain-ai.github.io

上記のページのコードから、とくに重要な箇所を簡単に説明します。

まず、グラフのステートとして、「SharedValue」という、あるキーをもとにシェアする値を定義します。

from langgraph.managed.shared_value import SharedValue

class AgentState(MessagesState):
    info: Annotated[dict, SharedValue.on("user_id")]

実行時のconfigで、SharedValueで指定したキーに適当な値を設定します。

config = {"configurable": {"thread_id": "1", "user_id": "1"}}

for update in graph.stream({"messages": [{"role": "user", "content": "hi"}]}, config, stream_mode="updates"):
    print(update)

このようにSharedValueを使うことで、「スレッドをまたいでユーザー単位で記憶を共有する」という実装ができるということです。

NodeInterruptによる動的なブレークポイントの設定

最後に、NodeInterruptについてです。

LangGraphでは、「interrupt_before」という設定によって、あるノードに処理がきた際に、処理を中断することができます。

より動的に処理を中断する方法として「NodeInterrupt」が提供されています。 サンプルコードは次のページに掲載されています。

langchain-ai.github.io

こちらも、上記のページのコードから、とくに重要な箇所を簡単に説明します。

from langgraph.errors import NodeInterrupt

def step_2(state: State) -> State:
    if len(state['input']) > 5:
        raise NodeInterrupt(f"Received input that is longer than 5 characters: {state['input']}")
    
    print("---Step 2---")
    return state

簡単に言えば、NodeInterruptをraiseすると、動的にグラフの実行をinterruptできるということです。

ノードの遷移のタイミングで処理を中断したい場合は「interrupt_before」を使えば十分ですが、より動的な制御が必要な場合は「NodeInterrupt」を使えるということになります。

おわりに

以上、LangGraphのあまり知られていなそうな機能を3つ紹介しました。

今回の勉強会は「LangGraphの最新ドキュメントを全体的にざっと読む」というテーマだったため、1つ1つの内容は深堀りできませんでした。 開催後のアンケートでも、「このあたりを深堀りしてほしい」といった意見をいくつかいただいており、もう少し深堀りする会も開催したいと考えています。

LangChain / LangGraph、その他のテーマで引き続き勉強会を開催していきます。 LangGraphの話でもLangGraph以外の話でも、もしも「こんな話が聞きたい」というテーマがあれば、ぜひお声がけください!