Pular para o conteúdo principal

Rastreamento manual e personalizado

O rastreamento automático instrumenta mais de 30 estruturas com uma única chamada. Use o rastreamento manual quando precisar instrumentar código que o autolog não cobre — lógica de agente personalizada, frameworks proprietários ou qualquer caminho de execução que você queira observar com precisão. As mesmas APIs funcionam independentemente de seu agente ser executado no Databricks ou em infraestrutura externa.

Qual método?

Método

Quando usar

Pai-filho automático

Tratamento de exceções

@mlflow.trace decorador

Rastreando uma função Python inteira

Sim

Automático

mlflow.start_span() gerenciador de contexto

Como rastrear um bloco de código dentro de uma função

Sim

Automático

Wrapper de mlflow.trace() para Node.js

Rastreando funções em TypeScript ou JavaScript

Sim

Automático

API MlflowClient de baixo nível

IDs de rastreio personalizados, integração com um sistema de observabilidade externo

Não — manual

Manual

Método

Quando usar

Pai-filho automático

Tratamento de exceções

@mlflow.trace decorador

Rastreando uma função Python inteira

Sim

Automático

mlflow.start_span() gerenciador de contexto

Como rastrear um bloco de código dentro de uma função

Sim

Automático

Wrapper de mlflow.trace() para Node.js

Rastreando funções em TypeScript ou JavaScript

Sim

Automático

API MlflowClient de baixo nível

IDs de rastreio personalizados, integração com um sistema de observabilidade externo

Não — manual

Manual

Pré-requisitos

Python
%pip install --upgrade "mlflow[databricks]>=3.1.0"
dbutils.library.restartPython()

O decorador @mlflow.trace

O decorador @mlflow.trace cria um span para qualquer função em Python. Ele captura automaticamente o nome da função, entradas, saídas e tempo de execução, além de gerenciar relacionamentos pai-filho e registro de exceções sem código extra.

Python
import mlflow


@mlflow.trace(span_type="func", attributes={"key": "value"})
def add_1(x):
return x + 1


@mlflow.trace(span_type="func", attributes={"key1": "value1"})
def minus_1(x):
return x - 1


@mlflow.trace(name="Trace Test")
def trace_test(x):
step1 = add_1(x)
return minus_1(step1)


trace_test(4)

Decorador de rastreamento

nota

Quando um rastreamento contém vários spans com o mesmo nome, o MLflow acrescenta um sufixo de incremento automático — _1, _2 e assim por diante.

Personalizar spans

O decorador aceita três argumentos opcionais:

  • name — substitui o nome de intervalo default (o nome da função)
  • span_type — define o tipo de intervalo; use um Span Type integrado ou uma string personalizada
  • attributes — adiciona metadados de key-value ao span

Para atualizar atributos dinamicamente de dentro da função, chame mlflow.get_current_active_span():

Python
from mlflow.entities import SpanType

@mlflow.trace(span_type=SpanType.LLM)
def invoke(prompt: str):
model_id = "gpt-4o-mini"
span = mlflow.get_current_active_span()
span.set_attributes({"model": model_id})
return client.invoke(messages=[{"role": "user", "content": prompt}], model=model_id)

Usar com outros decoradores

Coloque @mlflow.trace como o decorador mais externo . Se não for o primeiro, ele poderá perder modificações feitas por decoradores internos e produzir rastreamentos incompletos.

Python
# Correct: @mlflow.trace is outermost
@mlflow.trace(name="my_function")
@other_decorator
def my_function(x, y):
return x + y

Adicionar tags de rastreamento e pré-visualizações de interface

Use mlflow.update_current_trace() dentro de uma função rastreada para personalizar as colunas de visualização Request / Response na IU de rastreamentos. A mesma chamada pode anexar tags; para ver o fluxo de trabalho completo de tags e metadados, consulte Enrich traces: tags, context, and feedback.

Python
@mlflow.trace(name="Summarization Pipeline")
def summarize_document(document_content: str, user_instructions: str):
mlflow.update_current_trace(tags={"environment": "production"})

request_p = f"Doc: {document_content[:30]}... Instr: {user_instructions[:30]}..."
mlflow.update_current_trace(request_preview=request_p)

summary = generate_summary(document_content, user_instructions)

mlflow.update_current_trace(response_preview=f"Summary: {summary[:50]}...")
return summary

Tratamento de exceções

Quando uma exceção é gerada dentro de uma função rastreada, o span é marcado automaticamente como falha e os detalhes da exceção são registrados na Events tab do span.

Multithreading

MLflow tracing is thread-safe and isolates traces per thread by default. To create one trace that spans multiple threads, copy the execution context from the main thread into each worker:

Python
import contextvars
from concurrent.futures import ThreadPoolExecutor, as_completed
import mlflow
import openai

client = openai.OpenAI()
mlflow.openai.autolog()


@mlflow.trace
def worker(question: str) -> str:
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": question},
]
response = client.chat.completions.create(
model="gpt-4o-mini", messages=messages, temperature=0.1, max_tokens=100
)
return response.choices[0].message.content


@mlflow.trace
def main(questions: list[str]) -> list[str]:
results = []
with ThreadPoolExecutor(max_workers=2) as executor:
futures = []
for question in questions:
ctx = contextvars.copy_context() # copy context in main thread
futures.append(executor.submit(ctx.run, worker, question)) # run in copy
for future in as_completed(futures):
results.append(future.result())
return results


main(["What is the capital of France?", "What is the capital of Germany?"])

Rastreamento multithread

dica

asyncio as tarefas herdam o contexto automaticamente — nenhuma cópia manual é necessária para o código async/await.

Saídas de transmissão

O decorador oferece suporte a funções geradoras e geradoras assíncronas (MLflow 2.20.2+). Por default, o MLflow coleta todos os valores produzidos como uma lista na saída do span. Passe um output_reducer para agregar os blocos da transmissão em um único valor — o redutor recebe a lista completa assim que a iteração for concluída:

Python
@mlflow.trace(output_reducer=lambda chunks: "".join(chunks))
def stream_text():
for word in ["Hello", " ", "World", "!"]:
yield word
# Span output: "Hello World!"

Os pedaços brutos permanecem visíveis na tab Events do intervalo para depuração, independentemente de você usar um redutor. Para transmissões de SDK de provedor cujos pedaços não são strings simples — como os objetos ChatCompletionChunk da OpenAI — escreva um redutor que acumule os deltas em um único objeto de resposta.

dica

Para a OpenAI em produção, prefira o rastreamento automático para a OpenAI, que lida com a transmissão automaticamente.

Tipos de função compatíveis:

Tipo de função

Suportado

Sincronizar

Todas as versões

Assíncrono

MLflow 2.16.0+

Gerador (síncrono ou assíncrono)

MLflow 2.20.2+

Tipo de função

Suportado

Sincronizar

Todas as versões

Assíncrono

MLflow 2.16.0+

Gerador (síncrono ou assíncrono)

MLflow 2.20.2+

O gerenciador de contexto mlflow.start_span()

Use mlflow.start_span() para rastrear qualquer bloco de código dentro de uma função. Assim como o decorator, ele gerencia relações de pai e filho e o registro de exceções automaticamente. Ao contrário do decorator, você define o nome do span, as entradas e as saídas por meio do objeto LiveSpan que ele retorna.

Python
import mlflow

with mlflow.start_span(name="my_span") as span:
x, y = 1, 2
span.set_inputs({"x": x, "y": y})
z = x + y
span.set_outputs(z)

Eventos de intervalo

SpanEvent objects record specific occurrences during a span's lifetime — with the current timestamp, a specific timestamp in nanoseconds, or from an exception:

Python
from mlflow.entities import SpanEvent, SpanType
import time

with mlflow.start_span(name="pipeline_step", span_type=SpanType.CHAIN) as span:
span.add_event(SpanEvent(
name="validation_completed",
attributes={"records_validated": 1000, "errors_found": 3},
))
span.add_event(SpanEvent(
name="data_checkpoint",
timestamp=int(time.time() * 1e9),
attributes={"checkpoint_id": "ckpt_123"},
))
try:
raise ValueError("Invalid input format")
except Exception as e:
# SpanEvent.from_exception captures exception.message, exception.type, exception.stacktrace
mlflow.get_current_active_span().add_event(SpanEvent.from_exception(e))

Status do intervalo

SpanStatus indica se um span foi bem-sucedido ou falhou. O gerenciador de contexto substitui o status na saída (OK na saída limpa, ERROR em caso de exceção), portanto, defina-o antes que o bloco with seja fechado se você precisar de um status personalizado:

Python
from mlflow.entities import SpanStatus, SpanStatusCode, SpanType

with mlflow.start_span(name="my_span", span_type=SpanType.CHAIN) as span:
span.set_status(SpanStatus(SpanStatusCode.OK))
# String shortcuts also work: span.set_status("OK") or span.set_status("ERROR")

Status da query de um span concluído:

Python
trace = mlflow.get_trace(mlflow.get_last_active_trace_id())
for span in trace.data.spans:
print(span.status.status_code)

Intervalos RETRIEVER

Use SpanType.RETRIEVER quando seu intervalo recuperar documentos de um armazenamento de dados. Os intervalos RETRIEVER devem gerar uma lista de objetos Document para que a IU os renderize corretamente:

Python
from mlflow.entities import Document, SpanType


@mlflow.trace(span_type=SpanType.RETRIEVER)
def retrieve_documents(query: str):
span = mlflow.get_current_active_span()
documents = [
Document(
page_content="The content of the document...",
metadata={"doc_uri": "path/to/document.md", "relevance_score": 0.95},
id="doc_123",
),
Document(
page_content="Another relevant section...",
metadata={"doc_uri": "path/to/other.md", "relevance_score": 0.87},
),
]
span.set_outputs(documents)
return [doc.to_dict() for doc in documents]


retrieve_documents(query="What is ML?")

Node.js / TypeScript

O pacote mlflow-tracing npm traz o rastreamento do MLflow para agentes TypeScript e JavaScript. A API espelha a abordagem do Python: uma API de encapsulamento de função (equivalente ao decorador), uma API de rastreamento de bloco (equivalente a start_span) e um decorador de método de classe para o TypeScript 5.0+.

Configurar

TypeScript
import * as mlflow from 'mlflow-tracing';

mlflow.init({
trackingUri: 'databricks',
experimentId: '<your-experiment-id>',
});

Encontre o ID do experimento no seu Workspace do Databricks em AI/ML > Experiments > GenAI apps & agents clicando no ícone Ícone de informações.. Configure credenciais com variáveis de ambiente:

Bash
export DATABRICKS_TOKEN=<personal-access-token>
export DATABRICKS_HOST=https://<workspace>.cloud.databricks.com

Rastrear uma função

Envolva qualquer função com mlflow.trace() para criar uma versão rastreada. O MLflow captura entradas, saídas, exceções e latência automaticamente. Chamadas rastreadas aninhadas produzem um rastreamento de vários intervalos que reflete a hierarquia de chamadas.

TypeScript
const getWeather = async (city: string) => `The weather in ${city} is sunny`;
const tracedGetWeather = mlflow.trace(getWeather, { name: 'get-weather' });
const result = await tracedGetWeather('San Francisco');

Decorador de método de classe (TypeScript 5.0+)

TypeScript
class MyAgent {
@mlflow.trace({ spanType: mlflow.SpanType.LLM })
generateText(prompt: string) {
return "It's sunny in Seattle!";
}
}

Rastreie um bloco de código

Use mlflow.withSpan() para rastrear um bloco de código — o equivalente em TypeScript de mlflow.start_span():

TypeScript
const result = await mlflow.withSpan(async (span: mlflow.Span) => "It's sunny in Seattle!", {
name: 'generateText',
spanType: mlflow.SpanType.TOOL,
inputs: { prompt: question },
});

Rastreamento automático para OpenAI

Envolva o cliente OpenAI com tracedOpenAI para rastrear todas as chamadas automaticamente:

TypeScript
import { OpenAI } from 'openai';
import { tracedOpenAI } from 'mlflow-openai';

const client = tracedOpenAI(new OpenAI());
const response = await client.chat.completions.create({
model: 'gpt-4o-mini',
messages: [{ role: 'user', content: "What's the weather in Seattle?" }],
});

Para ver um exemplo funcional completo, consulte o exemplo full-stack em TypeScript no GitHub.

Combine o rastreamento automático e manual

Rastreamento automático e rastreamento manual se compõem. Habilite autolog() para cada framework usado pelo seu agente, e o MLflow capturará essas chamadas em um único rastreamento; adicione @mlflow.trace para agrupá-las sob um span pai único ou para instrumentar suas próprias funções — pré/pós-processamento, lógica de negócios, roteamento — que o registro automático não vê.

Rastrear vários frameworks em um único rastreamento

Habilite o salvamento automático para cada framework e o MLflow combina suas chamadas em um único rastreamento coeso. Use isto quando o agente combinar chamadas diretas de LLM com uma camada de orquestração:

Python
import mlflow

mlflow.openai.autolog()
mlflow.langchain.autolog()

# All OpenAI and LangChain calls in the same execution appear in one trace

Para agrupar chamadas de vários frameworks sob um único span pai, envolva o fluxo de trabalho com @mlflow.trace:

Python
import mlflow
import openai
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate

mlflow.openai.autolog()
mlflow.langchain.autolog()

client = openai.OpenAI()

@mlflow.trace
def multi_provider_workflow(query: str):
# Direct OpenAI call — auto-traced as a child span
topics = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "Extract key topics from the query."},
{"role": "user", "content": query},
],
).choices[0].message.content

# LangChain chain — also auto-traced as a child span
chain = ChatPromptTemplate.from_template(
"Topics: {topics}\nRespond to: {query}"
) | ChatOpenAI(model="gpt-4o-mini")
return chain.invoke({"topics": topics, "query": query})

multi_provider_workflow("Explain quantum computing")

Adicionar intervalos manuais junto com o registro automático

Adicione @mlflow.trace às suas próprias funções para capturar a lógica que o registro automático não cobre. O MLflow faz o merge desses trechos com os capturados automaticamente em um único rastreamento:

Python
import mlflow
import openai

mlflow.openai.autolog()
client = openai.OpenAI()

@mlflow.trace
def run(question):
messages = build_messages(question)
response = client.chat.completions.create( # auto-traced by autolog
model="gpt-4o-mini", max_tokens=100, messages=messages,
)
return parse_response(response)

@mlflow.trace
def build_messages(question):
return [
{"role": "system", "content": "You are a helpful chatbot."},
{"role": "user", "content": question},
]

@mlflow.trace
def parse_response(response):
return response.choices[0].message.content

run("What is MLflow?")

Isso produz um rastreamento: um span pai run com os filhos build_messages e parse_response, além do span da OpenAI capturado automaticamente.

Combinação de rastreamento automático e manual

Implantar fora do Databricks

O rastreamento de um agente implantado fora do Databricks usa a mesma instrumentação. Defina as seguintes variáveis de ambiente antes de iniciar o processo do agente e, em seguida, instrumente seu código com qualquer um dos métodos acima:

Bash
export DATABRICKS_HOST="https://your-workspace.cloud.databricks.com"
export DATABRICKS_TOKEN="your-databricks-token"
export MLFLOW_TRACKING_URI=databricks
export MLFLOW_EXPERIMENT_NAME="/Shared/production-genai-agent"

Para implantações em produção, prefira o pacote leve mlflow-tracing (pip install mlflow-tracing) ao mlflow[databricks] completo. Para a configuração de armazenamento do Docker, do Kubernetes e do UC, consulte Agentes de rastreamento implantados fora do Databricks.

Avançado: API de cliente de baixo nível

A API MlflowClient oferece controle direto sobre todos os aspectos do ciclo de vida do rastreamento. A maioria dos agentes não precisa disso — use o decorador ou o gerenciador de contexto. Recorra à API do cliente quando precisar de esquemas de ID de rastreamento personalizados ou integração com um sistema de observabilidade existente.

importante

As APIs de cliente não interoperam com o decorador ou com mlflow.start_span(). Use um estilo consistentemente em um determinado rastreamento.

Ciclo de vida

Cada chamada de start_trace ou start_span deve ter um end_trace ou end_span correspondente. Intervalos não fechados produzem rastreamentos incompletos.

O ciclo de vida de rastreamento e intervalo (span): start_trace, start_span, end_span, end_trace.

Identificador

Descrição

Uso

request_id

Identificador exclusivo de rastreamento

Faz o Link de todos os intervalos no rastreamento

span_id

Identificador exclusivo do span

Identifica qual intervalo finalizar

parent_id

Do intervalo principal span_id

Cria a hierarquia de pai e filho

Identificador

Descrição

Uso

request_id

Identificador exclusivo de rastreamento

Faz o Link de todos os intervalos no rastreamento

span_id

Identificador exclusivo do span

Identifica qual intervalo finalizar

parent_id

Do intervalo principal span_id

Cria a hierarquia de pai e filho

Uso básico

Python
from mlflow import MlflowClient

client = MlflowClient()

root_span = client.start_trace(
name="my_agent_flow",
inputs={&quot;user_id&quot;: &quot;123&quot;, &quot;action&quot;: &quot;generate_report&quot;},
attributes={&quot;environment&quot;: &quot;production&quot;, &quot;version&quot;: &quot;1.0.0&quot;},
)
request_id = root_span.request_id

data_span = client.start_span(
name="fetch_user_data",
request_id=request_id,
parent_id=root_span.span_id,
inputs={&quot;user_id&quot;: &quot;123&quot;},
attributes={&quot;database&quot;: &quot;users_db&quot;},
)

client.end_span(
request_id=data_span.request_id,
span_id=data_span.span_id,
outputs={&quot;record_count&quot;: 42},
status="OK",
)

client.end_trace(
request_id=request_id,
outputs={&quot;report_url&quot;: &quot;https://example.com/report/123&quot;},
status="OK",
)

Tratamento de erros

Sempre feche os intervalos mesmo quando ocorrerem exceções. Um gerenciador de contexto reutilizável torna isso seguro e conciso:

Python
from contextlib import contextmanager

@contextmanager
def traced_span(client, name, request_id, parent_id=None, **kwargs):
span = client.start_span(name=name, request_id=request_id, parent_id=parent_id, **kwargs)
try:
yield span
except Exception as e:
client.end_span(request_id=span.request_id, span_id=span.span_id,
status="ERROR", attributes={&quot;error&quot;: str(e)})
raise
else:
client.end_span(request_id=span.request_id, span_id=span.span_id, status="OK")

# Usage
with traced_span(client, "my_operation", request_id, parent_id) as span:
result = perform_operation()

Armadilhas comuns

  1. Esquecer de encerrar os intervalos — sempre use try/finally ou o padrão de gerenciador de contexto acima.
  2. IDs pai incorretos — verifique se você está passando o span_id correto como parent_id.
  3. IDs de rastreamento hardcoded — sempre geram IDs exclusivas.
  4. Segurança de thread — as APIs de cliente não são thread-safe por default; gerencie a concorrência explicitamente.
  5. Usando mlflow.log_metric() — grava em uma execução do MLflow, e não no span atual. Em vez disso, use span.set_attribute() ou span.set_attributes().

Instrumentação OpenTelemetry personalizada

nota

A instrumentação OTel personalizada que envia rastreamentos para o Databricks usa a versão preliminar de rastreamento do OTel . Certifique-se de que esta versão preliminar esteja habilitada em seu workspace antes de prosseguir.

If your agent uses the OTel SDK directly rather than a pre-built integration, set the span attributes described in this section so MLflow renders span types, inputs, outputs, and tokens counts correctly. Pre-built integrations set these attributes automatically.

nota

Os mapeamentos de atributos OTel para o MLflow gerenciado na Databricks diferem daqueles do MLflow OSS. Para o mapeamento de atributos OSS, consulte a documentação do MLflow.

Requisitos

Esta seção requer um experimento apoiado pelo Unity Catalog com um local de rastreio OTel e a visualização de rastreio OTel habilitada no seu workspace. Consulte Requisitos.

Definir o tipo de intervalo

Defina gen_ai.operation.name para identificar o tipo de operação. O MLflow lê este atributo e exibe o tipo de span do MLflow correspondente na IU de rastreamento. O valor segue a Convenção Semântica OpenTelemetry GenAI.

Valor do OTel gen_ai.operation.name

Tipo de intervalo do MLflow

chat

CHAT_MODEL

text_completion

LLM

generate_content

LLM

response

LLM

embeddings

EMBEDDING

execute_tool

TOOL

create_agent

AGENT

invoke_agent

AGENT

Valor do OTel gen_ai.operation.name

Tipo de intervalo do 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")

Definir entradas e saídas

Defina gen_ai.input.messages e gen_ai.output.messages em cada intervalo que deve exibir entradas e saídas. Defini-los no intervalo raiz também preenche as visualizações de solicitação e resposta no nível do rastreamento.

Atributo OTel

Atributo do MLflow

gen_ai.input.messages

mlflow.spanInputs

gen_ai.output.messages

mlflow.spanOutputs

Atributo OTel

Atributo do MLflow

gen_ai.input.messages

mlflow.spanInputs

gen_ai.output.messages

mlflow.spanOutputs

Os valores podem ser strings simples ou strings serializadas em JSON. Matrizes JSON de objetos de mensagem com campos role e content permitem uma renderização mais rica na IU do MLflow (rotulados como bolhas "User" e "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."}
]))

Definir o uso de tokens

Defina gen_ai.usage.input_tokens e gen_ai.usage.output_tokens no intervalo raiz para exibir contagens de token no resumo de rastreamento da UI. O MLflow lê esses valores do intervalo raiz porque agrega contagens no nível do rastreamento.

Atributo gen_ai.usage.* do OTel

Campo de token do MLflow

gen_ai.usage.input_tokens

Contagem de tokens de entrada

gen_ai.usage.output_tokens

Contagem de tokens de saída

(não definido — calculado automaticamente)

Contagem total de tokens

Atributo gen_ai.usage.* do OTel

Campo de token do MLflow

gen_ai.usage.input_tokens

Contagem de tokens de entrada

gen_ai.usage.output_tokens

Contagem de tokens de saída

(não definido — calculado automaticamente)

Contagem total de tokens

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

Definir sessão e usuário

Defina session.id e user.id para associar rastreamentos a uma sessão ou usuário específico. O MLflow os lê a partir do span raiz e os exibe como metadados em nível de rastreamento. A configuração de session.id habilita a tab de sessão na interface do usuário do MLflow.

Atributo OTel

Campo de metadados do MLflow

session.id

Identificador de sessão ou conversa

user.id

Identificador do usuário final do agente

Atributo OTel

Campo de metadados do MLflow

session.id

Identificador de sessão ou conversa

user.id

Identificador do usuário final do agente

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

Exemplo completo: um agente Python com um intervalo filho de LLM

O exemplo a seguir reúne todas as quatro categorias de atributos em um agente simples com um intervalo filho de LLM. Ele pressupõe que você já tenha configurado o exportador OTLP para enviar rastreamentos para o 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

Verificar na interface do usuário do MLflow

Depois de chamar run_agent(), abra a Traces tab em seu experimento do MLflow. Um rastreio instrumentado corretamente mostra:

  • Tipos de intervalo : cada intervalo exibe seu rótulo de tipo (por exemplo, chat) em vez de UNKNOWN.
  • Solicitação e resposta : O intervalo raiz mostra as mensagens de entrada e saída.
  • Token usage : The trace summary displays input, output, and total token counts.
  • Session and user : o rastreamento aparece na tab de sessão sob o identificador de sessão especificado, e o ID de usuário aparece nos metadados do rastreamento.

Rastreamento OTel GenAI no MLflow

Buscar rastreamentos por atributos de span do OTel

Após a ingestão dos rastreamentos no Unity Catalog — seja do Langfuse ou de um agente instrumentado por OTel personalizado —, use o prefixo span.attributes.* em mlflow.search_traces() para filtrar pelos valores de atributos do OTel definidos por você. O nome do atributo após o prefixo é o mesmo nome passado para 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"
)

Para ver a sintaxe completa de filter_string, incluindo operadores e comparadores suportados, consulte Acesso programático a rastreamentos.

Limitações

Os atributos de span OTel personalizados não aparecem como tags de rastreamento do MLflow. Os atributos definidos com span.set_attribute() fora dos mapeamentos reconhecidos de OTel para MLflow não aparecem em:

  • A coluna Tags ou a unified trace view na interface do usuário do MLflow.
  • A tabela do _traces_unified Unity Catalog.
  • O campo tags retornado por mlflow.search_traces().

Esses atributos são preservados no intervalo subjacente. Eles permanecem visíveis na tab Attributes da IU de rastreamento e podem ser consultados por meio do campo <prefix>_otel_spans.attributes da tabela de spans OTel.

Para anexar tags pesquisáveis que aparecem na view de rastreamento unificada, use as APIs de tag do MLflow. Consulte Enriquecer rastreamentos: tags, contexto e feedback.

Referência do modelo de dados de rastreamento

Os atributos de span, os tipos de span e os conceitos de ciclo de vida abaixo aplicam-se a qualquer span que você criar, seja por meio de um decorator, de um gerenciador de contexto ou do cliente de baixo nível.

Atributos do intervalo

Os atributos são pares key-value que fornecem percepções sobre a configuração e o contexto de execução de uma operação.

Você pode adicionar atributos específicos da plataforma para enriquecer a observabilidade. Por exemplo, você pode adicionar os objetos do Unity Catalog tocados pelo intervalo, o endpoint de servindo modelo ou o recurso de compute.

Por exemplo, defina atributos em um intervalo que encapsula uma chamada LLM:

Python
span.set_attributes({
"ai.model.name": "claude-3-5-sonnet-20241022",
"ai.model.version": "2024-10-22",
"ai.model.provider": "anthropic",
"ai.model.temperature": 0.7,
"ai.model.max_tokens": 1000,
})

Tipos de intervalo

O MLflow fornece valores predefinidos SpanType para operações comuns. Para casos especializados, passe um valor de string personalizado como o tipo de intervalo.

Tipo

Descrição

CHAT_MODEL

Query para um modelo de chat (interação especializada de LLM)

CHAIN

Cadeia de operações

AGENT

Operação de agente autônomo

TOOL

Execução de ferramenta (normalmente por agentes), como queries de pesquisa

EMBEDDING

Operação de incorporação de texto

RETRIEVER

Operação de recuperação de contexto, como queries em banco de dados vetorial

PARSER

Operação de análise transformando texto em formato estruturado

RERANKER

Contextos de ordenação de operações de reclassificação por relevância

MEMORY

Operação de memória que persiste o contexto no armazenamento de longo prazo

UNKNOWN

Tipo default usado quando nenhum outro tipo é especificado

Tipo

Descrição

CHAT_MODEL

Query para um modelo de chat (interação especializada de LLM)

CHAIN

Cadeia de operações

AGENT

Operação de agente autônomo

TOOL

Execução de ferramenta (normalmente por agentes), como queries de pesquisa

EMBEDDING

Operação de incorporação de texto

RETRIEVER

Operação de recuperação de contexto, como queries em banco de dados vetorial

PARSER

Operação de análise transformando texto em formato estruturado

RERANKER

Contextos de ordenação de operações de reclassificação por relevância

MEMORY

Operação de memória que persiste o contexto no armazenamento de longo prazo

UNKNOWN

Tipo default usado quando nenhum outro tipo é especificado

Você atribui um tipo de intervalo ao criar o intervalo. Consulte Personalizar intervalos para saber como definir span_type no decorador ou o gerenciador de contexto para um bloco de intervalo.

Rastreamentos e intervalos ativos vs. concluídos

Um rastreamento ativo é aquele que o MLflow está gravando no momento, por exemplo, enquanto uma função decorada com @mlflow.trace está em execução. Após a saída da função decorada, o rastreamento é concluído , mas você ainda pode anová-lo com novos dados.

Os intervalos seguem o mesmo ciclo de vida. Um intervalo ativo, representado por LiveSpan, é produzido por uma função decorada ou um gerenciador de contexto de intervalo. Após a saída da função ou o fechamento do gerenciador de contexto, o intervalo é concluído e se torna um Span imutável.

Para trabalhar com rastreamentos e spans ativos ou recentes, use estes métodos:

Recursos adicionais

Próximo passo: Enriquecer rastreamentos: tags, contexto e feedback