Борт
ночных проверок на выдуманные данные: 20Семейные деньги и привычки: трое взрослых пишут в Telegram обычными словами — что потратил, что съел, как спал, — а система превращает это в записи, считает и показывает картину целиком. Никаких форм и таблиц: сообщение в чат, как другу.
Заказчика не называем: там настоящие деньги и здоровье конкретной семьи. Данные на снимках ниже — тестовые, интерфейс настоящий.
Показываем главное: что произошло, когда искусственный интеллект придумал число и подал его как факт — и что мы сделали, чтобы это стало невозможным.
Два входа. Telegram — чтобы записывать на ходу: двадцать одна команда и тринадцать наборов кнопок. Веб-кабинет — чтобы смотреть, что из этого получилось.
- Понимает свободный текст. «Взял кофе за 25, потом обед 60» — это две траты с категориями, а не строка в блокноте. Разбирать пишущего человека, а не заставлять его заполнять форму, — в этом весь смысл.
- Работает сама по расписанию. Ночью ИИ-агент проходит по накопленному за день: раскладывает, считает, сверяет, готовит утренний разбор. Человек не нажимает ничего.
- Считает семейные деньги. Операции, счета в разных банках и валютах, доходы — вклады, облигации, акции, металлы, зарплата. Отдельно — «кто кому должен» внутри семьи.
- Сверяет запись с выпиской банка. Не «мы записали, значит так и есть», а сравнение с тем, что говорит банк.
- Показывает одни и те же операции в разных разрезах. По дням, по статьям, по людям, по местам, «нужное или лишнее». Каждый отчёт называет, чего он не знает.
- Умеет сказать «не знаю». Как ни странно, это оказалось самой трудной частью — и об этом весь кейс дальше.
Внутри — 68 таблиц данных, 417 правок кода за двадцать дней, 1731 автотест.
Проще всего показать на экранах. Обратите внимание не на цифры, а на подписи вокруг них — в них и есть вся работа:
- «Сложено по 4 счетам из 6. TBC не сложен — он в долларах; Kapital не сложен — снимок 12 июня». Итог не притворяется полным.
- «2 операции без курса — $18,98 — в итог не вошли и занизили его», и рядом кнопка «Задать курс доллара». Не молчаливая ошибка, а названная и с готовым действием.
- «1 августа в знаменатель не вошло: там есть записи, но все без курса — сумму дня посчитать нечем». Средний расход считается по дням, где есть что считать.
- «Август идёт 9 дней из 31 — столбец растёт по мере записи, сравнивать его целиком пока не с чем». Неполный месяц не выдаётся за месяц.
- У счёта с остатком 0 и у счёта со снимком месячной давности разный вид: первый — настоящий ноль, второй помечен «снимок старше месяца» и в сумму не идёт.
Это и есть тема кейса, только рассказанная интерфейсом, а не текстом.
За сутки система дала больше пятнадцати сбоев. Три из них были не ошибками разбора, а выдумкой.
Самый показательный: агент записал в дневник время приёма пищи, которого не было ни в одном сообщении. Не ошибся в цифре — придумал её целиком. Дальше принял на этом времени решение и сообщил вывод хозяину как установленный факт.
И вот что важно: с точки зрения программы эта запись была абсолютно законной. Проверка следила, чтобы время было временем, и больше ни за чем. А правило «у каждого числа должен быть источник» жило в инструкции для ИИ — то есть исполнялось как пожелание.
Отсюда весь остальной кейс. Вывод, к которому пришли:
Всё, что должно быть гарантией, переносится из текста инструкции в механизм — туда, где нарушение просто не проходит. Слова остаются только там, где нужна гибкость.
У каждого числа теперь есть графа «откуда»
Раньше запись хранила значение. Теперь рядом с каждым значением лежит его происхождение, и без него запись не сохранится вовсе.
| Откуда взялось | Что обязано быть приложено |
|---|---|
| сказал человек | номер сообщения и дословная цитата |
| посчитано | формула, по которой посчитано |
| прикинул ИИ | два числа — «не меньше» и «не больше» |
| пришло с устройства | какое устройство |
| настройка | какая именно |
| данных нет | почему нет |
Главное здесь — третья строка. Точного числа «от ИИ» в системе не существует. Не потому что запрещено, а потому что такое значение физически некуда положить: графа требует вилку. Ровно так и проходила ложная точность — одно и то же блюдо в двух разборах оценили с разницей в полтора раза, и обе цифры выглядели одинаково уверенно.
Второе правило: происхождение либо есть у всей записи, либо запись не сохраняется. Наполовину проверенная запись выглядит проверенной целиком.
А цитаты сверяются отдельно: если процитированного текста в исходном сообщении нет — это первый признак того, что ИИ сочиняет.
Ночная проверка, которая не спрашивает ИИ
Каждую ночь по всей базе проходят двадцать проверок: цитата, которой нет в сообщении; догадка без вилки; одно сообщение, разложенное на два разных дня; число без происхождения; запись, которую нельзя отменить.
Ни одного обращения к ИИ. Причина простая: проверяющий ИИ выдумывает ровно так же, как проверяемый.
Два решения, без которых это не работало бы:
- тревога — это появление нарушения, а не само число. Старые нарушения будут висеть неделями, и ежедневный крик о них кончится тем, что уведомления перестанут читать;
- проверка сообщает, когда она в последний раз запускалась. Проверка, которая сломалась и молчит, выглядит точно так же, как проверка, которая ничего не нашла.
Четырнадцать настоящих сбоев, которые повторяются по кнопке
Каждый инцидент из первого дня превращён в автоматический прогон. Не выдуманные примеры — настоящие случаи, с настоящими текстами.
Внутри прогона всё боевое: тот же код, те же инструкции. Подменяются ровно две вещи — адрес, по которому спрашивают ИИ, и текущее время. Второе обязательно: половина сбоев была связана со временем, и без «заморозки часов» их не воспроизвести в принципе.
Проверка «а откуда это число?» перед каждым ответом
Прежде чем система что-то скажет человеку, отдельная проверка вынимает из текста все числа и требует по каждому источник. Три вещи делают её небесполезной:
- собственные записи системы источником не считаются. Иначе получается замкнутый круг: выдумал время → записал в базу → «подтвердил» этой же записью свой ответ;
- пересказать можно, добавить нельзя. «В два часа ночи» → «02:00» это пересказ: час в тексте есть. А «21:40» — новое знание: ни двадцати одного, ни сорока в исходном сообщении нет нигде. Ровно эта граница отделяет допустимое от выдумки;
- то, что положено прикидывать, не проверяется. У еды есть честное поле «оценка». Требовать источник у оценки значит запретить оценку.
Это, пожалуй, главное, чем кейс отличается от обычных рассказов про внедрение искусственного интеллекта.
После первых сбоев у ИИ забрали часть работы и отдали её обычному коду.
Галочки дня. Раньше их проставлял ИИ, теперь считает программа. Довод: это арифметика, а не суждение. Отдавать её ИИ — значит платить за сложение и получать разные ответы при следующем обновлении модели. Агент по-прежнему рассказывает о результате человеку, но считает не он.
Разбор сумм и вкладов из текста. Теперь это обычный разбор, без «похоже на». И важное решение: число, которое не прочиталось, отменяет то, которое прочиталось. Если в сообщении два числа и одно непонятно — система не берёт понятное, а переспрашивает. Взять одно из двух значит решить за человека, какое настоящее.
Деньги. Запись «1,700» не читается вовсе — она означает и тысячу семьсот, и одну целую семь. Разница в тысячу раз, оба прочтения правдоподобны. Система отказывается и задаёт вопрос; записи не появляется ни одной.
Довод под всем этим один. То, что ИИ додумывает заново на каждом запуске, однажды он додумает иначе. Разница будет в тысячу раз — и ни одного признака ошибки.
Ноль «ничего не потратил» и ноль «мне не сказали» выглядят одинаково и означают противоположное. Различение проходит через всю систему.
- Устаревший остаток не показывается вовсе. Не «ноль», не прочерк — поля просто нет: пока поле существует, найдётся экран, который напечатает по нему ноль.
- Расчёт «сколько можно потратить» честно объявляет, чего не досчитал. Две части суммы умеют молча оказаться нулём. Такая ситуация даёт «посчитано не всё» со списком пробелов, а не зелёный свет. «Свободно столько-то» на недосчитанной сумме — это разрешение на трату, которой быть не должно.
- Пока накоплений нет, лимит не считается вообще. Зелёный индикатор на пустой базе — это страховка, которой нет, при исправном виде.
- «Изменения нет» и «изменение равно нулю» — разные ответы. Одна точка измерения за месяц не даёт права сказать «не изменилось».
- Система умеет отвечать «не знаю». Отдельная проверка следит именно за этим: ночь без данных обязана давать пустоту, а не правдоподобные «примерно семь часов».
Три находки из работы, и каждая — способ, которым провал притворяется зелёным статусом:
- проверка резервной копии была написана так, что считала успешной любую копию, даже битую;
- проверка наличия строки в файле работала наоборот: чем быстрее строка находилась, тем увереннее проверка сообщала, что её нет;
- сторож слал тревогу «сервис не отвечает» о полностью живом сервисе — потому что сама проверяющая команда не запускалась.
Все три чинятся в один приём, и ни одна не видна по индикатору. Это тот же класс, что и выдуманное время: механизм отчитывается об успехе, ничего не сделав.
Скажем прямо: этой системы как продукта не будет. Она собрана под уклад одной семьи, и её ценность именно в этом — тиражировать тут нечего.
Переносимо другое, и оно не про дневники, а про любую систему, где ИИ пишет в базу:
- происхождение каждого числа как обязательное поле, а не как просьба в инструкции;
- проверки, при которых выдумку невозможно записать, вместо надписи «не выдумывай»;
- дешёвые ночные проверки вместо дорогих ИИ-контролёров;
- прогон, повторяющий настоящие сбои, а не придуманные примеры;
- различение «нуля» и «данных нет» на всех экранах.
Это единственное, что мы готовы обещать про ИИ: не то, что он не ошибётся, а то, что его ошибку поймает механизм, а не человек глазами.
Если коротко и на профессиональном языке: происхождение живёт в колонке prov и проверяется CHECK-констрейнтом с обязательными спутниками на каждый вид источника; ночные инварианты — чистый SQL без вызовов модели; eval-харнесс на четырнадцать кейсов подменяет только базовый URL и часы; линтер чисел работает на выходе, судейская модель получает только форму и обязана приложить проверяемую цитату. Три бага «зелёного статуса» — это статус присваивания вместо конвейера в подстановке команд, связка pipefail с ранним выходом и отсутствующий каталог лога, съедавший саму команду.
Оставьте номер, и мы перезвоним
Одно поле. Расскажете задачу — как удобно: звонком, в Telegram или голосовым. Сразу назовём срок и вилку цены, а на следующий день пришлём три концепции. Бесплатно.