Привет, Хабр!
Меня зовут Анатолий, занимаюсь автоматизацией бизнес-процессов и применением Искусственного Интеллекта в бизнесе.
Кейсовая задача — создать Систему генерации ответов на основе существующей истории тикетов. При этом Система должна работать в закрытом контуре.
Это вторая часть.
В первой части был рассмотрен подход Question-Answering с timpal0l/mdeberta-v3-base-squad2 (модификация BERT для задач Question-Answering) — модели, умеющей «читать» текст и «вытаскивать» ответы.
В этой части переходим к семантическому поиску, контекстному сходству и SentenceTransformer.
SentenceTransformer
SentenceTransformer — библиотека для преобразования текста в векторные представления (эмбеддинги). SentenceTransformer позволяет преобразовывать слова и предложения в числовые представления, которые учитывают смысл, а не только лексическое совпадение. Это ключевое отличие от классического поиска по ключевым словам.
Поиск релевантных тикетов
-
Формирование базы знаний
Ответы сотрудников из истории тикетов собрали в массив answers. Этот массив становится нашей базой знаний для дальнейшей векторизации. -
Загрузка модели
Использовали модель deepvk/USER-bge-m3, оптимальное решение для русскоязычных текстов. Модель специализируется на понимании контекста и преобразовании текста в векторные представления, сохраняя его смысловую нагрузку. . -
Векторизация истории тикетов
Каждый текст из массива answers проходит через модель и превращается в вектор фиксированной размерности. Это позволяет перейти от сравнения строк к анализу векторов, что дает возможность находить ответы, близкие по смыслу, даже если они сформулированы иначе. -
Векторизация вопроса
Вопрос пользователя также векторизуется с использованием той же модели. Теперь вопрос и ответы представлены в одном векторном пространстве. -
Вычисление косинусного сходства
После преобразования вопроса и ответов в векторы основная задача — найти наиболее релевантные тикеты. Для этого применяется косинусное сходство — метрика, показывающая степень близости векторов вопроса и ответа в многомерном пространстве. Значения варьируются от -1 (противоположные по смыслу) до 1 (полностью идентичные).
Вычисляется косинусное сходство между вектором вопроса и всеми векторами ответов. -
Ранжирование результатов
Ответы сортируем по убыванию косинусного сходства, чтобы определить TOP-N релевантных тикетов.
Код на python
import torch from sentence_transformers import SentenceTransformer import numpy as np # Инициализация модели model_name = "deepvk/USER-bge-m3" model = SentenceTransformer(model_name) # Перемещение модели на GPU, если доступно device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") model = model.to(device) # Преобразование текстов тикетов в эмбеддинги embeddings_answers = model.encode(answers, normalize_embeddings=True) # Преобразование текста вопроса в эмбеддинг embeddings_question = model.encode(question, normalize_embeddings=True) # Вычисление косинусного сходства scores = embeddings_question @ embeddings_answers.T # Создание массива с показателями и текстами answers_scores = np.column_stack((scores, answers)) # Сортировка массива по убыванию косинусного сходства sorted_answers_scores = sorted(answers_scores, key=lambda x: x[0], reverse=True)
Примечание
Согласно карточке deepvk/USER-bge-m3 на huggingface, модель поддерживает окно контекста 8194 токена — этого достаточно для обработки большинства текстов ответов в тикетах без разбиения на чанки. Это упрощает реализацию и ускоряет обработку. В будущем можно добавить чанкинг, если при оптимизации качества анализ покажет такую необходимость. На текущем этапе разбиение не делали.
В результате формируется двумерный массив, в котором каждая строка содержит значения косинусного сходства, отсортированные по убыванию, и соответствующие тексты ответов из истории тикетов. Такой формат обеспечивает мгновенный доступ к TOP-N релевантных текстов для дальнейшей работы или выдачи.
Интеграция и веб-сервис
На основе предыдущего кода и Flask создали веб-сервер, который обрабатывает входящие HTTP-запросы с вопросами и возвращает JSON-ответ с TOP-N релевантных тикетов.
Варианты применения
Данное решение легко адаптируется под разные задачи — от помощи сотрудникам до полной автоматизации ответов.
Два ключевых варианта применения:
-
Ассистент для сотрудников
Сотрудники могут отправлять на сервер вопросы и моментально получать TOP-N релевантных тикетов, ранжированных по косинусному сходству. Это позволяет сотрудникам не искать информацию вручную, упрощает формирование собственных ответов, помогает более быстрой адаптации новому сотруднику. -
Полная автоматизация ответов
Для полной автоматизации ответов разворачивается Ollama с квантизованной Llama3.2 (оптимизирована для работы на CPU/GPU средней мощности) и генерируется автоматический ответ на основе полученных TOP-N релевантных тикетов, ранжированных по косинусному сходству.
Оптимизация хранения и загрузки данных
Также мы создавали массив answers не только из текстов тикетов, но и включали в него идентификаторы тикетов. И в таком случае в sorted_answers_scores хранили не тексты тикетов, а идентификаторы тикетов. Это давало некоторые преимущества, так как комбинация «эмбеддинги + идентификаторы» занимают значительно меньше места по объему памяти, чем «эмбеддинги + полные тексты».
В финальной версии мы использовали MySQL для хранения таблицы: идентификаторы, тексты, эмбеддинги.
При запуске Системы загружались только идентификаторы и эмбеддинги (минимальная нагрузка на память и передачу данных). После вычисления косинусного сходства тексты по идентификаторам подгружались только для TOP-N релевантных тикетов.
Выявленные критические проблемы
До этого момента все было хорошо, однако в дальнейшем были выявлены две критические проблемы, напрямую влияющие на качество, актуальность и достоверность ответов:
-
Проблема достоверности: противоречия в исторических ответах
Изначально предполагалось, что ответы сотрудников в истории тикетов корректны и согласованы. Однако на практике выявилось, что иногда разные сотрудники дают различающиеся ответы на один и тот же вопрос. Например:
«Срок обработки заявки — до 3 дней»
«Срок обработки заявки — до 5 дней»
Система не может определить, какой ответ верный, так как для Системы оба варианта считаются одинаково корректными с точки зрения семантического сходства. Отсутствует механизм валидации — алгоритм только ищет сходство по смыслу, но не проверяет правильность. -
Проблема актуальности: устаревание информации в истории тикетов
История тикетов — это статичный снимок прошлого. Если процессы, правила или документация изменяются, то Система все равно продолжает выдавать устаревшие ответы, не учитывая обновления.
Стратегическое решение: отказ от истории тикетов в пользу валидированной документации
Технически Система функционировала корректно, но упомянутые критические проблемы сделали ее непригодной для реального использования.
Важно, что противоречивость и устаревание исходной информации никак не решаются технически — ни увеличением размера окна контекста, ни улучшением эмбеддингов, ни масштабированием аппаратных мощностей. Это недостаток самого подхода, но не техническая проблема. Без валидации данных Система не может гарантировать достоверность и актуальность ответов.
Поскольку валидация истории тикетов не планировалась, в итоге мы отказались от использования истории тикетов в пользу более надежного решения: поиску TOP-N релевантых фрагментов аналогичным образом, но в валидированной документации.
ссылка на оригинал статьи https://habr.com/ru/articles/945404/
Добавить комментарий