Ce produit n'est pas pris en charge par le site Datadog que vous avez sélectionné. ().

Aperçu

Les SDK LLM Observability de Datadog fournissent une instrumentation automatique ainsi que des API d’instrumentation manuelle pour offrir une visibilité et des informations sur vos applications LLM.

Configuration

Exigences

  • Le dernier ddtrace paquet est installé (Python 3.7+ requis) :
    pip install ddtrace
    
  • Le dernier dd-trace paquet est installé (Node.js 16+ requis) :
    npm install dd-trace
    
  • Vous avez téléchargé le dernier dd-trace-java JAR. Le SDK LLM Observability est pris en charge dans dd-trace-java v1.51.0+ (Java 8+ requis).

Activez LLM Observability en exécutant votre application avec la commande ddtrace-run et en spécifiant les variables d’environnement requises.

Remarque: ddtrace-run active automatiquement toutes les intégrations LLM Observability.

DD_SITE=<YOUR_DATADOG_SITE> DD_API_KEY=<YOUR_API_KEY> DD_LLMOBS_ENABLED=1 \
DD_LLMOBS_ML_APP=<YOUR_ML_APP_NAME> ddtrace-run <YOUR_APP_STARTUP_COMMAND>

Variables d’environnement pour la configuration en ligne de commande

DD_SITE
requis - chaîne
Site Datadog de destination pour la soumission des données LLM. Votre site est .
DD_LLMOBS_ENABLED
requis - entier ou chaîne
Basculer pour activer la soumission des données à LLM Observability. Doit être défini sur 1 ou true.
DD_LLMOBS_ML_APP
optionnel - chaîne
Le nom de votre application LLM, service ou projet, sous lequel toutes les traces et spans sont regroupés. Cela aide à distinguer entre différentes applications ou expériences. Voir les directives de nommage des applications pour les caractères autorisés et d’autres contraintes. Pour remplacer cette valeur pour un span racine donné, voir Tracer plusieurs applications. Si non fourni, ce paramètre prend par défaut la valeur de DD_SERVICE ou celle d’un DD_LLMOBS_ML_APP propagé d’un service en amont.
Remarque: Avant la version ddtrace==3.14.0, ceci est un champ requis.
DD_LLMOBS_AGENTLESS_ENABLED
optionnel - entier ou chaîne - par défaut : false
Seulement requis si vous n’utilisez pas l’Agent Datadog, auquel cas cela doit être défini sur 1 ou true.
DD_API_KEY
optionnel - chaîne
Votre clé API Datadog. Seulement requis si vous n’utilisez pas l’Agent Datadog.

Activez LLM Observability en exécutant votre application avec NODE_OPTIONS="--import dd-trace/initialize.mjs" et en spécifiant les variables d’environnement requises.

Remarque: dd-trace/initialize.mjs active automatiquement toutes les intégrations APM.

DD_SITE=<YOUR_DATADOG_SITE> DD_API_KEY=<YOUR_API_KEY> DD_LLMOBS_ENABLED=1 \
DD_LLMOBS_ML_APP=<YOUR_ML_APP_NAME> NODE_OPTIONS="--import dd-trace/initialize.mjs" node <YOUR_APP_ENTRYPOINT>

Variables d’environnement pour la configuration en ligne de commande

DD_SITE
requis - chaîne
Le site Datadog pour soumettre vos données LLM. Votre site est .
DD_LLMOBS_ENABLED
requis - entier ou chaîne
Basculer pour activer la soumission des données à LLM Observability. Doit être défini sur 1 ou true.
DD_LLMOBS_ML_APP
optionnel - chaîne
Le nom de votre application LLM, service ou projet, sous lequel toutes les traces et spans sont regroupés. Cela aide à distinguer entre différentes applications ou expériences. Voir les directives de nommage des applications pour les caractères autorisés et d’autres contraintes. Pour remplacer cette valeur pour un span racine donné, voir Tracer plusieurs applications. Si non fourni, ce paramètre prend par défaut la valeur de DD_SERVICE ou celle d’un DD_LLMOBS_ML_APP propagé d’un service en amont.
Remarque: Avant la version dd-trace@5.66.0, ceci est un champ requis.
DD_LLMOBS_AGENTLESS_ENABLED
optionnel - entier ou chaîne - par défaut : false
Seulement requis si vous n’utilisez pas l’Agent Datadog, auquel cas cela doit être défini sur 1 ou true.
DD_API_KEY
optionnel - chaîne
Votre clé API Datadog. Seulement requis si vous n’utilisez pas l’Agent Datadog.

Activez LLM Observability en exécutant votre application avec dd-trace-java et en spécifiant les paramètres requis en tant que variables d’environnement ou propriétés système.

DD_SITE=<YOUR_DATADOG_SITE> DD_API_KEY=<YOUR_API_KEY> \
java -javaagent:path/to/your/dd-trace-java-jar/dd-java-agent-SNAPSHOT.jar \
-Ddd.service=my-app -Ddd.llmobs.enabled=true -Ddd.llmobs.ml.app=my-ml-app -jar path/to/your/app.jar

Variables d’environnement et propriétés système

Vous pouvez fournir les paramètres suivants en tant que variables d’environnement (par exemple, DD_LLMOBS_ENABLED) ou en tant que propriétés système Java (par exemple, dd.llmobs_enabled).

DD_SITE ou dd.site
requis - _ chaîne _
Site de destination Datadog pour la soumission de données LLM. Votre site est .
DD_LLMOBS_ENABLED ou dd.llmobs.enabled
requis - _ entier ou chaîne _
Basculer pour activer la soumission des données à LLM Observability. Doit être défini sur 1 ou true.
DD_LLMOBS_ML_APP ou dd.llmobs.ml.app
optionnel - _ chaîne _
Le nom de votre application LLM, service ou projet, sous lequel toutes les traces et spans sont regroupés. Cela aide à distinguer entre différentes applications ou expériences. Voir les directives de nommage des applications pour les caractères autorisés et d’autres contraintes. Pour remplacer cette valeur pour un span racine donné, voir Tracer plusieurs applications. Si non fourni, cela par défaut à la valeur de DD_SERVICE, ou la valeur d’un DD_LLMOBS_ML_APP propagé d’un service en amont.
Remarque: Avant la version 1.54.0 de dd-trace-java, ceci est un champ requis.
DD_LLMOBS_AGENTLESS_ENABLED ou dd.llmobs.agentless.enabled
optionnel - entier ou chaîne - par défaut: false
Uniquement requis si vous n’utilisez pas l’Agent Datadog, auquel cas cela doit être défini sur 1 ou true.
DD_API_KEY ou dd.api.key
optionnel - _ chaîne _
Votre clé API Datadog. Uniquement requis si vous n’utilisez pas l’Agent Datadog.

Au lieu d’utiliser la configuration en ligne de commande, vous pouvez également activer LLM Observability par programmation.

Utilisez la LLMObs.enable()fonction pour activer LLM Observability.

Ne pas utiliser cette méthode de configuration avec le ddtrace-run commande.
from ddtrace.llmobs import LLMObs
LLMObs.enable(
  ml_app="<YOUR_ML_APP_NAME>",
  api_key="<YOUR_DATADOG_API_KEY>",
  site="<YOUR_DATADOG_SITE>",
  agentless_enabled=True,
)
Paramètres
ml_app
optionnel - chaîne
Le nom de votre application LLM, service ou projet, sous lequel toutes les traces et spans sont regroupés. Cela aide à distinguer entre différentes applications ou expériences. Voir les directives de nommage des applications pour les caractères autorisés et d’autres contraintes. Pour remplacer cette valeur pour une trace donnée, voir Tracer plusieurs applications. Si non fourni, ce paramètre prend par défaut la valeur de DD_LLMOBS_ML_APP.
integrations_enabled - par défaut: true
optionnel - booléen
Un indicateur pour activer le traçage automatique des appels LLM pour les intégrations LLM prises en charge par Datadog. Si non fourni, toutes les intégrations LLM prises en charge sont activées par défaut. Pour éviter d’utiliser les intégrations LLM, définissez cette valeur sur false.
agentless_enabled
optionnel - booléen - par défaut: false
Uniquement requis si vous n’utilisez pas l’Agent Datadog, auquel cas cela doit être défini sur True. Cela configure la bibliothèque ddtrace pour ne pas envoyer de données nécessitant l’Agent Datadog. Si non fourni, ce paramètre prend par défaut la valeur de DD_LLMOBS_AGENTLESS_ENABLED.
site
optionnel - chaîne
Le site Datadog pour soumettre vos données LLM. Votre site est Si non fourni, ce paramètre prend par défaut la valeur de DD_SITE.
api_key
optionnel - chaîne
Votre clé API Datadog. Uniquement requis si vous n’utilisez pas l’Agent Datadog. Si non fourni, ce paramètre prend par défaut la valeur de DD_API_KEY.
env
optionnel - chaîne
Le nom de l’environnement de votre application (exemples: prod, pre-prod, staging). Si non fourni, ce paramètre prend par défaut la valeur de DD_ENV.
service
optionnel - chaîne
Le nom du service utilisé pour votre application. Si non fourni, ce paramètre prend par défaut la valeur de DD_SERVICE.
Ne pas utiliser cette méthode de configuration avec le dd-trace/initialize.mjs commande.

Utilisez la init()fonction pour activer LLM Observability.

const tracer = require('dd-trace').init({
  llmobs: {
    mlApp: "<YOUR_ML_APP_NAME>",
    agentlessEnabled: true,
  },
  site: "<YOUR_DATADOG_SITE>",
  env: "<YOUR_ENV>",
});

const llmobs = tracer.llmobs;

Options pour la configuration de llmobs

mlApp
optionnel - chaîne
Le nom de votre application LLM, service ou projet, sous lequel toutes les traces et spans sont regroupés. Cela aide à distinguer entre différentes applications ou expériences. Voir Directives de nommage des applications pour les caractères autorisés et autres contraintes. Pour remplacer cette valeur pour une trace donnée, consultez Traçage de plusieurs applications. Si non fourni, cela prend par défaut la valeur de DD_LLMOBS_ML_APP.
agentlessEnabled
optionnel - booléen - par défaut: false
Uniquement requis si vous n’utilisez pas l’Agent Datadog, auquel cas cela doit être défini sur true. Cela configure la bibliothèque dd-trace pour ne pas envoyer de données nécessitant l’Agent Datadog. Si non fourni, cela prend par défaut la valeur de DD_LLMOBS_AGENTLESS_ENABLED.

Options pour la configuration générale du traceur :

site
optionnel - chaîne
Le site Datadog pour soumettre vos données LLM. Votre site est . Si non fourni, cela prend par défaut la valeur de DD_SITE.
env
optionnel - chaîne
Le nom de l’environnement de votre application (exemples: prod, pre-prod, staging). Si non fourni, cela prend par défaut la valeur de DD_ENV.
service
optionnel - chaîne
Le nom du service utilisé pour votre application. Si non fourni, cela prend par défaut la valeur de DD_SERVICE.
Variables d’environnement

Définissez les valeurs suivantes comme variables d’environnement. Elles ne peuvent pas être configurées par programme.

DD_API_KEY
optionnel - chaîne
Votre clé API Datadog. Seulement requis si vous n’utilisez pas l’Agent Datadog.

Pour instrumenter une fonction AWS Lambda existante avec LLM Observabilité, vous pouvez utiliser l’Extension Datadog et les couches de langage respectives.

  1. Ouvrez un Cloudshell dans la console AWS.
  2. Installez le client Datadog CLI
npm install -g @datadog/datadog-ci
  1. Définissez la clé API Datadog et le site
export DD_API_KEY=<YOUR_DATADOG_API_KEY>
export DD_SITE=<YOUR_DATADOG_SITE>

Si vous avez déjà ou préférez utiliser un secret dans Secrets Manager, vous pouvez définir la clé API en utilisant l’ARN du secret :

export DATADOG_API_KEY_SECRET_ARN=<DATADOG_API_KEY_SECRET_ARN>
  1. Installez votre fonction Lambda avec LLM Observabilité (cela nécessite au moins la version 77 de la couche d’Extension Datadog)
datadog-ci lambda instrument -f <YOUR_LAMBDA_FUNCTION_NAME> -r <AWS_REGION> -v 127 -e 99 --llmobs <YOUR_LLMOBS_ML_APP>
datadog-ci lambda instrument -f <YOUR_LAMBDA_FUNCTION_NAME> -r <AWS_REGION> -v 142 -e 99 --llmobs <YOUR_LLMOBS_ML_APP>
datadog-ci lambda instrument -f <YOUR_LAMBDA_FUNCTION_NAME> -r <AWS_REGION> -v 27 -e 99 --llmobs <YOUR_LLMOBS_ML_APP>
  1. Invoquez votre fonction Lambda et vérifiez que les traces d’Observabilité LLM sont visibles dans l’interface utilisateur Datadog.

Videz manuellement les traces LLM Observability en utilisant la méthode flush avant que la fonction Lambda ne renvoie.

from ddtrace.llmobs import LLMObs
def handler():
  # function body
  LLMObs.flush()
import tracer from 'dd-trace';
const llmobs = tracer.llmobs;

export const handler = async (event) => {
  // your function body
  llmobs.flush();
};

Après avoir installé le SDK et exécuté votre application, vous devriez vous attendre à voir des données dans LLM Observability grâce à l’auto-instrumentation. L’instrumentation manuelle peut être utilisée pour capturer des frameworks ou des opérations personnalisés provenant de bibliothèques qui ne sont pas encore prises en charge.

Instrumentation manuelle

Pour capturer une opération LLM, un décorateur de fonction peut être utilisé pour instrumenter facilement les flux de travail :

from ddtrace.llmobs.decorators import workflow

@workflow
def handle_user_request():
    ...

ou une approche basée sur un gestionnaire de contexte pour capturer des opérations détaillées :

from ddtrace.llmobs import LLMObs

with LLMObs.llm(model="gpt-4o"):
    call_llm()
    LLMObs.annotate(
        metrics={
            "input_tokens": ...,
            "output_tokens": ...,
        },
    )

Pour une liste des types de span disponibles, consultez la documentation des types de span. Pour un traçage plus granulaire des opérations au sein des fonctions, consultez Traçage des spans en utilisant des méthodes en ligne.

Pour tracer un span, utilisez llmobs.wrap(options, function) comme un wrapper de fonction pour la fonction que vous souhaitez tracer. Pour une liste des types de span disponibles, consultez la documentation des types de span. Pour un traçage plus granulaire des opérations au sein des fonctions, consultez Traçage des spans en utilisant des méthodes en ligne.

Types de span

Les types de span sont requis et sont spécifiés sur l’objet options passé aux fonctions de traçage llmobs (trace, wrap et decorate). Consultez la documentation des types de span pour une liste des types de span pris en charge.

Remarque : Les spans avec un type de span invalide ne sont pas soumis à LLM Observability.

Capture automatique des arguments/résultats/noms de fonction

llmobs.wrap (avec llmobs.decorate pour TypeScript) essaie de capturer automatiquement les entrées, les sorties et le nom de la fonction en cours de traçage. Si vous devez annoter manuellement un span, consultez Enrichir les spans. Les entrées et sorties que vous annotez remplaceront la capture automatique. De plus, pour remplacer le nom de la fonction, passez la propriété name sur l’objet options à la fonction llmobs.wrap :

function processMessage () {
  ... // user application logic
  return
}
processMessage = llmobs.wrap({ kind: 'workflow', name: 'differentFunctionName' }, processMessage)

Conditions pour terminer un span pour une fonction enveloppée

llmobs.wrap étend le comportement sous-jacent de tracer.wrap. Le span sous-jacent créé lorsque la fonction est appelée se termine dans les conditions suivantes :

  • Si la fonction retourne une promesse, alors le span se termine lorsque la promesse est résolue ou rejetée.
  • Si la fonction prend un rappel comme dernier paramètre, alors le span se termine lorsque ce rappel est appelé.
  • Si la fonction n’accepte pas de rappel et ne retourne pas de promesse, alors le span se termine à la fin de l’exécution de la fonction.

L’exemple suivant illustre la deuxième condition, où le dernier argument est un rappel :

Exemple

const express = require('express')
const app = express()

function myAgentMiddleware (req, res, next) {
  const err = ... // user application logic
  // the span for this function is finished when `next` is called
  next(err)
}
myAgentMiddleware = llmobs.wrap({ kind: 'agent' }, myAgentMiddleware)

app.use(myAgentMiddleware)

Si l’application n’utilise pas la fonction de rappel, il est recommandé d’utiliser un bloc tracé en ligne à la place. Voir Traçage des spans en utilisant des méthodes en ligne pour plus d’informations.

const express = require('express')
const app = express()

function myAgentMiddleware (req, res) {
  // the `next` callback is not being used here
  return llmobs.trace({ kind: 'agent', name: 'myAgentMiddleware' }, () => {
    return res.status(200).send('Hello World!')
  })
}

app.use(myAgentMiddleware)

Démarrer un span

Il existe plusieurs méthodes pour démarrer un span, en fonction du type de span que vous démarrez. Consultez la documentation des types de span pour une liste des types de span pris en charge.

Tous les spans sont démarrés en tant qu’instance d’objet de LLMObsSpan. Chaque span a des méthodes que vous pouvez utiliser pour interagir avec le span et enregistrer des données.

Terminer un span

Les spans doivent être terminés pour que la trace soit soumise et visible dans l’application Datadog.

Pour terminer un span, appelez finish() sur une instance d’objet span. Si possible, enveloppez le span dans un bloc try/finally pour garantir que le span est soumis même si une exception se produit.

Exemple

    try {
        LLMObsSpan workflowSpan = LLMObs.startWorkflowSpan("my-workflow-span-name", "ml-app-override", "session-141");
        // user logic
        // interact with started span
    } finally {
      workflowSpan.finish();
    }

Appels LLM

Si vous utilisez des fournisseurs ou des frameworks LLM pris en charge par les intégrations LLM de Datadog, vous n'avez pas besoin de démarrer manuellement un span LLM pour tracer ces opérations.
Si vous instrumentez manuellement un span LLM, vous devez enregistrer le décompte des tokens (comme input_tokens, output_tokens, et total_tokens) vous-même en annotant le span. Voir Enrichir les spans pour plus d'informations.

Pour tracer un appel LLM, utilisez le décorateur de fonction ddtrace.llmobs.decorators.llm().

model_name
requis - _ chaîne_
Le nom du LLM invoqué.
name
optionnel - _ chaîne_
Le nom de l’opération. Si non fourni, name par défaut au nom de la fonction tracée.
model_provider
optionnel - _ chaîne_ - par défaut: "custom"
Le nom du fournisseur de modèle.
Remarque: Pour afficher le coût estimé en dollars américains, définissez model_provider sur l’une des valeurs suivantes : openai, azure_openai ou anthropic.
session_id
optionnel - chaîne
L’ID de la session utilisateur sous-jacente. Voir Suivi des sessions utilisateur pour plus d’informations.
ml_app
optionnel - chaîne
Le nom de l’application ML à laquelle l’opération appartient. Voir Traçage de plusieurs applications pour plus d’informations.

Exemple

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs.decorators import llm

@llm(model_name="claude", name="invoke_llm", model_provider="anthropic")
def llm_call(prompt):
    completion = ... # user application logic to invoke LLM
    LLMObs.annotate(
        input_data=[{"role": "user", "content": prompt}],
        output_data=[{"role": "assistant", "content": completion}],
        metrics={"input_tokens": 4, "output_tokens": 6, "total_tokens": 10},
    )
    return completion

Pour tracer un appel LLM, spécifiez le type de span comme llm et, le cas échéant, les arguments suivants sur l’objet options.

modelName
optionnel - _ chaîne_ - par défaut: "custom"
Le nom du LLM invoqué.
name
optionnel - _ chaîne _
Le nom de l’opération. Si non fourni, name prend par défaut le nom de la fonction tracée.
modelProvider
optionnel - chaîne - par défaut: "custom"
Le nom du fournisseur de modèle.
Remarque : Pour afficher le coût estimé en dollars américains, définissez modelProvider sur l’une des valeurs suivantes : openai, azure_openai ou anthropic.
sessionId
optionnel - chaîne
L’ID de la session utilisateur sous-jacente. Voir Suivi des sessions utilisateur pour plus d’informations.
mlApp
optionnel - chaîne
Le nom de l’application ML à laquelle l’opération appartient. Voir Traçage de plusieurs applications pour plus d’informations.

Exemple

function llmCall (prompt) {
  const completion = ... // user application logic to invoke LLM
  llmobs.annotate({
    inputData: [{ role: "user", content: prompt }],
    outputData: [{ role: "assistant", content: completion }],
    metrics: { input_tokens: 4, output_tokens: 6, total_tokens: 10 }
  })
  return completion
}
llmCall = llmobs.wrap({ kind: 'llm', name: 'invokeLLM', modelName: 'claude', modelProvider: 'anthropic' }, llmCall)

Pour tracer un appel LLM, importez et appelez la méthode suivante avec les arguments énumérés ci-dessous :

import datadog.trace.api.llmobs.LLMObs;
LLMObs.startLLMSpan(spanName, modelName, modelProvider, mlApp, sessionID);
spanName
optionnel - Chaîne
Le nom de l’opération. Si non fourni, spanName prend par défaut le type de portée.
modelName
optionnel - Chaîne - par défaut: "custom"
Le nom du LLM invoqué.
modelProvider
optionnel - Chaîne - par défaut: "custom"
Le nom du fournisseur de modèle.
Remarque : Pour afficher le coût estimé en dollars américains, définissez modelProvider sur l’une des valeurs suivantes : openai, azure_openai ou anthropic.
mlApp
optionnel - Chaîne
Le nom de l’application ML à laquelle l’opération appartient. Fournir une valeur non nulle remplace le nom de l’application ML fourni au début de l’application. Voir Suivi des sessions utilisateur pour plus d’informations.
sessionId
optionnel - Chaîne
L’ID de la session utilisateur sous-jacente. Voir Suivi des sessions utilisateur pour plus d’informations.

Exemple

import datadog.trace.api.llmobs.LLMObs;

public class MyJavaClass {
  public String invokeModel() {
    LLMObsSpan llmSpan = LLMObs.startLLMSpan("my-llm-span-name", "my-llm-model", "my-company", "maybe-ml-app-override", "session-141");
    String inference = ... // user application logic to invoke LLM
    llmSpan.annotateIO(...); // record the input and output
    llmSpan.setMetrics(Map.of(
      "input_tokens", 617,
      "output_tokens", 338,
      "total_tokens", 955
    ));
    llmSpan.finish();
    return inference;
  }
}

Flux de travail

Pour tracer un intervalle de flux de travail, utilisez le décorateur de fonction ddtrace.llmobs.decorators.workflow().

name
optionnel - chaîne
Le nom de l’opération. Si non fourni, name prend par défaut le nom de la fonction tracée.
session_id
optionnel - chaîne
L’ID de la session utilisateur sous-jacente. Voir Suivi des sessions utilisateur pour plus d’informations.
ml_app
optionnel - chaîne
Le nom de l’application ML à laquelle l’opération appartient. Voir Traçage de plusieurs applications pour plus d’informations.

Exemple

from ddtrace.llmobs.decorators import workflow

@workflow
def process_message():
    ... # user application logic
    return

Pour tracer un intervalle de flux de travail, spécifiez le type d’intervalle comme workflow, et spécifiez éventuellement des arguments sur l’objet options.

name
optionnel - chaîne
Le nom de l’opération. Si non fourni, name prend par défaut le nom de la fonction tracée.
sessionId
optionnel - chaîne
L’ID de la session utilisateur sous-jacente. Voir Suivre les sessions utilisateur pour plus d’informations.
mlApp
optionnel - chaîne
Le nom de l’application ML à laquelle l’opération appartient. Voir Tracer plusieurs applications pour plus d’informations.

Exemple

function processMessage () {
  ... // user application logic
  return
}
processMessage = llmobs.wrap({ kind: 'workflow' }, processMessage)

Pour tracer un intervalle de flux de travail, importez et appelez la méthode suivante avec les arguments énumérés ci-dessous :

import datadog.trace.api.llmobs.LLMObs;
LLMObs.startWorkflowSpan(spanName, mlApp, sessionID);
spanName
optionnel - Chaîne
Le nom de l’opération. Si non fourni, spanName prend par défaut le type de portée.
mlApp
optionnel - Chaîne
Le nom de l’application ML à laquelle l’opération appartient. Fournir une valeur non nulle remplace le nom de l’application ML fourni au début de l’application. Voir Tracer plusieurs applications pour plus d’informations.
sessionId
optionnel - Chaîne
L’ID de la session utilisateur sous-jacente. Voir Suivi des sessions utilisateur pour plus d’informations.

Exemple

import datadog.trace.api.llmobs.LLMObs;

public class MyJavaClass {
  public String executeWorkflow() {
    LLMObsSpan workflowSpan = LLMObs.startWorkflowSpan("my-workflow-span-name", null, "session-141");
    String workflowResult = workflowFn(); // user application logic
    workflowSpan.annotateIO(...); // record the input and output
    workflowSpan.finish();
    return workflowResult;
  }
}

Agents

Pour tracer l’exécution d’un agent, utilisez le décorateur de fonction ddtrace.llmobs.decorators.agent().

name
optionnel - chaîne
Le nom de l’opération. Si non fourni, name prend par défaut le nom de la fonction tracée.
session_id
optionnel - chaîne
L’ID de la session utilisateur sous-jacente. Voir Suivre les sessions utilisateur pour plus d’informations.
ml_app
optionnel - chaîne
Le nom de l’application ML à laquelle l’opération appartient. Voir Tracer plusieurs applications pour plus d’informations.

Exemple

from ddtrace.llmobs.decorators import agent

@agent
def react_agent():
    ... # user application logic
    return

Pour tracer l’exécution d’un agent, spécifiez le type de portée comme agent, et spécifiez éventuellement des arguments dans l’objet d’options.

name
optionnel - chaîne
Le nom de l’opération. Si non fourni, name prend par défaut le nom de la fonction tracée.
sessionId
optionnel - chaîne
L’ID de la session utilisateur sous-jacente. Voir Suivre les sessions utilisateur pour plus d’informations.
mlApp
optionnel - chaîne
Le nom de l’application ML à laquelle l’opération appartient. Voir Tracer plusieurs applications pour plus d’informations.

Exemple

function reactAgent () {
  ... // user application logic
  return
}
reactAgent = llmobs.wrap({ kind: 'agent' }, reactAgent)

Pour tracer l’exécution d’un agent, importez et appelez la méthode suivante avec les arguments énumérés ci-dessous.

import datadog.trace.api.llmobs.LLMObs;
LLMObs.startAgentSpan(spanName, mlApp, sessionID);
spanName
optionnel - Chaîne
Le nom de l’opération. Si non fourni, spanName prend par défaut le nom de la fonction tracée.
mlApp
optionnel - Chaîne
Le nom de l’application ML à laquelle l’opération appartient. Fournir une valeur non nulle remplace le nom de l’application ML fourni au début de l’application. Voir Tracer plusieurs applications pour plus d’informations.
sessionId
optionnel - Chaîne
L’ID de la session utilisateur sous-jacente. Voir Suivi des sessions utilisateur pour plus d’informations.

Appels d’outils

Pour tracer un appel d’outil, utilisez le décorateur de fonction ddtrace.llmobs.decorators.tool().

name
optionnel - chaîne
Le nom de l’opération. Si non fourni, name prend par défaut le nom de la fonction tracée.
session_id
optionnel - chaîne
L’ID de la session utilisateur sous-jacente. Voir Suivi des sessions utilisateur pour plus d’informations.
ml_app
optionnel - chaîne
Le nom de l’application ML à laquelle l’opération appartient. Voir Tracer plusieurs applications pour plus d’informations.

Exemple

from ddtrace.llmobs.decorators import tool

@tool
def call_weather_api():
    ... # user application logic
    return

Pour tracer un appel d’outil, spécifiez le type de portée comme tool, et spécifiez éventuellement des arguments dans l’objet d’options.

name
optionnel - chaîne
Le nom de l’opération. Si non fourni, name prend par défaut le nom de la fonction tracée.
sessionId
optionnel - chaîne
L’ID de la session utilisateur sous-jacente. Voir Suivi des sessions utilisateur pour plus d’informations.
mlApp
optionnel - chaîne
Le nom de l’application ML à laquelle l’opération appartient. Voir Tracer plusieurs applications pour plus d’informations.

Exemple

function callWeatherApi () {
  ... // user application logic
  return
}
callWeatherApi = llmobs.wrap({ kind: 'tool' }, callWeatherApi)

Pour tracer un appel d’outil, importez et appelez la méthode suivante avec les arguments énumérés ci-dessous :

import datadog.trace.api.llmobs.LLMObs;
LLMObs.startToolSpan(spanName, mlApp, sessionID);
spanName
optionnel - Chaîne
Le nom de l’opération. Si non fourni, spanName prend par défaut le nom de la fonction tracée.
mlApp
optionnel - Chaîne
Le nom de l’application ML à laquelle l’opération appartient. Fournir une valeur non nulle remplace le nom de l’application ML fourni au début de l’application. Voir Tracer plusieurs applications pour plus d’informations.
sessionId
optionnel - Chaîne
L’ID de la session utilisateur sous-jacente. Voir Suivi des sessions utilisateur pour plus d’informations.

Tâches

Pour tracer une portée de tâche, utilisez le décorateur de fonction LLMObs.task().

name
optionnel - chaîne
Le nom de l’opération. Si non fourni, name par défaut au nom de la fonction tracée.
session_id
optionnel - chaîne
L’ID de la session utilisateur sous-jacente. Voir Suivre les sessions utilisateur pour plus d’informations.
ml_app
optionnel - chaîne
Le nom de l’application ML à laquelle l’opération appartient. Voir Tracer plusieurs applications pour plus d’informations.

Exemple

from ddtrace.llmobs.decorators import task

@task
def sanitize_input():
    ... # user application logic
    return

Pour tracer une portée de tâche, spécifiez le type de portée comme task, et spécifiez éventuellement des arguments dans l’objet options.

name
optionnel - chaîne
Le nom de l’opération. Si non fourni, name est défini sur le nom de la fonction tracée.
sessionId
optionnel - chaîne
L’ID de la session utilisateur sous-jacente. Voir Suivi des sessions utilisateur pour plus d’informations.
mlApp
optionnel - chaîne
Le nom de l’application ML à laquelle l’opération appartient. Voir Traçage de plusieurs applications pour plus d’informations.

Exemple

function sanitizeInput () {
  ... // user application logic
  return
}
sanitizeInput = llmobs.wrap({ kind: 'task' }, sanitizeInput)

Pour tracer une portée de tâche, importez et appelez la méthode suivante avec les arguments énumérés ci-dessous :

import datadog.trace.api.llmobs.LLMObs;
LLMObs.startTaskSpan(spanName, mlApp, sessionID);
spanName
optionnel - chaîne
Le nom de l’opération. Si non fourni, spanName est défini sur le nom de la fonction tracée.
mlApp
optionnel - chaîne
Le nom de l’application ML à laquelle l’opération appartient. Fournir une valeur non nulle remplace le nom de l’application ML fourni au début de l’application. Voir Traçage de plusieurs applications pour plus d’informations.
sessionId
optionnel - chaîne
L’ID de la session utilisateur sous-jacente. Voir Suivi des sessions utilisateur pour plus d’informations.

Représentations vectorielles

Pour tracer une opération de représentation vectorielle, utilisez le décorateur de fonction LLMObs.embedding().

Remarque : Annoter l’entrée d’une portée de représentation vectorielle nécessite un formatage différent de celui des autres types de portée. Voir Enrichir les portées pour plus de détails sur la façon de spécifier les entrées de représentation vectorielle.

model_name
requis - chaîne
Le nom du LLM invoqué.
name
optionnel - chaîne
Le nom de l’opération. Si non fourni, name est défini sur le nom de la fonction tracée.
model_provider
optionnel - chaîne - par défaut: "custom"
session_id
optionnel - chaîne
L’ID de la session utilisateur sous-jacente. Voir Suivi des sessions utilisateur pour plus d’informations.
ml_app
optionnel - chaîne
Le nom de l’application ML à laquelle l’opération appartient. Voir Traçage de plusieurs applications pour plus d’informations.

Exemple

from ddtrace.llmobs.decorators import embedding

@embedding(model_name="text-embedding-3", model_provider="openai")
def perform_embedding():
    ... # user application logic
    return

Pour tracer une opération de représentation vectorielle, spécifiez le type de portée comme embedding, et spécifiez éventuellement des arguments dans l’objet options.

Remarque : Annoter l’entrée d’une portée de représentation vectorielle nécessite un formatage différent de celui des autres types de portée. Voir Enrichir les spans pour plus de détails sur la façon de spécifier les entrées de représentation vectorielle.

modelName
optionnel - chaîne - par défaut: "custom"
Le nom du LLM invoqué.
name
optionnel - chaîne
Le nom de l’opération. Si non fourni, name est défini sur le nom de la fonction tracée.
modelProvider
optionnel - chaîne - par défaut: "custom"
Le nom du fournisseur de modèle.
sessionId
optionnel - chaîne
L’ID de la session utilisateur sous-jacente. Voir Suivi des sessions utilisateur pour plus d’informations.
mlApp
optionnel - chaîne
Le nom de l’application ML à laquelle l’opération appartient. Voir Traçage de plusieurs applications pour plus d’informations.

Exemple

function performEmbedding () {
  ... // user application logic
  return
}
performEmbedding = llmobs.wrap({ kind: 'embedding', modelName: 'text-embedding-3', modelProvider: 'openai' }, performEmbedding)

Récupérations

Pour tracer une portée de récupération, utilisez le décorateur de fonction ddtrace.llmobs.decorators.retrieval().

Remarque : Annoter la sortie d’une portée de récupération nécessite un formatage différent de celui des autres types de portée. Voir Enrichissement des spans pour plus de détails sur la façon de spécifier les sorties de récupération.

name
optionnel - chaîne
Le nom de l’opération. Si non fourni, name est défini sur le nom de la fonction tracée.
session_id
optionnel - chaîne
L’ID de la session utilisateur sous-jacente. Voir Suivi des sessions utilisateur pour plus d’informations.
ml_app
optionnel - chaîne
Le nom de l’application ML à laquelle l’opération appartient. Voir Traçage de plusieurs applications pour plus d’informations.

Exemple

from ddtrace.llmobs.decorators import retrieval

@retrieval
def get_relevant_docs(question):
    context_documents = ... # user application logic
    LLMObs.annotate(
        input_data=question,
        output_data = [
            {"id": doc.id, "score": doc.score, "text": doc.text, "name": doc.name} for doc in context_documents
        ]
    )
    return

Pour tracer une portée de récupération, spécifiez le type de portée comme retrieval, et spécifiez éventuellement les arguments suivants dans l’objet options.

Remarque : Annoter la sortie d’une portée de récupération nécessite un formatage différent de celui des autres types de portée. Voir Enrichissement des spans pour plus de détails sur la façon de spécifier les sorties de récupération.

name
optionnel - chaîne
Le nom de l’opération. Si non fourni, name est défini sur le nom de la fonction tracée.
sessionId
optionnel - chaîne
L’ID de la session utilisateur sous-jacente. Voir Suivi des sessions utilisateur pour plus d’informations.
mlApp
optionnel - chaîne
Le nom de l’application ML à laquelle l’opération appartient. Voir Traçage de plusieurs applications pour plus d’informations.

Exemple

Ce qui suit inclut également un exemple d’annotation d’un span. Voir Enrichir les spans pour plus d’informations.

function getRelevantDocs (question) {
  const contextDocuments = ... // user application logic
  llmobs.annotate({
    inputData: question,
    outputData: contextDocuments.map(doc => ({
      id: doc.id,
      score: doc.score,
      text: doc.text,
      name: doc.name
    }))
  })
  return
}
getRelevantDocs = llmobs.wrap({ kind: 'retrieval' }, getRelevantDocs)

Imbrication des spans

Commencer un nouveau span avant que le span actuel ne soit terminé trace automatiquement une relation parent-enfant entre les deux spans. Le span parent représente l’opération plus grande, tandis que le span enfant représente une sous-opération imbriquée plus petite.

from ddtrace.llmobs.decorators import task, workflow

@workflow
def extract_data(document):
    preprocess_document(document)
    ... # performs data extraction on the document
    return

@task
def preprocess_document(document):
    ... # preprocesses a document for data extraction
    return
function preprocessDocument (document) {
  ... // preprocesses a document for data extraction
  return
}
preprocessDocument = llmobs.wrap({ kind: 'task' }, preprocessDocument)

function extractData (document) {
  preprocessDocument(document)
  ... // performs data extraction on the document
  return
}
extractData = llmobs.wrap({ kind: 'workflow' }, extractData)
import datadog.trace.api.llmobs.LLMObs;
import datadog.trace.api.llmobs.LLMObsSpan;

public class MyJavaClass {
  public void preprocessDocument(String document) {
  LLMObsSpan taskSpan = LLMObs.startTaskSpan("preprocessDocument", null, "session-141");
   ...   // preprocess document for data extraction
   taskSpan.annotateIO(...); // record the input and output
   taskSpan.finish();
  }

  public String extractData(String document) {
    LLMObsSpan workflowSpan = LLMObs.startWorkflowSpan("extractData", null, "session-141");
    preprocessDocument(document);
    ... // perform data extraction on the document
    workflowSpan.annotateIO(...); // record the input and output
    workflowSpan.finish();
  }
}

Enrichir les spans

Le metrics paramètre ici fait référence aux valeurs numériques attachées en tant qu'attributs sur des spans individuels — pas les métriques de la plateforme Datadog. Pour certaines clés reconnues telles que input_tokens, output_tokens, et total_tokens, Datadog utilise ces attributs de span pour générer des métriques de plateforme correspondantes (telles que ml_obs.span.llm.input.tokens) à utiliser dans les tableaux de bord et les moniteurs.

Le SDK fournit la méthode LLMObs.annotate() pour enrichir les spans avec des entrées, des sorties et des métadonnées.

La méthode LLMObs.annotate() accepte les arguments suivants :

span
optionnel - Span - par défaut: le span actif actuel
Le span à annoter. Si span n’est pas fourni (comme lors de l’utilisation de décorateurs de fonction), le SDK annotera le span actif actuel.
input_data
optionnel - type sérialisable en JSON ou liste de dictionnaires
Soit un type sérialisable en JSON (pour les spans non-LLM) ou une liste de dictionnaires avec ce format: {"content": "...", "role": "...", "tool_calls": ..., "tool_results": ...}"tool_calls" est une liste optionnelle de dictionnaires d’appels d’outils avec des clés requises : "name" et "arguments", ainsi que des clés optionnelles : "tool_id" et "type" ; et "tool_results" est une liste optionnelle de dictionnaires de résultats d’outils avec une clé requise : "result", ainsi que des clés optionnelles : "name", "tool_id" et "type" pour les scénarios d’appel de fonction. Remarque: Les portées de représentation vectorielle sont un cas spécial et nécessitent une chaîne ou un dictionnaire (ou une liste de dictionnaires) avec ce format : {"text": "..."}.
output_data
optionnel - type sérialisable en JSON ou liste de dictionnaires
Soit un type sérialisable en JSON (pour les spans non-LLM) ou une liste de dictionnaires avec ce format : {"content": "...", "role": "...", "tool_calls": ...}, où "tool_calls" est une liste optionnelle de dictionnaires d’appels d’outils avec des clés requises : "name", "arguments", et des clés optionnelles : "tool_id", "type" pour les scénarios d’appel de fonction. Remarque : Les spans de récupération sont un cas spécial et nécessitent une chaîne ou un dictionnaire (ou une liste de dictionnaires) avec ce format : {"text": "...", "name": "...", "score": float, "id": "..."}.
tool_definitions
optionnel - liste de dictionnaires
Liste des dictionnaires de définition d’outils pour les scénarios d’appel de fonction. Chaque définition d’outil doit avoir une clé "name": "..." requise et des clés "description": "..." et "schema": {...} optionnelles.
metadata
optionnel - dictionnaire
Un dictionnaire de paires clé-valeur sérialisables en JSON que les utilisateurs peuvent ajouter comme information de métadonnée pertinente à l’opération d’entrée ou de sortie décrite par le span (model_temperature, max_tokens, top_k, etc.).
metrics
optionnel - dictionnaire
Un dictionnaire de clés sérialisables en JSON et de valeurs numériques que les utilisateurs peuvent ajouter comme métriques pertinentes à l’opération décrite par le span (input_tokens, output_tokens, total_tokens, time_to_first_token, etc.). L’unité pour time_to_first_token est en secondes, similaire à la métrique duration qui est émise par défaut.
tags
optionnel - dictionnaire
Un dictionnaire de paires clé-valeur sérialisables en JSON que les utilisateurs peuvent ajouter comme étiquettes sur le span. Exemples de clés : session, env, system et version. Pour plus d’informations sur les étiquettes, voir Commencer avec les étiquettes.

Exemple

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs.decorators import embedding, llm, retrieval, workflow

@llm(model_name="model_name", model_provider="model_provider")
def llm_call(prompt):
    resp = ... # llm call here
    LLMObs.annotate(
        span=None,
        input_data=[{"role": "user", "content": "Hello world!"}],
        output_data=[{"role": "assistant", "content": "How can I help?"}],
        metadata={"temperature": 0, "max_tokens": 200},
        metrics={"input_tokens": 4, "output_tokens": 6, "total_tokens": 10},
        tags={"host": "host_name"},
    )
    return resp

@workflow
def extract_data(document):
    resp = llm_call(document)
    LLMObs.annotate(
        input_data=document,
        output_data=resp,
        tags={"host": "host_name"},
    )
    return resp

@embedding(model_name="text-embedding-3", model_provider="openai")
def perform_embedding():
    ... # user application logic
    LLMObs.annotate(
        span=None,
        input_data={"text": "Hello world!"},
        output_data=[0.0023064255, -0.009327292, ...],
        metrics={"input_tokens": 4},
        tags={"host": "host_name"},
    )
    return

@retrieval(name="get_relevant_docs")
def similarity_search():
    ... # user application logic
    LLMObs.annotate(
        span=None,
        input_data="Hello world!",
        output_data=[{"text": "Hello world is ...", "name": "Hello, World! program", "id": "document_id", "score": 0.9893}],
        tags={"host": "host_name"},
    )
    return

Le SDK fournit la méthode llmobs.annotate() pour annoter les spans avec des entrées, des sorties et des métadonnées.

La méthode LLMObs.annotate() accepte les arguments suivants :

span
optionnel - Span - par défaut: le span actif actuel
Le span à annoter. Si span n’est pas fourni (comme lors de l’utilisation de wrappers de fonction), le SDK annote le span actif actuel.
annotationOptions
requis - objet
Un objet de différents types de données pour annoter le span.

L’objet annotationOptions peut contenir les éléments suivants :

inputData
optionnel - type sérialisable en JSON ou liste d’objets
Soit un type sérialisable en JSON (pour les spans non-LLM) ou une liste de dictionnaires avec ce format: {role: "...", contenu: "..."} (pour les spans LLM). Remarque : Les spans d’incorporation sont un cas particulier et nécessitent une chaîne ou un objet (ou une liste d’objets) avec ce format : {text: "..."}.
outputData
optionnel - type sérialisable en JSON ou liste d’objets
Soit un type sérialisable en JSON (pour les spans non-LLM) ou une liste d’objets avec ce format : {role: "...", content: "..."} (pour les spans LLM). Remarque : Les spans de récupération sont un cas particulier et nécessitent une chaîne ou un objet (ou une liste d’objets) avec ce format : {text: "...", name: "...", score: number, id: "..."}.
metadata
optionnel - objet
Un objet de paires clé-valeur sérialisables en JSON que les utilisateurs peuvent ajouter comme métadonnées pertinentes pour l’opération d’entrée ou de sortie décrite par le span (model_temperature, max_tokens, top_k, etc.).
metrics
optionnel - objet
Un objet de clés sérialisables en JSON et de valeurs numériques que les utilisateurs peuvent ajouter pour enregistrer des métriques pertinentes pour l’opération décrite par le span (input_tokens, output_tokens, total_tokens, etc.).
tags
optionnel - objet
Un objet de paires clé-valeur sérialisables en JSON que les utilisateurs peuvent ajouter comme étiquettes concernant le contexte du span (session, environment, system, versioning, etc.). Pour plus d’informations sur les étiquettes, voir Commencer avec les étiquettes.

Exemple

function llmCall (prompt) {
  const completion = ... // user application logic to invoke LLM
  llmobs.annotate({
    inputData: [{ role: "user", content: "Hello world!" }],
    outputData: [{ role: "assistant", content: "How can I help?" }],
    metadata: { temperature: 0, max_tokens: 200 },
    metrics: { input_tokens: 4, output_tokens: 6, total_tokens: 10 },
    tags: { host: "host_name" }
  })
  return completion
}
llmCall = llmobs.wrap({ kind:'llm', modelName: 'modelName', modelProvider: 'modelProvider' }, llmCall)

function extractData (document) {
  const resp = llmCall(document)
  llmobs.annotate({
    inputData: document,
    outputData: resp,
    tags: { host: "host_name" }
  })
  return resp
}
extractData = llmobs.wrap({ kind: 'workflow' }, extractData)

function performEmbedding () {
  ... // user application logic
  llmobs.annotate(
    undefined, { // this can be set to undefined or left out entirely
      inputData: { text: "Hello world!" },
      outputData: [0.0023064255, -0.009327292, ...],
      metrics: { input_tokens: 4 },
      tags: { host: "host_name" }
    }
  )
}
performEmbedding = llmobs.wrap({ kind: 'embedding', modelName: 'text-embedding-3', modelProvider: 'openai' }, performEmbedding)

function similaritySearch () {
  ... // user application logic
  llmobs.annotate(undefined, {
    inputData: "Hello world!",
    outputData: [{ text: "Hello world is ...", name: "Hello, World! program", id: "document_id", score: 0.9893 }],
    tags: { host: "host_name" }
  })
  return
}
similaritySearch = llmobs.wrap({ kind: 'retrieval', name: 'getRelevantDocs' }, similaritySearch)

Le SDK fournit plusieurs méthodes pour annoter les spans avec des entrées, des sorties, des métriques et des métadonnées.

Annoter les entrées et les sorties

Utilisez la méthode membre annotateIO() de l’interface LLMObsSpan pour ajouter des données d’entrée et de sortie structurées à un LLMObsSpan. Cela inclut des arguments optionnels et des objets de message LLM.

Arguments

Si un argument est nul ou vide, rien ne se passe. Par exemple, si inputData est une chaîne non vide tandis que outputData est nul, alors seul inputData est enregistré.

inputData
optionnel - Chaîne ou Liste<LLMObs.LLMMessage>
Soit une chaîne (pour les spans non-LLM) ou une liste de LLMObs.LLMMessages pour les spans LLM.
outputData
optionnel - Chaîne ou Liste<LLMObs.LLMMessage>
Soit une chaîne (pour les spans non-LLM) ou une liste de LLMObs.LLMMessages pour les spans LLM.

Messages LLM

Les spans LLM doivent être annotés avec des Messages LLM en utilisant l’objet LLMObs.LLMMessage.

L’objet LLMObs.LLMMessage peut être instancié en appelant LLMObs.LLMMessage.from() avec les arguments suivants :

role
requis - Chaîne
Une chaîne décrivant le rôle de l’auteur du message.
content
requis - Chaîne
Une chaîne contenant le contenu du message.

Exemple

import datadog.trace.api.llmobs.LLMObs;

public class MyJavaClass {
  public String invokeChat(String userInput) {
    LLMObsSpan llmSpan = LLMObs.startLLMSpan("my-llm-span-name", "my-llm-model", "my-company", "maybe-ml-app-override", "session-141");
    String systemMessage = "You are a helpful assistant";
    Response chatResponse = ... // user application logic to invoke LLM
    llmSpan.annotateIO(
      Arrays.asList(
        LLMObs.LLMMessage.from("user", userInput),
        LLMObs.LLMMessage.from("system", systemMessage)
      ),
      Arrays.asList(
        LLMObs.LLMMessage.from(chatResponse.role, chatResponse.content)
      )
    );
    llmSpan.finish();
    return chatResponse;
  }
}

Ajout de métriques

Ajout en masse de métriques

La méthode membre setMetrics() de l’interface LLMObsSpan accepte les arguments suivants pour attacher plusieurs métriques en masse :

Arguments
metrics
requis - Map<String, Number>
Une map de clés sérialisables en JSON et de valeurs numériques que les utilisateurs peuvent ajouter pour enregistrer des métriques pertinentes pour l’opération décrite par le span (par exemple, input_tokens, output_tokens ou total_tokens).

Ajouter une seule métrique

La méthode membre setMetric() de l’interface LLMObsSpan accepte les arguments suivants pour attacher une seule métrique :

Arguments
key
requis - CharSequence
Le nom de la métrique.
value
requis - int, long ou double
La valeur de la métrique.

Exemples

import datadog.trace.api.llmobs.LLMObs;

public class MyJavaClass {
  public String invokeChat(String userInput) {
    LLMObsSpan llmSpan = LLMObs.startLLMSpan("my-llm-span-name", "my-llm-model", "my-company", "maybe-ml-app-override", "session-141");
    String chatResponse = ... // user application logic to invoke LLM
    llmSpan.setMetrics(Map.of(
      "input_tokens", 617,
      "output_tokens", 338,
      "time_per_output_token", 0.1773
    ));
    llmSpan.setMetric("total_tokens", 955);
    llmSpan.setMetric("time_to_first_token", 0.23);
    llmSpan.finish();
    return chatResponse;
  }
}

Ajout d’étiquettes

Pour plus d’informations sur les étiquettes, voir Commencer avec les étiquettes.

Ajout en masse d’étiquettes

La méthode membre setTags() de l’interface LLMObsSpan accepte les arguments suivants pour attacher plusieurs étiquettes en masse :

Arguments
tags
requis - Map<String, Object>
Une map de paires clé-valeur sérialisables en JSON que les utilisateurs peuvent ajouter comme étiquettes pour décrire le contexte du span (par exemple, session, environment, system, ou version).

Ajouter une seule étiquette

La méthode membre setTag() de l’interface LLMObsSpan accepte les arguments suivants pour attacher une seule étiquette :

Arguments
key
requis - String
La clé de l’étiquette.
value
requis - int, long, double, boolean ou String
La valeur de l’étiquette.

Exemples

import datadog.trace.api.llmobs.LLMObs;

public class MyJavaClass {
  public String invokeChat(String userInput) {
    LLMObsSpan llmSpan = LLMObs.startLLMSpan("my-llm-span-name", "my-llm-model", "my-company", "maybe-ml-app-override", "session-141");
    String chatResponse = ... // user application logic to invoke LLM
    llmSpan.setTags(Map.of(
      "chat_source", "web",
      "users_in_chat", 3
    ));
    llmSpan.setTag("is_premium_user", true);
    llmSpan.finish();
    return chatResponse;
  }
}

Annotation des erreurs

La méthode membre addThrowable() de l’interface LLMObsSpan accepte l’argument suivant pour attacher un throwable avec une trace de pile :

Arguments
throwable
requis - Throwable
Le throwable ou l’exception qui s’est produite.

Ajout d’un message d’erreur

La méthode membre setErrorMessage() de l’interface LLMObsSpan accepte l’argument suivant pour attacher une chaîne d’erreur :

Arguments
errorMessage
requis - Chaîne
Le message de l’erreur.

Définir un indicateur d’erreur

La méthode membre setError() de l’interface LLMObsSpan accepte l’argument suivant pour indiquer une erreur avec l’opération :

Arguments
error
requis - booléen
true si le span a rencontré une erreur.

Exemples

import datadog.trace.api.llmobs.LLMObs;

public class MyJavaClass {
  public String invokeChat(String userInput) {
    LLMObsSpan llmSpan = LLMObs.startLLMSpan("my-llm-span-name", "my-llm-model", "my-company", "maybe-ml-app-override", "session-141");
    String chatResponse = "N/A";
    try {
      chatResponse = ... // user application logic to invoke LLM
    } catch (Exception e) {
      llmSpan.addThrowable(e);
      throw new RuntimeException(e);
    } finally {
      llmSpan.finish();
    }
    return chatResponse;
  }
}

Annotation des métadonnées

La méthode membre setMetadata() de l’interface LLMObsSpan accepte les arguments suivants :

metadata
requis - Map<String, Object>
Une map de paires clé-valeur sérialisables en JSON contenant des métadonnées pertinentes pour l’opération d’entrée ou de sortie décrite par le span.

Exemple

import datadog.trace.api.llmobs.LLMObs;

public class MyJavaClass {
  public String invokeChat(String userInput) {
    LLMObsSpan llmSpan = LLMObs.startLLMSpan("my-llm-span-name", "my-llm-model", "my-company", "maybe-ml-app-override", "session-141");
    llmSpan.setMetadata(
      Map.of(
        "temperature", 0.5,
        "is_premium_member", true,
        "class", "e1"
      )
    );
    String chatResponse = ... // user application logic to invoke LLM
    return chatResponse;
  }
}

Annotation des spans auto-instrumentés

La méthode LLMObs.annotation_context() du SDK renvoie un gestionnaire de contexte qui peut être utilisé pour modifier tous les spans auto-instrumentés démarrés pendant que le contexte d’annotation est actif.

La méthode LLMObs.annotation_context() accepte les arguments suivants :

name
optionnel - str
Nom qui remplace le nom du span pour tous les spans auto-instrumentés démarrés dans le contexte d’annotation.
prompt
optionnel - dictionnaire
Un dictionnaire qui représente l’invite utilisée pour un appel LLM. Consultez la documentation de l’objet Prompt pour le schéma complet et les clés prises en charge. Vous pouvez également importer l’Promptobjet depuis ddtrace.llmobs.utils et le passer en tant qu’argument prompt. Remarque: Cet argument ne s’applique qu’aux spans LLM.
tags
optionnel - dictionnaire
Un dictionnaire de paires clé-valeur sérialisables en JSON que les utilisateurs peuvent ajouter en tant qu’étiquettes sur le span. Clés d’exemple : session, env, system et version. Pour plus d’informations sur les étiquettes, consultez Commencer avec les étiquettes.

Exemple

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs.decorators import workflow

@workflow
def rag_workflow(user_question):
    context_str = retrieve_documents(user_question).join(" ")

    with LLMObs.annotation_context(
        prompt = Prompt(
            id="chatbot_prompt",
            version="1.0.0",
            template="Please answer the question using the provided context: {{question}}\n\nContext:\n{{context}}",
            variables={
                "question": user_question,
                "context": context_str,
            }
        ),
        tags = {
            "retrieval_strategy": "semantic_similarity"
        },
        name = "augmented_generation"
    ):
        completion = openai_client.chat.completions.create(...)
    return completion.choices[0].message.content

Le llmobs.annotationContext()SDK accepte une fonction de rappel qui peut être utilisée pour modifier tous les spans auto-instrumentés démarrés pendant la portée de la fonction de rappel.

La méthode llmobs.annotationContext() accepte les options suivantes en premier argument :

name
optionnel - _ str _
Nom qui remplace le nom du span pour tous les spans auto-instrumentés démarrés dans le contexte d’annotation.
tags
optionnel - objet
Un objet de paires clé-valeur sérialisables en JSON que les utilisateurs peuvent ajouter en tant qu’étiquettes sur le span. Clés d’exemple : session, env, system et version. Pour plus d’informations sur les étiquettes, consultez Commencer avec les étiquettes.

Exemple

const { llmobs } = require('dd-trace');

function ragWorkflow(userQuestion) {
    const contextStr = retrieveDocuments(userQuestion).join(" ");

    const completion = await llmobs.annotationContext({
      tags: {
        retrieval_strategy: "semantic_similarity"
      },
      name: "augmented_generation"
    }, async () => {
      const completion = await openai_client.chat.completions.create(...);
      return completion.choices[0].message.content;
    });
}

Suivi des prompts

Attachez des métadonnées de prompt structurées au span LLM afin de pouvoir reproduire les résultats, auditer les modifications et comparer les performances des prompts entre les versions. Lors de l’utilisation de modèles, l’observabilité LLM fournit également un suivi des versions basé sur les changements de contenu des modèles.

Utilisez LLMObs.annotation_context(prompt=...) pour attacher des métadonnées de prompt avant l’appel LLM. Pour plus de détails sur l’annotation des spans, consultez Enrichir les spans.

Arguments

prompt
requis - dictionnaire
Un dictionnaire typé qui suit le schéma du prompt ci-dessous.

Clés prises en charge :

  • id (str) : Identifiant logique pour ce prompt. Doit être unique par ml_app. Par défaut, {ml_app}-unnamed_prompt
  • version (str) : Étiquette de version pour le prompt (par exemple, “1.0.0”). Voir suivi des versions pour plus de détails.
  • variables (Dict[str, str]) : Variables utilisées pour remplir les espaces réservés du modèle.
  • template (str) : Chaîne de modèle avec espaces réservés (par exemple, "Traduire {{text}} en {{lang}}").
  • chat_template (List[Message]) : Forme de modèle multi-message. Fournir une liste d’objets { "role": "<role>", "content": "<template string with placeholders>" }.
  • tags (Dict[str, str]) : Étiquettes à attacher à l’exécution du prompt.
  • rag_context_variables (List[str]) : Clés de variables contenant le contenu de vérité de base/contexte. Utilisé pour détection d’hallucinations.
  • rag_query_variables (List[str]) : Clés de variables contenant la requête de l’utilisateur. Utilisé pour la détection d’hallucinations.

Exemple : prompt à modèle unique

from ddtrace.llmobs import LLMObs

def answer_question(text):
    # Attach prompt metadata to the upcoming LLM span using LLMObs.annotation_context()
    with LLMObs.annotation_context(prompt={
        "id": "translation-template",
        "version": "1.0.0",
        "chat_template": [{"role": "user", "content": "Translate to {{lang}}: {{text}}"}],
        "variables": {"lang": "fr", "text": text},
        "tags": {"team": "nlp"}
    }):
        # Example provider call (replace with your client)
        completion = openai_client.chat.completions.create(
            model="gpt-4o",
            messages=[{"role": "user", "content": f"Translate to fr: {text}"}]
        )
    return completion

Exemple : modèles de prompt LangChain

Lorsque vous utilisez le modèle de prompt de LangChain avec auto-instrumentation, assignez des modèles à des variables avec des noms significatifs. L’auto-instrumentation utilise ces noms pour identifier les prompts.

# "translation_template" will be used to identify the template in Datadog
translation_template = PromptTemplate.from_template("Translate {text} to {language}")
chain = translation_template | llm

Utilisez llmobs.annotationContext({ prompt: ... }, () => { ... }) pour attacher des métadonnées de prompt avant l’appel LLM. Pour plus de détails sur l’annotation des spans, consultez Enrichir les spans.

Arguments

prompt
requis - objet
Un objet qui suit le schéma du prompt ci-dessous.

Propriétés prises en charge :

  • id (chaîne) : Identifiant logique pour ce prompt. Doit être unique par ml_app. Par défaut, {ml_app}-unnamed_prompt
  • version (chaîne) : Étiquette de version pour le prompt (par exemple, “1.0.0”). Voir suivi des versions pour plus de détails.
  • variables (Enregistrement<string, chaîne>) : Variables utilisées pour remplir les espaces réservés du modèle.
  • template (chaîne | Liste) : Chaîne de modèle avec espaces réservés (par exemple, "Traduire {{text}} en {{lang}}"). Alternatively, a list of { "role": "<role>", "content": "<template string with placeholders>" } objects.
  • tags (Enregistrement<string, chaîne>) : Étiquettes à attacher à l’exécution du prompt.
  • contextVariables (chaîne[]) : Clés de variables contenant le contenu de vérité de base/contexte. Utilisé pour la détection d’hallucinations.
  • queryVariables (chaîne[]) : Clés de variables contenant la requête de l’utilisateur. Utilisé pour la détection d’hallucinations.

Exemple : prompt à modèle unique

const { llmobs } = require('dd-trace');

function answerQuestion(text) {
    // Attach prompt metadata to the upcoming LLM span using LLMObs.annotation_context()
    return llmobs.annotationContext({
      prompt: {
        id: "translation-template",
        version: "1.0.0",
        chat_template: [{"role": "user", "content": "Translate to {{lang}}: {{text}}"}],
        variables: {"lang": "fr", "text": text},
        tags: {"team": "nlp"}
      }
    }, () => {
      // Example provider call (replace with your client)
      return openaiClient.chat.completions.create({
          model: "gpt-4o",
          messages: [{"role": "user", "content": f"Translate to fr: {text}"}]
        });
    });
}

Notes

  • L’annotation d’un prompt n’est disponible que sur les spans LLM.
  • Placez l’annotation immédiatement avant l’appel du fournisseur afin qu’elle s’applique au bon span LLM.
  • Utilisez un prompt unique id pour distinguer différents prompts au sein de votre application.
  • Gardez les templates statiques en utilisant la syntaxe des placeholders (comme {{variable_name}}) and define dynamic content in the section des variables.
  • Pour plusieurs appels LLM auto-instrumentés dans un bloc, utilisez un contexte d’annotation pour appliquer les mêmes métadonnées de prompt à travers les appels. Voir Annotation des spans auto-instrumentés.

Suivi des versions

L’observabilité LLM fournit un versionnage automatique pour vos prompts lorsque aucune version explicite n’est spécifiée. Lorsque vous fournissez un template ou chat_template dans vos métadonnées de prompt sans un tag version, le système génère automatiquement une version en calculant un hachage du contenu du prompt. Si vous fournissez un tag version, l’observabilité LLM utilise votre étiquette de version spécifiée au lieu d’en générer une automatiquement.

Le système de versionnage fonctionne comme suit :

  • Versionnage automatique : Lorsque aucun tag version n’est fourni, l’observabilité LLM calcule un hachage du contenu template ou chat_template pour générer automatiquement un identifiant de version numérique.
  • Versionnage manuel : Lorsqu’un tag version est fourni, l’observabilité LLM utilise votre étiquette de version spécifiée exactement comme fournie.
  • Historique des versions : Les versions auto-générées et manuelles sont maintenues dans l’historique des versions pour suivre l’évolution des prompts au fil du temps.

Cela vous donne la flexibilité de vous fier à la gestion automatique des versions basée sur les changements de contenu du prompt, ou de maintenir un contrôle total sur le versionnage avec vos propres étiquettes de version.

Suivi des coûts

Attachez des métriques de tokens (pour le suivi automatique des coûts) ou des métriques de coûts (pour le suivi manuel des coûts) à vos spans LLM/embedding. Les métriques de tokens permettent à Datadog de calculer les coûts en utilisant les prix du fournisseur, tandis que les métriques de coûts vous permettent de fournir vos propres prix lors de l’utilisation de modèles personnalisés ou non pris en charge. Pour plus de détails, voir Coûts.

Si vous utilisez une instrumentation automatique, les métriques de tokens et de coûts apparaissent automatiquement sur vos spans. Si vous instrumentez manuellement, suivez les instructions ci-dessous.

Dans ce contexte, les "métriques de jetons" et les "métriques de coût" font référence à des paires clé-valeur numériques que vous attachez aux spans via le metrics paramètre de la LLMObs.annotate() méthode. Celles-ci sont distinctes des métriques d'observabilité LLM de la plateforme Datadog. Pour les clés reconnues telles que input_tokens, output_tokens, input_cost, et output_cost, Datadog utilise ces attributs de span pour générer des métriques de plateforme correspondantes (telles que ml_obs.span.llm.input.cost) à utiliser dans les tableaux de bord et les moniteurs.

Cas d’utilisation : Utilisation d’un fournisseur de modèle commun

Datadog prend en charge des fournisseurs de modèles communs tels qu’OpenAI, Azure OpenAI, Anthropic et Google Gemini. Lorsque vous utilisez ces fournisseurs, vous devez simplement annoter votre demande LLM avec model_name, model_provider et l’utilisation des jetons. Datadog calcule automatiquement le coût estimé en fonction des tarifs du fournisseur.

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs.decorators import llm

@llm(model_name="gpt-5.1", model_provider="openai")
def llm_call(prompt):
    resp = ... # llm call here
    # Annotate token metrics
    LLMObs.annotate(
        metrics={
          "input_tokens": 50,
          "output_tokens": 120,
          "total_tokens": 170,
          "non_cached_input_tokens": 13,  # optional
          "cache_read_input_tokens": 22,  # optional
          "cache_write_input_tokens": 15, # optional
        },
    )
    return resp

Cas d’utilisation : Utilisation d’un modèle personnalisé

Pour les modèles personnalisés ou non pris en charge, vous devez annoter le span manuellement avec les données de coût.

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs.decorators import llm

@llm(model_name="custom_model", model_provider="model_provider")
def llm_call(prompt):
    resp = ... # llm call here
    # Annotate cost metrics
    LLMObs.annotate(
        metrics={
          "input_cost": 3,
          "output_cost": 7,
          "total_cost": 10,
          "non_cached_input_cost": 1,    # optional
          "cache_read_input_cost": 0.6,  # optional
          "cache_write_input_cost": 1.4, # optional
        },
    )
    return resp

Évaluations

Le SDK d’observabilité LLM fournit des méthodes pour exporter et soumettre vos évaluations à Datadog.

Pour créer des évaluateurs réutilisables basés sur des classes (BaseEvaluator, BaseSummaryEvaluator) avec des métadonnées de résultats riches, consultez le Guide du développeur d'évaluation.

Les évaluations doivent être jointes à un seul span. Vous pouvez identifier le span cible en utilisant l’une de ces deux méthodes :

  • Jointure basée sur des balises - Joindre une évaluation en utilisant une paire de balises clé-valeur unique qui est définie sur un seul span. L’évaluation échouera à se joindre si la paire clé-valeur de balise correspond à plusieurs spans ou à aucun span.
  • Référence de span directe - Joindre une évaluation en utilisant l’ID de trace unique du span et la combinaison de l’ID de span.

Exportation d’un span

LLMObs.export_span() peut être utilisé pour extraire le contexte associé à un span. Cette méthode est utile pour associer votre évaluation au span correspondant.

Arguments

La méthode LLMObs.export_span() accepte l’argument suivant :

span
optionnel - Span
Le span à partir duquel extraire le contexte (identifiants du span et de trace). S’il n’est pas fourni (comme lors de l’utilisation de décorateurs de fonction), le SDK exporte le span actuellement actif.

Exemple

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs.decorators import llm

@llm(model_name="claude", name="invoke_llm", model_provider="anthropic")
def llm_call():
    completion = ... # user application logic to invoke LLM
    span_context = LLMObs.export_span(span=None)
    return completion

llmobs.exportSpan() peut être utilisé pour extraire le contexte associé à un span. Vous devrez utiliser cette méthode pour associer votre évaluation au span correspondant.

Arguments

La méthode llmobs.exportSpan() accepte l’argument suivant :

span
optionnel - Span
Le span à partir duquel extraire le contexte (identifiants du span et de trace). S’il n’est pas fourni (comme lors de l’utilisation de wrappers de fonction), le SDK exporte le span actuellement actif.

Exemple

function llmCall () {
  const completion = ... // user application logic to invoke LLM
  const spanContext = llmobs.exportSpan()
  return completion
}
llmCall = llmobs.wrap({ kind: 'llm', name: 'invokeLLM', modelName: 'claude', modelProvider: 'anthropic' }, llmCall)

Soumission d’évaluations

LLMObs.submit_evaluation() peut être utilisé pour soumettre votre évaluation personnalisée associée à un span donné.

LLMObs.submit_evaluation_for est obsolète et sera supprimé dans la prochaine version majeure de ddtrace (4.0). Pour migrer, renommez vos LLMObs.submit_evaluation_for appels avec LLMObs.submit_evaluation.

Remarque : Les évaluations personnalisées sont des évaluateurs que vous implémentez et hébergez vous-même. Celles-ci diffèrent des évaluations prêtes à l’emploi, qui sont automatiquement calculées par Datadog en utilisant des évaluateurs intégrés. Pour configurer des évaluations prêtes à l’emploi pour votre application, utilisez la page Observabilité LLM > Paramètres > Évaluations dans Datadog.

La méthode LLMObs.submit_evaluation() accepte les arguments suivants :

label
requis - chaîne
Le nom de l’évaluation.
metric_type
requis - chaîne
Le type de l’évaluation. Doit être categorical, score, boolean ou json.
value
requis - chaîne, type numérique ou dict
La valeur de l’évaluation. Doit être une chaîne (metric_type==categorical), un entier/float (metric_type==score), un booléen (metric_type==boolean) ou un dict (metric_type==json).
span
optionnel - dictionnaire
Un dictionnaire qui identifie de manière unique le span associé à cette évaluation. Doit contenir span_id (chaîne) et trace_id (chaîne). Utilisez LLMObs.export_span() pour générer ce dictionnaire.
span_with_tag_value
optionnel - dictionnaire
Un dictionnaire qui identifie de manière unique le span associé à cette évaluation. Doit contenir tag_key (chaîne) et tag_value (chaîne).

Remarque: Exactement l’un de span ou span_with_tag_value est requis. Fournir les deux, ou aucun, soulève une ValueError.

ml_app
requis - chaîne
Le nom de l’application ML.
timestamp_ms
optionnel - entier
L’horodatage Unix en millisecondes lorsque le résultat de la métrique d’évaluation a été généré. Si non fourni, la valeur par défaut est l’heure actuelle.
tags
optionnel - dictionnaire
Un dictionnaire de paires clé-valeur de chaînes que les utilisateurs peuvent ajouter en tant qu’étiquettes concernant l’évaluation. Pour plus d’informations sur les étiquettes, voir Démarrer avec les étiquettes.
assessment
optionnel - chaîne
Une analyse de cette évaluation. Les valeurs acceptées sont pass et fail.
reasoning
optionnel - chaîne
Une explication textuelle du résultat de l’évaluation.
metadata
optionnel - dictionnaire
Un dictionnaire contenant des métadonnées structurées arbitraires associées au résultat de l’évaluation.

Exemple

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs.decorators import llm

@llm(model_name="claude", name="invoke_llm", model_provider="anthropic")
def llm_call():
    completion = ... # user application logic to invoke LLM

    # joining an evaluation to a span via a tag key-value pair
    msg_id = get_msg_id()
    LLMObs.annotate(
        tags = {'msg_id': msg_id}
    )

    LLMObs.submit_evaluation(
        span_with_tag_value = {
            "tag_key": "msg_id",
            "tag_value": msg_id
        },
        ml_app = "chatbot",
        label="harmfulness",
        metric_type="score",
        value=10,
        tags={"evaluation_provider": "ragas"},
        assessment="fail",
        reasoning="Malicious intent was detected in the user instructions.",
        metadata={"details": ["jailbreak", "SQL injection"]}
    )

    # joining an evaluation to a span via span ID and trace ID
    span_context = LLMObs.export_span(span=None)
    LLMObs.submit_evaluation(
        span_context = span_context,
        ml_app = "chatbot",
        label="harmfulness",
        metric_type="score",
        value=10,
        tags={"evaluation_provider": "ragas"},
        assessment="fail",
        reasoning="Malicious intent was detected in the user instructions.",
        metadata={"details": ["jailbreak", "SQL injection"]}
    )
    return completion

llmobs.submitEvaluation() peut être utilisé pour soumettre votre évaluation personnalisée associée à une portée donnée.

La méthode llmobs.submitEvaluation() accepte les arguments suivants :

span_context
obligatoire - dictionnaire
Le contexte de la portée à associer à l’évaluation. Cela devrait être la sortie de LLMObs.export_span().
evaluationOptions
obligatoire - objet
Un objet des données d’évaluation.

L’objet evaluationOptions peut contenir les éléments suivants :

label
obligatoire - chaîne
Le nom de l’évaluation.
metricType
requis - _ chaîne_
Le type de l’évaluation. Doit être l’un des suivants : “catégorique”, “score”, “booléen” ou “json”.
value
requis - _ type chaîne ou numérique_
La valeur de l’évaluation. Doit être une chaîne (pour catégorique metric_type), un nombre (pour score metric_type), un booléen (pour booléen metric_type), ou un objet JSON (pour json metric_type).
tags
optionnel - _ dictionnaire_
Un dictionnaire de paires clé-valeur de chaînes que les utilisateurs peuvent ajouter en tant qu’étiquettes concernant l’évaluation. Pour plus d’informations sur les étiquettes, voir Démarrer avec les Étiquettes.
assessment
optionnel - _ chaîne_
Une évaluation de cette évaluation. Les valeurs acceptées sont pass et fail.
reasoning
optionnel - _ chaîne_
Une explication textuelle du résultat de l’évaluation.
metadata
optionnel - _ dictionnaire_
Un objet JSON contenant des métadonnées structurées arbitraires associées au résultat de l’évaluation.

Exemple

function llmCall () {
  const completion = ... // user application logic to invoke LLM
  const spanContext = llmobs.exportSpan()
  llmobs.submitEvaluation(spanContext, {
    label: "harmfulness",
    metricType: "score",
    value: 10,
    tags: { evaluationProvider: "ragas" }
  })
  return completion
}
llmCall = llmobs.wrap({ kind: 'llm', name: 'invokeLLM', modelName: 'claude', modelProvider: 'anthropic' }, llmCall)

Utilisez LLMObs.SubmitEvaluation() pour soumettre votre évaluation personnalisée associée à une portée donnée.

La méthode LLMObs.SubmitEvaluation() accepte les arguments suivants :

llmObsSpan
requis - _ LLMObsSpan_
Le contexte de la portée à associer à l’évaluation.
label
requis - chaîne
Le nom de l’évaluation.
categoricalValue ou scoreValue
requis - chaîne ou double
La valeur de l’évaluation. Doit être une chaîne (pour les évaluations catégorielles) ou un double (pour les évaluations de score).
tags
optionnel - Map<String, Object>
Un dictionnaire de paires clé-valeur de chaînes utilisé pour étiqueter l’évaluation. Pour plus d’informations sur les étiquettes, voir Premiers pas avec les étiquettes.

Exemple

import datadog.trace.api.llmobs.LLMObs;

public class MyJavaClass {
  public String invokeChat(String userInput) {
    LLMObsSpan llmSpan = LLMObs.startLLMSpan("my-llm-span-name", "my-llm-model", "my-company", "maybe-ml-app-override", "session-141");
    String chatResponse = "N/A";
    try {
      chatResponse = ... // user application logic to invoke LLM
    } catch (Exception e) {
      llmSpan.addThrowable(e);
      throw new RuntimeException(e);
    } finally {
      llmSpan.finish();

      // submit evaluations
      LLMObs.SubmitEvaluation(llmSpan, "toxicity", "toxic", Map.of("language", "english"));
      LLMObs.SubmitEvaluation(llmSpan, "f1-similarity", 0.02, Map.of("provider", "f1-calculator"));
    }
    return chatResponse;
  }
}

Traitement des spans

Pour modifier les données d’entrée et de sortie sur les spans, vous pouvez configurer une fonction de traitement. La fonction de traitement a accès aux étiquettes de spans pour permettre la modification conditionnelle des entrées et sorties. Les fonctions de traitement peuvent soit renvoyer le span modifié pour l’émettre, soit renvoyer None/null pour empêcher le span d’être émis entièrement. Ceci est utile pour filtrer les spans qui contiennent des données sensibles ou qui répondent à certains critères.

Exemple

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs import LLMObsSpan

def redact_processor(span: LLMObsSpan) -> LLMObsSpan:
    if span.get_tag("no_output") == "true":
        for message in span.output:
            message["content"] = ""
    return span


# If using LLMObs.enable()
LLMObs.enable(
  ...
  span_processor=redact_processor,
)
# else when using `ddtrace-run`
LLMObs.register_processor(redact_processor)

with LLMObs.llm("invoke_llm_with_no_output"):
    LLMObs.annotate(tags={"no_output": "true"})

Exemple : modification conditionnelle avec auto-instrumentation

Lors de l’utilisation de l’auto-instrumentation, le span n’est pas toujours accessible contextuellement. Pour modifier conditionnellement les entrées et sorties sur les spans auto-instrumentés, annotation_context() peut être utilisé en plus d’un processeur de span.

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs import LLMObsSpan

def redact_processor(span: LLMObsSpan) -> LLMObsSpan:
    if span.get_tag("no_input") == "true":
        for message in span.input:
            message["content"] = ""
    return span

LLMObs.register_processor(redact_processor)


def call_openai():
    with LLMObs.annotation_context(tags={"no_input": "true"}):
        # make call to openai
        ...

Exemple : empêcher les span d’être émis

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs import LLMObsSpan
from typing import Optional

def filter_processor(span: LLMObsSpan) -> Optional[LLMObsSpan]:
    # Skip spans that are marked as internal or contain sensitive data
    if span.get_tag("internal") == "true" or span.get_tag("sensitive") == "true":
        return None  # This span will not be emitted

    # Process and return the span normally
    return span

LLMObs.register_processor(filter_processor)

# This span will be filtered out and not sent to Datadog
with LLMObs.workflow("internal_workflow"):
    LLMObs.annotate(tags={"internal": "true"})
    # ... workflow logic

Exemple

const tracer = require('dd-trace').init({
  llmobs: {
    mlApp: "<YOUR_ML_APP_NAME>"
  }
})

const llmobs = tracer.llmobs

function redactProcessor(span) {
  if (span.getTag("no_output") === "true") {
    for (const message of span.output) {
      message.content = ""
    }
  }
  return span
}

llmobs.registerProcessor(redactProcessor)

Exemple : modification conditionnelle avec auto-instrumentation

Lors de l’utilisation de l’auto-instrumentation, le span n’est pas toujours accessible contextuellement. Pour modifier conditionnellement les entrées et sorties sur les spans auto-instrumentés, llmobs.annotationContext() peut être utilisé en plus d’un processeur de span.

const { llmobs } = require('dd-trace');

function redactProcessor(span) {
  if (span.getTag("no_input") == "true") {
    for (const message of span.input) {
      message.content = "";
    }
  }

  return span;
}

llmobs.registerProcessor(redactProcessor);

async function callOpenai() {
  await llmobs.annotationContext({ tags: { no_input: "true" } }, async () => {
    // make call to openai
  });
}

Exemple : empêcher les span d’être émis

const tracer = require('dd-trace').init({
  llmobs: {
    mlApp: "<YOUR_ML_APP_NAME>"
  }
})

const llmobs = tracer.llmobs

function filterProcessor(span) {
  // Skip spans that are marked as internal or contain sensitive data
  if (span.getTag("internal") === "true" || span.getTag("sensitive") === "true") {
    return null  // This span will not be emitted
  }

  // Process and return the span normally
  return span
}

llmobs.registerProcessor(filterProcessor)

// This span will be filtered out and not sent to Datadog
function internalWorkflow() {
  return llmobs.trace({ kind: 'workflow', name: 'internalWorkflow' }, (span) => {
    llmobs.annotate({ tags: { internal: "true" } })
    // ... workflow logic
  })
}

Suivi des sessions utilisateur

Le suivi des sessions permet d’associer plusieurs interactions à un utilisateur donné.

Lors du démarrage d’un span racine pour une nouvelle trace ou un span dans un nouveau processus, spécifiez l’argument session_id avec l’ID de chaîne de la session utilisateur sous-jacente, qui est ajouté en tant qu’étiquette sur le span. Optionnellement, vous pouvez également spécifier les étiquettes user_handle, user_name et user_id.

from ddtrace.llmobs.decorators import workflow

@workflow(session_id="<SESSION_ID>")
def process_user_message():
    LLMObs.annotate(
        ...
        tags = {"user_handle": "poodle@dog.com", "user_id": "1234", "user_name": "poodle"}
    )
    return

Étiquettes de suivi de session

ÉtiquetteDescription
session_idL’ID représentant une seule session utilisateur, par exemple, une session de chat.
user_handleLe pseudonyme de l’utilisateur de la session de chat.
user_nameLe nom de l’utilisateur de la session de chat.
user_idL’ID de l’utilisateur de la session de chat.

Lors du démarrage d’un span racine pour une nouvelle trace ou un nouveau span dans un nouveau processus, spécifiez l’argument sessionId avec l’ID de chaîne de la session utilisateur sous-jacente :

function processMessage() {
    ... # user application logic
    return
}
processMessage = llmobs.wrap({ kind: 'workflow', sessionId: "<SESSION_ID>" }, processMessage)

Lors du démarrage d’un span racine pour une nouvelle trace ou un nouveau span dans un nouveau processus, spécifiez l’argument sessionId avec l’ID de chaîne de la session utilisateur sous-jacente :

import datadog.trace.api.llmobs.LLMObs;

public class MyJavaClass {
  public String processChat(int userID) {
    LLMObsSpan workflowSpan = LLMObs.startWorkflowSpan("incoming-chat", null, "session-" + System.currentTimeMillis() + "-" + userID);
    String chatResponse = answerChat(); // user application logic
    workflowSpan.annotateIO(...); // record the input and output
    workflowSpan.finish();
    return chatResponse;
  }
}

Traçage distribué

Le SDK prend en charge le traçage à travers des services ou des hôtes distribués. Le traçage distribué fonctionne en propageant les informations de span à travers les requêtes web.

La bibliothèque ddtrace fournit certaines intégrations prêtes à l’emploi qui prennent en charge le traçage distribué pour des frameworks web et des bibliothèques HTTP populaires. Si votre application effectue des requêtes en utilisant ces bibliothèques prises en charge, vous pouvez activer le traçage distribué en exécutant :

from ddtrace import patch
patch(<INTEGRATION_NAME>=True)

Si votre application n’utilise aucune de ces bibliothèques prises en charge, vous pouvez activer le traçage distribué en propageant manuellement les informations de span vers et depuis les en-têtes HTTP. Le SDK fournit les méthodes d’aide LLMObs.inject_distributed_headers() et LLMObs.activate_distributed_headers() pour injecter et activer les contextes de traçage dans les en-têtes de requête.

Injection des en-têtes distribués

La méthode LLMObs.inject_distributed_headers() prend un span et injecte son contexte dans les en-têtes HTTP à inclure dans la requête. Cette méthode accepte les arguments suivants :

request_headers
requis - dictionnaire
Les en-têtes HTTP à étendre avec les attributs de contexte de traçage.
span
optionnel - Span - par défaut: The current active span.
Le span pour injecter son contexte dans les en-têtes de requête fournis. Tous les spans (y compris ceux avec des décorateurs de fonction) utilisent par défaut le span actif actuel.

Activation des en-têtes distribués

La méthode LLMObs.activate_distributed_headers() prend des en-têtes HTTP et extrait les attributs de contexte de traçage à activer dans le nouveau service.

Remarque : Vous devez appeler LLMObs.activate_distributed_headers() avant de commencer tout span dans votre service en aval. Les spans commencés auparavant (y compris les spans de décorateurs de fonction) ne sont pas capturés dans le traçage distribué.

Cette méthode accepte l’argument suivant :

request_headers
requis - dictionnaire
Les en-têtes HTTP pour extraire les attributs de contexte de traçage.

Exemple

client.py

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs.decorators import workflow

@workflow
def client_send_request():
    request_headers = {}
    request_headers = LLMObs.inject_distributed_headers(request_headers)
    send_request("<method>", request_headers)  # arbitrary HTTP call

server.py

from ddtrace.llmobs import LLMObs

def server_process_request(request):
    LLMObs.activate_distributed_headers(request.headers)
    with LLMObs.task(name="process_request") as span:
        pass  # arbitrary server work

La bibliothèque dd-trace fournit des intégrations prêtes à l’emploi qui prennent en charge le traçage distribué pour des frameworks web populaires. Exiger le traceur active automatiquement ces intégrations, mais vous pouvez les désactiver optionnellement avec :

const tracer = require('dd-trace').init({
  llmobs: { ... },
})
tracer.use('http', false) // disable the http integration

Traçage avancé

Traçage des spans en utilisant des méthodes en ligne

Pour chaque type de span, la classe ddtrace.llmobs.LLMObs fournit une méthode en ligne correspondante pour tracer automatiquement l’opération qu’implique un bloc de code donné. Ces méthodes ont la même signature d’argument que leurs homologues de décorateurs de fonction, avec l’ajout que name prend par défaut la valeur correspondant au type de span (llm, workflow, etc.) s’il n’est pas fourni. Ces méthodes peuvent être utilisées comme gestionnaires de contexte pour terminer automatiquement le span après l’achèvement du bloc de code inclus.

Exemple

from ddtrace.llmobs import LLMObs

def process_message():
    with LLMObs.workflow(name="process_message", session_id="<SESSION_ID>", ml_app="<ML_APP>") as workflow_span:
        ... # user application logic
    return

Persistance d’un span à travers les contextes

Pour démarrer et arrêter manuellement un span à travers différents contextes ou portées :

  1. Démarrez un span manuellement en utilisant les mêmes méthodes (par exemple, la méthode LLMObs.workflow pour un span de workflow), mais en tant qu’appel de fonction simple plutôt qu’en tant que gestionnaire de contexte.
  2. Passez l’objet span en tant qu’argument à d’autres fonctions.
  3. Arrêtez le span manuellement avec la méthode span.finish(). Remarque : le span doit être terminé manuellement, sinon il n’est pas soumis.

Exemple

from ddtrace.llmobs import LLMObs

def process_message():
    workflow_span = LLMObs.workflow(name="process_message")
    ... # user application logic
    separate_task(workflow_span)
    return

def separate_task(workflow_span):
    ... # user application logic
    workflow_span.finish()
    return

Forcer le vidage dans des environnements sans serveur

LLMObs.flush() est une fonction bloquante qui soumet toutes les données d’observabilité LLM mises en mémoire tampon au backend Datadog. Cela peut être utile dans des environnements sans serveur pour empêcher une application de se fermer tant que toutes les traces LLM Observability ne sont pas soumises.

Tracer plusieurs applications

Le SDK prend en charge le traçage de plusieurs applications LLM à partir du même service.

Vous pouvez configurer une variable d’environnement DD_LLMOBS_ML_APP au nom de votre application LLM, dans laquelle tous les spans générés sont regroupés par défaut.

Pour remplacer cette configuration et utiliser un nom d’application LLM différent pour un span racine donné, passez l’argument ml_app avec le nom sous forme de chaîne de caractères de l’application LLM sous-jacente lors du démarrage d’un span racine pour une nouvelle trace ou d’un span dans un nouveau processus.

from ddtrace.llmobs.decorators import workflow

@workflow(name="process_message", ml_app="<NON_DEFAULT_ML_APP_NAME>")
def process_message():
    ... # user application logic
    return

Traçage des spans en utilisant des méthodes en ligne

Le llmobs SDK fournit une méthode en ligne correspondante pour tracer automatiquement l’opération qu’implique un bloc de code donné. Ces méthodes ont la même signature d’argument que leurs homologues de wrapper de fonction, avec l’ajout que name est requis, car le nom ne peut pas être déduit d’un rappel anonyme. Cette méthode terminera le span dans les conditions suivantes :

  • Si la fonction retourne une Promise, alors le span se termine lorsque la Promise est résolue ou rejetée.
  • Si la fonction prend un callback comme dernier paramètre, alors le span se termine lorsque ce callback est appelé.
  • Si la fonction n’accepte pas de callback et ne retourne pas de Promise, alors le span se termine à la fin de l’exécution de la fonction.

Exemple sans rappel

function processMessage () {
  return llmobs.trace({ kind: 'workflow', name: 'processMessage', sessionId: '<SESSION_ID>', mlApp: '<ML_APP>' }, workflowSpan => {
    ... // user application logic
    return
  })
}

Exemple avec un rappel

function processMessage () {
  return llmobs.trace({ kind: 'workflow', name: 'processMessage', sessionId: '<SESSION_ID>', mlApp: '<ML_APP>' }, (workflowSpan, cb) => {
    ... // user application logic
    let maybeError = ...
    cb(maybeError) // the span will finish here, and tag the error if it is not null or undefined
    return
  })
}

Le type de retour de cette fonction correspond au type de retour de la fonction tracée :

function processMessage () {
  const result = llmobs.trace({ kind: 'workflow', name: 'processMessage', sessionId: '<SESSION_ID>', mlApp: '<ML_APP>' }, workflowSpan => {
    ... // user application logic
    return 'hello world'
  })

  console.log(result) // 'hello world'
  return result
}

Décorateurs de fonction en TypeScript

Le SDK d’observabilité LLM de Node.js propose une llmobs.decorate fonction qui sert de décorateur de fonction pour les applications TypeScript. Le comportement de traçage de cette fonction est le même que llmobs.wrap.

Exemple

// index.ts
import tracer from 'dd-trace';
tracer.init({
  llmobs: {
    mlApp: "<YOUR_ML_APP_NAME>",
  },
});

const { llmobs } = tracer;

class MyAgent {
  @llmobs.decorate({ kind: 'agent' })
  async runChain () {
    ... // user application logic
    return
  }
}

Forcer le vidage dans des environnements sans serveur

llmobs.flush() est une fonction bloquante qui soumet toutes les données d’observabilité LLM mises en mémoire tampon au backend Datadog. Cela peut être utile dans des environnements sans serveur pour empêcher une application de se fermer tant que toutes les traces LLM Observability ne sont pas soumises.

Tracer plusieurs applications

Le SDK prend en charge le traçage de plusieurs applications LLM à partir du même service.

Vous pouvez configurer une variable d’environnement DD_LLMOBS_ML_APP au nom de votre application LLM, dans laquelle tous les spans générés sont regroupés par défaut.

Pour remplacer cette configuration et utiliser un nom d’application LLM différent pour un span racine donné, passez l’argument mlApp avec le nom sous forme de chaîne de caractères de l’application LLM sous-jacente lors du démarrage d’un span racine pour une nouvelle trace ou d’un span dans un nouveau processus.

function processMessage () {
  ... // user application logic
  return
}
processMessage = llmobs.wrap({ kind: 'workflow', name: 'processMessage', mlApp: '<NON_DEFAULT_ML_APP_NAME>' }, processMessage)

Directives de nommage des applications

Le nom de votre application (la valeur de DD_LLMOBS_ML_APP) doit suivre ces directives :

  • Doit être une chaîne Unicode en minuscules
  • Peut comporter jusqu’à 193 caractères
  • Ne peut pas contenir de traits de soulignement contigus ou en fin de chaîne
  • Peut contenir les caractères suivants :
    • Alphanumériques
    • Traits de soulignement
    • Tirets
    • Deux-points
    • Points
    • Barres obliques

Lectures complémentaires

Documentation, liens et articles supplémentaires utiles: