Интеграция 1С и LLM: передаём контекст формы без лишних связей
Интеграция с LLM (Large Language Models) — уже не экзотика, а рабочий инструмент для анализа документов, генерации ответов в чат-ботах и автозаполнения реквизитов. Однако стандартная практика — передавать в промпт всю форму целиком — приводит к катастрофическому расходу токенов и падению производительности. Разбираем, как передавать ровно тот контекст, который нужен, без лишних связей и «шума».
Проблема: «жирный» контекст и плата за воздух
Когда 1С-специалист впервые интегрирует нейросеть, он часто идёт по пути наименьшего сопротивления: сериализует всю форму в JSON и отправляет в запрос к LLM. На первый взгляд — просто и работает. Но через неделю эксплуатации приходит счёт за токены, а пользователи жалуются на тормоза.
Что на самом деле происходит под капотом
LLM (например, GPT-4o или YandexGPT) тарифицируется по количеству токенов. Каждый лишний реквизит, каждая пустая строка табличной части, каждый заголовок группы — это деньги и время. Форма документа «Реализация товаров и услуг» может содержать 50–80 реквизитов, из которых для ответа нейросети нужны 5–7. Остальное — мусор, который модель вынуждена обрабатывать.
Ключевой тезис: Передача полной формы в LLM — это аналог отправки всего склада, когда нужна только одна коробка. Вы платите за объём, а не за релевантность.
Архитектурный разрыв: форма vs. контекст
Типичная ошибка — использовать СериализоватьJSON для всей формы. Рассмотрим пример, который часто встречается в публикациях на Инфостарте:
// НЕПРАВИЛЬНО: передаём всю форму
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
СериализоватьJSON(ЗаписьJSON, ЭтаФорма);
СтрокаJSON = ЗаписьJSON.Закрыть();
// Отправляем в LLM
HTTPЗапрос = Новый HTTPЗапрос("/v1/chat/completions");
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаJSON);
HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
Проблема в том, что СериализоватьJSON для формы сериализует не только данные, но и служебные свойства: положение на экране, настройки условного оформления, текущую выделенную строку. Это не просто лишние токены — это потенциальная утечка внутреннего состояния системы.
Правильный подход: сборка контекста вручную
Вместо сериализации формы нужно создать структуру ровно с теми данными, которые нужны для решения задачи. Пример для документа «Счёт на оплату»:
// ПРАВИЛЬНО: собираем только нужные данные
Контекст = Новый Структура;
Контекст.Вставить("Номер", Объект.Номер);
Контекст.Вставить("Дата", Объект.Дата);
Контекст.Вставить("Контрагент", Объект.Контрагент.Наименование);
Контекст.Вставить("Сумма", Объект.СуммаДокумента);
// Табличная часть — только значимые строки
Товары = Новый Массив;
Для Каждого Строка Из Объект.Товары Цикл
Если Строка.Количество > 0 Тогда
Товар = Новый Структура;
Товар.Вставить("Наименование", Строка.Номенклатура.Наименование);
Товар.Вставить("Количество", Строка.Количество);
Товар.Вставить("Цена", Строка.Цена);
Товары.Добавить(Товар);
КонецЕсли;
КонецЦикла;
Контекст.Вставить("Товары", Товары);
// Сериализуем только контекст
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, Контекст);
СтрокаJSON = ЗаписьJSON.Закрыть();
Важно: Фильтрация пустых строк табличной части сокращает объём данных на 30–50% в типовых документах. Это не микрооптимизация, а существенная экономия.
Сравнение подходов: когда что применять
Выбор стратегии зависит от задачи. Ниже — условия применимости, проверенные на реальных проектах.
| Подход | Когда использовать | Когда НЕ использовать |
|---|---|---|
| Ручная сборка структуры | Точечные запросы: анализ одного документа, генерация описания, проверка реквизитов | Массовая обработка сотен документов с разной структурой (слишком много кода) |
| Сериализация формы целиком | Только для отладки или прототипирования | Промышленная эксплуатация — дорого и небезопасно |
| Динамическая сборка по метаданным | Универсальные обработки, где структура документа неизвестна заранее | Если нужна высокая скорость — рефлексия замедляет работу |
Практическое руководство: как внедрить без боли
Переходим к конкретным шагам, которые можно применить в вашей конфигурации уже сегодня.
Шаг 1. Определите «скелет» контекста
Для каждого типа документа или справочника, с которым работает LLM, создайте отдельную функцию формирования контекста. Пример для документа «Заказ клиента»:
Функция КонтекстЗаказаКлиента(Док) Экспорт
Результат = Новый Структура;
Результат.Вставить("Тип", "Заказ клиента");
Результат.Вставить("Номер", Док.Номер);
Результат.Вставить("Дата", Док.Дата);
Результат.Вставить("Клиент", Док.Контрагент.Наименование);
Результат.Вставить("Менеджер", Док.Ответственный.Наименование);
Результат.Вставить("Сумма", Док.СуммаДокумента);
Позиции = Новый Массив;
Для Каждого Стр Из Док.Товары Цикл
Если Стр.Количество = 0 Тогда Продолжить; КонецЕсли;
Поз = Новый Структура;
Поз.Вставить("Товар", Стр.Номенклатура.Наименование);
Поз.Вставить("Кол", Стр.Количество);
Поз.Вставить("Цена", Стр.Цена);
Поз.Вставить("Сумма", Стр.Сумма);
Позиции.Добавить(Поз);
КонецЦикла;
Результат.Вставить("Позиции", Позиции);
Возврат Результат;
КонецФункции
Шаг 2. Добавьте фильтр чувствительных данных
Перед отправкой убедитесь, что в контекст не попали персональные данные, которые нельзя передавать внешнему сервису. Создайте функцию-очиститель:
Процедура ОчиститьКонтекст(Контекст)
// Удаляем поля с персональными данными
Если Контекст.Свойство("Телефон") Тогда
Контекст.Удалить("Телефон");
КонецЕсли;
Если Контекст.Свойство("Email") Тогда
Контекст.Удалить("Email");
КонецЕсли;
// Рекурсивно для вложенных структур
Для Каждого Ключ Из Контекст Цикл
Если ТипЗнч(Контекст[Ключ.Значение]) = Тип("Структура") Тогда
ОчиститьКонтекст(Контекст[Ключ.Значение]);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Типичные ошибки и как их избежать
На основе опыта внедрения интеграций с LLM в десятках компаний выделим три главные ловушки.
- Передача ссылок вместо текста. Никогда не отправляйте
Объект.Контрагенткак ссылку. LLM не поймёт"Ссылка: 00-0000123". Всегда преобразуйте вКонтрагент.Наименование. - Игнорирование длины промпта. Если табличная часть содержит 1000 строк, не отправляйте их все. Либо агрегируйте (суммы по группам), либо ограничьте первые N строк с пометкой «и ещё X позиций».
- Отсутствие кэширования. Если один и тот же документ анализируется повторно (например, при переоткрытии формы), результат LLM можно кэшировать в регистре сведений. Это сократит расходы в 2–3 раза.
Предупреждение: Не используйте СериализоватьJSON для формы, если форма содержит элементы управления ActiveX или COM-объекты. Это может привести к зависанию платформы при сериализации.
Чек-лист: что сделать прямо сейчас
- Проверьте все места в конфигурации, где вызывается LLM — замените сериализацию формы на ручную сборку контекста.
- Добавьте функцию очистки контекста от персональных данных перед отправкой.
- Внедрите агрегацию для табличных частей с большим количеством строк.
- Реализуйте кэширование ответов LLM для повторяющихся запросов.
- Настройте логирование размера контекста в токенах — это позволит отслеживать аномалии.
Вывод
Интеграция 1С и LLM — мощный инструмент, но только при условии, что вы контролируете, что именно отправляете нейросети. Передача контекста формы без лишних связей — это не просто экономия токенов, а вопрос стабильности и безопасности системы. Начните с малого: выберите один документ, реализуйте для него функцию формирования контекста и сравните расходы с предыдущим подходом. Разница вас удивит.
Попробовать НОПик →
Проверить свой уровень бесплатно →