> ## Documentation Index
> Fetch the complete documentation index at: https://docs.coreweave.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Weave サービス API を使用してトレースする

> W&B Weave のサービス API を通じて Weave トレースを使用する方法を学びます

<Note>
  これはインタラクティブなノートブックです。ローカルで実行するか、以下のリンクを使用できます。

  * [Google Colab で開く](https://colab.research.google.com/github/wandb/docs/blob/main/weave/cookbooks/source/weave_via_service_api.ipynb)
  * [GitHub でソースを表示](https://github.com/wandb/docs/blob/main/weave/cookbooks/source/weave_via_service_api.ipynb)
</Note>

このノートブックでは、W\&B Weave サービス API を使用してトレースをログし、次の操作を行う方法を学びます。

1. [シンプルな LLM Call と応答のモックを作成し、Weave にログします。](#simple-trace)
2. [より複雑な LLM Call と応答のモックを作成し、Weave にログします。](#complex-trace)
3. [ログしたトレースに対してサンプルのルックアップクエリを実行します。](#run-a-lookup-query)

> **ログしたトレースを表示する**
>
> このガイドのコードを実行して作成されたすべての Weave トレースを表示するには、Weave プロジェクト (`team_id\project_id` で指定) の **Traces** タブに移動し、トレースの名前を選択します。

始める前に、[前提条件](#prerequisites-set-variables-and-endpoints)を済ませておいてください。

<h2 id="prerequisites-set-variables-and-endpoints">
  前提条件: 変数とエンドポイントを設定する
</h2>

トレースをログする前に、サービス API のエンドポイントを設定し、W\&B の認証情報で認証する必要があります。

次のコードは、サービス API へのアクセスに使用する URL エンドポイントを設定します。

* [`https://trace.wandb.ai/call/start`](/ja/products/wandb/weave/reference/service-api/calls/call-start)
* [`https://trace.wandb.ai/call/end`](/ja/products/wandb/weave/reference/service-api/calls/call-end)
* [`https://trace.wandb.ai/calls/stream_query`](/ja/products/wandb/weave/reference/service-api/calls/calls-query-stream)

また、次の変数を設定する必要があります。

* `project_id`: トレースをログする Weights & Biases のプロジェクト名。
* `team_id`: CoreWeave Forge のチーム名。
* `wandb_token`: ご自身の [W\&B APIキー](https://forge.coreweave.com/settings)。

```python lines theme={"system"}
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 = ""
```

<h2 id="simple-trace">
  シンプルなトレース
</h2>

以下のセクションでは、シンプルなトレースの作成方法について説明します：

1. [シンプルなトレースを開始する](#start-a-simple-trace)
2. [シンプルなトレースを終了する](#end-a-simple-trace)

<h3 id="start-a-simple-trace">
  シンプルなトレースを開始する
</h3>

以下のコードは、サンプルの LLM Call `payload_start` を作成し、`url_start` エンドポイントを使用して Weave にログします。`payload_start` オブジェクトは、クエリ `Why is the sky blue?` で OpenAI の `gpt-4o` への Call を模倣します。

成功すると、このコードはトレースが開始されたことを示すメッセージを出力します：

```
Call started. ID: 01939cdc-38d2-7d61-940d-dcca0a56c575, Trace ID: 01939cdc-38d2-7d61-940d-dcd0e76c5f34
python
## ------------
## トレースを開始
## ------------
payload_start = {
    "start": {
        "project_id": f"{team_id}/{project_id}",
        "op_name": "simple_trace",
        "started_at": datetime.datetime.now().isoformat(),
        "inputs": {
            # この「messages」スタイルを使用すると、展開したトレースにチャット UI が表示されます。
            "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()
```

<h3 id="end-a-simple-trace">
  シンプルなトレースを終了する
</h3>

シンプルなトレースを完了するために、以下のコードはサンプル LLM Call `payload_end` を作成し、`url_end` エンドポイントを使用して Weave にログします。`payload_end` オブジェクトは、クエリ `Why is the sky blue?` に対する OpenAI の `gpt-4o` からの応答を模倣しています。このオブジェクトは、pricing summary information とチャット補完が Weave ダッシュボードのトレースビューで生成されるようにフォーマットされています。

成功すると、このコードはトレースが完了したことを示すメッセージを出力します：

```
Call ended.
python
## ------------
## トレースを終了
## ------------
payload_end = {
    "end": {
        "project_id": f"{team_id}/{project_id}",
        "id": call_id,
        "ended_at": datetime.datetime.now().isoformat(),
        "output": {
            # この "choices" 形式を使用すると、展開したトレースのチャット UI に補完結果が追加されます。
            "choices": [
                {
                    "message": {
                        "content": "It’s due to Rayleigh scattering, where shorter blue wavelengths of sunlight scatter in all directions."
                    }
                },
            ]
        },
        # summary をこの形式にすると、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)
```

<h2 id="complex-trace">
  複雑なトレース
</h2>

シンプルな単一ステップのトレースをログしたので、以下のセクションでは、複数操作の RAG ルックアップに似た、子スパンを持つより複雑なトレースの作成方法をご案内します。

1. [複雑なトレースを開始する](#start-a-complex-trace)
2. [RAG ドキュメント ルックアップ用の子スパンを追加する](#add-a-child-span-for-a-rag-document-lookup)
3. [LLM 補完 Call 用の子スパンを追加する](#add-a-child-span-for-an-llm-completion-call)
4. [複雑なトレースを終了する](#end-a-complex-trace)

<h3 id="start-a-complex-trace">
  複雑なトレースを開始する
</h3>

以下のコードは、複数のスパンを持つより複雑なトレースを作成する方法を示しています。例として、Retrieval-Augmented Generation (RAG) のルックアップに続いて LLM Call を行うものがあります。最初の部分では、操作を表す親トレース (`payload_parent_start`) を初期化します。この場合、操作はユーザークエリ `Can you summarize the key points of this document?` を処理します。

`payload_parent_start` オブジェクトは、多段階のワークフローの初期ステップを模倣し、`url_start` エンドポイントを使用して Weave に操作をログします。

成功すると、このコードは親 Call がログされたことを示すメッセージを出力します:

```
Parent call started. ID: 01939d26-0844-7c43-94bb-cdc471b6d65f, Trace ID: 01939d26-0844-7c43-94bb-cdd97dc296c8
python
## ------------
## トレースを開始 (親)
## ------------

# 親Call: 開始
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()
```

<h3 id="add-a-child-span-for-a-rag-document-lookup">
  RAG ドキュメント ルックアップ用の子スパンを追加
</h3>

以下のコードは、前のステップで開始した複雑な親トレースに子スパンを追加する方法を示しています。このステップは、ワークフロー内の RAG ドキュメント ルックアップのサブ操作をモデル化します。

子トレースは、以下の内容を含む `payload_child_start` オブジェクトで開始されます：

* `trace_id`: この子スパンを親トレースにリンクします。
* `parent_id`: 子スパンを親操作に関連付けます。
* `inputs`: 検索クエリをログします。例：
  `"This is a search query of the documents I'm looking for."`

`url_start` エンドポイントへの呼び出しが成功すると、コードは子 Call が開始および完了したことを示すメッセージを出力します：

```
Child call started. ID: 01939d32-23d6-75f2-9128-36a4a806f179
Child call ended.
python
## ------------
## 子スパン:
## 例: RAG ドキュメントルックアップ
## ------------

# 子 Call: 開始
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()

# 子 Call: 終了
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)
```

<h3 id="add-a-child-span-for-an-llm-completion-call">
  LLM 補完 Call の子スパンを追加する
</h3>

次のコードは、複雑な親トレースに、LLM 補完 Call を表す子スパンをもう 1 つ追加する方法を示しています。このステップでは、前の RAG 操作で取得したドキュメントのコンテキストに基づいて LLM が応答を生成する処理をモデル化します。

LLM 補完のトレースは、`payload_child_start` オブジェクトで開始します。このオブジェクトには次の項目が含まれます。

* `trace_id`: この子スパンを親トレースにリンクします。
* `parent_id`: 子スパンを親ワークフローに関連付けます。
* `inputs`: ユーザーのクエリと、追加されたドキュメントのコンテキストを含む、LLM への入力メッセージをログします。
* `model`: 操作に使用するモデル (`gpt-4o`) を指定します。

成功すると、LLM の子スパンのトレースが開始されたことを示すメッセージが出力されます。

```
子呼び出しが開始されました。ID: 0245acdf-83a9-4c90-90df-dcb2b89f234a
```

操作が完了すると、`payload_child_end` オブジェクトは LLM が生成した応答を `output` フィールドにログして、トレースを終了します。また、このコードは使用量の要約情報もログします。

成功すると、LLM の子スパンのトレースが開始され、終了したことを示すメッセージが出力されます：

```
Child call started. ID: 0245acdf-83a9-4c90-90df-dcb2b89f234a
Child call ended.
python
## ------------
## 子スパン:
## LLM 補完 Call を作成します
## ------------

# 子 Call: 開始
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()

# 子 Call: 終了
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)
```

<h3 id="end-a-complex-trace">
  複雑なトレースを終了する
</h3>

次のコードは、親トレースを確定し、ワークフローの完了を示す方法を説明します。このステップでは、すべての子スパン (たとえば、RAG ルックアップや LLM 補完) の結果を集約し、最終出力とメタデータをログします。

トレースは、次の内容を含む `payload_parent_end` オブジェクトを使用して確定されます。

* `id`: 親トレースの開始時の `parent_call_id` です。
* `output`: ワークフローの最終出力を表します。
* `summary`: ワークフローの使用量データを集約します。
* `prompt_tokens`: すべてのプロンプトで使用されたトークンの総数です。
* `completion_tokens`: すべての応答で生成されたトークンの総数です。
* `total_tokens`: ワークフロー全体のトークン数の合計です。
* `requests`: 行われたリクエストの総数です (この場合は `1`) 。

成功すると、コードは次の内容を出力します。

```
Parent call ended.
python
## ------------
## トレースを終了
## ------------

# 親の呼び出し: 終了
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)
```

<h2 id="run-a-lookup-query">
  ルックアップクエリを実行する
</h2>

トレースが Weave にログされていれば、サービス API を使用してプログラムでクエリできます。以下のコードは、前のサンプル で作成されたトレースをクエリする方法を示しており、`inputs.model` フィールドが `gpt-4o` に等しいトレースのみをフィルターします。

`query_payload` オブジェクトには以下が含まれます：

* `project_id`: クエリする チーム と project を識別します。
* `filter`: クエリが トレース のルート (top-level のトレース) のみを返すようにします。
* `query`: `$expr` オペレーターを使用してフィルターロジックを定義します。
  * `$getField`: `inputs.model` フィールドを取得します。
  * `$literal`: `inputs.model` が `"gpt-4o"` に等しいトレースに一致します。
* `limit`: クエリを 10,000 件の結果に制限します。
* `offset`: 最初の結果からクエリを開始します。
* `sort_by`: `started_at` タイムスタンプで結果を降順に並べ替えます。
* `include_feedback`: 結果からフィードバックデータを除外します。

クエリが成功すると、応答にはクエリパラメーターに一致するトレースデータが含まれます：

```
{'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}
python
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)
```
