Журнал правок оператора для ИИ-агента в 1С: снимок предложения, разница при согласовании и откат изменений
В обсуждении моей статьи об узком HTTP-сервисе для агента с правом записи коллега-разработчик описал другой подход: агент ничего не записывает в документы сам, каждое изменение человек подтверждает в форме предпросмотра. И спросил о том, чему в той статье досталась одна строка: как собирать правки оператора в заказах, которые создал агент. Ответ требует кода и сравнения двух схем, поэтому он вынесен в отдельный текст.
Журнал правок отвечает на три вопроса:
- Что именно человек изменил в предложении агента — по полям, а не «документ изменён».
- Как отменить ошибку агента и не задеть то, что уже сделал человек.
- Где агенту (программе с языковой моделью, которая сама выполняет шаги процесса) можно доверять больше, а где нужна проверка — по цифрам за месяц, а не по ощущениям.
Примеры написаны для документа «Заказ клиента» в «1С:Управление торговлей 11» (УТ 11) и «1С:ERP Управление предприятием 2». Код — схема: целиком на стенде он не запускался, поэтому имена реквизитов и значения статусов сверьте со своей редакцией. Общий модуль АгентЖурналПравок, регистр ПравкиОператора и обработка отката условные: их добавляет расширение конфигурации, типовая остаётся на поддержке.
Почему не хватает журнала регистрации и версий объектов
Журнал регистрации записывает событие «Данные. Изменение»: пользователь, время, ссылка на документ. Значений полей в нём нет. Видно, что заказ записали в 10:42, но не видно, что склад поменяли с одного на другой.
Версионирование объектов из Библиотеки стандартных подсистем (БСП) хранит версии документа и строит отчёт о различиях двух версий одного объекта. Для разбора по сотням заказов оно неудобно:
- версия хранится целиком, одним сериализованным значением, и запросом «какое поле правят чаще всего» её не разобрать;
- включено ли версионирование для заказов и в каком режиме (при записи или только при проведении), решают настройки конкретной базы;
- устаревшие версии могут удаляться по сроку хранения;
- главного в версиях нет: какое значение предложил агент, а какое человек поставил после него.
Нужны две вещи: снимок предложения агента в момент предложения и сравнение с тем, что утвердил человек, в момент решения. Как их устроить, зависит от того, пишет агент в документ или только предлагает.
Две схемы: черновик со снимком и пакет с предпросмотром
В первой схеме агент создаёт заказ в статусе «Не согласован» (в интерфейсе он обычно называется «На согласовании»): без резерва, без проведения. Рядом агент сохраняет снимок своего предложения. Во второй агент не трогает документы: он формирует пакет изменений, а человек открывает предпросмотр «было → станет» и применяет пакет своими правами.
| Черновик со снимком | Пакет с предпросмотром | |
|---|---|---|
| Где предложение до решения | В базе: заказ «Не согласован», рядом снимок | В пакете со статусом, документы не изменены |
| Где работает человек | В обычной форме заказа, с типовыми проверками | В отдельной форме «было → станет» |
| Что считается правкой | Разница снимка и заказа в момент согласования | Разница предложения и того, что применили |
| Откат до решения | Пометка удаления заказа, которого человек не касался | Отклонить пакет: в базе ничего нет |
| Откат после решения | Типовыми средствами: отмена строк, закрытие заказа | Обратный пакет с той же проверкой на устаревание |
| Нагрузка на большом потоке | Согласование заказа, как и раньше | Каждый пакет — отдельное решение в новой форме |
| Где уместна | Создание новых документов | Изменение существующих данных |
Сильные стороны предпросмотра стоит признать прямо. База чистая до решения человека. Автор записи в журнале регистрации — сотрудник, а не служебный пользователь. Оператор видит ровно то, что изменится. Цена — новая форма и отдельный клик на каждый пакет: на большом потоке очередь собирается у предпросмотра, и это нужно мерить так же, как любую другую очередь.
Спор между схемами снимает простое правило: новые документы агент может создавать черновиком, существующие данные меняет только пакетом через предпросмотр. Причина в откате. Черновик, которого никто не касался, откатывается пометкой удаления. Изменение поверх чужой работы откатить можно, только если прежнее значение сохранено и с тех пор поле никто не трогал, а это и есть пакет с проверкой на устаревание.
Схема 1: снимок предложения агента
Что попадает в снимок
Только поля, которые выбирает агент: партнёр, контрагент, соглашение, склад и строки товаров с количеством. Цены в снимок не идут: их заполняет типовой код по соглашению, агент их не выбирает.
Строки сравниваются по товару и характеристике, номер строки не годится: оператор вставляет строки, сортирует, делит позицию на две, и номер меняется, а товар остаётся. Одинаковые товары в нескольких строках суммируются.
Каждое значение хранится дважды: строкой XMLСтрока() (для ссылки это уникальный идентификатор объекта) — для сравнения и обычным представлением — для человека, который читает журнал. Текста письма и контактных лиц в снимке нет — только ссылки на справочники базы и количества, так что персональных данных за пределы базы снимок не выносит.
Общий модуль расширения АгентЖурналПравок, флажок «Сервер»:
// Поля шапки, которые выбирает агент; имена — как в УТ 11 / 1С:ERP 2
Функция ПоляШапки()
Возврат СтрРазделить("Партнер,Контрагент,Соглашение,Склад", ",");
КонецФункции
Функция СнимокЗаказа(Заказ) Экспорт
Снимок = Новый Соответствие;
Для Каждого Поле Из ПоляШапки() Цикл
Снимок.Вставить(Поле, ЗначениеСнимка(Заказ[Поле]));
КонецЦикла;
// Ключ строки — товар и характеристика: номер строки оператор меняет сортировкой
Товары = Заказ.Товары.Выгрузить(, "Номенклатура, Характеристика, Количество");
Товары.Свернуть("Номенклатура, Характеристика", "Количество");
Для Каждого СтрокаТовара Из Товары Цикл
КлючСтроки = XMLСтрока(СтрокаТовара.Номенклатура) + "/" + XMLСтрока(СтрокаТовара.Характеристика);
Снимок.Вставить("Товары.Строка|" + КлючСтроки, ЗначениеСнимка(СтрокаТовара.Номенклатура));
Снимок.Вставить("Товары.Количество|" + КлючСтроки, ЗначениеСнимка(СтрокаТовара.Количество));
КонецЦикла;
Возврат Снимок;
КонецФункции
// [0] — для сравнения, [1] — для человека
Функция ЗначениеСнимка(Значение) Экспорт
Пара = Новый Массив;
Пара.Добавить(?(ЗначениеЗаполнено(Значение), XMLСтрока(Значение), ""));
Пара.Добавить(Строка(Значение));
Возврат Пара;
КонецФункции
Функция СнимокВJSON(Снимок) Экспорт
Запись = Новый ЗаписьJSON;
Запись.УстановитьСтроку();
ЗаписатьJSON(Запись, Снимок);
Возврат Запись.Закрыть();
КонецФункции
Функция СнимокИзJSON(Текст) Экспорт
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(Текст);
Снимок = ПрочитатьJSON(Чтение, Истина); // Истина — в Соответствие, ключи-строки сохраняются
Чтение.Закрыть();
Возврат Снимок;
КонецФункции
Снимок сериализуется встроенными ЗаписатьJSON и ПрочитатьJSON: соответствие со строковыми ключами и массивами строк они переводят туда и обратно без потерь. Пустое значение и ноль в снимке совпадают — для количества это допустимо.
Где хранить снимок
У агента уже есть регистр сведений обработанных писем: ключ письма, ссылка на заказ, время обработки. Ему добавляются два ресурса: СнимокАгента (строка неограниченной длины) и ВерсияАгента (строка 50 символов: модель и версия инструкции). Снимок пишется в той же транзакции, что и заказ, после записи документа:
// В транзакции сервиса агента, после ЗаказОбъект.Записать() и сверки статуса
Запись.СнимокАгента = АгентЖурналПравок.СнимокВJSON(АгентЖурналПравок.СнимокЗаказа(ЗаказОбъект));
Запись.ВерсияАгента = Строка(Данные.Получить("agent_version")); // присылает агент, не модель
Порядок важен: при записи типовой код может дозаполнить поля, и снимок после записи фиксирует то, что реально лежит в базе. Тогда разница при согласовании покажет только работу человека.
Разница в момент согласования
Момент сравнения — смена статуса с «Не согласован» на любой другой. Пока заказ не согласован, оператор может записывать его сколько угодно раз; разница снимается один раз и показывает, что человек утвердил по сравнению с предложением агента.
Нужны две подписки на события в расширении с источником ДокументОбъект.ЗаказКлиента. ПередЗаписью читает из базы статус до записи, ПриЗаписи сравнивает и пишет журнал в той же транзакции: если запись заказа откатится, строки журнала откатятся вместе с ней. Обработчики — в том же общем модуле:
// Подписка ПередЗаписью: запоминаем статус, который сейчас в базе
Процедура ЗаказКлиентаПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
Если Источник.ОбменДанными.Загрузка Или Источник.ЭтоНовый() Тогда
Возврат;
КонецЕсли;
УстановитьПривилегированныйРежим(Истина);
Запрос = Новый Запрос(
"ВЫБРАТЬ
| Док.Статус КАК Статус
|ИЗ
| Документ.ЗаказКлиента КАК Док
|ГДЕ
| Док.Ссылка = &Ссылка");
Запрос.УстановитьПараметр("Ссылка", Источник.Ссылка);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Источник.ДополнительныеСвойства.Вставить("АгентСтатусДоЗаписи", Выборка.Статус);
КонецЕсли;
КонецПроцедуры
// Подписка ПриЗаписи: при согласовании заказа агента пишем разницу в журнал
Процедура ЗаказКлиентаПриЗаписи(Источник, Отказ) Экспорт
Если Источник.ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
НеСогласован = Перечисления.СтатусыЗаказовКлиентов.НеСогласован;
СтатусДо = Неопределено;
Если Не Источник.ДополнительныеСвойства.Свойство("АгентСтатусДоЗаписи", СтатусДо)
Или СтатусДо <> НеСогласован Или Источник.Статус = НеСогласован Тогда
Возврат; // это не согласование
КонецЕсли;
УстановитьПривилегированныйРежим(Истина); // у оператора нет прав на журнал — исправить его он не сможет
Запрос = Новый Запрос(
"ВЫБРАТЬ ПЕРВЫЕ 1
| Обработка.СнимокАгента КАК СнимокАгента
|ИЗ
| РегистрСведений.ОбработанныеПисьма КАК Обработка
|ГДЕ
| Обработка.Заказ = &Заказ");
Запрос.УстановитьПараметр("Заказ", Источник.Ссылка);
Выборка = Запрос.Выполнить().Выбрать();
Если Не Выборка.Следующий() Или ПустаяСтрока(Выборка.СнимокАгента) Тогда
Возврат; // заказ создан не агентом
КонецЕсли;
Различия = РазличияСнимков(СнимокИзJSON(Выборка.СнимокАгента), СнимокЗаказа(Источник));
Различия.Добавить(Новый Структура("Поле, КлючСтроки, Вид, Было, Стало",
"Согласование", "", "согласован", Строка(СтатусДо), Строка(Источник.Статус)));
Набор = РегистрыСведений.ПравкиОператора.СоздатьНаборЗаписей();
Набор.Отбор.Заказ.Установить(Источник.Ссылка);
Автор = Пользователи.ТекущийПользователь(); // БСП
Момент = ТекущаяДатаСеанса();
Для Каждого Различие Из Различия Цикл
НоваяЗапись = Набор.Добавить();
ЗаполнитьЗначенияСвойств(НоваяЗапись, Различие);
НоваяЗапись.Заказ = Источник.Ссылка;
НоваяЗапись.Автор = Автор;
НоваяЗапись.ДатаПравки = Момент;
КонецЦикла;
Набор.Записать(); // замещение: при повторном согласовании остаётся последняя разница
КонецПроцедуры
Что здесь важно:
ДополнительныеСвойства— структура, у неё нет методаПолучить, поэтому значение достаётся черезСвойство(Ключ, Значение).- Привилегированный режим, включённый в процедуре, снимается при выходе из неё. В расширении с флажком «Безопасный режим» привилегированный режим недоступен, поэтому модуль журнала живёт в расширении без этого флажка — вместе с сервисом агента.
- Строка «Согласование» пишется всегда, даже без правок. По ней видно, кто и когда согласовал заказ, а заказ «без правок» — это заказ, у которого в журнале одна эта строка.
- Без БСП вместо
Пользователи.ТекущийПользователь()берутПользователиИнформационнойБазы.ТекущийПользователь(). Пользователя информационной базы в регистр не записать, поэтому ресурсАвторстановится строкой и хранит егоИмяилиУникальныйИдентификатор. - Нагрузка:
ПередЗаписьюделает один запрос по ссылке при каждой записи любого заказа, не только созданного агентом, аПриЗаписиобращается к регистру агента только при согласовании. Чтобы этот запрос не перебирал регистр целиком, у ресурсаЗаказвОбработанныеПисьмавключают индексирование.
Регистр сведений ПравкиОператора, независимый: измерения Заказ (ДокументСсылка.ЗаказКлиента), Поле (Строка 50), КлючСтроки (Строка 80); ресурсы Вид (Строка 20), Было и Стало (Строка 150), Автор (СправочникСсылка.Пользователи), ДатаПравки (Дата и время). Документ ЗаказКлиента и справочник Пользователи заимствуются в расширение: без этого их не выбрать источником подписки и типом измерения или ресурса. Сравнение снимков — в том же модуле:
Функция РазличияСнимков(Агент, Оператор) Экспорт
Различия = Новый Массив;
Для Каждого Элемент Из Агент Цикл
Стало = Оператор.Получить(Элемент.Ключ);
Если Стало = Неопределено Тогда
ДобавитьРазличие(Различия, Элемент.Ключ, "удалено", Элемент.Значение[1], "");
ИначеЕсли Стало[0] <> Элемент.Значение[0] Тогда
ДобавитьРазличие(Различия, Элемент.Ключ, "изменено", Элемент.Значение[1], Стало[1]);
КонецЕсли;
КонецЦикла;
Для Каждого Элемент Из Оператор Цикл
Если Агент.Получить(Элемент.Ключ) = Неопределено Тогда
ДобавитьРазличие(Различия, Элемент.Ключ, "добавлено", "", Элемент.Значение[1]);
КонецЕсли;
КонецЦикла;
Возврат Различия;
КонецФункции
Процедура ДобавитьРазличие(Различия, Ключ, Вид, Было, Стало)
Части = СтрРазделить(Ключ, "|");
// У удалённой или добавленной строки хватит записи «Товары.Строка», количество не дублируем
Если Вид <> "изменено" И Части[0] = "Товары.Количество" Тогда
Возврат;
КонецЕсли;
Различия.Добавить(Новый Структура("Поле, КлючСтроки, Вид, Было, Стало",
Части[0], ?(Части.Количество() > 1, Части[1], ""), Вид, Было, Стало));
КонецПроцедуры
Так выглядит журнал одного заказа (условный пример, названия складов и товаров придуманы):
| Поле | Вид | Было | Стало |
|---|---|---|---|
| Склад | изменено | Склад Центральный | Склад Северный |
| Товары.Строка | удалено | Фильтр масляный А-100 | |
| Товары.Строка | добавлено | Фильтр масляный А-110 | |
| Товары.Количество | изменено | 12 | 24 |
| Согласование | согласован | На согласовании | К обеспечению |
Пара «удалено + добавлено» в одном заказе читается как «агент сопоставил письмо не с тем товаром». Изменённое количество при том же товаре — как ошибка чтения письма или единицы измерения. Это разные причины и разные проверки, поэтому журнал и хранит строки по отдельности.
Откат: что можно отменить автоматически
Правило одно: автоматически откатывается только то, чего ещё не касался человек.
Один заказ до согласования. Оператор отклоняет его своими правами: пометка удаления плюс причина из короткого списка (не тот клиент, не та позиция, дубль, письмо не заявка). Причину удобно писать в тот же журнал строкой с видом «отклонён» — через команду, которую расширение добавляет в форму заказа. Как именно встроить команду, зависит от формы вашей редакции.
Серия заказов за интервал. После смены модели или инструкции агент час работал неверно. Ответственный за агента запускает обработку своими правами (его роли нужно чтение регистра агента и право изменять заказы); служебный пользователь агента прав на документы не имеет и откатить ничего не может:
// Модуль объекта обработки «Откат заказов агента»
Процедура ОткатитьЗаказыАгента(Начало, Конец, НеОткачены) Экспорт
Запрос = Новый Запрос(
"ВЫБРАТЬ
| Обработка.Заказ КАК Заказ,
| Обработка.СнимокАгента КАК СнимокАгента
|ИЗ
| РегистрСведений.ОбработанныеПисьма КАК Обработка
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ЗаказКлиента КАК Док
| ПО Обработка.Заказ = Док.Ссылка
|ГДЕ
| Обработка.ДатаОбработки МЕЖДУ &Начало И &Конец
| И НЕ Док.ПометкаУдаления");
Запрос.УстановитьПараметр("Начало", Начало);
Запрос.УстановитьПараметр("Конец", Конец);
Выборка = Запрос.Выполнить().Выбрать();
НеСогласован = Перечисления.СтатусыЗаказовКлиентов.НеСогласован;
Пока Выборка.Следующий() Цикл
Заказ = Выборка.Заказ.ПолучитьОбъект();
// Статус и проведение — из объекта, а не из запроса: между запросом и чтением заказ могли согласовать.
// Условия вычисляются слева направо: снимки сравниваются, только если заказ не согласован
Тронут = Заказ.Проведен Или Заказ.Статус <> НеСогласован
Или ПустаяСтрока(Выборка.СнимокАгента)
Или АгентЖурналПравок.РазличияСнимков(АгентЖурналПравок.СнимокИзJSON(Выборка.СнимокАгента),
АгентЖурналПравок.СнимокЗаказа(Заказ)).Количество() > 0;
Если Тронут Тогда
НеОткачены.Добавить(Выборка.Заказ); // с заказом уже работал человек — решает он
Продолжить;
КонецЕсли;
Попытка
Заказ.УстановитьПометкуУдаления(Истина);
ЗаписьЖурналаРегистрации("АгентЗаявки.Откат", УровеньЖурналаРегистрации.Информация,
Метаданные.Документы.ЗаказКлиента, Выборка.Заказ, "Откат серии заказов агента");
Исключение
// Заказ записали после чтения: платформа не даст записать устаревший объект
НеОткачены.Добавить(Выборка.Заказ);
КонецПопытки;
КонецЦикла;
КонецПроцедуры
Список НеОткачены уходит операторам: эти заказы человек уже открывал, менял или согласовал, и решение по ним принимает он.
После согласования автоматического отката нет. Резерв, ответ клиенту и сборка — действия людей, и отменяются они типовыми средствами: отменой строк, закрытием заказа.
Повторная обработка письма. Защита от дублей по ключу письма вернёт агенту прежний, уже помеченный заказ. Чтобы письмо обработалось заново, запись ключа удаляют отдельным действием — после того как причина ошибки найдена.
Схема 2: пакет изменений и предпросмотр
Здесь агент ничего не пишет в документы. Пакет — справочник или документ расширения с реквизитами:
- источник (ключ письма или задания) и версия агента;
- статус: «Предложен», «Применён», «Применён с правками», «Отклонён», «Устарел»;
- кто и когда решил, причина отклонения;
- табличная часть изменений: объект (составной тип ссылок), поле,
Было—XMLСтрока()значения, которое видел агент,Станет— предложенное значение нужного типа,Применено— то, что утвердил человек.
В форме предпросмотра у каждой строки четыре колонки: поле, «сейчас в базе», «предлагает агент», «утвердить». Колонка «сейчас в базе» читается из базы при открытии формы, не из пакета, — так оператор сразу видит, если данные успели измениться.
Главная техническая ловушка схемы — устаревший пакет. Агент видел значение в 9:00, человек применяет пакет в 15:00, а в 11:00 поле поменял кто-то третий. Применение вслепую затрёт его работу. Поэтому применение идёт под блокировкой и сверяет текущее значение с Было; если хоть одно поле разошлось, объект не записывается:
// Изменения — массив структур (Поле, Было, Станет) по одному объекту; Станет — значение, которое утвердил оператор
Функция ПрименитьИзмененияКОбъекту(Ссылка, Изменения) Экспорт
Результат = "устарел";
НачатьТранзакцию();
Попытка
Блокировка = Новый БлокировкаДанных;
Элемент = Блокировка.Добавить(Ссылка.Метаданные().ПолноеИмя());
Элемент.УстановитьЗначение("Ссылка", Ссылка);
Блокировка.Заблокировать();
Объект = Ссылка.ПолучитьОбъект();
Актуален = Истина;
Для Каждого Изменение Из Изменения Цикл
Если АгентЖурналПравок.ЗначениеСнимка(Объект[Изменение.Поле])[0] <> Изменение.Было Тогда
Актуален = Ложь;
Прервать;
КонецЕсли;
Объект[Изменение.Поле] = Изменение.Станет;
КонецЦикла;
Если Актуален Тогда
Объект.Записать();
Результат = "применён";
КонецЕсли;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
Возврат Результат;
КонецФункции
Функцию вызывает форма предпросмотра в контексте сервера, под правами оператора: в журнале регистрации автором записи будет он. Пример — для реквизитов шапки. Проведённый документ записывают в режиме РежимЗаписиДокумента.Проведение, иначе движения останутся по старым значениям. Изменения табличных частей требуют своего ключа строки, как в снимке выше. Если в пакете несколько объектов и их нужно применить «всё или ничего», внешнюю транзакцию открывает вызывающий код.
Откат после применения — обратный пакет: Было и Станет меняются местами и проходят через ту же функцию. Если поле с тех пор кто-то изменил, откат откажет, и решение снова за человеком.
Журнал пакетов при такой структуре получается сам: по каждому пакету видно, кто предложил (версия агента), кто и когда решил, с каким итогом и по какой причине отклонил. Правки оператора — разница между Станет и Применено у пакетов «Применён с правками». Очередь — пакеты в статусе «Предложен» на конец дня и возраст самого старого из них.
Как читать журнал: решения по цифрам
Какие поля правят чаще всего, за период:
ВЫБРАТЬ
Правки.Поле КАК Поле,
Правки.Вид КАК Вид,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Правки.Заказ) КАК Заказов
ИЗ
РегистрСведений.ПравкиОператора КАК Правки
ГДЕ
Правки.ДатаПравки МЕЖДУ &Начало И &Конец
И Правки.Поле <> "Согласование"
СГРУППИРОВАТЬ ПО
Правки.Поле,
Правки.Вид
УПОРЯДОЧИТЬ ПО
Заказов УБЫВ
Сколько согласовано и сколько из них с правками, по версиям агента:
ВЫБРАТЬ
Обработка.ВерсияАгента КАК ВерсияАгента,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Согл.Заказ) КАК Согласовано,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Правки.Заказ) КАК СПравками
ИЗ
РегистрСведений.ПравкиОператора КАК Согл
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ОбработанныеПисьма КАК Обработка
ПО Согл.Заказ = Обработка.Заказ
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПравкиОператора КАК Правки
ПО Согл.Заказ = Правки.Заказ
И Правки.Поле <> "Согласование"
ГДЕ
Согл.Поле = "Согласование"
И Согл.ДатаПравки МЕЖДУ &Начало И &Конец
СГРУППИРОВАТЬ ПО
Обработка.ВерсияАгента
ВерсияАгента — строка ограниченной длины, иначе по ней нельзя группировать. Доля заказов без правок — 1 − СПравками / Согласовано; её удобно считать уже в отчёте или в Excel.
Какие решения из этого следуют:
- Поле правят часто — на него ставят программную сверку со справочником или порог уверенности: ниже порога заявка уходит в ручную очередь. Порог настраивают по этому же журналу.
- Сменилась модель или инструкция — сравнивают долю без правок до и после на сопоставимых периодах. Новую версию запускают, когда обработка отката серии уже готова.
- «Без правок» не значит «без ошибок». Оператор может согласовывать не глядя. Поэтому часть заказов без правок проверяют выборочно: если выборка находит ошибки, которые пропустил оператор, проблема в согласовании, а не только в агенте.
- Пороги записывают до запуска. Например (это пример, а не норма): поле, которое правят в каждом двадцатом заказе и чаще, получает отдельную проверку; проверку поля, которое за месяц ни разу не правили, а выборочный контроль ошибок в нём не нашёл, можно снять.
Журнал правок — последняя из четырёх контрольных точек после программной сверки, порога уверенности и человека на необратимом действии. Примеры по каждой и расчёт, как ошибки отдельных шагов складываются в ошибку заявки, — в материале о четырёх видах контрольных точек.
Журнал правок и метрика процесса
Журнал показывает качество решений агента. Стал ли процесс быстрее, он не показывает: для этого нужна метрика всего пути заявки — сквозное время «письмо → отгрузка» и очередь несогласованных заказов, снятые ещё до запуска агента.
Одну цифру процесса журнал всё же даёт: время от создания заказа агентом до согласования. Это ДатаПравки строки «Согласование» минус время обработки письма из регистра агента. Если доля заказов без правок растёт, а время до согласования тоже растёт, узкое место переехало к согласующим. Тогда следующий шаг — маршрут согласования, а не точность агента. Например, узкий класс заказов, где журнал долго не показывает правок и выборочный контроль это подтверждает, можно согласовывать без человека. Решает это владелец процесса, по метрике, о которой договорились заранее.
Чек-лист
- В снимке — только поля, которые выбирает агент; строки товаров — по номенклатуре и характеристике.
- Снимок пишется после записи заказа, в той же транзакции, вместе с версией агента.
- Разница снимается при смене статуса, в транзакции записи заказа; строка «Согласование» — всегда.
- В журнале у каждой правки: поле, было, стало, кто, когда. Прав на журнал у оператора нет.
- Автоматический откат — только черновиков, которых не касался человек, под правами ответственного и с записью в журнал регистрации.
- Существующие данные агент меняет только пакетом, с проверкой на устаревание при применении и при откате.
- Пороги решений и выборочный контроль заказов без правок записаны до запуска.
Вопрос к тем, кто уже ведёт журнал пакетов: вы храните правки оператора внутри пакета или только итог «применён / отклонён»? Напишите в комментариях или автору в личные сообщения на Инфостарте — разберу ваш вариант на примере.
Автор — практик: ставит ИИ-агентов в рабочие процессы компаний на 1С.
Вступайте в нашу телеграмм-группу Инфостарт
Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».
- 0% комиссии — оплата напрямую исполнителю;
- Исполнители любого масштаба — от отдельных специалистов до команд под проект;
- Прямой обмен контактами между заказчиком и исполнителем;
- Безопасная сделка — при необходимости;
- Рейтинги, кейсы и прозрачная система откликов.