Обычный чат-бот отвечает по скриптам или галлюцинирует. Бот поддержки с RAG берет ответ прямо из твоих документов - FAQ, инструкций, политик - и не придумывает ничего лишнего. Здесь разберем, как собрать такого бота с нуля: Supabase pgvector для хран…
10+ лет в маркетинге, 300+ клиентских проектов: сайты, реклама, боты. Создатель GoBanana (228K+ пользователей, 11.6 млн ₽ выручки) и VibeCoderz. Делаю AI-продукты сам через Claude Code, Cursor, Windsurf и консультирую тех, кто хочет так же.
Об авторе →Claude Code: новый CLI-агент от Anthropic
Anthropic выпустила Claude Code — терминальный AI-агент для разработчиков. Инструмент работает прямо в командной строке и умеет писать, редактировать и запускать код.
Zcode AI: Полный гид по визуальному интерфейсу для Claude Code и AI-агентов
Узнайте, как использовать Zcode для управления Claude Code, Gemini и Codex в едином GUI. Настройка провайдеров, MCP-серверов и визуальный вайбкодинг.
YouTube-канал с монетизацией из любой точки мира: Пошаговый гайд 2026
Инструкция по созданию YouTube-канала: обход блокировок SMS, настройка расширенных функций через виртуальные номера и правила безопасности для монетизации.
Windsurf Code Maps: Как глубоко понимать архитектуру проекта перед написанием кода
Полный гайд по Windsurf Code Maps, модели Sway 1.5 и Sway Grep. Узнайте, как визуализировать архитектуру кода и ускорить разработку в 13 раз.
Vk Fast Cash Strategy
Аудитория ВКонтакте — это те же люди, что и в Instagram, но 'социальный контракт' площадки другой. Если Instagram — это 'дорогой ресторан' с демонстрацией успеха, то VK — это 'душевная шашлычная'. Здесь не работает глянцевый 'успешный успех
Обычный чат-бот отвечает по скриптам или галлюцинирует. Бот поддержки с RAG берет ответ прямо из твоих документов - FAQ, инструкций, политик - и не придумывает ничего лишнего. Здесь разберем, как собрать такого бота с нуля: Supabase pgvector для хранения, embeddings через OpenAI или DeepSeek, semantic search и генерация ответа через Claude Sonnet 4.6. В конце - готовый промпт для Windsurf.
Обновлено: июнь 2026
TL;DR. RAG-бот поддержки работает в три шага: загружаешь FAQ в векторную базу (Supabase pgvector), при вопросе ищешь похожий текст по смыслу, передаешь его в Claude Sonnet 4.6 и получаешь точный ответ. Стек: Supabase + OpenAI Embeddings + Claude API. Время сборки MVP - 4–6 часов.
RAG (Retrieval-Augmented Generation) - это когда ИИ не придумывает ответ из головы, а сначала ищет нужный кусок в твоей базе документов, и только потом генерирует ответ на его основе.
RAG - аббревиатура Retrieval-Augmented Generation. Грубо переводится как «генерация с подтяжкой данных». Смысл простой: перед тем как ответить, модель ищет в твоей базе знаний фрагменты, похожие на вопрос пользователя. Находит - передает их в контекст. И тогда ответ строится не из обучающих данных модели, а из твоего реального FAQ или документации.

Без RAG: пользователь спрашивает «Как изменить тариф?» - бот отвечает что-то из обучающей выборки, что может не совпадать с твоими реальными условиями.
С RAG: бот находит нужный абзац из твоих правил и отвечает точно. Без галлюцинаций.
Для бота техподдержки это принципиально. Неправильный ответ про тарифы или политику возврата - это репутационный ущерб и прямые убытки.
Вся цепочка - четыре шага: текст в числа, числа в базу, поиск по числам, ответ через LLM. Разберем каждый.
Самое важное понять сразу: компьютер не умеет сравнивать текст по смыслу. Но умеет сравнивать числа. Поэтому весь RAG строится вокруг векторных представлений текста - embeddings.
Embedding - это математический отпечаток смысла. Предложение «Как изменить тариф?» превращается в список из 1536 чисел (у OpenAI) или 384 чисел (у бесплатных open-source моделей). Два похожих по смыслу текста дают похожие наборы чисел - их можно сравнивать математически.

Схема работы:
Весь этот пайплайн можно собрать на TypeScript или Python за несколько часов. Без ML-опыта, только с вайбкодингом и правильным промптом.
Максим: «Ребят, это работает. Мы строили похожую архитектуру для NanaBanana - там бот отвечал на вопросы по продукту. Ключевой момент: чем чище и структурированнее твой FAQ, тем точнее ответы. Мусор на входе - мусор на выходе.»
Для 95% проектов поддержки подойдет Supabase pgvector + Claude Sonnet 4.6. Отдельная векторная БД нужна только при миллионах документов.

| Компонент | Вариант | Цена | Когда выбирать |
|---|---|---|---|
| Векторная БД | Supabase pgvector | Бесплатно до 500 МБ | MVP, стартапы, до 500K документов |
| Векторная БД | Pinecone | $70+/мес | Миллиарды векторов, субмс-латентность |
| Embeddings | OpenAI text-embedding-3-small | $0.02 за 1M токенов | Если нужна максимальная точность |
| Embeddings | GTE-small (Hugging Face) | Бесплатно | 95% проектов, разница в качестве <2% |
| Embeddings | DeepSeek V4 Pro Max | $0.435/$0.87 за 1M | Баланс цена/качество, MIT-лицензия |
| Генерация ответа | Claude Sonnet 4.6 | $3/$15 за 1M | Лучший баланс для поддержки |
| Генерация ответа | Claude Opus 4.8 | $5/$25 за 1M | Сложные кейсы, юридический контент |
| Генерация ответа | DeepSeek V4 Pro Max | $0.435/$0.87 | Экономия на масштабе |
Важный момент по embeddings из транскриптов: на стандартном MTEB-бенчмарке GTE-small набирает 61.36, а OpenAI - 62.26. Разница меньше 2%, которую большинство приложений поддержки никогда не почувствуют. А экономия колоссальная: 100 000 документов обойдутся в $0 против $1 с OpenAI. При ежедневной переиндексации это $50–100 в год только на embeddings.
Но вот нюанс: GTE-small через Supabase Edge Functions добавляет 100–200 мс на embedding. Для batch-обработки FAQ - не критично. Для real-time обновления базы каждую секунду - уже важно.
Чистый, структурированный FAQ - основа точности RAG. Плохой формат входных данных сломает бота даже при идеальном коде.
Перед тем как писать код, нужно привести базу знаний в правильный вид. RAG режет документы на чанки - фрагменты по 300–500 символов с перекрытием 100 символов. Это ограничение контекстного окна модели и оптимизация стоимости: платишь только за релевантный кусок, а не весь документ.

Как структурировать FAQ:
Q: Как изменить тарифный план?
A: Зайдите в Личный кабинет -> раздел "Подписка" -> нажмите "Изменить план".
Изменение вступит в силу с следующего расчетного периода.
Q: Как оформить возврат?
A: Возврат оформляется в течение 14 дней с момента покупки.
Напишите на support@example.com с темой "Возврат", укажите номер заказа.Каждая пара вопрос-ответ - отдельный чанк. Не смешивай несколько тем в один блок. Чем конкретнее формулировка, тем точнее найдет семантический поиск.
Форматы, которые работают:
Что сломает качество:
Supabase pgvector - Postgres с векторным расширением. Один сервис вместо двух: обычные данные и векторный поиск в одной БД.
Supabase - это Postgres с расширением pgvector. Не нужно поднимать отдельный Pinecone или Qdrant. Пользователи, заказы, векторы - все в одной БД без синхронизации между сервисами.
Создание таблицы для FAQ:
-- Включаем расширение
CREATE EXTENSION IF NOT EXISTS vector;
-- Таблица для базы знаний
CREATE TABLE knowledge_base (
id BIGSERIAL PRIMARY KEY,
content TEXT NOT NULL,
category TEXT,
embedding VECTOR(1536), -- 1536 для OpenAI, 384 для GTE-small
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Индекс для быстрого поиска
CREATE INDEX ON knowledge_base
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);Индекс ivfflat ускоряет поиск при росте базы. Для FAQ из 1000 записей - не критично, но при 50 000+ документов разница ощутима.

Функция семантического поиска:
CREATE OR REPLACE FUNCTION search_knowledge(
query_embedding VECTOR(1536),
match_threshold FLOAT DEFAULT 0.7,
match_count INT DEFAULT 5
)
RETURNS TABLE(content TEXT, similarity FLOAT)
LANGUAGE SQL STABLE
AS $$
SELECT
content,
1 - (embedding <=> query_embedding) AS similarity
FROM knowledge_base
WHERE 1 - (embedding <=> query_embedding) > match_threshold
ORDER BY similarity DESC
LIMIT match_count;
$$;Параметр match_threshold - важный рычаг настройки. При 0.7 бот найдет все похожие фрагменты, при 0.9 - только очень близкие. Начинай с 0.7, потом тестируй на реальных вопросах и корректируй.
Ingestion-скрипт нужно запустить один раз. При обновлении FAQ - переиндексировать только изменившиеся документы.
Скрипт загрузки: читает FAQ-файлы, разбивает на чанки, генерирует embeddings, записывает в Supabase.
import { createClient } from '@supabase/supabase-js'
import OpenAI from 'openai'
import { readFileSync } from 'fs'
const supabase = createClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_SERVICE_KEY!
)
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY! })
// Разбиваем текст на чанки
function splitIntoChunks(text: string, chunkSize = 500, overlap = 100): string[] {
const chunks: string[] = []
let start = 0
while (start < text.length) {
const end = Math.min(start + chunkSize, text.length)
chunks.push(text.slice(start, end))
start += chunkSize - overlap
}
return chunks
}
// Генерируем embedding для чанка
async function getEmbedding(text: string): Promise<number[]> {
const response = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: text,
})
return response.data[0].embedding
}
// Основная функция загрузки
async function ingestFAQ(filePath: string, category: string) {
const content = readFileSync(filePath, 'utf-8')
const chunks = splitIntoChunks(content)
console.log(`Загружаем ${chunks.length} чанков из ${filePath}`)
for (const chunk of chunks) {
const embedding = await getEmbedding(chunk)
await supabase.from('knowledge_base').insert({
content: chunk,
category,
embedding,
})
}
console.log('Готово!')
}
// Запуск
ingestFAQ('./faq.md', 'general')Скрипт запускаешь один раз. При обновлении FAQ - либо очищаешь таблицу и переиндексируешь заново, либо добавляешь только изменившиеся документы по ID.
Claude Sonnet 4.6 - лучший выбор для бота поддержки: 79.6% на SWE-bench Verified, $3/$15 за 1M токенов, отличное следование инструкциям.
Это ядро всей системы. После semantic search у тебя есть 3–5 релевантных фрагментов из базы. Их нужно передать в Claude вместе с вопросом пользователя.
import Anthropic from '@anthropic-ai/sdk'
import { createClient } from '@supabase/supabase-js'
import OpenAI from 'openai'
const claude = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY! })
const supabase = createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_ANON_KEY!)
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY! })
async function answerQuestion(userQuestion: string): Promise<string> {
// 1. Превращаем вопрос в embedding
const questionEmbedding = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: userQuestion,
})
// 2. Ищем похожие фрагменты в базе
const { data: relevantChunks } = await supabase.rpc('search_knowledge', {
query_embedding: questionEmbedding.data[0].embedding,
match_threshold: 0.7,
match_count: 5,
})
if (!relevantChunks || relevantChunks.length === 0) {
return 'К сожалению, я не нашел ответа в базе знаний. Обратитесь к живому специалисту поддержки.'
}
// 3. Формируем контекст из найденных фрагментов
const context = relevantChunks
.map((chunk: { content: string }) => chunk.content)
.join('\n\n---\n\n')
// 4. Отправляем в Claude Sonnet 4.6
const response = await claude.messages.create({
model: 'claude-sonnet-4-6',
max_tokens: 1024,
system: `Ты - бот поддержки. Отвечай только на основе предоставленной базы знаний.
Если в базе нет ответа на вопрос - честно скажи об этом и предложи обратиться к специалисту.
Не придумывай информацию. Отвечай кратко и по делу.
База знаний:
${context}`,
messages: [
{ role: 'user', content: userQuestion }
],
})
return response.content[0].type === 'text'
? response.content[0].text
: 'Ошибка формирования ответа.'
}Системный промпт - ключевой момент. Явная инструкция «отвечай только из базы знаний» резко снижает галлюцинации. Без нее Claude иногда додумывает от себя, даже если в контексте есть точный ответ.
Telegram-бот через Grammy или node-telegram-bot-api - самый быстрый способ дать доступ к RAG-боту команде и пользователям.
import { Bot } from 'grammy'
import { answerQuestion } from './rag-engine'
const bot = new Bot(process.env.TELEGRAM_BOT_TOKEN!)
bot.on('message:text', async (ctx) => {
const question = ctx.message.text
// Показываем, что обрабатываем
await ctx.replyWithChatAction('typing')
try {
const answer = await answerQuestion(question)
await ctx.reply(answer, { parse_mode: 'HTML' })
} catch (error) {
await ctx.reply('Произошла ошибка. Попробуйте позже.')
console.error('RAG error:', error)
}
})
bot.start()Бот получает вопрос -> передает в answerQuestion -> возвращает ответ. Индикатор typing показывает, что бот работает - это важно, потому что RAG занимает 2–4 секунды.
Промпт для автоматической сборки проекта через Windsurf IDE. Подходит для Cursor и Claude Code.
Вот промпт, который собирает полный стек с нуля. Используй его в Windsurf или Cursor:
Создай TypeScript-проект: бот поддержки с RAG для Telegram.
Стек:
- Supabase pgvector - векторная база знаний
- OpenAI text-embedding-3-small - embeddings
- Anthropic Claude Sonnet 4.6 (claude-sonnet-4-6) - генерация ответов
- Grammy - Telegram Bot framework
- Node.js + TypeScript
Структура проекта:
/src
/ingest.ts - загрузка FAQ в Supabase
/rag.ts - поиск + генерация ответа
/bot.ts - Telegram бот
/faq - папка для markdown-файлов базы знаний
/.env.example
/README.md
Требования:
1. Функция splitIntoChunks(text, chunkSize=500, overlap=100)
2. SQL-схема: CREATE TABLE knowledge_base с полями id, content, category, embedding vector(1536)
3. SQL-функция search_knowledge с параметрами query_embedding, match_threshold=0.7, match_count=5
4. System prompt для Claude: отвечать только из базы знаний, при отсутствии ответа - направлять к специалисту
5. Telegram бот с typing indicator и обработкой ошибок
6. .env.example с переменными: SUPABASE_URL, SUPABASE_SERVICE_KEY, SUPABASE_ANON_KEY, OPENAI_API_KEY, ANTHROPIC_API_KEY, TELEGRAM_BOT_TOKEN
Создай полный рабочий код всех файлов. После генерации покажи инструкцию по запуску.Этот промпт проверен на практике. После первой генерации может потребоваться 2–3 итерации правок - это нормально. Главное - сразу запускай, смотри на ошибки в консоли и закидывай их обратно в Windsurf.
GTE-small бесплатен и отстает от OpenAI на 2% по MTEB. Для большинства FAQ-ботов это незаметная разница - но экономия значительная.
| Модель | MTEB Score | Размерность | Цена | Латентность |
|---|---|---|---|---|
| OpenAI text-embedding-3-small | 62.26 | 1536 | $0.02/1M токенов | ~50 мс |
| OpenAI text-embedding-3-large | 64.6 | 3072 | $0.13/1M токенов | ~80 мс |
| GTE-small (open-source) | 61.36 | 384 | Бесплатно | 100–200 мс (Edge) |
| DeepSeek Embedding | ~63 | 1536 | $0.05/1M токенов | ~60 мс |
Для старта - OpenAI text-embedding-3-small. Понятна цена, стабильное качество, простая интеграция. Если объем базы знаний растет быстро и embeddings пересчитываются часто - переходи на GTE-small через Supabase Edge Functions.
Нюанс: 384 измерения против 1536 у OpenAI означают меньший объем хранилища и более быстрый cosine similarity search. При базе в 100 000 документов это заметно.
Три ошибки убивают 80% RAG-проектов: плохой FAQ, неправильный threshold и отсутствие fallback.

Ошибка 1: Огромные чанки. Размер 2000+ символов ломает relevance - бот находит «похожий» фрагмент, но в нем нет ответа на конкретный вопрос. Начинай с 400–600 символов, перекрытие 100.
Ошибка 2: Слишком низкий threshold. При 0.5 поиск возвращает нерелевантные результаты, Claude строит ответ из мусора. Начинай с 0.7, тестируй на 20–30 реальных вопросах, повышай до 0.75–0.8 по результатам.
Ошибка 3: Нет fallback. Когда поиск ничего не находит (новый вопрос, которого нет в FAQ), бот должен честно сказать об этом и предложить альтернативу. Без fallback Claude начинает галлюцинировать.
Ошибка 4: FAQ без структуры. Если база знаний - это PDF из 50 страниц сплошного текста, chunker разрежет его произвольно. Структурированный Q&A-формат дает точность в разы выше.
Ошибка 5: Забыли про переиндексацию. Обновил тарифы - переиндексируй базу. Бот будет давать устаревшие ответы до переиндексации, даже если ты поменял FAQ-файл.
Если у тебя есть структурированный FAQ из 50+ вопросов и поток входящих запросов поддержки - RAG-бот окупится быстро.
Подходит хорошо:
Требует дополнительной настройки:
Не подходит:
Если работаешь в сфере техподдержки - загляни на vibecoderz.ru/agents/tehpodderzhka, там есть ИИ-агент с готовыми промптами под эту роль.
При 10 000 запросов в месяц - меньше $10. При 100 000 - около $50–70 в зависимости от модели.
| Компонент | Бесплатный вариант | Платный вариант |
|---|---|---|
| Supabase pgvector | До 500 МБ хранилища | $25/мес - 8 ГБ |
| Embeddings | GTE-small через Edge Functions | OpenAI ~$0.02/1M токенов |
| LLM-ответы | Claude Sonnet 4.6 нет free tier | ~$3/$15 за 1M токенов |
| Telegram бот | Бесплатно | Бесплатно |
| Хостинг | Railway free tier | Railway ~$5/мес |

Расчет на 10 000 запросов/месяц:
При 100 000 запросов: ~$16/мес. Это дешевле одного часа работы специалиста поддержки.
Нужен ли опыт программирования для сборки RAG-бота? Базовый. Нужно уметь работать с .env файлами, запускать npm install и понимать структуру TypeScript-проекта. С промптом для Windsurf из этой статьи большую часть кода генерирует ИИ. Реальный опыт: примерно 4–6 часов от нуля до рабочего бота, если есть готовый FAQ.
Можно ли использовать DeepSeek вместо Claude для ответов? Да. DeepSeek V4 Pro Max стоит $0.435/$0.87 за 1M токенов против $3/$15 у Claude Sonnet 4.6 - в 6–7 раз дешевле. Качество следования инструкциям у DeepSeek хорошее, но Claude точнее соблюдает системный промпт «отвечать только из базы знаний» и реже галлюцинирует. На старте - Claude, на масштабе - тестируй DeepSeek.
Как бот поддержки с RAG узнает, что ответа нет в базе? Через match_threshold в функции поиска. Если ни один фрагмент не превышает порог сходства (например, 0.7), функция возвращает пустой массив. В коде это обрабатывается отдельно: бот честно говорит «не нашел в базе знаний» и предлагает обратиться к специалисту.
Сколько документов можно хранить в Supabase pgvector бесплатно? На бесплатном плане - 500 МБ базы данных. FAQ из 10 000 вопросов с embeddings размерностью 1536 займет примерно 60–80 МБ. То есть на бесплатном плане можно хранить 60 000–80 000 записей. Этого хватит для большинства малых и средних проектов.
Как часто нужно переиндексировать базу знаний? При каждом изменении FAQ. Самый простой подход: помечать документы датой обновления и переиндексировать только те, что изменились. Для небольших баз до 5000 документов - полная переиндексация занимает 5–15 минут и обходится в центы.
Поддерживает ли RAG-бот историю диалога? Нет, в базовой версии. Каждый вопрос обрабатывается независимо. Для истории диалога нужно хранить previous messages и передавать их в Claude как часть контекста. Это усложняет архитектуру и увеличивает стоимость запроса, поэтому для бота поддержки часто достаточно без истории - вопросы поддержки обычно атомарны.
Какой размер чанка выбрать для FAQ? 400–600 символов с перекрытием 100 - стандартная точка старта. Если вопросы и ответы короткие (до 200 символов), можно взять целую пару Q&A как один чанк. Если ответы длинные (инструкции на 3–4 абзаца), разбивай их отдельно и добавляй категорию в метаданные.
RAG (Retrieval-Augmented Generation) - метод, при котором языковая модель перед генерацией ответа извлекает релевантные фрагменты из внешней базы знаний. Позволяет отвечать на основе актуальных данных, а не только обучающей выборки.
Embedding - математическое векторное представление текста. Список чисел, кодирующий смысл предложения или абзаца. Похожие по смыслу тексты имеют похожие числовые представления.
pgvector - расширение для PostgreSQL, добавляющее тип данных VECTOR и операторы для вычисления сходства между векторами (cosine similarity, Euclidean distance).
Semantic search - поиск по смыслу, а не по ключевым словам. Запрос «как поменять тариф» найдет документ «изменение тарифного плана», даже если слово «поменять» в нем не встречается.
Chunk - фрагмент текста фиксированного размера, на которые разбиваются исходные документы перед индексацией.
Cosine similarity - метрика сходства двух векторов. Принимает значения от -1 до 1, где 1 означает идентичное направление векторов (максимальное сходство).
Match threshold - порог сходства при семантическом поиске. Фрагменты с cosine similarity ниже порога не возвращаются как результат.
Ingestion pipeline - процесс загрузки документов в векторную базу: чтение -> разбивка на чанки -> генерация embeddings -> запись в БД.
Grammy - TypeScript-фреймворк для Telegram-ботов. Аналог telegraf.js, более современный и с лучшей типизацией.
Собери бот за выходные - смотри каталог AI-инструментов для выбора IDE. Если хочешь разобрать архитектуру под твой конкретный проект - запишись на консультацию к Максиму.
Обновлено: июнь 2026