Генерация FAQ нейросетью: вопросы из обращений и ответы по базе знаний
Хороший FAQ строится на том, что клиенты правда спрашивают. Показываем пайплайн: группируем обращения, отвечаем по базе знаний со ссылкой на источник и проверяем результат.
5 мин · · автоматизация · бизнес
Если просить нейросеть «напиши FAQ для нашего сервиса», она напишет вежливые вопросы, которые никто не задаёт, и ответы, которых нет в вашей документации. Генерация FAQ нейросетью работает, когда у неё есть два источника: реальные обращения клиентов (откуда берутся вопросы) и ваша база знаний (откуда берутся ответы). Ниже пайплайн из четырёх шагов с кодом на Python, проверками и расчётом стоимости. Заодно разберём, как получить из него текст для сайта.
Шаг 0. Подготовьте обращения
Выгрузите из helpdesk, почты или чата текст обращений за 3–6 месяцев. Оставьте только сами вопросы клиентов, без переписки поддержки. Перед отправкой в модель уберите персональные данные: имена, телефоны, почты, номера заказов. Для вопросов они не нужны, а утечка из логов обходится дорого; про это есть отдельный разбор логирования без утечки данных.
Хватит одной колонки в CSV: идентификатор и текст. Тысяча коротких обращений по 40 токенов — это около 40 000 токенов, то есть задача для самой дешёвой модели.
Шаг 1. Кластеризация вопросов
Цель — превратить «где мой заказ», «когда приедет посылка» и «трек-номер не работает» в один канонический вопрос и узнать, сколько обращений за ним стоит. Сначала это делается пачками, потому что 5 000 обращений в один запрос класть не нужно.
import json
import os
import re
from openai import OpenAI
client = OpenAI(
base_url="https://api.zukko.pro/v1",
api_key=os.environ["ZUKKO_API_KEY"],
)
def ask(model, system, user, max_tokens=3000):
r = client.chat.completions.create(
model=model,Разбейте обращения на пачки по 100–150 штук и вызовите cluster_batch для каждой. Затем соберите канонические вопросы всех пачек в один список и отдайте модели ещё раз с просьбой слить дубликаты и просуммировать ids. Получится список вопросов с частотой. Отсортируйте по убыванию и возьмите верхние 20–40: хвост из единичных обращений в FAQ не нужен.
Эту часть проверьте глазами: откройте по три обращения из каждой группы и убедитесь, что они правда об одном. Дешёвая модель иногда склеивает близкие, но разные темы, например «вернуть деньги» и «отменить заказ».
Шаг 2. Найдите источник для каждого ответа
Ответы должны браться из вашей базы знаний: статьи справки, регламенты, условия. Разрежьте документы на фрагменты по 200–500 слов и дайте каждому идентификатор вроде kb-12. Векторная база для этого не обязательна: для сотни документов хватит поиска по пересечению слов, схему описывает статья про RAG без векторной БД.
def stems(text):
return {w[:5] for w in re.findall(r"\w{4,}", text.lower())}
def pick_chunks(question, chunks, k=4):
q = stems(question)
scored = sorted(chunks, key=lambda c: len(q & stems(c["text"])), reverse=True)
return scored[:k]Срез слов до пяти букв грубый, но отчасти сглаживает русские окончания. Если фрагменты находятся плохо, это сигнал, что в базе знаний нет ответа на частый вопрос. Такой результат ценен сам по себе: вы нашли дыру в документации.
Шаг 3. Ответ со ссылкой на источник
Правило, которое отличает рабочий FAQ от выдуманного: модель отвечает только по переданным фрагментам, указывает идентификаторы и честно сообщает, когда ответа нет.
ANSWER_PROMPT = (
"Ты пишешь ответ для раздела FAQ на сайте. Используй ТОЛЬКО переданные фрагменты. "
"Ответ: 2-4 предложения, спокойный тон, без обещаний сверх текста фрагментов. "
"В конце в квадратных скобках перечисли id использованных фрагментов, например [kb-12][kb-3]. "
"Если во фрагментах нет ответа, верни ровно NO_ANSWER."
)
def make_answer(question, chunks):
context = "\n\n".join(f"[{c['id']}] {c['text']}" for c in chunks)
user = f"Вопрос: {question}\n\nФрагменты:\n{context}"
return ask("claude-sonnet-5-5", ANSWER_PROMPT, user, max_tokens=500)
def check_sources(answer, chunks):
allowed = {c["id"] for c in chunks}
cited = set(re.findall(r"\[(kb-\d+)\]", answer))
return bool(cited) and cited <= allowedФункция check_sources отсекает два вида брака: ответ без ссылки на источник и ссылку на фрагмент, которого модели не давали. Всё, что не прошло, отправляйте в ручную очередь. Для ответов подойдёт модель посильнее, чем для группировки: по таблице Zukko у claude-sonnet-5-5 индекс силы 48, у deepseek-v4.1-flash — 39, но выбирайте по результату на 20 ваших вопросах, а не по индексу.
Ссылки [kb-12] в готовом тексте не публикуйте: они нужны вам для проверки. Перед выкладкой замените их ссылкой на статью справки или уберите.
Шаг 4. Проверка перед публикацией
- Человек читает каждый ответ. FAQ короткий, это час работы, а ошибка в условиях возврата или цене стоит дороже.
- Сверка с источником. Откройте фрагмент и сравните цифры, сроки и названия тарифов. Числа проверяйте особенно внимательно: ошибку в них труднее всего заметить при беглом чтении.
- Вторая модель-проверяющий. Опционально: дайте ответ и фрагмент другой модели и спросите, есть ли в ответе утверждения, которых нет во фрагменте. Это дополнение к проверке человеком, а не замена.
- Единый стиль. Задайте в системном промпте тон и длину, чтобы ответы не звучали как собранные из разных источников.
Готовый FAQ можно разметить для поисковиков в формате JSON-LD:
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [{
"@type": "Question",
"name": "Как узнать статус заказа?",
"acceptedAnswer": {"@type": "Answer", "text": "Статус виден в личном кабинете в разделе «Заказы»."}
}]
}Расширенный сниппет в поиске не гарантирован: поисковики показывают такие блоки избирательно. Разметка остаётся полезной, потому что структурирует страницу. Текст для сайта, собранный этим способом, получается ближе к реальной речи клиентов, чем написанный «с нуля».
Сколько стоит генерация FAQ нейросетью
Цены на 18 октября 2026, за 1M токенов. Пример: 2 000 обращений и 30 итоговых вопросов.
- Группировка на
deepseek-v4.1-flash(вход $0.013, выход $0.038). Вход: 2 000 × 40 = 80 000 токенов, выход около 20 000. Стоимость = 80 000 × 0.013 / 1 000 000 + 20 000 × 0.038 / 1 000 000 = 0.00104 + 0.00076 ≈ $0.002. - Ответы на
claude-sonnet-5-5(вход $0.4, выход $2). На вопрос 3 000 токенов фрагментов и промпта и 200 токенов ответа: вход 30 × 3 000 = 90 000, выход 30 × 200 = 6 000. Стоимость = 90 000 × 0.4 / 1 000 000 + 6 000 × 2 / 1 000 000 = 0.036 + 0.012 = $0.048.
Итого около $0.05 за прогон без учёта повторных запусков. Реальный счёт зависит от длины ваших фрагментов, актуальные цены: GET https://api.zukko.pro/v1/models или страница «Модели» в кабинете. Параметры запроса описаны в справке по chat completions.
Частые вопросы
Можно ли сделать FAQ без обращений, только по документации?
Можно, но вопросы придётся придумывать модели, и они будут про то, о чём логично спросить, а не про то, о чём спрашивают. Даже 200–300 реальных обращений заметно меняют результат.
Что делать, если модель вернула NO_ANSWER?
Это полезный сигнал. Либо в базе знаний нет ответа, и его нужно написать вручную, либо поиск не нашёл нужный фрагмент: увеличьте k или улучшите разбиение документов.
Как получить стабильный JSON от модели?
Попросите «только JSON», обрежьте текст по первой и последней скобке (как в parse_json) и повторите запрос при ошибке разбора. Подробнее в статье про структурированный JSON-ответ.
Как часто обновлять FAQ?
Пересобирайте раз в квартал или после изменения условий: новый срез обращений покажет, какие вопросы выросли, а какие ушли.
Если хотите попробовать на своих данных, создайте ключ в кабинете Zukko и поставьте ему небольшой дневной лимит.
zukko
Платите в 25×
меньше
за Claude Code & ChatGPT
Один ключ fetch_* и base URL api.zukko.pro — в Cursor, Claude Code, Codex и любом SDK.
Похожие статьи
- Нейросеть для тестировщика: тест-кейсы, чек-листы и баг-репортыКак QA-инженеру использовать модель для тест-кейсов, чек-листов и баг-репортов, проверять полноту покрытия и не получить придуманные требования.
- Обезличивание данных перед отправкой в нейросеть: практический подходПерсональные данные не нужно отправлять модели, чтобы она обработала документ. Показываем, как заменять их метками, возвращать в ответ и проверять, что ничего не просочилось.
- Нейросеть для HR: вакансии, письма кандидатам и разбор резюмеМодель может готовить черновики вакансий и писем и делать первичный разбор резюме. Разбираем, что отдавать, как работать с персональными данными кандидатов и как не допустить предвзятых решений.
- Тексты для сайта нейросетью: главная, услуги и FAQ без водыНейросеть пишет гладко, но не знает вашего бизнеса. Как составить бриф с фактами, получить структуру страниц, отредактировать результат до публикации и сколько это стоит.