Aller au contenu principal

Définissez les attributs d'étendue OpenTelemetry pour MLflow

Lorsque vous envoyez des traces depuis une application personnalisée instrumentée avec OpenTelemetry (OTel) vers Databricks MLflow, vous devez définir des attributs d'étendue spécifiques pour afficher correctement vos données de trace dans l'interface utilisateur de MLflow. Cette page vous indique quels attributs de la Convention sémantique OpenTelemetry GenAI configurer.

Si vous utilisez une intégration préconçue telle que Langfuse, cette intégration définit automatiquement ces attributs. Cette page est dédiée aux applications dotées d'une instrumentation OTel personnalisée.

remarque

Les attributs dans MLflow géré par Databricks diffèrent de MLflow OSS (outil/solution/technologie/plateforme open source). Pour le mappage d'attributs MLflow OSS, consultez la documentation MLflow.

Exigences

Avant de commencer, assurez-vous d’avoir :

  • Un Workspace Databricks avec l'aperçu du traçage OTel activé
  • L'exportateur OTLP configuré pour envoyer les traces à votre workspace. Voir Logs traces to the Unity Catalog tables.
  • Une application instrumentée avec le SDK OpenTelemetry.

Définir le type d'étendue

Chaque span de votre trace a besoin d'une étiquette de type afin que MLflow puisse identifier le type d'opération qu'il représente. Définissez gen_ai.operation.name sur l'une des valeurs du tableau suivant en appelant span.set_attribute("gen_ai.operation.name", "<value>"). MLflow lit cet attribut et affiche le type d'étendue MLflow correspondant dans l'interface utilisateur de trace.

Valeur gen_ai.operation.name OTel

Type d'étendue MLflow

chat

CHAT_MODEL

text_completion

LLM

generate_content

LLM

response

LLM

embeddings

EMBEDDING

execute_tool

TOOL

create_agent

AGENT

invoke_agent

AGENT

Valeur gen_ai.operation.name OTel

Type d'étendue MLflow

chat

CHAT_MODEL

text_completion

LLM

generate_content

LLM

response

LLM

embeddings

EMBEDDING

execute_tool

TOOL

create_agent

AGENT

invoke_agent

AGENT

Python
span.set_attribute("gen_ai.operation.name", "chat")

Définir les entrées et les sorties

Définissez gen_ai.input.messages et gen_ai.output.messages sur chaque span qui doit afficher les entrées et les sorties. Les définir sur le root span alimente également les aperçus des requêtes et réponses au niveau de la trace.

Attribut OTel

Attribut MLflow

gen_ai.input.messages

mlflow.spanInputs

gen_ai.output.messages

mlflow.spanOutputs

Attribut OTel

Attribut MLflow

gen_ai.input.messages

mlflow.spanInputs

gen_ai.output.messages

mlflow.spanOutputs

Les valeurs peuvent être des chaînes de caractères brutes ou des chaînes sérialisées JSON . L’utilisation de tableaux JSON d’objets de message avec les champs role et content permet un rendu plus riche dans l’interface utilisateur de MLflow (par exemple, des bulles étiquetées « Utilisateur » et « Assistant ») :

Python
import json

# Plain string — displays as-is in the UI
span.set_attribute("gen_ai.input.messages", "What is the weather today?")

# JSON message array — renders with role labels in the UI
span.set_attribute("gen_ai.input.messages", json.dumps([
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is the weather today?"}
]))
span.set_attribute("gen_ai.output.messages", json.dumps([
{"role": "assistant", "content": "It is sunny and 72°F in San Francisco."}
]))

Définir l'utilisation des jetons

Pour afficher le nombre de jetons dans le résumé de trace de l'interface utilisateur, définissez gen_ai.usage.input_tokens et gen_ai.usage.output_tokens en appelant span.set_attribute() sur l'étendue racine. MLflow lit ces valeurs à partir de la portée racine spécifiquement parce qu'il agrège les compteurs au niveau de la trace.

Attribut gen_ai.usage.* OTel

Champ du jeton MLflow

gen_ai.usage.input_tokens

Nombre de jetons d'entrée

gen_ai.usage.output_tokens

Nombre de jetons de sortie

(non défini — calculé automatiquement)

Nombre total de jetons

Attribut gen_ai.usage.* OTel

Champ du jeton MLflow

gen_ai.usage.input_tokens

Nombre de jetons d'entrée

gen_ai.usage.output_tokens

Nombre de jetons de sortie

(non défini — calculé automatiquement)

Nombre total de jetons

Python
root.set_attribute("gen_ai.usage.input_tokens", 150)
root.set_attribute("gen_ai.usage.output_tokens", 42)

Définir la session et l'utilisateur

Pour associer des traces à une session ou un utilisateur spécifique, définissez session.id et user.id sur n'importe quelle portée en appelant span.set_attribute(). MLflow lit ces attributs de la portée racine et les affiche comme métadonnées de niveau trace. Le paramètre session.id active le tab de session dans l'interface utilisateur de MLflow.

Attribut OTel

Champ de métadonnées MLflow

session.id

Identifiant de session ou de conversation

user.id

Identifiant de l'utilisateur final de l'application

Attribut OTel

Champ de métadonnées MLflow

session.id

Identifiant de session ou de conversation

user.id

Identifiant de l'utilisateur final de l'application

Python
span.set_attribute("session.id", "conversation-123")
span.set_attribute("user.id", "user-456")

Exemple complet : instrumenter un agent Python

L'exemple suivant rassemble les quatre catégories d'attributs dans un agent simple avec un span enfant LLM. Cela suppose que vous avez déjà configuré l'exportateur OTLP pour envoyer des traces à Databricks.

Python
import json
from opentelemetry import trace

tracer = trace.get_tracer("my-agent")

def run_agent(query: str) -> str:
with tracer.start_as_current_span("agent-run") as root:
# Child LLM span — set gen_ai attributes for this individual call
with tracer.start_as_current_span("chat") as llm:
llm.set_attribute("gen_ai.operation.name", "chat")
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": query}
]
response = call_llm(messages)
llm.set_attribute("gen_ai.input.messages", json.dumps(messages))
llm.set_attribute("gen_ai.output.messages", json.dumps([
{"role": "assistant", "content": response}
]))
llm.set_attribute("gen_ai.usage.input_tokens", 150)
llm.set_attribute("gen_ai.usage.output_tokens", 42)

# Root span — MLflow reads inputs, outputs, token usage, and session ID
# from the root span to populate the trace summary in the UI.
root.set_attribute("gen_ai.operation.name", "chat")
root.set_attribute("session.id", "conversation-123")
root.set_attribute("user.id", "user-456")
root.set_attribute("gen_ai.input.messages", json.dumps([
{"role": "user", "content": query}
]))
root.set_attribute("gen_ai.output.messages", json.dumps([
{"role": "assistant", "content": response}
]))
root.set_attribute("gen_ai.usage.input_tokens", 150)
root.set_attribute("gen_ai.usage.output_tokens", 42)
return response

Vérifier dans l'interface utilisateur MLflow

Après avoir appelé run_agent(), ouvrez l'onglet Traces MLflow dans votre expérimentation. Une trace correctement instrumentée affiche :

  • Types de portées : Chaque portée affiche son étiquette de type (par exemple, chat) au lieu de UNKNOWN
  • **Requête et réponse** : la portée racine affiche les messages d'entrée et les messages de sortie
  • Utilisation des jetons : le résumé de la trace affiche les nombres de jetons d'entrée, de sortie et totaux
  • **Session et utilisateur** : la trace apparaît dans la tab de session sous l'identifiant de session spécifié, et l'ID utilisateur est visible dans les métadonnées de la trace.

Trace GenAI OTel dans MLflow

Rechercher des traces par attributs d'étendue OTel

Après l’ingestion de traces OTel dans Unity Catalog, utilisez le préfixe span.attributes.* dans mlflow.search_traces() pour filtrer par les valeurs d’attribut OTel que vous avez définies. Le nom de l’attribut après le préfixe est le même nom d’attribut OTel que celui que vous définissez avec span.set_attribute().

Python
import mlflow

# experiment_id is visible in the MLflow UI URL and experiment details panel
mlflow.set_experiment(experiment_id="<experiment-id>")

# Find traces from a specific session (set using session.id)
traces = mlflow.search_traces(
filter_string="span.attributes.session.id = 'conversation-123'"
)

# Find traces from a specific user (set using user.id)
traces = mlflow.search_traces(
filter_string="span.attributes.user.id = 'user-456'"
)

# Find traces from a specific model (set using gen_ai.request.model)
traces = mlflow.search_traces(
filter_string="span.attributes.gen_ai.request.model LIKE '%gpt%'"
)

# Find traces by operation type (set using gen_ai.operation.name)
traces = mlflow.search_traces(
filter_string="span.attributes.gen_ai.operation.name = 'chat'"
)

# Find high-token traces (set using gen_ai.usage.input_tokens)
traces = mlflow.search_traces(
filter_string="span.attributes.gen_ai.usage.input_tokens > 1000"
)

Pour la syntaxe complète de filter_string, y compris les opérateurs et comparateurs pris en charge, consultez Rechercher les traces par programmation.

Limitations

Les attributs d'étendue OTel personnalisés ne sont pas affichés comme balises de suivi MLflow. Les attributs que vous définissez avec span.set_attribute() en dehors des mappages OTel-à-MLflow reconnus sur cette page n'apparaissent pas dans :

  • La colonne Tags ou la vue de trace unifiée dans l'interface utilisateur de MLflow
  • La table Unity Catalog _traces_unified
  • Le champ tags renvoyé par mlflow.search_traces()

Ces attributs sont conservés sur l'étendue sous-jacente. Ils restent visibles dans le tab **Attributes** de l'interface utilisateur de trace MLflow et peuvent être interrogés via le <prefix>_otel_spans.attributes champ de la table des spans OTel.

Pour attacher des tags interrogeables qui apparaissent dans la vue de trace unifiée, utilisez plutôt les APIs de tag MLflow. Consultez Attacher des tags et des métadonnées personnalisés.

Ressources supplémentaires