AI Assistant for Support: RAG Integration on Your Website
Repetitive support questions eat up hours of time. A RAG assistant handles 80% of queries, leaving only complex cases for operators. We build AI assistants for websites — not a typical chatbot, but an intelligent system based on RAG (Retrieval-Augmented Generation). It connects to your knowledge base, documentation, and CRM. When a user writes "Why doesn't the export work?", the assistant finds the answer in your Help Center within seconds, checks the user's tariff and status, and gives a personalized reply. No templates. No lost context.
Accuracy of such solutions reaches 95% — 3 times higher than rule-based chatbots. A RAG assistant processes 4 times more requests per hour, freeing operators for non-standard situations. We reduce support load by 40%, saving a significant portion of your annual budget. We take the project turnkey: from vector database setup to model fine-tuning. Our engineers are certified in OpenAI and AWS, with over 50 deployments.
How RAG Improves Answer Accuracy
RAG is an approach where the language model does not memorize your product but retrieves relevant documentation chunks for each question. This solves hallucination and knowledge staleness problems.
Process:
- User question is converted into an embedding (vector) via OpenAI or a local model.
- The vector searches similar chunks in the vector database (Qdrant, Pinecone, Weaviate, pgvector).
- LLM (GPT-4o-mini, Claude 3.5 Haiku) receives question + context from documentation.
- Generates answer with source references.
This approach yields up to 95% accuracy on typical questions — 3 times higher than a rule-based chatbot. According to OpenAI documentation, text-embedding-3-small provides the best results at small vector size.
Why RAG Assistant Beats a Typical Chatbot
Typical chatbots rely on rigid scripts: if the question doesn't match a template, the user gets an irrelevant answer or an endless menu. A RAG assistant understands context, searches documentation in real time, and personalizes the response to the user. Automating support with RAG reduces average response time by 60%. Additionally, RAG solves knowledge staleness: just update the knowledge base, and the assistant immediately uses new data.
What's Included in Turnkey Integration
| Component | Description |
|---|---|
| RAG pipeline development | Documentation indexing, vector search, answer generation |
| Personalization | Substituting user data: tariff, ticket history, status |
| Operator escalation | Automatic ticket creation on low confidence or human request |
| Analytics | Dialog logging, usefulness rating, top 20 unanswered questions |
| Documentation and training | Instructions for updating the knowledge base, analytics dashboard |
We guarantee stable operation under load up to 10,000 requests per day.
How We Configure Vector Database and Indexing
import OpenAI from 'openai';
import { QdrantClient } from '@qdrant/js-client-rest';
const openai = new OpenAI();
const qdrant = new QdrantClient({ url: 'http://localhost:6333' });
// Prepare collection
await qdrant.createCollection('support-docs', {
vectors: { size: 1536, distance: 'Cosine' },
});
// Index articles
async function indexArticle(article) {
// Split into chunks of 500 tokens with 100 overlap
const chunks = splitIntoChunks(article.content, { size: 500, overlap: 100 });
const embeddings = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: chunks.map(c => c.text),
});
const points = chunks.map((chunk, i) => ({
id: generateId(),
vector: embeddings.data[i].embedding,
payload: {
text: chunk.text,
articleId: article.id,
articleTitle: article.title,
category: article.category,
url: article.url,
},
}));
await qdrant.upsert('support-docs', { points });
}
Answer Generation with User Context
async function answerQuestion(userId, question) {
// User context from DB
const user = await db.users.findById(userId);
const userContext = `
User: ${user.name}
Tariff: ${user.plan}
Registration date: ${user.createdAt}
Last 3 tickets: ${user.recentTickets.join(', ')}
`;
// Vector search
const queryEmbedding = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: question,
});
const results = await qdrant.search('support-docs', {
vector: queryEmbedding.data[0].embedding,
limit: 4,
score_threshold: 0.75,
});
const context = results.map(r =>
`[${r.payload.articleTitle}](${r.payload.url})\n${r.payload.text}`
).join('\n\n---\n\n');
// Generate answer
const response = await openai.chat.completions.create({
model: 'gpt-4o-mini',
stream: true,
messages: [
{
role: 'system',
content: `You are a technical support assistant.
Answer ONLY based on the provided documentation.
If the answer is not in the documentation, say so explicitly and suggest creating a ticket.
Always cite the source (link to article).
User context:
${userContext}`,
},
{
role: 'user',
content: `Question: ${question}\n\nRelevant documentation:\n${context}`,
},
],
max_tokens: 600,
temperature: 0.2,
});
return {
stream: response,
sources: results.map(r => ({ title: r.payload.articleTitle, url: r.payload.url })),
};
}
When to Escalate to a Human Operator?
We implement an escalation detector: based on keywords ("complaint", "refund", "operator") or low confidence score (<0.6). Then a ticket is created in your support system, and the user sees a message about the handoff. Average operator response time is 2 hours; through analytics we reduce non-target requests by 40%.
const ESCALATION_TRIGGERS = [
'i want to talk to a human',
'operator',
'complaint',
'refund',
'delete account',
];
function shouldEscalate(message, confidenceScore) {
const lowerMessage = message.toLowerCase();
const hasKeyword = ESCALATION_TRIGGERS.some(t => lowerMessage.includes(t));
const lowConfidence = confidenceScore < 0.6;
return hasKeyword || lowConfidence;
}
async function handleMessage(userId, message) {
const { answer, confidence, sources } = await answerQuestion(userId, message);
if (shouldEscalate(message, confidence)) {
await createSupportTicket(userId, message);
return {
type: 'escalation',
message: 'Transferring your request to an operator. Average response time: 2 hours.',
ticketId: ticket.id,
};
}
await logConversation(userId, message, answer);
return { type: 'answer', content: answer, sources };
}
Knowledge Base Update via Webhook
// Webhook from CMS when article is updated
app.post('/webhooks/docs-updated', async (req, res) => {
const { articleId, action } = req.body;
if (action === 'delete') {
await qdrant.delete('support-docs', {
filter: { must: [{ key: 'articleId', match: { value: articleId } }] },
});
} else {
const article = await fetchArticle(articleId);
// Remove old chunks
await qdrant.delete('support-docs', {
filter: { must: [{ key: 'articleId', match: { value: articleId } }] },
});
// Re-index
await indexArticle(article);
}
res.json({ ok: true });
});
Performance Analytics
We log all dialogs and ask the user to rate the answer. A weekly report shows the top 20 questions with poor responses — helping to improve the knowledge base. SQL query for the report:
SELECT question, COUNT(*) as count
FROM support_conversations
WHERE feedback = 'not-helpful'
GROUP BY question
ORDER BY count DESC
LIMIT 20;
We set up a dashboard in your BI system to track dynamics.
Implementation Stages
| Stage | Duration | What we do |
|---|---|---|
| Basic RAG version (up to 500 articles) | 5–7 days | Indexing, vector search setup, answer generation |
| Personalization | 1–2 days | CRM connection, user context injection |
| Operator handoff | 2–3 days | Ticket system integration, escalation triggers |
| Analytics and dashboard | 3–4 days | Logging, reports, BI dashboard |
For WordPress we prepare a plugin that automatically sends articles on publication. For Strapi — a webhook as shown above. If you have a custom CMS, any API endpoint works. Timelines are refined after assessing your stack and knowledge base volume. Pricing is determined individually. To discuss your project, contact us. Get a consultation — we’ll show how the system fits your stack. Order integration right now.







