A production-grade, multi-agent RAG chatbot that answers any question about GitLab by retrieving answers directly from the official GitLab documentation β grounded, cited, and hallucination-free. Built with CrewAI, ChromaDB, and local sentence embeddings. Total running cost: $0.00.
streamlit run app.pyThe Streamlit UI showcases the full agentic pipeline with a recruiter-ready interface:
| Section | What you see |
|---|---|
| Hero banner | Title, tagline, and tech badges |
| Feature cards | Six cards explaining the architecture before you start chatting |
| Architecture strip | Full pipeline flow as a single visual line |
| Sidebar | Pipeline diagram Β· Tech stack Β· System stats Β· Clickable sample questions |
| Chat | Orange user bubbles Β· Fox-avatar bot cards Β· Source chips Β· Pipeline route pill Β· Response time |
User Query
β
βΌ
βββββββββββββββββββββββ
β Smart Router β < 4 words or ambiguous β Full pipeline
β β Clear question (5+ words) β Simple pipeline
βββββββββββ¬ββββββββββββ
β
βββββββ΄βββββββββββββββββββββββββββββββββββ
β FULL PIPELINE (vague queries) β
β Intent Classify βββ (async parallel) β
β Query Rewrite ββββ asyncio.gather() β
βββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββ
β Retriever Agent β semantic_search / filtered_search / multi_query_search
β (CrewAI) β ChromaDB cosine similarity Β· RRF fusion
βββββββββββ¬ββββββββββββ
β heuristic validation (relevance β₯ 0.40)
βΌ
βββββββββββββββββββββββ
β Synthesiser Agent β Writes grounded answer with citations
β (CrewAI) β Flags deprecated features Β· Never extrapolates
βββββββββββ¬ββββββββββββ
β
βΌ
Cited Answer + Source URLs
- Async parallel pre-processing β intent classification and query rewriting run
with
asyncio.gather(), cutting pre-processing from ~8s to ~4s. - Heuristic validation replaces a full LLM-based validator agent β chunks below 0.40 cosine relevance are dropped before the synthesiser sees them, saving 5β8s per query with no quality loss.
- Smart routing skips the full pipeline for clear, well-formed questions, reducing average latency by 30β50%.
- BGE asymmetric embeddings β query prefix
"Represent this sentence for searching relevant passages: "is prepended to queries but not documents, improving retrieval accuracy over symmetric models.
| Layer | Technology | Notes |
|---|---|---|
| UI | Streamlit 1.35+ | Custom CSS Β· Chat interface Β· Feature showcase |
| Agents | CrewAI | Sequential crew Β· @tool decorator |
| LLM | OpenRouter (free tier) | LiteLLM routing Β· openrouter/ prefix Β· 3Γ retry |
| Embeddings | BAAI/bge-small-en-v1.5 | 384-dim Β· local CPU Β· disk-cached |
| Vector DB | ChromaDB | Persistent local client Β· cosine distance |
| Doc processing | LangChain Β· tiktoken | Header-aware chunking Β· token counting |
| Config | Pydantic BaseSettings | .env β typed singleton |
| Logging | loguru | Rotating file logs |
git-guide/
βββ app.py # Streamlit UI β start here
βββ config/
β βββ settings.py # Pydantic settings singleton
β βββ llm_client.py # OpenRouter client + factory functions
βββ phase1_ingestion/ # One-time data pipeline
β βββ run_ingestion.py # Orchestrator
β βββ scraper.py # Git sparse-checkout downloader
β βββ chunker.py # Markdown β DocChunk
β βββ embedder.py # Local BAAI/bge embeddings + cache
β βββ vector_store.py # ChromaDB wrapper
βββ phase2_agents/ # Runtime agent system
β βββ run_agents.py # CLI entry point + routing logic
β βββ crew.py # CrewAI crew definitions
β βββ parallel_pipeline.py # Async intent + rewrite
β βββ agents/
β β βββ retriever.py # Search specialist agent
β β βββ synthesiser.py # Answer writer agent
β βββ tools/
β βββ retrieval_tools.py # 4 search tools (semantic/filtered/multi/id)
βββ data/
β βββ raw/gitlab-docs/ # Downloaded GitLab .md files
β βββ processed/ # chunks.json Β· embedding_cache.json
βββ vectorstore/chroma_db/ # ChromaDB local database
βββ requirements.txt
βββ .env # API keys (copy from .env.example)
git clone https://github.com/raghavgupta/git-guide.git
cd git-guide
python -m venv venv && source venv/bin/activate
pip install -r requirements.txtcp .env.example .envEdit .env:
OPENROUTER_API_KEY=sk-or-v1-... # Free key from https://openrouter.ai/keys
OPENROUTER_MODEL=meta-llama/llama-3.1-8b-instruct:free
EMBEDDING_MODEL=BAAI/bge-small-en-v1.5This downloads the GitLab docs, chunks them, embeds them locally, and stores them in ChromaDB. Run once; subsequent runs use the embedding cache.
python -m phase1_ingestion.run_ingestion| Flag | Effect |
|---|---|
| (no flag) | Full pipeline |
--reset |
Wipe + re-index from scratch |
--skip-scrape |
Skip git clone, use existing raw files |
--verify-only |
Run 6 test queries without re-indexing |
What happens: git sparse-checkout pulls only
/doc(~80 MB, not the full 4 GB repo) β ~8,000 Markdown files β ~30,000 chunks β embedded locally β stored in ChromaDB.
streamlit run app.pyOpen http://localhost:8501. Click a sample question in the sidebar or type your own.
# Interactive REPL
python -m phase2_agents.run_agents
# Single query
python -m phase2_agents.run_agents --test-query "how do I cache npm in CI?"
# Verbose (shows all agent reasoning)
python -m phase2_agents.run_agents --verboseBefore you start chatting, the main area displays:
- A dark hero banner with tech badges
- Six feature cards explaining the system architecture
- A pipeline flow diagram
Once you send a message:
- The status widget expands and shows which pipeline route was chosen
- The answer appears in a bot card with:
- π¦ avatar
- Full markdown answer
- β‘ / π pipeline pill (simple vs. full)
- π Clickable source chips linking directly to
docs.gitlab.com - β± Response time in seconds
Sidebar shortcuts β click any of the six sample questions to submit instantly.
How do I cache npm packages in GitLab CI?
What is the difference between stages and jobs?
How do I set up a Docker-in-Docker pipeline?
How do I protect a branch in GitLab?
What are GitLab CI/CD variables and how do I use them?
How do I run SAST security scanning in my pipeline?
| Component | Cost |
|---|---|
| LLM calls (OpenRouter free tier) | $0.00 |
| Embeddings (local CPU, BAAI/bge-small) | $0.00 |
| Vector database (ChromaDB local files) | $0.00 |
| Scraping (public GitLab repo) | $0.00 |
| Total | $0.00 |
semantic_searchβ default tool; embeds the query and runs cosine similarity against all ~30,000 chunks.filtered_searchβ same, plus metadata filters (section=ci,has_code=True, etc.) for precision retrieval.multi_query_searchβ for ambiguous queries, the LLM generates 2β3 alternative phrasings, embeds all of them, and fuses results with Reciprocal Rank Fusion (RRF, k=60).get_chunk_by_idβ fetches a specific chunk by its ID for follow-up lookups.
Chunks below 0.40 cosine relevance are dropped before the synthesiser sees them.
- Multi-turn conversation memory
- Streaming token output in the UI
- Automatic re-indexing when GitLab docs update
- REST API wrapper (
FastAPI) - Docker Compose for one-command deployment
Raghav Gupta β built as a portfolio demonstration of production agentic RAG systems.
Stack: Python Β· CrewAI Β· ChromaDB Β· sentence-transformers Β· OpenRouter Β· Streamlit
