Spaces:
Running on Zero
A newer version of the Gradio SDK is available: 6.22.0
ποΈ Architecture Overview
System Architecture
High-level system architecture diagram illustrating the complete RAG pipeline flow
Detailed Component View
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β User Interface β
β (Streamlit Web App) β
β app.py β
βββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β RAG Pipeline β
β (rag_pipeline.py) β
β β
β ββββββββββββββββββ ββββββββββββββββ β
β β System Prompt β β QA Chain β β
β β Template βββββββΆβ (LangChain) β β
β ββββββββββββββββββ ββββββββ¬ββββββββ β
βββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββ
β
βββββββββββββββ΄ββββββββββββββ
βΌ βΌ
βββββββββββββββββββββββββ ββββββββββββββββββββββββ
β Vector Store β β LLM Handler β
β (vectorstore.py) β β (llm_handler.py) β
β β β β
β βββββββββββββββββββ β β βββββββββββββββββ β
β β ChromaDB β β β β Ollama β β
β β (Embeddings) β β β β (llama3.2) β β
β βββββββββββββββββββ β β βββββββββββββββββ β
β β β β
β βββββββββββββββββββ β ββββββββββββββββββββββββ
β β HuggingFace β β
β β Embeddings β β
β β (all-MiniLM) β β
β βββββββββββββββββββ β
βββββββββββββββββββββββββ
β²
β
βββββββββββββ΄βββββββββββββ
β Document Processor β
β (document_processor.py)β
β β
β ββββββββββββββββββββ β
β β PDF Loader β β
β β DOCX Loader β β
β β HTML Loader β β
β β Text Loader β β
β ββββββββββββββββββββ β
β β
β ββββββββββββββββββββ β
β β Text Splitter β β
β β (Chunking) β β
β ββββββββββββββββββββ β
ββββββββββββββββββββββββββ
β²
β
βββββββββββββ΄βββββββββββββ
β Source Documents β
β data/documents/ β
β β
β β’ Resume.pdf β
β β’ LinkedIn.html β
β β’ Projects.docx β
β β’ ... β
ββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Configuration Layer β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β config.yaml env.template (.env) β
β ββ profile ββ OLLAMA_BASE_URL β
β ββ llm ββ CHROMA_PERSIST_DIR β
β ββ embeddings ββ DOCUMENTS_DIR β
β ββ vectorstore ββ LOG_LEVEL β
β ββ document_proc ββ API_KEYS (optional) β
β ββ rag β
β ββ ui β
β ββ logging β
β β
β (config_loader.py) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Data Flow
1οΈβ£ Indexing Phase (One-time Setup)
Documents β Load β Chunk β Build Indexes
β β β β
resume.pdf PyPDF Split βββββββββββββββββββββββββββββββ
linkedin.html BS4 into β BM25 Index (keyword) β
projects.docx docx chunks β ./bm25_index/ β
βββββββββββββββββββββββββββββββ€
β Vector Index (semantic) β
β ./chroma_db/ (ChromaDB) β
βββββββββββββββββββββββββββββββ
Command: python -m src.build_vectorstore
Strategy Options:
--strategy bm25_vector- Build both indexes (default, recommended)--strategy vector- Vector index only--strategy bm25- BM25 index only
2οΈβ£ Query Phase (Runtime) - WITH HYBRID SEARCH
User Question
β
βββββββββββββββββββββββββββββββββββββββ
β Extract Chat History (if enabled) β
β β’ Format previous Q&A pairs β
β β’ Truncate by turns/tokens β
β β’ Include in context β
ββββββββββββββ¬βββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββ
β Load Main Document (if enabled) β
β β’ Check cache validity β
β β’ Auto-detect format β
β β’ Count tokens β
β β’ Summarize if needed β
ββββββββββββββ¬βββββββββββββββββββββββββ
β
[Main Doc Content]
β
βββββββββββββββββββββββββββββββββββββββ
β β
βββββββββββββββββββββββββββββββββββββββ Main Doc (Priority)
β Hybrid Retrieval Strategy β β
β β [Always Available]
β βββββββββββββββ βββββββββββββββ β [10k tokens max]
β β BM25 β β Vector β β
β β (keyword) β β (semantic) β β
β ββββββββ¬βββββββ ββββββββ¬βββββββ β
β β β β
β βββββββββ¬βββββββββ β
β β β
β Reciprocal Rank Fusion (RRF) β
β (70% vector, 30% BM25) β
ββββββββββββββββββ¬βββββββββββββββββββββ
β
[Retrieved Context]
β
βββββββββββ¬ββββββββββββββββββββ
β
Construct Prompt:
System Prompt β Chat History β Main Doc β Retrieved Context β Question
β
Send to LLM (Ollama/Groq)
β
Generate Answer (streaming)
β
Response Enhancer
β’ Detect negative phrases
β’ Rewrite positively
β’ Fix markdown formatting
β’ Add forward-looking closings
β
Display in Streamlit UI (with source citations)
Component Details
π Main Document Integration
The Main Document feature ensures critical profile information is always available in the LLM context, regardless of VectorDB retrieval quality.
MainDocumentLoader
βββ Format Auto-Detection
β βββ Markdown (.md) β LangChain TextLoader
β βββ Plain Text (.txt) β LangChain TextLoader
β βββ PDF (.pdf) β Existing PDF loader
β βββ Word (.docx) β Existing DOCX loader
β βββ HTML (.html) β Existing HTML loader
β
βββ Token Management
β βββ Counting: tiktoken (cl100k_base encoding)
β βββ Max Limit: 10,000 tokens (configurable)
β βββ Truncation: Smart token-based trimming
β βββ Summarization: LLM-based if exceeds limit
β
βββ Caching Strategy
β βββ File hash-based invalidation (MD5)
β βββ Configurable check interval (60s default)
β βββ Automatic reload on file changes
β
βββ Integration Point
βββ Positioned BEFORE VectorDB context (high priority)
Architecture Flow:
Main Document (Priority Context)
β
[Essential Info Always Available]
β
VectorDB Retrieval (Additional Context)
β
[Supplementary Information]
β
Combined Context β LLM β Response
Benefits:
- β Critical information never missed by retrieval
- β Auto-format detection (no manual config)
- β Intelligent token management with LLM summarization
- β Efficient caching for performance
- β Graceful degradation if unavailable
Note: The system also supports chat history for conversational context. Previous Q&A pairs are included in the prompt (after system prompt, before main document) with configurable truncation by turns or tokens. Responses are post-processed to improve tone, remove negative language, and fix markdown formatting.
π Document Processing Pipeline
DocumentProcessor
βββ Supported Formats
β βββ PDF β pypdf
β βββ Word β python-docx
β βββ HTML β BeautifulSoup4
β βββ Text/MD β LangChain TextLoader
β
βββ Chunking Strategy
β βββ Size: 1000 chars (configurable)
β βββ Overlap: 200 chars (configurable)
β βββ Separators: ["\n\n", "\n", ". ", " ", ""]
β
βββ Output: List[Document]
βββ Each with content + metadata
π Retrieval Strategy System
The retrieval system uses a pluggable strategy pattern for extensibility.
RetrieverFactory
βββ Registered Strategies
β βββ "vector" β VectorStrategy (semantic search)
β βββ "bm25" β BM25Strategy (keyword search)
β βββ "bm25_vector" β BM25VectorStrategy (hybrid)
β βββ (future: "page_index", "graph_vector")
β
βββ Strategy Interface (BaseRetrieverStrategy)
βββ build_index(documents) β Build/update index
βββ load_index() β Load from disk
βββ retrieve(query, k) β Get relevant docs
βββ as_retriever() β LangChain compatible
Hybrid Search (BM25 + Vector)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β BM25VectorStrategy β
β β
β βββββββββββββββββββββββ βββββββββββββββββββββββββββ β
β β BM25Retriever β β VectorRetriever β β
β β (keyword match) β β (semantic match) β β
β β β β β β
β β β’ Exact terms β β β’ Meaning/context β β
β β β’ Abbreviations β β β’ Synonyms β β
β β β’ Proper nouns β β β’ Related concepts β β
β ββββββββββββ¬βββββββββββ βββββββββββββ¬ββββββββββββββ β
β β (k=10) β (k=10) β
β ββββββββββββ¬ββββββββββββββββββββ β
β β β
β Reciprocal Rank Fusion (RRF) β
β weights: {vector: 0.7, bm25: 0.3} β
β β β
β Top K results (k=4) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
RRF Formula: score(d) = Ξ£ (weight Γ 1/(k + rank(d)))
π§ Vector Store Architecture
VectorStoreManager
βββ Embedding Model
β βββ sentence-transformers/all-MiniLM-L6-v2
β βββ Dimension: 384
β βββ Speed: ~2000 sentences/sec (CPU)
β βββ Quality: Good for semantic search
β
βββ ChromaDB
β βββ Type: Persistent (SQLite)
β βββ Location: ./chroma_db/
β βββ Collection: profile_documents
β βββ Indexing: HNSW (approximate NN)
β
βββ Retrieval
βββ Search Type: Similarity (or MMR)
βββ Top K: 10 (before fusion)
βββ Distance: Cosine similarity
π BM25 Store Architecture
BM25Store
βββ Algorithm: BM25Okapi (rank-bm25)
β
βββ Tokenization
β βββ "simple": Whitespace + punctuation split
β βββ "nltk": NLTK word_tokenize (optional)
β
βββ Persistence
β βββ Location: ./bm25_index/
β βββ Format: Pickle (index + documents)
β βββ Metadata: JSON (hash, stats)
β
βββ Retrieval
βββ Top K: 10 (before fusion)
βββ Scoring: BM25 term frequency
π€ LLM Integration
LLMHandler
βββ Provider Support
β βββ Ollama (Local)
β β βββ Base URL: http://localhost:11434
β β βββ Protocol: HTTP/REST API
β β βββ Auto-detected if no API key
β β
β βββ Groq (Cloud)
β βββ Base URL: https://api.groq.com/openai/v1
β βββ Protocol: OpenAI-compatible API
β βββ Requires GROQ_API_KEY env var
β
βββ Model Options (Ollama)
β βββ llama3.2:3b (Recommended)
β βββ phi3:mini
β βββ gemma2:2b
β βββ llama3.1:8b (with GPU)
β
βββ Model Options (Groq)
β βββ openai/gpt-oss-120b
β βββ llama-3.3-70b-versatile
β βββ llama-3.1-8b-instant
β βββ mixtral-8x7b-32768
β βββ gemma2-9b-it
β
βββ Parameters
βββ Temperature: 0.7
βββ Max Tokens: 800 (increased for better formatting)
βββ Top P: 0.9
βββ Context Window: Model-dependent (8192-128k tokens)
π RAG Chain
RAGPipeline
βββ Retrieval Strategy
β βββ RetrieverFactory.create(strategy_name)
β βββ "vector" β Vector-only retriever
β βββ "bm25" β BM25-only retriever
β βββ "bm25_vector" β Fusion retriever (default)
β
βββ Prompt Template Structure
β βββ System Prompt (from config)
β βββ Chat History (formatted previous Q&A pairs)
β βββ Main Document (priority context, always available)
β βββ Retrieved Context (from strategy)
β βββ User Question
β
βββ LLM
β βββ Ollama or Groq (auto-detected or configured)
β
βββ Output
βββ Answer (post-processed for tone/formatting, streaming support)
βββ Source Documents (citations)
Configuration Hierarchy
1. Environment Variables (.env)
βββ Override config.yaml values
βββ Secrets (API keys)
βββ Runtime settings (ports, URLs)
β
2. config.yaml
βββ Application defaults
βββ Model selection
βββ Retrieval strategy (vector, bm25, bm25_vector)
βββ RAG parameters
β
3. Code Defaults
βββ Fallback values if config missing
Retrieval Configuration
retrieval:
strategy: "bm25_vector" # Which strategy to use
final_k: 4 # Documents returned to LLM
vector:
search_type: "similarity" # or "mmr"
k: 10 # Docs before fusion
bm25:
k: 10 # Docs before fusion
persist_path: "./bm25_index"
tokenizer: "simple"
fusion:
algorithm: "rrf" # Reciprocal Rank Fusion
rrf_k: 60 # RRF constant
weights:
vector: 0.7
bm25: 0.3
Chat History Configuration
chat:
enable_history: true # Enable conversation context
max_history_turns: 10 # Max Q&A pairs to include
max_history_tokens: 2000 # Token limit for history
RAG Configuration
rag:
enhance_responses: true # Enable post-processing enhancement
include_sources: true # Show source citations
source_max_length: 150 # Max length of source preview
Deployment Architecture
Local Development
ββββββββββββββββββββ
β Developer β
β Machine β
β β
β ββββββββββββββ β
β β Ollama β β β Port 11434 (optional)
β β Server β β
β ββββββββββββββ β
β β
β ββββββββββββββ β
β β Groq API β β β https://api.groq.com (optional)
β β (Cloud) β β
β ββββββββββββββ β
β β
β ββββββββββββββ β
β β Streamlit β β β Port 8501
β β App β β
β ββββββββββββββ β
β β
β ββββββββββββββ β
β β ChromaDB β β β ./chroma_db/
β β (local) β β
β ββββββββββββββ β
β β
β ββββββββββββββ β
β β BM25 Index β β β ./bm25_index/
β β (local) β β
β ββββββββββββββ β
ββββββββββββββββββββ
Hugging Face Spaces
βββββββββββββββββββββββββββββββββ
β HF Spaces Container β
β β
β βββββββββββββββββββββββββββ β
β β Dockerfile β β
β β ββ Install Ollama β β
β β ββ Pull Model β β
β β ββ Build Indexes β β
β β ββ Start Services β β
β βββββββββββββββββββββββββββ β
β β
β ββββββββββββ ββββββββββββ β
β β Ollama β βStreamlit β β
β β Server β β App β β
β ββββββββββββ ββββββββββββ β
β β
β βββββββββββββββββββββββββββ β
β β Persistent Storage β β
β β ββ chroma_db/ β β
β β ββ bm25_index/ β β
β βββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββ
β
β HTTPS
β
ββββββββββ΄βββββββββββ
β Public Users β
β (Recruiters) β
βββββββββββββββββββββ
Build & Packaging
UV + Hatchling + Versioningit
pyproject.toml
βββ [build-system]
β βββ requires: ["hatchling", "versioningit"]
β βββ build-backend: "hatchling.build"
β
βββ [project]
β βββ name: "profillybot"
β βββ version: <from git tags via versioningit>
β βββ dependencies: [...]
β
βββ [tool.versioningit]
β βββ Read git tags (v0.1.0, v0.2.0, etc.)
β βββ Generate version string
β βββ Write to src/_version.py
β
βββ [tool.ruff]
βββ Linting rules
βββ Formatting config
Version from Git Tags
# Tag release
git tag v0.1.0
git push origin v0.1.0
# Version automatically set
python -c "from src import __version__; print(__version__)"
# Output: 0.1.0
# Development version (after tag)
# Output: 0.1.0+5.g1a2b3c4 (5 commits after v0.1.0)
Code Quality Pipeline
Developer Writes Code
β
βββββββββββββββββββββ
β Pre-commit β
β (Optional) β
βββββββββββ¬ββββββββββ
β
βββββββββββββββββββββ
β Ruff Check β β Linting
β Ruff Format β β Formatting
βββββββββββ¬ββββββββββ
β
βββββββββββββββββββββ
β Git Commit β
βββββββββββ¬ββββββββββ
β
βββββββββββββββββββββ
β Push to GitHub β
βββββββββββ¬ββββββββββ
β
βββββββββββββββββββββ
β GitHub Actions β
β β’ Lint Check β
β β’ Format Check β
β β’ Tests (future) β
βββββββββββββββββββββ
Module Dependencies
app.py
ββ src.config_loader
ββ src.rag_pipeline
ββ src.llm_handler (provider detection)
ββ src.response_enhancer (post-stream enhancement)
ββ src.main_document_loader (token counting for history)
ββ streamlit (UI, chat history management)
src.rag_pipeline
ββ src.config_loader
ββ src.llm_handler
ββ src.retrieval (RetrieverFactory, strategies)
ββ src.main_document_loader
ββ src.response_enhancer
ββ langchain (LCEL chains)
src.retrieval
ββ src.retrieval.base (BaseRetrieverStrategy)
ββ src.retrieval.factory (RetrieverFactory)
ββ src.retrieval.fusion (RRF, FusionRetriever)
ββ src.retrieval.stores.bm25_store
ββ src.retrieval.strategies.*
src.retrieval.strategies.vector
ββ src.vectorstore
ββ src.retrieval.base
src.retrieval.strategies.bm25
ββ src.retrieval.stores.bm25_store
ββ rank_bm25
src.retrieval.strategies.bm25_vector
ββ src.retrieval.strategies.vector
ββ src.retrieval.strategies.bm25
ββ src.retrieval.fusion
src.main_document_loader
ββ src.config_loader
ββ src.document_processor
ββ src.llm_handler
ββ tiktoken
ββ pathlib, hashlib, time
src.response_enhancer
ββ src.config_loader
ββ re (regex pattern matching)
src.vectorstore
ββ src.config_loader
ββ chromadb
ββ langchain_huggingface
src.llm_handler
ββ src.config_loader
ββ langchain_community.llms (Ollama)
ββ langchain_groq (Groq support)
src.document_processor
ββ src.config_loader
ββ pypdf
ββ python-docx
ββ beautifulsoup4
ββ langchain
src.config_loader
ββ pyyaml
ββ python-dotenv
src.build_vectorstore
ββ src.document_processor
ββ src.retrieval (RetrieverFactory)
ββ src.vectorstore
Performance Characteristics
Indexing (One-time)
| Documents | Chunks | Embedding Time | ChromaDB Insert | Total |
|---|---|---|---|---|
| 5 PDFs | ~100 | ~5 seconds | ~1 second | ~6s |
| 20 PDFs | ~400 | ~20 seconds | ~2 seconds | ~22s |
| 50 PDFs | ~1000 | ~50 seconds | ~5 seconds | ~55s |
Query (Runtime)
| Step | Time (CPU) | Time (GPU) | Notes |
|---|---|---|---|
| Chat history extraction | <1ms | <1ms | Token counting overhead |
| Main doc loading | <1ms | <1ms | Cached after first load |
| Embed query | 50ms | 10ms | Sentence transformers |
| Vector search | 10-50ms | 10-50ms | ChromaDB HNSW |
| BM25 search | 5-20ms | 5-20ms | In-memory index |
| Fusion (RRF) | <1ms | <1ms | Rank combination |
| LLM inference (Ollama) | 2-5s | 0.5-1s | Local model |
| LLM inference (Groq) | 0.5-2s | N/A | Cloud API |
| Response enhancement | <10ms | <10ms | Post-processing |
| Total (Ollama) | 2-5s | 0.5-1s | |
| Total (Groq) | 0.6-2s | N/A | Faster cloud option |
Memory Usage
| Component | RAM | Disk |
|---|---|---|
| Streamlit | ~200MB | - |
| Ollama (llama3.2:3b) | ~2GB | ~2GB |
| ChromaDB | ~100MB | ~50MB per 1k docs |
| BM25 Index | ~50MB | ~10MB per 1k docs |
| Embeddings | ~500MB | ~500MB |
| Chat History | ~1-10MB | - |
| Response Enhancer | <1MB | - |
| Total | ~3GB | ~3GB |
Security Architecture
User Input
β
βββββββββββββββββββββββ
β Input Validation β β Length limits
β (Streamlit) β β Character filtering
βββββββββββ¬ββββββββββββ
β
βββββββββββββββββββββββ
β RAG Pipeline β β Context isolation
βββββββββββ¬ββββββββββββ
β
βββββββββββββββββββββββ
β LLM (Local) β β No external API calls
β β β Data stays local
βββββββββββββββββββββββ
Secrets Management:
ββ .env (local)
ββ .gitignore (.env excluded)
ββ HF Spaces Secrets (cloud)
Extensibility Points
π Plugin Architecture
# Easy to extend:
# 1. New document types
DocumentProcessor.load_custom_format()
# 2. New LLM providers
LLMHandler.get_openai_llm()
LLMHandler.get_anthropic_llm()
# Already supports: Ollama (local), Groq (cloud)
# 3. New retrieval strategies (extensible system!)
@RetrieverFactory.register("page_index")
class PageIndexStrategy(BaseRetrieverStrategy):
"""Vision-based document retrieval (ColPali)"""
...
@RetrieverFactory.register("graph_vector")
class GraphVectorStrategy(BaseRetrieverStrategy):
"""Knowledge graph + vector hybrid"""
...
# 4. New UI features
app.py β add_authentication()
app.py β add_analytics()
# Already supports: Chat history, provider switching, streaming responses
# 5. New embedding models
VectorStoreManager(embedding_model="...")
# 6. New fusion algorithms
# Add to src/retrieval/fusion.py
def custom_fusion(results_list, weights):
...
# 7. New response enhancement patterns
# Edit src/response_enhancer.py
ResponseEnhancer.negative_patterns.append((pattern, rewrite_func))
# 8. Custom chat history strategies
# Modify truncate_chat_history() in app.py
# Add custom truncation logic (e.g., importance-based)
Adding a New Retrieval Strategy
- Create
src/retrieval/strategies/my_strategy.py - Implement
BaseRetrieverStrategyinterface - Register with
@RetrieverFactory.register("my_strategy") - Add config section in
config.yaml - Import in
src/retrieval/strategies/__init__.py
from src.retrieval import RetrieverFactory
from src.retrieval.base import BaseRetrieverStrategy
@RetrieverFactory.register("my_strategy")
class MyStrategy(BaseRetrieverStrategy):
@property
def name(self) -> str:
return "my_strategy"
def build_index(self, documents): ...
def load_index(self) -> bool: ...
def retrieve(self, query, k=4): ...
def as_retriever(self, **kwargs): ...
This architecture prioritizes:
- β Simplicity (easy to understand)
- β Modularity (easy to extend)
- β Performance (optimized for small-medium datasets)
- β Privacy (local processing)
- β Deployability (cloud-ready)