Перейти к основному содержимому
megapromotingДавайте обсудим

Решения · Финансовые услуги

Агент, который классифицирует денежные движения, выбирая из закрытого списка, а не составляя предложение, которое затем кто-то интерпретирует.

В финансовой организации полезный агент не дает советов и ничего не одобряет: он читает документы и транзакции, относит их к категории из фиксированного набора, говорит, насколько он уверен, и может ответить «не знаю». Остальное — решение, одобрение, политика — остается за людьми.

Предложение с условиямиNu scriem „livrat”, pentru că nu avem un agent de acest fel pus în producție la un client din sectorul financiar. Ce avem, și arătăm exact ca atare, e o conductă proprie de ingestie care rulează pe datele noastre: cinci module Python, 1.526 de linii, care citesc notificări bancare din e-mail și extrase în PDF, clasifică fiecare tranzacție prin unelte și o scriu în PostgreSQL cu dedublare, plus patru fluxuri de automatizare pentru webhookuri de la trei procesatori de plăți. Starea reală, spusă în aceeași frază: depozitul nu e sub git, directoarele `tests/` și `webhook-server/` sunt goale, iar potrivirea aproximativă a numelor de contrapartidă folosește o euristică de n-grame marcată în cod ca „de înlocuit cu un serviciu de înglobare înainte de producție”. Partea de platformă financiară în producție — flux de cerere, contract, grafic de plăți, audit — e o lucrare separată, cu dovezile ei, și acolo scriem „livrat”.

Запросы на AI-агентов в финансовых сервисах почти всегда приходят в форме «чтобы отвечал клиентам на вопросы о наших продуктах». Это законный запрос, но время там не выигрывается. Время теряется в другом месте: кто-то каждый день открывает десятки банковских уведомлений и выписок, смотрит на описание в виде строки из заглавных букв с кодом и решает, является ли это поступлением от клиента, зарплатой, налогом, платежом кредитору или операционным расходом. Эта работа повторяющаяся, скучная и, именно поэтому, полная ошибок.

Языковая модель хороша в этом, при одном условии: от неё нельзя требовать писать ответ в свободном тексте. Если вы просите предложение, его будете парсить вы, и парсинг вы ошибёте. В нашей проводке модель не пишет: она получает семь инструментов и должна вызвать ровно один — поступление от клиента, зарплата, налог, платёж кредитору, операционный расход, банковская комиссия или неизвестно. Каждый инструмент требует, помимо имени контрагента или категории, показатель уверенности от 0 до 1. «Неизвестно» требует письменную причину. Выход — структура, а не мнение.

Второе правило — ничто не попадает дважды. Каждая транзакция, извлечённая из уведомления или из выписки, получает внешний идентификатор, рассчитанный как префикс из 16 символов от SHA-256-хэша по её полям, столбец уникален в таблице, а вставка выполняется с `ON CONFLICT (external_id) DO NOTHING`. Практическое следствие: почтовый ящик можно перечитывать сколько угодно раз, а баланс не удваивается. Без этого правила любая финансовая ingest-проводка к третьей неделе начинает порождать дубликаты, которые кто-то чистит вручную.

Чего такой агент не делает и почему важно писать это на странице: он не утверждает платёж, не принимает кредитное решение, не даёт инвестиционные рекомендации и не отвечает клиенту от имени учреждения. Показатель уверенности, который он возвращает, — это оценка модели о самой себе, а не измерение точности, сделанное нами — это различие и есть разница между инструментом и иллюзией контроля.

Что входит

Что конкретно меняется в финансовых сервисах

Документ попадает один раз, даже если мы читаем его десять раз

Уведомления читаются из почтового ящика по IMAP, выписки — из PDF. Каждая транзакция получает внешний идентификатор из SHA-256-хэша по её полям, столбец `external_id` в таблице `NOT NULL UNIQUE`, а вставка выполняется с `ON CONFLICT (external_id) DO NOTHING`, с отдельным журналом для вставленной строки и для пропущенной как дубликат. Повторное чтение того же ящика не создаёт ни одного дубликата.

Классификация выполняется с помощью инструментов, с закрытым списком результатов

Семь инструментов, а не свободный текст: поступление от клиента, зарплата, налог, платёж кредитору, операционный расход, банковская комиссия, неизвестно. Модель должна вызвать только один. Первые шесть обязательно требуют, помимо имени или категории, показатель уверенности от 0,0 до 1,0, объявленный в схеме инструмента; седьмой требует причину. Используемая модель объявлена в коде, а не скрыта в конфигурации.

«Неизвестно» — это легитимный выход, с причиной

Классификатор, которому нельзя сказать «не знаю», будет ошибочно относить с высокой уверенностью именно необычные транзакции — то есть те, которые важны. Поэтому инструмент неизвестного доступен так же, как остальные, и требует письменную причину, которая попадает в строку. Строки неизвестного — это рабочий список человека, а не сбой системы.

Приблизительное сопоставление имён контрагентов, с его реальным состоянием

Одна и та же компания в выписках встречается в трёх написаниях. Над классификацией есть сопоставление по косинусному сходству между векторами. Сегодня мы точно говорим, что представляют собой эти векторы: это эвристика из n-грамм символов, написанная в коде с комментарием, что для production её нужно заменить на реальный вызов сервиса эмбеддингов. Она работает для вариантов написания; это не семантическое сопоставление.

Webhook-ы от платёжных процессоров попадают в ту же таблицу

Четыре потока автоматизации, по одному для трёх платёжных процессоров и один для ежедневной сверки, по 7 до 10 узлов каждый. Архитектурная идея в том, что разные источники — e-mail, PDF, webhook — не создают три таблицы, которые потом нужно сводить, а создают строки в одной и той же таблице, с тем же правилом дедупликации.

Потребление модели находится под бюджетом на ключ, а не под счётом

Запросы проходят через собственный шлюз к `api.megapromoting.com/v1`, с 44 настроенными моделями, у каждой — стоимость за токен и лимит контекста. У проектного ключа есть белый список моделей, бюджет и период, его можно ротировать с сохранением истории, а потребление ежедневно консолидируется по пользователь × ключ × модель. Деталь, которая удивляет всех: модели рассуждения производят внутренние шаги, которые система отслеживания не видит, но поставщик их выставляет к оплате — значит, грубый бюджет по ключу задается ниже желаемого потолка.

Что можно запускать, чтобы данные не покидали машину

Для шагов, которым не нужна большая модель — извлечение полей из известного формата, сопоставление имен, проверки согласованности — не нужен никакой внешний поставщик; это обычный код. Модель вызывается только для шага классификации. Когда ваша политика запрещает вывод данных, речь идет о том, что именно отправляется модели, а не о том, используется ли AI: можно отправлять описание транзакции без идентификаторов счета.

Что не делает и не будет делать такой агент

Он не одобряет платеж и не выполняет перевод. Он не принимает решение о кредитовании — правила, пороги и одобрение задает политика учреждения. Он не дает инвестиционных рекомендаций и не отвечает клиенту от вашего имени без отдельного маршрута согласования. И он не гарантирует вам точность: score de încredere — это выход модели о самой себе, а не независимое измерение.

Traseul

Как запрос проходит через систему.

01

Фиксируем закрытый список результатов до любого кода

Первая поставка — не агент, а список: категории, в которые ему разрешено относить, какие обязательные поля требуется для каждой, и что означает «неизвестно» у вас. Если список нельзя записать на одной странице, задача не подходит для агента — и лучше узнать это сейчас.

02

Строим ingest и dedup без модели

Чтение из e-mail, PDF или webhook, извлечение полей, расчет внешнего идентификатора и запись в базу выполняются и проверяются без единого обращения к модели. Мы поставляем конвейер, который корректно ingerează и не дублирует. Если этот шаг неустойчив, модель поверх него лишь производит более убедительные ошибки.

03

Добавляем классификацию и измеряем ее на ваших случаях

Поверх работающего конвейера мы ставим инструменты классификации и прогоняем на наборе ваших реальных транзакций с правильным результатом, определенным человеком, который сегодня выполняет эту работу. Мы поставляем таблицу с совпадениями и расхождениями, а не утверждение о точности. Порог, при котором строка уходит человеку, выбирается из этой таблицы.

04

Ставим бюджет, журнал и пороги

Проектный ключ с белым списком моделей и бюджетом, ежедневная консолидация потребления, журнал с вызванным инструментом и оценкой, и гейт, который отправляет человеку всё, что ниже порога или неизвестно. Передаем доступы, документ ввода в эксплуатацию и письменный список того, что агент делает сам и чего не делает.

1E-mail, PDF sauwebhook2extragerea câmpurilor3amprentă SHA-2564scriere cu ONCONFLICT DO NOTHING5încadrare prin unadin șapte unelte, cuscorrândurile„necunoscut” către om
Traseul, în 6 pași

Данные

К чему прикасаемся, где оно лежит и сколько остаётся

Правила различаются от одной отрасли к другой. Это те, что применяются в финансовых услугах.

Какие данные он реально затрагивает
Движения денег, с датой, суммой, валютой, описанием и контрагентом. Часть контрагентов — физические лица — зарплата содержит имя сотрудника — поэтому таблица содержит персональные данные сотрудников, а не только коммерческие данные. Это меняет, у кого есть право открывать таблицу.
Что уходит к модели и что остается на месте
К модели поступают текст описания транзакции и сумма. Идентификаторы счёта, IBAN и остальные поля не нужны в запросе, чтобы сработала классификация, поэтому их можно оставить за его пределами. Общее правило, которое мы применяем: всё, что не нужно для соответствующего шага, не отправляется, потому что то, что не ушло, не может быть ни у кого удержано.
Где хранятся извлечённые данные
PostgreSQL, с уникальным `external_id` и индексом по нему. База остаётся вашей, на вашей инфраструктуре или на той, которой управляем мы. Общего хранилища между клиентами нет, потому что нет технической причины, по которой оно должно существовать.
След автоматического решения
Каждая строка сохраняет, какой инструмент был вызван, с каким score и, когда это нужно, причину «неизвестно». Это минимально необходимое, чтобы через шесть месяцев кто-то мог ответить на вопрос «почему эта транзакция была отнесена к операционным расходам» — с ответом, а не с пожатием плечами.
Срок хранения, который здесь вы не выбираете сами
Финансовые документы имеют сроки хранения, установленные бухгалтерским и налоговым законодательством, а не нашими или вашими предпочтениями. В финансовом проекте срок берётся из этих правил, записывается в реестр обработок и только потом реализуется удаление. Обратный порядок — сначала реализуется, потом проверяется — приводит к системам, которые удаляют то, что следовало сохранить.

Случай

Конвейер ingest, который можно перезапустить без страха

Ситуация

Банковские уведомления и ежемесячные выписки попадали в почтовый ящик и читались человеком, который относил их к категориям. Первый очевидный вариант — скрипт, который читает ящик и пишет в базу, — имеет проблему, которая становится заметной лишь на третьей неделе: при любом перезапуске или повторном чтении одни и те же транзакции заходят снова.

Что мы построили

Я написал пять модулей, 1.526 строк Python: два парсера уведомлений через IMAP, извлекатель PDF-выписок, классификатор через инструменты и запись в PostgreSQL. Центральное правило — внешний идентификатор: префикс из 16 символов от SHA-256-отпечатка по полям транзакции — с уникальной колонкой в таблице и вставкой `ON CONFLICT DO NOTHING`. Классификация не возвращает текст: модель вызывает один из семи инструментов, с обязательным score уверенности, а «неизвестно» требует причину.

Что получилось

Почтовый ящик можно перечитывать в любой момент, а уже обработанные строки пропускаются и помечаются как дубликат в журнале. Транзакции, которые модель не может классифицировать, попадают в список задач, с указанием причины рядом, вместо того чтобы их запихивали в категорию, чтобы казалось, что всё прошло.

Чего этот случай не говорит

Это внутренняя конвейерная система, а не система, поставленная финансовому клиенту: она не под git, тестовые каталоги пусты, а приблизительное сопоставление имён использует эвристику n-грамм, которую код явно помечает как временную. Я описал её здесь, потому что она показывает метод, а не потому, что это продукт.

Вопросы

Что спрашивает человек из финансовых услуг

Агент одобряет платежи или кредиты?

Нет, и это не техническое ограничение, которое мы преодолеем в следующей версии. Одобрение — это решение с юридическими последствиями, которое принадлежит уполномоченному лицу в учреждении. Агент готовит: классифицирует, заполняет, сигнализирует о том, что не совпадает. Система, которая одобряет сама, должна уметь отвечать перед контролёром, а score уверенности — не ответ.

Как я узнаю, что он классифицировал правильно?

Не по score уверенности — это оценка модели о самой себе, а не измерение. Это известно из сравнения с решениями человека, который делает эту работу сегодня, на наборе реальных транзакций, проведённого до запуска чего-либо в автоматическом режиме. Результат такого сравнения — таблица, которую мы поставляем, включая строки, в которых агент ошибся.

Что происходит, когда он не уверен?

Вызовите инструмент «неизвестно» и укажите причину. Строка попадает в рабочий список человека, а не в случайно выбранную категорию, чтобы казалось, что система сработала. Классификатор без выхода «не знаю» ошибается именно там, где ошибка стоит дорого: на необычных транзакциях.

Если мы дважды прочитаем одно и то же уведомление, сумма удвоится?

Нет. У каждой транзакции есть внешний идентификатор, вычисленный как отпечаток по её полям, столбец уникален, а вставка использует `ON CONFLICT (external_id) DO NOTHING`. Пропущенная строка отмечается в журнале как дубликат, так что видно, что её прочитали повторно.

Наши данные уходят поставщику модели?

Для шага отнесения — да: описание транзакции и сумма уходят в выбранную модель через наш gateway, с проектным ключом, белым списком моделей и бюджетом. Остальные шаги — чтение, извлечение, дедупликация, сопоставление имён — это обычный код, и они никуда не уходят. Что именно можно отправлять, определяется письменно заранее, а не выясняется по журналам потом.

Вы можете читать выписки в PDF, а не только уведомления по e-mail?

Да, это один из модулей конвейера. Важно понимать, что PDF-выписка — хрупкий формат: она читается по структуре, которую создаёт соответствующий банк, а когда банк меняет шаблон, модуль нужно доработать. Поэтому он пишется с проверками, которые падают шумно, а не с теми, что угадывают.

Почему на этой странице написано «оферта», а не «доставлено»?

Потому что наше правило требует минимум двух собственных внедрений, чтобы мы писали «доставлено», а описанный здесь конвейер работает на наших данных, а не в продакшене у клиента из финансового сектора. У него есть и ограничения, которые мы называем прямо: он не под git, у него нет тестов, а сопоставление имён использует эвристику, помеченную в коде как временная. Когда мы сможем сослаться на два внедрения у клиентов, мы изменим слово.

Что нам нужно от себя, чтобы начать работу?

Три вещи: закрытый список категорий, в которые ему разрешено отнести, набор реальных транзакций с правильным ответом, данным человеком, который сейчас выполняет эту работу, и письменное решение о том, какие поля могут выходить из вашей сети. Без третьего пункта мы не начинаем, потому что это единственное, что нельзя исправить позже.

Что вы хотели бы наладить?

Расскажите о своём процессе. Вместе определим, что стоит построить, что можно подключить и как проверим результат.

Давайте обсудим