Files
oci_tips/23AI/app/doc-embedding-service/TECHNICAL_OVERVIEW.md
2025-12-04 11:47:29 -03:00

15 KiB

Document Embedding Service - Visão Técnica

Arquitetura

Visão Geral

O Document Embedding Service é uma aplicação web RESTful desenvolvida em Python que implementa um pipeline completo de processamento de documentos para sistemas de Retrieval-Augmented Generation (RAG). A aplicação processa documentos em múltiplos formatos, extrai texto, divide em chunks semânticos, gera embeddings vetoriais e armazena tudo em um banco de dados Oracle Autonomous Database (ADW) 23AI com suporte nativo a vetores.

Componentes Principais

┌─────────────────────────────────────────────────────────────┐
│                     Flask Web Server                        │
│                    (app.py - Port 8000)                     │
└─────────────────────────────────────────────────────────────┘
                              │
        ┌─────────────────────┼─────────────────────┐
        │                     │                     │
        ▼                     ▼                     ▼
┌──────────────┐    ┌──────────────────┐   ┌──────────────┐
│ Auth Module  │    │ Document         │   │  Embedding   │
│  (auth.py)   │    │  Processor       │   │   Service    │
│              │    │ (document_       │   │ (embedding_  │
│ - OCI Signer │    │  processor.py)   │   │  service.py) │
│ - HTTP Auth  │    │                  │   │              │
│   (API Key)  │    │ - PDF Extract    │   │ - Sentence   │
│              │    │ - Word Extract   │   │   Transform. │
│              │    │ - OCR (Tess.)    │   │ - Batch      │
│              │    │ - Chunking       │   │   Encoding   │
└──────────────┘    └──────────────────┘   └──────────────┘
                              │                     │
                              └──────────┬──────────┘
                                         ▼
                              ┌──────────────────┐
                              │  Database Layer  │
                              │  (database.py)   │
                              │                  │
                              │ - Connection Mgr │
                              │ - Schema Init    │
                              │ - CRUD Ops       │
                              │ - Vector Search  │
                              └──────────────────┘
                                         │
                                         ▼
                              ┌──────────────────┐
                              │  Oracle ADW 23AI │
                              │                  │
                              │ - DOCUMENTS      │
                              │ - DOCUMENT_CHUNKS│
                              │ - Vector Index   │
                              └──────────────────┘

Módulos Detalhados

1. auth.py - Módulo de Autenticação

Responsabilidades:

  • Gerenciar autenticação OCI via Signer
  • Validar credenciais HTTP (X-API-Key e Bearer Token)
  • Carregar configuração de arquivo externo
  • Suportar modo de teste (sem OCI real)

Classes:

  • OCIAuthManager: Gerencia autenticação OCI
  • HTTPAuthManager: Gerencia autenticação HTTP

Padrões de Segurança:

  • Comparação de strings usando hmac.compare_digest (timing-attack safe)
  • Suporte a múltiplos métodos de autenticação HTTP
  • Modo debug configurável para troubleshooting

Exemplo de Uso:

from auth import initialize_auth

oci_auth, http_auth = initialize_auth(
    config_file="/path/to/credentials.conf",
    api_key="your-api-key",
    test_mode=False
)

# Middleware Flask
@app.before_request
def authenticate():
    http_auth.check_api_key()

2. document_processor.py - Processamento de Documentos

Responsabilidades:

  • Extrair texto de PDF (nativo e escaneado)
  • Extrair texto de Word (.docx)
  • Realizar OCR em imagens
  • Dividir texto em chunks com sobreposição
  • Calcular hash de conteúdo

Formatos Suportados:

  • PDF: PyPDF2 para texto nativo, pdf2image + Tesseract para escaneados
  • Word: python-docx para .docx
  • Imagens: PIL + Tesseract OCR (PNG, JPG, TIFF)

Algoritmo de Chunking:

  1. Define tamanho do chunk (padrão: 500 caracteres)
  2. Define sobreposição (padrão: 50 caracteres)
  3. Tenta quebrar em limites naturais (ponto, nova linha, espaço)
  4. Mantém contexto entre chunks via sobreposição

Configuração:

processor = DocumentProcessor(
    chunk_size=500,      # Tamanho do chunk
    chunk_overlap=50     # Sobreposição
)

result = processor.process_document(
    content=file_bytes,
    filename="document.pdf",
    mime_type="application/pdf"
)
# result = {
#     'text': "...",
#     'chunks': [...],
#     'content_hash': "sha256...",
#     'text_length': 12345,
#     'chunks_count': 25
# }

3. embedding_service.py - Geração de Embeddings

Responsabilidades:

  • Carregar modelo Sentence Transformers
  • Gerar embeddings para texto único ou batch
  • Calcular similaridade de cosseno
  • Buscar embeddings similares

Modelo Padrão:

  • sentence-transformers/all-MiniLM-L6-v2
  • Dimensão: 384
  • Multilíngue (suporta português e inglês)
  • Rápido e eficiente

Modelos Alternativos:

# Modelo maior e mais preciso
EMBEDDING_MODEL=sentence-transformers/all-mpnet-base-v2  # 768 dim

# Modelo multilíngue otimizado
EMBEDDING_MODEL=sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2  # 384 dim

# Modelo específico para português
EMBEDDING_MODEL=neuralmind/bert-base-portuguese-cased  # 768 dim

Performance:

  • Batch processing para eficiência
  • Normalização automática de vetores
  • Cache de modelo em memória

Exemplo de Uso:

from embedding_service import EmbeddingService

service = EmbeddingService(model_name="sentence-transformers/all-MiniLM-L6-v2")

# Encoding único
embedding = service.encode_text("Este é um texto de exemplo")

# Encoding batch
embeddings = service.encode_batch(["texto 1", "texto 2", "texto 3"])

# Busca similar
results = service.find_similar(query_embedding, all_embeddings, top_k=5)

4. database.py - Camada de Banco de Dados

Responsabilidades:

  • Gerenciar conexão com ADW 23AI
  • Criar schema automaticamente
  • Operações CRUD para documentos e chunks
  • Busca vetorial usando índice nativo

Schema do Banco de Dados:

Tabela DOCUMENTS

CREATE TABLE DOCUMENTS (
    id VARCHAR2(36) PRIMARY KEY,           -- UUID
    filename VARCHAR2(500) NOT NULL,       -- Nome do arquivo
    file_type VARCHAR2(50) NOT NULL,       -- MIME type
    file_size NUMBER NOT NULL,             -- Tamanho em bytes
    upload_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    content_hash VARCHAR2(64),             -- SHA-256
    metadata CLOB,                         -- JSON metadata
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)

Tabela DOCUMENT_CHUNKS

CREATE TABLE DOCUMENT_CHUNKS (
    id VARCHAR2(36) PRIMARY KEY,           -- UUID
    document_id VARCHAR2(36) NOT NULL,     -- FK para DOCUMENTS
    chunk_index NUMBER NOT NULL,           -- Índice do chunk
    chunk_text CLOB NOT NULL,              -- Texto do chunk
    chunk_size NUMBER NOT NULL,            -- Tamanho do chunk
    embedding VECTOR(384, FLOAT32),        -- Vetor de embedding
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT fk_document FOREIGN KEY (document_id) 
        REFERENCES DOCUMENTS(id) ON DELETE CASCADE
)

Índices

-- Índice para busca por documento
CREATE INDEX idx_chunks_document ON DOCUMENT_CHUNKS(document_id);

-- Índice vetorial para busca semântica (Oracle 23AI)
CREATE VECTOR INDEX idx_chunks_embedding 
    ON DOCUMENT_CHUNKS(embedding) 
    ORGANIZATION NEIGHBOR PARTITIONS
    WITH DISTANCE COSINE;

Busca Vetorial:

-- Busca usando VECTOR_DISTANCE
SELECT c.id, c.chunk_text, d.filename,
       VECTOR_DISTANCE(c.embedding, TO_VECTOR(:query_embedding), COSINE) as distance
FROM DOCUMENT_CHUNKS c
JOIN DOCUMENTS d ON c.document_id = d.id
ORDER BY distance
FETCH FIRST :top_k ROWS ONLY

Tipo VECTOR do Oracle 23AI:

  • Suporte nativo a vetores de alta dimensão
  • Índices otimizados para busca de vizinhos mais próximos
  • Funções de distância: COSINE, EUCLIDEAN, DOT
  • Performance superior a soluções baseadas em BLOB

5. app.py - Aplicação Flask

Endpoints:

Método Endpoint Descrição Auth
GET / ou /health Health check Não
POST /api/v1/documents/upload Upload de documento Sim
GET /api/v1/documents Lista documentos Sim
GET /api/v1/documents/{id} Busca documento Sim
DELETE /api/v1/documents/{id} Deleta documento Sim
POST /api/v1/search Busca semântica Sim
GET /api/v1/stats Estatísticas Sim

Fluxo de Upload:

1. Cliente → POST /api/v1/documents/upload
2. Validação de autenticação (HTTP Auth)
3. Validação de arquivo (tipo, tamanho)
4. Extração de texto (DocumentProcessor)
5. Chunking (DocumentProcessor)
6. Geração de embeddings (EmbeddingService)
7. Inserção no banco (DatabaseManager)
   - INSERT INTO DOCUMENTS
   - INSERT INTO DOCUMENT_CHUNKS (batch)
8. Resposta com document_id e estatísticas

Fluxo de Busca:

1. Cliente → POST /api/v1/search {"query": "..."}
2. Validação de autenticação
3. Geração de embedding da query (EmbeddingService)
4. Busca vetorial no banco (VECTOR_DISTANCE)
5. Filtragem por threshold
6. Ordenação por similaridade
7. Resposta com top_k resultados

Padrões de Design

1. Factory Pattern

# Criação de instâncias via factory functions
processor = create_document_processor(chunk_size=500)
embedding_service = create_embedding_service(model_name="...")

2. Singleton Pattern

# Instâncias globais para serviços compartilhados
_embedding_service = None

def get_embedding_service():
    return _embedding_service

3. Dependency Injection

# Inicialização de dependências no startup
def initialize_services():
    oci_auth, http_auth = initialize_auth(...)
    embedding_service = initialize_embedding_service(...)
    db = initialize_database(...)

4. Middleware Pattern

# Autenticação como middleware Flask
@app.before_request
def before_all_requests():
    if request.method == "OPTIONS":
        return "", 204
    http_auth.check_api_key()

Configuração e Variáveis de Ambiente

Arquivo .env

# Segurança
API_KEY=your-secure-api-key

# OCI
OCI_CONFIG_FILE=/path/to/credentials.conf
OCI_REGION=us-chicago-1
TEST_MODE=false

# Banco de Dados
DB_USER=ADMIN
DB_PASSWORD=password
DB_DSN=(description=...)

# Embeddings
EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2
EMBEDDING_DIMENSION=384
CHUNK_SIZE=500
CHUNK_OVERLAP=50

# Aplicação
UPLOAD_FOLDER=/app/uploads
MAX_UPLOAD_SIZE=52428800  # 50MB
PORT=8000

Arquivo credentials.conf (OCI)

tenancy=ocid1.tenancy.oc1..aaa...
user=ocid1.user.oc1..aaa...
fingerprint=xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx
key_file=/path/to/oci_api_key.pem
pass_phrase=
region=us-chicago-1
test_mode=false

Performance e Otimização

Chunking

  • Trade-off: Chunks menores = maior precisão, mais chunks, mais storage
  • Recomendação: 500 caracteres com 50 de overlap para documentos técnicos
  • Ajuste: Aumentar para 1000+ em documentos narrativos

Embeddings

  • Batch Processing: Processa múltiplos chunks de uma vez
  • GPU Support: Configure EMBEDDING_DEVICE=cuda se disponível
  • Modelo: MiniLM-L6 é rápido; use MPNet para maior qualidade

Banco de Dados

  • Vector Index: Essencial para performance em grandes volumes
  • Connection Pool: Considere usar pool de conexões em produção
  • Batch Insert: Chunks são inseridos em batch para eficiência

Escalabilidade

  • Horizontal: Múltiplas instâncias com load balancer
  • Vertical: Aumentar CPU/RAM para processamento mais rápido
  • Storage: Object Storage para arquivos originais (não implementado)

Segurança

Autenticação

  • Dual HTTP auth (X-API-Key e Bearer)
  • OCI Signer para serviços Oracle
  • Timing-attack safe string comparison

Validação

  • Tipo de arquivo (whitelist)
  • Tamanho de arquivo (configurável)
  • Sanitização de filename

Dados Sensíveis

  • Credenciais em variáveis de ambiente
  • Chaves privadas fora do repositório
  • Secrets management recomendado (OCI Vault)

Monitoramento e Logging

Logs

print(f"[module] Message")  # Formato padrão

Métricas

  • Tempo de processamento por documento
  • Número de chunks gerados
  • Taxa de sucesso/erro
  • Estatísticas via /api/v1/stats

Health Check

curl http://localhost:8000/health

Testes

Teste Manual

python test_service.py

Teste com curl

./examples/curl_examples.sh

Teste Unitário (Recomendado para produção)

# Adicionar pytest e testes unitários
pytest tests/

Limitações Conhecidas

  1. Armazenamento: Arquivos originais não são persistidos (apenas texto extraído)
  2. OCR: Qualidade depende da resolução da imagem
  3. Idiomas: OCR configurado para português e inglês
  4. Concorrência: Não há lock de documentos duplicados
  5. Rate Limiting: Não implementado (adicionar se necessário)

Roadmap Futuro

  1. Object Storage: Armazenar arquivos originais no OCI Object Storage
  2. Async Processing: Usar Celery para processamento assíncrono
  3. Webhooks: Notificações de conclusão de processamento
  4. Versioning: Suporte a múltiplas versões de documentos
  5. Multi-tenancy: Isolamento por tenant/usuário
  6. Advanced Search: Filtros por metadata, data, tipo
  7. Reranking: Reranking de resultados com modelo cross-encoder
  8. Caching: Cache de embeddings frequentes

Referências