AI Codebase Engineer is a backend and search systems project for indexing GitHub repositories and answering architecture questions with file-and-line citations. It combines source-aware chunking, vector retrieval, Python dependency graphs, LLM-based answer generation, persistent caching, and an evaluation harness.
The project is designed to explore the engineering work around code search: repository ingestion, deterministic identifiers, hybrid retrieval, storage, API design, observability metrics, and reproducible evaluation.
- Clones and indexes public GitHub repositories.
- Recursively scans source files while excluding generated and vendor folders.
- Detects common programming languages and skips binary or oversized files.
- Uses Python ASTs to chunk top-level functions, async functions, and classes.
- Falls back to overlapping line windows for non-Python source files.
- Generates free local embeddings with Sentence Transformers by default.
- Supports OpenAI embeddings and deterministic fake embeddings through a configurable provider.
- Stores vectors and source metadata in persistent Chroma collections.
- Builds Python repository graphs with file, import, class, function, method, and call relationships.
- Expands vector search results through one-hop imports, calls, and parent classes.
- Generates answers locally with Ollama by default, constrained to retrieved code with enforced file-and-line citations.
- Supports OpenAI
gpt-4o-minias an optional hosted LLM provider. - Persists repository metadata, chunks, query history, and JSON cache entries in SQLite.
- Caches embeddings by content hash and answers by repository plus normalized question.
- Exposes FastAPI endpoints and a Streamlit interface.
- Evaluates Recall@5, Recall@10, citation accuracy, latency, retrieved chunk count, and cache hit rate.
- Includes Docker Compose and GitHub Actions support.
flowchart LR
User[User] --> UI[Streamlit UI]
User --> API[FastAPI API]
UI --> API
API --> Indexer[Repository Indexer]
Indexer --> Loader[Git Repository Loader]
Loader --> Scanner[Source File Scanner]
Scanner --> Chunker[AST and Sliding Window Chunker]
Chunker --> Embeddings[Embedding Service]
Embeddings --> LocalModel[Sentence Transformers]
Embeddings -. optional .-> OpenAIEmbeddings[OpenAI Embeddings API]
Embeddings --> Chroma[(Chroma Vector Index)]
Indexer --> SQLite[(SQLite Metadata and Cache)]
API --> RAG[RAG Engine]
RAG --> Retriever[Graph-Enhanced Retriever]
Retriever --> Embeddings
Retriever --> Chroma
Retriever --> Graph[NetworkX Dependency Graph]
Graph --> AST[Python AST Parser]
Retriever --> SQLite
RAG --> Ollama[Ollama Local Chat API]
RAG -. optional .-> OpenAILLM[OpenAI Chat Completions]
RAG --> SQLite
Eval[Evaluation CLI] --> Indexer
Eval --> Retriever
Eval --> RAG
Neo4j[(Neo4j Container)]
Graph -. future persistence .-> Neo4j
The active graph implementation uses NetworkX and rebuilds graphs from indexed source. Docker Compose also provisions Neo4j as a foundation for future persistent graph storage.
- Embed the user's question.
- Search Chroma for the highest-ranked chunks within the selected repository.
- Map seed chunks to dependency-graph nodes.
- Expand one hop to imported files, called functions, and parent classes.
- Load related chunks from SQLite and deduplicate by stable chunk ID.
- Format the ranked context and ask the LLM to answer using only that context.
- Return the answer with source file paths and line ranges.
| Area | Technology |
|---|---|
| API | FastAPI, Pydantic, Uvicorn |
| Frontend | Streamlit |
| Metadata and cache | SQLite, SQLAlchemy |
| Vector search | ChromaDB |
| Embeddings | Sentence Transformers (all-MiniLM-L6-v2) by default; optional OpenAI |
| Answer generation | Ollama with qwen2.5-coder:1.5b by default; optional OpenAI |
| Parsing | Python ast |
| Dependency graphs | NetworkX |
| Repository operations | GitPython |
| Testing | pytest, FastAPI TestClient |
| Infrastructure | Docker, Docker Compose, GitHub Actions |
| Optional graph service | Neo4j |
Create the environment file:
cp .env.example .envRepository indexing uses free local embeddings by default and does not require an OpenAI API key. The model is downloaded from Hugging Face the first time it is used:
EMBEDDING_PROVIDER=local
LOCAL_EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2Add OPENAI_API_KEY only when using LLM_PROVIDER=openai or
EMBEDDING_PROVIDER=openai. If OpenAI embeddings return
insufficient_quota, indexing automatically falls back to the local model.
Tests use injected models and deterministic embeddings, so they do not require
external API calls.
For free local answer generation, install Ollama and prepare the default model:
ollama serve
ollama pull qwen2.5-coder:1.5bConfigure .env:
LLM_PROVIDER=ollama
OLLAMA_MODEL=qwen2.5-coder:1.5bTo use OpenAI instead, set LLM_PROVIDER=openai and provide
OPENAI_API_KEY. The mock provider is restricted to automated tests.
Start FastAPI, Streamlit, and Neo4j:
docker compose up --buildOpen:
- Streamlit: http://localhost:8501
- FastAPI documentation: http://localhost:8000/docs
- Neo4j Browser: http://localhost:7474
Persistent repository clones, SQLite data, and Chroma indexes are stored under
data/. Neo4j uses named Docker volumes.
docker compose downUse docker compose down -v only when you also want to remove Neo4j volumes.
Python 3.11 or newer is required.
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[test]"
cp .env.example .envThe default .env.example configuration uses local embeddings. You can verify
the configured provider with:
python scripts/check_embeddings.pyThe first local run downloads all-MiniLM-L6-v2; later runs use the local
model cache.
To view the website locally, run the backend and frontend in two terminals.
Terminal 1 - start the FastAPI backend:
source .venv/bin/activate
uvicorn app.main:app --reloadTerminal 2 - start the Streamlit frontend:
source .venv/bin/activate
streamlit run frontend/streamlit_app.pyThen open the website at http://localhost:8501. The API docs are available at http://localhost:8000/docs.
Run tests:
pytest- Where is authentication handled?
- How does the API persist indexed repository metadata?
- Which functions call the token-generation service?
- What files participate in the repository indexing flow?
- Where is the database schema defined?
- What would need to change to add OAuth support?
- How are embeddings cached and invalidated?
- Which modules depend on the user model?
curl -X POST http://localhost:8000/repos/index \
-H "Content-Type: application/json" \
-d '{"repo_url":"https://github.com/owner/repository"}'Example response:
{
"repo_id": "abc123",
"files_scanned": 87,
"chunks_created": 214,
"indexing_time_seconds": 12.42
}curl -X POST http://localhost:8000/query \
-H "Content-Type: application/json" \
-d '{
"repo_id": "abc123",
"question": "How does authentication work?",
"top_k": 8
}'Example response:
{
"answer": "Authentication is handled by the login route and supporting service.",
"sources": [
{
"file_path": "app/auth/routes.py",
"start_line": 10,
"end_line": 45,
"symbol_name": "login_user"
}
]
}curl http://localhost:8000/repos/abc123curl http://localhost:8000/query/history/abc123curl http://localhost:8000/graph/abc123The graph response contains typed nodes and directed edges such as CONTAINS,
DEFINES, IMPORTS, and CALLS.
Evaluation cases use JSON Lines:
{"repo_url":"https://github.com/owner/repository","question":"Where is authentication handled?","expected_files":["app/auth/routes.py","app/auth/utils.py"]}Run the evaluation suite:
python scripts/run_eval.pyThe evaluator prints a Markdown summary and writes detailed results to
data/eval/results.json.
| Metric | Meaning |
|---|---|
| Recall@5 | Fraction of expected files represented in the first five retrieved chunks |
| Recall@10 | Fraction of expected files represented in the first ten retrieved chunks |
| Citation file accuracy | Fraction of cited files that match expected files |
| Average latency | Mean retrieval and answer latency per question |
| Average chunks retrieved | Mean amount of context returned by retrieval |
| Cache hit rate | Cache hits divided by cache lookups during the evaluation run |
The repository does not publish benchmark scores yet; metrics depend on the evaluation dataset, target repositories, model configuration, and cache state.
app/
api/ FastAPI routes and dependencies
core/ ingestion, retrieval, graph, cache, RAG, and evaluation
models/ SQLAlchemy and Pydantic models
prompts/ answer-generation prompts
frontend/ Streamlit application
scripts/ indexing and evaluation CLIs
tests/ unit and integration tests
data/ persisted repositories, indexes, database, and eval data