How It Works
How We Built City Budget AI Assistant
City budgets are hundreds of pages long. We built a pipeline that parses them, indexes their meaning, and retrieves precise answers with page citations — so you never have to skim a PDF again.
The Pipeline
Document Ingestion
Budget PDFs are parsed page-by-page using pdf-parse to extract raw text. Each page's content is preserved with its page number, so every answer can cite exactly where the information came from.
Intelligent Chunking
Extracted text is split into overlapping ~1,000-character segments. The overlap ensures that context isn't lost at chunk boundaries — a sentence that spans two pages still gets captured in full.
Vector Embeddings
Each chunk is converted into a high-dimensional numerical vector using BGE-M3. This model captures semantic meaning — so "public safety expenditure" and "police department funding" end up close together in vector space.
Semantic Retrieval
When a user asks a question, it's also embedded into the same vector space. Upstash Vector finds the most relevant chunks by cosine similarity — no keyword matching, just meaning.
Contextual Answer Generation
The retrieved excerpts are assembled into a prompt with instructions to stay grounded in the source material. The language model generates an answer with page citations, so users can verify every claim.
Architecture
┌─────────────┐
│ PDF Upload │
└──────┬──────┘
│ parse pages
▼
┌─────────────┐
│ Text Chunks │ ~1000 chars, overlapping
└──────┬──────┘
│ embed (BGE-M3)
▼
┌─────────────┐
│ Vector Store │ Upstash Vector
└──────┬──────┘
│
│ ┌──────────────┐
│ │ User Question │
│ └──────┬───────┘
│ │ embed
│ ▼
│ ┌──────────────┐
└────────►│ Similarity │
│ Search │
└──────┬───────┘
│ top-k chunks
▼
┌──────────────┐
│ Prompt + │
│ Context │
└──────┬───────┘
│ generate
▼
┌──────────────┐
│ Answer │
│ (with pages) │
└──────────────┘