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

Aperçu

En utilisant les conventions sémantiques standardisées d’OpenTelemetry pour les opérations d’IA générative, vous pouvez instrumenter vos applications LLM avec n’importe quelle bibliothèque ou framework compatible OpenTelemetry et visualiser les traces dans LLM Observability.

LLM Observability prend en charge l’ingestion des traces OpenTelemetry qui suivent les conventions sémantiques OpenTelemetry 1.37+ pour l’IA générative. Cela vous permet d’envoyer des traces LLM directement depuis des applications instrumentées avec OpenTelemetry à Datadog sans nécessiter le SDK Datadog LLM Observability ou un Datadog Agent.

Prérequis

Pour envoyer des évaluations externes directement à l’API pour les spans OpenTelemetry, vous devez inclure le source:otel tag dans l’évaluation. Lors de la référence aux spans, fournissez span_id et trace_id sous forme de chaînes décimales. OpenTelemetry utilise des identifiants hexadécimaux nativement, donc convertissez-les en décimal avant de soumettre les évaluations. Par exemple, utilisez la fonction de Python int(hex_span_id, 16) pour convertir un identifiant de span hexadécimal en son équivalent décimal.

Pour des informations sur l’utilisation du suivi des invites avec les spans OpenTelemetry, consultez Suivi des invites - Instrumentation OpenTelemetry.

Vous pouvez également utiliser des spans OpenTelemetry à l’intérieur de Expériences LLM Observability. En définissant DD_TRACE_OTEL_ENABLED=1, les spans OTel créés à l’intérieur d’une tâche d’expérience apparaissent automatiquement comme des enfants du span d’expérience.

Configuration

Pour envoyer des traces OpenTelemetry à LLM Observability, configurez votre exportateur OpenTelemetry avec les paramètres suivants :

Configuration

Définissez les variables d’environnement suivantes dans votre application :

OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=
OTEL_EXPORTER_OTLP_TRACES_HEADERS=dd-api-key=<YOUR_API_KEY>,dd-otlp-source=llmobs

Remplacez <YOUR_API_KEY> par votre clé API Datadog.

Si votre framework prenait auparavant en charge une version de spécification OpenTelemetry antérieure à 1.37, vous devez également définir :

OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental

Cette variable d’environnement active les traces OpenTelemetry conformes à la version 1.37+ pour les frameworks qui prennent désormais en charge les conventions sémantiques de la version 1.37+, mais qui prenaient auparavant en charge des versions plus anciennes (comme strands-agents).

Remarque :

  • Si vous utilisez une bibliothèque OpenTelemetry autre que le SDK OpenTelemetry par défaut, vous devrez peut-être configurer l’endpoint, le protocole et les en-têtes différemment selon l’API de la bibliothèque. Consultez la documentation de votre bibliothèque pour la méthode de configuration appropriée.
  • Lors de l’utilisation de l’instrumentation OpenTelemetry, certaines données envoyées à LLM Observability peuvent également être écrites dans les traces APM correspondantes. Si vous protégez des données sensibles, envisagez également de configurer un ensemble de données restreint sur APM pour correspondre à vos contrôles d’accès LLM Observability. Consultez Contrôle d’accès aux données pour plus d’informations.

Utilisation de strands-agents

Si vous utilisez la strands-agents bibliothèque, vous devez définir une variable d’environnement supplémentaire pour activer les traces conformes à OpenTelemetry v1.37+ :

OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental

Cette variable d’environnement garantit que strands-agents émet des traces suivant les conventions sémantiques OpenTelemetry v1.37+ pour l’IA générative, qui sont requises par LLM Observability.

Instrumentation

Pour générer des traces compatibles avec LLM Observability, choisissez l’une des méthodes suivantes :

Après le démarrage de votre application, les traces apparaissent automatiquement dans la page Traces d’observabilité LLM. Pour rechercher vos traces dans l’interface utilisateur, utilisez l’attribut ml_app, qui est automatiquement défini sur la valeur de l’attribut service de votre span racine OpenTelemetry.

  • OpenLLMetry version 0.47+ est pris en charge. Consultez l'exemple OpenLLMetry.
  • OpenInference n'est pas pris en charge.
  • Il peut y avoir un délai de 3 à 5 minutes entre l'envoi des traces et leur apparition sur la page des Traces d'observabilité LLM. Si vous avez APM activé, les traces apparaissent immédiatement sur la page des Traces APM.

Frameworks et bibliothèques testés

Ces frameworks et bibliothèques ont été testés avec Datadog LLM Observability. Tout framework qui émet des spans conformes à la convention sémantique OpenTelemetry 1.37+ GenAI est pris en charge.

Exemples

Utilisation des agents Strands

L’exemple suivant démontre une application complète utilisant Strands Agents avec l’intégration OpenTelemetry. Cette même approche fonctionne avec tout framework qui prend en charge les conventions sémantiques OpenTelemetry version 1.37+ pour l’IA générative.

from strands import Agent
from strands_tools import calculator, current_time
from strands.telemetry.config import StrandsTelemetry
import os

# Configure AWS credentials for Bedrock access
os.environ["AWS_PROFILE"] = "<YOUR_AWS_PROFILE>"
os.environ["AWS_DEFAULT_REGION"] = "<YOUR_AWS_REGION>"

# Enable latest GenAI semantic conventions (1.37)
os.environ["OTEL_SEMCONV_STABILITY_OPT_IN"] = "gen_ai_latest_experimental"

# Configure OTLP endpoint to send traces to Datadog LLM Observability
os.environ["OTEL_EXPORTER_OTLP_TRACES_PROTOCOL"] = "http/protobuf"
os.environ["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"] = ""
os.environ["OTEL_EXPORTER_OTLP_TRACES_HEADERS"] = f"dd-api-key={os.getenv('DD_API_KEY')},dd-otlp-source=llmobs"

# Initialize telemetry with OTLP exporter
telemetry = StrandsTelemetry()
telemetry.setup_otlp_exporter()

# Create agent with tools
agent = Agent(tools=[calculator, current_time])

# Run the agent
if __name__ == "__main__":
    result = agent("I was born in 1993, what is my age?")
    print(f"Agent: {result}")

Instrumentation OpenTelemetry personnalisée

L’exemple suivant démontre comment instrumenter votre application LLM en utilisant du code OpenTelemetry personnalisé. Cette approche vous donne un contrôle total sur les traces et les spans émis par votre application.

import os
import json
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource, SERVICE_NAME
from openai import OpenAI

# Configure OpenTelemetry to send traces to Datadog
os.environ["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"] = ""
os.environ["OTEL_EXPORTER_OTLP_TRACES_HEADERS"] = "dd-api-key=<YOUR_DATADOG_API_KEY>,dd-otlp-source=llmobs"
os.environ["OTEL_SEMCONV_STABILITY_OPT_IN"] = "gen_ai_latest_experimental"

# Initialize OpenTelemetry SDK
resource = Resource(attributes={SERVICE_NAME: "simple-llm-example"})
provider = TracerProvider(resource=resource)
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
trace.set_tracer_provider(provider)

tracer = trace.get_tracer(__name__)

# Make LLM call with OpenTelemetry tracing
with tracer.start_as_current_span(
    "chat gpt-4o",
    kind=trace.SpanKind.CLIENT,
) as span:
    model = "gpt-4o"
    max_tokens = 1024
    temperature = 0.7
    messages = [{"role": "user", "content": "Explain OpenTelemetry in one sentence."}]

    # Set request attributes
    span.set_attribute("gen_ai.provider.name", "openai")
    span.set_attribute("gen_ai.request.model", model)
    span.set_attribute("gen_ai.operation.name", "chat")
    span.set_attribute("gen_ai.request.max_tokens", max_tokens)
    span.set_attribute("gen_ai.request.temperature", temperature)

    # Add input messages as event
    input_messages_parts = []
    for msg in messages:
        input_messages_parts.append({
            "role": msg["role"],
            "parts": [{"type": "text", "content": msg["content"]}]
        })

    span.add_event(
        "gen_ai.client.inference.operation.details",
        {
            "gen_ai.input.messages": json.dumps(input_messages_parts)
        }
    )

    # Make actual LLM call
    client = OpenAI(api_key="<YOUR_OPENAI_API_KEY>")
    response = client.chat.completions.create(
        model=model,
        max_tokens=max_tokens,
        temperature=temperature,
        messages=messages
    )

    # Set response attributes from actual data
    span.set_attribute("gen_ai.response.id", response.id)
    span.set_attribute("gen_ai.response.model", response.model)
    span.set_attribute("gen_ai.response.finish_reasons", [response.choices[0].finish_reason])
    span.set_attribute("gen_ai.usage.input_tokens", response.usage.prompt_tokens)
    span.set_attribute("gen_ai.usage.output_tokens", response.usage.completion_tokens)

    # Add output messages as event
    output_text = response.choices[0].message.content
    span.add_event(
        "gen_ai.client.inference.operation.details",
        {
            "gen_ai.output.messages": json.dumps([{
                "role": "assistant",
                "parts": [{"type": "text", "content": output_text}],
                "finish_reason": response.choices[0].finish_reason
            }])
        }
    )

    print(f"Response: {output_text}")

# Flush spans before exit
provider.force_flush()

Après avoir exécuté cet exemple, recherchez ml_app:simple-llm-example dans l’interface utilisateur d’observabilité LLM pour trouver la trace générée.

Utilisation d’OpenLLMetry

L’exemple suivant démontre l’utilisation de OpenLLMetry pour instrumenter automatiquement les appels OpenAI avec OpenTelemetry.

from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.openai import OpenAIInstrumentor
import openai
from opentelemetry.sdk.resources import Resource

resource = Resource.create({
    "service.name": "simple-openllmetry-test",
})

provider = TracerProvider(resource=resource)
trace.set_tracer_provider(provider)

exporter = OTLPSpanExporter(
    endpoint="",
    headers={
        "dd-api-key": "<YOUR_DATADOG_API_KEY>",
        "dd-ml-app": "simple-openllmetry-test",
        "dd-otlp-source": "llmobs",
    },
)

provider.add_span_processor(BatchSpanProcessor(exporter))

OpenAIInstrumentor().instrument()

# Make OpenAI call (automatically traced)
client = openai.OpenAI(api_key="<YOUR_OPENAI_API_KEY>")
client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[{"role": "user", "content": "What is 15 multiplied by 7?"}]
)

provider.force_flush(timeout_millis=5000)

Après avoir exécuté cet exemple, recherchez ml_app:simple-openllmetry-test dans l’interface utilisateur d’observabilité LLM pour trouver la trace générée.

Référence de mappage d’attributs

Cette section fournit le mappage entre les conventions sémantiques OpenTelemetry GenAI (v1.37+) ainsi qu’OpenLLMetry au schéma de span d’observabilité LLM de Datadog.

Les mappages spécifiques à OpenLLMetry sont documentés séparément dans la section Mappages d'attributs OpenLLMetry.

Mappages d’attributs OpenTelemetry 1.37+

Attributs de base des spans

Champ OTLPChamp d’observabilité LLMRemarques
resource.attributes.service.nameml_app, tags.service
namenameRemplacé par gen_ai.tool.name si présent
parent_span_idparent_id
start_time_unix_nanostart_ns
end_time_unix_nanodurationCalculé : fin - début
status.codestatuserror si > 0, sinon ok
status.messagemeta.error.message
attributes.error.typemeta.error.type

Résolution du type de span

gen_ai.operation.nameObservabilité LLM span.kind
generate_content, chat, text_completion, completionllm
embeddings, embeddingembedding
execute_tooltool
invoke_agent, create_agentagent
rerank, unknown, (par défaut)workflow

Informations sur le modèle

Attribut OTelChamp d’observabilité LLMNotes
gen_ai.operation.namemeta.span.kindVoir le tableau de résolution ci-dessus
gen_ai.provider.namemeta.model_providerRevient à gen_ai.system, puis custom
gen_ai.response.modelmeta.model_name
gen_ai.request.modelmeta.model_nameSolution de repli lorsque response.model est absent

Métriques d’utilisation des jetons

Attribut OTelChamp d’observabilité LLM
gen_ai.usage.input_tokensmetrics.input_tokens
gen_ai.usage.output_tokensmetrics.output_tokens
gen_ai.usage.prompt_tokensmetrics.prompt_tokens
gen_ai.usage.completion_tokensmetrics.completion_tokens
gen_ai.usage.total_tokensmetrics.total_tokens

Paramètres de requête

Tous gen_ai.request.* les paramètres correspondent à meta.metadata.* avec le préfixe supprimé.

Attribut OTelChamp d’observabilité LLM
gen_ai.request.seedmetadata.seed
gen_ai.request.frequency_penaltymetadata.frequency_penalty
gen_ai.request.max_tokensmetadata.max_tokens
gen_ai.request.stop_sequencesmetadata.stop_sequences
gen_ai.request.temperaturemetadata.temperature
gen_ai.request.top_kmetadata.top_k
gen_ai.request.top_pmetadata.top_p
gen_ai.request.choice.countmetadata.choice.count

Attributs de l’outil

Attribut OTelChamp d’observabilité LLMNotes
gen_ai.tool.namenameNom du span remplacé
gen_ai.tool.call.idmetadata.tool_id
gen_ai.tool.descriptionmetadata.tool_description
gen_ai.tool.typemetadata.tool_type
gen_ai.tool.definitionsmeta.tool_definitionsTableau JSON analysé
gen_ai.tool.call.argumentsinput.value
gen_ai.tool.call.resultoutput.value

Session et conversation

Attribut OTelChamp d’observabilité LLMNotes
gen_ai.conversation.idsession_idÉgalement ajouté à metadata.conversation_id et étiquettes

Attributs de réponse

Attribut OTelChamp d’observabilité LLM
gen_ai.response.modelmeta.model_name
gen_ai.response.finish_reasonsmetadata.finish_reasons

Messages d’entrée et de sortie

Les messages d’entrée et de sortie sont extraits des sources suivantes, par ordre de priorité :

  1. Attributs directs : gen_ai.input.messages, gen_ai.output.messages, gen_ai.system_instructions
  2. Span events (meta["events"]) with name gen_ai.client.inference.operation.details
OTel SourceChamp d’observabilité LLMRemarques
gen_ai.input.messagesmeta.input.messages (llm) / meta.input.value (autres)
gen_ai.output.messagesmeta.output.messages (llm) / meta.output.value (autres)
gen_ai.system_instructionsPréfixé à l’entréeAjouté en tant que messages de rôle système
Embedding spans
OTel SourceChamp d’observabilité LLM
gen_ai.input.messagesmeta.input.documents
N/Ameta.output.value = [N embedding(s) returned]

Étiquettes

Les étiquettes sont placées directement sur le span :

  • Les attributs non-gen_ai.* sont convertis en balises key:value
  • Les clés inconnues gen_ai.* sont ajoutées avec le préfixe supprimé
  • Filtrés : _dd.*, llm.*, ddtags, events, et les clés gen_ai.* déjà spécifiquement mappées
Tout gen_ai.* Les attributs qui ne sont pas explicitement mappés aux champs de portée d'observabilité LLM sont placés dans les étiquettes de la portée LLM, avec une limite de 256 caractères par valeur. Les valeurs dépassant cette limite sont tronquées. Tous les autres non-gen_ai attributs sont supprimés.

Mappages d’attributs OpenLLMetry

Cette section documente les mappages d’attributs spécifiques à OpenLLMetry qui diffèrent ou étendent les conventions sémantiques standard d’OpenTelemetry GenAI.

Résolution du type de portée

llm.request.type est utilisé comme solution de repli lorsque gen_ai.operation.name est absent.

llm.request.typeObservabilité LLM span.kind
chatllm
completionllm
embeddingembedding
rerankworkflow
unknown, (par défaut)workflow

Informations sur le modèle

OpenLLMetry AttributeLLM Observability FieldNotes
gen_ai.systemmeta.model_providerSolution de repli lorsque gen_ai.provider.name est absent

Métriques d’utilisation des jetons

OpenLLMetry AttributeLLM Observability FieldNotes
llm.usage.total_tokensmetrics.total_tokensSolution de repli lorsque gen_ai.usage.total_tokens est absent

Messages d’entrée et de sortie

OpenLLMetry utilise des attributs indexés au lieu de tableaux JSON. Ce sont les sources de la plus basse priorité et ne sont utilisées que lorsque aucune source standard OTel n’existe.

Attributs de prompt (entrée)
Attribut OpenLLMetryDescription
gen_ai.prompt.<index>.roleRôle du message (utilisateur, système, assistant, outil)
gen_ai.prompt.<index>.contentContenu du message
gen_ai.prompt.<index>.tool_call_idID d’appel d’outil pour les messages de réponse d’outil
Attributs de complétion (sortie)
Attribut OpenLLMetryDescription
gen_ai.completion.<index>.roleRôle du message
gen_ai.completion.<index>.contentContenu du message
gen_ai.completion.<index>.finish_reasonRaison de la fin de la complétion
Mapping

Les messages sont convertis au format compatible OTel et traités normalement :

OpenLLMetry SourceLLMObs Field
gen_ai.prompt.*meta.input.messages (llm) / meta.input.value (autres)
gen_ai.completion.*meta.output.messages (llm) / meta.output.value (autres)

Appels d’outils

Les appels d’outils sont imbriqués dans les attributs de complétion.

Attribut OpenLLMetryCorrespond à
gen_ai.completion.<index>.tool_calls.<idx>.nametool_calls[].name
gen_ai.completion.<index>.tool_calls.<idx>.idtool_calls[].tool_id
gen_ai.completion.<index>.tool_calls.<idx>.argumentstool_calls[].arguments
Messages de réponse des outils

Lorsque role = "tool" et tool_call_id sont présents, le message est converti en un résultat d’outil :

Attribut OpenLLMetryCorrespond à
gen_ai.prompt.<index>.tool_call_idtool_results[].tool_id
gen_ai.prompt.<index>.contenttool_results[].result

Embedding spans

Pour les embedding spans, les documents sont extraits des attributs de contenu de l’invite.

OpenLLMetry SourceLLM Observability Field
gen_ai.prompt.<index>.contentmeta.input.documents[].text

Filtrage des étiquettes

Les attributs spécifiques à OpenLLMetry suivants sont filtrés des étiquettes :

  • gen_ai.prompt.*
  • gen_ai.completion.*
  • llm.*

Conventions sémantiques prises en charge

LLM Observability prend en charge les spans qui suivent les conventions sémantiques OpenTelemetry 1.37+ pour l’IA générative, y compris :

  • Opérations LLM avec gen_ai.provider.name, "gen_ai.operation.name", gen_ai.request.model et d’autres attributs gen_ai
  • Entrées/sorties d’opération sur les attributs de span directs ou via des événements de span
  • Métriques d’utilisation des jetons (gen_ai.usage.input_tokens, gen_ai.usage.output_tokens)
  • Paramètres et métadonnées du modèle

Pour la liste complète des attributs pris en charge et de leurs spécifications, voir la documentation des conventions sémantiques OpenTelemetry pour l’IA générative.

Disabling LLM Observability conversion

Si vous souhaitez que vos spans d’IA générative restent uniquement dans APM et n’apparaissent pas dans LLM Observability, vous pouvez désactiver la conversion automatique en définissant l’attribut dd_llmobs_enabled sur false. Définir cet attribut sur n’importe quel span dans une trace empêche la conversion de l’ensemble de la trace en LLM Observability.

Utilisation des variables d’environnement

Ajoutez l’attribut dd_llmobs_enabled=false à votre variable d’environnement OTEL_RESOURCE_ATTRIBUTES :

OTEL_RESOURCE_ATTRIBUTES=dd_llmobs_enabled=false

Utilisation du code

Vous pouvez également définir l’attribut de manière programmatique sur n’importe quel span dans votre trace :

from opentelemetry import trace

tracer = trace.get_tracer(__name__)

with tracer.start_as_current_span("my-span") as span:
    # Disable LLM Observability conversion for this entire trace
    span.set_attribute("dd_llmobs_enabled", False)