メインコンテンツへスキップ
これはインタラクティブなノートブックです。ローカルで実行するか、以下のリンクを使用してください:

Service API を使用して Traces の ログ とクエリを行う

このガイドでは、 Weave Service API を使用して Traces を ログ に記録する方法を学びます。具体的には、Service API を使用して以下の操作を行います。
  1. シンプルな LLM の呼び出しと応答のモックを作成し、 Weave に ログ を記録する。
  2. より複雑な LLM の呼び出しと応答のモックを作成し、 Weave に ログ を記録する。
  3. ログ に記録された Traces に対してサンプル検索クエリを実行する。
ログに記録された Traces を表示する このガイドの コード を実行した際に作成されたすべての Weave Traces は、 Weave プロジェクト(team_id\project_id で指定)の Traces タブに移動し、 Trace の名前を選択することで表示できます。
開始する前に、事前準備を完了させてください。

事前準備:変数とエンドポイントの設定

以下の コード は、Service API への アクセス に使用される URL エンドポイントを設定します。 さらに、以下の変数を設定する必要があります。
  • project_id: Traces を ログ に記録したい W&B Projects の名前。
  • team_id: W&B の Teams 名。
  • wandb_token: あなたの W&B APIキー
import datetime
import json

import requests

# ヘッダーとURL
headers = {"Content-Type": "application/json"}
url_start = "https://trace.wandb.ai/call/start"
url_end = "https://trace.wandb.ai/call/end"
url_stream_query = "https://trace.wandb.ai/calls/stream_query"

# W&B 変数
team_id = ""
project_id = ""
wandb_token = ""

シンプルな Trace

以下のセクションでは、シンプルな Trace の作成手順を説明します。
  1. シンプルな Trace を開始する
  2. シンプルな Trace を終了する

シンプルな Trace を開始する

以下の コード は、サンプルの LLM 呼び出し payload_start を作成し、url_start エンドポイントを使用して Weave に ログ を記録します。payload_start オブジェクト は、Why is the sky blue?(なぜ空は青いの?)というクエリを用いた OpenAI の gpt-4o への呼び出しを模倣しています。 成功すると、この コード は Trace が開始されたことを示すメッセージを出力します。
Call started. ID: 01939cdc-38d2-7d61-940d-dcca0a56c575, Trace ID: 01939cdc-38d2-7d61-940d-dcd0e76c5f34
## ------------
## Trace を開始
## ------------
payload_start = {
    "start": {
        "project_id": f"{team_id}/{project_id}",
        "op_name": "simple_trace",
        "started_at": datetime.datetime.now().isoformat(),
        "inputs": {
            # 展開された Trace でチャット UI を生成するには、この "messages" スタイルを使用します。
            "messages": [{"role": "user", "content": "Why is the sky blue?"}],
            "model": "gpt-4o",
        },
        "attributes": {},
    }
}
response = requests.post(
    url_start, headers=headers, json=payload_start, auth=("api", wandb_token)
)
if response.status_code == 200:
    data = response.json()
    call_id = data.get("id")
    trace_id = data.get("trace_id")
    print(f"Call started. ID: {call_id}, Trace ID: {trace_id}")
else:
    print("Start request failed with status:", response.status_code)
    print(response.text)
    exit()

シンプルな Trace を終了する

シンプルな Trace を完了するために、以下の コード はサンプルの LLM 呼び出し payload_end を作成し、url_end エンドポイントを使用して Weave に ログ を記録します。payload_end オブジェクト は、クエリ Why is the sky blue? に対する OpenAI の gpt-4o からのレスポンスを模倣しています。この オブジェクト は、Weave ダッシュボード の Trace ビューで料金サマリー 情報 とチャットの完了内容が生成されるようにフォーマットされています。 成功すると、この コード は Trace が完了したことを示すメッセージを出力します。
Call ended.
## ------------
## Trace を終了
## ------------
payload_end = {
    "end": {
        "project_id": f"{team_id}/{project_id}",
        "id": call_id,
        "ended_at": datetime.datetime.now().isoformat(),
        "output": {
            # 展開された Trace のチャット UI に回答を追加するには、この "choices" スタイルを使用します。
            "choices": [
                {
                    "message": {
                        "content": "It’s due to Rayleigh scattering, where shorter blue wavelengths of sunlight scatter in all directions."
                    }
                },
            ]
        },
        # Traces テーブルに料金サマリー情報を生成するには、サマリーをこのようにフォーマットします。
        "summary": {
            "usage": {
                "gpt-4o": {
                    "prompt_tokens": 10,
                    "completion_tokens": 20,
                    "total_tokens": 30,
                    "requests": 1,
                }
            }
        },
    }
}
response = requests.post(
    url_end, headers=headers, json=payload_end, auth=("api", wandb_token)
)
if response.status_code == 200:
    print("Call ended.")
else:
    print("End request failed with status:", response.status_code)
    print(response.text)

複雑な Trace

以下のセクションでは、マルチオペレーションの RAG 検索に似た、子スパン(child spans)を持つより複雑な Trace の作成手順を説明します。
  1. 複雑な Trace を開始する
  2. RAG ドキュメント検索用の子スパンを追加する
  3. LLM 完了呼び出し用の子スパンを追加する
  4. 複雑な Trace を終了する

複雑な Trace を開始する

以下の コード は、複数のスパンを持つより複雑な Trace を作成する方法を示しています。この例としては、RAG(検索拡張生成)検索の後に LLM 呼び出しを行う場合が挙げられます。最初のパートでは、全体の操作を表す親 Trace(payload_parent_start)を初期化します。このケースでは、ユーザーのクエリ Can you summarize the key points of this document?(このドキュメントの要点をまとめてくれますか?)を処理する操作です。 payload_parent_start オブジェクト は、マルチステップ ワークフロー の最初のステップを模倣し、url_start エンドポイントを使用して Weave に操作を ログ 記録します。 成功すると、この コード は親の呼び出しが ログ に記録されたことを示すメッセージを出力します。
Parent call started. ID: 01939d26-0844-7c43-94bb-cdc471b6d65f, Trace ID: 01939d26-0844-7c43-94bb-cdd97dc296c8
## ------------
## Trace を開始 (parent)
## ------------

# 親呼び出し: 開始
payload_parent_start = {
    "start": {
        "project_id": f"{team_id}/{project_id}",
        "op_name": "complex_trace",
        "started_at": datetime.datetime.now().isoformat(),
        "inputs": {"question": "Can you summarize the key points of this document?"},
        "attributes": {},
    }
}
response = requests.post(
    url_start, headers=headers, json=payload_parent_start, auth=("api", wandb_token)
)
if response.status_code == 200:
    data = response.json()
    parent_call_id = data.get("id")
    trace_id = data.get("trace_id")
    print(f"Parent call started. ID: {parent_call_id}, Trace ID: {trace_id}")
else:
    print("Parent start request failed with status:", response.status_code)
    print(response.text)
    exit()

RAG ドキュメント検索用の子スパンを追加する

以下の コード は、前のステップで開始した複雑な親 Trace に子スパンを追加する方法を示しています。このステップでは、全体的な ワークフロー 内の RAG ドキュメント検索サブ操作をモデル化しています。 子 Trace は payload_child_start オブジェクト で開始され、以下を含みます。
  • trace_id: この子スパンを親 Trace にリンクします。
  • parent_id: 子スパンを親の操作に関連付けます。
  • inputs: 検索クエリを ログ に記録します。例: "This is a search query of the documents I'm looking for."
url_start エンドポイントへの呼び出しが成功すると、 コード は子の呼び出しが開始および完了したことを示すメッセージを出力します。
Child call started. ID: 01939d32-23d6-75f2-9128-36a4a806f179
Child call ended.
## ------------
## 子スパン:
## 例:RAG ドキュメント検索
## ------------

# 子呼び出し: 開始
payload_child_start = {
    "start": {
        "project_id": f"{team_id}/{project_id}",
        "op_name": "rag_document_lookup",
        "trace_id": trace_id,
        "parent_id": parent_call_id,
        "started_at": datetime.datetime.now().isoformat(),
        "inputs": {
            "document_search": "This is a search query of the documents I'm looking for."
        },
        "attributes": {},
    }
}
response = requests.post(
    url_start, headers=headers, json=payload_child_start, auth=("api", wandb_token)
)
if response.status_code == 200:
    data = response.json()
    child_call_id = data.get("id")
    print(f"Child call started. ID: {child_call_id}")
else:
    print("Child start request failed with status:", response.status_code)
    print(response.text)
    exit()

# 子呼び出し: 終了
payload_child_end = {
    "end": {
        "project_id": f"{team_id}/{project_id}",
        "id": child_call_id,
        "ended_at": datetime.datetime.now().isoformat(),
        "output": {
            "document_results": "This will be the RAG'd document text which will be returned from the search query."
        },
        "summary": {},
    }
}
response = requests.post(
    url_end, headers=headers, json=payload_child_end, auth=("api", wandb_token)
)
if response.status_code == 200:
    print("Child call ended.")
else:
    print("Child end request failed with status:", response.status_code)
    print(response.text)

LLM 完了呼び出し用の子スパンを追加する

以下の コード は、複雑な親 Trace に別の子スパンを追加し、LLM の完了呼び出しを表現する方法を示しています。このステップでは、前の RAG 操作で取得されたドキュメントのコンテキストに基づいた AI のレスポンス生成をモデル化しています。 LLM 完了 Trace は payload_child_start オブジェクト で開始され、以下を含みます。
  • trace_id: この子スパンを親 Trace にリンクします。
  • parent_id: 子スパンを全体的な ワークフロー に関連付けます。
  • inputs: ユーザーのクエリと付加されたドキュメントのコンテキストを含む、LLM への入力メッセージを ログ に記録します。
  • model: 操作に使用された モデル を指定します(gpt-4o)。
成功すると、 コード は LLM の子スパン Trace が開始および終了したことを示すメッセージを出力します。
Child call started. ID: 0245acdf-83a9-4c90-90df-dcb2b89f234a
操作が完了すると、payload_child_end オブジェクト が output フィールドに LLM 生成レスポンスを ログ 記録して Trace を終了します。使用状況のサマリー 情報 も ログ に記録されます。 成功すると、 コード は LLM の子スパン Trace が開始および終了したことを示すメッセージを出力します。
Child call started. ID: 0245acdf-83a9-4c90-90df-dcb2b89f234a
Child call ended.
## ------------
## 子スパン:
## LLM 完了呼び出しの作成
## ------------

# 子呼び出し: 開始
payload_child_start = {
    "start": {
        "project_id": f"{team_id}/{project_id}",
        "op_name": "llm_completion",
        "trace_id": trace_id,
        "parent_id": parent_call_id,
        "started_at": datetime.datetime.now().isoformat(),
        "inputs": {
            "messages": [
                {
                    "role": "user",
                    "content": "With the following document context, could you help me answer:\n Can you summarize the key points of this document?\n [+ appended document context]",
                }
            ],
            "model": "gpt-4o",
        },
        "attributes": {},
    }
}
response = requests.post(
    url_start, headers=headers, json=payload_child_start, auth=("api", wandb_token)
)
if response.status_code == 200:
    data = response.json()
    child_call_id = data.get("id")
    print(f"Child call started. ID: {child_call_id}")
else:
    print("Child start request failed with status:", response.status_code)
    print(response.text)
    exit()

# 子呼び出し: 終了
payload_child_end = {
    "end": {
        "project_id": f"{team_id}/{project_id}",
        "id": child_call_id,
        "ended_at": datetime.datetime.now().isoformat(),
        "output": {
            "choices": [
                {"message": {"content": "This is the response generated by the LLM."}},
            ]
        },
        "summary": {
            "usage": {
                "gpt-4o": {
                    "prompt_tokens": 10,
                    "completion_tokens": 20,
                    "total_tokens": 30,
                    "requests": 1,
                }
            }
        },
    }
}
response = requests.post(
    url_end, headers=headers, json=payload_child_end, auth=("api", wandb_token)
)
if response.status_code == 200:
    print("Child call ended.")
else:
    print("Child end request failed with status:", response.status_code)
    print(response.text)

複雑な Trace を終了する

以下の コード は、親 Trace を終了し、 ワークフロー 全体の完了をマークする方法を示しています。このステップでは、すべての子スパン(例:RAG 検索と LLM 完了)の結果を集約し、最終的な出力と メタデータ を ログ に記録します。 Trace は payload_parent_end オブジェクト を使用して完了します。これには以下が含まれます。
  • id: 最初の親 Trace 開始時の parent_call_id
  • output: ワークフロー 全体の最終出力を表します。
  • summary: ワークフロー 全体の使用状況データを統合します。
  • prompt_tokens: すべてのプロンプトで使用された合計トークン数。
  • completion_tokens: すべてのレスポンスで生成された合計トークン数。
  • total_tokens: ワークフロー の合計トークン数。
  • requests: 行われたリクエストの総数(この場合は 1)。
成功すると、 コード は以下を出力します。
Parent call ended.
## ------------
## Trace を終了
## ------------

# 親呼び出し: 終了
payload_parent_end = {
    "end": {
        "project_id": f"{team_id}/{project_id}",
        "id": parent_call_id,
        "ended_at": datetime.datetime.now().isoformat(),
        "output": {
            "choices": [
                {"message": {"content": "This is the response generated by the LLM."}},
            ]
        },
        "summary": {
            "usage": {
                "gpt-4o": {
                    "prompt_tokens": 10,
                    "completion_tokens": 20,
                    "total_tokens": 30,
                    "requests": 1,
                }
            }
        },
    }
}
response = requests.post(
    url_end, headers=headers, json=payload_parent_end, auth=("api", wandb_token)
)
if response.status_code == 200:
    print("Parent call ended.")
else:
    print("Parent end request failed with status:", response.status_code)
    print(response.text)

検索クエリの実行

以下の コード は、前の例で作成された Traces を照会し、inputs.model フィールドが gpt-4o に等しい Traces のみをフィルタリングする方法を示しています。 query_payload オブジェクト には以下が含まれます。
  • project_id: クエリ対象の Team と プロジェクト を特定します。
  • filter: クエリが trace roots(トップレベルの Trace)のみを返すようにします。
  • query: $expr 演算子を使用してフィルタロジックを定義します。
    • $getField: inputs.model フィールドを取得します。
    • $literal: inputs.model"gpt-4o" に一致する Traces を照合します。
  • limit: クエリの結果を 10,000 件に制限します。
  • offset: クエリを最初の結果から開始します。
  • sort_by: started_at タイムスタンプの降順で結果を並べ替えます。
  • include_feedback: 結果からフィードバック データ を除外します。
クエリが成功すると、レスポンスにはクエリ パラメータ に一致する Trace データが含まれます。
{'id': '01939cf3-541f-76d3-ade3-50cfae068b39', 'project_id': 'cool-new-team/uncategorized', 'op_name': 'simple_trace', 'display_name': None, 'trace_id': '01939cf3-541f-76d3-ade3-50d5cfabe2db', 'parent_id': None, 'started_at': '2024-12-06T17:10:12.590000Z', 'attributes': {}, 'inputs': {'messages': [{'role': 'user', 'content': 'Why is the sky blue?'}], 'model': 'gpt-4o'}, 'ended_at': '2024-12-06T17:47:08.553000Z', 'exception': None, 'output': {'choices': [{'message': {'content': 'It’s due to Rayleigh scattering, where shorter blue wavelengths of sunlight scatter in all directions.'}}]}, 'summary': {'usage': {'gpt-4o': {'prompt_tokens': 10, 'completion_tokens': 20, 'requests': 1, 'total_tokens': 30}}, 'weave': {'status': 'success', 'trace_name': 'simple_trace', 'latency_ms': 2215963}}, 'wb_user_id': 'VXNlcjoyMDk5Njc0', 'wb_run_id': None, 'deleted_at': None}
query_payload = {
    "project_id": f"{team_id}/{project_id}",
    "filter": {"trace_roots_only": True},
    "query": {
        "$expr": {"$eq": [{"$getField": "inputs.model"}, {"$literal": "gpt-4o"}]}
    },
    "limit": 10000,
    "offset": 0,
    "sort_by": [{"field": "started_at", "direction": "desc"}],
    "include_feedback": False,
}
response = requests.post(
    url_stream_query, headers=headers, json=query_payload, auth=("api", wandb_token)
)
if response.status_code == 200:
    print("Query successful!")
    try:
        data = response.json()
        print(data)
    except json.JSONDecodeError as e:
        # 代替のデコード
        json_objects = response.text.strip().split("\n")
        parsed_data = [json.loads(obj) for obj in json_objects]
        print(parsed_data)
else:
    print(f"Query failed with status code: {response.status_code}")
    print(response.text)