💡 Inspiration
We wanted to build an assistant that bridges the gap between raw document storage and natural language questioning. Most document search solutions either retrieve irrelevant chunks or hallucinate facts. We set out to create SearchBot—a fully transparent, highly responsive tool that utilizes advanced hybrid search to retrieve precise document fragments and instructs Gemini to answer only based on retrieved contexts, always attaching clear page-level citations.
🔍 What it does
SearchBot allows users to:
- Upload Multi-Format Documents: Instantly parse and index PDFs, Word files (
.docx), CSVs, plain text (.txt), and Markdown (.md). - Track Indexing in Real Time: A dynamic chunk-by-chunk progress bar shows exactly which file and chunk is currently being processed.
- Execute Hybrid Search: Combines semantic (vector similarity) search with traditional lexical (keyword) search inside Elasticsearch to fetch the most relevant context.
- Get Verifiable Answers: Answers questions in natural language, citing the exact document name and page number (or offset page) for every response.
🏗️ How we built it
- Frontend: Streamlit, styled with custom CSS for a premium, compact dark theme (
rgb(14, 17, 23)). - Backend: FastAPI, configured with standard REST endpoints and a
StreamingResponseevent-stream generator to stream indexing progress. - Search Engine: Elasticsearch (hosted on Elastic Cloud), configured with
dense_vectorcosine-similarity indexes (768 dimensions) to handle Gemini vector searches. - AI Stack: Google's new unified
google-genaiPython SDK, usinggemini-2.5-flash-litefor reasoning and stateful chat (client.chats.create), andgemini-embedding-2for creating vector embeddings.
⚠️ Challenges we ran into
- Windows localhost DNS Latency: We hit a strange issue where local frontend-backend requests had a persistent 2.0-second delay due to IPv6/IPv4 DNS query timeouts on
localhost. We resolved this by changing the default API address to127.0.0.1:8000, dropping latency to under 5 ms. - Gemini Free Tier Rate Limits (429): We implemented custom exponential backoff retry algorithms in Python to gracefully handle Gemini free-tier quotas.
- SDK Deprecation and Migration: The project was originally using the deprecated
google-generativeaiSDK. During development, we migrated the entire codebase to the new unifiedgoogle-genaiSDK, updating chat session setups, embedding calls, and catching rate limits witherrors.APIError. - API deprecations: Moving to Elasticsearch v9.x required rewriting deprecated payload parameters (
body=...) to top-level keyword arguments.
🎉 Accomplishments that we're proud of
- Real-Time Indexing Progress: Built a custom generator on FastAPI that streams indexing status line-by-line, coupled with an interpolating Streamlit progress bar.
- Clean UI & UX: Customized Streamlit's default margins, padding-bottom containers, and uploader keys to build a responsive interface that automatically clears file cards upon successful indexing.
- Speed: Offloaded background MCP search queries to daemon threads to keep the main agent response loop completely non-blocking.
🧠 What we learned
- How to set up and fine-tune dense vector mappings inside Elasticsearch.
- Streaming data over HTTP using FastAPI and parsing standard line-by-line JSON streams in Python.
- Strict prompt engineering layouts to avoid AI hallucinations and strictly enforce citations.
🚀 What's next for SearchBot
- OCR Support: Integrate Tesseract or Google Cloud Vision API to parse scanned images and handwritten pages.
- Auto-Syncing: Sync directly with Dropbox, Google Drive, or OneDrive folders to auto-index new files.
- Enterprise RBAC: Role-based access control to ensure users only search documents they have permissions to view.
Built With
- elasticsearch
- fastapi
- gemini-api
- hybrid-search
- python
- rag
- streamlit
- vector-search
Log in or sign up for Devpost to join the conversation.