Enriquecer rastreamentos: tags, contexto e feedback
Depois de instrumentar o agente para emitir rastreamentos, você poderá enriquecer esses rastreamentos com informações adicionais que os tornam úteis para pesquisa, depuração e monitoramento de qualidade:
- Tags e metadados — pares key-value para organizar, filtrar e anotar rastreamentos.
- Contexto — ID do usuário, ID da sessão, ambiente e versão do agente para análise de coorte e depuração específica de implantação.
- Feedback do usuário final — classificações e comentários capturados como avaliações em rastreamentos, fornecendo um sinal de qualidade de verdade fundamental (ground truth) da produção.
Um padrão de produção fundamental é o feedback do usuário final. Quando alguém clicar em polegar para cima ou para baixo, ou deixar um comentário no seu aplicativo implantado, registre-o como uma avaliação no rastreamento para essa interação. Manter o feedback anexado à execução de origem o torna imediatamente útil para fins posteriores — para depurar a solicitação específica e para criar datasets de avaliação a partir de sucessos e falhas reais.
Requisitos
Escolha o pacote adequado para o seu ambiente:
- Production
- Development
pip install --upgrade mlflow-tracing
O pacote mlflow-tracing tem dependências mínimas e é otimizado para uso em produção.
pip install --upgrade "mlflow[databricks]>=3.1.0" openai "databricks-connect>=16.1"
Crie um experimento do MLflow seguindo Set up your environment.
Tags e metadados
As tags são pares key-value mutáveis que você pode definir, atualizar ou excluir a qualquer momento — inclusive após o rastreamento ser registrado. Use tags para informações dinâmicas: status de revisão, rótulos de qualidade dos dados ou sinais de feedback do usuário.
Os metadados são imutáveis assim que o rastreamento é registrado. Use metadados para fatos estáveis capturados no momento da execução: versão do modelo, ambiente ou configuração.
API | Quando usar |
|---|---|
Defina tags ou metadados em um rastreamento ativo durante a execução | |
Definir ou atualizar uma tag em um rastreamento concluído | |
Remover uma tag de um rastreamento concluído | |
IU do MLflow | Defina ou atualize as tags em um rastreamento concluído de forma interativa |
Definir tags e metadados durante a execução
Chame mlflow.update_current_trace dentro de uma função rastreada para anexar tags ou metadados enquanto
o rastreamento estiver ativo:
import mlflow
@mlflow.trace
def my_func(x):
mlflow.update_current_trace(
metadata={"model_version": "v1.2.3", "environment": "production"},
tags={"fruit": "apple"}
)
return x + 1
my_func(10)
update_current_trace adiciona uma nova key ou sobrescreve uma key existente para tags . Para metadados , tentar atualizar uma key existente é ignorado silenciosamente — os metadados são imutáveis após definidos.
Definir tags em um rastreamento concluído
Para atualizar ou remover tags após o registro de um rastreamento:
import mlflow
@mlflow.trace
def process_data(data):
return data.upper()
result = process_data("hello world")
trace_id = mlflow.get_last_active_trace_id()
mlflow.set_trace_tag(trace_id=trace_id, key="review_status", value="approved")
mlflow.set_trace_tag(trace_id=trace_id, key="data_quality", value="high")
mlflow.delete_trace_tag(trace_id=trace_id, key="data_quality")
Definir tags na IU
Navegue até o rastreamento e clique no ícone de lápis ao lado de qualquer tag para editá-la ou excluí-la.

Adicionar contexto aos rastreamentos
O contexto vincula rastreamentos a usuários, sessões, implantações e código — permitindo o agrupamento de conversas com várias entradas, análise de coorte de usuários e depuração específica de ambiente.
Chame mlflow.update_current_trace dentro da lógica do seu agente rastreado para anexar o contexto:
import mlflow
mlflow.update_current_trace(
metadata={
"mlflow.trace.user": user_id,
"mlflow.trace.session": session_id,
},
tags={
"query_category": "chat",
},
)
After logging, access context via mlflow.search_traces() (the metadata and tags columns
in the returned DataFrame), or directly on Trace objects via
Trace.info.trace_metadata
and Trace.info.tags.
Consulte Enriquecer rastreamentos: tags, contexto e feedback para ver um exemplo prático completo.
Campos de contexto padrão
O MLflow define campos de metadados padronizados para os tipos de contexto mais comuns. Quando você os usa, a interface do usuário ativa automaticamente a filtragem e o agrupamento por esses campos.
Context type | Campo do MLflow | Casos de uso |
|---|---|---|
ID do usuário |
| Associar rastreamentos a usuários específicos para personalização, análise de coorte e depuração específica do usuário |
ID da sessão |
| Agrupe rastreamentos de conversas em vários turnos para analisar o fluxo conversacional completo |
ID de solicitação do cliente | Link rastreia chamadas de API upstream para depuração de ponta a ponta | |
Ambiente / versão |
| Rastreie o contexto de implantação em diferentes ambientes e versões de agentes |
Custom fields | (as suas chaves de metadados) | Qualquer contexto específico do agente: ID de implantação, região, sinalizadores de recursos |
Campos preenchidos automaticamente
O MLflow define automaticamente vários campos de metadados do seu ambiente de execução. Você pode substituir qualquer um deles por mlflow.update_current_trace quando a detecção default não atender aos seus requisitos.
Campo de metadados | Descrição | Definição automática a partir de |
|---|---|---|
| Ponto de entrada ou nome do script | Nome do arquivo Python; nome do notebook do Databricks |
| Hash do commit do Git | Repositório git atual |
| Nome da branch do Git | Repositório git atual |
| URL do repositório do Git | Repositório git atual |
| Ambiente de execução |
|
| ID de execução de origem | Execução ativa do MLflow |
| ID do LoggedModel do MLflow |
|
Para metadados de implantação como ambiente e versão, extraia valores de variáveis de ambiente em vez de codificá-los rigidamente:
import mlflow
import os
mlflow.update_current_trace(
metadata={
"mlflow.source.type": os.getenv("APP_ENVIRONMENT", "development"),
}
)
Práticas recomendadas
- Formatos de ID consistentes — Use formatos padronizados para IDs de usuário e de sessão em todo o agente.
- Limites de sessão — Defina regras claras para quando as sessões começam e terminam.
- Variáveis de ambiente — Preencha metadados a partir de variáveis de ambiente em vez de usar valores codificados rigidamente.
- Combine context types — Rastreie o contexto do usuário, da sessão e do ambiente juntos.
- Análise regular — Configure dashboards para monitorar o comportamento do usuário, os padrões de sessão e o desempenho da versão.
- Substituir os values default com cuidado — Só substitua metadados preenchidos automaticamente quando o valor detectado automaticamente não se adequar à sua implantação.
Coletar feedback do usuário
O feedback do usuário final fornece um sinal de verdade fundamental sobre a qualidade real do seu agente. O MLflow captura o feedback como avaliações — uma entidade estruturada permanentemente anexada a um rastreamento — para que cada classificação permaneça associada à interação exata que a motivou.

Tipos de feedback
Tipo de feedback | Descrição | Casos de uso comuns |
|---|---|---|
binário | Polegar para cima/para baixo ou correto/incorreto | Sinais de satisfação rápidos |
Numérico | Avaliações em uma escala (por exemplo, 1–5 estrelas) | Avaliação detalhada da qualidade |
Categórico | Opções de múltipla escolha | Classificando problemas ou tipos de resposta |
Texto | Comentários em formato livre | Explicações detalhadas do usuário |
Feedback data model
O feedback do usuário é capturado como uma entidade Feedback (um tipo de Avaliação) anexada a um rastreamento ou intervalo. Cada entidade de feedback armazena:
- Valor — o sinal de feedback (booleano, numérico, texto ou dados estruturados)
- Source — um
AssessmentSourceque identifica quem forneceu o feedback (consulte abaixo) - Rationale — explicação opcional para o feedback
- Metadados — contexto adicional, como Timestamp ou atributos personalizados
Campos AssessmentSource
The AssessmentSource object on every feedback assessment identifies the origin of the feedback:
source_type—"HUMAN"para feedback do usuário final,"LLM_JUDGE"para avaliação automatizadasource_id— o usuário ou sistema específico que forneceu o feedback (por exemplo, uma string de ID de usuário ou identificador de avaliador)
Passe ambos os campos ao chamar mlflow.log_feedback:
from mlflow.entities import AssessmentSource
mlflow.log_feedback(
trace_id=trace_id,
name="user_feedback",
value=True,
source=AssessmentSource(source_type="HUMAN", source_id=user_id),
rationale="The answer was accurate and helpful.",
)
Link feedback a rastreamentos
Para registrar o feedback, você precisa associar a resposta do usuário a um rastreamento específico. Duas abordagens:
Abordagem 1 — Usar o ID de rastreamento do MLflow (mais simples): recupere o ID de rastreamento gerado pelo MLflow durante a solicitação e retorne-o ao cliente. O cliente o envia de volta com o feedback.
Abordagem 2 — Usar um ID de solicitação do cliente (mais controle): gere seu próprio ID exclusivo por solicitação, anexe-o como uma tag de rastreamento e, em seguida, pesquise o rastreamento por essa tag quando o feedback chegar. Útil quando você já tem um sistema de acompanhamento de solicitações.
Se você implantar seu agente em um Endpoint do Databricks Model Serving, defina client_request_id como uma
tag (e não como um atributo). Usar update_current_trace(client_request_id=...) como um atributo
de metadados interrompe a exportação de rastreamentos em ambientes de serviço. Se você precisar usar o Model Serving,
prefira a Abordagem 1 (IDs de rastreamento do MLflow) ou defina client_request_id por meio de
update_current_trace(tags={"client_request_id": ...}).
- Approach 1: MLflow trace ID
- Approach 2: Client request ID
Backend
import mlflow
from fastapi import FastAPI, Query
from mlflow.entities import AssessmentSource
from pydantic import BaseModel
from typing import Optional
app = FastAPI()
class ChatRequest(BaseModel):
message: str
class ChatResponse(BaseModel):
response: str
trace_id: str # Return the trace ID so the client can reference it for feedback
@app.post("/chat", response_model=ChatResponse)
def chat(request: ChatRequest):
response = process_message(request.message) # Your agent logic here
trace_id = mlflow.get_current_active_span().trace_id
return ChatResponse(response=response, trace_id=trace_id)
class FeedbackRequest(BaseModel):
is_correct: bool
comment: Optional[str] = None
@app.post("/feedback")
def submit_feedback(
trace_id: str = Query(..., description="Trace ID from the chat response"),
feedback: FeedbackRequest = ...,
user_id: Optional[str] = Query(None)
):
mlflow.log_feedback(
trace_id=trace_id,
name="user_feedback",
value=feedback.is_correct,
source=AssessmentSource(source_type="HUMAN", source_id=user_id),
rationale=feedback.comment
)
return {"status": "success", "trace_id": trace_id}
Frontend (React)
import React, { useState } from 'react';
function ChatWithFeedback() {
const [message, setMessage] = useState('');
const [response, setResponse] = useState('');
const [traceId, setTraceId] = useState(null);
const [feedbackSubmitted, setFeedbackSubmitted] = useState(false);
const sendMessage = async () => {
const res = await fetch('/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message }),
});
const data = await res.json();
setResponse(data.response);
setTraceId(data.trace_id);
setFeedbackSubmitted(false);
};
const submitFeedback = async (isCorrect, comment = null) => {
if (!traceId || feedbackSubmitted) return;
const params = new URLSearchParams({ trace_id: traceId });
await fetch(`/feedback?${params}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ is_correct: isCorrect, comment }),
});
setFeedbackSubmitted(true);
};
return (
<div>
<input value={message} onChange={(e) => setMessage(e.target.value)} placeholder="Ask a question..." />
<button onClick={sendMessage}>Send</button>
{response && (
<div>
<p>{response}</p>
<div>
<button onClick={() => submitFeedback(true)} disabled={feedbackSubmitted}>
👍
</button>
<button onClick={() => submitFeedback(false)} disabled={feedbackSubmitted}>
👎
</button>
</div>
{feedbackSubmitted && Thanks for your feedback!</span>}
</div>
)}
</div>
);
}
Anexe um ID personalizado como uma tag durante a solicitação e, em seguida, pesquise o rastreamento por essa tag quando o feedback chegar.
Backend
import mlflow
from fastapi import FastAPI, Query, Request
from mlflow.client import MlflowClient
from mlflow.entities import AssessmentSource
from pydantic import BaseModel
from typing import Optional
import uuid
app = FastAPI()
class ChatRequest(BaseModel):
message: str
class ChatResponse(BaseModel):
response: str
client_request_id: str
@app.post("/chat", response_model=ChatResponse)
def chat(request: ChatRequest):
client_request_id = f"req-{uuid.uuid4().hex[:8]}"
# Must be a tag, not an attribute — required for Model Serving compatibility
mlflow.update_current_trace(tags={"client_request_id": client_request_id})
response = process_message(request.message)
return ChatResponse(response=response, client_request_id=client_request_id)
class FeedbackRequest(BaseModel):
is_correct: bool
comment: Optional[str] = None
@app.post("/feedback")
def submit_feedback(
request: Request,
client_request_id: str = Query(..., description="Request ID from the original interaction"),
feedback: FeedbackRequest = ...
):
client = MlflowClient()
experiment = client.get_experiment_by_name("/Shared/production-app")
traces = client.search_traces(
experiment_ids=[experiment.experiment_id],
filter_string=f"tags.client_request_id = '{client_request_id}'",
max_results=1
)
if not traces:
return {"status": "error", "message": "Unexpected error: request not found"}, 500
mlflow.log_feedback(
trace_id=traces[0].info.trace_id,
name="user_feedback",
value=feedback.is_correct,
source=AssessmentSource(
source_type="HUMAN",
source_id=request.headers.get("X-User-ID")
),
rationale=feedback.comment
)
return {"status": "success", "trace_id": traces[0].info.trace_id}
O frontend espelha a Abordagem 1 — enviar a mensagem, armazenar o client_request_id retornado por turno de conversa e enviá-lo de volta com cada envio de feedback.
Feedback multidimensional
Registre várias avaliações nomeadas em um único rastreamento para capturar dimensões de qualidade separadas:
from mlflow.entities import AssessmentSource
@app.post("/detailed-feedback")
def submit_detailed_feedback(
trace_id: str,
accuracy: int = Query(..., ge=1, le=5, description="Accuracy rating 1–5"),
helpfulness: int = Query(..., ge=1, le=5, description="Helpfulness rating 1–5"),
relevance: int = Query(..., ge=1, le=5, description="Relevance rating 1–5"),
user_id: str = Query(...),
comment: Optional[str] = None
):
dimensions = {"accuracy": accuracy, "helpfulness": helpfulness, "relevance": relevance}
for dimension, score in dimensions.items():
mlflow.log_feedback(
trace_id=trace_id,
name=f"user_{dimension}",
value=score / 5.0, # Normalize to 0–1 scale
source=AssessmentSource(source_type="HUMAN", source_id=user_id),
rationale=comment if dimension == "accuracy" else None
)
return {"status": "success", "trace_id": trace_id, "feedback_recorded": dimensions}
Respostas em transmissão
Com transmissão (SSE ou WebSockets), o ID de rastreamento não estará disponível até que a transmissão seja concluída. Retorne-o como um evento de transmissão final e desative os controles de feedback até que ele chegue.
Backend (FastAPI SSE)
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import mlflow, json, asyncio
from typing import AsyncGenerator
@app.post("/chat/stream")
async def chat_stream(request: ChatRequest):
async def generate() -> AsyncGenerator[str, None]:
try:
with mlflow.start_span(name="streaming_chat") as span:
full_response = ""
async for token in your_llm_stream_function(request.message):
full_response += token
yield f"data: {json.dumps({'type': 'token', 'content': token})}\n\n"
await asyncio.sleep(0.01) # Prevent overwhelming the client
span.set_attribute("response", full_response)
span.set_attribute("token_count", len(full_response.split()))
# Send trace ID as the final event
yield f"data: {json.dumps({'type': 'done', 'trace_id': span.trace_id})}\n\n"
except Exception as e:
yield f"data: {json.dumps({'type': 'error', 'error': str(e)})}\n\n"
return StreamingResponse(
generate(),
media_type="text/event-stream",
headers={
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"X-Accel-Buffering": "no", # Disable proxy buffering
},
)
No frontend, leia a transmissão, acumule token eventos no texto de resposta e capture a ID de rastreamento do evento done final. Use traceId && !isStreaming como a condição para habilitar os controles de feedback.
Notas de implementação principais:
- O ID do rastreamento só fica disponível após a conclusão da transmissão — projete sua interface para desativar os controles de feedback até que ele chegue.
- Use um formato de evento consistente com um campo
typepara distinguir tokens de conteúdo, eventos de conclusão e erros. - Defina
X-Accel-Buffering: nopara desativar o buffer de proxy. - Implemente o buffer de linha no frontend para lidar com mensagens SSE parciais.
- Include error events in the transmissão so failures are logged to the trace and visible to the user.
Analisar feedback
Visualize o feedback na interface do usuário do MLflow abrindo qualquer rastreamento — as avaliações aparecem junto aos dados do intervalo.


Query e agregue o feedback programaticamente:
from mlflow.client import MlflowClient
from datetime import datetime, timedelta
def analyze_user_feedback(experiment_name: str, hours: int = 24):
client = MlflowClient()
cutoff_ms = int((datetime.now() - timedelta(hours=hours)).timestamp() * 1000)
traces = client.search_traces(
experiment_names=[experiment_name],
filter_string=f"trace.timestamp_ms > {cutoff_ms}"
)
total = len(traces)
with_feedback = positive = negative = 0
for trace in traces:
detail = client.get_trace(trace.info.trace_id)
if detail.data.assessments:
with_feedback += 1
for a in detail.data.assessments:
if a.name == "user_feedback":
if a.value:
positive += 1
else:
negative += 1
feedback_rate = (with_feedback / total * 100) if total else 0
positive_rate = (positive / with_feedback * 100) if with_feedback else 0
print(f"Feedback rate: {feedback_rate:.1f}% Positive: {positive_rate:.1f}%")
print(f"Total feedback: {with_feedback} of {total} traces")
analyze_user_feedback("/Shared/production-genai-agent")
O mesmo padrão se estende ao feedback multidimensional: faça a iteração sobre as avaliações de cada rastreamento e agrupe a.value por a.name para calcular a média de cada dimensão de classificação separadamente.
Outros recursos
- Enriquecer rastreamentos: tags, contexto e feedback - Tutorial completo: adicione contexto de usuário, sessão, ambiente e versão aos rastreamentos
- Acesso programático a rastreamentos — Filtrar e pesquisar rastreamentos usando tags e metadados
- Encontrar problemas em rastreamentos - Exemplos de analítica de rastreamento
- Criando conjuntos de dados de avaliação do MLflow — Use o feedback coletado para criar conjuntos de dados de avaliação
- Configurar monitoramento de produção — Monitore métricas de qualidade com base no feedback
Próximo passo: Armazenar rastreamentos do OpenTelemetry no Unity Catalog