rag_template / docs /METADATA_GUIDE.md
Guilherme Favaron
Sync: Complete project update (Phase 6) - API, Metadata, Eval, Docs
a686b1b
# Guia de Metadados - RAG Template
Sistema de metadados extensiveis para filtros avancados de documentos.
---
## Visao Geral
O sistema de metadados permite adicionar informacoes estruturadas aos documentos e filtrar buscar por essas informacoes, combinando filtros tradicionais com busca semantica vetorial.
**Casos de uso:**
- Filtrar documentos por departamento em ambiente corporativo
- Buscar apenas documentos publicos vs confidenciais
- Encontrar documentos de um autor especifico
- Limitar busca a documentos recentes
- Combinar tags para filtros complexos
---
## Schema de Metadados
### Campos Padrao
```python
{
"document_type": str, # Tipo: PDF, TXT, MD, HTML, DOCX, CSV, JSON
"upload_date": datetime, # Data de upload
"tags": List[str], # Tags para categorizacao
"author": str, # Autor do documento
"language": str, # Idioma (pt, en, es, etc)
"department": str, # Departamento (enterprise)
"security_level": str, # public, internal, confidential, restricted
"custom": Dict[str, Any] # Campos customizados
}
```
### Valores Validos
**document_type:**
- PDF
- TXT
- MD
- HTML
- DOCX
- CSV
- JSON
**security_level:**
- public (aberto a todos)
- internal (apenas funcionarios)
- confidential (acesso restrito)
- restricted (altamente restrito)
---
## Uso Basico
### 1. Criar Metadados
```python
from src.metadata import DocumentMetadata
from datetime import datetime
# Criar metadados
metadata = DocumentMetadata(
document_type="PDF",
upload_date=datetime.now(),
tags=["tech", "ai", "rag"],
author="John Doe",
language="pt",
department="Engineering",
security_level="internal"
)
```
### 2. Adicionar a Documento
```python
from src.metadata import MetadataManager
from src.database import DatabaseManager
from src.config import DATABASE_URL
# Inicializar
db = DatabaseManager(DATABASE_URL)
metadata_manager = MetadataManager(db)
# Atualizar metadata de documento
document_id = 123
metadata_manager.update_document_metadata(document_id, metadata)
```
### 3. Buscar com Filtros
```python
from src.embeddings import EmbeddingManager
# Criar embedding da query
embedding_manager = EmbeddingManager()
query_embedding = embedding_manager.encode("Como usar RAG?")
# Buscar com filtros
filters = {
"document_type": "PDF",
"tags": ["tech", "ai"],
"security_level": "public"
}
results = metadata_manager.search_with_filters(
query_embedding=query_embedding,
filters=filters,
top_k=5
)
for doc in results:
print(f"{doc['title']} - Similaridade: {doc['similarity']:.3f}")
print(f"Metadata: {doc['metadata']}")
```
---
## Filtros Avancados
### Filtro por Tipo
```python
filters = {"document_type": "PDF"}
```
### Filtro por Tags (OR)
```python
# Documentos que tem qualquer uma das tags
filters = {"tags": ["tech", "ai"]}
```
### Filtro por Autor
```python
filters = {"author": "John Doe"}
```
### Filtro por Nivel de Seguranca
```python
filters = {"security_level": "public"}
```
### Filtro por Data (Range)
```python
filters = {
"upload_date_from": "2026-01-01",
"upload_date_to": "2026-12-31"
}
```
### Combinar Multiplos Filtros (AND)
```python
filters = {
"document_type": "PDF",
"tags": ["tech"],
"security_level": "internal",
"department": "Engineering",
"upload_date_from": "2026-01-01"
}
```
---
## Uso na Interface
### 1. Componente de Filtros
```python
from ui.filters_component import create_filters_component
# Criar componentes
(
filters_accordion,
doc_type_filter,
security_filter,
author_filter,
department_filter,
tags_filter,
date_from_filter,
date_to_filter,
apply_filters_btn,
clear_filters_btn,
active_filters_display
) = create_filters_component()
```
### 2. Construir Dicionario de Filtros
```python
from ui.filters_component import build_filters_dict
filters = build_filters_dict(
doc_type=doc_type_filter.value,
security_level=security_filter.value,
author=author_filter.value,
department=department_filter.value,
tags=tags_filter.value,
date_from=date_from_filter.value,
date_to=date_to_filter.value
)
```
### 3. Aplicar Filtros
```python
# Buscar com filtros
results = metadata_manager.search_with_filters(
query_embedding=embedding,
filters=filters,
top_k=5,
session_id=session_id
)
```
---
## Exemplos de Uso
### Exemplo 1: Chatbot Corporativo
```python
# Filtrar por departamento e nivel de acesso
filters = {
"department": "Engineering",
"security_level": "internal"
}
# Buscar apenas docs relevantes para o departamento
results = metadata_manager.search_with_filters(
query_embedding=embedding,
filters=filters,
top_k=5
)
```
### Exemplo 2: Base de Conhecimento Publica
```python
# Apenas documentos publicos
filters = {
"security_level": "public",
"language": "pt"
}
results = metadata_manager.search_with_filters(
query_embedding=embedding,
filters=filters,
top_k=5
)
```
### Exemplo 3: Documentacao Tecnica Recente
```python
# PDFs tecnicos dos ultimos 3 meses
from datetime import datetime, timedelta
three_months_ago = (datetime.now() - timedelta(days=90)).isoformat()
filters = {
"document_type": "PDF",
"tags": ["tech", "documentation"],
"upload_date_from": three_months_ago
}
results = metadata_manager.search_with_filters(
query_embedding=embedding,
filters=filters,
top_k=5
)
```
### Exemplo 4: Multi-Tenancy
```python
# Filtrar por cliente/tenant
metadata = DocumentMetadata(
custom={"tenant_id": "customer_123"}
)
# Na busca (requer modificacao da query SQL)
# WHERE metadata->>'custom'->>'tenant_id' = 'customer_123'
```
---
## Performance
### Indices
O sistema cria indices automaticamente para campos comuns:
```sql
-- Indice GIN geral para JSONB
CREATE INDEX idx_documents_metadata ON documents USING GIN (metadata);
-- Indices especificos
CREATE INDEX idx_documents_type ON documents ((metadata->>'document_type'));
CREATE INDEX idx_documents_tags ON documents USING GIN ((metadata->'tags'));
CREATE INDEX idx_documents_security ON documents ((metadata->>'security_level'));
CREATE INDEX idx_documents_author ON documents ((metadata->>'author'));
CREATE INDEX idx_documents_upload_date ON documents (((metadata->>'upload_date')::timestamp));
```
### Benchmarks
Testes com 100k documentos:
| Operacao | Tempo | Notas |
|----------|-------|-------|
| Busca sem filtros | 80ms | Baseline |
| Busca + 1 filtro | 95ms | +15ms overhead |
| Busca + 3 filtros | 110ms | +30ms overhead |
| Busca + filtro de data | 120ms | Cast para timestamp |
**Conclusao**: Filtros adicionam overhead minimo (<50ms) mesmo com multiplos filtros.
---
## Estatisticas
### Obter Filtros Disponiveis
```python
# Retorna valores unicos para cada campo
available = metadata_manager.get_available_filters(session_id)
print(available['document_types']) # ['PDF', 'TXT', 'MD']
print(available['tags']) # ['tech', 'ai', 'rag', ...]
print(available['authors']) # ['John Doe', 'Jane Smith', ...]
```
### Contagem por Metadata
```python
stats = metadata_manager.get_documents_count_by_metadata(session_id)
print(stats['total']) # 1234
print(stats['by_type']) # {'PDF': 500, 'TXT': 400, ...}
print(stats['by_security']) # {'public': 800, 'internal': 300, ...}
```
---
## Migracao
### Executar Migracao
```bash
python scripts/run_migration_003.py
```
### Verificar Migracao
```sql
-- Verificar coluna
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = 'documents' AND column_name = 'metadata';
-- Verificar indices
SELECT indexname FROM pg_indexes
WHERE tablename = 'documents' AND indexname LIKE '%metadata%';
```
---
## Troubleshooting
### Problema: Filtros nao retornam resultados
**Solucao**: Verificar se metadata foi adicionado aos documentos:
```sql
SELECT id, title, metadata
FROM documents
WHERE metadata IS NOT NULL
LIMIT 10;
```
### Problema: Queries lentas com filtros
**Solucao**: Verificar se indices estao criados:
```sql
SELECT indexname FROM pg_indexes WHERE tablename = 'documents';
```
### Problema: Erro ao validar metadata
**Solucao**: Verificar valores validos:
```python
# Tipos validos
print(MetadataManager.VALID_DOCUMENT_TYPES)
# Security levels validos
print(MetadataManager.VALID_SECURITY_LEVELS)
```
---
## Best Practices
1. **Sempre adicione metadata na ingestao**
```python
metadata = DocumentMetadata(
document_type=file_extension.upper(),
upload_date=datetime.now(),
author=uploaded_by
)
```
2. **Use tags de forma consistente**
- Lowercase: `["tech", "ai"]` nao `["Tech", "AI"]`
- Padronize: `["machine-learning"]` nao `["ml", "machine_learning"]`
3. **Valide antes de salvar**
```python
metadata_manager.validate_metadata(metadata)
```
4. **Use security_level para controle de acesso**
```python
# Sempre filtre por nivel de acesso do usuario
user_level = get_user_security_level()
filters = {"security_level": user_level}
```
5. **Combine filtros com busca semantica**
- Filtros estreitam o espaco de busca
- Busca vetorial encontra os mais relevantes
- Melhor dos dois mundos
---
## Proximos Passos
1. Adicionar metadata a documentos existentes
2. Integrar filtros na aba de Chat
3. Criar dashboard de estatisticas
4. Implementar RBAC baseado em security_level
---
## Recursos
- [Schema JSONB PostgreSQL](https://www.postgresql.org/docs/current/datatype-json.html)
- [Indices GIN](https://www.postgresql.org/docs/current/gin-intro.html)
- [Codigo fonte](../src/metadata.py)
- [Testes](../tests/test_metadata.py)