14-01-02 — Orchestrator-Workers e Evaluator-Optimizer
TL;DR
Orchestrator-Workers: um LLM "maestro" decompõe tarefas e delega para LLMs especializados ("workers"), depois consolida. Evaluator-Optimizer: um LLM gera, outro avalia e solicita revisão em loop até atingir qualidade-alvo. Ambos são padrões multi-agente que aumentam qualidade a custo de latência e tokens.
Orchestrator-Workers
O orchestrator recebe o objetivo de alto nível, decompõe em subtarefas, e delega para workers especializados. Cada worker opera no seu domínio e retorna resultado ao orchestrator, que sintetiza a resposta final.
Quando usar:
- Tarefas que requerem expertise em múltiplos domínios simultaneamente
- Quando workers especializados têm prompts/contextos muito diferentes entre si
- Relatórios complexos que combinam análise, pesquisa e redação
Implementação com Semantic Kernel:
// Orchestrator define o plano
var orchestratorPrompt = """
Você é um orquestrador. Dado o objetivo abaixo, crie um plano de subtarefas.
Retorne JSON com array de tasks: [{worker: string, task: string, dependsOn: string[]}]
Objetivo: {{$goal}}
""";
// Workers especializados
var researchAgent = kernel.CreateFunctionFromPrompt(
"Você é especialista em pesquisa. Encontre informações sobre: {{$task}}",
functionName: "ResearchWorker"
);
var analysisAgent = kernel.CreateFunctionFromPrompt(
"Você é analista financeiro. Analise os dados: {{$task}}\nDados: {{$researchResult}}",
functionName: "AnalysisWorker"
);
// O orchestrator chama os workers na ordem correta
// baseado nas dependências declaradas no plano
Evaluator-Optimizer
Loop de geração e avaliação. O Generator produz uma resposta. O Evaluator (outro LLM ou função determinística) verifica qualidade contra critérios definidos. Se não atende, o Generator recebe feedback e tenta novamente.
Critérios de avaliação típicos:
- Groundedness: resposta baseada apenas no contexto fornecido?
- Completeness: todos os requisitos atendidos?
- Format compliance: saída no formato exigido (JSON, Markdown, etc)?
- Safety: conteúdo seguro e appropriado?
- Length: dentro do limite especificado?
async def evaluator_optimizer(task: str, criteria: list[str], max_iterations: int = 3) -> str:
draft = await generate(task)
for i in range(max_iterations):
evaluation = await evaluate(draft, criteria)
if evaluation["passed"]:
return draft
feedback = evaluation["feedback"]
print(f"Iteração {i+1}: {feedback}")
# Regenera com feedback
draft = await generate(
f"{task}\n\nRascunho anterior:\n{draft}\n\nFeedback para melhorar:\n{feedback}"
)
# Retorna melhor versão após max_iterations
return draft
Combinando: Orchestrator com Evaluator por Worker
Padrão avançado: cada worker tem seu próprio evaluator, garantindo qualidade de cada subtarefa antes de retornar ao orchestrator. O orchestrator recebe apenas resultados validados.
| Pattern | Latência | Custo | Qualidade | Caso de uso |
|---|---|---|---|---|
| Single LLM | Baixa | Baixo | Básica | Chat simples |
| Prompt Chaining | Média | Médio | Boa | Workflows sequenciais |
| Orchestrator-Workers | Média | Alto | Muito boa | Tarefas multi-domínio |
| Evaluator-Optimizer | Alta | Alto | Excelente | Conteúdo crítico |