RousselTMLEARNING

Observabilité

OpenInference : les conventions OpenTelemetry pour tracer les applications d'IA

Guide détaillé d'OpenInference : conventions sémantiques et instrumentations OpenTelemetry pour LLM, RAG et agents. Types de spans, attributs llm.*, retrieval.*, tool.*, instrumentation automatique et manuelle, sessions, confidentialité, interopérabilité avec les conventions GenAI d'OpenTelemetry.

1. Qu'est-ce qu'OpenInference ? #

Un vocabulaire commun pour les traces d'IA.

Définition #

OpenInference est un projet open source (initié par Arize) qui définit deux choses :

  • des conventions sémantiques : quels attributs mettre sur un span pour décrire un appel de modèle, une recherche de documents, un appel d'outil ou une étape d'agent ;
  • des instrumentations prêtes à l'emploi qui produisent automatiquement ces spans pour les principaux SDK et frameworks d'IA, en Python, JavaScript et Java.

Tout repose sur OpenTelemetry : les spans OpenInference sont des spans OpenTelemetry ordinaires, exportés en OTLP. Phoenix et Arize AX savent les afficher de façon riche (messages, documents, jetons), et n'importe quel backend OTLP peut les stocker.

Les couches d'OpenInference au-dessus d'OpenTelemetry

Pourquoi des conventions ? #

Sans convention, chaque équipe nomme ses attributs à sa façon (prompt, llm_input, messages...) et aucun outil ne peut calculer un coût en jetons ou afficher une conversation. Avec OpenInference, llm.token_count.prompt signifie la même chose quel que soit le framework, ce qui permet des tableaux de bord, des évaluations et des comparaisons génériques.

2. Les types de spans #

openinference.span.kind.

Les valeurs #

Arbre de spans OpenInference pour un agent
TypeReprésenteExemple
LLMUn appel à un modèle de langagechat.completions.create
EMBEDDINGLe calcul d'embeddingsVectorisation d'une question
RETRIEVERLa recherche de documentsRequête vers une base vectorielle
RERANKERLe reclassement de documentsCross-encoder sur les 20 premiers résultats
CHAINUn enchaînement d'étapes ou la logique applicativePipeline RAG complet
TOOLUn appel d'outil ou de fonctionget_weather(city)
AGENTUne étape de raisonnement d'agentBoucle choix d'outil puis réponse
GUARDRAILUn contrôle de sécurité ou de conformitéDétection de données personnelles
EVALUATORUne évaluationLLM juge de pertinence
PROMPTLe rendu d'un gabarit de promptRemplissage des variables
À savoir : La liste des types évolue avec la spécification (par exemple DECISION pour les choix de routage) : consultez spec/semantic_conventions.md du dépôt OpenInference.

3. Les attributs essentiels #

Ce que contient un span.

Par famille #

FamilleAttributsContenu
Entrée et sortieinput.value, input.mime_type, output.value, output.mime_typeCe qui entre et sort de l'étape (texte ou JSON)
Modèlellm.model_name, llm.provider, llm.invocation_parametersModèle, fournisseur, température, max_tokens (JSON)
Messagesllm.input_messages.<i>.message.role, .message.content, llm.output_messages.<i>...La conversation envoyée et reçue, message par message
Jetonsllm.token_count.prompt, llm.token_count.completion, llm.token_count.totalLa base du calcul de coût
Gabaritllm.prompt_template.template, .variables, .versionLe prompt avant remplissage, pour relier une réponse à une version
Documentsretrieval.documents.<i>.document.id, .content, .score, .metadataLes passages récupérés et leur score
Embeddingsembedding.model_name, embedding.embeddings.<i>.embedding.text, .vectorTextes vectorisés
Outilstool.name, tool.description, tool.parameters, tool_call.function.name, tool_call.function.argumentsOutil appelé et arguments choisis par le modèle
Contextesession.id, user.id, metadata, tag.tagsRegrouper par conversation, utilisateur, version, fonctionnalité

4. Instrumenter #

Automatique d'abord, manuel ensuite.

Instrumentation automatique #

pip install arize-phoenix-otel openinference-instrumentation-openai openai
from phoenix.otel import register

# configure OpenTelemetry et active toutes les instrumentations OpenInference installées
tracer_provider = register(
    project_name="support-bot",
    endpoint="http://localhost:6006/v1/traces",   # Phoenix, en OTLP/HTTP
    auto_instrument=True,
)

from openai import OpenAI
client = OpenAI()
client.chat.completions.create(model="gpt-4o-mini",
                               messages=[{"role": "user", "content": "Bonjour"}])

Sans Phoenix, la même instrumentation fonctionne avec le SDK OpenTelemetry standard :

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

provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter(endpoint="http://collector:4318/v1/traces")))
OpenAIInstrumentor().instrument(tracer_provider=provider)
ÉcosystèmeExemples de paquets
Fournisseurs de modèlesopeninference-instrumentation-openai, -anthropic, -bedrock, -vertexai, -mistralai, -litellm
Frameworks-langchain, -llama-index, -dspy, -haystack
Agents-openai-agents, -crewai, -smolagents, -autogen
JavaScript, Java@arizeai/openinference-instrumentation-openai, instrumentations LangChain.js, LangChain4j

Instrumentation manuelle #

Pour une étape maison (une recherche dans votre propre index, un outil métier), créez le span vous-même avec les conventions :

from opentelemetry import trace
from openinference.semconv.trace import SpanAttributes, OpenInferenceSpanKindValues

tracer = trace.get_tracer("rag")

def retrieve(question: str):
    with tracer.start_as_current_span("retrieve") as span:
        span.set_attribute(SpanAttributes.OPENINFERENCE_SPAN_KIND, OpenInferenceSpanKindValues.RETRIEVER.value)
        span.set_attribute(SpanAttributes.INPUT_VALUE, question)
        docs = index.search(question, k=3)
        for i, d in enumerate(docs):
            span.set_attribute(f"retrieval.documents.{i}.document.id", d.id)
            span.set_attribute(f"retrieval.documents.{i}.document.content", d.text)
            span.set_attribute(f"retrieval.documents.{i}.document.score", d.score)
        return docs

Contexte : sessions, utilisateurs, métadonnées #

from openinference.instrumentation import using_attributes

with using_attributes(session_id=conversation_id, user_id=user.id,
                      metadata={"app_version": "2.3.0", "feature": "faq"}, tags=["beta"]):
    answer = agent.run(question)   # tous les spans créés ici portent ces attributs
Bonne Pratique : Renseignez toujours session.id pour les conversations et une métadonnée de version : c'est ce qui permet d'afficher une conversation complète et de comparer deux versions de l'application.

5. Confidentialité et volume #

Les prompts contiennent des données sensibles.

Masquer #

Les prompts et les réponses peuvent contenir des données personnelles. Les instrumentations OpenInference acceptent une configuration de masquage, en code (TraceConfig) ou par variables d'environnement :

VariableEffet
OPENINFERENCE_HIDE_INPUTSMasque input.value et les messages d'entrée
OPENINFERENCE_HIDE_OUTPUTSMasque les sorties
OPENINFERENCE_HIDE_INPUT_MESSAGES, ..._OUTPUT_MESSAGESMasque seulement les messages
OPENINFERENCE_HIDE_EMBEDDING_VECTORSSupprime les vecteurs, souvent volumineux
OPENINFERENCE_BASE64_IMAGE_MAX_LENGTHLimite la taille des images encodées
Erreur Courante : Masquer toutes les entrées empêche ensuite d'évaluer les réponses. Préférez masquer les champs sensibles (dans le code ou dans un OpenTelemetry Collector) et limiter l'accès aux traces.

6. OpenInference et les conventions GenAI d'OpenTelemetry #

Deux standards proches.

Comparaison #

OpenTelemetry définit aussi des conventions pour l'IA générative (attributs gen_ai.* : gen_ai.request.model, gen_ai.usage.input_tokens...), encore en cours de stabilisation. OpenInference est antérieur, plus riche sur les RAG et les agents (documents, reranking, outils, types de spans), et largement outillé.

OpenInferenceOpenTelemetry GenAI
Porté parProjet OpenInference (Arize)OpenTelemetry (CNCF)
Préfixellm.*, retrieval.*, tool.*gen_ai.*
Types de spans métierOui (openinference.span.kind)Par opération (gen_ai.operation.name)
InstrumentationsNombreuses, Python, JS, JavaEn croissance (instrumentations contrib)
Bonne Pratique : Choisissez l'instrumentation selon votre backend principal ; si vous devez alimenter plusieurs outils, un OpenTelemetry Collector peut renommer des attributs (processeur transform) pour passer d'une convention à l'autre.

Articles liés

Arize AI : observabilité et évaluation des applications LLM et des agents

Comprendre Arize AI : Phoenix (open source) et Arize AX (plateforme), traces OpenInference, évaluations par L…

Installer Phoenix et tracer sa première application LLM

Installer Arize Phoenix (pip, Docker), envoyer ses premières traces OpenInference depuis une application Open…

Tracer un RAG et un agent avec OpenInference et Phoenix

Instrumenter une application RAG et un agent : spans RETRIEVER, RERANKER, TOOL et AGENT, sessions de conversa…

Pour aller plus loin