メインコンテンツへスキップ
W&B Weave の Threads を使用すると、LLM アプリケーション内の複数ターンにわたる会話をトラッキングして分析できます。Threads では、関連する Call を共通の thread_id の下にグループ化するため、セッション全体を可視化し、ターンをまたいで会話レベルのメトリクスをトラッキングできます。スレッドはプログラムで作成でき、Weave UI で可視化できます。 Threads を使い始めるには、次の手順に従ってください。
  1. まず、Threads の基本を確認します。
  2. コードサンプルを試します。一般的な使用パターンと実際のユースケースを示しています。

ユースケース

Threads は、次のような対象を整理・分析したい場合に役立ちます。
  • 複数ターンにわたる会話
  • セッションベースのワークフロー
  • 関連する一連の操作
Threads を使用すると、コンテキストごとに Calls をグループ化できるため、複数の ターン にまたがってシステムがどのように応答するかを把握しやすくなります。たとえば、単一のユーザーセッション、エージェント の一連の意思決定、あるいはインフラストラクチャー層とビジネスロジック層にまたがる複雑なリクエストをトラッキングできます。 application を threads と ターン で構造化することで、より整理されたメトリクスを得られ、Weave UI での可視性も向上します。低レベルの Op を個別にすべて見るのではなく、重要な高レベルの step に集中できます。

定義

Thread

Thread は、共通の会話コンテキストを共有する関連する Calls を、論理的にまとめたものです。Thread には次の特徴があります。
  • 一意の thread_id を持つ
  • 1 つ以上の turn を含む
  • Calls をまたいでコンテキストを維持する
  • 完結したユーザーセッションまたはインタラクションフローを表す

Turn

Turn は Thread 内の高レベルな操作で、UI ではスレッドビュー内の個々の行として表示されます。各 Turn には、次の特徴があります。
  • 会話またはワークフローにおける 1 つの論理的な step を表します
  • スレッドコンテキストの直接の子要素であり、ネストされた下位レベルの Call を含む場合があります (スレッドレベルの統計には表示されません) 。

Call

Call とは、アプリケーション内で実行される @weave.op でデコレートされた関数呼び出しのことです。
  • Turn Call は、新しいターンを開始するトップレベルの操作です。
  • Nested Call は、ターン内のより下位の操作です。

トレース

トレース には、単一のoperationにおける完全なCallスタックが記録されます。スレッドは、同じ論理的な会話またはセッションに属するトレースをまとめるものです。言い換えると、スレッドは複数のターンで構成され、それぞれが会話の一部を表します。トレースの詳細については、トレースの概要を参照してください。

UIの概要

Weave のプロジェクトのサイドバーで Threads を選択して、Threads list view を開きます。
Weave サイドバーの Threads アイコン

Threads list view

  • プロジェクト内の最近のThreadsを一覧表示します
  • 列には、ターン数、開始時刻、最終更新時刻があります
  • 行をクリックすると、詳細ドロワーが開きます
Threads list view

スレッド詳細ドロワー

  • 任意の行をクリックすると、その行の詳細ドロワーが開きます。
  • スレッド内のすべてのターンを表示します。
  • ターンは開始順に表示されます (継続時間や終了時刻ではなく、開始時刻に基づきます) 。
  • Callレベルのメタデータ (レイテンシ、inputs、outputs) が含まれます。
  • ログされていれば、メッセージ内容や構造化データを表示することもできます。
  • ターンの実行全体を表示するには、スレッド詳細ドロワーからそのターンを開きます。これにより、そのターン中に発生したすべてのネストされた操作を詳しく確認できます。
  • ターンに LLM calls から抽出されたメッセージが含まれている場合、それらはチャットペインに表示されます。これらのメッセージは通常、サポート対象のインテグレーションによる calls (たとえば openai.ChatCompletion.create) に由来し、表示するには特定の条件を満たす必要があります。詳細は チャットビューの挙動 を参照してください。

チャットビューの挙動

チャットペインには、各ターンで行われた LLM Calls から抽出された構造化メッセージデータが表示されます。このビューでは、やり取りを会話形式で表示できます。
構造化された LLM メッセージを表示する Threads のチャットペイン

どのようなものがメッセージとして扱われますか

Weave は、1 つのターン内にある Calls のうち、LLM プロバイダーとの直接的なやり取り (たとえば、プロンプトを送信してレスポンスを受け取る処理) を表すものからメッセージを抽出します。ほかの Calls の内側にさらにネストされていない Calls だけが、メッセージとして表示されます。これにより、中間 step や集約された内部ロジックが重複して表示されるのを防げます。 通常、メッセージを生成するのは、自動的にパッチが適用されたサードパーティ製 SDK です。たとえば、次のようなものがあります。
  • openai.ChatCompletion.create
  • anthropic.Anthropic.completion

メッセージがない場合

ターンでメッセージが1件も出力されない場合、チャットペイン にはそのターンの空のメッセージセクションが表示されます。同じスレッド内の別のターンのメッセージは、引き続き チャットペイン に表示される場合があります。

Turn と chat の連動

  • ターンをクリックすると、チャットペインがそのターンのメッセージ位置までスクロールします (ピン留めの動作) 。
  • チャットペインをスクロールすると、ターンリストで対応するターンがハイライト表示されます。
項目をクリックすると、そのターンのトレース全体を開けます。 左上に戻るボタンが表示され、スレッド詳細ビューに戻れます。Weave は、この画面遷移の前後で UI の状態 (スクロール位置など) を保持しません。
スレッドビューに戻るための戻るボタンがある Threads 詳細ドロワー

SDK の使用

以下のセクションでは、Weave SDK を使用してプログラムからスレッドを作成および管理する方法を説明します。このセクションの各例では、アプリケーション内でターンとスレッドを整理するための異なる方法を示します。ほとんどの例では、スタブ関数内に独自の LLM call やシステムの挙動を実装する必要があります。
  • セッションまたは会話をトラッキングするには、weave.thread() コンテキストマネージャを使用します。
  • 論理的な処理に @weave.op を付けて、ターンまたはネストされた Call としてトラッキングします。
  • thread_id を渡すと、Weave はそのブロック内のすべての処理を同じスレッドにまとめます。thread_id を省略すると、Weave が一意の ID を自動生成します。
weave.thread() の戻り値は、thread_id プロパティを持つ ThreadContext オブジェクトです。これをログしたり、再利用したり、他のシステムに渡したりできます。 ネストされた weave.thread() コンテキストは、同じ thread_id を再利用しない限り、常に新しいスレッドを開始します。子コンテキストを終了しても、親コンテキストが中断されたり上書きされたりすることはありません。これにより、アプリのロジックに応じて、分岐したスレッド構造や階層的なスレッドオーケストレーションが可能になります。

基本的なスレッド作成

次のコード例では、weave.thread() を使用して、1 つ以上の処理を共通の thread_id でグループ化する方法を示します。これは、アプリケーションでスレッドを使い始めるためのわかりやすい方法です。

手動エージェントループの実装

この例では、@weave.op デコレーターと weave.thread() のコンテキスト管理を使って、会話型エージェントを手動で定義する方法を示します。process_user_message を呼び出すたびに、スレッド内に新しいターンが作成されます。独自のエージェントループを構築し、コンテキストやネストの扱いを完全に制御したい場合は、このパターンを使用できます。 短時間のやり取りには自動生成されたスレッド ID を使用するか、カスタムのセッション ID (user_session_123 など) を渡して、セッションをまたいでスレッドのコンテキストを保持できます。

Call 深度が不均衡な手動エージェント

この例では、スレッドコンテキストの適用方法によって、ターンを Call スタック内の異なる深度で定義できることを示します。サンプルでは 2 つのプロバイダ (OpenAI と Anthropic) を使用しており、それぞれターン境界に到達するまでの Call 深度が異なります。 すべてのターンは同じ thread_id を共有しますが、ターン境界はプロバイダのロジックに応じてスタック内の異なるレベルに現れます。これは、バックエンドごとに Call を異なる方法でトレースする必要がありつつ、それらを同じスレッドにまとめたい場合に便利です。

以前のセッションを再開する

以前に開始したセッションを再開し、同じスレッドに Calls を追加し続けなければならない場合があります。一方で、既存のセッションを再開できず、代わりに新しいスレッドを開始しなければならない場合もあります。 スレッド再開をオプションとして実装する場合は、thread_id パラメーターを None のままにしないでください。そうすると、スレッドのグループ化が無効になります。代わりに、必ず有効なスレッド ID を指定してください。新しいスレッドを作成するには、generate_id() のような関数を使用して一意の ID を生成してください。 thread_id が指定されていない場合、Weave の内部実装によってランダムな UUID v7 が自動的に生成されます。この動作は独自の generate_id() 関数で再現することも、任意の一意な文字列値を使用することもできます。

ネストされたスレッド

この例では、複数の連携したスレッドを使って複雑なアプリケーションをどのように構成するかを示します。 各レイヤーはそれぞれ独自のスレッドコンテキストで実行されるため、責務を明確に分離できます。親アプリケーションのスレッドは、共有の ThreadContext を使ってスレッド ID を設定し、これらのレイヤーを連携させます。システムの異なる部分を個別に分析または監視しつつ、同じセッションにひも付けたい場合は、このパターンを使用してください。

API 仕様

以下のセクションでは、Threads クエリエンドポイント、そのリクエスト/レスポンスのスキーマ、およびスレッドデータをプログラムから取得する際に使用できる一般的なクエリパターンについて説明します。

エンドポイント

エンドポイント: POST /threads/query

リクエストスキーマ

レスポンススキーマ

最近更新されたアクティブなスレッドをクエリする

この例では、直近で更新されたスレッドを50件取得します。my-project は実際のプロジェクト ID に置き換えてください。

アクティビティレベル別にスレッドをクエリする

この例では、ターン数が多い順に、最もアクティブなスレッド20件を取得します。

直近のスレッドのみをクエリする

この例では、過去24時間以内に開始されたスレッドを返します。timedeltadays の値を調整すると、期間を変更できます。