Агенти за митнически и регулаторни декларации
AI агенти, които подготвят митнически и регулаторни декларации, а всяко число се проверява от код
- Роля
- Ръководех AI инженерството в малък екип в DigiSol
- Статус
- Работи
- Код
- Клиентски проект
- Технологии
- Next.js 16TypeScriptshadcn/uiRadixTailwind 4TanStack TablePythonFastAPILangGraphAG-UIPostgreSQLLiteLLMLangfuseKeycloakoauth2-proxyCaddyDocker ComposeGitea CI
В числа
135/ 135
суми от закрито разрешение, възпроизведени от модула за закриване на стимули
1 185/ 1 185
клетки от собствената матрица на потреблението на клиента, преизчислени идентично от суровите параметри
166/ 166
реда от доклада за капацитета, преизчислени точно и съпоставени с подписаните окончателни доклади
24/ 24
реда от одобрена декларация, възпроизведени и пазени като постоянен регресионен тест
8 355
теста на агентската част преминаха в един пълен пуск
85/ 85
реда за внос, класифицирани еднакво с файла, който клиентът е класифицирал на ръка
Проблемът
Голям индустриален производител подава всяка година три семейства регулирани документи: годишен доклад за производствения капацитет, проучвания за разрешения за данъчни стимули и заявления за митнически разрешения. Правилата се пазеха в електронни таблици, в записани срещи и в главите на няколко специалисти, а нищо от това не беше документирано. Грешна цифра в тези документи има регулаторни последствия, затова модел, който сам произвежда числа, беше неприемлив от самото начало.
Подходът
Преди да напиша какъвто и да е код, възстанових процесите в писмени спецификации. Всяко твърдение отбелязвах като доказано, теория или отворено, а зад доказаните стоеше скрипт, който го доказва. Редът на работа беше определен рано: първо генерираните документи трябваше да са верни, а интерфейсът и агентът идваха след това. Работех в малък екип. Водещият разработчик отговаряше за инфраструктурата, идентичността, шлюза към моделите и пускането на версии, а аз отговарях за модулите на отделите, проверката на изчислителните модули, договореността на интерфейсната част и шаблоните за управление. Своята част изградих с много AI агенти за програмиране, които работеха под проверки преди приемане, проектирани от мен: пиша изискванията и критериите за приемане, чета доказателствата и решавам.
Как работи
Модули, проверявани по историята на клиента
Моделът не прави аритметика. Всяко число идва от детерминиран изчислителен модул: генератори на документи, които възпроизвеждат доклада за капацитета във формата на всеки получател, модул за закриване на стимули, класификатор на тарифни кодове и генератор на работни листове за заявления за разрешения. Преди да се доверя на даден модул, включих в проекта оригиналните референтни страници, записах числовия им резултат като еталонен JSON и пренесеният код трябваше да съвпада с него цифра по цифра. Класификаторът е единственото място, където преценява модел, и то само на третото ниво, след търсене в регистрирани връзки и след модул с правила, изграден върху официалния текст на тарифата, а пред модела стои пакет с доказателства.
Нищо не се генерира без преглед
Качените файлове първо се задържат отделно, сравняват се с текущото състояние и се съпоставят ред по ред. Двусмислено съвпадение се отхвърля, а име без съвпадение проваля вноса. Преди всеки запис предишното състояние се архивира, човек преглежда данните, преди да може да се генерира документ, а генерирането тръгва от замразена моментна снимка на данните. След това втори, независим изчислителен процес преизчислява всеки генериран файл и го изхвърля при всяка разлика. Всичко, което модулите не могат да остойностят, показва изрично състояние „няма двойка“ вместо число.
Агенти около страниците, с подписани одобрения
Операторите работят върху обикновени страници, захранвани с данни през REST. Всеки отдел има един прост граф LangGraph StateGraph с възел за чат и възел за инструменти, като на всяка стъпка се извиква по един инструмент, а отгоре няма координиращ агент. Където асистент помага, той вижда състоянието на страницата и управлява същите контроли като човека. Инструментите, които променят данни, са разпределени по нива на риск: запис със среден риск чака на карта за одобрение, чийто подпис покрива каноничните аргументи, а цяла серия редакции става едно одобрение, едно решение в одита и едно повишаване на номера на ревизията. При един одит открих път, по който инструментите за запис в интерфейсната част променяха работната база данни без никаква карта, и го премахнах.
Заключена в мрежата на клиента
Продукцията работи на сървър в мрежата на клиента, зад единен вход (SSO) и входна проверка. Всеки агент има собствена идентичност, а ефективните му права са сечението на правата на потребителя, на агента и на ресурса, така че правомощията могат само да се свиват. Приложението няма общ достъп до интернет: изходящите връзки следват списък с разрешени адреси, с класификация на данните за всяка дестинация, а нощен одит на изходящия трафик проверява дали телеметрията на доставчиците остава изключена. Всеки AI чат се проследява по потребител, всяко извикване на инструмент, действие на администратор и запис на данни попада в таблица за одит само за добавяне, а CI сканира контейнерните образи за уязвимости. Водещият разработчик проектира интеграционната точка за идентичността, а аз написах изискванията за изходящите връзки.
Пускане на версии с агенти за преглед
Преди версия за продукция седем агента за преглед проверяваха кандидата едновременно и завеждаха находките си като задачи. Агенти за поправки работеха в изолирани git worktree, тестване в браузър върху реалните файлове на клиента откри нови блокиращи проблеми в един от процесите, а поправките бяха тествани повторно, преди всеки pull request да бъде слят, един по един, при отделен пуск на CI, по инструкция за пускане със smoke тест и стъпка за връщане към предишната версия. После продукцията работи с поправената версия. Миграциите са само напред, затова пътят за възстановяване се репетира.
Какво избрах и какво отпадна
Избрах
Първо страниците: обикновени страници, в които е вграден агентът
Пред
Портал, ориентиран към чата, в който агентът е основният интерфейс
Операторите се нуждаят от страници, които могат да четат и проверяват. Ако първо изградя страниците и после оставя агента да ги използва, агентът получава същите контроли като човека, а всяка промяна се вижда на място, където някой може да я прегледа.
Избрах
Един прост граф за отдел и без координиращ агент
Пред
Координиращ агент, който насочва заявките между агентите на отделите
Координиращият агент застава между потребителя и извикването на инструмент и размива кой какво е решил. Един граф за отдел с по едно извикване на инструмент на стъпка пази одитната следа четлива.
Избрах
Комплект за интерфейса без логика: браузърът никога не изчислява и никога не извлича данни
Пред
Аритметика и извличане на данни вътре в компонентите на интерфейса
Когато само едно място изчислява, има само едно място за проверка спрямо историята. Границата оцеля след две пълни подмени на сървърната част с няколко променени реда.
Избрах
Облекчен профил за продукция, с чат само на страницата за класификация
Пред
Асистент на всяка страница
Където агентът не добавяше нищо към детерминираната страница, го премахвах. По-малко агенти в продукция означава по-малко точки на отказ и по-малко за преглед.
Части от софтуера, възстановени, за да ги пипнете
Данните на клиента никога не напускат мрежата му, затова това са възстановки: същата структура, но с измислени продукти, хора и числа.
Експонат 01
Карта за одобрение
Картата, на която чака промяната на данни от агент, докато човек я приеме или отхвърли.
Обновяване на нормите за разход
Агент Калоян действа от името на Р. Петрова
3 промени, едно одобрение
| Поле | Текущо | Предложено |
|---|---|---|
| Основна смес на линия 7, kg на единица | 0,42 | 0,40 |
| Добив на партида A-114, % | 92,0 | 93,5 |
| Допустим отпадък, профил P-40, % | 3,0 | 2,5 |
7f3a 91c2 e04b 5d18Експонат 02
Лист с двойно изчисление
Проверката, която се изпълнява за всеки генериран файл: записаните във файла числа до независимо преизчисление. Файл с каквато и да е разлика се изхвърля.
Годишен доклад за капацитета, раздел B
От снимка S-0193, замразена в 09:40
| Позиция | Основа | Записано | Преизчислено | Разлика | Статус |
|---|---|---|---|---|---|
| B.1 Производство на линия 7 | 1 200 t × 0,92 | 1104,0 | 1104,0 | 0,0 | съвпада |
| B.2 Производство на линия 9 | 800 t × 0,95 | 760,0 | 760,0 | 0,0 | съвпада |
| B.3 Партида A-114 | 400 t × 0,90 | 360,0 | 360,0 | 0,0 | съвпада |
| B.4 Смола R4, от внос | няма цена за изчислението | Без съпоставяне | Без съпоставяне | несъпоставено | |
| B.5 Общо за раздела | B.1 до B.3 | 2224,0 | 2224,0 | 0,0 | съвпада |
Експонат 03
Отчет за съвпадение при повторно възпроизвеждане
Как един изчислителен модул печели доверие: резултатът му, пуснат отново върху минала декларация с еталонен отговор, с посочен вид на доказателството.
119/ 120 съвпаднали
Допустимо отклонение: точно, до стотинка
Повторен прогон върху минала декларация, за която има еталон.
Несъответствия
| Ред | Очаквано | Получено | Проследена причина |
|---|---|---|---|
| Ред 47 | 1 250,00 | 1 200,00 | Изходната електронна таблица събира ред 47 два пъти, а подадената цифра съдържа грешката. |
golden: permit_closure_case_aЕкспонат 04
Сравнение на подготвения внос
Какво вижда човек между качването на работна книга и промяната на каквито и да е данни.
rates-update.xlsx
Лист Ставки, прочетени 64 реда, още нищо не е записано
Нови2
- Профил P-52: 4,10 на m
- Партида A-120: 91,0%
Променени4
- Основна смес на линия 7: 0,42 става 0,40
- Профил P-40: 3,85 на m става 3,90 на m
- Смола R4: 2,20 на kg става 2,35 на kg
- Партида A-114: 92,0% става 93,5%
Без съответствие1
- Профил P-44: няма запис с това име
Едно име без съответствие проваля целия внос. Поправете файла и го качете отново.
Експонат 05
Одитна следа
Записът само за добавяне на извикванията на AI инструменти, възобновяванията, записите в паметта, промените в работната маса и действията на администратори. Съхранява препратки, а не съдържание на документи.
Одитна следа
Само препратки, без съдържание на документи
| Час | Кой | Действие | Обект | Резултат | Проследяване |
|---|---|---|---|---|---|
| 09:40:12 | Агент Калоян за Р. Петрова | Извикване на инструмент | propose_edits, 3 промени | чака на карта C-77 | |
| 09:41:03 | Р. Петрова | Одобрение | карта C-77 | одобрено | човек |
| 09:41:03 | Агент Калоян за Р. Петрова | Запис на данни | норми, версия от 41 на 42 | записано | |
| 09:44:50 | Агент Десислава за Н. Стоянов | Възобновяване | сесия S-12 | възобновена | |
| 09:46:18 | Агент Десислава за Н. Стоянов | Запис в паметта | бележка M-9 | запазена | |
| 09:52:31 | Д. Илиева | Администриране | даване на роля, страница Внос | дадена | човек |
| 10:02:07 | Агент Боян за Р. Петрова | Извикване на инструмент | generate_report от S-0193 | одобрено след повторна проверка |
Резултатът
Системата работи в продукция, изградена върху четири агента за отдели и един общ процес за трите семейства документи. Коректността се доказва чрез повторно възпроизвеждане: модулът за закриване на стимули възпроизвежда и 135-те суми на закрито разрешение, собствената матрица на потреблението на клиента се преизчислява идентично във всичките 1 185 клетки, 166 от 166 реда на доклада за капацитета съвпадат с подписаните окончателни доклади, генераторът на заявления възпроизвежда и 24-те реда на одобрена декларация, а класификацията на редове за внос съвпадна с файла на клиента, класифициран на ръка, в 85 от 85 реда. В последните си пълни пускове наборът от тестове на агентската част премина 8 355 теста, а уеб наборът 1 682, като покритието на редовете беше 92,1% срещу наложен минимален праг. Същата проверка улови преувеличено твърдение за точност, преди то да излезе: независимо повторно извеждане не го потвърди и то беше махнато от чернова за клиента. Ограничения: един от четирите агента за отдели е изключен в продукция, а следенето на грешки още не подаваше данни от продукцията при последната проверка, затова твърдя само проследяването на AI чатовете, отчитането на токените и одита.
Какво следва
Права за достъп по страници, така че потребителят да има само страниците, от които се нуждае работата му, и включено следене на грешките в продукция.