Agent ArenaClickHouse Workshops

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:

  1. o feedback revela uma lacuna no evaluator online atual;
  2. uma pessoa investiga e aprova a correção;
  3. o incidente revisado amplia o dataset dourado;
  4. versões baseline e candidata executam no mesmo dataset ampliado;
  5. um evaluator geral é calibrado offline antes de ser ativado online; e
  6. 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.json

Espere três linhas prepared prod-active-* seguidas de:

promoted 3 question(s) into the 'arena-golden' dataset

Em 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-experiments

Espere 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-adherence

O 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-adherence

Registre o agregado e exija:

  • IDs e contagens de itens idênticos;
  • os três prod-active-* passam de correctness=0 em policy-v1 a correctness=1 em policy-v2;
  • nenhum item anterior sofre regressão de correctness=1 para correctness=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çãoExecução/itembusiness-policy-adherence exigido
SQL desatualizado de cliente ativobaseline prod-active-001FAIL
SQL corrigido de cliente ativocandidata prod-active-001PASS
política de receitacandidata q005PASS
política de conversão view-to-purchasecandidata q018PASS
contagem simples de clientescandidata q001NOT_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-online

Espere 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 8100

No 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=PASS

A 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
fi

Nã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_APPLICABLE

O 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=true e Boolean user-thumbs=false.
  • A tarefa production-investigation-<session> está concluída com correção verificada e approved-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, PASS e NOT_APPLICABLE sob business-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 tem agent-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.

Nesta página

Acompanhar seu progresso?

Opcional. Enviaremos um link por e-mail para confirmar seu endereço; o progresso será registrado depois que você o abrir.

Use seu e-mail corporativo, não um endereço pessoal.

O acompanhamento do progresso também exige a aceitação dos Termos de Serviço atuais nas Configurações de privacidade.

PT