💡 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:

  1. Upload Multi-Format Documents: Instantly parse and index PDFs, Word files (.docx), CSVs, plain text (.txt), and Markdown (.md).
  2. Track Indexing in Real Time: A dynamic chunk-by-chunk progress bar shows exactly which file and chunk is currently being processed.
  3. Execute Hybrid Search: Combines semantic (vector similarity) search with traditional lexical (keyword) search inside Elasticsearch to fetch the most relevant context.
  4. 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 StreamingResponse event-stream generator to stream indexing progress.
  • Search Engine: Elasticsearch (hosted on Elastic Cloud), configured with dense_vector cosine-similarity indexes (768 dimensions) to handle Gemini vector searches.
  • AI Stack: Google's new unified google-genai Python SDK, using gemini-2.5-flash-lite for reasoning and stateful chat (client.chats.create), and gemini-embedding-2 for 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 to 127.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-generativeai SDK. During development, we migrated the entire codebase to the new unified google-genai SDK, updating chat session setups, embedding calls, and catching rate limits with errors.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

Share this project:

Updates

Submission history