Skip to content

Implementa pipeline de chunking, geração de embeddings e indexação no ChromaDB - #3

Merged
DanielDPereira merged 5 commits into
developfrom
feature/Chunking-Embeddings
Jul 3, 2026
Merged

Implementa pipeline de chunking, geração de embeddings e indexação no ChromaDB#3
DanielDPereira merged 5 commits into
developfrom
feature/Chunking-Embeddings

Conversation

@DanielDPereira

Copy link
Copy Markdown
Owner

Descrição da PR

Esta Pull Request conclui a Epic 3 — Chunking e Embeddings do backlog, realizando o merge da branch correspondente para develop.

Ela implementa toda a pipeline responsável pela preparação dos documentos para o sistema RAG, incluindo a divisão dos textos em chunks, geração de embeddings utilizando o Google Gemini e indexação em uma base vetorial local com ChromaDB. A implementação adota uma arquitetura modular, com tratamento de erros, rotação automática de chaves da API e utilitários para facilitar a operação e manutenção da base vetorial.

Implementação da pipeline

  • Adicionada a classe DocumentChunker (chunker.py) para realizar a divisão recursiva dos documentos em chunks utilizando Recursive Character Text Splitting, preservando os metadados de cada documento.
  • Implementadas as classes FallbackGeminiEmbeddings e GeminiAPIKeyManager (database.py) para geração de embeddings com o Google Gemini, incluindo rotação automática de chaves da API, tentativas de recuperação (retry/backoff) e acesso singleton às instâncias de embeddings e do banco vetorial.
  • Adicionado o script populate.py, responsável pela indexação em lote dos documentos processados no ChromaDB, incluindo limpeza opcional da coleção, processamento em batches, tratamento de erros e gerenciamento de limites de requisição da API.

Integração e melhorias na API

  • Atualizado o arquivo __init__.py para expor os componentes de chunking, embeddings e banco vetorial, facilitando sua reutilização em outras partes do projeto.
  • Aprimorado o endpoint /health, que agora valida a conectividade com o ChromaDB e informa, em tempo real, a quantidade de chunks atualmente indexados.

Documentação

  • Adicionada a documentação vectorstore.md, detalhando a arquitetura, decisões de implementação e instruções de utilização da pipeline de chunking, embeddings e banco vetorial.
  • Atualizado o backlog.md, marcando todas as funcionalidades da Epic 3 como concluídas.

Epic atendida

Epic 3 — Chunking e Embeddings

Responsável pela preparação e armazenamento dos documentos na base vetorial.

Feature 3.1 — Chunking

  • ✅ Estudar estratégias de chunking (RecursiveCharacterTextSplitter)
  • ✅ Definir tamanho ideal de chunk e overlap
  • ✅ Implementar a divisão estruturada dos documentos em chunks

Feature 3.2 — Embeddings

  • ✅ Escolher modelo de embeddings adequado para o idioma português
  • ✅ Implementar a geração de embeddings para os chunks
  • ✅ Validar a qualidade da conversão dos embeddings

Feature 3.3 — Banco Vetorial

  • ✅ Configurar e instanciar o ChromaDB local
  • ✅ Criar coleção persistente para o projeto
  • ✅ Inserir os chunks com seus respectivos embeddings
  • ✅ Implementar e validar consultas por similaridade cosseno

✅ Definition of Done

  • Divisão dos documentos em chunks com overlap validado.
  • Embeddings gerados com sucesso para todos os chunks.
  • Chunks indexados corretamente no ChromaDB local.
  • Base vetorial pronta para a etapa de recuperação semântica (RAG).

Copilot AI review requested due to automatic review settings July 3, 2026 00:56
@DanielDPereira
DanielDPereira merged commit 291270d into develop Jul 3, 2026
1 check passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Esta PR implementa a pipeline de preparação de documentos para RAG no projeto (chunking → embeddings Gemini → indexação local no ChromaDB), adicionando componentes de app/vectorstore/, um script de carga em lote e testes/documentação de suporte.

Changes:

  • Adiciona o DocumentChunker (RecursiveCharacterTextSplitter) para gerar chunks com metadados.
  • Implementa geração de embeddings com fallback/rotação de chaves e instanciação do ChromaDB.
  • Inclui script populate.py, endpoint /health aprimorado, testes e documentação da arquitetura.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
app/vectorstore/chunker.py Implementa chunking recursivo e propagação de metadados para Document.
app/vectorstore/database.py Adiciona gerenciador de chaves Gemini e wrapper de embeddings com retry/rotação; fornece helpers para Chroma.
app/vectorstore/populate.py Script CLI para fatiar documentos processados e indexar em lote no ChromaDB.
app/vectorstore/__init__.py Expõe APIs públicas do pacote vectorstore.
app/main.py Atualiza /health para reportar conectividade/contagem de chunks no ChromaDB.
tests/test_chunker.py Testes unitários do chunker (texto normal e vazio).
tests/test_database.py Testes do gerenciador de chaves e da rotação/fallback de embeddings (com mocks).
tests/test_vectorstore_integration.py Testes de integração de inserção e busca por similaridade com Chroma usando embeddings mockados.
docs/vectorstore.md Documenta arquitetura/decisões e instruções de uso/testes.
docs/backlog.md Marca Epic 3 como concluída no backlog.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +130 to +134
except Exception as e:
err_str = str(e)
# Se for limite de cota/autorização e temos outras chaves, rotacionamos sem gastar retentativas locais
if ("RESOURCE_EXHAUSTED" in err_str or "429" in err_str or "403" in err_str) and self.key_manager.count > 1:
break
Comment on lines +174 to +177
except Exception as e:
err_str = str(e)
if ("RESOURCE_EXHAUSTED" in err_str or "429" in err_str or "403" in err_str) and self.key_manager.count > 1:
break
Comment thread app/main.py
Comment on lines +40 to +44
from app.vectorstore.database import get_vectorstore
db = get_vectorstore()
count = db._collection.count()
db_status = f"connected ({count} chunks)"
except Exception as e:
Comment on lines +25 to +42
# 2. Limpa coleção anterior para evitar duplicações
print("🧹 Limpando dados antigos da coleção...")
try:
# Chroma do LangChain não tem um método direto 'clear' de alto nível,
# mas podemos deletar por ids ou usar a API do client interno para deletar
# a coleção e criá-la novamente.
# Uma forma limpa usando a API do LangChain Chroma é:
# obter todos os documentos e deletar por IDs.
all_docs = vectorstore.get()
if all_docs and "ids" in all_docs and all_docs["ids"]:
print(f"🗑️ Removendo {len(all_docs['ids'])} registros existentes...")
vectorstore.delete(ids=all_docs["ids"])
print("✅ Coleção limpa com sucesso.")
else:
print("ℹ️ Coleção já estava vazia.")
except Exception as e:
print(f"⚠️ Erro ao limpar a coleção (pode ser a primeira execução): {str(e)}")

print(f"⏳ Limite de requisições excedido. Aguardando 35 segundos para recuperar cota... (Tentativas restantes: {retries})")
time.sleep(35)
else:
raise e
Comment thread tests/test_database.py
assert manager.current_key == "good_key"
assert mock_google_embeddings.call_count == 3

@patch("app.vectorstore.database.GoogleGenerativeAIEmbeddings")
Comment on lines +52 to +53
# Cria uma cópia profunda/estendida dos metadados originais
metadata = doc_metadata.copy()
Comment on lines +209 to +227
def get_embedding_model() -> FallbackGeminiEmbeddings:
"""
Cria e retorna a instância de embeddings configurada com suporte a fallback.
"""
key_manager = get_key_manager()
return FallbackGeminiEmbeddings(key_manager=key_manager)

def get_vectorstore() -> Chroma:
"""
Retorna a instância do ChromaDB configurada com os embeddings suportados por fallback.
"""
chroma_db_path = os.getenv("CHROMA_DB_PATH", "data/db")
embeddings = get_embedding_model()

return Chroma(
collection_name="brasil_copa_2026",
embedding_function=embeddings,
persist_directory=chroma_db_path
)
Comment thread docs/vectorstore.md
* **Modelo**: `models/gemini-embedding-001`. Este modelo foi selecionado por possuir excelente custo-benefício e suporte nativo robusto a idiomas multilíngues, em especial o Português do Brasil.
* **Gerenciador de Chaves (`GeminiAPIKeyManager`)**: Permite o carregamento de múltiplas chaves de API a partir da variável de ambiente `GEMINI_API_KEYS` (lista separada por vírgula) ou fallback automático para a chave tradicional `GEMINI_API_KEY`.
* **Resiliência e Rotação**: Criamos a classe wrapper `FallbackGeminiEmbeddings` que encapsula o cliente de embeddings e intercepta erros de cota ou limites de taxa (`429 RESOURCE_EXHAUSTED`). Caso uma chave falhe, ela é rotacionada automaticamente para a próxima chave configurada na lista.
* **Retentativas locais com Backoff**: Para suportar falhas temporárias de rede (ex: `WinError 10060`), implementamos uma lógica de retentativas locais (até 3 tentativas) com tempo de espera exponencial crescente (2s, 4s, 8s) antes de desistir ou rotacionar a chave.
Comment thread docs/vectorstore.md
Criamos um script utilitário CLI para processar a base de dados de `data/processed/` e indexar tudo no banco vetorial.
* **Carga Fracionada**: Os 502 chunks são enviados ao banco em lotes de 10 chunks com 4 segundos de intervalo entre envios. Isso garante que a API Free Tier do Gemini nunca exceda o limite de requisições por minuto (RPM) e previne timeouts por tamanho excessivo do payload.
* **Uso**: `python -m app.vectorstore.populate`
* **Limpeza Automática**: O script limpa registros duplicados da coleção antes de iniciar uma nova carga, evitando duplicidade de dados caso seja executado mais de uma vez.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants