PRD-003 — Knowledge Router + BM25
Motor de Recuperação Híbrida de Alta Performance
Versão: 1.0 Status: Proposta para desenvolvimento Dependências: ADR-000, PRD-001, PRD-002 Próximo documento: PRD-004 — Capability Registry
1. Objetivo
Implementar o Knowledge Router, responsável por encontrar, classificar e entregar ao agente o menor conjunto possível de informações relevantes da HAG.
O objetivo principal é:
maximizar precisão e minimizar latência, tokens e chamadas ao LLM.
A arquitetura não será um RAG convencional.
Será uma Retrieval Cascade híbrida, na qual mecanismos baratos e determinísticos são executados antes dos mecanismos semanticamente mais caros.
2. Objetivo de performance
Metas iniciais:
| Operação | Meta |
|---|---|
| Cache hit | < 20 ms |
| Exact/Semantic ID | < 30 ms |
| Keyword | < 40 ms |
| BM25 | < 80 ms |
| Hybrid retrieval | < 150 ms |
| Retrieval + reranking | < 300 ms |
| Retrieval + LLM | variável |
| Consulta completa simples | idealmente < 1 s |
Os números são SLOs iniciais, não garantias.
A equipe deverá medi-los com dados reais antes de estabelecer os valores definitivos.
3. Princípio central
Não fazer:
Pergunta
↓
Vector Search
↓
LLM
Fazer:
Pergunta
↓
Cache?
↓
Exact Match?
↓
Semantic ID?
↓
Keyword?
↓
BM25?
↓
Wikilinks?
↓
Vectorize?
↓
Reranking
↓
LLM somente se necessário
4. Retrieval Cascade
A arquitetura:
QUERY
│
▼
Normalizer
│
▼
Query Analyzer
│
▼
┌──── Cache ─────┐
│ HIT │
▼ │
Response │
│ MISS
▼
Exact Resolver
│
▼
Semantic Resolver
│
▼
Keyword Index
│
▼
BM25
│
▼
Graph Expansion
│
▼
Vectorize
│
▼
Rank Fusion
│
▼
Context Selection
5. Query Normalizer
Antes da pesquisa:
" O que é APR ? "
será normalizado para uma representação canônica.
Operações:
- lowercase;
- remoção de espaços redundantes;
- normalização Unicode;
- tratamento de pontuação;
- normalização de acentos;
- tokenização;
- identificação de termos especiais.
Não remover informações que sejam semanticamente importantes.
6. Query Analyzer
O sistema deverá classificar a consulta.
Exemplo:
"Explique APR"
pode produzir:
{
"type": "knowledge",
"terms": ["apr"],
"shortQuery": true
}
Enquanto:
"Crie uma nova permissão para João"
será identificada como potencialmente operacional.
{
"type": "agentic",
"potentialAction": true
}
Essa distinção será posteriormente integrada ao Intent Engine.
7. Exact Match
Primeiro mecanismo.
Exemplo:
query = "workPermit.validity"
Se existir:
semanticId = workPermit.validity
não há necessidade de executar uma busca ampla.
Resultado imediato.
8. Keyword Index
A infraestrutura existente de palavras-chave será preservada.
O índice deverá relacionar:
keyword
│
├── document
├── section
├── semanticId
├── entity
├── component
└── wikilink
Exemplo:
"validade"
│
├── workPermit.validity
├── certificate.validity
├── equipment.validity
└── training.validity
9. BM25
BM25 será introduzido como o principal mecanismo lexical de ranking.
A fórmula conceitual:
f(q,d) * (k1 + 1)
score = Σ ─────────────────────────
f(q,d) + k1(...)
A implementação não deverá ser construída do zero se houver uma biblioteca TypeScript madura e adequada.
A equipe deverá avaliar:
- implementação própria;
- biblioteca BM25;
- índice persistido;
- índice em memória;
- WASM;
- serviço externo.
A decisão deverá ser registrada no ADR correspondente.
10. Por que BM25 é importante
Vector Search responde muito bem a:
"Como faço para renovar uma permissão vencida?"
mesmo que as palavras sejam diferentes.
Mas BM25 é excelente quando o usuário utiliza exatamente a terminologia do sistema:
"permissão de trabalho"
"APR"
"PGR"
"validade"
"componente"
"certificado"
Em sistemas empresariais complexos, a terminologia exata é extremamente importante.
Por isso:
BM25 + Vectorize, e não BM25 versus Vectorize.
11. Campos ponderados
Nem todo texto deverá possuir o mesmo peso.
Exemplo:
title × 3.0
semanticId × 5.0
heading × 2.5
keywords × 3.0
description × 1.5
body × 1.0
wikilinks × 2.0
Os pesos deverão ser configuráveis.
12. Metadata Boost
Contexto da aplicação deverá influenciar o ranking.
Se:
page = workPermit
tab = components
focus = workPermit.components
documentos associados a esses IDs receberão boost.
Exemplo:
base BM25 = 0.62
context boost = +0.30
final = 0.92
13. Semantic ID como chave primária de relevância
Uma das principais decisões arquiteturais:
Semantic IDs deverão ser utilizados como ponte entre aplicação, conhecimento e capacidades.
Exemplo:
workPermit.components.equipment.validity
poderá existir simultaneamente em:
React
│
HAG
│
BM25
│
Vectorize
│
Capability Registry
Isso reduz drasticamente a dependência de inferência do LLM.
14. Wikilinks como Knowledge Graph
Os Wikilinks existentes serão utilizados como relacionamentos explícitos.
Exemplo:
[[workPermit]]
[[workPermit.components]]
[[equipment]]
[[equipment.validity]]
Se o usuário estiver em:
workPermit.components
o router poderá expandir:
current node
│
├── parent
├── children
├── siblings
└── related
15. Graph Expansion
A expansão deverá ser limitada.
Não fazer:
node
↓
todos os descendentes
↓
todos os vizinhos
↓
todo o grafo
Fazer:
node
↓
top N relevant neighbors
com profundidade configurável.
Inicialmente:
depth = 1
maxNodes = 10
16. Vectorize
Vectorize será utilizado quando:
- BM25 tiver baixa confiança;
- a pergunta usar linguagem diferente da documentação;
- houver necessidade de busca conceitual;
- não existir correspondência lexical suficiente;
- houver ambiguidade semântica.
Exemplo:
"Como regularizo uma autorização que já venceu?"
poderá encontrar:
"Procedimento para renovação de autorização expirada"
mesmo com pouca correspondência textual.
17. Vectorize não será primeira escolha
Isso é importante para performance.
Não fazer:
100% das queries → embeddings
Fazer:
100%
│
├── cache
├── exact
├── keyword
└── BM25
│
└── baixa confiança
↓
Vectorize
18. Hybrid Rank Fusion
Resultados de diferentes mecanismos serão combinados.
Fontes:
Exact
BM25
Keyword
Wikilink
Vector
Context
Cada resultado possuirá scores independentes.
Exemplo:
interface RetrievalResult {
documentId: string;
scores: {
exact?: number;
keyword?: number;
bm25?: number;
graph?: number;
vector?: number;
context?: number;
};
finalScore: number;
}
19. Score final
A primeira versão poderá utilizar:
finalScore =
exactScore
+ bm25Score
+ keywordScore
+ graphScore
+ vectorScore
+ contextScore
com pesos normalizados.
Os pesos serão posteriormente ajustados por avaliação real.
Não assumir que os pesos inicialmente escolhidos serão os definitivos.
20. Confidence Threshold
O router deverá determinar:
HIGH
MEDIUM
LOW
Exemplo:
score >= 0.85 → HIGH
0.60–0.85 → MEDIUM
< 0.60 → LOW
Esses valores são apenas iniciais.
21. Retrieval Budget
Cada consulta deverá possuir um orçamento.
Exemplo:
interface RetrievalBudget {
maxDocuments: number;
maxGraphNodes: number;
maxVectorResults: number;
maxLatencyMs: number;
}
Isso impede que uma consulta problemática consuma recursos excessivos.
22. Top-K adaptativo
Não retornar sempre 20 documentos.
Exemplo:
HIGH confidence
→ 3 documentos
MEDIUM
→ 8 documentos
LOW
→ 15 documentos + semantic search
O objetivo é:
entregar ao LLM apenas o conhecimento necessário.
23. Contextual Filtering
Antes do ranking, aplicar filtros.
Exemplo:
tenant
application
version
module
entity
page
Isso evita que o ranking tenha que escolher entre documentos que nunca deveriam ter participado da busca.
24. Knowledge Version
Todas as consultas deverão identificar:
knowledgeVersion
O router nunca deverá misturar:
Knowledge v152
+
Knowledge v153
a menos que explicitamente configurado para isso.
25. R2
R2 será utilizado como armazenamento de objetos para:
- Markdown;
- knowledge packages;
- índices;
- artefatos;
- snapshots;
- versões.
Não deverá ser utilizado como mecanismo primário de pesquisa de baixa latência.
26. D1
D1 armazenará metadados estruturados.
Exemplo:
knowledge_documents
knowledge_sections
knowledge_keywords
knowledge_links
knowledge_entities
knowledge_versions
D1 será utilizado para resolver relações e metadata.
27. KV
KV será usado para dados altamente acessados e relativamente estáveis.
Exemplos:
knowledge:active-version
knowledge:semantic:workPermit.components
knowledge:keyword:apr
knowledge:route:/work-permits/*
Não utilizar KV como substituto de D1 para relacionamentos complexos.
28. BM25 Index
O índice BM25 deverá ser considerado um artefato compilado, e não necessariamente recalculado durante cada consulta.
Pipeline:
Markdown
↓
Tokenizer
↓
Term frequencies
↓
Document frequencies
↓
BM25 Index
↓
Knowledge Package
↓
R2
Durante runtime:
Query
↓
BM25 Index
↓
Results
29. Incremental Indexing
Uma mudança em um único Markdown não deverá exigir recompilação completa.
Exemplo:
commit
│
├── changed: workPermit.md
└── unchanged: 12,481 docs
Idealmente:
update only affected documents
A estratégia exata será definida no Knowledge Compiler.
30. Cache de consultas
Perguntas repetidas deverão ser cacheadas.
Chave conceitual:
hash(
normalizedQuery
+
relevantContext
+
knowledgeVersion
)
Exemplo:
cache:
knowledge-query:{hash}
31. Cache não pode ignorar contexto
Não fazer:
"Explique isso"
→ cache global
Porque:
"isso"
depende do contexto.
A chave deverá incorporar os elementos semânticos relevantes:
query
+
pageId
+
tabId
+
focusId
+
selectionType
+
knowledgeVersion
32. Context-aware Retrieval
O pipeline final será:
User Query
│
▼
Context Engine
│
▼
Query Normalization
│
▼
Reference Resolution
│
▼
Context Filtering
│
▼
Exact Match
│
▼
Keyword
│
▼
BM25
│
▼
Wikilink Expansion
│
▼
Confidence?
│
├── HIGH ─────► Return
│
└── LOW/MEDIUM
│
▼
Vectorize
│
▼
Rank Fusion
│
▼
Top-K
33. Retrieval sem LLM
Um dos objetivos é permitir:
perguntas que possam ser respondidas sem LLM.
Exemplo:
"Qual a validade padrão da APR?"
Se existir uma resposta estruturada na HAG:
APR.defaultValidity = 30 days
o sistema poderá retornar diretamente.
O LLM será usado para explicar, quando necessário, e não para simplesmente recuperar um valor conhecido.
34. Retrieval + LLM
Quando for necessária uma resposta narrativa:
Query
↓
Hybrid Retrieval
↓
3–8 knowledge chunks
↓
LLM
Nunca:
Query
↓
50.000 Markdown files
↓
LLM
35. Context Builder
O Context Builder produzirá um pacote mínimo.
interface AgentKnowledgeContext {
query: string;
uiContext: AgentContext;
references: KnowledgeReference[];
relevantChunks: KnowledgeChunk[];
confidence: number;
knowledgeVersion: string;
}
36. Proteção contra prompt injection
Markdown não deve ser considerado automaticamente uma instrução para o agente.
Um documento poderá conter:
"Ignore todas as regras anteriores..."
Isso deve ser tratado como conteúdo, não como comando.
A separação deverá ser:
SYSTEM POLICY
≠
KNOWLEDGE CONTENT
≠
USER INPUT
37. Knowledge Trust Levels
Documentos poderão receber níveis:
official
verified
generated
draft
deprecated
O ranking deverá privilegiar conteúdo:
official > verified > generated > draft
Documentação obsoleta deverá ser penalizada ou excluída.
38. Temporal Awareness
O Knowledge Router deverá conhecer:
createdAt
updatedAt
validFrom
validUntil
version
status
Isso é particularmente importante para regras de Segurança e Saúde do Trabalho.
Uma regra antiga não deve vencer uma versão atual simplesmente porque possui maior similaridade textual.
39. Explainability
O sistema deverá poder informar:
"Encontrei esta resposta na documentação de Permissão de Trabalho, seção Componentes."
Internamente:
retrievalTrace:
exact: false
bm25: 0.91
graph: 0.73
vector: 0.81
contextBoost: 0.95
Isso será útil para debugging e auditoria.
40. Métricas
O router deverá medir:
retrieval_latency_ms
bm25_latency_ms
vector_latency_ms
reranking_latency_ms
cache_hit_rate
exact_match_rate
bm25_success_rate
vector_fallback_rate
top1_accuracy
top3_accuracy
topK_recall
41. Test Dataset
Antes da produção, criar um conjunto de perguntas reais.
Exemplo:
Q001:
"O que é APR?"
Q002:
"Explique este campo."
Q003:
"Como renovar uma permissão?"
Q004:
"Qual o prazo desse certificado?"
Q005:
"Onde encontro os componentes?"
Cada pergunta deverá possuir uma resposta/referência esperada.
Isso permitirá comparar versões do algoritmo.
42. Teste de regressão
Quando o índice mudar:
Knowledge v153
executar automaticamente:
Test Set
↓
Retrieval
↓
Metrics
↓
Compare v152 vs v153
Se a qualidade cair significativamente:
DEPLOY = BLOCKED
43. Integração com o futuro Agentic Flow
O Knowledge Router não precisa saber executar ações.
Ele apenas responde:
"What does the user need to know?"
O Intent Engine responderá:
"What does the user want to do?"
Essa separação é fundamental.
Knowledge Router
│
└── KNOWLEDGE
Intent Engine
│
└── INTENTION
44. Critérios de aceite
Evidência de implementação e produção — 2026-09-05
O KnowledgeRouter compila índice BM25/keyword reproduzível por tenant e release, combina exact, keyword, BM25, semantic IDs, wikilinks e contexto semântico, e expõe trace com top-K adaptativo, cache e orçamento de retrieval. O conjunto de contexto é limitado e remove ou encapsula instruções de prompt como evidência não executável; validade, tenant, versão e bindings de capability são filtrados antes da resposta. Indexação, validação de bindings, avaliação de retrieval e rotas de Knowledge/Trust possuem 40 testes focados aprovados em 2026-09-04.
Em 2026-09-05, router, avaliação, binding, indexação e rota passaram com 37 testes em 5 arquivos. O canário autenticado de produção confirmou bundle ACTIVE, índice READY, 2 documentos, 6 chunks e 6 vetores observados, recibo de mutação vetorial, retrieval do documento esperado, integridade verificada, isolamento e ausência de exposição de segredos; a limpeza PostgreSQL encerrou com remainingRows: 0. A avaliação de carga contra corpus produtivo continua melhoria operacional, sem invalidar os contratos e o vertical de indexação certificados.
- BM25 implementado;
- índice BM25 compilável;
- keyword index existente integrado;
- Wikilinks utilizados no ranking;
- Semantic IDs integrados;
- Vectorize integrado como fallback;
- ranking híbrido implementado;
- contextual boost implementado;
- confidence score implementado;
- top-K adaptativo implementado;
- cache contextual implementado;
- knowledge version obrigatória;
- tenant isolation implementada;
- retrieval trace disponível;
- métricas de latência disponíveis;
- conjunto inicial de avaliação criado;
- nenhum documento desnecessário enviado ao LLM;
- Fast Path implementado;
- Slow Path implementado.
45. Resultado
Depois deste PRD, o agente terá uma capacidade de pesquisa muito diferente de um RAG tradicional.
Em vez de:
Pergunta
↓
Embedding
↓
Vector DB
↓
LLM
teremos:
PERGUNTA
│
CONTEXTO
│
▼
┌───────────────┐
│ Fast Retrieval│
└───────┬───────┘
│
┌──────────┼──────────┐
▼ ▼ ▼
Exact Keyword BM25
│ │ │
└──────────┼──────────┘
▼
Wikilinks
│
▼
Context Boost
│
confidence?
/ \
HIGH LOW
│ │
│ Vectorize
│ │
└─────┬──────┘
▼
Rank Fusion
│
▼
Top-K
│
▼
LLM
E existe uma consequência arquitetural particularmente importante:
A HAG existente deixa de ser apenas documentação. Ela passa a ser o sistema de conhecimento operacional do agente.
Os Semantic IDs, por sua vez, tornam-se a ponte entre:
Documentação
↕
HAG
↕
React UI
↕
Capabilities
↕
APIs
Essa será provavelmente uma das decisões mais valiosas de toda a plataforma.
PRD-004 — Capability Registry
O próximo documento muda de natureza.
Até aqui estamos ensinando o agente a saber.
No PRD-004 começaremos a ensinar o agente a fazer.
O Capability Registry será o catálogo formal de todas as operações que o agente poderá executar, com:
- nome semântico;
- descrição;
- parâmetros;
- JSON Schema;
- API correspondente;
- método HTTP;
- permissões necessárias;
- nível de risco;
- necessidade de confirmação;
- pré-condições;
- pós-condições;
- regras de idempotência;
- entidades envolvidas;
- relação com os Semantic IDs da UI e da HAG.
Por exemplo:
workPermit.updateValidity
│
├── Input Schema
├── Permission
├── Risk = MEDIUM
├── Confirmation = conditional
├── POST/PUT API
├── Validation
└── Verification
Esse catálogo será a ponte entre a inteligência do agente e a capacidade real de operar o sistema.