All posts
AI7 min read

RAG That Answers Correctly: Building Business Knowledge Bases

How we build RAG that answers correctly: structure-aware chunking, pgvector in Postgres, the retrieval failures that bite, and evals before shipping.

Our voice agents at TeleVox AI answer business phone calls with retrieved knowledge inside a roughly 0.7-second response budget. On a live call there is no regenerate button. A wrong answer about opening hours or pricing is worse than no answer, because the caller believes it. That constraint forced us to treat RAG as an engineering discipline rather than a demo, and most of what we learned applies to any business knowledge base — support bots, internal assistants, customer-facing chat.

Here is how we build RAG systems that answer correctly, and where they fail when you don't.

Chunking that respects document structure

The default approach — split every document into fixed 500-token windows with overlap — is where most RAG quality problems start. Fixed windows cut tables in half, separate a heading from the paragraph that explains it, and split a policy's rule from its exception.

The rules we follow:

Chunk size is a tradeoff, not a constant. Small chunks retrieve precisely but strip context; large chunks carry context but dilute the embedding. We start around 300–500 tokens for prose, atomic for structured content, then let evals move it.

pgvector, because your data is already in Postgres

We run retrieval on pgvector inside Supabase Postgres. Not because it benchmarks best — dedicated vector databases will beat it at extreme scale — but because at the tens or hundreds of thousands of chunks a real business knowledge base contains, it is fast enough, and it removes an entire class of problems:

An HNSW index gets you a long way:

CREATE INDEX ON chunks USING hnsw (embedding vector_cosine_ops);

SELECT id, content, 1 - (embedding <=> $1) AS similarity
FROM chunks
WHERE tenant_id = $2   -- RLS enforces this anyway
ORDER BY embedding <=> $1
LIMIT 10;

We also keep a tsvector column and merge keyword hits with vector hits. Embeddings are weak on exact strings — SKUs, error codes, people's names — and keyword search catches what cosine similarity misses.

The retrieval failures you will actually hit

Demos fail in three predictable ways. Production systems need an answer for each.

Stale documents

The pricing page changed; the old embedding is still in the index. Retrieval now returns both versions and the model picks one. Treat ingestion as sync, not append: hash each source document, and when the hash changes, delete every chunk from that source and re-ingest inside a single transaction. Append-only ingestion is the most common cause of confidently outdated answers in RAG systems.

Near-duplicate chunks

Business content repeats itself — the same guarantee on five product pages, boilerplate headers, templated sections. All five near-copies land in your top ten and crowd out the one chunk that actually answers the question. Deduplicate at ingestion (embedding similarity above roughly 0.95 is a duplicate) and diversify at query time — maximal marginal relevance is simple to implement and noticeably improves multi-fact answers.

Questions that span chunks

"What's the difference between the Pro and Enterprise SLA?" needs two chunks that may not both surface for one query embedding. Two mitigations work reliably. Retrieve small, feed big: match on a precise chunk, then hand the model its whole parent section. And decompose comparison questions into sub-queries, retrieving separately for each side. Both add latency, which is why our voice stack applies them selectively — a phone caller will not wait out a five-hop retrieval chain.

Evals before shipping, not after

You cannot tune what you do not measure, and "we tried some questions and it seemed good" is not measurement.

Before a knowledge base goes live we build a golden set: 50 to 200 real questions with known correct answers, sourced from actual support tickets and call transcripts, not invented by the team that wrote the docs. Then we score two things separately:

The golden set must include questions the knowledge base cannot answer. The correct behavior is "I don't know" or an escalation — for a voice agent, a transfer to a human. Systems never tested on unanswerable questions learn to guess.

Re-run the suite on every re-ingestion. Retrieval regressions from an innocent docs update are real and otherwise invisible.

When fine-tuning is the wrong answer

Clients regularly ask us to fine-tune a model on their data so it "knows the business." For factual knowledge this is usually the wrong tool:

Fine-tuning earns its place for tone, output format, and domain phrasing — an agent that always speaks in your brand voice. Facts belong in the retrieval layer, where you can update, audit, and delete them.

What this looks like end to end

Structure-aware chunking, hybrid pgvector retrieval under RLS, sync-not-append ingestion, and a golden-set eval gate is not an exotic stack. It is a few weeks of disciplined engineering, and it is the difference between a demo and a system a business can put in front of customers — in chat through our AI solutions practice, or on live phone calls through our voice AI work, where the same retrieval layer has to perform inside a sub-second response budget.

If you are building a knowledge base for support, internal ops, or a voice agent — or fixing one that answers confidently and wrongly — get in touch. We start with your documents and your real questions, not a framework.

UKUsama KhalilFounder, KiswahTech — senior software architect, builder of TeleVox AIWork With Us