Краткое содержание первой части
В первой части статьи я рассказывал о создании цифрового юриста, способного отвечать на вопросы на основе 200-страничного регламента. Цель — работа такого юриста в закрытом контуре организации, без использования облачных технологий.
Для этого задания мы разработали фреймворк, позволяющий изменять LLM-модель и тип токенизации в реальном времени. В качестве эталона мы использовали GPT4 Turbo и ADA-02 для токенизации. Хотя такое решение не подходит для продакшн, оно отлично служит точкой отсчёта.
Особенностью нашего подхода стало собрание 31 вопроса, от простых до сложных, с последующей оценкой ответов юристами. Оценка была сделана руками, людьми, что делает её особенно ценной. Мы тестировали различные комбинации моделей и промптов, включая GPT4, GPT3.5, GigaChat и YandexGPT. Гипотеза об эталонной модели и токенайзере подтвердилась результатами от OpenAI (около 70% точных ответов). Однако токенайзеры от RuBert оказались не настолько эффективными, как ожидалось.
Более подробно об этом можно прочитать в первой части.
Сравнительная таблица из первой части
![](https://habrastorage.org/getpro/habr/upload_files/aa0/468/555/aa0468555fd7a08abd4bcf33d6319c04.png)
В этой части мы рассмотрим дообученный токенайзер и модели Saiga на базе Llama и Mistral.
Какой выбрать токензайзер (тот что создаёт векторное представление текста)?
Правильный выбор токенайзера в RAG аналогичен выбору ингредиентов для супа. Чтобы избежать перебора всех возможных вариантов и не нагружать проверкой наших юристов, я решил провести предварительную квалификацию.
Напомню, что в RAG промпт задачи формируется динамически. Вопрос (A) конвертируется в вектор, и выбираются наиболее близкие ему математические векторы фрагментов регламента, сортируемые по убыванию "близости". Затем из них формируется запрос. Например, для вопроса A наиболее близкими являются фрагменты текста P, D, F, G, при этом дистанция между векторами A-P больше, чем A-D. С этой задачей лучше всего справляется ADA-02 от OpenAI.
Таким образом, можно создать собственный токенайзер и сравнить, какие фрагменты текста он выдаст для такого же запроса. Если их последовательность совпадает с ADA-02, это отлично. В противном случае, эту ошибку можно измерить и анализировать.
Если скормить этот текст в СhatGPT и попросить зарисовать, он выделит суп как основный элемент.
![](https://habrastorage.org/getpro/habr/upload_files/6ac/058/3c5/6ac0583c5c207d7484a8756a48aa4ad4.jpg)
В некотором смысле наш токензайзер должен выделять правильные элементы.
Методология поиска лучшего токенайзера
В качестве референса было я взял около 5000 текстовых фрагментов различного содержания: примеры вопросов, выдержки из регламента. Из этих данных случайным образом формировались 250 пар текстов для расчета косинусной близости для выбранного токенизайзера. Далее рассчитывал отклонение между значением эталонного ADA-02 и выбранного. Колебание этого отклонения и есть наш параметр. Если токензайзеры идентичны, то и среднееквадратичное отклонение между ними = 0.
Среднее квадратичное отклонение между каждой точкой позволило определить точность выбранного токенизатора. RuBert – Large демонстрировал погрешность около 10-11% в отношении ADA-02, sbert-nlu-ru-mt – 9-11%, что является улучшением, хоть и незначительным.
![Близко, но все равно колбасит (9-13%) Близко, но все равно колбасит (9-13%)](https://habrastorage.org/getpro/habr/upload_files/be2/dd8/99a/be2dd899a10e91389c88f87863c0f53d.png)
9Ембеддинг – это матрица чисел, поэтому задача адаптации локального токенизатора, такого как RuBERT или sbert‑nlu‑ru‑mt, заключается в преобразовании одной матрицы в другую. Классическая ML задача.
![](https://habrastorage.org/getpro/habr/upload_files/611/93a/020/61193a0208d781bcda0ee471820042d9.png)
После исследований промпта в ChatGPT я остановился на трехслойной сети TensorFlow, без специальной настройки и подбора гиперпараметров (всё по умолчанию, что наверное упущение).
30 эпох обучения и был создан адаптер. Он переводит вектор RuBert (1024 параметра) в вектор OpenAI (1526 параметров). Этот адаптер будет эффективно работать только с текстами, близкими к определенной тематике.
![Желтая линия - это токенайзер RuBert после FineTuning. Он по форме и пикам больше подходит под эталонный. Улучшение точности с 11 до 6% - радикально улучшило общие показатели. Желтая линия - это токенайзер RuBert после FineTuning. Он по форме и пикам больше подходит под эталонный. Улучшение точности с 11 до 6% - радикально улучшило общие показатели.](https://habrastorage.org/getpro/habr/upload_files/31b/a8a/2ca/31ba8a2ca1a10411a6ef6b2990ab1bd5.jpg)
Синтетические тесты показали, что ошибка снизилась с 9-11% до 6%. При этом использование sbert-nlu-ru-mt не дало прироста, поэтому был выбран RuBert-large в качестве основы.
Таким образом, был получен локально работающий токенизатор, близкий по эффективности к облачному ADA-02, что теоретически должно улучшить качество ответов.
Проверка на практике, как работает FineTuned токенайзер.
Возьмем наш эталон GPT-4 и пропустим через нашу машинку вопросов/ответов и отдадим на оценку ответов юристам. И мы получаем следующие результаты:
GPT-4 | ADA-02 | RuBert - Large | RuBert-Large FineTuned |
Верно | 71% | 32% | 55% |
Спорно | 6% | 13% | 19% |
Ошибочно | 23% | 55% | 26% |
Значения правильных ответов на эталонной модели значительно выросли (с 32% до 55%). Ошибочных ответов уменьшилось в двое и равно эталонным (уменьшение с 55% до 26%, при 23% эталонных). Иными словами – наша стратегия сработала:
Правильный токенайзер повышает качество. Улучшение точности ембедингов с 11% до 6% даёт значимый результат.
Fine Tune токенайзера возможен
Аналогичный результат мы видим и для моделей YandexGPT. Количество правильных ответов растет, ошибочных падает:
YandexGPT | ADA-02 | RuBert - Large | RuBert-Large FineTuned |
Верно | 29% | 32% | 45% |
Спорно | 26% | 6% | 13% |
Ошибочно | 45% | 61% | 42% |
Локальные модели
Пришло время к самому интересному. Я развернул локальные на базе Saiga2 (LLama2).
Решение не тестировать на токенизаторе от OpenAI и обычном RuBert было обоснованным, так как использование локальной модели с облачным токенизатором от OpenAI кажется абсурдным, а применение обычного RuBert нецелесообразно из-за его низкого качества.
Для сравнения я взял модели с двумя разными квантованиями. На 5 и 8. Первая может поместиться в видеокарту 3060 (12GB), вторая уже требует карты 3090 или 4090 (24GB).
Обе модели показали почти идентичные: 35% верных ответов, 52% ошибочных и 13% спорных ответов. Это немного лучше, чем у YandexGPT|GigaChat на базе обычного RuBert, но хуже, чем у RuBert-fine tuned.
В целом, YandexGPT немного превосходит Saiga LLama2, что является положительным моментом.
Итоговая сравнительная таблица:
![](https://habrastorage.org/getpro/habr/upload_files/b7f/0d5/34e/b7f0d534e640feaa1edfe8e116a2b37e.jpg)
А вот с fine-tune моделями у меня пока не всё получается как надо. Много галлюцинаций. Поэтому я планирую написать отдельную статью по этой теме, когда завершу эксперименты.
Влияние сложности вопросов на оценку
На данный момент задача RAG с использованием локальных моделей (в закрытом контуре) не решается в полной мере в лоб. Одновременно эту задачу можно решать, если есть доступ к OpenAI GPT4 с широким окном контекста, достигая 70-80% правильных ответов без особых усилий. Обратная сторона медали, кроме отсутсвия контура безопасности - это стоимость. Сейчас запрос будет обходиться где-то в 5-10 центов.
Основные ограничения локальных моделей, на мой взгляд связаны в первую очередь с (1) правильным формированием чанков первичного текста (2) токенайзерами,и в меньшей степени – с самими моделями. Недостатки моделей, по моему мнению, можно компенсировать более точными промптами и fine-tuning. Альтернативно, можно подождать развития технологий в ближайшие месяцы.
Работа над нарезкой и векторизацией данных – это задача требующая нашего внимания и которая не будет решена сама по себе. Доработка FineTune токенайзера представляется технически выполнимой. Нужно больше экспериментировать с гиперпараметрами модели.
По вопросу нарезки данных (чанков текста) возможны три пути. Первый, немного примитивный, но правильный с точки зрения продуктового подхода – ограничить RAG задачу информацией, которая умещается в 1-2 абзаца, возможно с ручной нарезкой.
Второй – изучить возможности и технологии графового представления данных для более сложной обработки.
Третий - ждать, пока появятся достойный локальные модели с длиной контекста (эффективной длинной) до 128К символов. Но это не наш путь.
Поэтому не прощаюсь ...