A CLI-based Retrieval-Augmented Generation (RAG) system that reads any policy document from a URL and answers natural language questions with structured, justifiable decisions.
Built for HackRx 6.0, PoliSense combines Google Gemini embeddings, a local Qdrant vector store, and Groq-hosted LLaMA inference to deliver fast, explainable answers grounded in the actual document text.
| Feature | Details |
|---|---|
| Multi-format ingestion | PDF via pypdf, DOCX/email/others via unstructured-io |
| Semantic chunking | RecursiveCharacterTextSplitter (1000 tokens, 200 overlap) with page-level metadata |
| Google Gemini embeddings | embedding-001 model for high-quality vector representations |
| Local Qdrant vector DB | Persisted on disk at ./qdrant_db β no cloud dependency |
Dual LLM support (test,py) |
Groq llama-3.1-8b-instant (fast) + Gemini 1.5-pro-latest (accurate) side-by-side |
| Structured JSON output | Every answer includes Decision, Amount, Justification, and PageReference |
| Progress bar download | Real-time download progress for large documents |
| Token usage tracking | Reports estimated embedding tokens + LLM tokens consumed |
PoliSense runs a classic RAG (Retrieval-Augmented Generation) pipeline in 6 sequential stages:
flowchart TD
A([π Input: Document URL + Questions]) --> B
subgraph INGESTION["π₯ Stage 1 β Document Ingestion"]
B[HTTP GET with progress bar\nrequests + User-Agent header]
B --> C{Content Type?}
C -- PDF --> D[pypdf\nPer-page text extraction\nwith page number metadata]
C -- DOCX / Email / Other --> E[unstructured-io\nAuto-partition β single Document]
end
subgraph CHUNKING["βοΈ Stage 2 β Text Chunking"]
D & E --> F[RecursiveCharacterTextSplitter\nchunk_size=1000 overlap=200\nPreserves page metadata]
end
subgraph INDEXING["ποΈ Stage 3 β Vector Indexing"]
F --> G[Google Gemini embedding-001\nGenerates dense vector per chunk]
G --> H[(Local Qdrant DB\n./qdrant_db\nforce_recreate=True)]
end
subgraph QUERY["π Stage 4 β Retrieval"]
I([β User Question]) --> J[Embed question\nvia Gemini embedding-001]
J --> K[Similarity search\nagainst Qdrant collection]
K --> L[Top-k relevant chunks\nwith page references]
end
subgraph GENERATION["π€ Stage 5 β LLM Generation"]
H -.populated by.-> K
L --> M[Prompt assembly\nContext + Question + Domain]
M --> N{LLM Choice}
N -- app.py --> O[Groq API\nllama3-8b-8192\nLow latency]
N -- test,py --> P[Groq llama-3.1-8b-instant\n+\nGemini 1.5 Pro\nSide-by-side comparison]
end
subgraph OUTPUT["π Stage 6 β Structured Output"]
O & P --> Q[JSON response parsing]
Q --> R["β
Decision: Approved / Rejected / N/A
π° Amount: βΉX or N/A
π Justification: quoted clause
π PageReference: page N"]
end
R --> S([π₯οΈ Terminal output + timing summary])
-
Document Ingestion β
load_document_from_url()
Downloads the file viarequestswith a spoofed browserUser-Agent. Supports optional--no-ssl-verifyfor self-signed certs. Streams the response and shows a real-time[####----]progress bar. -
Document Processing β
process_document()
Detects the content type (application/pdfheader or.pdfURL suffix) and routes to the right parser:- PDF β
pypdf.PdfReader, page-by-page, each page stored as aDocumentwithmetadata={"page": N} - Other β
unstructured.partition.auto.partition(), entire file collapsed into oneDocument
- PDF β
-
Text Chunking β
get_text_chunks()
RecursiveCharacterTextSplitterbreaks each document into overlapping 1000-character chunks.split_documents()(used intest,py) preserves page metadata across chunk boundaries β so the LLM knows which page each answer comes from. -
Vector Store Creation β
get_vector_store()
Embeds every chunk using Google Geminiembedding-001and stores them in a local Qdrant collection (hackrx-local-collection). The DB is re-created fresh on every run (force_recreate=True). Token count is estimated viatiktoken(cl100k_baseencoding) for cost tracking. -
LLM Initialization
app.pyβ single Groq client withllama3-8b-8192test,pyβ both Groq (llama-3.1-8b-instant) and Gemini (gemini-1.5-pro-latest) initialized in parallel, enabling direct model comparison on the same queries.
-
Retrieval & Generation β
create_retrieval_chain()
For each question:- The question is embedded and used to query Qdrant for the top-k most semantically similar chunks.
- The chunks + question are injected into a structured prompt template (with
{domain},{context},{input}slots). - The LLM is instructed to respond only in JSON with
Decision,Amount,Justification, andPageReference. - The raw response is parsed; if JSON extraction fails, the raw text is printed as a fallback.
- Python 3.9+
pip- Internet connection (for document downloads + API calls)
- API Keys: Google Gemini and Groq
# 1. Clone the repo
git clone <your-repo-url>
cd PoliSense
# 2. Create and activate a virtual environment
python -m venv venv
source venv/bin/activate # Windows: .\venv\Scripts\activate
# 3. Install dependencies
pip install -r requirements.txtCreate a .env file in the project root:
GEMINI_API_KEY="YOUR_GEMINI_API_KEY_HERE"
GROQ_API_KEY="YOUR_GROQ_API_KEY_HERE"
β οΈ Never commit.envto git. It is already listed in.gitignore.
python app.py <document_url> -q "<question_1>" "<question_2>" [--domain <domain>] [--no-ssl-verify]python "test,py" <document_url> -q "<question_1>" "<question_2>" [--domain <domain>] [--no-ssl-verify]| Argument | Required | Description |
|---|---|---|
document_url |
β | URL of the policy PDF or document |
-q / --questions |
β | One or more questions (each in double quotes) |
--domain |
β | Document domain, default: insurance. E.g. legal, hr, compliance |
--no-ssl-verify |
β | Disables SSL verification (use for self-signed certs) |
python app.py \
"https://hackrx.blob.core.windows.net/assets/policy.pdf" \
-q "Is knee surgery covered for a 46-year-old male with a 3-month-old policy?" \
"What is the waiting period for pre-existing diseases?" \
--domain insurance1. Fetching document from URL: https://example.com/policy.pdf...
Downloading document...
Progress: [########################################] 100.00%
Document fetched successfully.
2. Processing document...
(Processing as PDF using pypdf...)
Document processed.
3. Chunking text...
Text split into 248 chunks.
4. Creating vector store with embeddings...
Initializing embedding model (Google Gemini)...
Estimated tokens for embedding: 152400
Setting up local Qdrant database at './qdrant_db'...
Local Qdrant vector store is ready.
5. Initializing LLM...
LLM initialized successfully.
--- Answering Questions ---
-> Question: Is knee surgery covered for a 46-year-old male with a 3-month-old policy?
Answer:
{
"Decision": "Rejected",
"Amount": "N/A",
"Justification": "As per clause 3.1.2: 'A waiting period of 24 months applies to all knee-related surgeries.' The policy has only been active for 3 months, which does not satisfy the minimum waiting period.",
"PageReference": "Page 12"
}
(Time taken for this question: 2.15s)
------------------------------
--- Final Summary ---
Step Durations:
- Document Loading: 1.50s
- Document Processing: 0.80s
- Text Chunking: 0.10s
- Vector Store Creation: 5.20s
- LLM Initialization: 0.30s
Token Usage:
- Estimated Embedding Tokens (Gemini): 152400
- Total LLM Tokens (Groq): 1200
Total Application Execution Time: 8.10s
PoliSense/
βββ app.py # Main RAG pipeline (Groq LLM only)
βββ test,py # Experimental β dual LLM comparison (Groq + Gemini)
βββ requirements.txt
βββ .env # API keys (not committed)
βββ .gitignore
βββ LICENSE
βββ qdrant_db/ # Auto-generated local vector database
- Groq API (
llama-3.1-8b-instant) delivers sub-3s inference latency per question. - Qdrant local skips network round-trips β similarity search is in-process.
force_recreate=Truemeans the vector store is rebuilt fresh on each run. For repeated queries on the same document, remove this flag to reuse the existing index and save embedding cost.- Token costs are tracked via
tiktoken(embeddings) andget_openai_callback(LLM tokens).
- Persistent vector store β skip re-embedding if the document URL is unchanged
- Cross-encoder reranking β improve retrieval quality with a
sentence-transformersreranker - Query rewriting β expand ambiguous queries with an LLM before retrieval
- FastAPI / web UI β REST endpoint for integration into external systems
- OCR support β
unstructured-iohi_resstrategy for scanned PDFs - Batch document ingestion β index multiple policy documents into a single collection
MIT License β see LICENSE for details.
Developed for HackRx 6.0. Powered by LangChain, Qdrant, Groq, and Google Gemini.