"Плачу 20 золотых" - а зелья нет: как ДнД с ИИ научился торговать без обмана
В ДнД с ИИ торговлю ломала неатомарность сделки: бот списывал 20 золотых отдельно от выдачи предмета, поэтому золото уходило, а зелья не было; иногда двухходовую покупку он засчитывал дважды и снимал −40. Починил, связав деньги и товар в одну операцию "всё или ничего" и добавив дедуп повторной сделки.
Представь: заходишь ты к торговцу, говоришь “плачу 20 золотых за зелье лечения”, жмёшь ход - и получаешь минус 20 золотых и пустые руки. Деньги ушли, зелья нет, а НПС в прозе ещё и разводит руками: “нет такого товара”. Именно так пару недель назад работала торговля в моём ДнД с ИИ. Ребят, это был не грабёж со стороны жадного трактирщика - это был баг. И не один. Ниже разберу, как мой ai днд бот учился торговать честно: где он терял твоё золото, где списывал его дважды, и как я это чинил.
”Заплатил 20 золотых, а зелья нет”: что это был за баг
Баг сидел в атомарности сделки. ИИ-мастер списывал золото и выдавал предмет двумя независимыми шагами, которые друг о друге не знали. В том самом случае система сняла с тебя 20 золотых, но “гейт авторитетности” - проверка, откуда вообще взялся предмет, - зарезал само зелье: решил, что у товара нет источника. Итог: золота нет, склянки нет, а проза отыграла вежливый отказ.
Представь двух приказчиков за одним прилавком. Один молча забирает у тебя монеты. Второй в это время говорит “извини, товара нет” и ничего не даёт. И они между собой не общаются. Вот так деньги и предмет ехали по разным рельсам и разъезжались.
Манифест, который я после этого прибил гвоздями: нейросеть не имеет права трогать твой кошелёк отдельно от твоего рюкзака.
Почему днд-бот дважды списывал золото за одну покупку
Второй баг - дубль, и он про двухходовую покупку. Работало так: на ходе “покупаю верёвку и меч за 20 золотых” торговец в прозе только назвал цену - а экстрактор уже выдал предметы и списал золото. На следующем ходе “плачу и забираю” всё повторялось второй раз: предметы задвоились, с кошелька ушло −40 золотых вместо −20.
То есть система засчитывала покупку дважды - на “хочу купить” и на “плачу”. Ты один раз купил меч, а в инвентаре их два, и денег вдвое меньше. Приятного мало.
В чём была причина: бот путал “хочу купить” с “уже купил”
Корень у обоих багов один. Экстрактор - это модуль, который из текста достаёт структурные данные: кто, что, кому и за сколько. Так вот, он вытаскивал сделку из реплики игрока, а не из прозы мастера. Твоё намерение купить он засчитывал как совершённую покупку. Ты только сказал “беру” - а он уже лез в кошелёк и в инвентарь.
Тут стоит пояснить про кухню. LLM извлечение структурированных данных - это когда модель отдаёт не свободный текст, а строгую схему: условный JSON с полями “предмет”, “цена”, “количество”. Штука полезная: строгая схема снижает галлюцинации, и надёжный tool-calling умеют почти все - Anthropic, OpenAI, Google, Mistral, Cohere (Agenta). Но есть засада: если модель “галлюцинирует” при вызове инструмента, это валит уже нижележащие системы (Phare, 2025). В моём случае схема-то заполнялась исправно - только не по тому источнику. Намерение игрока - это ещё не факт мира. Факт мира устанавливает мастер.
Как я это чинил: атомарность сделки и защита от дублей
Атомарность транзакции - это принцип “всё или ничего”: сделка либо проходит целиком, либо не проходит вовсе, а при сбое всё откатывается (Хабр, 2021). Ровно этого торговле и не хватало. Что было → что стало:
- Было: сделку засчитывали по реплике игрока. Стало: в схему экстракции добавлен флаг
trade_completed- сделка засчитывается только по прозе мастера-НПС, когда он реально отдал товар. - Было: списание золота и выдача предмета - два независимых шага. Стало: голд-дельта и предмет связаны в одну атомарную операцию с общим гейтом. Это и есть атомарность транзакций в игре: деньги и товар едут вместе или никуда.
- Было: двухходовая покупка засчитывалась дважды. Стало: дедуп повторной сделки с окном в 2 хода не даёт списать одно и то же второй раз.
- Было: гейт резал легитимного торговца как “без источника”. Стало: гейт научился признавать НПС текущей сцены по её
location_id- свой трактирщик больше не “чужой”.
Одной строкой: один ход - одна сделка.
Честный размен: где я специально пожертвовал точностью
Один трейд-офф я выбрал осознанно. Дедуп с окном в 2 хода иногда ложно срабатывает: если ты реально дважды подряд купил одинаковый набор за ту же сумму, вторую покупку он может счесть дублем и не провести. Я выбрал редкий ложняк вместо частого дубля - такой случай логируется, я его вижу в логах. Лучше изредка переспросить, чем регулярно тихо воровать у тебя золото. Честность тут дороже удобства.
Что дальше и почему торговле теперь можно верить
Перед выкаткой спека и план фикса прошли адверсариальное ревью, автотесты - 4807 штук в сьюте - зелёные, и я вручную переиграл три сценария покупки на живом боте: PASS. Торговля в ДнД с ИИ теперь атомарна: либо честная сделка (золото ушло И зелье в рюкзаке), либо честный отказ - без “деньги списали, товар потеряли”.
Это по-прежнему активная стройка, и багов мы с вами ещё выловим - как обычно. Если поймал, что нейросеть мастер подземелий жульничает с золотом, - пришли мне тот самый ход, гляну по логам. А пока иди затарься зельями у трактирщика: теперь он не обманет )
Частые вопросы
Может ли ИИ-мастер в ДнД сам менять количество золота у игрока?
Не произвольно. В боте деньги меняются только вместе с предметом одной атомарной сделкой: либо золото ушло и товар в рюкзаке, либо не изменилось ничего. Отдельно списать золото "просто так" система не может.
Что делать, если днд-бот дважды списал деньги за одну покупку?
Пришлите мне тот ход, где это случилось. После фикса дедуп ловит повторную сделку в окне двух ходов, а редкие пограничные случаи логируются - по логу я вижу проблему и откатываю лишнее списание.
Почему нейросеть путает намерение купить с самой покупкой?
Из-за наивного экстрактора: он достаёт сделку из реплики игрока, и "беру меч" уже считается покупкой. Правильно засчитывать сделку только по прозе мастера-НПС, когда он реально отдал товар - это и есть флаг завершённой сделки.
Как готовился материал: черновик собирает мой ИИ-конвейер по темам из практики таверны, факты сверяются с первоисточниками и правилами, финальную версию я читаю и правлю руками перед публикацией. Обложку тоже рисует нейросеть. Про кухню — на странице о проекте.