LLM для интервью клиентов: считаем темы по респондентам и сохраняем цитаты

Продуктовая команда провела интервью о закупках. Нужно понять, какие проблемы повторяются и какие истории стоит разобрать глубже. LLM может быстро разметить длинные расшифровки темами, но красивый список частых слов легко смещает картину: разговорчивый респондент повторил одну жалобу десять раз и стал «голосом большинства». Единица анализа здесь — человек в выбранной выборке.

Модель полезна на этапе чтения свободного текста: разные люди описывают один барьер разными словами. «Пока начальник подпишет, цена уже другая» и «слишком долго согласуем» могут попасть в тему согласования. Для итогового отчёта нужны проверяемые цитаты, единое значение темы и понятный знаменатель доли.

Сначала договоритесь о словаре

Задайте несколько тем с определениями и примерами. Разделяйте проблему и предложение решения: «хочу кнопку повторить заказ» ещё не объясняет, какую работу клиент выполняет. Разрешите метку «другая тема», чтобы модель не насильно распределяла весь текст по существующим категориям. После первого прохода аналитик объединяет близкие темы и фиксирует новую редакцию словаря.

Сохраните interview_id, respondent_id, quote_id, исходную цитату и присвоенную тему. Один человек может участвовать в нескольких сессиях, поэтому interview_id не всегда подходит для подсчёта людей. Наличие цитаты помогает проверить разметку, но не делает её автоматически правильной: ирония и обсуждение чужого опыта требуют чтения контекста.

Посчитайте итог после проверки разметки

В локальном примере кодирование текста моделью уже выполнено и проверено аналитиком. Скрипт решает следующую задачу: считает людей по темам, сохраняя ссылки на цитаты. Он проверяет принадлежность цитаты респонденту и существование темы. Выборка задаётся отдельно: интервью без найденных проблем тоже должно остаться в знаменателе.

Запустите код обычным Python. В нём четыре участника, три цитаты о согласовании и одна о доставке. У первого респондента две цитаты об одной проблеме. После объединения по людям согласование встречается у двух из четырёх участников, хотя сырых упоминаний было три.

from collections import defaultdict
respondents = {"p1", "p2", "p3", "p4"}
quotes = {
    "q1": ("p1", "Согласование длится неделю"),
    "q2": ("p1", "Подпись руководителя приходится ждать"),
    "q3": ("p2", "Заказ задерживается на согласовании"),
    "q4": ("p3", "Дата доставки меняется без предупреждения")}
labels = [("p1","q1","approval"), ("p1","q2","approval"),
          ("p2","q3","approval"), ("p3","q4","delivery")]
topics = {"approval":"Согласование", "delivery":"Доставка"}
people, evidence = defaultdict(set), defaultdict(list)
for person, quote_id, topic in labels:
    if person not in respondents or topic not in topics:
        raise ValueError("Unknown person or topic")
    if quote_id not in quotes or quotes[quote_id][0] != person:
        raise ValueError("Quote ownership mismatch")
    people[topic].add(person)
    evidence[topic].append(quote_id)
report = [{"topic":topics[t], "respondents":len(people[t]),
           "sample":len(respondents),
           "share":len(people[t]) / len(respondents),
           "quotes":sorted(set(evidence[t]))} for t in topics]
assert report[0]["share"] == 0.5
assert report[1]["share"] == 0.25
for row in report:
    print(row)

Дайте модели определение темы и исходный фрагмент

Пользовательское задание аналитика: «Разметь интервью p1 по барьерам закупки». Передайте q1: «Согласование длится неделю» и q2: «Подпись руководителя приходится ждать». Обе цитаты относятся к p1, но остаются разными основаниями. Словарь задаёт approval как задержку разрешения на закупку, delivery как проблему доставки после оформления.

Присвой цитатам ноль или несколько тем из словаря approval, delivery. Не выводи тему из отсутствия жалобы. Верни массив объектов respondent_id, quote_id, topic, rationale. Сохрани исходные ID. Если подходящей темы нет, верни пустой список тем и предложение новой категории отдельно. Не объединяй разные цитаты и не считай людей.

Для q1 и q2 ожидается approval. Аналитик проверяет rationale рядом с полным фрагментом интервью и только затем передаёт утверждённые связи в labels. Расчёт долей выполняется после этой проверки. Модельный ответ с несуществующим quote_id нужно отклонить ещё до редакторской очереди.

Что написать в отчёте

Корректная формулировка: «в четырёх проведённых интервью двое участников описали трудности согласования». Из этого нельзя получить долю всех клиентов компании: качественные интервью обычно отбирают целенаправленно. Для продуктового решения приложите цитаты, сегмент участников и описание ситуации. Частота темы помогает организовать обсуждение, но серьёзная редкая проблема тоже может требовать отдельного решения.

После изменения словаря сохраните обе версии разметки и повторите подсчёт. Если вчера «ожидание подписи» было отдельной темой, а сегодня вошло в согласование, рост частоты не означает изменение клиентского поведения. Сравнивать можно только результаты с одинаковыми правилами кодирования либо после повторной разметки старого материала.

Как принять модельный этап

Дайте двум аналитикам независимо разметить часть интервью. Разберите спорные цитаты и уточните определения до массового запуска. Затем проверьте модель на других интервью, включая случаи, где человек описывает хороший опыт. Для рабочего инструмента важнее воспроизводимо поддержать анализ, чем назначить как можно больше меток каждому абзацу.

Соберите приложение для проверки разметки

Когда подсчёт и словарь готовы, следующий шаг — автоматизировать чтение новых расшифровок и возвращать проверяемые структурированные результаты. На курсе вы построите LLM-приложение с инструментами, API и интерфейсом, добавите версии промптов, оценку качества и контроль стоимости. Это позволит аналитикам проверять разметку в одном рабочем процессе и видеть последствия изменения инструкции. Откройте программу платного курса «LangChain 1.0.x: c нуля до продакшн LLM-приложений».

Продолжить на практике

  • LangChain 1.0.x: c нуля до продакшн LLM-приложений ↗

    Практический курс по LangChain. Соберёте продакшн LLM-бота: RAG по PDF с цитатами, веб-поиск и трекинг заказов, многошаговый агент для анализа CSV и финальное веб-приложение (UI + API). Плюс профессиональные блоки: PromptOps и версионирование промптов, метрики качества RAG, гибридный поиск с реранком, observability/стоимость, надёжность (ретраи, таймауты), guardrails и отдельный модуль по LangGraph для устойчивых workflow. P.S. Полностью обновили материалы на актуальную версию LangChain