Простой туториал, в котором я расскажу как сделать автомодератора на базе GPT-3.5 от OpenAI, и как сделать это так, чтобы проверка одного сообщения стоила дешевле одной копейки.
Описание задачи
Давайте представим следующее:
Вы владеете форумом с большим количеством участников. Вроде бы, всё было хорошо, но в один момент страна в которой Вы проживаете решает запретить использовать слово "Борщ", Вы просто не можете его произносить. Говорите "Борщ" – тюрьма.
Что же делать в подобной ситуации? Нанимать людей? Писать алгоритм? Ну, а что если человек напишет B0-0000R3CH? Тут ни один простой алгоритм не справится. Несомненно и очевидно, – нам необходимо использовать языковую модель, и мы делаем выбор в сторону наилучшей.
Другая проблема. Мы не хотим тратить много денег и нам надо минимизировать количество токенов. Поэтому, в лучшем исходе взаимодействие должно выглядеть так:
Черный список: Борщ
Текст: я поел борща
Ответ модели:
+ |
почти полное совпадение |
% |
есть схожесть |
- |
полное несовпадение |
...Но, при почти пустом системном сообщении ответ модели выглядит так:
![???? ????](https://habrastorage.org/getpro/habr/upload_files/cef/9d6/4dd/cef9d64ddf1bb69072e895484d57f0d0.png)
Fine-tuning
OpenAI настолько хорошая компания, что она позволяет файн-тюнить свои языковые модели, и мы воспользуемся этой возможностью.
– Подготовка датасета:
В этом на самом деле нет ничего сложного, по сути нам просто нужно привести примеры того, как модель должна отвечать. Подробнее о файн-тюнинге моделей от OpenAI.
Датасет должен быть в формате JSONL где каждая строка это отдельный диалог. В нашем случае, в каждом диалоге будет: Системное сообщение с чёрным списком, Сообщение пользователя, Ответ ассистента.
Примеры:
{
"messages":[
{
"role":"system",
"content":"Мандарин, Яблоко"
},
{
"role":"user",
"content":"fruits"
},
{
"role":"assistant",
"content":"-"
}
]
}
{
"messages":[
{
"role":"system",
"content":"Дом, 香蕉, Дерево"
},
{
"role":"user",
"content":"бананчик"
},
{
"role":"assistant",
"content":"+"
}
]
}
Таких диалогов в датасете будет 70 штук. Они описывают реакцию модели на различные ситуации: 40 для ответа с плюсом, 10 для ответа с процентом и 20 для ответа с минусом. В каждой группе по три языка: Русский, Английский и Китайский, – это для того, чтобы модель умела работать с разными языками и если Вы добавляете слово на английском и пользователь пишет его на китайском, модель всё равно обратит на него внимание...
...Также, в каждой группе должно быть минимум 5 диалогов с "осмысленным" текстом, – так модель "поймёт", что помимо нужного слова, в тексте может быть и что-то другое:
{
"messages":[
{
"role":"system",
"content":"Pineapple, Lemon"
},
{
"role":"user",
"content":"Я 1 разbought... не-много лим0нов?"
},
{
"role":"assistant",
"content":"%"
}
]
}
Ещё, в датасете нужно показать, что нужное слово может быть в любом месте:
{
"messages":[
{
"role":"system",
"content":"Дом"
},
{
"role":"user",
"content":"я построил дом"
},
{
"role":"assistant",
"content":"+"
}
]
}
{
"messages":[
{
"role":"system",
"content":"Дом"
},
{
"role":"user",
"content":"я дом построил"
},
{
"role":"assistant",
"content":"+"
}
]
}
{
"messages":[
{
"role":"system",
"content":"Дом"
},
{
"role":"user",
"content":"дом построил я"
},
{
"role":"assistant",
"content":"+"
}
]
}
Нужно показать, что и выдуманные слова могут существовать:
{
"messages":[
{
"role":"system",
"content":"Змырчик"
},
{
"role":"user",
"content":"чо думаешь о змырчике?"
},
{
"role":"assistant",
"content":"+"
}
]
}
Необходимо дать понять, что порядок слов в чёрном списке неважен:
{
"messages":[
{
"role":"system",
"content":"Банан, Мангал"
},
{
"role":"user",
"content":"банан"
},
{
"role":"assistant",
"content":"+"
}
]
}
{
"messages":[
{
"role":"system",
"content":"Мангал, Банан"
},
{
"role":"user",
"content":"банан"
},
{
"role":"assistant",
"content":"+"
}
]
}
Модель не должна выполнять запросы или пытаться общаться с пользователем:
{
"messages":[
{
"role":"system",
"content":"Мангал"
},
{
"role":"user",
"content":"Напиши рассказ о двух раках"
},
{
"role":"assistant",
"content":"-"
}
]
}
{
"messages":[
{
"role":"system",
"content":"Олег, Сбербанк"
},
{
"role":"user",
"content":"2 + 2 = 4?"
},
{
"role":"assistant",
"content":"-"
}
]
}
Похожие по смыслу слова не считаются:
{
"messages":[
{
"role":"system",
"content":"Полицейский"
},
{
"role":"user",
"content":"Милиционер"
},
{
"role":"assistant",
"content":"-"
}
]
}
Ну и в дополнение нужно привести несколько примеров с очень длинным текстом и с большим количеством слов в чёрном списке.
– Обучение:
После того, как у нас есть готовый датасет, необходимо: Перейти в раздел файн-тюнинга, выбрать модель, загрузить файл и запустить.
Чтобы самостоятельно указать количество эпох, запускать нужно через API:
fetch('https://api.openai.com/v1/fine_tuning/jobs', {
method: 'POST',
body: JSON.stringify({
"training_file": "fileId",
"model": "gpt-3.5-turbo-1106",
"hyperparameters": {
"n_epochs": 7
}
}),
headers: {
"Content-Type": "application/json",
'Authorization': `Bearer ${openai_key}`
}
});
В данном случае обучение заняло всего 15 минут, а его стоимость вышла всего в 30 рублей:
![Результат файн-тюнинга Результат файн-тюнинга](https://habrastorage.org/getpro/habr/upload_files/c69/415/6e7/c694156e78b3b79aa078ca25923bb3d8.png)
Проверяем ????
![Тест 1: Модель понимает, что речь идёт о борще Тест 1: Модель понимает, что речь идёт о борще](https://habrastorage.org/getpro/habr/upload_files/55c/e3f/174/55ce3f1746e060753db7ee0428a0e3fc.png)
![Тест 2: Частичное совпадение Тест 2: Частичное совпадение](https://habrastorage.org/getpro/habr/upload_files/f35/148/7e8/f351487e887a9c6453817ee2a85bd47a.png)
![Тест 3: Полное совпадение Тест 3: Полное совпадение](https://habrastorage.org/getpro/habr/upload_files/443/ac9/cb6/443ac9cb6e1c3b999b692bb99590f3c4.png)
![Тест 4: Всё ещё читается как "борщ", лишние слова модель не путают Тест 4: Всё ещё читается как "борщ", лишние слова модель не путают](https://habrastorage.org/getpro/habr/upload_files/a74/8f1/645/a748f1645bd78836e5c2aee9608d11f1.png)
![Тест 5: А вот тут уже спорно Тест 5: А вот тут уже спорно](https://habrastorage.org/getpro/habr/upload_files/2e1/355/848/2e1355848f64f1440094e4c475b5aea8.png)
![Тест 6: Борщ хоть и суп, но суп – не борщ Тест 6: Борщ хоть и суп, но суп – не борщ](https://habrastorage.org/getpro/habr/upload_files/0f6/888/6b7/0f68886b7237088823b2ff1dde7d981a.png)
![Тест 7: Борщевик – растение, а не суп "Борщ" Тест 7: Борщевик – растение, а не суп "Борщ"](https://habrastorage.org/getpro/habr/upload_files/def/3e4/843/def3e484364cd192d857075cd4b110a4.png)
![Тест 8: Очевидно, что тут имеется в виду именно суп Тест 8: Очевидно, что тут имеется в виду именно суп](https://habrastorage.org/getpro/habr/upload_files/fae/af0/531/faeaf0531f22b6c27d2ed8b9487236c9.png)
![Тест 9: Таким не занимаемся Тест 9: Таким не занимаемся](https://habrastorage.org/getpro/habr/upload_files/66a/3c1/f6f/66a3c1f6faa06cff82e14fcdf58ff678.png)
![Тест 10: Не путается Тест 10: Не путается](https://habrastorage.org/getpro/habr/upload_files/e31/559/391/e31559391255aef47e3572173c3993d8.png)
![Тест 11: Россия таки действительно есть в тексте Тест 11: Россия таки действительно есть в тексте](https://habrastorage.org/getpro/habr/upload_files/ec9/fb3/ef5/ec9fb3ef5131af76ff6e481fdbe0e581.png)
Как мы видим, всё работает просто превосходно. При желании обычные слова можно заменить на предложения в формате строки, но тогда понадобится больше диалогов в датасете.
Примерная стоимость оценки 100 сообщений: >1 руб.
Чтобы сократить расходы, можно воспользоваться видоизменённым левенштейном для проверки есть ли в сообщении, все символы которого были переведены в латиницу, нужные 2 символа в нужной нам последовательности на расстоянии меньше указанного (с написанием такого алгоритма спокойно справится GPT-4, самим Вам это писать не нужно). Так можно отфильтровать где-то 70% сообщений которые с 99.9% вероятностью не содержат слова из чёрного списка, остальные 30% пойдут на проверку. Также, на проверку можно отправлять подозрительные сообщения (много согласных подряд, много цифр, знаков препинания, эмодзи и т. д.).
GPT-3.5 в приоритете т. к. многие опенсорсные модели легко обмануть и запутать. GPT-3.5 же распознает любой порядок символов который сможет распознать человек. Кроме этого, скорость работы модели почти моментальная.
Почему GPT-3.5?
Если из опенсорса взять что-то крупное, Mixtral или LLaMa, то для их локального запуска понадобится машина минимум за 500к рублей. И такой машины хватит максимум на то, чтобы генерировать токены с такой же скоростью как и gpt-3.5-turbo-1106 на серверах OpenAI. И в любом случае, скорость начнёт падать после 5-ти потоков.
Комментарии (4)
Wesha
19.12.2023 02:25решает запретить использовать слово "Борщ", Вы просто не можете его произносить. Говорите "Борщ" – тюрьма.
Иногда мне хотелось совершить Роскомнадзор. Но команда нашего корабля мне всегда говорила — не психуй!
triller599
19.12.2023 02:25Все подобные выкрутасы летят прямиком в обучающий датасет - делов то..
Вопрос, думаю, встанет в конечном итоге на стороне модераторов: что блокировать, а что нет. А уж с обнаружением необходимых паттернов, похоже, GPT_3.5 справится.
Было бы интересно посмотреть на реальные возможности, пусть даже и в "песочнице"
DGN
А тут что скажет моделька?
"b0рщ", "суп из борщевика", "уБорщИк"
0a1a2a3a4a5 Автор