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

# Utiliser l’API de service de Weave pour le traçage

> Découvrez comment utiliser le traçage Weave via l’API de service avec W&B Weave

<Note>
  Il s’agit d’un notebook interactif. Vous pouvez l’exécuter localement ou utiliser les liens suivants :

  * [Ouvrir dans Google Colab](https://colab.research.google.com/github/wandb/docs/blob/main/weave/cookbooks/source/weave_via_service_api.ipynb)
  * [voir la source sur GitHub](https://github.com/wandb/docs/blob/main/weave/cookbooks/source/weave_via_service_api.ipynb)
</Note>

Dans le notebook suivant, vous apprendrez comment utiliser l’API de service de W\&B Weave pour enregistrer des traces afin de :

1. [Créer une simulation d’un appel et d’une réponse LLM simples, et l’enregistrer dans Weave.](#simple-trace)
2. [Créer une simulation d’un appel et d’une réponse LLM plus complexes, et l’enregistrer dans Weave.](#complex-trace)
3. [Exécuter un exemple de requête de recherche sur les traces enregistrées.](#run-a-lookup-query)

> **Consulter les traces enregistrées**
>
> Vous pouvez consulter toutes les traces Weave créées lorsque vous exécutez le code de ce guide en accédant à l’onglet **Traces** de votre projet Weave (spécifié par `team_id\project_id`), puis en sélectionnant le nom de la trace.

Avant de commencer, consultez les [prérequis](#prerequisites-set-variables-and-endpoints).

<div id="prerequisites-set-variables-and-endpoints">
  ## Prérequis : définir les variables et les endpoints
</div>

Avant de journaliser des traces, vous devez configurer les endpoints de l’API de service et vous authentifier avec vos identifiants W\&B.

Le code suivant définit les URL des endpoints utilisées pour accéder à l’API de service :

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

De plus, vous devez définir les variables suivantes :

* `project_id`: Le nom du projet W\&B dans lequel vous souhaitez journaliser vos traces.
* `team_id`: Le nom de votre équipe W\&B.
* `wandb_token`: Votre [clé API W\&B](https://wandb.ai/settings).

```python lines theme={null}
import datetime
import json

import requests

# En-têtes et URLs
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"

# Variables W&B
team_id = ""
project_id = ""
wandb_token = ""
```

<div id="simple-trace">
  ## Trace simple
</div>

Les sections suivantes expliquent comment créer une trace simple :

1. [Démarrer une trace simple](#start-a-simple-trace)
2. [Terminer une trace simple](#end-a-simple-trace)

<div id="start-a-simple-trace">
  ### Démarrer une trace simple
</div>

Le code suivant crée un exemple d’appel LLM `payload_start` et le journalise dans Weave via l’endpoint `url_start`. L’objet `payload_start` simule un appel à `gpt-4o` d’OpenAI avec la requête `Why is the sky blue?`.

En cas de succès, ce code affiche un message indiquant que la trace a été démarrée :

```
Call started. ID: 01939cdc-38d2-7d61-940d-dcca0a56c575, Trace ID: 01939cdc-38d2-7d61-940d-dcd0e76c5f34
python
## ------------
## Démarrer la trace
## ------------
payload_start = {
    "start": {
        "project_id": f"{team_id}/{project_id}",
        "op_name": "simple_trace",
        "started_at": datetime.datetime.now().isoformat(),
        "inputs": {
            # Utilisez ce style "messages" pour générer l'interface de chat dans la trace développée.
            "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()
```

<div id="end-a-simple-trace">
  ### Terminer une trace simple
</div>

Pour terminer la trace simple, le code suivant crée un exemple de charge utile d'appel LLM, `payload_end`, et le journalise dans Weave à l'aide de l'endpoint `url_end`. L'objet `payload_end` imite la réponse de `gpt-4o` d'OpenAI à la requête `Why is the sky blue?`. L'objet est formaté de sorte que les informations récapitulatives de tarification et la chat complétion soient générées dans la vue de trace du tableau de bord Weave.

En cas de réussite, ce code affiche un message indiquant que la trace est terminée :

```
Call ended.
python
## ------------
## Fin de la trace
## ------------
payload_end = {
    "end": {
        "project_id": f"{team_id}/{project_id}",
        "id": call_id,
        "ended_at": datetime.datetime.now().isoformat(),
        "output": {
            # Utilisez ce style "choices" pour ajouter la complétion à l'interface de chat dans la trace développée.
            "choices": [
                {
                    "message": {
                        "content": "It’s due to Rayleigh scattering, where shorter blue wavelengths of sunlight scatter in all directions."
                    }
                },
            ]
        },
        # Formatez la synthèse de cette façon pour générer les informations récapitulatives de tarification dans le tableau des 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)
```

<div id="complex-trace">
  ## Trace complexe
</div>

Maintenant que vous avez enregistré une trace simple en une seule étape, les sections suivantes vous guident dans la création d'une trace plus complexe avec des spans enfants, semblable à une recherche RAG en plusieurs opérations.

1. [Démarrer une trace complexe](#start-a-complex-trace)
2. [Ajouter un span enfant pour une recherche de document RAG](#add-a-child-span-for-a-rag-document-lookup)
3. [Ajouter un span enfant pour un appel de complétion LLM](#add-a-child-span-for-an-llm-completion-call)
4. [Terminer une trace complexe](#end-a-complex-trace)

<div id="start-a-complex-trace">
  ### Démarrer une trace complexe
</div>

Le code suivant montre comment créer une trace plus complexe avec plusieurs spans. Un exemple serait une recherche de type Retrieval-Augmented Generation (RAG), suivie d'un Appel à un LLM. La première partie initialise une trace parente (`payload_parent_start`) qui représente l'opération. Dans ce cas, l'opération traite la requête utilisateur `Can you summarize the key points of this document?`.

L'objet `payload_parent_start` reproduit l'étape initiale d'un flux de travail à plusieurs étapes, en journalisant l'opération dans Weave à l'aide de l'endpoint `url_start`.

En cas de réussite, ce code affiche un message indiquant que l'Appel parent est journalisé :

```
Parent call started. ID: 01939d26-0844-7c43-94bb-cdc471b6d65f, Trace ID: 01939d26-0844-7c43-94bb-cdd97dc296c8
python
## ------------
## Démarrer la trace (parente)
## ------------

# Appel parent : Démarrage
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()
```

<div id="add-a-child-span-for-a-rag-document-lookup">
  ### Ajouter un span enfant pour une recherche de document RAG
</div>

Le code suivant montre comment ajouter un span enfant à la trace parente complexe démarrée à l’étape précédente. Cette étape modélise la sous-opération de recherche de document RAG dans le flux de travail.

La trace enfant est initiée avec l’objet `payload_child_start`, qui inclut :

* `trace_id` : relie ce span enfant à la trace parente.
* `parent_id` : associe le span enfant à l’opération parente.
* `inputs` : journalise la requête de recherche, par ex. :
  `"Ceci est une requête de recherche pour les documents que je cherche."`

Si l’appel à l’endpoint `url_start` réussit, le code affiche un message indiquant que l’appel enfant a démarré et s’est terminé :

```
Child call started. ID: 01939d32-23d6-75f2-9128-36a4a806f179
Child call ended.
python
## ------------
## Span enfant :
## Ex. recherche de document RAG
## ------------

# Appel enfant : Début
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()

# Appel enfant : Fin
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)
```

<div id="add-a-child-span-for-an-llm-completion-call">
  ### Ajouter un span enfant pour un appel de complétion LLM
</div>

Le code suivant montre comment ajouter un autre span enfant à la trace parente complexe pour représenter un appel de complétion LLM. Cette étape modélise la génération de la réponse du LLM à partir du contexte documentaire récupéré lors de l’opération RAG précédente.

La trace de complétion LLM est lancée avec l’objet `payload_child_start`, qui comprend :

* `trace_id` : relie ce span enfant à la trace parente.
* `parent_id` : associe le span enfant au flux de travail parent.
* `inputs` : journalise les messages d’entrée pour le LLM, y compris la requête de l’utilisateur et le contexte documentaire ajouté.
* `model` : spécifie le modèle utilisé pour l’opération (`gpt-4o`).

En cas de réussite, le code affiche un message indiquant que la trace du span enfant LLM a démarré :

```
Child call started. ID: 0245acdf-83a9-4c90-90df-dcb2b89f234a
```

Une fois l’opération terminée, l’objet `payload_child_end` met fin à la trace en journalisant la réponse générée par le LLM dans le champ `output`. Le code journalise également des informations récapitulatives d’utilisation.

En cas de réussite, le code affiche un message indiquant que la trace du span enfant du LLM a démarré puis s’est terminée :

```
Child call started. ID: 0245acdf-83a9-4c90-90df-dcb2b89f234a
Child call ended.
python
## ------------
## Span enfant :
## Créer un appel de complétion LLM
## ------------

# Appel enfant : Début
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()

# Appel enfant : Fin
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)
```

<div id="end-a-complex-trace">
  ### Terminer une trace complexe
</div>

Le code suivant montre comment finaliser la trace parente afin de marquer l’achèvement du flux de travail. Cette étape agrège les résultats de toutes les spans enfants (par exemple, la recherche RAG et la complétion LLM) et journalise la sortie finale ainsi que les métadonnées.

La trace est finalisée à l’aide de l’objet `payload_parent_end`, qui comprend :

* `id` : le `parent_call_id` du démarrage initial de la trace parente.
* `output` : représente la sortie finale du flux de travail.
* `summary` : consolide les données d’utilisation pour le flux de travail.
* `prompt_tokens` : nombre total de tokens utilisés pour tous les prompts.
* `completion_tokens` : nombre total de tokens générés dans toutes les réponses.
* `total_tokens` : nombre total combiné de tokens pour le flux de travail.
* `requests` : nombre total de requêtes effectuées (dans ce cas, `1`).

En cas de réussite, le code affiche :

```
Parent call ended.
python
## ------------
## Fin de la trace
## ------------

# Appel parent : fin
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)
```

<div id="run-a-lookup-query">
  ## Exécuter une requête de recherche
</div>

Une fois les traces enregistrées dans Weave, vous pouvez utiliser l’API de service pour les interroger par programmation. Le code suivant montre comment interroger les traces créées dans les exemples précédents, en filtrant uniquement celles pour lesquelles le champ `inputs.model` est égal à `gpt-4o`.

L'objet `query_payload` comprend :

* `project_id` : identifie l'équipe et le projet à interroger.
* `filter` : garantit que la requête ne renvoie que les **racines de trace** (traces de niveau supérieur).
* `query` : définit la logique de filtrage à l'aide de l'opérateur `$expr` :
  * `$getField` : récupère le champ `inputs.model`.
  * `$literal` : sélectionne les traces pour lesquelles `inputs.model` est égal à `"gpt-4o"`.
* `limit` : limite la requête à 10 000 résultats.
* `offset` : commence la requête au premier résultat.
* `sort_by` : trie les résultats selon l'horodatage `started_at`, par ordre décroissant.
* `include_feedback` : exclut les données de feedback des résultats.

Si la requête aboutit, la réponse inclut les données de trace correspondant aux paramètres de la requête :

```
{'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:
        # Décodage alternatif
        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)
```
