Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

Build a RAG Chatbot for Your Product Documentation

By Kokil Thapa | Last reviewed: August 2026

Users ignore static documentation and file support tickets instead because they cannot find answers quickly. When you build a RAG chatbot for your product documentation, you convert passive markdown files into an interactive knowledge base that answers specific technical questions with cited sources. This approach reduces support load while keeping responses grounded in your actual verified content rather than generic model training data.

What is the core architecture when you build a RAG chatbot for your product documentation?

Retrieval-Augmented Generation (RAG) solves the hallucination problem by forcing the Large Language Model (LLM) to reference your specific documents before generating text. Instead of relying solely on parametric memory, the system performs a similarity search against your indexed documentation at runtime. For PHP developers working with Laravel development in Nepal or globally, this architecture integrates naturally into existing application stacks without requiring a complete rewrite in Python.

DocumentationMarkdown / HTMLChunkerSemantic SplitterEmbedding APIOpenAI / OllamaVector Storepgvector / QdrantUser QueryNatural LanguageLLM GeneratorContext + PromptRetrieved Context
Core RAG architecture separating the offline indexing pipeline from the online retrieval and generation flow

The diagram above illustrates the two distinct phases you must implement. The indexing phase runs asynchronously whenever documentation changes, converting raw text into searchable vectors. The retrieval phase happens synchronously during user interaction, fetching relevant chunks to construct a grounded prompt. In my experience building legal-tech portals where accuracy is non-negotiable, separating these concerns prevents slow user-facing requests and allows you to re-index content independently of the chat interface.

How do you prepare and chunk documentation for reliable retrieval?

Naive character-based splitting destroys semantic meaning and produces poor retrieval results. You must respect document structure when preparing data for your RAG system. Documentation typically contains headers, code blocks, lists, and tables that define logical boundaries. A recursive text splitter that prioritizes these structural markers preserves context far better than arbitrary token counts.

Implementing a structural chunker in PHP

While many RAG tutorials assume Python, PHP 8.4 handles text processing efficiently for documentation-scale workloads. The goal is to create chunks between 512 and 1024 tokens with 10-20% overlap to maintain continuity across boundaries. Here is a practical implementation pattern I have used in production Laravel applications:

<?php

namespace App\Services\RAG;

class DocumentationChunker
{
    public function __construct(
        private int $maxTokens = 800,
        private int $overlapTokens = 100,
    ) {}

    public function chunk(string $markdown, string $sourcePath): array
    {
        // Split by H2/H3 headers first to preserve section context
        $sections = preg_split('/(?=^#{2,3}\s)/m', $markdown);
        $chunks = [];
        
        foreach ($sections as $section) {
            if (str_word_count($section) < 20) continue;
            
            // Further split large sections by paragraphs
            $paragraphs = explode("\n\n", trim($section));
            $currentChunk = '';
            
            foreach ($paragraphs as $paragraph) {
                $testChunk = $currentChunk . "\n\n" . $paragraph;
                
                if ($this->estimateTokens($testChunk) > $this->maxTokens) {
                    $chunks[] = $this->createChunk($currentChunk, $sourcePath);
                    // Overlap: keep last few sentences of previous chunk
                    $currentChunk = $this->getOverlap($currentChunk) . "\n\n" . $paragraph;
                } else {
                    $currentChunk = $testChunk;
                }
            }
            
            if (!empty(trim($currentChunk))) {
                $chunks[] = $this->createChunk($currentChunk, $sourcePath);
            }
        }
        
        return $chunks;
    }
    
    private function estimateTokens(string $text): int
    {
        // Rough approximation: 1 token ≈ 4 chars for English
        return (int) ceil(strlen($text) / 4);
    }
}

This structural approach matters significantly for technical documentation. Code examples should never be split mid-function. Tables should remain intact when possible. When you build REST APIs in Laravel that serve documentation content, consider exposing chunk metadata alongside the raw text so your embedding pipeline can filter or boost results based on section type.

Which vector database should you choose for a PHP-based RAG system?

Your vector store selection depends heavily on existing infrastructure and operational complexity tolerance. For teams already running PostgreSQL 16 or 17, pgvector eliminates an entire category of operational overhead. Dedicated vector databases like Qdrant or Weaviate offer superior performance at massive scale but introduce another service to monitor, backup, and secure.

CriteriaPostgreSQL + pgvectorQdrantPinecone
Infrastructure ComplexityLow (existing DB)Medium (new service)None (managed SaaS)
PHP Client MaturityExcellent (PDO/Eloquent)Good (official SDK)Limited (REST only)
Hybrid SearchNative SQL WHERE + vectorPayload filtering + vectorMetadata filtering
Cost at ScaleLowest (shared resources)Medium (dedicated RAM)Highest (vendor lock-in)
Data SovereigntyFull controlSelf-hostableCloud regions only
Best ForSME apps, legal-tech, complianceHigh-scale dedicated searchRapid prototyping

For most product documentation use cases serving hundreds to low thousands of concurrent users, pgvector on PostgreSQL 17 provides more than adequate performance with dramatically simpler operations. I have deployed this stack for Nepal-based legal platforms where data residency requirements prohibit sending sensitive case information to third-party vector APIs. The ability to run hybrid queries—combining traditional SQL filters on document version or category with semantic similarity in a single statement—proves invaluable for scoped documentation search.

Start: Choose Vector DBData residency required?YESNOExisting PostgreSQL?>1M vectors?pgvector ✓Qdrant ✓Yes → pgvectorNo → QdrantNo → Pinecone
Practical decision framework for choosing vector storage based on compliance, existing infrastructure, and scale requirements

How do you implement the retrieval and generation pipeline in Laravel?

The retrieval step transforms the user's natural language question into a vector embedding, then queries your store for the k-nearest neighbors. The generation step constructs a system prompt that includes both the retrieved context and strict instructions to cite sources. Getting this prompt engineering right determines whether your chatbot helps users or confidently fabricates nonsense.

Building the retrieval service

In Laravel 12, encapsulate vector search logic in a dedicated service class. This keeps controllers thin and makes testing straightforward. Use dependency injection to swap embedding providers between OpenAI for production and a local Ollama instance for development without code changes:

<?php

namespace App\Services\RAG;

use Illuminate\Support\Facades\DB;

class RetrievalService
{
    public function __construct(
        private EmbeddingService $embedder,
        private int $defaultTopK = 5,
        private float $similarityThreshold = 0.75,
    ) {}

    public function retrieve(string $query, ?string $docVersion = null): array
    {
        $queryVector = $this->embedder->embed($query);
        
        $results = DB::select("
            SELECT 
                content,
                source_path,
                section_title,
                1 - (embedding <=> ?::vector) AS similarity
            FROM document_chunks
            WHERE (? IS NULL OR doc_version = ?)
              AND 1 - (embedding <=> ?::vector) > ?
            ORDER BY embedding <=> ?::vector
            LIMIT ?
        ", [
            $queryVector, 
            $docVersion, $docVersion,
            $queryVector, $this->similarityThreshold,
            $queryVector,
            $this->defaultTopK
        ]);
        
        return array_map(fn($row) => [
            'content' => $row->content,
            'source' => $row->source_path,
            'title' => $row->section_title,
            'score' => round($row->similarity, 4),
        ], $results);
    }
}

Note the similarity threshold filter. Returning low-confidence matches introduces noise that degrades LLM output quality. Start conservative at 0.75 and adjust based on real user feedback. For technical SEO audits of documentation sites, I have found that tracking "no results found" queries reveals gaps in both your content and your chunking strategy.

Constructing the grounded generation prompt

The system prompt must explicitly instruct the model to use only provided context and to cite sources. Without these constraints, even well-retrieved context gets mixed with parametric knowledge. Here is a battle-tested prompt template:

You are a technical documentation assistant. Answer questions using ONLY 
the provided context below. Follow these rules strictly:

1. If the context does not contain enough information, say "I don't have 
   enough information in the documentation to answer this fully" and 
   suggest what the user might search for instead.
2. Always cite sources using [Source: filename.md#section] format.
3. Never invent API endpoints, parameters, or configuration values.
4. For code examples, reproduce them exactly as shown in context.
5. If multiple sources conflict, note the discrepancy and present both.

CONTEXT:
@foreach($chunks as $chunk)
---
[{{ $chunk['source'] }}#{{ $chunk['title'] }}]
{{ $chunk['content'] }}
@endforeach

This structured approach produces verifiable answers. Users can click through to source documents, building trust in the system. On legal-tech projects where I have implemented similar patterns, this citation requirement was non-negotiable—attorneys needed to verify every claim against primary sources before advising clients.

UserLaravel AppVector DBLLM API1. Ask question2. Embed + search3. Top-K chunks4. Grounded prompt5. Cited answer6. Response + sourcesLog metrics
Request lifecycle showing synchronous retrieval and generation steps with observability touchpoints

How do you evaluate and improve RAG quality over time?

Deploying the chatbot is the beginning, not the end. Without systematic evaluation, you cannot distinguish genuine improvements from placebo effects. Establish quantitative metrics before launch and track them continuously. Three metrics matter most for product documentation RAG systems:

  • Retrieval Precision@K: What percentage of the top-K retrieved chunks are actually relevant to the query? Measure this by sampling queries and having humans rate relevance. Target above 80% for documentation.
  • Answer Faithfulness: Does the generated response accurately reflect the retrieved context without hallucination? Use LLM-as-judge evaluation with explicit rubrics, or better yet, human review of flagged responses.
  • User Satisfaction Rate: Track thumbs up/down, "helpful" clicks, or follow-up question rates. High follow-up rates often indicate retrieval failure or incomplete answers.

Build feedback collection directly into the chat interface. Every response should include a mechanism for users to report incorrect or unhelpful answers. Store this feedback linked to the specific query, retrieved chunks, and generated response. This dataset becomes your golden evaluation set for testing chunking strategies, embedding models, and prompt variations. When working on website development cost estimation for AI features, I always budget 30-40% of initial build cost for this evaluation infrastructure—it pays for itself within months by preventing costly rework.

Common failure modes and fixes

After deploying RAG systems across multiple production environments, certain failure patterns recur consistently. Recognizing these early saves weeks of debugging:

  1. Over-chunking destroys context: Chunks smaller than 256 tokens lose surrounding explanation. Increase minimum chunk size and add parent-document retrieval where small chunks link back to larger context windows.
  2. Stale embeddings after updates: Documentation changes but vectors do not. Implement webhook-triggered re-indexing or scheduled reconciliation jobs. Never assume your index reflects current docs.
  3. Query-document vocabulary mismatch: Users ask "how to reset password" but docs say "credential recovery procedure." Fine-tune embeddings on domain-specific Q&A pairs or implement query expansion with synonyms.
  4. Prompt injection via documentation: Malicious or poorly written docs contain instructions that override system prompts. Sanitize ingested content and treat retrieved context as untrusted input.

Practical next steps for your documentation chatbot

When you build a RAG chatbot for your product documentation, start with the simplest viable architecture: pgvector on your existing PostgreSQL instance, OpenAI embeddings for quality, and conservative retrieval thresholds. Resist premature optimization toward dedicated vector databases until you have proven the concept with real users and measured actual query volumes. The engineering effort saved by avoiding unnecessary infrastructure complexity compounds over months of maintenance.

Focus your initial iteration on chunking quality and evaluation infrastructure rather than fancy retrieval techniques. Most RAG failures stem from poor data preparation, not sophisticated algorithms. Get the fundamentals right first, then layer on reranking, hybrid search, or fine-tuned embeddings based on measured deficiencies.

If you need help architecting or implementing a documentation chatbot for your Laravel application, reach out to discuss your specific requirements. I have built RAG systems for legal-tech platforms, e-commerce knowledge bases, and technical documentation portals where accuracy and source verification are critical success factors.

Frequently Asked Questions

A Retrieval-Augmented Generation chatbot that retrieves specific documentation chunks before generating answers, reducing hallucinations compared to standalone LLMs.

Custom Laravel-based RAG systems typically cost NPR 150,000–400,000 (USD 1,100–3,000) depending on documentation volume and integration complexity.

Use RAG when documentation updates frequently; fine-tuning requires expensive retraining cycles unsuitable for weekly or daily content changes.

PostgreSQL with pgvector extension handles most documentation workloads under 500,000 chunks without adding operational complexity. In my experience building legal-tech portals like Court Marriage In Nepal, keeping the vector store in the same relational database as your application metadata simplifies backups, permissions, and deployment significantly. Only consider dedicated solutions like Qdrant or Weaviate if you exceed millions of chunks or require sub-10ms latency at scale. For typical product documentation, pgvector on PostgreSQL 16 or 17 provides sufficient performance with familiar tooling.

Avoid naive fixed-size splitting which breaks code examples and API references mid-block. Use semantic chunking that respects markdown headers, code fences, and logical sections. On production Laravel applications I have maintained, chunk sizes between 512 and 1024 tokens with 10–20% overlap preserve context without excessive noise. Always keep parent-child relationships so the retriever can fetch surrounding context when a small chunk matches. Test retrieval quality against real user questions before deploying, as chunk strategy directly impacts answer accuracy more than model selection.

OpenAI text-embedding-3-small offers the best cost-to-quality ratio for English technical docs at roughly USD 0.02 per million tokens. For multilingual documentation including Nepali, consider multilingual-e5-large or BGE-M3 which handle non-Latin scripts better. Run embeddings asynchronously via Laravel queues using Redis 7.x to avoid blocking user requests during indexing. Store embeddings as half-precision floats in pgvector to reduce storage by 50% with negligible recall loss. Benchmark retrieval on your actual documentation corpus rather than trusting generic leaderboards.

Implement strict source attribution requiring every generated answer to cite specific document chunks with verifiable links. Add metadata timestamps to each chunk and filter out content older than your last verified review date. In production systems I have built, adding a confidence threshold below which the bot responds "I could not find current information about this" reduced false answers dramatically. Use hybrid search combining vector similarity with BM25 keyword matching to catch exact terminology mismatches. Regularly audit failed queries to identify documentation gaps rather than blaming the model.

Yes, use Laravel Sanctum or Passport to scope retrieval based on user roles and permissions. Filter vector search results using metadata tags matching the authenticated user's access level before passing context to the LLM. This prevents leaking internal or premium documentation to unauthorized users. On client portals like Mijar Law Associates, I implemented row-level security in PostgreSQL combined with application-level filtering to ensure tenants only retrieve their own documents. Never rely solely on prompt instructions for access control; enforce permissions at the database query layer where they cannot be bypassed.

Build an evaluation dataset of 100–200 real user questions with ground-truth answers extracted from your documentation. Track retrieval precision, answer correctness, and citation validity separately using automated metrics like RAGAS plus human review. Log all conversations with user feedback buttons to capture production failures. On projects I have shipped, we found that tracking "answer helpfulness" ratings correlated better with actual support ticket reduction than synthetic benchmarks. Re-evaluate monthly as documentation evolves, since retrieval quality degrades silently when new content lacks proper chunking or metadata.

The most frequent issues are outdated chunks remaining after doc updates, overly broad chunks returning irrelevant context, and embedding models failing on domain-specific terminology. Another recurring problem is users asking questions that span multiple documents where no single chunk contains sufficient context. In my experience troubleshooting production deployments, adding explicit "last updated" metadata and automated re-indexing pipelines resolved most staleness issues. For cross-document queries, implement query decomposition that breaks complex questions into sub-queries before retrieval. Always monitor token usage costs, as verbose prompts with excessive retrieved context inflate expenses unexpectedly.

Tag every chunk with documentation version metadata and allow users to specify target versions in queries or default to latest stable. Maintain separate vector indices or filtered namespaces per major version to prevent v1 answers contaminating v3 responses. When documentation is deprecated, soft-delete chunks but retain them for historical queries with explicit warnings. On Laravel projects with versioned APIs, I store version ranges in chunk metadata and apply WHERE clauses during retrieval rather than maintaining duplicate indices. This approach scales cleanly and keeps the admin interface simple for content teams managing multiple release branches.

Review your LLM provider's data retention and training policies carefully; OpenAI and Anthropic offer zero-retention API tiers for enterprise customers. For highly sensitive documentation, consider self-hosted models like Llama 3 or Mistral running on your own infrastructure. Encrypt embeddings at rest and in transit, and implement audit logging for all retrieval requests. On legal-tech platforms handling confidential client materials, I have used local Ollama instances with quantized models to avoid any external data exposure entirely. Balance security requirements against operational complexity; self-hosting adds significant DevOps overhead that may not justify marginal risk reduction for public product docs.

Cache frequent query results in Redis 7.x with TTLs matching your documentation update frequency. Pre-compute embeddings for new content during CI/CD pipelines rather than at query time. Use streaming responses to show partial answers while full generation completes. Limit retrieved chunks to 3–5 highest-relevance results instead of flooding the context window. On Laravel applications deployed via Deployer 7, I configure PHP-FPM opcache and enable pgvector HNSW indexes to keep p95 latency under 800ms. Profile your pipeline end-to-end; often the bottleneck is serialization overhead or unoptimized database queries rather than the LLM call itself.

Managed services like Algolia AI Search, Pinecone Assistant, or Notion AI handle infrastructure but limit customization and increase vendor lock-in. Open-source frameworks like LangChain or LlamaIndex accelerate development but add abstraction layers that complicate debugging. For simple FAQ-style docs, traditional search with synonym expansion may suffice without LLM costs. In my practice, I recommend custom Laravel implementations for products requiring tight integration with existing auth, billing, or workflow systems. Use managed solutions only when time-to-market outweighs long-term control, and always evaluate total cost including egress fees and per-query pricing at projected scale.

Trigger re-indexing via webhooks or Git post-commit hooks whenever documentation changes merge to main. Use incremental indexing that processes only modified files rather than rebuilding entire corpora. Store content hashes to detect meaningful changes versus formatting-only edits. On Laravel projects using GitLab CI, I run artisan commands within deployment pipelines to validate index health alongside application tests. Implement dead-letter queues for failed indexing jobs with alerting, as silent failures create dangerous knowledge gaps. Schedule weekly full reconciliation audits comparing source documents against indexed chunks to catch drift. Treat index synchronization as critical infrastructure requiring the same monitoring and rollback capabilities as your application code.

Share this article

Quick Contact Options
Choose how you want to connect me: