Inteligência artificial, sem ruído.
Tutoriais5 min

Dispatcher: como substituir mega-prompts de RAG por prompts modulares e auditáveis

Substitua mega-prompts de RAG pelo padrão dispatcher: um BASE fixo + fragmentos por tipo de resposta. Com evidência por campo, few-shot dinâmico e auditoria completa.

Dispatcher: como substituir mega-prompts de RAG por prompts modulares e auditáveis

Todo sistema RAG começa simples: um prompt de sistema, alguns documentos recuperados e uma chamada ao modelo. Mas conforme os casos de uso crescem — extrair valores monetários, datas, listas, tabelas, booleanos — o prompt de sistema vira uma monstruosidade. Cada novo tipo de resposta ganha uma cláusula condicional (“se a resposta for uma data, use ISO 8601; se for um valor, use ISO 4217…”), e dois meses depois ninguém lembra qual cláusula resolve qual caso.

Kezhan Shi, na série Enterprise Document Intelligence do Towards Data Science, propõe uma alternativa elegante: o padrão dispatcher para montagem de prompts. Em vez de um mega-prompt monolítico, você mantém um BASE fixo com regras universais (citar fontes, tipar respostas, falhar honestamente) e um conjunto de fragmentos que são acionados conforme o tipo de pergunta.

Como funciona o dispatcher

O coração do sistema é um objeto ParsedQuestion — uma pergunta do usuário já classificada por tipo e forma de resposta. Esse objeto carrega:

  • expected_answer_shape: o formato esperado (data, valor monetário, lista, tabela, boolean)
  • generation brief: restrições de formato e regras de desambiguação
  • keywords: termos extraídos da pergunta original
  • structural_hints: pistas como “na página 5” ou “páginas 3 a 7”

Quando a pergunta chega, o dispatcher consulta um ANSWER_REGISTRY que mapeia cada expected_answer_shape para um schema Pydantic e para os fragmentos de prompt relevantes. A composição é determinística: BASE + fragmentos da vez, sem cláusulas condicionais que crescem indefinidamente. Adicionar um novo formato de resposta significa adicionar um fragmento — e nada mais.

Prompt de sistema: BASE + fragmentos

O BASE é agnóstico ao formato e codifica o contrato que vale para toda chamada:

  • Toda afirmação precisa de uma linha de origem (GLOBAL_LINE)
  • Se a informação não estiver nos documentos, retorne answer_found=False
  • Nunca invente dados — o modelo não está “consultando” nada, está prevendo tokens

Os fragmentos são específicos por formato: um para valores monetários (ISO 4217), outro para datas (ISO 8601), outro para listas (“retorne um AnswerItem por elemento”). O dispatcher monta apenas o que a pergunta pede. O schema Pydantic garante a estrutura; o fragmento orienta a estratégia de extração.

Prompt do usuário: pergunta + palavras-chave + passagens

O prompt do usuário é uma casca fina: a pergunta original, as palavras-chave extraídas (para o modelo sinalizar quais apareceram nas passagens) e as linhas dos documentos recuperados, com colunas explicitamente rotuladas (GLOBAL_LINE | page | line_in_page | text). O cabeçalho das colunas aparece duas vezes — no BASE e no prompt do usuário — porque isso resolveu um bug recorrente em que o modelo confundia número de linha global com número de linha por página.

Evidência por campo: FieldExtraction

Quando a resposta tem múltiplos campos tipados (ex: extrair nome, email, telefone e cargo de um currículo), o padrão escala com FieldExtraction[T]: cada campo carrega seu próprio valor tipado mais a página, linha inicial e linha final de onde foi lido. Em vez de um bloco de evidências genérico no topo da resposta, cada campo responde individualmente: “o email veio da linha 47, página 2”.

O verificador pós-LLM percorre o schema, confere se cada citação realmente existe no documento original e sinaliza campos com citações alucinadas. É barato e resolve o medo número um de empresas que adotam RAG: o modelo inventar uma justificativa que parece plausível mas não existe.

Few-shot dinâmico: exemplos que chegam na hora

Um banco de exemplos validados (pergunta + resposta JSON correta) é indexado com o mesmo embedding do corpus. Quando chega uma pergunta nova, o sistema recupera os 3-5 exemplos mais próximos e os insere no prompt como worked examples. Se um exemplo anterior já resolveu a normalização de “$” para “USD”, o modelo copia o padrão por demonstração, sem precisar rederivar de um parágrafo de regras que ele acabou de ignorar.

O custo é real — cada exemplo gasta tokens —, então o mecanismo é condicional: só é ativado quando o banco existe, quando a pergunta é similar a exemplos do banco e quando os dados do banco não são sensíveis.

O que levar para o seu projeto

  • Mega-prompts não escalam. Separe regras universais (BASE) de regras por formato (fragmentos).
  • Rotule as colunas do prompt do usuário. O modelo confunde número de linha global com número de linha por página se você não disser qual é qual — e isso acontece com frequência.
  • Evidência por campo, não por resposta. Quando um campo está errado, você quer saber exatamente qual linha o modelo leu — não um bloco genérico de “páginas consultadas”.
  • Guarde o payload bruto da API.output_text não basta. Salvar o JSON completo da resposta (tokens, modelo, request ID, system fingerprint) custa alguns KB por chamada e salva horas de investigação forense depois.
  • Few-shot dinâmico resolve casos difíceis. Um banco de exemplos validados, indexado com embeddings e puxado por similaridade, corrige erros de formatação que regras textuais não conseguem evitar.

O código completo com notebooks executáveis está disponível no GitHub do projeto doc-intel. O dispatcher é parte de uma série maior sobre os quatro blocos de um sistema RAG empresarial: parsing de documentos, parsing de perguntas, recuperação e geração — cada um com contrato, auditoria e verificação.


Descubra mais sobre noticiAI

Assine para receber nossas notícias mais recentes por e-mail.

R
Sobre o autorRedação Noticiai

Equipe editorial dedicada a explicar inteligência artificial com clareza, independência e contexto.