Sistema especialista para análise automatizada de Termos de Referência (TR) de licitações públicas usando Inteligência Artificial.
- Upload de documentos PDF, DOCX e ODT
- Parsing automático com detecção de itens numerados, tabelas e anexos
- OCR para PDFs escaneados (Tesseract)
- Múltiplos Agentes Inteligentes Especializados (Multi-Agent System):
- ⚖️ Agente Jurídico: Auditagem estrita sob a Lei 14.133/21, Lei 13.303/16, TCU, AGU e CGU
- 🛠️ Agente Técnico: Especificações técnicas, quantitativos, amostragem e SLAs
- ✍️ Agente de Redação: Clareza textual, remoção de ambiguidade e ampla competitividade
- 📐 Agente Estrutural: Organização e checklist dos 10 elementos do Art. 6º, XXIII
- 👑 Orquestrador Multi-Agente: Execução concorrente assíncrona (
asyncio.gather) + deduplicação de achados
- RAG v1.0 & Corpus Jurídico Expandido:
- Embeddings semânticos com
get_embeddings_provider()(Gemini / Ollamabge-m3) - Jurisprudência do TCU (Súmula 247, Súmula 272, Acórdão 1214/2013) e RILC CODEBA-2023 (315 chunks no índice FTS5/Semântico)
- Busca sem acento (FTS5
remove_diacritics 2): consultas com/sem acentuação retornam os mesmos resultados - Retrieval híbrido RRF: combina busca semântica + textual com fusão por rank recíproco
- Comparador Visual de Versões de TR (
/comparacao/versoes): Alinhamento por item com identificação dealterado,adicionadoeremovido
- Embeddings semânticos com
- Correções no formato DE → PARA com fundamentação legal
- Fluxo SEI Otimizado (Cópia em 1-clique):
- 📋 Copiar Texto Corrigido (PARA): Copia o trecho pronto para colar na cláusula do SEI
- 📄 Copiar Item Inteiro: Copia a cláusula inteira com as correções aplicadas
- 📝 Copiar Parecer & Justificativa: Copia o fundamento legal para o despacho/parecer do SEI
- Relatório com pontuação (0-10), nível de risco e parecer final
- 3 provedores de IA: Groq (free tier), Google Gemini (free tier), Ollama (local) — com failover automático
- Auditoria TR × Propostas (módulo aditivo de conformidade):
- Moldes de regras configuráveis (RF02): 10 tipos de âncoras (numéricas, por extenso, booleanas, legais, data, percentual, monetária, CNPJ, prazo relativo e CEP) com extração determinística + fallback LLM
- Editor visual de moldes no frontend (
/moldes): cria/edita regras, com Duplicação de Molde em 1-clique e Validação Dry-Run em tempo real - Moldes padrão de seed: TR geral, serviços continuados e obras públicas (
scripts/seed_moldes.py) - Matriz de conformidade (RF03): compara TR vs propostas dos fornecedores com status OK / ATENÇÃO / FALHA
- Notificação de Pendências por E-mail (RF04): Envio automático via SMTP para fornecedores com pendências na matriz
- Copiloto LicitAI (chat consultivo):
- Painel de chat integrado à tela de análise (
/analysis/[id]) com contexto do documento/análise/item selecionado - Respostas sempre ancoradas em fontes citadas (RAG jurídico, análise, correções, itens do documento) ou recusa explícita
- Badges de ancoragem/confiança, provedor e latência; acordeão de fontes; feedback 👍/👎
- API
/api/v1/chat(health, conversas, mensagens, feedback) com validação de tamanho e guards 404/400/422 - Modo demo/teste com provider fake (
CHAT_FORCE_FAKE_PROVIDER=True) — sem chamadas de IA real
- Painel de chat integrado à tela de análise (
| Camada | Tecnologia |
|---|---|
| Frontend | Next.js 14, React, Tailwind CSS 3, TypeScript |
| Backend | FastAPI, Python 3.12, SQLAlchemy (async) |
| Banco | PostgreSQL 16 (pgvector) ou SQLite (aiosqlite nativo) |
| Parser | PyMuPDF, pdfplumber, python-docx, Tesseract OCR, python-magic-bin |
| IA | Groq API, Google Gemini API, Ollama |
| Validação de schema | pglast (parser oficial do PostgreSQL) |
| Deploy | Docker Compose ou Execução Nativa Windows (sem Docker) |
O backend executa na porta 8000 usando o ambiente virtual Python .venv.
# 1. No terminal, navegue para a raiz do projeto:
cd c:\Users\bruno.santos\Downloads\Bruno\Codeba\projetos-tech\licitacao
# 2. Inicie o servidor FastAPI via Uvicorn:
backend\.venv\Scripts\python.exe -m uvicorn app.main:app --reload --app-dir backend --host 127.0.0.1 --port 8000📍 URL do Backend:
http://127.0.0.1:8000
📑 Documentação da API (Swagger):http://127.0.0.1:8000/docs
O frontend executa na porta 3000 usando Node.js.
# 1. Abra um NOVO terminal e entre na pasta do frontend:
cd c:\Users\bruno.santos\Downloads\Bruno\Codeba\projetos-tech\licitacao\frontend
# 2. Inicie o servidor de desenvolvimento do Next.js:
npm run dev🌐 URL da Aplicação Web:
http://localhost:3000
Para conectar o LicitAI diretamente ao editor de textos do SEI:
- Acesse no Chrome/Edge:
chrome://extensionsouedge://extensions. - Ative o Modo do Desenvolvedor no canto superior direito.
- Clique em "Carregar sem compactação" (Load unpacked).
- Selecione a pasta
extension/do projeto (licitacao/extension). - O ícone do LicitAI 🪄 aparecerá na barra do navegador para injeção automática de TRs.
| Provedor | Onde obter | Free Tier |
|---|---|---|
| Groq | console.groq.com | ~30 req/min, Llama 3.3 70B |
| Google Gemini | aistudio.google.com/apikey | Cota diária limitada (429 possível sob uso intenso), Gemini 2.0 Flash |
| Ollama | ollama.com | Ilimitado (local) — qwen3:32b (padrão) ou hermes3 (mais leve, bom em JSON/instruções; ideal p/ TRs sigilosos) |
Se o backend for iniciado várias vezes (ex.: no terminal e em background), podem restar processos uvicorn duplicados disputando a mesma porta. Os sintomas são: porta ocupada, respostas de uma versão antiga do código, ou ChildProcess.kill ao iniciar.
Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -match "uvicorn" }Identifique na saída: ProcessId, a porta (--port 8000, --port 8001) e qual interpretador está em uso (backend\.venv\Scripts\python.exe vs Python\Python312\python.exe).
Para encerrar todos os uvicorn de uma vez:
Get-CimInstance Win32_Process |
Where-Object { $_.CommandLine -match "uvicorn" -and $_.CommandLine -notmatch "Get-CimInstance" } |
ForEach-Object { Stop-Process -Id $_.ProcessId -Force }Para encerrar apenas os processos de uma porta específica (ex.: 8001):
Get-NetTCPConnection -State Listen | Where-Object { $_.LocalPort -eq 8001 } |
ForEach-Object { Stop-Process -Id $_.OwningProcess -Force }Dica: os processos
uvicorncom--reloaddeixam um processo pai (supervisor) e um filho (worker). Ambos são capturados pelo filtro acima.
Get-NetTCPConnection -State Listen | Where-Object { $_.LocalPort -in 8000, 8001 }Sem saída = portas livres. Em seguida, reinicie o backend normalmente (seção Início Rápido).
Para remover o banco de desenvolvimento, arquivos de upload e logs de execução, deixando o projeto como recém-clonado (exceto .env):
# Banco de dados (recriado automaticamente na próxima inicialização)
Remove-Item licitacao.db -Force -ErrorAction SilentlyContinue
Remove-Item e2e-test.db -Force -ErrorAction SilentlyContinue
# Arquivos de upload
Remove-Item backend/uploads\* -Force -Recurse -ErrorAction SilentlyContinue
Remove-Item e2e-uploads -Recurse -Force -ErrorAction SilentlyContinue
# Logs de execução do backend
Remove-Item backend\server_stdout.log, backend\server_stderr.log -Force -ErrorAction SilentlyContinue
Remove-Item backend\test_stdout.log, backend\test_stderr.log -Force -ErrorAction SilentlyContinue
# Diretório de trabalho do SQLite (WAL)
Remove-Item licitacao.db-wal, licitacao.db-shm -Force -ErrorAction SilentlyContinue
Remove-Item e2e-test.db-wal, e2e-test.db-shm -Force -ErrorAction SilentlyContinue
⚠️ Atenção: os comandos acima apagam dados locais de desenvolvimento. Não os execute se quiser preservar documentos enviados ou análises já realizadas.
licitacao/
├── docker-compose.yml # Orquestração
├── .env.example # Template de configuração
├── db/init.sql # Schema do banco (PostgreSQL)
├── memory.md # Memória contínua do projeto (contexto p/ agentes de IA)
├── backend/
│ ├── Dockerfile
│ ├── requirements.txt
│ └── app/
│ ├── main.py # FastAPI + middlewares
│ ├── config.py # Settings (env vars)
│ ├── database.py # SQLAlchemy async
│ ├── models/ # ORM models
│ ├── schemas/ # Pydantic validation
│ ├── api/ # REST endpoints
│ ├── services/
│ │ ├── parser/ # PDF, DOCX, OCR, estruturador
│ │ ├── llm/ # Groq, Gemini, Ollama providers
│ │ ├── analyzer/ # Motor de análise + prompts
│ │ ├── rules/ # Moldes de regras (loader, extractor, fallback LLM)
│ │ └── comparator/ # Comparação TR × Propostas (comparator, matrix)
│ └── utils/ # Segurança, validação de uploads
├── frontend/
│ ├── Dockerfile
│ ├── package.json
│ └── src/
│ ├── app/ # Pages (Dashboard, Upload, Análise, Relatório, Comparações)
│ ├── components/ # Layout (Sidebar, Header)
│ ├── lib/api.ts # Cliente API
│ └── types/ # TypeScript types
└── e2e/ # Testes End-to-End
├── .env.test # Config para testes
├── run_e2e.ps1 # Script automatizado
├── fixtures/ # Documentos de exemplo
├── scripts/ # Scripts auxiliares
└── tests/ # Testes pytest + httpx
- Validação de uploads (allowlist de extensões + magic bytes)
- Renomeação de arquivos para UUID (nunca usa nome original)
- Prevenção de path traversal
- CSP strict + X-Frame-Options DENY
- Rate limiting configurável via env
RATE_LIMIT_MAX(padrão 600 req/min) - CORS com allowlist de origens
- SQL via ORM (sem string concatenation)
- Secrets via variáveis de ambiente (nunca hardcoded)
- XXE prevention no parsing de DOCX
- Portas bind em 127.0.0.1
# 1. Iniciar backend (provedores reais: Gemini/Groq via failover)
# IMPORTANTE: o config.py lê o .env relativo ao CWD — carregue as variáveis da raiz no processo:
$env:LLM_PROVIDER="gemini"; $env:GEMINI_API_KEY="<chave>"; $env:RATE_LIMIT_MAX="6000"
backend\.venv\Scripts\python.exe -m uvicorn app.main:app --app-dir backend --host 127.0.0.1 --port 8000
# 2. Rodar testes (em outro terminal)
$env:E2E_BASE_URL="http://127.0.0.1:8000"; $env:PYTHONPATH="backend"
backend\.venv\Scripts\python.exe -m pytest e2e/tests -v --tb=short- 17 testes cobrindo health check, upload, CRUD, análise e relatório
- Fluxo completo: upload → parsing → análise → relatório
- Testes de borda: extensão inválida, documento não encontrado
- Os testes usam provedores de IA reais (sem mock); exigem chaves de API válidas
- O fixture de análise aguarda até 240s (o LLM real sob cota free tier pode passar de 60s; 4 testes podem estourar o timeout se a cota diária de Gemini/Groq estiver esgotada)
cd backend
.\.venv\Scripts\python.exe -m pytest tests -q- 156 testes cobrindo parser, extractor, retriever, rules/comparador/matriz, multi-agente, schema do banco, chat/Copiloto e demais módulos.
- Testes do Copiloto usam provider fake (determinístico) — nunca chamam Gemini/Groq/Ollama reais nem dependem de
.env.
Sem Docker, o db/init.sql é validado contra a gramática oficial do PostgreSQL via pglast (libpg_query) em tests/test_init_sql.py (16 testes):
cd backend
.\.venv\Scripts\python.exe -m pytest tests\test_init_sql.py -vVerifica sintaxe válida + contrato de schema: document_items fechado, items_snapshot JSON, analysis_mode, agent_origin, embedding TEXT, constraint uq_comparacao_fornecedor_regra, tabelas do Copiloto (chat_conversations/chat_messages com context_json/sources JSON, check de role, constraint uq_chat_messages_conversation_role) e ausência de índice ivfflat sobre embedding. Para validação de runtime em Postgres real, use docker compose up -d db (o init.sql é aplicado automaticamente no 1º boot do volume pgdata).
cd backend
.\.venv\Scripts\python.exe -m pytest tests\test_rules_loader.py tests\test_extractor.py tests\test_comparator.py tests\test_matrix.py -v- 40 testes cobrindo validação de moldes, extração por âncoras (numérica/extensa/booleana/legal/data/percentual/monetária), classificação OK/FALHA/ATENÇÃO e montagem da matriz.
Compara modelos lado a lado nos TRs fixture usando os mesmos prompts de produção, medindo por modelo: aderência ao formato DE→PARA (JSON válido), recall (grounding nos problemas esperados), % de correções com fundamento legal e latência média:
cd backend
# Baixe os modelos locais antes (uma vez):
ollama pull hermes3
ollama pull qwen3:32b
# Roda todos (Groq llama-3.1-8b + Hermes 3 8B local + Qwen3 32B local):
.\.venv\Scripts\python.exe scripts\benchmark_modelos.py
# Só locais, apontando para o Ollama na sua máquina (execução nativa Windows):
.\.venv\Scripts\python.exe scripts\benchmark_modelos.py --models hermes3,qwen3 --ollama-base-url http://localhost:11434- Requer
GROQ_API_KEYno.envapenas para o modelo Groq; os modelos Ollama rodam 100% local (privacidade para TRs sigilosos). - Saídas em
backend/:benchmark_modelos_report.json(métricas detalhadas) ebenchmark_modelos_report.md(tabela markdown comparativa). - Para usar Hermes 3 no fluxo normal, defina
OLLAMA_MODEL=hermes3no.env(veja Configuração de Chaves de IA).
Todas as rotas sob /api/v1:
| Método | Rota | Descrição |
|---|---|---|
| POST | /fornecedores |
Cadastra fornecedor |
| GET / PUT / DELETE | /fornecedores/{id} |
CRUD de fornecedor |
| POST | /moldes |
Cria molde de regras (valida config_json) |
| GET / PUT / DELETE | /moldes/{id} |
CRUD de molde |
| POST | /documents/upload |
Upload com document_type=tr|proposta + fornecedor_id |
| POST | /comparison/start |
Inicia comparação TR × propostas (202, background) |
| GET | /comparison |
Lista comparações |
| GET | /comparison/{id} |
Status e totais |
| GET | /comparison/{id}/matrix |
Matriz de conformidade regras × fornecedores |
{
"versao": 1,
"regras": [
{ "id": "vigencia_dias", "rotulo": "Vigência mínima", "tipo": "numero_inteiro",
"ancora": "vigência", "expectativa": 90 },
{ "id": "garantia", "rotulo": "Garantia", "tipo": "booleano",
"palavras_chave": ["garantia", "caução"] },
{ "id": "lei_14133", "rotulo": "Lei 14.133/2021", "tipo": "legal",
"regex": "14\\.133/2021" }
]
}Tipos suportados: numero_inteiro, numero_extenso, booleano, legal, data, percentual, monetario.
cd backend
.\.venv\Scripts\python.exe scripts\seed_moldes.pyCria (idempotente) os moldes: Molde Padrão de TR, Molde de Serviços Continuados e Molde de Obras Públicas.
Delete protegido: moldes com comparações vinculadas e fornecedores com propostas retornam
409ao tentar exclusão (integridade referencial).
Reconstrói o índice FTS5 (com remove_diacritics 2) e regenera os embeddings semânticos. Rode os scripts sequencialmente — execução paralela contra o mesmo SQLite pode causar corrida no rebuild do FTS:
# Carregue as chaves do .env da raiz no processo antes de rodar:
Get-Content .env | Where-Object { $_ -match '^[A-Z_]+=' } | ForEach-Object {
$kv = $_ -split '=',2; [Environment]::SetEnvironmentVariable($kv[0], $kv[1])
}
cd backend
.\.venv\Scripts\python.exe scripts\ingest_laws.py
.\.venv\Scripts\python.exe scripts\ingest_juris_tcu.py
.\.venv\Scripts\python.exe scripts\ingest_corpus_extra.py
.\.venv\Scripts\python.exe scripts\ingest_embeddings.pyResultado esperado: 7 documentos, 315 chunks, 100% com embedding. Dica: se ingest_embeddings.py falhar com 429 RESOURCE_EXHAUSTED, aguarde ~60s (cota free tier de ~100 req/min do Gemini) e rode novamente — o script é idempotente (só processa chunks sem embedding).
Todas as rotas sob /api/v1:
| Método | Rota | Descrição |
|---|---|---|
| GET | /chat/health |
Status/configuração do Copiloto |
| POST | /chat/conversations |
Cria conversa (201), opcionalmente vinculada a documento/análise |
| GET | /chat/conversations |
Lista conversas (paginado por updated_at desc) |
| GET | /chat/conversations/{id}/messages |
Mensagens da conversa (404 se inexistente) |
| POST | /chat/conversations/{id}/messages |
Envia mensagem e retorna resposta com fontes (422 se conteúdo vazio/estouro) |
| POST | /chat/messages/{id}/feedback |
Feedback up/down (400 em mensagem do usuário, 404 inexistente, 422 rating inválido) |
Regras de comportamento:
- Grounding obrigatório (padrão): resposta factual exige pelo menos uma citação válida; sem fontes, o Copiloto recusa explicitamente.
suggested_actionsgeradas pelo LLM são descartadas no MVP — o chat é somente-leitura em relação às entidades de negócio.- Modo fake para demo/teste (sem IA real):
CHAT_FORCE_FAKE_PROVIDER=True. - Configurações:
CHAT_ENABLED,CHAT_REQUIRE_GROUNDING,CHAT_TOP_K_SOURCES,CHAT_MAX_MESSAGE_LENGTH,CHAT_MAX_SOURCES_STORED.
- MVP: Upload, parsing, análise com IA, relatório
- RF02/RF03: Auditoria TR × Propostas — moldes de regras + matriz de conformidade
- Auditoria (polimentos): editor visual de moldes + seed + tipos data/percentual/monetário
- RAG v1.0: legislação + jurisprudência TCU/RILC (315 chunks), busca semântica, busca sem acento, diff de versões
- RF04: Feedback/e-mail por fornecedor (endpoint + UI; requer
SMTP_HOST/SMTP_FROMno.env) - Correções de alto impacto (PRD v2.0): parsing determinístico, extração por âncoras robusta, FTS com diacríticos, schema Postgres sincronizado, paginação backward-compatible
- Copiloto LicitAI (chat consultivo): API + painel na tela de análise com grounding e citações (26 testes novos + 4 de schema)
- v2.0: Múltiplos agentes com LangGraph, checklist de conformidade, multi-usuário
- Validação Postgres runtime:
docker compose up -d dbquando houver Docker daemon (schema já validado por parserpglast)
Uso interno — Codeba.