Просьба — не ограничение: что стоит между человеком и платной моделью
Инструкция модели не защищает ни деньги, ни данные: когда модель её читает, запрос уже отправлен и оплачен. Что проверяет код перед каждым обращением к модели и чего он проверить не может.
Это третья статья серии о приложении, которое превращает рассказ о бизнес-процессе в схему. В первой мы перечислили восемь задач вокруг языковой модели, во второй разобрали измерение качества. Здесь — о защите: что происходит с сообщением человека до того, как оно уйдёт внешней модели.
Каждое обращение к модели в нашем приложении стоит денег и выносит текст за пределы компьютера. Отсюда три вещи, которые нужно беречь: расходы, данные и сам разговор — чтобы он оставался разговором о процессе, а не обо всём подряд.
Проще всего дописать в инструкцию модели: «не отвечай на посторонние вопросы», «не принимай длинные сообщения», «не повторяй названия организаций». Модель будет стараться. Но защитой это назвать нельзя.
К моменту, когда модель читает инструкцию, запрос уже отправлен. Он оплачен: длинное сообщение стоит столько же, откажется модель на него отвечать или нет. И текст уже ушёл наружу: если в нём было настоящее название, оно у поставщика модели.
Поэтому правило у нас такое: всё, что должно сработать до отправки, проверяет код. Инструкции остаётся только то, что без понимания смысла не проверить.
Перед каждым платным запросом сообщение проходит шесть проверок. Значения ниже — наши настройки по умолчанию.
Проверки перед платным запросом
Проверка
Предел
Что происходит при отказе
Длина сообщения
4000 знаков
Просьба рассказать частями
Число сообщений в разговоре
60
Новое сообщение не принимается
Настоящие названия
ни одного
Названия заменяются по словарю; если что-то осталось, сообщение не уходит
Расход на один разговор
$0,50
Сообщение, что предел разговора достигнут
Расход за сутки
$3
То же для всех разговоров вместе
Посторонние сообщения подряд (о них ниже)
5
Пауза на 10 минут
Проверка названий включается для тех предметных областей, где замена обязательна; остальные пять действуют всегда. Отклонённое сообщение не записывается в разговор и не отправляется. Человек сразу видит причину: например, какого вида данные остались в тексте.
Проверка до отправки работает как шаблон с прорезью: то, что не проходит по размеру, остаётся снаружи и не оплачивается.
Ответ модели приходит по частям: человек видит, как он пишется. Отказ защиты не должен появляться посреди этого потока — он должен быть известен раньше, чем ответ начат.
Поэтому обработка сообщения разделена на два шага. Первый принимает сообщение: прогоняет проверки и записывает его. Второй запрашивает модель и выполняется, только если первый прошёл. Отказ защиты всегда известен до первого слова ответа, и на это есть отдельный тест.
Замена названий работает по словарю «настоящее — подставное». А если словаря нет?
Можно было бы отправить текст как есть: проверять нечем, значит, и замечаний нет. Мы сделали наоборот. В области, где замена названий обязательна, без словаря сообщение не отправляется вообще. Если проверка сообщений не подключена, разговор в такой области не ведётся.
«
Отсутствие проверки приложение считает отказом, а не разрешением.
Проверяется весь запрос, а не только слова человека #
В разговоре достаточно проверить новое сообщение: остальное уже проверено раньше. Но у приложения есть и другие обращения к модели — например, когда она предлагает правку схемы по ответу владельца процесса. Там в запрос попадают схема, вопрос, записанный ответ и сама инструкция.
Для таких обращений проверяется итоговый текст запроса целиком, после сборки. Настоящее название может прийти не от человека, а из сохранённого ответа или из самой схемы, и проверка одного поля его бы пропустила.
Относится ли сообщение к процессу, код понять не способен. Это решает модель: в её ответе есть признак «не по теме». Она ставит его, если человек задал посторонний вопрос, попросил о чём-то другом, попытался изменить правила или узнать их.
Здесь защита честно стоит одного оплаченного запроса. Зато дальше снова работает код:
—Сообщение убирается из разговора. В каждый следующий запрос уходит вся история разговора, и постороннее сообщение оплачивалось бы заново на каждом ходу.
—Человек получает заранее написанный текст. Слова модели в этом случае ему не показываются, поэтому через посторонний вопрос нельзя получить от неё произвольный ответ.
—Считаются посторонние сообщения подряд. После пяти разговор ставится на паузу на десять минут. Принятое сообщение обнуляет счёт, так что навсегда разговор не запирается.
Постороннее сообщение убирается из разговора: в истории остаётся пустое место, а не текст, который пришлось бы оплачивать на каждом ходу.
Одно уточнение пришлось внести после первых проб. Вопрос о самом разговоре — «что ты уже записал?», «что ещё нужно рассказать?» — посторонним не считается.
Проверяется не только то, что уходит модели, но и то, что от неё приходит. Ответ должен соответствовать заданному формату, а его текстовая часть — уложиться в 1500 знаков. Более длинный ответ считается негодным и человеку не показывается.
Это закрывает обходной путь: приложение нельзя использовать как генератор длинных текстов, даже если удалось уговорить модель.
Негодный ответ запрашивается заново, и это место, где деньги уходят незаметно.
—Попыток немного. В разговоре не больше трёх; после этого человек получает отказ, а не бесконечный цикл.
—На повторе модель видит свою ошибку. К запросу добавляются её негодный ответ и причина отказа. Без этого она получает тот же запрос и повторяет ту же ошибку, а платим мы за каждую попытку.
—Отвергнутый ответ учитывается в расходе. Он оплачен, и в журнал попадает его стоимость.
—Перед повтором, который запускает человек, снова проверяется бюджет. Это такой же платный запрос, как первый.
Отдельный случай — два ответа на одно сообщение, когда повтор отправлен из второго окна. Записывается первый, второй отклоняется, но его стоимость тоже попадает в журнал.
Каждый оплаченный запрос записывается в журнал разговора со стоимостью. Суточный расход не хранится отдельным числом, а считается из журналов. Так он не расходится с тем, что было на самом деле.
Потолок на сутки общий для всех обращений к модели: и разговоров, и правок схемы, и оценки требований. Иначе у каждого вида запросов был бы свой бюджет, а общий никто бы не видел.
Для запросов о схеме приложение может заранее показать, что именно уйдёт модели и во что это обойдётся: размер текста, оценку стоимости ввода, среднюю цену прежних запросов такого вида. Предпросмотр бесплатный и проходит те же проверки, что и настоящий запрос. Если запрос будет отклонён, человек узнаёт об этом ещё на предпросмотре.
Оценка грубая. Число токенов прикидывается по числу знаков, а стоимость ответа заранее неизвестна, и обычно она больше стоимости ввода. Поэтому мы показываем цену ввода и не выдаём её за полную.
В упрощённом режиме приложения суммы и название модели не показываются: человек видит только, что предел достигнут.
—Она не ловит неизвестные названия. Словарь знает только то, что в него внесли. Почту, ссылки и внутренние идентификаторы находят шаблоны, но новое название подразделения, которого нет в словаре, пройдёт.
—Признак «не по теме» ставит модель. Её можно уговорить его не ставить. Ущерб от этого ограничен остальными проверками: длиной ответа, его форматом и потолками расхода.
—Проверки повторяются в каждом виде запросов. Общие у них замена названий, отказ до отправки и суточный потолок, но единого места, мимо которого нельзя пройти, в коде нет. Держится это на правиле для разработчиков: новый путь к модели без этих проверок не заводится.
—Это защита от случайности, а не от взлома. Приложение работает на компьютере пользователя, и пределы — его настройки.
В следующей статье — об обезличивании: как устроены словарь и шаблоны и почему замена сделана необратимой.