Есть отечественный файрвол (NGFW). У этого файрвола есть документация для пользователей powered by GitBook, на русском языке. В этой документации работает простой поиск — только по словам и словосочетаниям. И это плохо, потому что нет ответов на вопросы:
Какие алгоритмы шифрования ipsec поддерживаются у вас?
Как заблокировать ютуб?
Как настроить DMZ?
Хочется, чтобы поиск был "умным" и чтобы пользователи могли обращаться с подобными вопросами именно к поиску, а не к инженерам тех. поддержки. AI или ML внутри — не важно, как это называть. Но на простые вопросы из списка выше поиск должен отвечать.
Я решил эту задачу (Retrieval Question Answering), используя OpenAI API. Казалось бы, уже опубликованы сотни похожих инструкций, как это сделать. Но под катом будет не инструкция, а рассказ про сложности, которые пришлось решить на пути от идеи до запуска поиска: как прикинуть бюджет, быстро собрать прототип с сохранением всех ответов и оценок обратной связи, организовать альфа- и бета-тестирование, позвать асессоров и разметить собранный датасет, подвести итоги проекта и наметить следующие шаги.
Постановка задачи
Итак, уточняем задачу.
Есть документация по продукту, внутри — база документов в формате markdown.
Нужно по этой документации сделать "умный" поиск (далее — GPT поиск или бот).
В ответах мы хотим увидеть и ссылки на источники. Как окажется позже, наличие правильно подобранных ссылок на источники даже при ответе плохого качества — нравится пользователям поиска.
Те, кто знакомы с большими языковыми моделями (LLM), знают, что эта задача называется Retrieval QA.
При решении этой задачи главным ограничением выступает максимальная длина запроса к модели: нужно как-то передать в модель всю базу документов, по которой должен работать поиск, а длина запроса ограничена. И самый простой способ обойти это ограничение — сначала во всей базе документов оставить только те, которые могут иметь отношение к ответу на вопрос, а затем передать эти документы (вместе с исходным вопросом) в языковую модель, и перейти к шагу генерации ответа.
Предварительные изыскания
Перед тем, как браться за задачу, проверим, а можно ли её вообще не делать?
Что было сделано на первых шагах (пишу во множественном числе, потому что мне помогали коллеги):
Для начала мы собрали статистику поиска по документации продукта и ещё раз убедились, что поиск нужно делать. Вопросы, которые задавали пользователи продукта, в большинстве случаев оставались без ответов (см. три вопроса во вступительной части).
Разобрались с GitBook, нельзя ли подключить плагин поиска Algolia или подобный? Нет, в июне 2023 года это сделать было нельзя. Были лишь планы разрешить сторонним разработчикам создавать свои собственные плагины, но без указания сроков.
На тот момент у GitBook был доступен "умный" AI поиск — Lens (сегодня он по умолчанию включен). Мы включили его для теста, но оказалось, что с русским языком он не работает. Выглядело это так себе: задаёшь вопрос на русском языке, а получаешь ответ на английском. Да ещё и качество в сравнении с привычными чат-ботами chat.openai.com и perplexity.ai неудовлетворительное.
Сначала попробовали сделать "умный" поиск локальным — скачать к себе языковую модель, локально задавать ей вопросы и получать ответы. Наиболее подходящей моделью тогда оказалась Dolly. Запустили прототип, на русском языке сравнили качество ответов модели с привычными чат-ботами, не понравилось.
Всё, что мы смогли до сих пор сделать, по качеству ответов сильно уступало чат-боту ChatGPT. Похоже, пришло время протестировать OpenAI API.
Разработка прототипа "умного" поиска
Шаг 1. Быстро решить задачу Retrieval QA.
В этом проекте я решал задачу Retrieval QA впервые, за основу для первых набросков взял эту инструкцию.
Пример построен с применением фреймворка для работы с языковыми моделями — LangChain, в качестве языковой модели используется модель GPT 3.5 Turbo от компании OpenAI. Код не буду повторять, расскажу лишь про неочевидные детали:
Для работы с OpenAI API понадобится API-ключ, который можно получить после регистрации на https://openai.com/ (доступ из России блокируется, помогает VPN).
Услуга платная, для новых пользователей дают несколько долларов, чтобы протестировать возможности.
Начать можно с пробной версии, а дальше уже привязать карту (не российскую, помогает поисковая выдача по запросу: "Оплата иностранных сервисов, подписок и товаров").
Итак, цепочка RetrievalQAWithSourcesChain работает, я получаю ответы на вопросы по базе документов. При выставленном параметре "температура" в ноль (так я прошу модель в качестве источников использовать только предъявленную базу документов) качество ответов вполне устраивает, ответы заметно лучше по сравнению с Dolly и GitBook Lens.
Теперь всё это нужно упаковать в сервис для пользователей.
Шаг 2. Прикинуть бюджет.
Но сначала прикидываю бюджет. Точнее, выбираю между GPT-3.5 Turbo и GPT-4. Тариф на входящие токены для модели GPT-3.5 Turbo — $0.001 за тысячу токенов, в то время как у GPT-4 — $0.03. Тариф на исходящие токены для GPT-3.5 Turbo — $0.002, а у GPT-4 — $0.06.
Выходит, что вопросы и ответы у модели GPT-4 дороже в ~30 раз. Пока выбираю модель GPT-3.5 Turbo.
Первые эксперименты показали, что с учётом всех комиссий один вопрос к модели стоит ~1 российский рубль. Сразу же для защиты от непорядочных бета-тестеров выставляю порог расходов в личном кабинете OpenAI. Если начнут ддосить — сервис просто перестанет давать ответы.
Пока это всего лишь прототип для проверки гипотезы, поэтому на следующих шагах быстро собираю финальное решение.
Шаг 3. Быстро сделать фронтенд.
Фронтенд будет обращаться к бекенду с вопросами пользователей. Для быстрого старта подойдёт Twitter Bootstrap 5.
Шаг 4. Быстро сделать бекенд.
Выбираю FastAPI. Не зря он fast, отлично подходит для решаемой задачи.
Шаг 5. Подключить к модели полную документацию продукта.
Шаг 6. Сохранить все вопросы и ответы.
Для разбора ответов и улучшения сервиса будем сохранять все вопросы пользователей, полученные моделью ответы, источники, ошибки. В самом продукте активно используется ClickHouse, поэтому эти данные складываю туда же.
Шаг 7. Арендовать сервер, где будет работать поиск.
Поскольку к OpenAI API нельзя обращаться напрямую из России, выбираю дата-центр за пределами.
Шаг 8. Выбрать доменное имя.
Шаг 9. Подключить сертификаты LE.
И проверить, что всё работает и нет предупреждений безопасности, которые могут отпугнуть будущих пользователей поиска.
Шаг 10. Запустить альфа-тестирование.
Устраиваем альфа-тестирование нового поиска среди сотрудников компании. Обрабатываем шквал скриншотов с замечаниями и предложениями, даже находим ошибки в исходной документации, исправляем. Стало понятно, что перед бета-тестированием нужно добавить обратную связь.
Вспоминаем Алексея Лысенкова — бессменного ведущего передачи "Сам себе режиссер". Он рассказывал, что когда команда редакторов просматривает присланные видеоролики, то первые комментарии — они самые живые и смешные, но в эфир попасть не могут, потому что не пройдут цензуру. Чувствуем себя примерно так же, особенно разбирая вопрос про коз.
Шаг 11. Доработать поиск по результатам альфа-тестирования.
Список доработок:
Замечаем, что иногда модель отвечает на английском языке. Исправляю это уточнением промпта.
Обнаруживаем недокументированные коды ошибок модели OpenAI, корректно обрабатываю их.
Набираем примеры разметки источников. Иногда они дописываются в текст ответа, иногда — в структуру данных “источники”. Иногда используется HTML разметка, иногда нет.
Делаю источники кликабельными, удобно же.
Добавляю возможность для каждого ответа выставить оценку: "Плохо" (-1), "Нормально" (0), "Хорошо" (+1). Учу бекенд принимать оценки и сохранять в ClickHouse.
Шаг 12. Запустить бета-тестирование.
Публикуем новость о запуске поиска в официальных каналах компании-разработчика файрвола, запускаем бета-тестирование.
Шаг 13. Оценить результаты тестирования.
Набираем за несколько дней более 300 запросов и уходим обрабатывать ответы. По каждому запросу просим наших дорогих асессоров (сотрудников компании-разработчика файрвола, которые в совершенстве владеют документацией) разметить выборку. Проверить каждый ответ и выставить свою оценку: -1, 0, 1. Также просим прикрепить комментарий, чтобы знать, что можно улучшить.
Подведение итогов
Для оценки качества поиска я выбрал простой подход — Human Evaluation. По размеченной пользователями и асессорами выборке составил таблицу:
Статистика |
От пользователей |
От асессоров |
Всего запросов (с 22.09 по 02.10) |
336 |
336 |
Количество отрицательных оценок |
18 |
122 |
Количество нейтральных оценок |
7 |
63 |
Количество положительных оценок |
18 |
139 |
Без оценок |
293 |
12 |
Асессорам мы доверяем больше, чем пользователям. Поэтому смотрим на самый правый столбец.
Положительных оценок больше отрицательных. Но это ещё не значит, что GPT поиск работает хорошо. Среди ответов с положительной оценкой асессоров много "плохих" вопросов, не относящихся к теме, вроде: "Как настроить велосипед". Поэтому вместе с асессорами обсуждаем детали.
Что работает хорошо:
Если вопрос подробно сформулирован и про это есть конкретно в документации, то GPT поиск генерирует хорошие ответы. Иногда даже добавляет то, чего может не хватать в документации для понимания.
Бот приемлемо хорошо умеет собирать ответ из нескольких блоков с разных страниц документации. Опять же, если вопрос подробно сформулирован и части ответов есть в документации.
В подавляющем большинстве случаев бот находит корректные источники в документации. Уже в этом есть польза, даже если сам ответ плохого качества.
Всё, что мы пробовали до GPT-3.5 Turbo (Dolly, GitBook Lens), по качеству на голову ниже.
Однозначно, такой поиск работает лучше поиска по умолчанию в GitBook.
Что работает плохо:
Бот плохо отвечает на вопросы, которые не освещены в документации. За исключением общих и/или энциклопедических вопросов ("Что такое DNS?").
Модель может фантазировать.
Редко, но модель может ошибаться в источниках.
Модель может давать неполные ответы.
Модель может давать по большей части верные ответы, но добавлять и неподходящие блоки.
Иногда ответ генерируется на данных из файлов changelog старых версий.
Финальный вывод: GPT поиск по документации файрвола работает лучше других поисков, почти всегда даёт правильные источники, генерирует ответ хорошего качества при условии конкретного и подробного вопроса, который описан в документации.
От идеи до запуска GPT поиска прошло около 3 месяцев, ещё месяц ушёл на подведение итогов. Опыт внедрения современных технологий искусственного интеллекта считаем успешным, пора задуматься о стратегии развития AI/ML в компании.
Что делать дальше:
Ответить на вопрос: "Если модель сгенерирует неправдоподобный/ложный ответ, будет ли это безопасно для пользователя?"
Научить бота не отвечать матом.
Научить бота распознавать версию файрвола в вопросе и генерировать ответ по документации нужной версии.
Разобраться, как максимально ускорить сервис. Сейчас отвечает достаточно медленно (и Сэм Альтман признаёт это).
Перенести поиск в общую инфраструктуру компании.
Добавить фильтрацию чувствительных данных, которые могут появиться в ответе.
Попробовать GPT-4, GigaChat API, Yi-34B и что там ещё.
Короткие итоги от меня лично. Теперь я согласен с Chip Huyen: "It’s easy to make something cool with LLMs, but very hard to make something production-ready with them." (Building LLM applications for production)
GPT поиск доступен для всех желающих по ссылке: https://gpt-docs.ideco.ru/
Вместе со мной над проектом работали:
@socketpair — идейный вдохновитель
@fisher85 — научный руководитель
дорогие асессоры Анастасия и Владислав
Комментарии (23)
mtop
03.12.2023 16:45а как подобную штуку реализовать?
https://www.highcharts.com/chat/gpt/imf1ne Автор
03.12.2023 16:45+1Всё-таки этот вопрос лучше задать разработчикам Highcharts GPT.
Но кое-что можно и прикинуть самим. В блоге у них есть подсказка — модель отвечает только по версиям до 2021 года. Значит, они даже не дополняют "контекст" вопроса свежими примерами использования своей библиотеки. Выглядит так, что этот поиск работает следующим образом: к промпту пользователя "Create a donut chart of the world's top 5 car manufacturers. Use dark mode." они дописывают в конце что-то вроде: "Use Highcharts JS library". Я задал такой вопрос модели ChatGPT, ответ по содержанию совпадает с ответом Highcharts GPT.
mtop
03.12.2023 16:45Ну и с другой стороны их система не отвечает на вопросы за пределами вопросов Highcharts , но с удовольствием расскажет как это юзать
yrub
03.12.2023 16:45есть instruct модели, которые пишут четко что в промпте одним ответом, а большая часть промпта будет системная, которую вы не видете. в ней будет написано что-то типа "напиши js код используя следующие функции.." ну и там будет перечень функций с описанием. есть путь посложнее - дообучение. месяца 3 это есть в chatgpt, дообучить не дорого стоит.
ЗЫ: при желании наверно можно заставить написать не код, надо эксперементировать
talraaash
03.12.2023 16:45+1Если пользователь по ключевому слову в простом поиске "dmz" или "ipsec" не может найти ответа на свой вопрос по этой теме, то проблема в самой документации.
Асессорам мы доверяем больше, чем пользователям. Поэтому смотрим на самый правый столбец.
А почему? На мой вкус реальный отзыв от пользователя системы актуальнее для понимания решает ли эта система поставленную задачу. Нежели несколько деформированное восприятие человека цель которого не решить проблему с помощью инструмента, а протестировать инструмент.
imf1ne Автор
03.12.2023 16:45Не соглашусь с первым тезисом. Если пользователь по ключевому слову "ipsec" не может найти ответа на свой вопрос, то могут быть разные тому причины, например:
В документации про это нет. Согласен, это проблема документации.
Пользователь получает много ссылок на страницы, где упоминается "ipsec". И ему сложно обработать такой объем информации в ответе. В этом случае документация "не виновата". И поможет тут "умный" поиск, если пользователь более подробно сформулирует свой запрос.
К вопросу, почему мы больше доверяем асессорам. Важно заметить: речь не про "отзыв от пользователя". Речь про оценку пользователя, насколько хороший ответ в поиске он получил. Пользователь не всегда обладает знаниями, чтобы корректно оценить качество ответа, особенно сложного и объёмного ответа. Асессор лучше знает предмет и корректнее сможет оценить качество ответа.
talraaash
03.12.2023 16:45Пользователь получает много ссылок на страницы, где упоминается "ipsec". И ему сложно обработать такой объем информации в ответе. В этом случае документация "не виновата". И поможет тут "умный" поиск, если пользователь более подробно сформулирует свой запрос.
Для этого используют не один ключ в поиске) Я понимаю, что "гугление" - забытая техника древних, но не до такой же степени. И мы снова упремся в то насколько хорошо написана документация, охватывает ли она весь функционал софта и т.п.. Перевод тех документации в "упрощенный человеко читаемый формат" с помощью нейронки - хорошая задача для разминки. Но для реальных юзкейсов сомнительно... человек не знающий что такое DMZ не будет у нейронки спрашивать советов по его настройке, а знакомый со значением термина довольно легко найдет нужный раздел в документации. А абстрактные кейсы "Как заблокировать сайт Х" решаются хорошим FAQ или рекапом текста документаци, тут как раз может помочь нейронка сократить время на подсвечивание основных сценариев использования и функций софта.
Речь про оценку пользователя, насколько хороший ответ в поиске он получил. Пользователь не всегда обладает знаниями, чтобы корректно оценить качество ответа
Но задача пользователя не решена или решена отсюда и оценка пользователя по качеству ответа. И это важнейший критерий качества ответа, нет?
Mike_666
03.12.2023 16:45Называйте меня пароноиком, но таки интеграция помошника на базе OpenAI API в справочную систему для ПО обеспечения безопасности ориентированного на рынок РФ в текущей геополитической ситуации напрашивается на ачивки:
Утечка сведений об особенностях конкретных инсталяций этого самого ПО (через вопросы пользователей с конкретными настройками)
Первая успешная атака вида 'автоматизация приёмов социальной инженерии для создания заведомо уязвимых конфигураций посредством llm'
imf1ne Автор
03.12.2023 16:45Да, всё верно. И в задачах на будущее у нас много подобных вопросов. Вообще, безопасен ли ложный ответ модели? Фильтрация чувствительных данных в ответе. Защита от состязательных атак (ваш пример атаки отравления — абсолютно реальный).
Nabusteam
03.12.2023 16:45+2Как для хаброуровня ждал какой то код с описанием. По факту только два слова langchain и retrievalqa.
imf1ne Автор
03.12.2023 16:45+1Рабочий код подобного примера со всеми пояснениями опубликован в оригинальной работе, на которую я ссылаюсь в посте: https://www.reaminated.com/run-chatgpt-style-questions-over-your-own-files-using-the-openai-api-and-langchain
dimnsk
03.12.2023 16:45промпт покажите?
text_splitter = CharacterTextSplitter(chunk_size=512 , chunk_overlap=0)
это все варианты разделения?
thunderspb
03.12.2023 16:45А llama index не пробовали?
imf1ne Автор
03.12.2023 16:45Не работал с таким инструментом
thunderspb
03.12.2023 16:45Посмотрите, оно как раз для аггрегации внутренней документации, причём из разных источников, типа пдф, док и много чего другого. Индексирует и отправляет в чатгпт. Идея крутая, но я, как далёкий человек от мл/ии, примерно заставил это работать и оно хорошие ответы выдает, но обрезанные. Скорее всего, чтото подтюнить надо :)
AlexanderAnisimov
03.12.2023 16:45Хотелось бы узнать ваше мнение по поводу (потенциальной) возможности применения этого инструмента https://habr.com/ru/articles/778414/ к вашей задаче. Я имею ввиду прикрепить вашу базу документов к ассистенту и потом разговаривать с этим ассистентом.
kolabaister
Интересная идея, но вот ответы по моему бесполезны. Пара полезных слов и много воды. Единственное ценное - ссылки, но ведь их можно и простым индексированием выдавать.
Вы оценивали CSI?
imf1ne Автор
Чтобы понять, полезные ответы или бесполезные, мы привлекли на помощь асессоров. Вместе разметили ответы поиска и оценили его качество. Совместный вывод сделали такой: польза есть и в самих ответах, табличка в посте это подтверждает.
Да, согласен, ссылки можно выдавать индексированием. Но ссылки — это точно не единственная польза. Польза есть и в ответах.
CSI явно не оценивали. Неявно — по оценкам от пользователей можно сделать первые выводы. Количество положительных оценок совпадает с количеством отрицательных оценок, но пока это статистически незначимые числа. Продолжаем набирать статистику.