05 Fechar o ciclo
Transforme uma falha de produção revisada em dado dourado, evaluator calibrado de política de negócio e proteção para o tráfego futuro.
Ponto de partida
O Módulo 04 terminou com uma anotação humana concluída para o chat_turn autoritativo do Módulo 03. Mantenha disponíveis o SQL corrigido e a planilha de proveniência:
source=production-feedback
source_trace_id=<authoritative Chat trace ID>
failure_category=stale-business-policy
source_policy_version=policy-v1
annotation_id=<completed task ID when available>O trace original tem sql-execution-success=true e user-thumbs=false. O 👎 encontrou um trace que merecia revisão; a anotação concluída forneceu o diagnóstico e a verdade corrigida.
O ciclo contínuo de avaliação e melhoria
Este módulo fecha uma volta do ciclo:
- o feedback revela uma lacuna no evaluator online atual;
- uma pessoa investiga e aprova a correção;
- o incidente revisado amplia o dataset dourado;
- versões baseline e candidata executam no mesmo dataset ampliado;
- um evaluator geral é calibrado offline antes de ser ativado online; e
- o tráfego futuro continua coletando pontuações e feedback.
A última etapa é essencial: um evaluator melhor não encerra o feedback. Ele só mede dimensões presentes em seu catálogo e prompt. Um futuro 👎 pode revelar outra política ausente, solicitação ambígua ou modo de falha e reiniciar o ciclo.
Objetivo
Passar por cinco portões de evidência: promover, baseline, candidata, calibrar e, por fim, ativar e reproduzir. Use o vencedor do Módulo 02 nos dois experimentos, deixando a versão da política como única mudança intencional.
Execute os comandos em ClickHouse_Demos/workshops/agent_arena:
cd ClickHouse_Demos/workshops/agent_arena
source .env
export WINNER_MODEL="${WINNER_MODEL:-qwen3.7-flash}"
export WINNER_PROMPT="${WINNER_PROMPT:-P2_fewshot}"
export WINNER_CONFIG_ID="${WINNER_CONFIG_ID:-qwen3.7-flash__P2_fewshot}"Os padrões são do workshop verificado. Se sua turma escolheu outro config_id, defina os três valores correspondentes e não os altere entre portões.
Portão de evidência 1 — Promover o incidente revisado
Crie reviewed.json na raiz com os três registros abaixo. Substitua os dois placeholders em toda parte. Se o Langfuse não mostrar ID da tarefa, remova annotation_id dos três registros; ele é opcional, os demais campos de proveniência são obrigatórios.
[
{
"id": "prod-active-001",
"question": "How many active customers do we have?",
"golden_sql": "SELECT uniqExact(customer_id) FROM v_orders WHERE order_ts >= now() - INTERVAL 30 DAY AND status NOT IN ('cancelled', 'returned')",
"tier": 2,
"ordered": false,
"source": "production-feedback",
"source_trace_id": "<paste the Module 03 Chat trace ID>",
"failure_category": "stale-business-policy",
"source_policy_version": "policy-v1",
"annotation_id": "<paste the completed task ID>"
},
{
"id": "prod-active-002",
"question": "What is our active customer count right now?",
"golden_sql": "SELECT uniqExact(customer_id) FROM v_orders WHERE order_ts >= now() - INTERVAL 30 DAY AND status NOT IN ('cancelled', 'returned')",
"tier": 2,
"ordered": false,
"source": "production-feedback",
"source_trace_id": "<paste the Module 03 Chat trace ID>",
"failure_category": "stale-business-policy",
"source_policy_version": "policy-v1",
"annotation_id": "<paste the completed task ID>"
},
{
"id": "prod-active-003",
"question": "How many customers qualify as active under our business definition?",
"golden_sql": "SELECT uniqExact(customer_id) FROM v_orders WHERE order_ts >= now() - INTERVAL 30 DAY AND status NOT IN ('cancelled', 'returned')",
"tier": 2,
"ordered": false,
"source": "production-feedback",
"source_trace_id": "<paste the Module 03 Chat trace ID>",
"failure_category": "stale-business-policy",
"source_policy_version": "policy-v1",
"annotation_id": "<paste the completed task ID>"
}
]Somente prod-active-001 é a pergunta exata do feedback. prod-active-002 e prod-active-003 são paráfrases escritas pelo revisor a partir do mesmo incidente; usam o mesmo trace e anotação para auditoria, não são outros dois traces. As três entradas invocam a métrica governada de cliente ativo, impedindo que o baseline pareça saudável ao testar contagens irrelevantes.
Promova o lote:
source .env
.venv/bin/python -m scripts.promote_to_golden reviewed.jsonEspere três linhas prepared prod-active-* seguidas de:
promoted 3 question(s) into the 'arena-golden' datasetEm Langfuse → Datasets → arena-golden, inspecione os metadados: source=production-feedback, o mesmo source_trace_id real, failure_category=stale-business-policy e source_policy_version=policy-v1.
O corpus tem 20 perguntas YAML. q019 e q020 são holdouts few-shot, então um projeto limpo começa com 18 itens em arena-golden e chega a 21. Um projeto reutilizado pode ter outros itens aprovados; registre a proveniência em vez de apagá-los e exija IDs idênticos no baseline e na candidata.
reviewed.json é estado mutável ignorado e o caminho principal. O --synthetic-fixture versionado serve apenas para ensaio reproduzível; não representa anotação humana nem satisfaz este portão. Os modos são mutuamente exclusivos: nunca execute a alternativa sintética após a promoção genuína.
A promoção valida lote completo, SQL somente leitura e proveniência antes de consultar o ClickHouse ou escrever itens. Depois lê os metadados existentes e rejeita ID colidente com proveniência diferente. Se o preflight autenticado não comprovar a segurança, para sem escrever. Repetir uma promoção genuína só é seguro com proveniência idêntica.
Portão de evidência 2 — Executar o baseline policy-v1
Primeiro, provisione o judge orientado pelo catálogo para experimentos; sua regra de observação online nasce desativada:
source .env
.venv/bin/python -m scripts.provision_online_evaluators \
--business-policy-experimentsEspere experiment rule enabled=True; online rule enabled=False e confirme no Langfuse que a regra online continua desativada.
Dê um sufixo único à tentativa e execute modelo e prompt no dataset ampliado com a política antiga:
export LOOP_RUN_SUFFIX="${LOOP_RUN_SUFFIX:-$(date +%Y%m%d-%H%M%S)}"
export BASELINE_RUN_ID="online-loop-baseline-${LOOP_RUN_SUFFIX}"
export CANDIDATE_RUN_ID="online-loop-candidate-${LOOP_RUN_SUFFIX}"
.venv/bin/python -m eval.harness --run-id "$BASELINE_RUN_ID" \
--policy-version policy-v1 --models "$WINNER_MODEL" --prompts "$WINNER_PROMPT" \
--wait-for-score business-policy-adherenceO harness acrescenta --policy-v1 ao ID da versão e aguarda três pontuações em cada trace: correctness, agent-arena-llm-judge e business-policy-adherence. Não prossiga se expirar ou faltar pontuação.
Nos Experiments do Langfuse, registre contagem de itens e correctness agregada. Espere 21 num projeto limpo. Projetos reutilizados podem ter mais e provedores variam; o portão real é a comparação pareada abaixo.
Portão de evidência 3 — Executar a candidata policy-v2
Sem alterar dataset, modelo, prompt ou sufixo, execute:
.venv/bin/python -m eval.harness --run-id "$CANDIDATE_RUN_ID" \
--policy-version policy-v2 --models "$WINNER_MODEL" --prompts "$WINNER_PROMPT" \
--wait-for-score business-policy-adherenceRegistre o agregado e exija:
- IDs e contagens de itens idênticos;
- os três
prod-active-*passam decorrectness=0empolicy-v1acorrectness=1empolicy-v2; - nenhum item anterior sofre regressão de
correctness=1paracorrectness=0; e - correctness agregada da candidata não é menor.
Pare se um item existente regredir. Corrigir o incidente quebrando comportamento conhecido não passa no portão.
Portão de evidência 4 — Calibrar um judge geral de política
business-policy-adherence não é um “evaluator de cliente ativo”. Ele recebe pergunta, SQL e catálogo completo de métricas policy-v2, identifica a política aplicável e retorna PASS, FAIL ou NOT_APPLICABLE. Assim verifica clientes ativos, receita, conversão e margem bruta sem um evaluator por formulação. Repita a verificação para todos os itens prod-active-*.
Antes da produção, inspecione:
| Sonda de calibração | Execução/item | business-policy-adherence exigido |
|---|---|---|
| SQL desatualizado de cliente ativo | baseline prod-active-001 | FAIL |
| SQL corrigido de cliente ativo | candidata prod-active-001 | PASS |
| política de receita | candidata q005 | PASS |
| política de conversão view-to-purchase | candidata q018 | PASS |
| contagem simples de clientes | candidata q001 | NOT_APPLICABLE |
Repita para prod-active-002 e prod-active-003. Leia também o raciocínio: ele deve nomear a política e comparar o SQL. Uma contagem simples deve ser NOT_APPLICABLE, provando que o judge não força toda contagem na política de cliente ativo.
Mantenha a regra online desativada se uma categoria estiver errada, faltar pontuação, a saída estruturada estiver malformada ou houver regressão. A calibração offline permite examinar falsos positivos e negativos conhecidos antes de afetar o monitoramento.
Portão de evidência 5 — Ativar e reproduzir em policy-v2
Somente após todos os portões, ative a regra:
source .env
.venv/bin/python -m scripts.provision_online_evaluators \
--enable-business-policy-onlineEspere a regra exata agent-arena-business-policy-online com enabled=True. O comando falha de modo fechado se não encontrar uma pontuação de Experiment business-policy-adherence; a revisão manual continua sendo o portão de qualidade.
Pare o servidor policy-v1 e inicie a candidata:
source .env
AGENT_ARENA_POLICY_VERSION=policy-v2 \
.venv/bin/uvicorn serving.api:app --port 8100No segundo terminal, defina um helper que só retorna o ID após confirmar sucesso em policy-v2:
source .env
export WINNER_CONFIG_ID="${WINNER_CONFIG_ID:-qwen3.7-flash__P2_fewshot}"
ask_trace() {
local question="$1"
local body
body=$(.venv/bin/python -c \
'import json,sys; print(json.dumps({"question": sys.argv[1], "config_id": sys.argv[2]}))' \
"$question" "$WINNER_CONFIG_ID")
curl -fsS http://localhost:8100/ask \
-H 'content-type: application/json' -d "$body" | \
.venv/bin/python -c \
'import json,sys; data=json.load(sys.stdin); assert data["policy_version"] == "policy-v2" and data["outcome"] == "ok"; print(data["trace_id"])'
}Faça uma pergunta de cliente ativo e uma de receita. Pontuações online usam o nome da regra agent-arena-business-policy-online, não o nome do Experiment:
ACTIVE_TRACE=$(ask_trace "How many active customers do we have?")
.venv/bin/python -m scripts.verify_online_scores "$ACTIVE_TRACE" \
sql-execution-success=true agent-arena-business-policy-online=PASS
REVENUE_TRACE=$(ask_trace "What was revenue in the last 30 days?")
.venv/bin/python -m scripts.verify_online_scores "$REVENUE_TRACE" \
sql-execution-success=true agent-arena-business-policy-online=PASSA pergunta de conversão tem limite estocástico verificado. Faça-a uma vez e preserve o trace. Se o outcome não for ok, ou faltarem/falharem as pontuações exatas, repita a mesma pergunta e configuração no máximo uma vez. O bloco mantém ambas visíveis:
ask_conversion() {
local body
body=$(.venv/bin/python -c \
'import json,sys; print(json.dumps({"question": sys.argv[1], "config_id": sys.argv[2]}))' \
"What is our view-to-purchase conversion rate for the last 7 days?" \
"$WINNER_CONFIG_ID")
curl -fsS http://localhost:8100/ask \
-H 'content-type: application/json' -d "$body" | \
.venv/bin/python -c \
'import json,sys; data=json.load(sys.stdin); assert data["policy_version"] == "policy-v2"; print("\t".join((data["trace_id"], data["outcome"])))'
}
IFS=$'\t' read -r CONVERSION_TRACE_1 CONVERSION_OUTCOME_1 <<< \
"$(ask_conversion)"
if .venv/bin/python -m scripts.verify_online_scores "$CONVERSION_TRACE_1" \
sql-execution-success=true agent-arena-business-policy-online=PASS; then
CONVERSION_SCORES_1=pass
else
CONVERSION_SCORES_1=fail
fi
if [ "$CONVERSION_OUTCOME_1" = ok ] && [ "$CONVERSION_SCORES_1" = pass ]; then
CONVERSION_RESULT_1=pass
else
CONVERSION_RESULT_1=fail
fi
printf 'conversion_attempt=1 trace_id=%s outcome=%s exact_scores=%s result=%s\n' \
"$CONVERSION_TRACE_1" "$CONVERSION_OUTCOME_1" \
"$CONVERSION_SCORES_1" "$CONVERSION_RESULT_1"
CONVERSION_TRACE_2=not-run
CONVERSION_OUTCOME_2=not-run
CONVERSION_SCORES_2=not-run
CONVERSION_RESULT_2=not-run
if [ "$CONVERSION_RESULT_1" != pass ]; then
IFS=$'\t' read -r CONVERSION_TRACE_2 CONVERSION_OUTCOME_2 <<< \
"$(ask_conversion)"
if .venv/bin/python -m scripts.verify_online_scores "$CONVERSION_TRACE_2" \
sql-execution-success=true agent-arena-business-policy-online=PASS; then
CONVERSION_SCORES_2=pass
else
CONVERSION_SCORES_2=fail
fi
if [ "$CONVERSION_OUTCOME_2" = ok ] && [ "$CONVERSION_SCORES_2" = pass ]; then
CONVERSION_RESULT_2=pass
else
CONVERSION_RESULT_2=fail
fi
fi
printf 'conversion_attempt=2 trace_id=%s outcome=%s exact_scores=%s result=%s\n' \
"$CONVERSION_TRACE_2" "$CONVERSION_OUTCOME_2" \
"$CONVERSION_SCORES_2" "$CONVERSION_RESULT_2"
if [ "$CONVERSION_RESULT_1" != pass ] && \
[ "$CONVERSION_RESULT_2" != pass ]; then
printf '%s\n' \
'STOP: conversion failed twice; preserve both traces and investigate.' >&2
false
fiNão repita até ficar verde. Se ambas falharem, preserve os traces, mantenha o resultado visível e encaminhe a evidência por anotação humana, melhoria de dados dourados e nova calibração pareada.
Somente após a conversão passar, faça uma contagem simples uma vez:
PRODUCT_TRACE=$(ask_trace "How many products are there?")
.venv/bin/python -m scripts.verify_online_scores "$PRODUCT_TRACE" \
sql-execution-success=true agent-arena-business-policy-online=NOT_APPLICABLEO evaluator online é assíncrono. O verificador consulta por até 180 segundos; pendente não significa reprovado.
Manter o ciclo em funcionamento
Mantenha 👍/👎 após a implantação. Divergências como agent-arena-business-policy-online=PASS ao lado de user-thumbs=false são candidatas valiosas à próxima fila. A revisão humana decide corrigir política, prompts, dados ou evaluator. Casos aprovados voltam a arena-golden; a próxima candidata repete baseline → candidata → calibração → ativação protegida.
As regras do workshop amostram 100% dos traces elegíveis para fins didáticos. Em produção, a amostragem deve refletir tráfego, custo, latência, risco e cobertura de incidentes.
Evidências de conclusão
- O trace raiz ainda mostra
sql-execution-success=truee Booleanuser-thumbs=false. - A tarefa
production-investigation-<session>está concluída com correção verificada eapproved-for-golden=true. - Os três itens dourados têm proveniência genuína
production-feedback; você distingue a pergunta real das duas paráfrases. - Baseline e candidata usaram o mesmo dataset, modelo e prompt; a candidata corrigiu os três itens sem regressão existente.
- A calibração produziu
FAIL,PASSeNOT_APPLICABLEsobbusiness-policy-adherence. - A regra de observação ficou desativada na calibração e só foi ativada após os portões.
- Traces de cliente ativo, receita e conversão têm
agent-arena-business-policy-online=PASS; a contagem de produtos temagent-arena-business-policy-online=NOT_APPLICABLE. - Você explica por que avaliação online e feedback continuam melhorando um ao outro após a implantação.