September 29, 2026
Document Q&A — building a retrieval system that knows when not to answer
Built Django document Q&A with configured 768-dimensional embeddings, top-5 retrieval, batch imports, category filtering, retry handling, and a no-context fallback.
Personal prototype
- Role
- Software engineer
- Published
- September 2026
- Focus
- Personal prototype
- Engineer
- Saaim Abdullah

The product problem: answer from the dataset, not from a guess
System facts and configured numbers
| Metric or configuration | Documented value | Interpretation |
|---|---|---|
| Public API operations | 3 — query, ingest, health | Separate serving, data administration, and readiness paths |
| Embedding width | 768 dimensions | Vector schema and embedding model must agree |
| Candidate limit | Top 5 | Bound the context admitted to generation by default |
| Cosine distance threshold | 0.7 | Filter candidates with distance above the configured cutoff |
| Ingestion batch size | 20 records | Bound each embedding request during CSV import |
| API quota retry setting | 3 attempts | Recover from transient provider rate limits with backoff |
| Required input columns | 4 — name, category, question, answer | Explicit and testable ingestion contract |
| Generation service | Gemini | External inference dependency, distinct from PostgreSQL |
End-to-end request and data flow
| Step | Input | Work performed | What can fail |
|---|---|---|---|
| 1. Import | CSV file | Validate required columns and normalize Q&A rows | Schema errors, malformed content |
| 2. Embed | Text batches | Request Gemini embeddings | Quotas, model changes, network errors |
| 3. Persist | Content + metadata + vectors | Store in PostgreSQL with pgvector | Partial imports, incompatible dimensions |
| 4. Query | User question + optional category | Embed query with same model family | Provider latency, unavailable API |
| 5. Retrieve | Query vector | Rank stored vectors by cosine distance; filter by category | Poor matches, unbounded search cost |
| 6. Gate | Retrieved candidates | Apply top-K and distance cutoff | Relevant evidence absent |
| 7. Generate | Selected Q&A records | Build constrained prompt and call Gemini | Unsupported assertions, timeout |
| 8. Respond | Answer + context | Return answer and source context, or fallback | Client contract, sensitive source exposure |
Import is part of the product, not a one-off script
Retrieval has a refusal boundary
0.7 cutoff is a retrieval parameter that should be calibrated against question sets and expected false positives. I would separately measure relevance of retrieved records and faithfulness of the generated answer; good search results do not automatically guarantee good generation.
The API is deliberately smaller than the architecture
| Endpoint | Role | Contract |
|---|---|---|
POST /query/ | Query a stored knowledge base | Question, optional category; answer and retrieved context |
POST /ingest/ | Import Q&A CSV | Validates columns and reports ingested/skipped records |
GET /health/ | Health inspection | Includes database connectivity and stored chunk count |
The engineering trade-offs
| Choice | Why I made it | Cost or limitation |
|---|---|---|
| PostgreSQL + pgvector | One database stores content, source metadata, and vectors | Index strategy matters as corpus grows |
| Hosted embeddings | Simplifies local model operations and deployment | Adds provider latency, quotas, and data boundary |
| Top-K + threshold | Keeps generation grounded in bounded evidence | Needs dataset-specific relevance calibration |
| Source/category metadata | Makes results inspectable and filterable | Import mapping must be consistent |
| Provider retry logic | Handles transient 429 errors | Retries need budgets and can increase latency |
| Refusal without retrieved context | Reduces unsupported, costly generation calls | May decline answerable questions if retrieval misses |
A concrete operational failure scenario
What is implemented, and what is not
Result and measurable next milestone
Source and technical walkthrough



SaaimOpen to full-time roles, contract work, and conversations about things worth building.