A production-ready semantic search application for searching through AI coding assistant (Claude Code) session history. Built with FastAPI, Sentence Transformers, ChromaDB, and React.
β Production-Ready RAG Pipeline with:
- β Dual Search Modes: Basic (fast) and Enhanced (high-quality)
- β Hybrid Search: BM25 + Vector similarity for best results
- β Cross-Encoder Reranking: Improved relevance scoring
- β Query Expansion: LLM-powered with Groq API
- β Redis Caching: 70% latency reduction for cached queries
- β Fairness Enforcement: Equal quota distribution across engineers
- β Pagination Support: Efficient result browsing
- β Query Validation: Security and input sanitization
- β Rate Limiting: Protection against abuse
- β Docker Deployment: One-command setup
- β Memory Optimized: Efficient embedding storage
- β Fixed Data Chunking: Improved message parsing logic
# Clone the repository
git clone <your-repo-url>
cd Dexicon_assignment
# Copy environment file (optional)
cp .env.example .env
# Edit .env if needed (set GROQ_API_KEY for enhanced mode)
# Start all services
docker-compose up -d
# View logs
docker-compose logs -f
# Access the application
# Frontend: http://localhost
# Backend API: http://localhost:8001Services:
- Frontend: http://localhost (port 80)
- Backend: http://localhost:8001
- Redis: localhost:6379
Stop services:
docker-compose downRebuild after changes:
docker-compose up -d --build- Python 3.9+
- Node.js 18+
- npm or yarn
- Redis (optional, for caching)
cd backend
pip install -r requirements.txtNote: First run will download the embedding model (~90MB). This may take a minute.
# Create and activate virtual environment (recommended)
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install -r backend/requirements.txt
# Set environment variables (optional)
export SEARCH_MODE=enhanced # or "basic"
export CACHE_ENABLED=true
export REDIS_URL=redis://localhost:6379/0
export GROQ_API_KEY=your_key_here # Optional, for query expansion
# Start the server
cd backend
python main.pyThe server will:
- Load session JSON files from
data/directory - Parse and create searchable chunks (based on mode)
- Generate embeddings using Sentence Transformers
- Index into ChromaDB (persistent storage)
- Initialize Redis cache (if enabled)
- Start API server at
http://localhost:8001
Switch between modes:
- Set
SEARCH_MODE=basicfor fast vector-only search - Set
SEARCH_MODE=enhancedfor hybrid search with reranking
cd frontend
npm installcd frontend
npm run devOpen http://localhost:5173 in your browser.
βββ backend/
β βββ basic/ # Basic search implementation
β β βββ __init__.py
β β βββ search_engine.py # Vector-only search
β β
β βββ enhanced/ # Enhanced search (hybrid + reranking)
β β βββ __init__.py
β β βββ enhanced_search.py # Hybrid search + reranking
β β βββ enhanced_chunking.py # Advanced chunking strategies
β β βββ knowledge_graph.py # Knowledge graph for entity-aware retrieval
β β
β βββ shared/ # Shared utilities
β β βββ __init__.py
β β βββ data_loader.py # JSON parsing & chunking
β β βββ models.py # Pydantic schemas
β β βββ config.py # Configuration management
β β βββ cache.py # Redis caching layer
β β βββ fairness.py # Equal quota enforcement
β β βββ evaluation.py # Quality metrics
β β
β βββ tests/ # Test suite
β β βββ __init__.py
β β βββ test_knowledge_graph.py # KG building & visualization
β β βββ test_enhanced_retrieval.py # Step-by-step retrieval testing
β β βββ test_vector_scores.py # Basic vs Enhanced comparison
β β βββ investigate_negative_scores.py # Score debugging
β β βββ knowledge_graph_visualization.png # Full graph visualization
β β βββ knowledge_graph_simplified.png # Simplified graph view
β β
β βββ main.py # FastAPI application
β βββ Dockerfile # Backend container
β βββ requirements.txt
β βββ README.md # Backend documentation
β
βββ frontend/
β βββ src/
β β βββ App.jsx # Main application
β β βββ components/ # React components
β β β βββ SearchBar.jsx
β β β βββ ResultsList.jsx
β β β βββ FilterPanel.jsx
β β β βββ ...
β β βββ hooks/ # Custom hooks
β β βββ useSearch.js
β βββ Dockerfile # Frontend container
β βββ nginx.conf # Nginx configuration
β βββ package.json
β
βββ data/ # Session JSON files
β βββ andrew_wang_sessions.json
β βββ daniel_lin_sessions.json
β βββ diana_lu_sessions.json
β
βββ docker-compose.yml # Docker Compose configuration
βββ .gitignore # Git ignore rules
βββ README.md # This file
Search for relevant coding sessions with pagination and filters.
curl -X POST http://localhost:8001/api/search \
-H "Content-Type: application/json" \
-d '{
"query": "how to handle large file uploads",
"limit": 10,
"offset": 0,
"filters": {
"engineer": "andrewwang",
"project": "video-ingester",
"language": "Go"
}
}'Response includes:
results: Array of search resultstotal: Total number of resultsoffset,limit,has_more: Pagination infoquery_time_ms: Query execution timequery_expanded: Expanded query (if enhanced mode)reranked: Whether results were rerankeddistribution: Engineer distribution stats (fairness)
List all engineers in the dataset.
List all projects in the dataset.
Get dataset statistics.
Get Redis cache statistics (hits, misses, hit rate).
Invalidate cached search results.
- Chunking: Simple Q&A pairs (no overlap)
- Model:
all-MiniLM-L6-v2(384-dim, fast) - Search: Pure vector search (cosine similarity)
- Speed: 50-200ms per query
- Best For: Fast queries, clear semantic matches
- Chunking: Overlapping windows (2 Q&A pairs + context, overlap=1)
- Model:
all-mpnet-base-v2(768-dim, better quality) - Search: Hybrid (70% vector + 30% BM25) + Knowledge Graph (20% boost)
- Reranking: Cross-encoder for final ordering
- Query Expansion: Groq LLM for intelligent synonym expansion
- Knowledge Graph: Entity-aware retrieval with relationship traversal
- Speed: 500-1000ms per query (50-200ms for cached)
- Best For: Complex queries, maximum quality, entity-specific searches
- Data Loading: Parse JSON session files, extract Q+A conversation pairs
- Chunking:
- Basic mode: Simple Q&A pairs
- Enhanced mode: Overlapping windows with context
- Embedding: Generate vectors using Sentence Transformers
- Indexing: Store embeddings in ChromaDB with metadata
- Search:
- Basic: Vector similarity only
- Enhanced: Hybrid search (BM25 + Vector + Knowledge Graph) β Reranking
- Post-Processing: Fairness distribution, pagination, caching
- Zero API setup: No keys, no costs, works offline
- Fast inference: ~14ms per query on CPU
- Good quality: MiniLM achieves ~90% of larger models' performance
- Semantic understanding: Captures meaning beyond keywords
- Embedded: Just a Python library, no server to run
- Metadata filtering: Built-in support for engineer/project filters
- Fast: Uses HNSW for approximate nearest neighbor search
- Simple: Perfect for prototypes and small-to-medium datasets
The sample data includes sessions from 3 engineers working at a video streaming company:
| Engineer | Role | Topics |
|---|---|---|
| Andrew Wang | Staff Backend Engineer | Video encoding, S3 uploads, Celery |
| Daniel Lin | Senior Full-Stack Engineer | WebRTC, video validation, FFprobe |
| Diana Lu | Senior Frontend Engineer | HLS streaming, iOS PiP, SwiftUI |
Languages: Python, Go, TypeScript, Swift Frameworks: FastAPI, Chi, Next.js, React, SwiftUI
Basic Mode: Simple Q&A pairs
- Each user query + assistant response = one chunk
- ~53 chunks from dataset
- Fast indexing and retrieval
Enhanced Mode: Overlapping windows
- Sliding window of 2 Q&A pairs with 1-pair overlap
- Includes context from previous pairs
- ~53 chunks (same count as basic, but with context)
- Better context preservation, no boundary issues
- Optimal balance between granularity and context
Why Q+A pairs?
- Semantic completeness: Question and answer together carry full meaning
- Better retrieval: Search finds complete discussions, not fragments
- Display-ready: Can show conversation context directly
- Fixed Data Chunking: Improved message parsing to handle all assistant responses, even after tool invocations
- Memory Optimization: Embeddings stored in ChromaDB only, not duplicated in memory
- Better Embedding Model: Switched from CodeBERT to all-mpnet-base-v2 for better Q&A understanding
- Embedding Normalization: Fixed negative semantic scores by normalizing embeddings for proper cosine distance
- Knowledge Graph: Implemented entity extraction and relationship-based retrieval
- Fairness Enforcement: Implements "equal quota" rule for balanced engineer representation
- Security: Query validation, XSS prevention, rate limiting
- Performance: Redis caching reduces latency by 70% for repeated queries
- Dark theme: Matches IDE aesthetic, easier on eyes for developers
- Animated placeholders: Show example queries to guide users
- Score badges: Visual indicator of relevance
- Staggered animations: Results feel more dynamic and responsive
- Minimal filters: Only most useful (engineer, project) to avoid clutter
The easiest way to deploy is using Docker Compose:
docker-compose up -dThis starts:
- Backend: FastAPI server with enhanced search
- Frontend: React app served via Nginx
- Redis: Caching layer
Create a .env file:
SEARCH_MODE=enhanced # or "basic"
GROQ_API_KEY=your_key_here # Optional, for query expansion
CACHE_ENABLED=true
REDIS_URL=redis://redis:6379/0- Use persistent ChromaDB storage (already configured in Docker)
- Set GROQ_API_KEY for enhanced query expansion
- Configure CORS for your domain in
backend/main.py - Add authentication if needed
- Use environment variables for sensitive data
- Monitor Redis for cache performance
- Consider Pinecone/Weaviate for larger datasets (>100K chunks)
The project includes a comprehensive test suite in backend/tests/:
cd backend
python3 tests/test_knowledge_graph.py- Builds knowledge graph from chunks
- Visualizes entities and relationships
- Shows graph statistics
- Tests entity extraction and graph retrieval
- Generates visualization PNGs
cd backend
python3 tests/test_enhanced_retrieval.py "your query here"- Shows step-by-step retrieval process
- Displays Vector, BM25, and Graph search results
- Shows score combination
- Demonstrates reranking impact
cd backend
python3 tests/test_vector_scores.py "video encoding optimization"- Compares Basic vs Enhanced mode
- Explains score calculations
- Shows performance differences
cd backend
python3 tests/investigate_negative_scores.py- Investigates embedding normalization
- Tests different chunking strategies
- Analyzes query expansion impact
- "video encoding optimization" - Should find Andrew's encoding work
- "file upload S3" - Should find multipart upload discussions
- "error handling" - Should find multiple engineers' error handling
- "React streaming" - Should find Diana's React work
- "memory optimization" - Should find performance discussions
- Open http://localhost:5173
- Try different search queries
- Test filters (Engineer, Project)
- Test pagination (change limit, use offset)
- Verify cache (same query twice - second should be faster)
The test suite generates two graph visualizations:
- Full Graph (
tests/knowledge_graph_visualization.png): Complete entity-relationship graph - Simplified Graph (
tests/knowledge_graph_simplified.png): Focus on engineers, projects, and technologies
View these to understand:
- Entity relationships (engineers β projects β technologies)
- Concept connections
- How graph retrieval works
- Query Time: 50-200ms
- Precision@5: ~0.65
- Recall@5: ~0.64
- Best For: Fast, simple queries
- Query Time: 500-1000ms (with caching: 50-200ms for cached)
- Precision@5: ~0.70-0.78
- Recall@5: ~0.72-0.75
- Best For: Complex queries, maximum quality
- Hit Rate: ~60-80% for repeated queries
- Latency Reduction: 70% for cached queries
- TTL: 1 hour (configurable)
- β Query validation and sanitization
- β XSS prevention
- β SQL injection protection
- β Rate limiting (30 requests/minute per IP)
- β CORS configuration
- β Input length limits
- ChromaDB embeddings are regenerated on restart (unless persistent storage is used)
- Enhanced mode requires Groq API key for query expansion (fallback available)
- Rate limiting requires slowapi package
- Redis is optional but recommended for production
Current Implementation: β Knowledge graph is already implemented in Enhanced Mode!
- Extracts entities: Engineers, Projects, Technologies, Concepts
- Builds relationships: works_on, uses, discussed, related_to
- Provides 20% boost in hybrid search
- Enables entity-aware retrieval
Why Knowledge Graphs? A knowledge graph significantly enhances retrieval by modeling relationships between entities:
Entities to Model:
- Engineers (Andrew, Daniel, Diana)
- Projects (video-encoder, video-ingester, etc.)
- Technologies (Python, Go, React, WebRTC, S3, etc.)
- Concepts (encoding, streaming, error handling, etc.)
- Code Patterns (multipart upload, retry logic, etc.)
Relationships:
Engineer -[works_on]-> ProjectProject -[uses]-> TechnologyEngineer -[discussed]-> ConceptConcept -[related_to]-> Concept(e.g., "encoding" β "compression")Session -[about]-> Concept
Benefits:
- Multi-hop Reasoning: "What did Andrew discuss about video encoding?" β Query engineer β project β concept relationships
- Better Context: Understand that "S3 upload" and "multipart upload" are related concepts
- Entity-aware Retrieval: Find results based on entity relationships, not just text similarity
- Query Understanding: "Show me all discussions about technologies used in video-encoder" β Traverse graph
- Recommendations: "Similar sessions" based on graph structure, not just embeddings
Current Implementation:
# Already implemented in enhanced/knowledge_graph.py
from enhanced.knowledge_graph import KnowledgeGraph
kg = KnowledgeGraph()
kg.build_from_chunks(chunks) # Extracts entities and relationships
results = kg.graph_search(query, chunks) # Entity-aware retrievalHybrid Retrieval with KG (Current):
- Vector search finds semantically similar chunks
- BM25 search finds keyword matches
- Knowledge graph finds related entities through relationships
- Combine: 80% (Vector + BM25) + 20% Graph boost
- Rerank for final ordering
- Example: Query "video encoding" β Vector finds chunks + BM25 finds keywords + Graph finds all encoding-related discussions across projects
Current Tools:
- Custom Implementation: Lightweight entity extraction and relationship modeling
- Pattern Matching: Regex-based technology and concept extraction
- Graph Traversal: Multi-hop relationship finding
Future Enhancements:
- Neo4j: Full-featured graph database for larger scale
- spaCy NER: Better entity extraction with named entity recognition
- NetworkX: More sophisticated graph algorithms
- Graph Embeddings: Learn entity representations
Current Status:
- β Basic entity extraction (engineers, projects, technologies, concepts)
- β Relationship modeling (works_on, uses, discussed, related_to)
- β Graph-based retrieval integrated into hybrid search
- β Entity name variations handled (e.g., "Andrew Wang" β "andrewwang")
- π Future: More sophisticated NER, graph embeddings, Neo4j integration
- Click on search result to see full session conversation
- Expandable context windows
- Thread navigation (previous/next messages)
- Code block highlighting within conversations
- Semantic Chunking: Use embeddings to find natural boundaries
- Code-aware Chunking: Separate code blocks from text
- Hierarchical Chunking: Multi-level (document β section β paragraph)
- Adaptive Chunking: Dynamic size based on content type
- Search across code snippets, documentation, and conversations
- Code-to-code similarity (using CodeBERT)
- Visual code search (AST-based matching)
- Unified search interface
- Classify queries: "how-to", "debugging", "optimization", "architecture"
- Route to specialized retrieval strategies
- Intent-aware reranking
- Query suggestions based on intent
- Click-through rate tracking
- Relevance feedback (thumbs up/down)
- Fine-tune embeddings based on user interactions
- A/B testing framework for retrieval strategies
- Most searched topics dashboard
- Engineer expertise mapping
- Project knowledge gaps identification
- Trending technologies/concepts
- Search pattern analysis
- Watch for new sessions and auto-index
- Incremental embedding updates
- Live search results as new data arrives
- WebSocket support for real-time updates
- Syntax highlighting in results
- Code diff visualization
- "Show me similar code patterns"
- Code snippet extraction and search
- Language-specific search (Python vs Go vs TypeScript)
- Authentication & authorization
- Team-specific search (private sessions)
- Export search results (PDF, CSV)
- Search history and saved searches
- Collaborative annotations on results
The knowledge graph is fully integrated into Enhanced Mode:
Entities Extracted:
- Engineers: andrewwang, daniellin, dianalu
- Projects: video-encoder, video-ingester, stream-client-react, etc.
- Technologies: Python, Go, React, FastAPI, S3, WebRTC, etc.
- Concepts: encoding, streaming, error handling, optimization, etc.
Relationships Modeled:
Engineer -[works_on]-> Project(53 relationships)Project -[uses]-> Technology(333 relationships)Engineer -[discussed]-> Concept(187 relationships)Concept -[related_to]-> Concept(58 relationships)Session -[about]-> Concept(187 relationships)
How It Works:
- Entity Extraction: Regex patterns + metadata extraction
- Graph Building: Automatically builds relationships from chunks
- Query Processing: Extracts entities from user queries
- Graph Traversal: Finds related entities (1-2 hop traversal)
- Retrieval: Gets chunks associated with entities
- Scoring: Boosts results with entity matches (20% of final score)
Example Query Flow:
Query: "video encoding optimization"
β Extract: concepts=["encoding", "optimization"]
β Traverse: encoding -[related_to]-> [streaming, compression, ...]
β Find chunks: All chunks discussing encoding/optimization
β Score: Direct matches (2.0) + Related matches (0.5)
β Combine: 80% (Vector+BM25) + 20% Graph
Visualizations:
- Run
python3 tests/test_knowledge_graph.pyto generate graph visualizations - See
tests/knowledge_graph_visualization.pngfor full graph - See
tests/knowledge_graph_simplified.pngfor simplified view
- Better NER: Use spaCy for more accurate entity extraction
- Graph Embeddings: Learn entity representations
- Neo4j Integration: Scale to larger graphs
- Multi-hop Reasoning: Deeper relationship traversal
- Temporal Relationships: Track concept evolution over time
MIT
Built as part of Dexicon AI take-home assessment. Demonstrates production-ready RAG pipeline with comprehensive improvements and best practices.