Este producto no es compatible con el sitio Datadog seleccionado. ().

Descripción general

Los Agent Observability SDKs proporcionan instrumentación automática, así como API de instrumentación manual para brindar observabilidad y perspectivas en sus aplicaciones de LLM.

Configuración

Requisitos

  • El paquete ddtrace más reciente está instalado (se requiere Python 3.7+):
    pip install ddtrace
    
  • El paquete dd-trace más reciente está instalado (se requiere Node.js 16+):
    npm install dd-trace
    
  • Ha descargado el dd-trace-java JAR más reciente. El Agent Observability SDK es compatible con dd-trace-java v1.51.0+ (se requiere Java 8+).

Habilite Agent Observability ejecutando su aplicación mediante el comando ddtrace-run y especificando las variables de entorno requeridas.

Nota: ddtrace-run activa automáticamente todas las integraciones de Agent 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 de entorno para la configuración de línea de comandos

DD_SITE
requerido - cadena
Sitio de Datadog de destino para el envío de datos de LLM. Su sitio es .
DD_LLMOBS_ENABLED
requerido - entero o cadena
Active para habilitar el envío de datos a Agent Observability. Debe establecerse en 1 o true.
DD_LLMOBS_ML_APP
opcional - cadena
El nombre de su aplicación, servicio o proyecto de LLM, bajo el cual se agrupan todas las trazas y tramos. Esto ayuda a distinguir entre diferentes aplicaciones o experimentos. Consulte las pautas de nomenclatura de aplicaciones para conocer los caracteres permitidos y otras restricciones. Para anular este valor para un tramo raíz determinado, consulte Seguimiento de múltiples aplicaciones. Si no se proporciona, el valor predeterminado es el valor de DD_SERVICE, o el valor de un DD_LLMOBS_ML_APP propagado desde un servicio ascendente.
Nota: Antes de la versión ddtrace==3.14.0, este es un campo obligatorio.
DD_LLMOBS_AGENTLESS_ENABLED
opcional - entero o cadena - predeterminado: false
Solo es necesario si no está utilizando el Datadog Agent, en cuyo caso debe establecerse en 1 o true.
DD_LLMOBS_SAMPLE_RATE
opcional - flotante - predeterminado: 1.0
La fracción de trazas retenidas por Agent Observability. Consulte Muestreo de trazas.
DD_API_KEY
opcional - cadena
Su clave de API de Datadog. Solo es necesario si no está utilizando el Datadog Agent.
DD_MCP_CAPTURE_INTENT
opcional - entero o cadena - predeterminado: false
Cuando se establece en 1 o true, agrega un argumento a cada herramienta de servidor MCP solicitando que el modelo que realiza la llamada describa por qué eligió llamar a la herramienta. La intención se registra en el tramo de la herramienta.

Habilite Agent Observability ejecutando su aplicación con NODE_OPTIONS="--import dd-trace/initialize.mjs" y especificando las variables de entorno requeridas.

Nota: dd-trace/initialize.mjs activa automáticamente todas las integraciones de 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 de entorno para la configuración de línea de comandos

DD_SITE
requerido - cadena
El sitio de Datadog para enviar sus datos de LLM. Su sitio es .
DD_LLMOBS_ENABLED
requerido - entero o cadena
Active para habilitar el envío de datos a Agent Observability. Debe establecerse en 1 o true.
DD_LLMOBS_ML_APP
opcional - cadena
El nombre de su aplicación, servicio o proyecto de LLM, bajo el cual se agrupan todas las trazas y tramos. Esto ayuda a distinguir entre diferentes aplicaciones o experimentos. Consulte las pautas de nomenclatura de aplicaciones para conocer los caracteres permitidos y otras restricciones. Para anular este valor para un tramo raíz determinado, consulte Seguimiento de múltiples aplicaciones. Si no se proporciona, el valor predeterminado es el valor de DD_SERVICE, o el valor de un DD_LLMOBS_ML_APP propagado desde un servicio ascendente.
Nota: Antes de la versión dd-trace@5.66.0, este es un campo obligatorio.
DD_LLMOBS_AGENTLESS_ENABLED
opcional - entero o cadena - predeterminado: false
Solo es necesario si no está utilizando el Datadog Agent, en cuyo caso debe establecerse en 1 o true.
DD_LLMOBS_SAMPLE_RATE
opcional - flotante - predeterminado: 1.0
La fracción de trazas retenidas por Agent Observability. Consulte Muestreo de trazas.
DD_API_KEY
opcional - cadena
Su clave de API de Datadog. Solo es necesario si no está utilizando el Datadog Agent.

Habilite Agent Observability ejecutando su aplicación con dd-trace-java y especificando los parámetros requeridos como variables de entorno o propiedades del sistema.

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 de entorno y propiedades del sistema

Puede proporcionar los siguientes parámetros como variables de entorno (por ejemplo, DD_LLMOBS_ENABLED) o como propiedades del sistema Java (por ejemplo, dd.llmobs_enabled).

DD_SITE o dd.site
obligatorio - cadena
Sitio de Datadog de destino para el envío de datos de LLM. Su sitio es .
DD_LLMOBS_ENABLED o dd.llmobs.enabled
requerido - entero o cadena
Active para habilitar el envío de datos a Agent Observability. Debe establecerse en 1 o true.
DD_LLMOBS_ML_APP o dd.llmobs.ml.app
opcional - cadena
El nombre de su aplicación, servicio o proyecto de LLM, bajo el cual se agrupan todas las trazas y tramos. Esto ayuda a distinguir entre diferentes aplicaciones o experimentos. Consulte las pautas de nomenclatura de aplicaciones para conocer los caracteres permitidos y otras restricciones. Para anular este valor para un tramo raíz determinado, consulte Seguimiento de múltiples aplicaciones. Si no se proporciona, el valor predeterminado es el valor de DD_SERVICE, o el valor de un DD_LLMOBS_ML_APP propagado desde un servicio ascendente.
Nota: Antes de la versión 1.54.0 de dd-trace-java, este es un campo obligatorio.
DD_LLMOBS_AGENTLESS_ENABLED o dd.llmobs.agentless.enabled
opcional - entero o cadena - predeterminado: false
Solo es necesario si no está utilizando el Datadog Agent, en cuyo caso debe establecerse en 1 o true.
DD_LLMOBS_SAMPLE_RATE o dd.llmobs.sample.rate
opcional - flotante - predeterminado: 1.0
La fracción de trazas retenidas por Agent Observability. Requiere dd-trace-java 1.66.0 o posterior. Consulte Muestreo de trazas.
DD_API_KEY o dd.api.key
opcional - cadena
Su clave de API de Datadog. Solo es necesario si no está utilizando el Datadog Agent.

En lugar de usar la configuración de línea de comandos, también puede habilitar Agent Observability mediante programación.

Use la función LLMObs.enable() para habilitar Agent Observability.

No utilice este método de configuración con el ddtrace-run comando.
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,
)
Parámetros
ml_app
opcional - cadena
El nombre de su aplicación, servicio o proyecto de LLM, bajo el cual se agrupan todas las trazas y tramos. Esto ayuda a distinguir entre diferentes aplicaciones o experimentos. Consulte las pautas de nomenclatura de aplicaciones para conocer los caracteres permitidos y otras restricciones. Para anular este valor para una traza determinada, consulte Seguimiento de múltiples aplicaciones. Si no se proporciona, el valor predeterminado es el de DD_LLMOBS_ML_APP.
integrations_enabled - predeterminado: true
opcional - booleano
Una marca para habilitar automáticamente el rastreo de llamadas de LLM para las integraciones de LLM compatibles con Datadog. Si no se proporciona, todas las integraciones de LLM compatibles están habilitadas de forma predeterminada. Para evitar el uso de las integraciones de LLM, establezca este valor en false.
agentless_enabled
opcional - booleano - predeterminado: false
Solo es necesario si no está utilizando el Datadog Agent, en cuyo caso esto debe establecerse en True. Esto configura la biblioteca ddtrace para que no envíe ningún dato que requiera el Datadog Agent. Si no se proporciona, esto toma por defecto el valor de DD_LLMOBS_AGENTLESS_ENABLED.
site
opcional - cadena
El sitio de Datadog para enviar sus datos de LLM. Su sitio es . Si no se proporciona, esto toma por defecto el valor de DD_SITE.
api_key
opcional - cadena
Su clave de API de Datadog. Solo es necesario si no está utilizando el Datadog Agent. Si no se proporciona, esto toma por defecto el valor de DD_API_KEY.
env
opcional - cadena
El nombre del entorno de su aplicación (ejemplos: prod, pre-prod, staging). Si no se proporciona, esto toma por defecto el valor de DD_ENV.
service
opcional - cadena
El nombre del servicio utilizado para su aplicación. Si no se proporciona, esto toma por defecto el valor de DD_SERVICE.
sample_rate
opcional - flotante
La fracción de trazas retenidas por Agent Observability. Requiere ddtrace 4.12.0 o posterior. Cuando se establece, esto tiene prioridad sobre DD_LLMOBS_SAMPLE_RATE. Consulte Muestreo de trazas.
capture_intent
opcional - booleano - predeterminado: false
Cuando se establece en True, agrega un argumento a cada herramienta de servidor MCP solicitando que el modelo que realiza la llamada describa por qué eligió llamar a la herramienta. La intención se registra en el tramo de la herramienta. Si no se proporciona, esto toma como valor predeterminado el valor de DD_MCP_CAPTURE_INTENT.
No utilice este método de configuración con el dd-trace/initialize.mjs comando.

Use la función init() para habilitar Agent 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;

Opciones para la configuración de llmobs

mlApp
opcional - cadena
El nombre de su aplicación, servicio o proyecto de LLM, bajo el cual se agrupan todas las trazas y tramos. Esto ayuda a distinguir entre diferentes aplicaciones o experimentos. Consulte las pautas de nomenclatura de aplicaciones para conocer los caracteres permitidos y otras restricciones. Para anular este valor para una traza determinada, consulte Seguimiento de múltiples aplicaciones. Si no se proporciona, el valor predeterminado es el de DD_LLMOBS_ML_APP.
agentlessEnabled
opcional - booleano - predeterminado: false
Solo es necesario si no está utilizando Datadog Agent, en cuyo caso esto debe establecerse en true. Esto configura la biblioteca dd-trace para que no envíe ningún dato que requiera el Datadog Agent. Si no se proporciona, esto toma por defecto el valor de DD_LLMOBS_AGENTLESS_ENABLED.
sampleRate
opcional - número
La fracción de trazas retenidas por Agent Observability. Requiere dd-trace 5.110.0 o posterior. Cuando se establece, esto tiene prioridad sobre DD_LLMOBS_SAMPLE_RATE. Consulte Muestreo de trazas.

Opciones para la configuración general del trazador:

site
opcional - cadena
El sitio de Datadog para enviar sus datos de LLM. Su sitio es . Si no se proporciona, esto toma por defecto el valor de DD_SITE.
env
opcional - cadena
El nombre del entorno de su aplicación (ejemplos: prod, pre-prod, staging). Si no se proporciona, esto toma por defecto el valor de DD_ENV.
service
opcional - cadena
El nombre del servicio utilizado para su aplicación. Si no se proporciona, esto toma por defecto el valor de DD_SERVICE.
Variables de entorno

Establezca los siguientes valores como variables de entorno. No se pueden configurar mediante programación.

DD_API_KEY
opcional - cadena
Su clave de API de Datadog. Solo es necesario si no está utilizando el Datadog Agent.

Para AWS Lambda, consulte Rastrear una aplicación LLM en AWS Lambda.

Después de instalar el SDK y ejecutar su aplicación, debería esperar ver algunos datos en Agent Observability a partir de la instrumentación automática. La instrumentación manual se puede utilizar para capturar marcos de trabajo personalizados o operaciones de bibliotecas que aún no son compatibles.

Muestreo de trazas

El muestreo de trazas está disponible en el SDK de Python (ddtrace 4.12.0 o posterior), el SDK de Node.js (dd-trace 5.110.0 o posterior), y el SDK de Java (dd-trace-java 1.66.0 o posterior).

El muestreo de trazas establece la fracción de trazas que retiene Agent Observability. Debido a que la facturación de Agent Observability se basa en el volumen de tramos que envía, establecer una tasa de muestreo es una forma de controlar sus costos de Agent Observability. El SDK toma la decisión de muestreo en el tramo raíz y la aplica a todos los tramos secundarios de ese tramo raíz, incluidos los tramos creados en servicios downstream a través de trazado distribuido.

El muestreo no afecta sus métricas de Agent Observability, incluidas las métricas de tokens y costos y otras métricas operativas. Debido a que los tramos no muestreados se descartan después de que Datadog ingiere sus trazas, estas métricas siguen basándose en el 100% del tráfico instrumentado de su aplicación, independientemente de la tasa de muestreo especificada. El muestreo de trazas también es independiente de los controles en la aplicación, como las reglas de automatización y el muestreo de trazas de APM, que se aplican después de la ingestión.

Configure la tasa de muestreo a través de cualquiera de estos dos mecanismos:

  • Variable de entorno (DD_LLMOBS_SAMPLE_RATE): se aplica tanto a la configuración de línea de comandos como a la configuración en el código. En Java, la propiedad del sistema dd.llmobs.sample.rate establece el mismo valor.
  • Parámetro en el código (sample_rate en Python, sampleRate en Node.js): se pasa a LLMObs.enable() en Python, o bajo llmobs en Node.js, cuando habilita el SDK con configuración en el código. Cuando se establece, tiene prioridad sobre DD_LLMOBS_SAMPLE_RATE. El SDK de Java no tiene un equivalente en el código fuente.

La tasa de muestreo es un número de punto flotante entre 0.0 (no retener trazas) y 1.0 (retener todas las trazas). El valor predeterminado es 1.0. Los valores fuera de rango se ignoran.

Establezca la tasa de muestreo con la variable de entorno:

DD_LLMOBS_SAMPLE_RATE=0.5 ddtrace-run <YOUR_APP_STARTUP_COMMAND>

O pase sample_rate a LLMObs.enable(), lo cual tiene prioridad sobre la variable de entorno:

from ddtrace.llmobs import LLMObs

LLMObs.enable(
  ml_app="<YOUR_ML_APP_NAME>",
  sample_rate=0.5,
)

Establezca la tasa de muestreo con la variable de entorno:

DD_LLMOBS_SAMPLE_RATE=0.5 NODE_OPTIONS="--import dd-trace/initialize.mjs" <YOUR_APP_STARTUP_COMMAND>

O pase sampleRate bajo llmobs a init(), lo cual tiene prioridad sobre la variable de entorno:

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

const llmobs = tracer.llmobs;

Establezca la tasa de muestreo con la variable de entorno:

DD_LLMOBS_SAMPLE_RATE=0.5 \
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=<YOUR_ML_APP_NAME> \
-jar path/to/your/app.jar

O establezca la propiedad dd.llmobs.sample.rate del sistema equivalente:

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=<YOUR_ML_APP_NAME> \
-Ddd.llmobs.sample.rate=0.5 -jar path/to/your/app.jar

Instrumentación manual

Para capturar una operación de LLM, se puede utilizar un decorador de función para instrumentar flujos de trabajo fácilmente:

from ddtrace.llmobs.decorators import workflow

@workflow
def handle_user_request():
    ...

o un enfoque basado en gestor de contexto para capturar operaciones detalladas:

from ddtrace.llmobs import LLMObs

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

Para obtener una lista de los tipos de tramos disponibles, consulte la documentación de Tipos de tramos. Para un rastreo más detallado de las operaciones dentro de las funciones, consulte Rastreo de tramos mediante métodos en línea.

Para rastrear un tramo, utilice llmobs.wrap(options, function) como envoltorio de función para la función que desea rastrear. Para obtener una lista de los tipos de tramos disponibles, consulte la documentación de Tipos de tramos. Para un rastreo más detallado de las operaciones dentro de las funciones, consulte Rastreo de tramos mediante métodos en línea.

Tipos de tramo

Los tipos de tramo son obligatorios y se especifican en el objeto options que se pasa a las funciones de rastreo llmobs (trace, wrap y decorate). Consulte la documentación de Tipos de tramo para obtener una lista de los tipos de tramo admitidos.

Nota: Los tramos con un tipo de tramo no válido no se envían a Agent Observability.

Captura automática de argumentos/salida/nombre de función

llmobs.wrap (junto con llmobs.decorate para TypeScript) intenta capturar automáticamente las entradas, las salidas y el nombre de la función que se está rastreando. Si necesita anotar un tramo manualmente, consulte Enriquecimiento de tramos. Las entradas y salidas que usted anote anularán la captura automática. Además, para anular el nombre de la función, pase la propiedad name en el objeto de opciones a la función llmobs.wrap:

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

Condiciones para finalizar un tramo para una función envuelta

llmobs.wrap extiende el comportamiento subyacente de tracer.wrap. El tramo subyacente creado cuando se llama a la función finaliza bajo las siguientes condiciones:

  • Si la función devuelve una Promesa, el tramo finaliza cuando la promesa se resuelve o se rechaza.
  • Si la función toma una devolución de llamada como su último parámetro, el tramo finaliza cuando se llama a esa devolución de llamada.
  • Si la función no acepta una devolución de llamada y no devuelve una Promise, el tramo finaliza al final de la ejecución de la función.

El siguiente ejemplo demuestra la segunda condición, donde el último argumento es una devolución de llamada:

Ejemplo

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 la aplicación no utiliza la función de devolución de llamada, se recomienda utilizar un bloque de traza en línea en su lugar. Consulte Rastreo de tramos mediante métodos en línea para obtener más información.

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)

Inicio de un tramo

Existen varios métodos para iniciar un tramo, según el tipo de tramo que esté iniciando. Consulte la documentación de Tipos de tramo para obtener una lista de los tipos de tramo admitidos.

Todos los tramos se inician como una instancia de objeto de LLMObsSpan. Cada tramo tiene métodos que puede utilizar para interactuar con el tramo y registrar datos.

Finalización de un tramo

Los tramos deben finalizarse para que la traza se envíe y sea visible en la aplicación de Datadog.

Para finalizar un tramo, llame a finish() en una instancia de objeto de tramo. Si es posible, envuelva el tramo en un bloque try/finally para asegurarse de que el tramo se envíe incluso si ocurre una excepción.

Ejemplo

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

Llamadas a LLM

Si utiliza algún proveedor o marco de trabajo de LLM compatible con las integraciones de LLM de Datadog, no necesita iniciar manualmente un tramo de LLM para realizar la traza de estas operaciones.
Si está instrumentando manualmente un tramo de LLM, debe registrar los conteos de tokens (como input_tokens, output_tokens, y total_tokens) usted mismo anotando el tramo. Consulte Enriquecimiento de tramos para obtener más información.

Para trazar una llamada de LLM, utilice el decorador de función ddtrace.llmobs.decorators.llm().

model_name
obligatorio - cadena
El nombre del LLM invocado.
name
opcional - cadena
El nombre de la operación. Si no se proporciona, name utiliza de forma predeterminada el nombre de la función rastreada.
model_provider
opcional - cadena - predeterminado: "custom"
El nombre del proveedor del modelo.
Nota: Para mostrar el costo estimado en dólares estadounidenses, establezca model_provider en uno de los siguientes valores: openai, azure_openai o anthropic.
session_id
opcional - cadena
El ID de la sesión de usuario subyacente. Consulte Seguimiento de sesiones de usuario para obtener más información.
ml_app
opcional - cadena
El nombre de la aplicación de ML a la que pertenece la operación. Consulte Trazar múltiples aplicaciones para obtener más información.

Ejemplo

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

Para trazar una llamada a un LLM, especifique el tipo de tramo como llm y, opcionalmente, especifique los siguientes argumentos en el objeto de opciones.

modelName
opcional - cadena - predeterminado: "custom"
El nombre del LLM invocado.
name
opcional - cadena
El nombre de la operación. Si no se proporciona, name utiliza de forma predeterminada el nombre de la función rastreada.
modelProvider
opcional - cadena - predeterminado: "custom"
El nombre del proveedor del modelo.
Nota: Para mostrar el costo estimado en dólares estadounidenses, establezca modelProvider en uno de los siguientes valores: openai, azure_openai o anthropic.
sessionId
opcional - cadena
El ID de la sesión de usuario subyacente. Consulte Seguimiento de sesiones de usuario para obtener más información.
mlApp
opcional - cadena
El nombre de la aplicación de ML a la que pertenece la operación. Consulte Trazar múltiples aplicaciones para obtener más información.

Ejemplo

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)

Para trazar una llamada a un LLM, importe y llame al siguiente método con los argumentos enumerados a continuación:

import datadog.trace.api.llmobs.LLMObs;
LLMObs.startLLMSpan(spanName, modelName, modelProvider, mlApp, sessionID);
spanName
opcional - Cadena
El nombre de la operación. Si no se proporciona, spanName utiliza de forma predeterminada el tipo de tramo.
modelName
opcional - string - predeterminado: "custom"
El nombre del LLM invocado.
modelProvider
opcional - string - predeterminado: "custom"
El nombre del proveedor del modelo.
Nota: Para mostrar el costo estimado en dólares estadounidenses, establezca modelProvider en uno de los siguientes valores: openai, azure_openai o anthropic.
mlApp
opcional - string
El nombre de la aplicación de ML a la que pertenece la operación. Proporcionar un valor no nulo anula el nombre de la aplicación de ML proporcionado al inicio de la aplicación. Consulte Trazar múltiples aplicaciones para obtener más información.
sessionId
opcional - string
El ID de la sesión de usuario subyacente. Consulte Seguimiento de sesiones de usuario para obtener más información.

Ejemplo

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;
  }
}

Flujos de trabajo

Para trazar un tramo de flujo de trabajo, utilice el decorador de función ddtrace.llmobs.decorators.workflow().

name
opcional - cadena
El nombre de la operación. Si no se proporciona, name utiliza de forma predeterminada el nombre de la función rastreada.
session_id
opcional - cadena
El ID de la sesión de usuario subyacente. Consulte Seguimiento de sesiones de usuario para obtener más información.
ml_app
opcional - cadena
El nombre de la aplicación de ML a la que pertenece la operación. Consulte Trazar múltiples aplicaciones para obtener más información.

Ejemplo

from ddtrace.llmobs.decorators import workflow

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

Para trazar un tramo de flujo de trabajo, especifique el tipo de tramo como workflow y, opcionalmente, especifique los argumentos en el objeto de opciones.

name
opcional - cadena
El nombre de la operación. Si no se proporciona, name utiliza de forma predeterminada el nombre de la función rastreada.
sessionId
opcional - cadena
El ID de la sesión de usuario subyacente. Consulte Seguimiento de sesiones de usuario para obtener más información.
mlApp
opcional - cadena
El nombre de la aplicación de ML a la que pertenece la operación. Consulte Trazar múltiples aplicaciones para obtener más información.

Ejemplo

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

Para rastrear un tramo de flujo de trabajo, importe y llame al siguiente método con los argumentos enumerados a continuación:

import datadog.trace.api.llmobs.LLMObs;
LLMObs.startWorkflowSpan(spanName, mlApp, sessionID);
spanName
opcional - Cadena
El nombre de la operación. Si no se proporciona, spanName utiliza de forma predeterminada el tipo de tramo.
mlApp
opcional - Cadena
El nombre de la aplicación de ML a la que pertenece la operación. Proporcionar un valor no nulo anula el nombre de la aplicación de ML proporcionado al inicio de la aplicación. Consulte Trazar múltiples aplicaciones para obtener más información.
sessionId
opcional - Cadena
El ID de la sesión de usuario subyacente. Consulte Seguimiento de sesiones de usuario para obtener más información.

Ejemplo

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;
  }
}

Agentes

Para realizar el seguimiento de una ejecución de agente, utilice el decorador de función ddtrace.llmobs.decorators.agent().

name
opcional - cadena
El nombre de la operación. Si no se proporciona, name utiliza de forma predeterminada el nombre de la función rastreada.
session_id
opcional - cadena
El ID de la sesión de usuario subyacente. Consulte Seguimiento de sesiones de usuario para obtener más información.
ml_app
opcional - cadena
El nombre de la aplicación de ML a la que pertenece la operación. Consulte Trazar múltiples aplicaciones para obtener más información.

Ejemplo

from ddtrace.llmobs.decorators import agent

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

Para rastrear una ejecución de agente, especifique el tipo de tramo como agent y, opcionalmente, especifique los argumentos en el objeto de opciones.

name
opcional - cadena
El nombre de la operación. Si no se proporciona, name utiliza de forma predeterminada el nombre de la función rastreada.
sessionId
opcional - cadena
El ID de la sesión de usuario subyacente. Consulte Seguimiento de sesiones de usuario para obtener más información.
mlApp
opcional - cadena
El nombre de la aplicación de ML a la que pertenece la operación. Consulte Trazar múltiples aplicaciones para obtener más información.

Ejemplo

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

Para rastrear una ejecución de agente, importe y llame al siguiente método con los argumentos enumerados a continuación

import datadog.trace.api.llmobs.LLMObs;
LLMObs.startAgentSpan(spanName, mlApp, sessionID);
spanName
opcional - Cadena
El nombre de la operación. Si no se proporciona, spanName utiliza de forma predeterminada el nombre de la función rastreada.
mlApp
opcional - Cadena
El nombre de la aplicación de ML a la que pertenece la operación. Proporcionar un valor no nulo anula el nombre de la aplicación de ML proporcionado al inicio de la aplicación. Consulte Trazar múltiples aplicaciones para obtener más información.
sessionId
opcional - Cadena
El ID de la sesión de usuario subyacente. Consulte Seguimiento de sesiones de usuario para obtener más información.

Llamadas a herramientas

Para rastrear una llamada a herramienta, utilice el decorador de función ddtrace.llmobs.decorators.tool().

name
opcional - cadena
El nombre de la operación. Si no se proporciona, name utiliza de forma predeterminada el nombre de la función rastreada.
session_id
opcional - cadena
El ID de la sesión de usuario subyacente. Consulte Seguimiento de sesiones de usuario para obtener más información.
ml_app
opcional - cadena
El nombre de la aplicación de ML a la que pertenece la operación. Consulte Trazar múltiples aplicaciones para obtener más información.

Ejemplo

from ddtrace.llmobs.decorators import tool

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

Para rastrear una llamada a herramienta, especifique el tipo de tramo como tool y, opcionalmente, especifique los argumentos en el objeto de opciones.

name
opcional - cadena
El nombre de la operación. Si no se proporciona, name utiliza de forma predeterminada el nombre de la función rastreada.
sessionId
opcional - cadena
El ID de la sesión de usuario subyacente. Consulte Seguimiento de sesiones de usuario para obtener más información.
mlApp
opcional - cadena
El nombre de la aplicación de ML a la que pertenece la operación. Consulte Trazar múltiples aplicaciones para obtener más información.

Ejemplo

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

Para rastrear una llamada a una herramienta, importe y llame al siguiente método con los argumentos enumerados a continuación:

import datadog.trace.api.llmobs.LLMObs;
LLMObs.startToolSpan(spanName, mlApp, sessionID);
spanName
opcional - Cadena
El nombre de la operación. Si no se proporciona, spanName utiliza de forma predeterminada el nombre de la función rastreada.
mlApp
opcional - Cadena
El nombre de la aplicación de ML a la que pertenece la operación. Proporcionar un valor no nulo anula el nombre de la aplicación de ML proporcionado al inicio de la aplicación. Consulte Trazar múltiples aplicaciones para obtener más información.
sessionId
opcional - Cadena
El ID de la sesión de usuario subyacente. Consulte Seguimiento de sesiones de usuario para obtener más información.

Tareas

Para rastrear un tramo de tarea, utilice el decorador de función LLMObs.task().

name
opcional - cadena
El nombre de la operación. Si no se proporciona, name utiliza de forma predeterminada el nombre de la función rastreada.
session_id
opcional - cadena
El ID de la sesión de usuario subyacente. Consulte Seguimiento de sesiones de usuario para obtener más información.
ml_app
opcional - cadena
El nombre de la aplicación de ML a la que pertenece la operación. Consulte Trazar múltiples aplicaciones para obtener más información.

Ejemplo

from ddtrace.llmobs.decorators import task

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

Para rastrear un tramo de tarea, especifique el tipo de tramo como task y, opcionalmente, especifique los argumentos en el objeto de opciones.

name
opcional - cadena
El nombre de la operación. Si no se proporciona, name utiliza de forma predeterminada el nombre de la función rastreada.
sessionId
opcional - cadena
El ID de la sesión de usuario subyacente. Consulte Seguimiento de sesiones de usuario para obtener más información.
mlApp
opcional - cadena
El nombre de la aplicación de ML a la que pertenece la operación. Consulte Trazar múltiples aplicaciones para obtener más información.

Ejemplo

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

Para rastrear un tramo de tarea, importe y llame al siguiente método con los argumentos enumerados a continuación:

import datadog.trace.api.llmobs.LLMObs;
LLMObs.startTaskSpan(spanName, mlApp, sessionID);
spanName
opcional - Cadena
El nombre de la operación. Si no se proporciona, spanName utiliza de forma predeterminada el nombre de la función rastreada.
mlApp
opcional - Cadena
El nombre de la aplicación de ML a la que pertenece la operación. Proporcionar un valor no nulo anula el nombre de la aplicación de ML proporcionado al inicio de la aplicación. Consulte Trazar múltiples aplicaciones para obtener más información.
sessionId
opcional - Cadena
El ID de la sesión de usuario subyacente. Consulte Seguimiento de sesiones de usuario para obtener más información.

Incrustaciones

Para rastrear una operación de incrustación, utilice el decorador de función LLMObs.embedding().

Nota: La anotación de la entrada de un tramo de incrustación requiere un formato diferente al de otros tipos de tramo. Consulte Enriquecimiento de tramos para obtener más detalles sobre cómo especificar las entradas de incrustación.

model_name
obligatorio - cadena
El nombre del LLM invocado.
name
opcional - cadena
El nombre de la operación. Si no se proporciona, name se establece en el nombre de la función rastreada.
model_provider
opcional - cadena - predeterminado: "custom"
session_id
opcional - cadena
El ID de la sesión de usuario subyacente. Consulte Seguimiento de sesiones de usuario para obtener más información.
ml_app
opcional - cadena
El nombre de la aplicación de ML a la que pertenece la operación. Consulte Trazar múltiples aplicaciones para obtener más información.

Ejemplo

from ddtrace.llmobs.decorators import embedding

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

Para rastrear una operación de incrustación, especifique el tipo de tramo como embedding y, opcionalmente, especifique argumentos en el objeto de opciones.

Nota: La anotación de la entrada de un tramo de incrustación requiere un formato diferente al de otros tipos de tramo. Consulte Enriquecimiento de tramos para obtener más detalles sobre cómo especificar las entradas de incrustación.

modelName
opcional - cadena - predeterminado: "custom"
El nombre del LLM invocado.
name
opcional - cadena
El nombre de la operación. Si no se proporciona, name se establece en el nombre de la función rastreada.
modelProvider
opcional - cadena - predeterminado: "custom"
El nombre del proveedor del modelo.
sessionId
opcional - cadena
El ID de la sesión de usuario subyacente. Consulte Seguimiento de sesiones de usuario para obtener más información.
mlApp
opcional - cadena
El nombre de la aplicación de ML a la que pertenece la operación. Consulte Trazar múltiples aplicaciones para obtener más información.

Ejemplo

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

Recuperaciones

Para rastrear un tramo de recuperación, utilice el decorador de función ddtrace.llmobs.decorators.retrieval().

Nota: La anotación de la salida de un tramo de recuperación requiere un formato diferente al de otros tipos de tramos. Consulte Enriquecimiento de tramos para obtener más detalles sobre cómo especificar las salidas de recuperación.

name
opcional - cadena
El nombre de la operación. Si no se proporciona, name utiliza de forma predeterminada el nombre de la función rastreada.
session_id
opcional - cadena
El ID de la sesión de usuario subyacente. Consulte Seguimiento de sesiones de usuario para obtener más información.
ml_app
opcional - cadena
El nombre de la aplicación de ML a la que pertenece la operación. Consulte Trazar múltiples aplicaciones para obtener más información.

Ejemplo

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

Para rastrear un tramo de recuperación, especifique el tipo de tramo como retrieval y, opcionalmente, especifique los siguientes argumentos en el objeto de opciones.

Nota: La anotación de la salida de un tramo de recuperación requiere un formato diferente al de otros tipos de tramos. Consulte Enriquecimiento de tramos para obtener más detalles sobre cómo especificar las salidas de recuperación.

name
opcional - cadena
El nombre de la operación. Si no se proporciona, name utiliza de forma predeterminada el nombre de la función rastreada.
sessionId
opcional - cadena
El ID de la sesión de usuario subyacente. Consulte Seguimiento de sesiones de usuario para obtener más información.
mlApp
opcional - cadena
El nombre de la aplicación de ML a la que pertenece la operación. Consulte Trazar múltiples aplicaciones para obtener más información.

Ejemplo

A continuación también se incluye un ejemplo de cómo anotar un tramo. Consulte Enriquecimiento de tramos para obtener más información.

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)

Tramos anidados

Iniciar un nuevo tramo antes de que finalice el tramo actual rastrea automáticamente una relación padre-hijo entre ambos tramos. El tramo principal representa la operación más grande, mientras que el tramo secundario representa una suboperación anidada más pequeña dentro de esta.

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();
  }
}

Enriquecer tramos

El metrics parámetro aquí se refiere a valores numéricos adjuntos como atributos en tramos individuales, no a métricas de la plataforma Datadog. Para ciertas claves reconocidas como input_tokens, output_tokens, y total_tokens, Datadog utiliza estos atributos de tramo para generar métricas de plataforma correspondientes (como ml_obs.span.llm.input.tokens) para su uso en tableros y monitores.

El SDK proporciona el método LLMObs.annotate() para enriquecer los tramos con entradas, salidas y metadatos.

El método LLMObs.annotate() acepta los siguientes argumentos:

span
opcional - Tramo - predeterminado: el tramo activo actual
El tramo que se va a anotar. Si span no se proporciona (como cuando se usan decoradores de funciones), el SDK anota el tramo activo actual.
input_data
opcional - tipo serializable en JSON o lista de diccionarios
Ya sea un tipo serializable en JSON (para tramos que no son de LLM) o una lista de diccionarios con este formato: {"content": \"...\", \"role\": \"...\", \"tool_calls\": ..., \"tool_results\": ..., \"audio_parts\": ..., \"image_parts\": ...}, donde "tool_calls" son una lista opcional de diccionarios de llamadas a herramientas con las claves requeridas: "name", "arguments", y claves opcionales: "tool_id", "type", y "tool_results" son una lista opcional de diccionarios de resultados de herramientas con la clave requerida: "result", y claves opcionales: "name", "tool_id", "type" para escenarios de llamada a funciones. "audio_parts" y "image_parts" son listas opcionales de diccionarios de medios para tramos multimodales, cada uno con un "mime_type" requerido y "content" (medios codificados en base64, incluidos directamente). Nota: Los tramos de incrustación son un caso especial y requieren una cadena o un diccionario (o una lista de diccionarios) con este formato: {"text": "..."}.
output_data
opcional - tipo serializable en JSON o lista de diccionarios
Ya sea un tipo serializable en JSON (para tramos que no son de LLM) o una lista de diccionarios con este formato: {"content": "...", "role": "...", "tool_calls": ..., "audio_parts": ..., "image_parts": ...}, donde "tool_calls" son una lista opcional de diccionarios de llamadas a herramientas con las claves requeridas: "name", "arguments", y claves opcionales: "tool_id", "type" para escenarios de llamada a funciones. "audio_parts" y "image_parts" son listas opcionales de diccionarios de medios para tramos multimodales, cada uno con un "mime_type" requerido y "content" (medios codificados en base64, incluidos directamente). Nota: Los tramos de recuperación son un caso especial y requieren una cadena o un diccionario (o una lista de diccionarios) con este formato: {"text": "...", "name": "...", "score": float, "id": "..."}.
tool_definitions
opcional - lista de diccionarios
Lista de diccionarios de definición de herramientas para escenarios de llamada a funciones. Cada definición de herramienta debe tener una clave "name": "..." obligatoria y claves "description": "..." y "schema": {...} opcionales.
metadata
opcional - diccionario
Un diccionario de pares clave-valor serializables en JSON que los usuarios pueden agregar como información de metadatos relevante para la operación de entrada o salida descrita por el tramo (model_temperature, max_tokens, top_k, etc.).
metrics
opcional - diccionario
Un diccionario de claves serializables en JSON y valores numéricos que los usuarios pueden agregar como métricas relevantes para la operación descrita por el tramo (input_tokens, output_tokens, total_tokens, time_to_first_token, etc.). La unidad para time_to_first_token está en segundos, similar a la métrica duration que se emite de forma predeterminada.
tags
opcional - diccionario
Un diccionario de pares clave-valor serializables en JSON que los usuarios pueden agregar como etiquetas en el tramo. Ejemplos de claves: session, env, system y version. Para obtener más información sobre las etiquetas, consulte Getting Started with Tags.
cost_tags
opcional - lista de cadenas
Una lista de claves de etiqueta (ya establecidas con tags o anotadas previamente en el mismo tramo) para propagar como etiquetas personalizadas en las métricas de costo y tokens de LLM generadas. Las entradas que no hacen referencia a una clave de etiqueta existente se omiten. Consulte Supervisión de costos para obtener más detalles.

Ejemplo

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

@llm(model_name="gpt-realtime", model_provider="openai")
def voice_turn(user_audio_bytes):
    import base64
    resp = ... # multimodal (audio) llm call here
    LLMObs.annotate(
        span=None,
        input_data=[
            {
                "role": "user",
                "content": "Hey, how are you?",  # transcript of the input audio
                "audio_parts": [
                    {"mime_type": "audio/wav", "content": base64.b64encode(user_audio_bytes).decode("utf-8")}
                ],
            }
        ],
        output_data=[
            {
                "role": "assistant",
                "content": "Hey! I'm doing great, thanks for asking. How about you?",
                "audio_parts": [
                    {"mime_type": "audio/wav", "content": base64.b64encode(resp.audio_bytes).decode("utf-8")}
                ],
            }
        ],
    )
    return resp

@llm(model_name="gpt-4o", model_provider="openai")
def describe_image(image_bytes):
    import base64
    resp = ... # multimodal (vision) llm call here
    LLMObs.annotate(
        span=None,
        input_data=[
            {
                "role": "user",
                "content": "What is in this image?",
                "image_parts": [
                    {"mime_type": "image/png", "content": base64.b64encode(image_bytes).decode("utf-8")}
                ],
            }
        ],
        output_data=[{"role": "assistant", "content": "The image shows a golden retriever puppy."}],
    )
    return resp

Los mensajes anotados con audio_parts o image_parts se muestran como reproductores de audio e imágenes integrados en la visualización de la traza. Para ver ejemplos renderizados, formatos admitidos, límites de tamaño e integraciones que completan estos campos automáticamente, consulte Soporte multimodal.

El SDK proporciona el método llmobs.annotate() para anotar tramos con entradas, salidas y metadatos.

El método LLMObs.annotate() acepta los siguientes argumentos:

span
opcional - Tramo - predeterminado: el tramo activo actual
El tramo que se va a anotar. Si span no se proporciona (como cuando se usan envoltorios de funciones), el SDK anota el tramo activo actual.
annotationOptions
requerido - objeto
Un objeto de diferentes tipos de datos con el cual anotar el tramo.

El objeto annotationOptions puede contener lo siguiente:

inputData
opcional - tipo serializable en JSON o lista de objetos
Ya sea un tipo serializable en JSON (para tramos que no son de LLM) o una lista de diccionarios con este formato: {role: \"...\", content: \"...\", audioParts: [...], imageParts: [...]} (para tramos de LLM). audioParts y imageParts son listas opcionales de objetos multimedia para tramos multimodales, cada uno con un mimeType requerido y content (medios codificados en base64, incluidos directamente). Nota: Los tramos de incrustación son un caso especial y requieren una cadena o un objeto (o una lista de objetos) con este formato: {text: "..."}.
outputData
opcional - tipo serializable en JSON o lista de objetos
Ya sea un tipo serializable en JSON (para tramos que no son de LLM) o una lista de objetos con este formato: {role: "...", content: "...", audioParts: [...], imageParts: [...]} (para tramos de LLM). audioParts y imageParts son listas opcionales de objetos multimedia para tramos multimodales, cada uno con un mimeType requerido y content (medios codificados en base64, incluidos directamente). Nota: Los tramos de recuperación son un caso especial y requieren una cadena o un objeto (o una lista de objetos) con este formato: {text: "...", name: "...", score: number, id: "..."}.
metadata
opcional - objeto
Un objeto de pares clave-valor serializables en JSON que los usuarios pueden agregar como información de metadatos relevante para la operación de entrada o salida descrita por el tramo (model_temperature, max_tokens, top_k, etc.).
metrics
opcional - objeto
Un objeto de claves serializables en JSON y valores numéricos que los usuarios pueden agregar como métricas relevantes para la operación descrita por el tramo (input_tokens, output_tokens, total_tokens, etc.).
tags
opcional - objeto
Un objeto de pares clave-valor serializables en JSON que los usuarios pueden agregar como etiquetas relacionadas con el contexto del tramo (session, environment, system, versioning, etc.). Para obtener más información sobre las etiquetas, consulte Getting Started with Tags.
costTags
opcional - matriz de cadenas
Una lista de claves de etiqueta (ya establecidas con tags o anotadas previamente en el mismo tramo) para propagar como etiquetas personalizadas en las métricas de costo y tokens de LLM generadas. Las entradas que no hacen referencia a una clave de etiqueta existente se omiten. Consulte Supervisión de costos para obtener más detalles.

Ejemplo

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)

function voiceTurn (userAudioBytes) {
  const resp = ... // multimodal (audio) llm call here
  llmobs.annotate({
    inputData: [
      {
        role: "user",
        content: "Hey, how are you?", // transcript of the input audio
        audioParts: [{ mimeType: "audio/wav", content: userAudioBytes.toString("base64") }]
      }
    ],
    outputData: [
      {
        role: "assistant",
        content: "Hey! I'm doing great, thanks for asking. How about you?",
        audioParts: [{ mimeType: "audio/wav", content: resp.audioBuffer.toString("base64") }]
      }
    ]
  })
  return resp
}
voiceTurn = llmobs.wrap({ kind: 'llm', modelName: 'gpt-audio', modelProvider: 'openai' }, voiceTurn)

function describeImage (imageBytes) {
  const resp = ... // multimodal (vision) llm call here
  llmobs.annotate({
    inputData: [
      {
        role: "user",
        content: "What is in this image?",
        imageParts: [{ mimeType: "image/png", content: imageBytes.toString("base64") }]
      }
    ],
    outputData: [{ role: "assistant", content: "The image shows a golden retriever puppy." }]
  })
  return resp
}
describeImage = llmobs.wrap({ kind: 'llm', modelName: 'gpt-4o', modelProvider: 'openai' }, describeImage)

Los mensajes anotados con audioParts o imageParts se muestran como reproductores de audio e imágenes integrados en la visualización de la traza. Para ver ejemplos renderizados, formatos admitidos, límites de tamaño e integraciones que completan estos campos automáticamente, consulte Soporte multimodal.

Para las finalizaciones de chat de audio de OpenAI, audioParts también se capturan automáticamente mediante las integraciones de LLM de Datadog, sin necesidad de anotación manual. El SDK de Node.js no captura imageParts automáticamente. Anótelos como se muestra arriba.

El SDK proporciona varios métodos para anotar tramos con entradas, salidas, métricas y metadatos.

Anotación de entradas y salidas

Utilice el método miembro annotateIO() de la interfaz LLMObsSpan para agregar datos estructurados de entrada y salida a un LLMObsSpan. Esto incluye argumentos opcionales y objetos de mensaje de LLM.

Argumentos

Si un argumento es nulo o está vacío, no sucede nada. Por ejemplo, si inputData es una cadena no vacía mientras que outputData es nulo, entonces solo se registra inputData.

inputData
opcional - String o List<LLMObs.LLMMessage>
Ya sea una cadena (para tramos que no son de LLM) o una lista de LLMObs.LLMMessage para tramos de LLM.
outputData
opcional - String o List<LLMObs.LLMMessage>
Ya sea una cadena (para tramos que no son de LLM) o una lista de LLMObs.LLMMessage para tramos de LLM.

Mensajes de LLM

Los tramos de LLM deben anotarse con mensajes de LLM utilizando el objeto LLMObs.LLMMessage.

El objeto LLMObs.LLMMessage se puede instanciar llamando a LLMObs.LLMMessage.from() con los siguientes argumentos:

role
obligatorio - String
Una cadena que describe el rol del autor del mensaje.
content
obligatorio - String
Una cadena que contiene el contenido del mensaje.

Ejemplo

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;
  }
}

Agregar métricas

Agregar métricas en bloque

El método miembro setMetrics() de la interfaz LLMObsSpan acepta los siguientes argumentos para adjuntar múltiples métricas en bloque:

Argumentos
metrics
obligatorio - Map<String, Number>
Un mapa de claves serializables en JSON y valores numéricos que los usuarios pueden agregar para registrar métricas relevantes para la operación descrita por el tramo (por ejemplo, input_tokens, output_tokens o total_tokens).

Agregar una sola métrica

El método miembro setMetric() de la interfaz LLMObsSpan acepta los siguientes argumentos para adjuntar una sola métrica:

Argumentos
key
obligatorio - CharSequence
El nombre de la métrica.
value
obligatorio - int, long o double
El valor de la métrica.

Ejemplos

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;
  }
}

Agregar etiquetas

Para obtener más información sobre las etiquetas, consulte Getting Started with Tags.

Agregar etiquetas en bloque

El método miembro setTags() de la interfaz LLMObsSpan acepta los siguientes argumentos para adjuntar varias etiquetas en bloque:

Argumentos
tags
obligatorio - Map<String, Object>
Un mapa de pares clave-valor serializables en JSON que los usuarios pueden agregar como etiquetas para describir el contexto del tramo (por ejemplo, session, environment, system o version).

Agregar una sola etiqueta

El método miembro setTag() de la interfaz LLMObsSpan acepta los siguientes argumentos para adjuntar una sola etiqueta:

Argumentos
key
obligatorio - String
La clave de etiqueta.
value
obligatorio - int, long, double, boolean o String
El valor de la etiqueta.

Ejemplos

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;
  }
}

Anotación de errores

El método miembro addThrowable() de la interfaz LLMObsSpan acepta el siguiente argumento para adjuntar un throwable con una traza de pila:

Argumentos
throwable
obligatorio - Throwable
El throwable/excepción que ocurrió.

Agregar un mensaje de error

El método miembro setErrorMessage() de la interfaz LLMObsSpan acepta el siguiente argumento para adjuntar una cadena de error:

Argumentos
errorMessage
obligatorio - String
El mensaje del error.

Establecer una marca de error

El método miembro setError() de la interfaz LLMObsSpan acepta el siguiente argumento para indicar un error en la operación:

Argumentos
error
requerido - booleano
true si el tramo dio error.

Ejemplos

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;
  }
}

Anotación de metadatos

El método miembro setMetadata() de la interfaz LLMObsSpan acepta los siguientes argumentos:

metadata
obligatorio - Map<String, Object>
Un mapa de pares clave-valor serializables en JSON que contiene metadatos relevantes para la operación de entrada o salida descrita por el tramo.

Ejemplo

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;
  }
}

Anotación de tramos auto-instrumentados

El método LLMObs.annotation_context() del SDK devuelve un administrador de contexto que se puede utilizar para modificar todos los tramos auto-instrumentados iniciados mientras el contexto de anotación está activo.

El método LLMObs.annotation_context() acepta los siguientes argumentos:

name
opcional - str
Nombre que sobrescribe el nombre del tramo para cualquier tramo auto-instrumentado que se inicie dentro del contexto de anotación.
prompt
opcional - diccionario
Un diccionario que representa el prompt utilizado para una llamada a LLM. Consulte la documentación del objeto Prompt para obtener el esquema completo y las claves admitidas. También puede importar el objeto Prompt desde ddtrace.llmobs.utils y pasarlo como el argumento prompt. Nota: Este argumento solo se aplica a los tramos de LLM.
tags
opcional - diccionario
Un diccionario de pares clave-valor serializables en JSON que los usuarios pueden agregar como etiquetas en el tramo. Ejemplos de claves: session, env, system y version. Para obtener más información sobre las etiquetas, consulte Getting Started with Tags.
cost_tags
opcional - lista de cadenas
Una lista de claves de etiqueta para propagar como etiquetas personalizadas en las métricas de costo y tokens de LLM generadas. Cada entrada debe hacer referencia a una clave presente en tags al inicio del tramo (proporcionada al mismo contexto o a un contexto principal); las claves de etiqueta agregadas posteriormente con LLMObs.annotate() no se conservan. Consulte Supervisión de costos para obtener más detalles.

Ejemplo

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

El llmobs.annotationContext() del SDK acepta una función de devolución de llamada que se puede utilizar para modificar todos los tramos autoinstrumentados iniciados mientras se está dentro del contexto de la función de devolución de llamada.

El método llmobs.annotationContext() acepta las siguientes opciones en el primer argumento:

name
opcional - str
Nombre que sobrescribe el nombre del tramo para cualquier tramo auto-instrumentado que se inicie dentro del contexto de anotación.
tags
opcional - objeto
Un objeto de pares clave-valor serializables en JSON que los usuarios pueden agregar como etiquetas en el tramo. Ejemplos de claves: session, env, system y version. Para obtener más información sobre las etiquetas, consulte Getting Started with Tags.
costTags
opcional - matriz de cadenas
Una lista de claves de etiqueta para propagar como etiquetas personalizadas en las métricas de costo y tokens de LLM generadas. Cada entrada debe hacer referencia a una clave presente en tags al inicio del tramo (proporcionada al mismo contexto o a un contexto principal); las claves de etiqueta agregadas posteriormente con llmobs.annotate() no se conservan. Consulte Supervisión de costos para obtener más detalles.

Ejemplo

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;
    });
}

Seguimiento de prompts

Adjunte metadatos de prompt estructurados al tramo del LLM para que pueda reproducir resultados, auditar cambios y comparar el rendimiento de los prompts entre versiones. Al usar plantillas, Agent Observability también proporciona seguimiento de versiones basado en cambios en el contenido de la plantilla.

Use LLMObs.annotation_context(prompt=...) para adjuntar metadatos de prompt antes de la llamada al LLM. Para obtener más detalles sobre la anotación de tramos, consulte Enriquecimiento de tramos.

Argumentos

prompt
obligatorio - diccionario
Un diccionario escrito que sigue el esquema de Prompt a continuación.

Claves admitidas:

  • id (str): Identificador lógico para este prompt. Debe ser único por ml_app. Se establece de forma predeterminada en {ml_app}-unnamed_prompt
  • version (str): Etiqueta de versión para el prompt (por ejemplo, “1.0.0”). Consulte seguimiento de versiones para obtener más detalles.
  • variables (Dict[str, str]): Variables utilizadas para completar los marcadores de posición de la plantilla.
  • template (str): Cadena de plantilla con marcadores de posición (por ejemplo, “Traducir {{text}} a {{lang}}”).
  • chat_template (List[Message]): Formato de plantilla de mensajes múltiples. Proporcione una lista de { "role": "<role>", "content": "<template string with placeholders>" } objetos.
  • tags (Dict[str, str]): Etiquetas para adjuntar a la ejecución del prompt.
  • rag_context_variables (List[str]): Claves de variables que contienen contenido de ground-truth/contexto. Se utiliza para la detección de alucinaciones.
  • rag_query_variables (List[str]): Claves de variables que contienen la consulta del usuario. Se utiliza para la detección de alucinaciones.

Ejemplo: prompt de plantilla única

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

Ejemplo: plantillas de prompt de LangChain

Cuando utilice la creación de plantillas de prompt de LangChain con auto-instrumentación, asigne nombres significativos a las variables de las plantillas. La auto-instrumentación utiliza estos nombres para identificar los 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

Use llmobs.annotationContext({ prompt: ... }, () => { ... }) para adjuntar metadatos de prompt antes de la llamada al LLM. Para obtener más detalles sobre la anotación de tramos, consulte Enriquecimiento de tramos.

Argumentos

prompt
obligatorio - objeto
Un objeto que sigue el esquema de Prompt a continuación.

Propiedades admitidas:

  • id (string): Identificador lógico para este prompt. Debe ser único por ml_app. Se establece de forma predeterminada en {ml_app}-unnamed_prompt
  • version (string): Etiqueta de versión para el prompt (por ejemplo, “1.0.0”). Consulte seguimiento de versiones para obtener más detalles.
  • variables (Record<string, string>): Variables utilizadas para completar los marcadores de posición de la plantilla.
  • template (string | List[Message]): Template string with placeholders (for example, "Translate {{text}} a {{lang}}\"). Alternatively, a list of { \"role\": \"<role>\", \"content\": \"<template string with placeholders>\" } objetos.
  • tags (Record<string, string>): Etiquetas para adjuntar a la ejecución del prompt.
  • contextVariables (string[]): Claves de variables que contienen contenido de ground-truth/contexto. Se utiliza para la detección de alucinaciones.
  • queryVariables (string[]): Claves de variables que contienen la consulta del usuario. Se utiliza para la detección de alucinaciones.

Ejemplo: prompt de plantilla única

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}"}]
        });
    });
}

Notas

  • La anotación de un prompt solo está disponible en tramos de LLM.
  • Coloque la anotación inmediatamente antes de la llamada al proveedor para que se aplique al tramo de LLM correcto.
  • Utilice un prompt único id para distinguir diferentes prompts dentro de su aplicación.
  • Mantenga las plantillas estáticas utilizando la sintaxis de marcador de posición (como {{variable_name}}) and define dynamic content in the sección de variables.
  • Para múltiples llamadas a LLM auto-instrumentadas dentro de un bloque, utilice un contexto de anotación para aplicar los mismos metadatos de prompt en todas las llamadas. Consulte Anotación de tramos auto-instrumentados.

Seguimiento de versiones

Agent Observability proporciona versiones automáticas para sus prompts cuando no se especifica una versión explícita. Cuando proporciona un template o chat_template en los metadatos de su prompt sin una etiqueta version, el sistema genera automáticamente una versión calculando un hash del contenido de la plantilla. Si proporciona una etiqueta version, Agent Observability utiliza la etiqueta de versión que especificó en lugar de generar una automáticamente.

El sistema de versiones funciona de la siguiente manera:

  • Versiones automáticas: Cuando no se proporciona una etiqueta version, Agent Observability calcula un hash del contenido de template o chat_template para generar automáticamente un identificador de versión numérico
  • Versiones manuales: Cuando se proporciona una etiqueta version, Agent Observability utiliza la etiqueta de versión que especificó exactamente como se proporcionó
  • Historial de versiones: Tanto las versiones generadas automáticamente como las manuales se mantienen en el historial de versiones para realizar un seguimiento de la evolución de los prompts a lo largo del tiempo

Esto le brinda la flexibilidad de confiar en la gestión automática de versiones basada en cambios en el contenido de la plantilla, o mantener un control total sobre el versionado con sus propias etiquetas de versión.

Captura de intención de MCP

Para obtener información sobre por qué se llamaron sus herramientas MCP, habilite la captura de intención en su servidor MCP. Cuando se habilita, el SDK agrega un argumento a cada herramienta del servidor MCP solicitando que el modelo que realiza la llamada describa por qué eligió llamar a la herramienta. La intención se registra en el tramo de la herramienta, lo que le ayuda a mejorar las definiciones y descripciones de sus herramientas.

Habilite la captura de intención de MCP con la variable de entorno DD_MCP_CAPTURE_INTENT:

DD_MCP_CAPTURE_INTENT=1 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>

O bien, habilítela mediante programación con el parámetro capture_intent en LLMObs.enable():

from ddtrace.llmobs import LLMObs
LLMObs.enable(
  ml_app="<YOUR_ML_APP_NAME>",
  capture_intent=True,
)

Monitor de costos

Adjunte métricas de tokens (para el seguimiento automático de costos) o métricas de costos (para el seguimiento manual de costos) a sus tramos de LLM/embedding. Las métricas de tokens permiten a Datadog calcular los costos utilizando los precios del proveedor, mientras que las métricas de costos le permiten suministrar sus propios precios cuando utiliza modelos personalizados o no compatibles. Para obtener más detalles, vea Costs.

Si utiliza la instrumentación automática, las métricas de tokens y de costos aparecen en sus tramos automáticamente. Si está realizando la instrumentación manualmente, siga la guía a continuación.

En este contexto, "métricas de tokens" y "métricas de costos" se refieren a pares clave-valor numéricos que usted adjunta a los tramos a través del metrics parámetro del LLMObs.annotate() Método. Estos son distintos de las métricas de Agent Observability de la plataforma Datadog. Para claves reconocidas como input_tokens, output_tokens, input_cost, y output_cost, Datadog utiliza estos atributos de tramo para generar métricas de plataforma correspondientes (como ml_obs.span.llm.input.cost) para su uso en paneles y monitores.

Caso de uso: Uso de un proveedor de modelos común

Datadog admite proveedores de modelos comunes como OpenAI, Azure OpenAI, Anthropic y Google Gemini. Al usar estos proveedores, solo necesita anotar su solicitud de LLM con el nombre del modelo, el proveedor del modelo y el uso de tokens. Datadog calcula automáticamente el costo estimado según los precios del proveedor.

Para obtener más información sobre lo que representa cada token y cómo los calcula Datadog, consulte Cómo se calculan los recuentos de tokens.

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
function llmCall (prompt) {
  const resp = ... // llm call here
  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
}
llmCall = llmobs.wrap({ kind: 'llm', modelName: 'gpt-5.1', modelProvider: 'openai' }, llmCall)
import datadog.trace.api.llmobs.LLMObs;
import datadog.trace.api.llmobs.LLMObsSpan;
import java.util.Map;

public class MyJavaClass {
  public String llmCall(String prompt) {
    LLMObsSpan llmSpan = LLMObs.startLLMSpan("llm-call", "gpt-5.1", "openai", null, null);
    String resp = ... // llm call here
    llmSpan.setMetrics(Map.of(
      "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
    ));
    llmSpan.finish();
    return resp;
  }
}

Caso de uso: Uso de un modelo personalizado

Para modelos personalizados o no admitidos, debe anotar el tramo manualmente con los datos de costo en dólares.

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
function llmCall (prompt) {
  const resp = ... // llm call here
  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
}
llmCall = llmobs.wrap({ kind: 'llm', modelName: 'custom_model', modelProvider: 'model_provider' }, llmCall)
import datadog.trace.api.llmobs.LLMObs;
import datadog.trace.api.llmobs.LLMObsSpan;
import java.util.Map;

public class MyJavaClass {
  public String llmCall(String prompt) {
    LLMObsSpan llmSpan = LLMObs.startLLMSpan("llm-call", "custom_model", "model_provider", null, null);
    String resp = ... // llm call here
    llmSpan.setMetrics(Map.of(
      "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
    ));
    llmSpan.finish();
    return resp;
  }
}

Adición de etiquetas personalizadas a las métricas de costo y tokens

De forma predeterminada, las métricas de costo y tokens de LLM incluyen un conjunto fijo de etiquetas predeterminadas como model_name, model_provider y ml_app. Para desglosar el gasto en LLM por atributos específicos de su aplicación (como equipo, cliente o función), marque un subconjunto de las claves de etiqueta existentes del tramo para propagarlas a esas métricas como etiquetas personalizadas. Para ver casos de uso de ejemplo como paneles y monitores personalizados, consulte Etiquetas personalizadas en métricas de costo y tokens.

Cada entrada debe ser una cadena y debe hacer referencia a una clave ya proporcionada a través del parámetro tags del tramo en el momento en que se aplica la anotación. Al anotar un solo tramo, la clave puede proporcionarse a través de tags en la misma llamada de anotación o en una anotación anterior en el mismo tramo. Al utilizar un contexto de anotación, solo califican las claves presentes en tags al inicio del tramo; las claves añadidas posteriormente mediante anotaciones de tramo individuales no se conservan. Las entradas que no hacen referencia a una clave de etiqueta existente se omiten.

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
    LLMObs.annotate(
        metrics={"input_tokens": 50, "output_tokens": 120, "total_tokens": 170},
        tags={"team": "nlp", "customer_tier": "enterprise", "host": "host_name"},
        cost_tags=["team", "customer_tier"],
    )
    return resp
function llmCall (prompt) {
  const resp = ... // llm call here
  llmobs.annotate({
    metrics: { input_tokens: 50, output_tokens: 120, total_tokens: 170 },
    tags: { team: 'nlp', customer_tier: 'enterprise', host: 'host_name' },
    costTags: ['team', 'customer_tier']
  })
  return resp
}
llmCall = llmobs.wrap({ kind: 'llm', modelName: 'gpt-5.1', modelProvider: 'openai' }, llmCall)

También puede propagar etiquetas de esta manera a través de un contexto de anotación para aplicarlas a todos los tramos auto-instrumentados iniciados dentro del contexto.

with LLMObs.annotation_context(
    tags={"team": "nlp", "customer_tier": "enterprise"},
    cost_tags=["team", "customer_tier"],
):
    resp = ... # llm call here
llmobs.annotationContext({
  tags: { team: 'nlp', customer_tier: 'enterprise' },
  costTags: ['team', 'customer_tier']
}, () => {
  const resp = ... // llm call here
})

Evaluaciones

El Agent Observability SDK proporciona métodos para exportar y enviar sus evaluaciones a Datadog.

Para crear evaluadores reutilizables basados en clases (BaseEvaluator, BaseSummaryEvaluator) con metadatos de resultados enriquecidos, consulte la Guía para desarrolladores de evaluaciones.

Las evaluaciones deben unirse a un solo tramo. Puede identificar el tramo de destino utilizando cualquiera de estos dos métodos:

  • Unión basada en etiquetas - Una evaluación utilizando un par clave-valor de etiqueta único que se establece en un solo tramo. La evaluación no se unirá si el par clave-valor de la etiqueta coincide con varios tramos o con ninguno.
  • Referencia directa al tramo - Una evaluación se une utilizando la combinación única del ID de traza y del ID de tramo del tramo.

Exportación de un tramo

LLMObs.export_span() se puede utilizar para extraer el contexto del tramo de un tramo. Este método es útil para asociar su evaluación con el tramo correspondiente.

Argumentos

El método LLMObs.export_span() acepta el siguiente argumento:

span
opcional - Tramo
El tramo del cual extraer el contexto (ID de traza y ID de tramo). Si no se proporciona (como al usar decoradores de funciones), el SDK exporta el tramo activo actual.

Ejemplo

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() se puede utilizar para extraer el contexto del tramo de un tramo. Necesitará usar este método para asociar su evaluación con el tramo correspondiente.

Argumentos

El método llmobs.exportSpan() acepta el siguiente argumento:

span
opcional - Tramo
El tramo del cual extraer el contexto (ID de traza y ID de tramo). Si no se proporciona (como al usar envoltorios de funciones), el SDK exporta el tramo activo actual.

Ejemplo

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)

Envío de evaluaciones

LLMObs.submit_evaluation() se puede usar para enviar su evaluación personalizada asociada con un tramo determinado.

LLMObs.submit_evaluation_for está obsoleto y se eliminará en la próxima versión principal de ddtrace (4.0). Para migrar, cambie el nombre de sus LLMObs.submit_evaluation_for llamadas con LLMObs.submit_evaluation.

Nota: Las evaluaciones personalizadas son evaluadores que usted implementa y aloja por su cuenta. Estas difieren de las evaluaciones listas para usar, las cuales son calculadas automáticamente por Datadog utilizando evaluadores integrados. Para configurar las evaluaciones listas para usar para su aplicación, utilice la página Agent Observability > Settings > Evaluations en Datadog.

El método LLMObs.submit_evaluation() acepta los siguientes argumentos:

label
obligatorio - cadena
El nombre de la evaluación.
metric_type
obligatorio - cadena
El tipo de evaluación. Debe ser categorical, score, boolean o json.
value
obligatorio - cadena, tipo numérico o dict
El valor de la evaluación. Debe ser una cadena (metric_type==categorical), entero/flotante (metric_type==score), booleano (metric_type==boolean) o dict (metric_type==json).
span
opcional - diccionario
Un diccionario que identifica de forma única el tramo asociado con esta evaluación. Debe contener span_id (cadena) y trace_id (cadena). Use LLMObs.export_span() para generar este diccionario.
span_with_tag_value
opcional - diccionario
Un diccionario que identifica de forma única el tramo asociado con esta evaluación. Debe contener tag_key (cadena) y tag_value (cadena).

Nota: Se requiere exactamente uno de span o span_with_tag_value. Proporcionar ambos, o ninguno, genera un ValueError.

ml_app
obligatorio - cadena
El nombre de la aplicación de ML.
timestamp_ms
opcional - entero
La marca de tiempo unix en milisegundos cuando se generó el resultado de la métrica de evaluación. Si no se proporciona, esto toma como valor predeterminado la hora actual.
tags
opcional - diccionario
Un diccionario de pares clave-valor de cadena que los usuarios pueden agregar como etiquetas con respecto a la evaluación. Para obtener más información sobre las etiquetas, consulte Getting Started with Tags.
assessment
opcional - cadena
Una evaluación de esta evaluación. Los valores aceptados son pass y fail.
reasoning
opcional - cadena
Una explicación textual del resultado de la evaluación.
metadata
opcional - diccionario
Un diccionario que contiene metadatos estructurados arbitrarios asociados con el resultado de la evaluación.

Ejemplo

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() se puede usar para enviar su evaluación personalizada asociada con un tramo determinado.

El método llmobs.submitEvaluation() acepta los siguientes argumentos:

span_context
obligatorio - diccionario
El contexto del tramo con el que asociar la evaluación. Este debería ser el resultado de LLMObs.export_span().
evaluationOptions
requerido - objeto
Un objeto de los datos de evaluación.

El objeto evaluationOptions puede contener lo siguiente:

label
obligatorio - cadena
El nombre de la evaluación.
metricType
obligatorio - cadena
El tipo de evaluación. Debe ser uno de “categorical”, “score”, “boolean” o “json”.
value
obligatorio - cadena o tipo numérico
El valor de la evaluación. Debe ser una cadena (para metric_type categórica), un número (para metric_type puntuación), un booleano (para metric_type booleana) o un objeto JSON (para metric_type json).
tags
opcional - diccionario
Un diccionario de pares clave-valor de cadena que los usuarios pueden agregar como etiquetas con respecto a la evaluación. Para obtener más información sobre las etiquetas, consulte Getting Started with Tags.
assessment
opcional - cadena
Una evaluación de esta evaluación. Los valores aceptados son pass y fail.
reasoning
opcional - cadena
Una explicación textual del resultado de la evaluación.
metadata
opcional - diccionario
Un objeto JSON que contiene metadatos estructurados arbitrarios asociados con el resultado de la evaluación.

Ejemplo

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)

Use LLMObs.SubmitEvaluation() para enviar su evaluación personalizada asociada con un tramo determinado.

El método LLMObs.SubmitEvaluation() acepta los siguientes argumentos:

llmObsSpan
obligatorio - LLMObsSpan
El contexto del tramo con el que asociar la evaluación.
label
obligatorio - String
El nombre de la evaluación.
categoricalValue o scoreValue
obligatorio - Cadena o doble
El valor de la evaluación. Debe ser una cadena (para evaluaciones categóricas) o un doble (para evaluaciones de puntuación).
tags
opcional - Mapa<Cadena, Objeto>
Un diccionario de pares clave-valor de cadena utilizados para etiquetar la evaluación. Para obtener más información sobre las etiquetas, consulte Getting Started with Tags.

Ejemplo

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;
  }
}

Envío de retroalimentación del usuario final

La retroalimentación del usuario final captura las aportaciones de los usuarios de su aplicación LLM, como calificaciones de pulgar hacia arriba o hacia abajo, si un usuario aceptó el cambio de un agent y comentarios de texto libre. A diferencia de una evaluación, la retroalimentación lleva la identidad de quien la envía y puede dirigirse a un tramo, una traza, una sesión o una entidad definida por el cliente. Para obtener más información, consulte End-User Feedback.

Utilice LLMObs.submit_feedback() para enviar la retroalimentación del usuario final asociada con un tramo, traza, sesión o entidad definida por el cliente.

El método LLMObs.submit_feedback() acepta los siguientes argumentos:

label
obligatorio - cadena
El nombre de la métrica de retroalimentación. No debe contener un ..
metric_type
obligatorio - cadena
El tipo de retroalimentación. Debe ser categorical, score, boolean, json o text.
value
obligatorio - string, tipo numérico, boolean o dict
El valor de la retroalimentación. Debe ser un string (metric_type==categorical o metric_type==text), un integer o float (metric_type==score), un boolean (metric_type==boolean) o un dict (metric_type==json).
submitter
obligatorio - diccionario
Un diccionario que identifica quién envió la retroalimentación. Debe contener un id (cadena) que no esté vacío y puede contener un type (cadena) opcional, como user.
span
opcional - diccionario
Un diccionario que identifica el tramo asociado con esta retroalimentación. Use LLMObs.export_span() para generar este diccionario.
span_id
opcional - cadena
El ID del tramo asociado con esta retroalimentación.
trace_id
opcional - cadena
El ID de la traza asociada con esta retroalimentación.
session_id
opcional - cadena
El ID de la sesión asociada con esta retroalimentación.
feedback_join_key
opcional - cadena
Una clave definida por el cliente asociada con esta retroalimentación, como un ID de incidente o un ID de ticket. Para conectar la retroalimentación con sus tramos, primero anótelos con una etiqueta feedback_join_key que contenga el mismo valor. Consulte Enriquecimiento de tramos.

Nota: Se requiere exactamente uno de span, span_id, trace_id, session_id o feedback_join_key. Proporcionar más de uno, o ninguno, genera un ValueError.

ml_app
opcional - cadena
El nombre de la aplicación de ML. Si no se proporciona, esto toma como valor predeterminado la aplicación de ML configurada para el SDK.
timestamp_ms
opcional - entero
La marca de tiempo Unix en milisegundos cuando se generó la retroalimentación. Si no se proporciona, esto toma como valor predeterminado la hora actual.
tags
opcional - diccionario
Un diccionario de pares clave-valor de string que los usuarios pueden agregar como etiquetas con respecto a la retroalimentación. Para obtener más información sobre las etiquetas, consulte Getting Started with Tags.
assessment
opcional - cadena
Una valoración de esta retroalimentación. Los valores aceptados son pass y fail.
reasoning
opcional - cadena
Una explicación textual de la retroalimentación.

Ejemplo

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)

    # submitting feedback for a trace
    LLMObs.submit_feedback(
        label="thumbs",
        metric_type="categorical",
        value="down",
        submitter={"id": "user-123", "type": "user"},
        trace_id=span_context["trace_id"],
        assessment="fail",
    )

    # connecting the span to a customer-defined entity
    LLMObs.annotate(tags={"feedback_join_key": "incident-123"})

    # submitting feedback for that entity
    LLMObs.submit_feedback(
        label="user_comment",
        metric_type="text",
        value="The investigation missed the customer impact.",
        submitter={"id": "user-123", "type": "user"},
        feedback_join_key="incident-123",
    )
    return completion

Utilice llmobs.submitFeedback() para enviar la retroalimentación del usuario final asociada con un tramo, traza, sesión o entidad definida por el cliente.

El método llmobs.submitFeedback() acepta un objeto de opciones con las siguientes propiedades:

label
obligatorio - cadena
El nombre de la métrica de retroalimentación. No debe contener un ..
metricType
obligatorio - cadena
El tipo de retroalimentación. Debe ser uno de categorical, score, boolean, json o text.
value
obligatorio - string, número, boolean, o object
El valor de la retroalimentación. Debe ser una cadena (para los tipos de métrica categorical y text), un número (para score), un booleano (para boolean) o un objeto JSON (para json).
submitter
requerido - objeto
Un object que identifica quién envió la retroalimentación. Debe contener un id (cadena) que no esté vacío y puede contener un type (cadena) opcional, como user.
span
opcional - objeto
El contexto del tramo al que se adjuntará la retroalimentación. Esto debería ser el resultado de llmobs.exportSpan().
spanId
opcional - cadena
El ID del tramo al que se adjuntará la retroalimentación.
traceId
opcional - cadena
El ID de la traza al que se adjuntará la retroalimentación.
sessionId
opcional - cadena
El ID de la sesión a la que se adjuntará la retroalimentación.
feedbackJoinKey
opcional - cadena
Una clave definida por el cliente a la que se adjuntará la retroalimentación, como un ID de incidente o un ID de ticket. Establezca la misma clave en sus tramos para conectar la retroalimentación a ellos.

Nota: Se requiere exactamente uno de span, spanId, traceId, sessionId o feedbackJoinKey. Proporcionar más de uno, o ninguno, genera un error.

mlApp
opcional - cadena
El nombre de la aplicación de ML. Si no se proporciona, esto toma como valor predeterminado la aplicación de ML configurada para el SDK.
timestampMs
opcional - number
La marca de tiempo Unix en milisegundos cuando se generó la retroalimentación. Si no se proporciona, esto toma como valor predeterminado la hora actual.
tags
opcional - objeto
Un object de pares clave-valor de string que los usuarios pueden agregar como etiquetas con respecto a la retroalimentación. Para obtener más información sobre las etiquetas, consulte Getting Started with Tags.
assessment
opcional - cadena
Una valoración de esta retroalimentación. Los valores aceptados son pass y fail.
reasoning
opcional - cadena
Una explicación textual de la retroalimentación.

Ejemplo

function llmCall () {
  const completion = ... // user application logic to invoke LLM
  const spanContext = llmobs.exportSpan()

  // submitting feedback for a trace
  llmobs.submitFeedback({
    label: 'thumbs',
    metricType: 'boolean',
    value: true,
    submitter: { id: 'user-123', type: 'user' },
    traceId: spanContext.traceId,
    assessment: 'pass'
  })

  // connecting the span to a customer-defined entity
  llmobs.annotate({
    tags: { feedback_join_key: 'incident-123' }
  })

  // submitting feedback for that entity
  llmobs.submitFeedback({
    label: 'user_comment',
    metricType: 'text',
    value: 'This answer was helpful.',
    submitter: { id: 'user-123', type: 'user' },
    feedbackJoinKey: 'incident-123'
  })
  return completion
}
llmCall = llmobs.wrap({ kind: 'llm', name: 'invokeLLM', modelName: 'claude', modelProvider: 'anthropic' }, llmCall)

Utilice LLMObs.submitFeedback() para enviar la retroalimentación del usuario final asociada con un tramo, traza, sesión o entidad definida por el cliente. Cree la retroalimentación con LLMObs.Feedback.builder().

El generador acepta los siguientes métodos:

label(String label)
Obligatorio
El nombre de la métrica de retroalimentación. No debe contener un ..
categoricalValue(String), scoreValue(double), booleanValue(boolean), jsonValue(Map<String, Object>) o textValue(String)
Obligatorio
El valor de la retroalimentación. Establezca exactamente uno de estos métodos, el cual también determina el tipo de métrica.
submitter(String id, String type) o submitter(Submitter submitter)
Obligatorio
Identifica quién envió la retroalimentación. El id debe ser una cadena no vacía. El type es un calificador opcional, como user.
span(LLMObsSpan span), spanId(String), traceId(String), sessionId(String) o feedbackJoinKey(String)
Obligatorio
La entidad a la que se adjuntará la retroalimentación. Establezca exactamente uno de estos métodos. Use feedbackJoinKey para una entidad definida por el cliente, como un ID de incidente o un ID de ticket, y establezca la misma clave en sus tramos para conectar la retroalimentación con ellos.
mlApp(String mlApp)
opcional
El nombre de la aplicación de ML. Si no se proporciona, esto toma como valor predeterminado la aplicación de ML configurada para el tracer.
timestampMs(long timestampMs)
opcional
La marca de tiempo Unix en milisegundos cuando se generó la retroalimentación. Si no se proporciona, esto toma como valor predeterminado la hora actual.
tags(Map<String, Object> tags) o tag(String key, Object value)
opcional
Pares de clave-valor utilizados para etiquetar los comentarios. Para obtener más información sobre las etiquetas, consulte Getting Started with Tags.
assessment(Assessment assessment)
opcional
Una valoración de esta retroalimentación. Los valores aceptados son LLMObs.Feedback.Assessment.PASS y LLMObs.Feedback.Assessment.FAIL.
reasoning(String reasoning)
opcional
Una explicación textual de la retroalimentación.

Nota: LLMObs.submitFeedback() valida los comentarios y arroja una IllegalArgumentException cuando la Agent Observability está habilitada y los comentarios no son válidos, como cuando faltan el objetivo, el valor o el remitente. Cuando Agent Observability está deshabilitada, o el Agent no está conectado, la llamada es una no-op.

Ejemplo

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 {
      // connecting the span to a customer-defined entity
      llmSpan.setTag("feedback_join_key", "incident-123");
      llmSpan.finish();

      // submitting feedback for a trace
      LLMObs.submitFeedback(
          LLMObs.Feedback.builder()
              .traceId(llmSpan.getTraceId().toString())
              .label("thumbs")
              .booleanValue(true)
              .submitter("user-123", "end_user")
              .assessment(LLMObs.Feedback.Assessment.PASS)
              .reasoning("answered the question")
              .build());

      // submitting feedback for that entity
      LLMObs.submitFeedback(
          LLMObs.Feedback.builder()
              .feedbackJoinKey("incident-123")
              .label("user_comment")
              .textValue("The answer missed the customer impact.")
              .submitter("user-123", "end_user")
              .assessment(LLMObs.Feedback.Assessment.FAIL)
              .build());
    }
    return chatResponse;
  }
}

Procesamiento de tramo

Para modificar los datos de entrada y salida en los tramos, puede configurar una función de procesador. La función de procesador tiene acceso a las etiquetas de tramo para permitir la modificación condicional de entrada/salida. Las funciones de procesador pueden devolver el tramo modificado para emitirlo, o devolver None/null para evitar que el tramo se emita por completo. Esto es útil para filtrar tramos que contienen datos confidenciales o que cumplen con ciertos criterios.

Ejemplo

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"})

Ejemplo: modificación condicional con instrumentación automática

Cuando se utiliza la instrumentación automática, el span no siempre es accesible contextualmente. Para modificar condicionalmente las entradas y salidas en tramos instrumentados automáticamente, se puede utilizar annotation_context() además de un procesador de tramos.

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
        ...

Ejemplo: evitar que se emitan tramos

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

Ejemplo

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)

Ejemplo: modificación condicional con instrumentación automática

Cuando se utiliza la instrumentación automática, el span no siempre es accesible contextualmente. Para modificar condicionalmente las entradas y salidas en tramos instrumentados automáticamente, se puede utilizar llmobs.annotationContext() además de un procesador de tramos.

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
  });
}

Ejemplo: evitar que se emitan tramos

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
  })
}

Seguimiento de sesiones de usuario

El seguimiento de sesiones le permite asociar múltiples interacciones con un usuario determinado.

Al iniciar un tramo raíz para una nueva traza o tramo en un nuevo proceso, especifique el argumento session_id con el ID de cadena de la sesión de usuario subyacente, el cual se envía como una etiqueta en el tramo. Opcionalmente, también puede especificar las etiquetas user_handle, user_name y 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

Etiquetas de seguimiento de sesión

EtiquetaDescripción
session_idEl ID que representa una sesión de usuario única, por ejemplo, una sesión de chat.
user_handleEl identificador del usuario de la sesión de chat.
user_nameEl nombre del usuario de la sesión de chat.
user_idEl ID del usuario de la sesión de chat.

Al iniciar un tramo raíz para una nueva traza o tramo en un nuevo proceso, especifique el argumento sessionId con el ID de cadena de la sesión de usuario subyacente:

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

Al iniciar un tramo raíz para una nueva traza o tramo en un nuevo proceso, especifique el argumento sessionId con el ID de cadena de la sesión de usuario subyacente:

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;
  }
}

Trazado distribuido

El SDK admite el trazado a través de servicios o hosts distribuidos. El trazado distribuido funciona propagando información de tramo a través de solicitudes web.

La biblioteca ddtrace proporciona algunas integraciones listas para usar que admiten el trazado distribuido para bibliotecas populares de marco web y HTTP. Si su aplicación realiza solicitudes utilizando estas bibliotecas compatibles, puede habilitar el trazado distribuido ejecutando:

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

Si su aplicación no utiliza ninguna de estas bibliotecas compatibles, puede habilitar el trazado distribuido propagando manualmente la información de tramo hacia y desde los encabezados HTTP. El SDK proporciona los métodos auxiliares LLMObs.inject_distributed_headers() y LLMObs.activate_distributed_headers() para inyectar y activar contextos de trazado en los encabezados de solicitud.

Inyección de encabezados distribuidos

El método LLMObs.inject_distributed_headers() toma un tramo e inyecta su contexto en los encabezados HTTP para incluirlo en la solicitud. Este método acepta los siguientes argumentos:

request_headers
obligatorio - diccionario
Los encabezados HTTP que se deben extender con atributos de contexto de traza.
span
opcional - tramo - default: The current active span.
El tramo para inyectar su contexto en los encabezados de solicitud proporcionados. Cualquier tramo (incluidos aquellos con decoradores de función), esto utiliza de forma predeterminada el tramo activo actual.

Activación de encabezados distribuidos

El método LLMObs.activate_distributed_headers() toma los encabezados HTTP y extrae los atributos de contexto de traza para activarlos en el nuevo servicio.

Nota: Debe llamar a LLMObs.activate_distributed_headers() antes de iniciar cualquier tramo en su servicio descendente. Los tramos iniciados anteriormente (incluidos los tramos de decoradores de función) no se capturan en la traza distribuida.

Este método acepta el siguiente argumento:

request_headers
requerido - diccionario
Los encabezados HTTP para extraer atributos de contexto de traza.

Ejemplo

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 biblioteca dd-trace proporciona integraciones listas para usar que admiten el trazado distribuido para marcos web populares. Requerir el tracer habilita automáticamente estas integraciones, pero puede deshabilitarlas opcionalmente con:

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

Trazado avanzado

Rastreo de tramos mediante métodos en línea

Para cada tipo de tramo, la clase ddtrace.llmobs.LLMObs proporciona un método en línea correspondiente para trazar automáticamente la operación que conlleva un bloque de código determinado. Estos métodos tienen la misma firma de argumentos que sus contrapartes decoradoras de funciones, con la adición de que name toma como valor predeterminado el tipo de tramo (llm, workflow, etc.) si no se proporciona. Estos métodos se pueden utilizar como administradores de contexto para finalizar automáticamente el tramo una vez completado el bloque de código incluido.

Ejemplo

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

Persistencia de un tramo entre contextos

Para iniciar y detener manualmente un tramo en diferentes contextos o ámbitos:

  1. Inicie un tramo manualmente utilizando los mismos métodos (por ejemplo, el método LLMObs.workflow para un tramo de flujo de trabajo), pero como una llamada de función simple en lugar de como un administrador de contexto.
  2. Pase el objeto tramo como argumento a otras funciones.
  3. Detenga el tramo manualmente con el método span.finish(). Nota: el tramo debe finalizarse manualmente; de lo contrario, no se enviará.

Ejemplo

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

Forzar el vaciado en entornos sin servidor

LLMObs.flush() es una función de bloqueo que envía todos los datos de Agent Observability almacenados en búfer al backend de Datadog. Esto puede ser útil en entornos sin servidor para evitar que una aplicación se cierre hasta que se envíen todas las trazas de Agent Observability.

Rastreo de múltiples aplicaciones

El SDK admite el rastreo de múltiples aplicaciones LLM desde el mismo servicio.

Puede configurar una variable de entorno DD_LLMOBS_ML_APP con el nombre de su aplicación LLM, en la cual se agrupan de forma predeterminada todos los tramos generados.

Para anular esta configuración y usar un nombre de aplicación LLM diferente para un tramo raíz determinado, pase el argumento ml_app con el nombre de cadena de la aplicación LLM subyacente al iniciar un tramo raíz para una nueva traza o un tramo en un nuevo proceso.

from ddtrace.llmobs.decorators import workflow

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

Rastreo de tramos mediante métodos en línea

El llmobs SDK proporciona un método en línea correspondiente para rastrear automáticamente la operación que conlleva un bloque de código determinado. Estos métodos tienen la misma firma de argumento que sus contrapartes de envoltura de función, con la adición de que name es obligatorio, ya que el nombre no se puede inferir de una devolución de llamada anónima. Este método finalizará el tramo bajo las siguientes condiciones:

  • Si la función devuelve una Promesa, el tramo finaliza cuando la promesa se resuelve o se rechaza.
  • Si la función toma una devolución de llamada como su último parámetro, el tramo finaliza cuando se llama a esa devolución de llamada.
  • Si la función no acepta una devolución de llamada y no devuelve una Promesa, el tramo finaliza al final de la ejecución de la función.

Ejemplo sin una devolución de llamada

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

Ejemplo con una devolución de llamada

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
  })
}

El tipo de retorno de esta función coincide con el tipo de retorno de la función rastreada:

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
}

Decoradores de funciones en TypeScript

El Agent Observability SDK para Node.js ofrece una llmobs.decorate función que sirve como decorador de funciones para aplicaciones TypeScript. El comportamiento de rastreo de esta función es el mismo que llmobs.wrap.

Ejemplo

// 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
  }
}

Forzar el vaciado en entornos sin servidor

llmobs.flush() es una función de bloqueo que envía todos los datos de Agent Observability almacenados en búfer al backend de Datadog. Esto puede ser útil en entornos sin servidor para evitar que una aplicación se cierre hasta que se envíen todas las trazas de Agent Observability.

Rastreo de múltiples aplicaciones

El SDK admite el rastreo de múltiples aplicaciones LLM desde el mismo servicio.

Puede configurar una variable de entorno DD_LLMOBS_ML_APP con el nombre de su aplicación LLM, en la cual se agrupan de forma predeterminada todos los tramos generados.

Para anular esta configuración y usar un nombre de aplicación LLM diferente para un tramo raíz determinado, pase el argumento mlApp con el nombre de cadena de la aplicación LLM subyacente al iniciar un tramo raíz para una nueva traza o un tramo en un nuevo proceso.

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

Pautas para nombrar aplicaciones

El nombre de su aplicación (el valor de DD_LLMOBS_ML_APP) debe seguir estas pautas:

  • Debe ser una cadena Unicode en minúsculas
  • Puede tener hasta 193 caracteres de longitud
  • No puede contener guiones bajos contiguos o al final
  • Puede contener los siguientes caracteres:
    • Alfanuméricos
    • Guiones bajos
    • Guiones
    • Dos puntos
    • Puntos
    • Barras

Lecturas adicionales