backend/docs/ai/configuration.md
Rodrigo Verdiani 90ee74b3b9 docs: add AI module documentation and AGENTS.md
Comprehensive documentation for the AI module covering architecture,
API design, data model, RAG pipeline, configuration, integration points,
and frontend integration guide. Includes IDA5 extraction points reference
and AGENTS.md with project conventions and coding standards.
2026-06-08 20:13:21 -03:00

439 lines
11 KiB
Markdown

# Guia de Configuração — Módulo AI
## Pré-requisitos
| Componente | Como obter | Status |
|---|---|---|
| **Ollama** (host) | `curl -fsSL https://ollama.com/install.sh \| sh` | Local, necessário |
| **qwen3-embedding** | `ollama pull qwen3-embedding:latest` | Modelo de embedding |
| **gemma4:12b** | `ollama pull gemma4:12b` | LLM para chat local |
| **DeepSeek API key** | [platform.deepseek.com](https://platform.deepseek.com) | LLM cloud (opcional) |
| **PostgreSQL + pgvector** | `docker compose up -d postgres` | Já configurado |
| **RabbitMQ** | `docker compose up -d rabbit-mq` | Já configurado |
## 1. Setup do Ollama (Host)
### Instalação
```bash
# Linux
curl -fsSL https://ollama.com/install.sh | sh
# Verificar se está rodando
ollama --version
curl http://localhost:11434/api/tags
```
### Download dos Modelos
```bash
# Embedding (4.7 GB)
ollama pull qwen3-embedding:latest
# Chat local (7.6 GB)
ollama pull gemma4:12b
# Alternativa menor para máquinas com pouca RAM (9.6 GB, MoE)
# ollama pull gemma4:e4b
# Verificar modelos instalados
ollama list
```
**Hardware recomendado**:
| Modelo | RAM mínima | RAM recomendada | GPU VRAM (opcional) |
|---|---|---|---|
| `qwen3-embedding:latest` (8B) | 8 GB | 16 GB | 6 GB |
| `gemma4:12b` | 10 GB | 16 GB | 8 GB |
| `gemma4:e4b` | 6 GB | 12 GB | 6 GB |
### Configuração do Ollama
Por padrão, o Ollama escuta em `localhost:11434`. Se precisar acessar de outro host:
```bash
# Editar /etc/systemd/system/ollama.service ou usar env var
export OLLAMA_HOST=0.0.0.0:11434
```
Para otimizar performance com GPU (se disponível):
```bash
# Verificar se GPU está sendo usada
ollama run gemma4:12b --verbose
# Saída: "total duration: ..." — procure por "eval rate: XX tokens/s"
```
## 2. Arquivo `.env`
Criar na raiz do projeto (`backend/.env`):
```bash
# ============================================================
# Decompile-AI — Environment Variables
# ============================================================
# --- LLM Providers ---
# DeepSeek API Key (obter em https://platform.deepseek.com)
DEEPSEEK_API_KEY=sk-your-api-key-here
# --- Override de modelos (opcional) ---
# Provedor padrão de chat: ollama | deepseek
AI_DEFAULT_CHAT_PROVIDER=ollama
# Modelo de chat Ollama (padrão: gemma4:12b)
# AI_CHAT_MODEL_OLLAMA=gemma4:12b
# Modelo de chat DeepSeek (padrão: deepseek-chat)
# AI_CHAT_MODEL_DEEPSEEK=deepseek-chat
# Modelo de embedding (padrão: qwen3-embedding:latest)
# AI_EMBEDDING_MODEL=qwen3-embedding:latest
# Dimensão do embedding (padrão: 1024, max 4096 para qwen3)
# AI_EMBEDDING_DIMENSION=1024
# --- Database ---
# Sobrescrever credenciais do Postgres se necessário
# SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/decompile_ai
# SPRING_DATASOURCE_USERNAME=decompile_ai
# SPRING_DATASOURCE_PASSWORD=decompile_ai
```
**Importante**: Adicione `.env` ao `.gitignore`:
```bash
echo ".env" >> .gitignore
```
## 3. Carregamento do `.env`
O Spring Boot precisa saber como carregar o `.env`. Opções:
### Opção A: `spring.config.import` (nativo Spring Boot)
Adicionar ao `application.yml`:
```yaml
spring:
config:
import: optional:file:.env[.properties]
```
Isso carrega o `.env` como um arquivo de propriedades. **Limitação**: não suporta substituição de variáveis inline como `${VAR}` dentro de outras variáveis no `.env`, mas funciona bem para definir valores.
### Opção B: Plugin `dotenv` (recomendado para desenvolvimento)
Adicionar dependência ao `pom.xml`:
```xml
<dependency>
<groupId>me.paulschwarz</groupId>
<artifactId>spring-dotenv</artifactId>
<version>4.0.0</version>
</dependency>
```
Suporta interpolação de variáveis e convenção `.env` padrão.
### Opção C: Export manual (desenvolvimento)
```bash
set -a && source .env && set +a
./mvnw spring-boot:run
```
## 4. `application.yml` — Configuração do Módulo AI
### Blocos a adicionar ao arquivo existente
```yaml
spring:
# ... configurações existentes (datasource, jpa, flyway, rabbitmq) ...
ai:
ollama:
base-url: http://localhost:11434
embedding:
options:
model: ${AI_EMBEDDING_MODEL:qwen3-embedding:latest}
chat:
options:
model: ${AI_CHAT_MODEL_OLLAMA:gemma4:12b}
temperature: 0.3 # respostas determinísticas para análise técnica
top-p: 0.95
top-k: 64
openai:
base-url: https://api.deepseek.com
api-key: ${DEEPSEEK_API_KEY}
chat:
options:
model: ${AI_CHAT_MODEL_DEEPSEEK:deepseek-chat}
temperature: 0.3
max-tokens: 4096
app:
# ... configurações existentes (storage, rabbitmq, docker, die, engines) ...
ai:
# Provedor padrão de chat quando a sessão não especifica modelo
default-chat-provider: ${AI_DEFAULT_CHAT_PROVIDER:ollama}
# --- Configurações de Embedding ---
embedding:
# Dimensão do vetor (qwen3-embedding suporta 32-4096)
# DEVE corresponder à coluna vector(N) na migration V008
dimension: ${AI_EMBEDDING_DIMENSION:1024}
# Tamanho máximo do chunk em caracteres
chunk-max-chars: 3000
# Quantas funções processar por batch na API de embedding
batch-size: 20
# --- Configurações de RAG ---
rag:
# Quantos chunks retornar na busca semântica
top-k: 10
# Similaridade mínima para incluir um chunk (0.0 a 1.0)
similarity-threshold: 0.6
# Máximo de tokens de contexto enviados à LLM
max-context-tokens: 8000
# --- Configurações de Chat ---
chat:
# Quantas mensagens de histórico incluir no prompt
max-history-messages: 20
# Temperatura padrão para geração
temperature: 0.3
```
### Configuração completa do `application.yml` (após merge)
```yaml
spring:
threads:
virtual:
enabled: true
application:
name: decompile-ai
config:
import: optional:file:.env[.properties]
datasource:
url: jdbc:postgresql://localhost:5432/decompile_ai
username: decompile_ai
password: decompile_ai
jpa:
hibernate:
ddl-auto: validate
flyway:
enabled: true
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
servlet:
multipart:
max-file-size: 500MB
max-request-size: 500MB
ai:
ollama:
base-url: http://localhost:11434
embedding:
options:
model: ${AI_EMBEDDING_MODEL:qwen3-embedding:latest}
chat:
options:
model: ${AI_CHAT_MODEL_OLLAMA:gemma4:12b}
temperature: 0.3
top-p: 0.95
top-k: 64
openai:
base-url: https://api.deepseek.com
api-key: ${DEEPSEEK_API_KEY}
chat:
options:
model: ${AI_CHAT_MODEL_DEEPSEEK:deepseek-chat}
temperature: 0.3
max-tokens: 4096
app:
storage:
upload-dir: ./uploads/binaries
rabbitmq:
exchange: decompile.jobs
queue: decompile.jobs.queue
routing-key: decompile.jobs.created
docker:
enabled: true
die:
image: decompile-ai/diec:latest
timeout-seconds: 60
docker-host: unix:///var/run/docker.sock
engines:
ida5:
image: decompile-ai/ida5:latest
timeout-seconds: 300
ghidra:
image: decompile-ai/ghidra:latest
timeout-seconds: 600
ai:
default-chat-provider: ${AI_DEFAULT_CHAT_PROVIDER:ollama}
embedding:
dimension: ${AI_EMBEDDING_DIMENSION:1024}
chunk-max-chars: 3000
batch-size: 20
rag:
top-k: 10
similarity-threshold: 0.6
max-context-tokens: 8000
chat:
max-history-messages: 20
temperature: 0.3
logging:
level:
org.springframework.modulith: DEBUG
ai.decompile.ai: DEBUG # Logs do módulo AI
org.springframework.ai: INFO # Logs do Spring AI
```
## 5. `docker-compose.yml` (sem alterações)
O `docker-compose.yml` atual já atende todos os requisitos:
```yaml
services:
postgres:
container_name: decompile-ai-postgres
image: pgvector/pgvector:pg18 # PostgreSQL 18 + pgvector nativo
environment:
- POSTGRES_USER=decompile_ai
- POSTGRES_PASSWORD=decompile_ai
- POSTGRES_DB=decompile_ai
ports:
- "5432:5432"
volumes:
- postgres:/var/lib/postgresql
networks:
- decompile-ai-network
rabbit-mq:
container_name: decompile-ai-rabbitmq
image: rabbitmq:4-management
ports:
- "5672:5672"
- "15672:15672"
networks:
- decompile-ai-network
networks:
decompile-ai-network:
driver: bridge
volumes:
postgres:
```
**Não adicionamos Ollama ao docker-compose** porque ele roda no host.
## 6. Startup
### Ordem de inicialização
```bash
# 1. Infraestrutura Docker
docker compose up -d postgres rabbit-mq
# 2. Verificar Ollama no host
ollama list
# Deve mostrar: qwen3-embedding:latest, gemma4:12b
# 3. Configurar .env
cp .env.example .env
# Editar com a DEEPSEEK_API_KEY
# 4. Iniciar o backend
./mvnw spring-boot:run
# 5. Verificar health
curl http://localhost:8080/actuator/health
```
### Verificação de saúde dos componentes AI
```bash
# Ollama
curl http://localhost:11434/api/tags | jq '.models[].name'
# Testar embedding
curl http://localhost:11434/api/embed -d '{
"model": "qwen3-embedding:latest",
"input": "test"
}' | jq '.embeddings[0] | length'
# Deve retornar 1024 (ou dimensão configurada)
# Testar chat local
curl http://localhost:11434/api/chat -d '{
"model": "gemma4:12b",
"messages": [{"role": "user", "content": "Hello"}],
"stream": false
}' | jq '.message.content'
```
## 7. Troubleshooting
### Ollama não responde
```bash
# Verificar se está rodando
systemctl status ollama
# ou
ps aux | grep ollama
# Reiniciar se necessário
systemctl restart ollama
```
### Erro: "model not found"
```bash
# Listar modelos disponíveis
ollama list
# Baixar modelo faltante
ollama pull qwen3-embedding:latest
ollama pull gemma4:12b
```
### Erro: "DeepSeek API key not configured"
- Verificar se `.env` existe e contém `DEEPSEEK_API_KEY=sk-...`
- Verificar se `spring.config.import: optional:file:.env[.properties]` está no `application.yml`
- Alternativa: `export DEEPSEEK_API_KEY=sk-...` no terminal
### Erro: "relation 'vector_store' does not exist"
- Verificar se Flyway rodou a migration V008: `SELECT * FROM flyway_schema_history;`
- Rodar manualmente se necessário: `./mvnw flyway:migrate`
### Erro: "column 'embedding' type vector not supported"
- Verificar se a extensão pgvector está ativada: `SELECT * FROM pg_extension WHERE extname = 'vector';`
- Ativar manualmente: `CREATE EXTENSION IF NOT EXISTS vector;`
### Performance lenta nos embeddings
- Reduzir `batch-size` no `application.yml`
- Verificar se o Ollama está usando GPU: `ollama run qwen3-embedding --verbose` e checar `eval rate`
- Sem GPU, o modelo 8B pode ser lento para centenas de funções (esperar 2-5 minutos)
### Contexto da LLM estourando
- Reduzir `max-context-tokens` em `app.ai.rag`
- Reduzir `max-history-messages` em `app.ai.chat`
- Aumentar `chunk-max-chars` (para incluir menos chunks maiores)