01 — The Real Problem
Everyone Wants an AI That Answers Questions. Almost Nobody Wants an AI That Makes Things Up.
The story of every business deploying a customer-facing chatbot follows a predictable arc. They hook up a general LLM to their product. It's impressive for the first week. Then a customer asks what the refund policy is, and the model — having no idea — invents a policy with complete confidence. Then a user asks about a product that doesn't exist. The model describes it in vivid detail. By week three, the chatbot is a liability.
This is not a bug. It is the fundamental behavior of language models. They are trained to produce fluent, confident text. Uncertainty is uncomfortable to them. When they don't know something, they approximate — and approximation at scale, in production, is hallucination.
Knavia was built to solve this in a way that's actually verifiable. Not with better prompting or "just tell it to be careful." With architecture. Every layer of the system — from how documents are ingested, to how knowledge is retrieved, to how the prompt is assembled — is designed to make hallucination structurally unlikely, and the closed-domain rules make unsupported answers structurally forbidden.
"The challenge wasn't building an AI that knows things. It was building one that knows exactly what it doesn't know — and stays quiet about everything else."
02 — Why Naive RAG Fails
Retrieval-Augmented Generation Is Not Enough On Its Own
The standard RAG setup looks simple: embed documents, store in a vector DB, embed the user's question, find the nearest chunks, stuff them into the prompt. This works well for demos. In production, it fails in four distinct ways.
Vector similarity misses exact keyword matches
A user searching for a specific product code or model name may get no relevant results from dense embedding search, because embedding space doesn't preserve exact token identity. The model may then fill the gap from training data.
Short chunks destroy context
Splitting documents into 300-character chunks to maximize retrieval precision throws away the surrounding context that makes answers accurate. A chunk about "our refund policy" without the surrounding paragraph is barely useful to an LLM.
Follow-up questions have no retrieval signal
"What are its features?" embedded alone will not retrieve the right document, because "it" refers to something discussed a turn earlier. The retrieval system doesn't know what "it" means.
The model leaks training data anyway
Even with good retrieval, a general LLM will sometimes supplement retrieved knowledge with what it learned during training. Without hard structural rules in the prompt, this is nearly impossible to prevent consistently.
Knavia addresses all four. Not with heuristics, but with deliberate, layered engineering choices at every stage of the pipeline.
03 — Ingestion Pipeline
Documents Are Not Trusted Until They Are Verified
Knavia accepts three document sources: file upload, URL ingestion, and raw text. Each path goes through validation that is more careful than it might appear.
File type validation via finfo, not browser claims
The browser's reported MIME type is ignored. PHP's finfo library reads the actual magic bytes of the file. Only application/pdf, text/plain, text/html, text/csv, and application/json are accepted. An .exe renamed to .pdf is detected and rejected.
SSRF protection on every URL and every redirect hop
When a user submits a URL, the host is resolved via DNS and checked against private and reserved IP ranges. This prevents Knavia from being weaponized to probe internal services. Each redirect in the chain is independently validated — not just the initial URL.
SHA-256 checksum written at ingest time
Every document gets a sha256 checksum computed from the raw file bytes at ingest time. This enables future deduplication, integrity verification, and version comparison when documents are updated.
Processing dispatched to a chained queue pipeline
Document processing — text extraction → chunking → QA generation → embedding → vector indexing — runs as a chained sequence of Laravel queue jobs. The HTTP response returns immediately. The user sees live progress updates. Heavy work happens off the web process.
04 — Parent-Child Chunking
Small Chunks for Precision. Large Chunks for Context. Both at Once.
Standard RAG chunking forces a trade-off: small chunks give retrieval precision but throw away context. Large chunks give context but retrieve noisily. Knavia resolves this with a parent-child architecture that stores both sizes and uses the right one for each purpose.
The small unit. Embedded and stored in Qdrant. Precise enough that semantic search finds the right section, not just the right document. Overlaps 100 chars with neighbors to avoid context gaps at boundaries.
The large unit. When a child chunk is retrieved, the parent is what gets injected into the prompt. The model receives the full surrounding context — not just the precise sentence — which produces far more accurate answers.
The splitter respects paragraph boundaries (\n\n) before falling back to sentence boundaries ([.?!] followed by uppercase). Chunks don't cut mid-sentence or mid-paragraph whenever possible.
05 — Semantic QA Augmentation
Documents Don't Know What Questions They Answer. We Teach Them.
This is one of the most impactful improvements over standard RAG, and also one of the least understood. Here's the problem: documents are written in declarative form. Questions are asked in interrogative form. The embedding space between "Our refund policy allows 30-day returns" and "Can I return this?" is surprisingly large. Vector similarity can miss this match entirely.
Knavia solves this with a background job that runs after chunking: for every chunk, a fast LLM generates five hypothetical questions that the chunk would answer. These questions are stored in a qa_content column and concatenated with the chunk text before embedding is generated.
The generated QA pairs are concatenated before the embedding is generated:
The effect: a chunk about a refund policy now scores high on both "30-day returns" (declarative) and "can I return this?" (interrogative). Retrieval quality improves substantially, especially on short or ambiguous queries. Arabic and English documents produce language-matched QA pairs automatically, improving multilingual retrieval without special configuration.
The QA job uses Http::pool() to parallelize requests across chunks in each batch, with automatic token rotation across a token pool file and retry logic for rate-limited responses.
06 — Hybrid Retrieval + RRF
Dense Vectors Find Meaning. Keywords Find Exactness. RRF Merges Them Without Picking a Winner.
Neither dense vector search nor keyword search is universally superior. Dense search finds semantically similar content but can miss exact product names, codes, and technical identifiers. Keyword search finds exact matches but can't rank by conceptual relevance. Knavia runs both in parallel and fuses the ranked results using Reciprocal Rank Fusion (RRF).
content and qa_content columns in NATURAL LANGUAGE MODE. Exact and near-exact matches surface here.1 / (k + rank) summed across both result lists. Final list sorted by combined score. Top-K returned to the prompt.The result set is deduplicated by content hash before being assembled into the context string. The ContextBuilder uses each matched chunk's parent (2500 chars) for injection, giving the model full surrounding context.
07 — The Closed-Domain Prompt
Telling an LLM What It Cannot Do Is Harder Than Telling It What It Can
This is where most RAG products fail silently. They retrieve good content, put it in the prompt, and say "answer only from the context provided." And the model complies, mostly — until it doesn't. Because that instruction is easy to override when the model has a strong training signal about the topic.
Knavia's prompt architecture has two layers: a configurable system prompt that administrators can customize, and a set of mandatory runtime rules appended after the configurable part. These rules cannot be overridden by any administrative configuration — they're always appended last.
The prompt also handles a subtle but critical behavioral distinction between using conversation history to understand a question versus using it to answer one:
User asks "what are its features?" after discussing Voice Chat Apps. Model is allowed to understand this as asking about Voice Chat App features — and retrieve accordingly.
A previous assistant turn mentioned "$99 pricing." User asks a follow-up about cost. The model cannot use that previous answer as fact unless the price exists in the current KNOWLEDGE retrieval.
The fallback is configurable per-project and deterministic: if set to a specific string, the model returns exactly that string (translated to the user's language). No improvisation around the edges of the fallback.
08 — Token Budget Engine
The Prompt Has a Fixed Budget. Everyone Fights for a Share. Knowledge Wins.
LLMs have finite context windows. In a multi-turn conversation with a large knowledge base, a naive implementation will silently truncate the history, or the knowledge, or the system prompt — usually whatever is last in the concatenation. The model then answers from whatever is left, which may be nothing relevant, and hallucinates to fill the gap.
Knavia enforces an explicit token budget with a clear priority order: system prompt first, then conversation history (newest-to-oldest, dropped when budget runs low), then retrieved knowledge — but with a guaranteed minimum of 1,000 tokens reserved for knowledge regardless of how long the history is.
Token estimation uses a conservative 4-char-per-token heuristic, with an explicit note in the code that Arabic and multilingual content consumes more. The intentional conservatism means the budget is never unexpectedly exceeded, even for non-English content.
09 — Conversation Context
The Follow-Up Question Problem — And Why It's Harder Than It Looks
Consider this two-turn exchange:
The second message, "what are the features?", is nearly meaningless without the first. If you embed it alone and send it to Qdrant, you'll retrieve random chunks about features of various things. The answer will be wrong.
The solution has two parts. First, conversation history is included in the prompt in chronological order so the model has full context to understand the reference. Second, the mandatory prompt rules explicitly teach the model how to resolve pronouns and references from history — while reminding it that understanding the question from history does not mean the answer can come from history.
10 — SSRF & Document Security
A Document Ingestion System Is a Potential Attack Surface
Any system that fetches URLs on behalf of users is a potential Server-Side Request Forgery (SSRF) vector. An attacker could submit http://169.254.169.254/latest/meta-data/ (AWS metadata endpoint) or http://localhost:6333 (Qdrant's HTTP API) and extract internal system information through the ingestion response.
Direct private IP submission
Submitting http://10.0.0.1/admin directly. Blocked by resolving the host and checking against private IP ranges with FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE.
DNS rebinding via redirect chain
Submitting a public URL that redirects to an internal IP via HTTP 301/302. Blocked by re-running SSRF validation on every redirect hop, not just the initial URL.
Executable file upload disguised as document
Uploading a script with a .pdf extension. Blocked by reading the file's actual magic bytes via PHP's finfo instead of trusting the browser-supplied MIME type or extension.
Website crawler weaponized as internal scanner
Triggering the crawler on an internal hostname. The same SSRF validation runs inside CrawlWebsiteJob — every discovered link is validated before being fetched, and the crawler is bounded to the same host as the starting URL.
11 — Summary
What We Built, and What It Took
Knavia is not a wrapper around a language model. It is a purpose-built system for one specific job: answering questions from business knowledge, reliably and verifiably, with no hallucination leakage. That job is harder than it sounds. It requires coordination across ingestion, chunking, semantic augmentation, hybrid retrieval, context assembly, and prompt architecture — all of it working together.
Small chunks for retrieval precision. Large chunks for answer context. Both stored per document segment.
Every chunk is pre-augmented with 5 hypothetical questions, bridging the embedding gap between declarative documents and interrogative queries.
Dense vector search and MySQL FULLTEXT run in parallel. Reciprocal Rank Fusion merges results without score normalization.
Explicit 4,000-token budget. History drops oldest-first. Knowledge is guaranteed a 1,000-token minimum floor. No silent truncation.
Appended after any custom prompt — not overridable. The model cannot use training data for factual answers, regardless of configuration.
DNS resolution + private IP check on every URL and every redirect hop. Magic byte validation on all file uploads.
Deploy Knavia for Your Business
Give your customers an AI that knows your products — and nothing else. Available as a managed service through knavia.rasnu.com.