CodebaseQA is designed as a local-first, privacy-focused RAG (Retrieval Augmented Generation) system for codebases. It is split into a Python backend (for ML/RAG capabilities) and a Next.js frontend (for a modern UI).
graph TD
User[User] -->|Browser| Web[Next.js App]
Web -->|HTTP/REST| API[FastAPI Server]
subgraph Backend
API -->|Parse| Parser[Tree-sitter Service]
API -->|Embed| Embedder[OpenAI/Local Embedding]
API -->|Store| VectorDB[(ChromaDB)]
API -->|Query| LLM[LLM Service]
Parser -->|Chunks| Embedder
Embedder -->|Vectors| VectorDB
LLM <-->|Context| VectorDB
end
subgraph Data
VectorDB
SQLite[(Metadata DB)]
end
- Repo Manager: Handles cloning and file system operations
- Indexing Service: Orchestrates parsing, chunking, and embedding
- Chat Service: Manages RAG pipeline and streaming responses
- Query Expansion: Generates multiple variations of user query
- Hybrid Search: Combines vector similarity with keyword matching (BM25-like)
- Re-ranking: Uses LLM to re-rank top chunks for better precision
- Context Building: Formats code blocks with syntax highlighting
- SQLite: Stores repo metadata, file tree, and chat history
- ChromaDB: Stores vector embeddings of code chunks
To leverage Python's rich ML ecosystem (Tree-sitter, LangChain/LlamaIndex compatibility) while keeping the UI performant and modern with React/Next.js.
Regex-based chunking fails for code. Tree-sitter gives us semantic understanding of code structure (functions, classes) for better chunk boundaries.
Code retrieval requires exact keyword matching (for variable names) + semantic understanding (for "how does X work"). We combine both to reduce hallucinations.
Dependency graph generation is deterministic-first: the backend extracts import relationships from indexed repository files, computes node/edge metrics, and prunes large graphs with stable ranking so repeated runs remain consistent. For dense repositories, Graph V2.1 supports adaptive module-first entry, scoped file drill-down, and ranked edge budgets for progressive edge reveal. Optional LLM enrichment is used only for concise node descriptions, never as the primary structure source.