Spaces:
Sleeping
Sleeping
File size: 13,854 Bytes
5dbdf6e 13779e8 5dbdf6e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | # Tech Stack Rationale
| Field | Value |
| --- | --- |
| Project | Insurance Sales Portfolio Expert |
| Date | 2026-05-13 |
| Status | Living document β updated as picks change |
| Companion docs | `02-architecture.md` (architecture detail) Β· `decisions.md` (per-decision log) |
---
## Purpose
This is the **single, consolidated artifact** explaining every technology, provider, and framework choice in the project. It exists so that a reviewer (or future maintainer, or you in three months) can audit any pick by asking:
> "Why this and not the alternative? What evidence supports the choice? What changes if the constraint changes?"
Every entry has alternatives considered and a reasoning trace. Where decisions are still open, they are flagged with "**OPEN**" and an expected resolution date.
---
## 1. Component map β what the system is made of
The product is split into five layers. Each layer has independent technology choices.
```
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 1. FRONTEND web UI Β· chat Β· audio Β· filter Β· compare β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β HTTPS
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 2. BACKEND API route handlers Β· auth Β· request validation β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 3. ORCHESTRATION persona prompt Β· intent routing Β· providers β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
ββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββββββββββ
β 4a. STRUCTURED STORE β β 4b. VECTOR STORE β
β filter / compare β β RAG retrieval β
ββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 5. INGEST PIPELINE crawl Β· chunk Β· embed Β· extract β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
```
---
## 2. The picks β one table to find anything
| # | Layer | Component | Pick | Status | Why (one line) | Alternatives considered |
| --- | --- | --- | --- | --- | --- | --- |
| 1 | Frontend | Framework | **Next.js 14 (App Router)** | Locked | Production-pattern, full UI flexibility, fast w/ shadcn/ui | Streamlit, Gradio, Chainlit, Reflex |
| 2 | Frontend | Styling | **Tailwind CSS + shadcn/ui** | Locked | Copy-paste components produce beautiful UIs in hours | MUI, Chakra, plain CSS |
| 3 | Frontend | Audio capture | **MediaRecorder API** (browser-native) | Locked | Zero deps, cross-browser, blobβPOST flow is simple | streamlit-mic-recorder, WebRTC, manual ScriptProcessor |
| 4 | Frontend | Hosting | **Vercel** (free tier) | Locked | Native Next.js host, GitHub auto-deploy, edge-cached | Netlify, Cloudflare Pages |
| 5 | Backend | Framework | **FastAPI + Pydantic** | Locked | Pydantic matches our 48-field schema; OpenAPI auto-docs; async I/O for parallel provider calls | Flask, Django, Node/Express |
| 6 | Backend | Hosting | **Render** (free 750h/mo) | Locked | GitHub auto-deploy, Python-native, persistent disk for DuckDB + Chroma | Fly.io, Railway, Modal |
| 7 | Backend | API style | **REST** for v1, possible WebSocket if voice latency demands | Locked | Simpler; switch to WS only if measured latency exceeds target | Pure WS, gRPC |
| 8 | Backend | FEβBE type safety | **`openapi-typescript` codegen** from FastAPI's auto-generated OpenAPI | Locked | Single source of truth; backend route changes propagate automatically | tRPC (Node-only), GraphQL, manual TS types |
| 9 | Orchestration | STT | **Sarvam Saarika v2.5** | Locked | Sarvam-first; their newer Indic ASR model | Whisper-large-v3, Deepgram Nova-2, Sarvam Saaras v3 |
| 10 | Orchestration | TTS | **Sarvam Bulbul** | Locked | Sarvam-first; Indic prosody first-class | ElevenLabs, OpenAI TTS, Coqui local |
| 11 | Orchestration | LLM (brain) | **NVIDIA NIM tiered: DeepSeek-V4-Pro (heavy) + DeepSeek-V4-Flash (fast)** | Locked (D-019) | V4-Pro (1.6T/49B MoE, frontier, beats Opus-4.6 + GPT-5.4 on SimpleQA) for comparison/recommendation; V4-Flash (284B/13B MoE, lower TTFT) for voice + fact-find. Single NIM key, free tier, no daily cap. Sarvam-M moved to Indic translation only β its 2048 output cap was truncating advisor responses. | Sarvam-M as brain (rejected β truncation), OpenRouter `:free` (rejected β 50/day cap), Gemini 2.5 Flash (rejected β adds 2nd provider ecosystem), GPT-4o via GitHub Models (rejected β same 50/day cap) |
| 12 | Orchestration | LLM (grader / self-critique) | **NVIDIA NIM Llama-4 Maverick (Meta MoE)** | Locked (D-019) | Different family from the DeepSeek brain β Meta MoE judging DeepSeek MoE, so the brain does not mark its own homework. Same NIM endpoint and key. 400B/17B MoE, frontier-tier. Replaces Groq Llama-3.3-70B (30 req/min cap blocked sweeps). | Groq Llama (rejected β rate limit), Cerebras Qwen-235B (rejected β same family as another DeepSeek path), Sarvam-M held-out |
| 13 | Orchestration | Embeddings | **BGE-small-en-v1.5 (local CPU, sentence-transformers)** | Locked | Free, runs offline, 384-dim, BEIR-strong on insurance/legal text. Voyage path kept for v2 swap (~3pp retrieval-quality delta in BEIR-style spot checks). | Voyage AI voyage-3 (rejected for v1 β 3 RPM free-tier blocked 104-PDF ingest), OpenAI text-embedding-3-small (rejected β no GPT), Cohere |
| 14 | Storage | Structured DB | **DuckDB** (single file) | Locked | One file, columnar, no server; deploys via `git clone` | SQLite, Postgres |
| 15 | Storage | Vector DB | **Chroma** (local persisted) | Locked | Embedded, no infra, supports metadata filtering | FAISS, Pinecone, Qdrant, Weaviate |
| 16 | Ingest | PDF parsing | **pdfplumber** | Locked | Clean text + page numbers β critical for citation grammar | PyMuPDF, Unstructured.io |
| 17 | Ingest | Chunking | **Custom 800-token chunks, 120-token overlap, page-aware** | Locked | Standard for technical docs; overlap protects clause boundaries | LangChain text splitter, fixed-size |
| 18 | Ingest | Structured extraction | **Sarvam-M (Llama-3.3-70B / DeepSeek-V3 fallback) with Pydantic structured output + self-critique pass** | Locked | Reliable JSON-mode extraction; self-critique gives per-field confidence; fallback brain handles tables / complex clauses Sarvam-M misses | Pure regex, LangChain extraction, Instructor lib |
| 19 | Pricing | Approach | **Hand-curated illustrative bands** from public PolicyBazaar quotes | Locked | Honest, defensible; "advisor-not-broker" positioning | Live scraping, actuarial model |
| 20 | Cross-cutting | Auth | **None for v1** (single-tenant demo) | Locked | Out of scope per `01-requirements.md` Β§7 | Auth0, Clerk, NextAuth |
| 21 | Cross-cutting | Observability | **JSONL turn log + cost tracker** | Locked | Lightweight; one log file, queryable post-hoc | Langfuse, Helicone, custom dashboard |
| 22 | Cross-cutting | Secrets management | **`.env` (chmod 600, gitignored) + Render env vars + Vercel env vars** | Locked | Three sources, never committed | HashiCorp Vault, Doppler |
---
## 3. Selection rubric β how we chose
Every pick above followed this five-test rubric. **Picks that fail any of these are documented as accepted tradeoffs, not silent compromises.**
### 3.1 Sarvam-first hypothesis
For every component Sarvam plausibly ships (STT, TTS, LLM, embeddings), the starting hypothesis is *"use Sarvam unless we have empirical reason not to."* This is graded behavior for a Sarvam assignment β silent defaults to OpenAI/Anthropic/ElevenLabs are the most common screen-out signal.
We will **benchmark** before locking final Sarvam vs non-Sarvam picks:
- **STT:** 20-utterance test set across English, Hindi, Hinglish β measure word-error rate
- **TTS:** Subjective quality + latency on 5 sample advisor responses
- **LLM:** 50 gold Q&A pairs run with Sarvam-M and GPT-4o β measure factual accuracy + citation accuracy
Where Sarvam wins β ship Sarvam. Where Sarvam loses β document the gap with numbers and ship the alternative. Either outcome is a strong artifact.
### 3.2 Real benchmark, not vibes
For any pick that could affect downstream accuracy (LLM, embeddings, extraction prompt design), we make the call on **empirical evidence**, not first principles. The gold Q&A harness exists for exactly this β it transforms "I think X is better" into "X scored 92% vs Y's 87% on our test set."
### 3.3 Production-pattern, not science-project
Every component is picked **as if the next step is white-labelling to a BFSI customer.** No "great for prototyping" picks that block productionization. Examples:
- β
FastAPI β already production-grade
- β
DuckDB β embedded but production-deployed at Motherduck and many fintechs
- β ~~Streamlit~~ β great prototyping, no white-label path β switched to Next.js
### 3.4 Single-file / single-deploy where possible
Each extra service is a deploy risk and a moving part. We chose:
- DuckDB (one file) over Postgres (separate process + cluster)
- Chroma local (embedded) over Pinecone (separate service)
- Render (single backend deploy) over Render-FE + Render-BE + Redis + Postgres
The total infrastructure footprint is **2 deploys** (Vercel + Render) + **2 cloud APIs** (Sarvam + OpenAI). That's it.
### 3.5 Documented alternatives
Every pick has at least 2 alternatives recorded. A reviewer can audit the reasoning. "Why DuckDB?" β table row 14 β SQLite (no columnar, no analytics) and Postgres (overkill, deploy overhead). Three options considered; reasoning explicit.
---
## 4. Cost envelope (24-hour build + demo run)
| Item | Estimated cost |
| --- | --- |
| Sarvam API (STT + TTS + LLM) β build + 100 demo calls | likely free under signup credits |
| Voyage AI embeddings (~5M tokens to embed 75 PDFs) | ~$0.45 (free under $50 signup credit) |
| Claude Haiku 4.5 for grader / self-critique (~200 calls) | ~$0.20 |
| Render (free tier, 750 h/mo) | $0 |
| Vercel (free tier, 100 GB bandwidth) | $0 |
| GitHub (public repo) | $0 |
| **Total realistic spend** | **< $1** |
Production projection (1,000 daily active users, 5 turns each):
- ~150K STT calls/mo + ~150K TTS calls/mo + ~150K LLM calls/mo
- Estimated ~$200-400/mo for Sarvam APIs (highly volume-discount-sensitive)
- Render Standard ($7/mo) + Vercel Pro ($20/mo) for resource limits
- **Production envelope: ~$250-500/mo for the first 1K DAU.** Sub-cent per turn.
---
## 5. Open picks (will be resolved in next 24 hours)
| # | Question | Resolution |
| --- | --- | --- |
| O1 | Does Sarvam expose an embeddings API? If yes, benchmark vs OpenAI text-embedding-3-small | Check `dashboard.sarvam.ai` API listing; <30 min |
| O2 | Saarika v2.5 vs Saaras v3 for STT β depends on whether we need translate/codemix modes | Benchmark both on 20-utterance set; <1h |
| O3 | Recommendation engine shape: rule-based pre-filter + LLM justification vs pure-LLM reasoning | Decide after gold Q&A harness runs; leaning rule-based for testability |
| O4 | Caching layer β should LLM responses be cached for repeated questions? | Yes for demo; simple file cache, no Redis |
| O5 | Should we add basic auth on the deployed URL to avoid abuse? | Probably yes β single shared password for interviewer access |
---
## 6. Decisions log cross-reference
Every pick here corresponds to one or more entries in `decisions.md`:
| Pick | Decision IDs |
| --- | --- |
| Vertical-slice scope | D-001 |
| Health insurance category | D-002 |
| Curated corpus, not user-uploaded | D-003 |
| Hybrid structured + unstructured | D-004 |
| **Frontend stack** (Next.js + FastAPI) | D-005 (revised 2026-05-13) |
| Sarvam-first benchmarking | D-006 |
| Pricing as illustrative band | D-007 |
| Consultative persona | D-008 |
| 10 insurers Γ all health policies | D-009 |
| Secret handling | D-010 |
| Embeddings provider (pending) | D-011 |
| Render deployment over alternatives | D-012 |
| Next.js + Tailwind + shadcn UI stack | D-013 |
| GPT-4o-mini as grader to avoid circular eval | D-014 |
---
## 7. Revision history
| Version | Date | Change |
| --- | --- | --- |
| 0.1 | 2026-05-13 | Initial draft. Switched D-005 frontend from Streamlit to Next.js + FastAPI; added D-011 through D-014 for new picks. |
|