「AIエージェントキャッチアップ #16 - Open Canvas (LangChain)」を開催しました

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

「AIエージェントキャッチアップ #16 - Open Canvas (LangChain)」という勉強会を開催しました。

generative-agents.connpass.com

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

youtube.com

Open Canvas

今回は、OpenAIの「Canvas」にインスパイアされたLangChainの「Open Canvas」について、ソースコードを読んだり動かしたりしてみました。

Open CanvasのGitHubリポジトリはこちらです。

github.com

今回のポイント

Open Canvasの概要

Open Canvasは、ChatGPTの「Canvas」のオープンソース版という立ち位置です。

アシスタントと対話するチャット欄の右側に、ソースコードやマークダウンを編集できる「キャンバス」があり、LLMが生成したソースコードやマークダウンのテキストを人間も編集しつつLLMにも編集させることができます。

Open Canvasは https://opencanvas.langchain.com/ にアクセスして試すこともできれば、手元で起動することもできます。

手元で動かす際は、SupabaseやLangGraph Serverのセットアップが必要になります。

エージェントの概要

Open CanvasのGitHubリポジトリのlanggraph.jsonには以下のように記述されています。

{
  "node_version": "20",
  "dockerfile_lines": [],
  "dependencies": [
    "."
  ],
  "graphs": {
    "agent": "./src/agent/open-canvas/index.ts:graph",
    "reflection": "./src/agent/reflection/index.ts:graph",
    "thread_title": "./src/agent/thread-title/index.ts:graph"
  },
  "env": ".env"
}

この設定から、LangGraph Serverで「agent」「reflection」「thread_title」の3つのグラフが動いていることが分かります。

「agent」は、Open Canvasのチャット欄でやりとりするアシスタントの実装です。 「thread_title」は、スレッドのタイトルを生成する機能です。

「reflection」は面白そうだったので、少し丁寧に見ていきました。

リフレクション機能

実は、Open Canvasにはリフレクション機能があります。

ユーザーとアシスタントの対話が停止して30秒ほど経つと、過去のやり取りをもとにリフレクションが実行される、というものです。 リフレクションの結果は、以後同じアシスタントとやり取りする際のプロンプトに含まれます。

以下の画像はリフレクションの結果の例です。

リフレクション機能を呼び出している箇所

「対話が停止して30秒ほど経つと過去のやり取りをもとにリフレクションが実行される」という機能がどのように実装されているか気になったので、ソースコードを見ていきました。

すると、以下の箇所で「reflection」のグラフが呼び出されていることが分かりました。

    :
export const reflectNode = async (
  state: typeof OpenCanvasGraphAnnotation.State,
  config: LangGraphRunnableConfig
) => {
  const langGraphClient = new Client({
    apiUrl: `http://localhost:${process.env.PORT}`,
    defaultHeaders: {
      "X-API-KEY": process.env.LANGCHAIN_API_KEY,
    },
  });
    :
  await langGraphClient.runs.create(
      :
    newThread.thread_id,
      :
    "reflection",
    {
      input: reflectionInput,
      config: reflectionConfig,
      :
      multitaskStrategy: "enqueue",
      :
      afterSeconds: 15,
    }
  );
    :

https://github.com/langchain-ai/open-canvas/blob/4c826cf0aaa18d4c8f6113b82843bf4d9257f25e/src/agent/open-canvas/nodes/reflect.ts

これは、チャット欄で動作する「agent」のreflectNodeのコードです。 「agent」の処理の中で、別途LangGraph Serverの「reflection」グラフを呼び出しているということです。

※LangGraphには他のグラフを呼び出す「RemoteGraph」や「Subgraph」という機能もありますが、ここでは単にLangGraph ServerのClientを使用して呼び出しています

LangGraph Serverの活用

上記の「reflection」グラフの呼び出しは、次のように設定されています。

  • バックグラウンドで(非同期に)実行するAPIを使っている
  • multitaskStrategy: "enqueue"という設定により、複数回呼び出された場合に最後の呼び出しのみ実行されるようにしている
  • afterSeconds: 15という設定により、15秒経過してから実行されるようにしている

これらの挙動を組み合わせることで、「対話が停止して30秒ほど経つと過去のやり取りをもとにリフレクションが実行される」という挙動を実現しているということです。

LangGraph ServerのmultitaskStrategyやafterSecondsの使用例として参考になりますね。 非同期で実行したい処理を別のグラフにしておくと、LangGraph Serverの機能で簡単に呼び出しを制御できるということを頭に入れておくと、役立つシーンもありそうです。

ちなみに、ここで使用されているLangGraph ServerのAPIのリファレンスは以下で参照できます。

https://langchain-ai.github.io/langgraph/cloud/reference/api/api_ref.html#tag/thread-runs/POST/threads/{thread_id}/runs

次回のご案内

以上、今回はLangChainの「Open Canvas」をキャッチアップしました。

次回は「AIエージェントキャッチアップ #17 - LLM Guard」ということで、LLMのセキュリティに関するOSS「LLM Guard」がテーマです!

generative-agents.connpass.com

ご興味・お時間ある方はぜひご参加ください!

また、その次の回以降のテーマも募集しているので、気になるエージェントのOSSなどあれば教えてください!