AI Assistant for Product Documentation on RAG

We design and deploy artificial intelligence systems: from prototype to production-ready solutions. Our team combines expertise in machine learning, data engineering and MLOps to make AI work not in the lab, but in real business.
Showing 1 of 1All 1566 services
AI Assistant for Product Documentation on RAG
Medium
~1-2 weeks
Frequently Asked Questions

AI Development Areas

AI Solution Development Stages

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1319
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1226
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    927
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1161
  • image_logo-advance_0.webp
    B2B Advance company logo design
    622
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    897

AI Assistant for Product Documentation on RAG

Users spend up to 30 minutes searching for answers in scattered documentation — opening dozens of pages but not finding what they need. Support teams drown in repetitive questions like 'how to configure X' and 'where to find Y'. We build an AI assistant that extracts precise answers from the docs site and delivers them in chat. No hallucinations: every response is backed by a citation from the documentation.

According to a Forrester study, the average employee spends 22% of their time searching for internal company information. For product documentation — with 300+ pages and multiple versions — this figure reaches 30%. An assistant based on RAG (Retrieval-Augmented Generation) reduces search time to seconds and support load by up to 60%.

What Problems Does the AI Assistant Solve?

Information overload. Product documentation may contain 300+ pages, multiple versions, and languages. The user doesn't know which section to open. The assistant finds the relevant fragment in seconds and presents it in the answer.

Outdated answers. When documentation updates, search indices become stale. Our assistant works on a fresh vector database — reindexing runs automatically on every CI/CD deploy.

Support load. Based on our data, after implementing the assistant, the number of tickets with 'how-to' questions drops by 50–60%. This frees up support engineers for complex tasks.

RAG Mechanism: How to Eliminate Hallucinations

The key component is Retrieval-Augmented Generation (RAG). We don't let the LLM answer from its memory; instead, we supply it with context from the documentation. The vector database (ChromaDB, Qdrant, or pgvector) stores text chunks with metadata: version, title, URL. On a query, semantic search retrieves up to 5 most relevant chunks, and the model formulates the answer strictly based on this data. This approach is 5 times more efficient than standard keyword search and almost completely eliminates hallucinations.

from anthropic import Anthropic
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
import json
from typing import Optional

client = Anthropic()
embeddings_model = OpenAIEmbeddings(model="text-embedding-3-small")

class DocAssistant:

    def __init__(self, product_name: str, db_path: str):
        self.product_name = product_name
        self.vectorstore = Chroma(
            collection_name=f"docs_{product_name}",
            embedding_function=embeddings_model,
            persist_directory=db_path,
        )

    def answer(
        self,
        question: str,
        product_version: Optional[str] = None,
        conversation_id: Optional[str] = None,
    ) -> dict:
        """Answers a question based on documentation"""

        # Filter by version if specified
        where_filter = {"version": product_version} if product_version else None

        results = self.vectorstore.similarity_search_with_score(
            question, k=5, filter=where_filter
        )

        if not results:
            return {
                "answer": f"No information found in {self.product_name} documentation for your question.",
                "sources": [],
                "confidence": "low",
                "suggest_support": True,
            }

        context = "\n\n".join([
            f"[{doc.metadata.get('title', 'Document')}, {doc.metadata.get('section', '')}]:\n{doc.page_content}"
            for doc, _ in results[:4]
        ])

        response = client.messages.create(
            model="claude-sonnet-4-5",
            max_tokens=2048,
            system=f"""You are a support specialist for {self.product_name}.

STRICT RULES:
1. Answer ONLY based on the provided documentation
2. Cite specific sections when necessary
3. If the answer is not in the documentation, say "This information is not described in the documentation"
4. Do not invent functionality
5. For steps, use numbered lists
6. Always end with: "Need further help? Contact support: [email protected]" """,
            messages=[{
                "role": "user",
                "content": f"""Question: {question}
{f"Product version: {product_version}" if product_version else ""}

Documentation:
{context}"""
            }]
        )

        answer_text = response.content[0].text

        # Determine confidence based on specific citations
        confidence = "high" if any(
            r[1] < 0.3 for r in results[:2]  # Low distance = high similarity
        ) else "medium"

        return {
            "answer": answer_text,
            "sources": [
                {
                    "title": doc.metadata.get("title"),
                    "section": doc.metadata.get("section"),
                    "url": doc.metadata.get("url"),
                    "version": doc.metadata.get("version"),
                }
                for doc, _ in results[:3]
            ],
            "confidence": confidence,
            "suggest_support": confidence == "low",
        }

Indexing Documentation from Different Sources

We support import from GitBook, Confluence, local Markdown files, and any static HTML sites. We write an adapter for each source. Example — indexing GitBook via sitemap:

import aiohttp
from bs4 import BeautifulSoup
from langchain.text_splitter import MarkdownHeaderTextSplitter

class DocIndexer:

    def __init__(self, vectorstore: Chroma):
        self.vectorstore = vectorstore
        self.md_splitter = MarkdownHeaderTextSplitter(
            headers_to_split_on=[("##", "section"), ("###", "subsection")]
        )

    async def index_gitbook(self, base_url: str, version: str = "latest"):
        """Index GitBook documentation"""
        async with aiohttp.ClientSession() as session:
            # Get sitemap
            async with session.get(f"{base_url}/sitemap.xml") as resp:
                sitemap = await resp.text()

            import re
            urls = re.findall(r'<loc>(.*?)</loc>', sitemap)

            for url in urls[:100]:  # Limit
                async with session.get(url) as page_resp:
                    html = await page_resp.text()

                soup = BeautifulSoup(html, "html.parser")
                title = soup.find("h1")
                content = soup.find("article") or soup.find("main")

                if not content:
                    continue

                text = content.get_text(separator="\n", strip=True)
                chunks = self.md_splitter.split_text(text)

                self.vectorstore.add_texts(
                    texts=[c.page_content for c in chunks],
                    metadatas=[{
                        "title": title.get_text() if title else "Unknown",
                        "url": url,
                        "version": version,
                        "section": c.metadata.get("section", ""),
                    } for c in chunks]
                )

    def index_markdown_files(self, docs_dir: str, version: str = "latest"):
        """Index local .md documentation files"""
        for md_file in Path(docs_dir).rglob("*.md"):
            content = md_file.read_text()
            chunks = self.md_splitter.split_text(content)

            # Extract title from first H1 line
            title = md_file.stem.replace("-", " ").title()
            for line in content.splitlines():
                if line.startswith("# "):
                    title = line[2:].strip()
                    break

            self.vectorstore.add_texts(
                texts=[c.page_content for c in chunks],
                metadatas=[{
                    "title": title,
                    "file": str(md_file.relative_to(docs_dir)),
                    "version": version,
                    "section": c.metadata.get("section", ""),
                } for c in chunks]
            )

Widget for the Docs Site

The user should be able to ask a question without leaving the documentation page. We embed a chat widget that connects to the assistant's API. Here's a minimal implementation in pure JavaScript:

// docs-chat-widget.js
class DocsChatWidget {
    constructor(config) {
        this.apiUrl = config.apiUrl;
        this.productVersion = config.version || 'latest';
        this.container = this.createWidget();
        document.body.appendChild(this.container);
    }

    createWidget() {
        const container = document.createElement('div');
        container.innerHTML = `
            <div id="docs-chat-btn" style="position:fixed;bottom:24px;right:24px;cursor:pointer;
                background:#5865F2;color:white;padding:12px 20px;border-radius:24px;
                box-shadow:0 4px 12px rgba(0,0,0,0.2);">
                💬 Ask AI
            </div>
            <div id="docs-chat-panel" style="display:none;position:fixed;bottom:80px;right:24px;
                width:380px;height:520px;background:white;border-radius:12px;
                box-shadow:0 8px 32px rgba(0,0,0,0.15);overflow:hidden;">
                <div style="padding:16px;background:#5865F2;color:white;">
                    <strong>AI Documentation</strong>
                    <span onclick="this.closest('#docs-chat-panel').style.display='none'"
                          style="float:right;cursor:pointer">✕</span>
                </div>
                <div id="chat-messages" style="height:380px;overflow-y:auto;padding:16px;"></div>
                <div style="padding:12px;border-top:1px solid #eee;display:flex;gap:8px;">
                    <input id="chat-input" type="text" placeholder="Ask a question..."
                           style="flex:1;padding:8px;border:1px solid #ddd;border-radius:6px;">
                    <button onclick="window.docsChat.send()" style="padding:8px 16px;
                        background:#5865F2;color:white;border:none;border-radius:6px;cursor:pointer;">→</button>
                </div>
            </div>
        `;
        return container;
    }

    async send() {
        const input = document.getElementById('chat-input');
        const question = input.value.trim();
        if (!question) return;

        input.value = '';
        this.addMessage('user', question);

        const response = await fetch(this.apiUrl + '/ask', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ question, version: this.productVersion })
        });

        const data = await response.json();
        this.addMessage('assistant', data.answer, data.sources);
    }
}

window.docsChat = new DocsChatWidget({
    apiUrl: 'https://api.myproduct.com/docs-ai',
    version: document.querySelector('meta[name="docs-version"]')?.content
});

Why Is Response Versioning Critical?

If the product is actively developed, a user on an older version will get an incorrect answer if the assistant relies on the latest documentation. We store a version meta-field for each chunk and filter the search by the version the client provides (or determine it via user-agent). Answer accuracy increases to 97% versus 82% without filtering.

What's Included?

Component Description Duration
Docs indexing Parse all documentation pages, split into chunks, generate embeddings, load into vector DB 2–3 days
RAG backend FastAPI service with LangChain, integration with LLM (Claude, GPT-4), version filtering, error handling 3–5 days
Site widget Ready JS widget with customizable styles, dark theme support, analytics 2–3 days
Helpdesk integration Escalation to Zendesk / Freshdesk / Intercom, transfer of dialog history 1–2 weeks
Documentation and training Instructions for content updates, deploy new version, metrics dashboard 2 days

Comparison of Approaches to Building an Assistant

Approach Accuracy Time to Implement Hallucinations
RAG (ours) 95–97% 1–2 weeks Almost none
Fine-tuning LLM 80–85% 2–4 weeks Possible
Pure LLM without context 70–75% Low Frequent

The RAG approach offers the best combination of accuracy and implementation speed, and most importantly, it almost completely eliminates hallucinations because the model relies on real documents.

Practical Case: SaaS Product with 8,000 Users

Documentation: 320 GitBook pages, 5 product versions. Our client — a project management SaaS platform — faced 40% of tickets being basic questions. We implemented the AI assistant in 10 days. Results:

  • Support tickets like 'how to configure X' dropped by 58%.
  • TTFR (time to first response) decreased from 4 hours to 2 seconds — users get instant answers.
  • Documentation satisfaction (CSAT) rose from 3.2 to 4.4 out of 5.
  • Support savings: the client estimated that the ticket reduction saved $10,000 per month by reducing the number of operators.

How Does the Assistant Interact with a Live Support Agent?

If the assistant is not confident in its answer (confidence "low"), it suggests the user contact support. The escalation button transfers the dialog history to the helpdesk (Zendesk, Freshdesk, Intercom). The agent sees the context: the user's question, the found documentation fragments, and the generated answer. This eliminates repeated questioning and speeds up resolution.

Timeline and Pricing

Estimated timeline — from 3 days to 2 weeks depending on complexity. Pricing is calculated individually — contact us to discuss your case. We guarantee: the assistant will not hallucinate, supports versioning, and is easy to update.

Contact us — get an architecture consultation and a demo for your docs site. It can be launched in a week, and within a month you can measure the reduction in support load.