Construa um Agente Actor-Critic para Inferência Causal

Construa um Agente Actor-Critic para Inferência Causal

Inferência causal é o último lugar onde a maioria dos times confia em um LLM. Um confounder que você não controlou e seu “efeito” vira ruído — e, diferente de um typo no código, um estimand ruim não quebra nada. Ele engana o negócio silenciosamente. É exatamente por isso que o release desta semana da Netflix merece sua atenção: o oci-agent (Netflix-Skunkworks/oci-agent) é uma implementação de referência de um fluxo de trabalho agêntico para inferência causal observacional (OCI). Um agente actor preenche notebooks Jupyter baseados em templates a partir de um plano de análise escrito por humanos e os executa; um agente critic audita os resultados e exige revisões; o loop se repete até que o relatório seja aprovado. Não é algo pronto para produção, mas é o blueprint público mais claro até agora para automatizar o trabalho braçal da análise causal sem abrir mão do julgamento humano.

Por que esse padrão importa

A Netflix enquadra a OCI como emulação de ensaio-alvo (target trial emulation) — encontrar o teste A/B ótimo para a sua pergunta usando dados observacionais. O case study deles deixa isso claro: ao estimar o impacto na retenção de um novo tipo de entretenimento, o fluxo produziu uma estimativa de efeito apenas 25% de um baseline ingênuo de regressão linear com Claude, porque o critic sinalizou o viés de early adopters e um teste placebo que falhou antes que alguém publicasse o número. O scaffolding é o produto.

Design central: o loop actor-critic

O pipeline é um único loop com artefatos inspecionáveis a cada passo:

plan → actor.draft → spec → nb_runner → results.json → critic.evaluate → oci_report.md
 ↑                                                    │
 └────── actor.revise ◀────────── critique.json ◀──────┘

Três componentes, todos dentro de oci_agent/:

  • Actor (actor.py) — traduz um plano de análise em markdown para um spec YAML; em iterações posteriores, aplica as mudanças sugeridas pelo critic.
  • Runner (nb_runner.py) — injeta os parâmetros do spec na célula de configuração de um notebook, executa o notebook e depois anexa uma célula de serialização de resultados.
  • Critic (critic.py) — revisa o results.json contra a skill writing-reports e emite um veredito em três níveis (fully_satisfactory / satisfactory_with_caveats / not_satisfactory) além de mudanças concretas no spec.

Duas escolhas de design fazem isso funcionar. Primeira, notebooks baseados em templates: o agente opera dentro de uma estrutura de análise fixa e revisada, então as boas práticas são o padrão e não uma esperança. Segunda, skills como markdown: writing-specs, changing-notebooks, running-notebooks, writing-reports, suggesting-remedies são carregadas em runtime — troque o texto, mude o comportamento do agente, sem alterar código.

Rode você mesmo

Python 3.10+ necessário. Atenção ao numpy<2 fixado: a dependência transitiva shap do econml referencia o np.bool8, removido no numpy ≥ 2.0.

python3 -m venv .venv && source .venv/bin/activate
pip install -e .
export ANTHROPIC_API_KEY=sk-ant-...   # actor/critic chamam a API Claude Messages

# Gere um dataset sintético no formato ACIC para um smoke test rápido
python evals/generate_synthetic_acic.py

# Conduza o loop um passo de cada vez
oci-agent draft --plan plans/tryitout.md --specs-dir specs
oci-agent run specs/tryitout/iter_01.yaml --output-dir output/tryitout
oci-agent evaluate output/tryitout --plan plans/tryitout.md
oci-agent revise output/tryitout --specs-dir specs/tryitout

# Ou rode o loop completo em um único comando
oci-agent loop specs/tryitout/iter_01.yaml --output-dir output/tryitout \
  --specs-dir specs/tryitout --plan plans/tryitout.md --iterations 1

A CLI auto-incrementa os diretórios de saída (iter_02/, iter_03/, …) e os nomes dos arquivos de spec, então você nunca precisa controlar contadores de iteração manualmente. Precisa de um proxy em vez da API pública da Anthropic? Configure ANTHROPIC_BASE_URL.

O loop realmente ajuda? Os números

Na bateria de benchmarks ACIC 2016 (77 processos geradores de dados), o fluxo entrega cobertura sólida com viés baixo:

Estimand   |Bias|   RMSE   Cov95
ATE        0.015   0.173   84.8%
ATT        0.017   0.083   96.1%
ATO        0.014   0.066   97.0%

O ATT fica em 5º lugar entre 16 em viés no benchmark black-box oficial do ACIC. A ablação comparativa é o destaque: em 10 datasets do ACIC, o loop actor-critic completo entrega ATT com |erro| médio = 0.054 e cobre o valor verdadeiro em 9/10 execuções — enquanto o mesmo modelo (Sonnet 4.6) recebendo apenas o plano e uma amostra de 5 linhas dos dados, sem ferramentas ou skills, tem |erro| médio = 2.572 (~48× pior) e cobre o valor verdadeiro em apenas 3/10. Os vereditos determinísticos do critic também concordam com um juiz LLM independente em 666/693 registros (96%).

Lições práticas

  • Mantenha o humano no topo. Você formula a pergunta e aprova os resultados; o agente cuida da análise de sensibilidade, do rastreamento de iterações e da escrita do relatório — exatamente o trabalho que consome horas do analista.
  • Audite artefatos, não vibes. Cada iteração deixa spec.yaml, results.json, o notebook executado, critique.json e oci_report.md. Integre esses artefatos ao seu fluxo de revisão e você ganha transparência de processo, não apenas output.
  • Não coloque em produção como está. Este é um release de referência do Skunkworks: sem aceitação de PRs, sem compromisso de manutenção. Modele seu próprio fluxo de trabalho a partir dele — o esqueleto actor-critic transita bem para outros domínios de análise, já que as skills são apenas markdown.

Recursos

Notícias Relacionadas