Məzmuna keç
Tez Base

Код 1С от нейросети: как найти выдуманные методы и поля до первого запуска

· Dərc edilib:

1С Нейросети и 1С

Модель, которая пишет код 1С, почти никогда не ошибается в грамматике. Ошибается она в именах: берёт их по аналогии, и аналогия звучит убедительно. ОбщегоНазначения.ПолучитьЗначениеРеквизитаОбъекта похоже на БСП ровно настолько, чтобы его не перепроверяли, но в типовой УТ 11.5 такой функции нет. Там есть ЗначениеРеквизитаОбъекта и ЗначениеРеквизитаОбъектов.

Обычно про выдуманное имя узнают в момент, когда выполнение до него дошло. Если повезло, на копии. Эта статья про то, как найти такие места раньше: какая проверка какой класс ошибок вообще способна заметить и чем закрыть те, что не видит никто.

Карта: класс ошибки и проверка, которая его видит

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

Что выдуманоВыполнить с обёрткой Если ЛожьЧто закрывает дыру
синтаксис: лишний знак, цикл без КонецЦиклаловит, со строкой и колонкой-
глобальная функция, которой нетловит-
общий модуль, которого нетловит как “Переменная не определена”-
справочник, документ, регистрмолчитколлекции Метаданные
реквизит объектамолчитМетаданные, включая стандартные реквизиты
метод общего модулямолчитвызов со ста аргументами
метод менеджера или объектамолчиттот же вызов, для объекта на экземпляре в памяти
поле в тексте запросамолчит, текст запроса для него просто строкаНайтиПараметры() в цикле
поле переменной неизвестного типамолчитничем, типа из текста не видно

Обёртка работает так: фрагмент кладётся внутрь Если Ложь Тогда ... КонецЕсли и отдаётся Выполнить. Платформа компилирует его целиком, а ветка никогда не исполняется.

Код =
"Если Ложь Тогда
|	Спр = Справочники.ВыдуманныйСправочник;
|	Имя = ОбщегоНазначения.НесуществующийМетод(1);
|КонецЕсли;";
Выполнить(Код); // исключения не будет

Почему компилятор пропускает половину

Если посмотреть на правую половину таблицы, видно общее правило. Компилятор разбирает имя слева до первой точки: глобальная функция, общий модуль, менеджер Справочники. Всё, что идёт после точки, он оставляет на время выполнения. Модуль ОбщегоНазначения есть в каждой конфигурации на БСП, поэтому левая часть выдуманного вызова проверку проходит, а правую никто не смотрит.

Отсюда и способ лечения: вторую половину имени надо проверять отдельно, своим средством для каждого вида объекта.

Справочники, документы, реквизиты: хватает метаданных

С объектами метаданных просто, их состав платформа отдаёт целиком. Набросок проверки для справочника и его реквизита:

// Есть ли справочник и реквизит у него. Стандартные реквизиты
// (Код, Наименование, Родитель) лежат в отдельной коллекции.
Функция ЕстьРеквизитСправочника(ИмяСправочника, ИмяРеквизита)

	ОбъектМД = Метаданные.Справочники.Найти(ИмяСправочника);
	Если ОбъектМД = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;

	Если ОбъектМД.Реквизиты.Найти(ИмяРеквизита) <> Неопределено Тогда
		Возврат Истина;
	КонецЕсли;

	Для Каждого Станд Из ОбъектМД.СтандартныеРеквизиты Цикл
		Если Станд.Имя = ИмяРеквизита Тогда
			Возврат Истина;
		КонецЕсли;
	КонецЦикла;

	Возврат Ложь;

КонецФункции

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

Метод общего модуля: спросить платформу, не входя в тело

Тут метаданные не помогают. Модуль в Метаданные.ОбщиеМодули найдётся, а перечня его экспортных методов там нет, и прочитать текст модуля из пользовательского сеанса нельзя. Вызвать метод по-честному тоже нельзя, он что-то сделает.

Выручает порядок, в котором платформа обрабатывает вызов. Сначала она сравнивает число переданных аргументов с объявлением и только потом входит в метод. Сто аргументов не принимает ни один обычный метод, поэтому ответов бывает два:

  • “Слишком много фактических параметров” значит, что метод в модуле есть, а тело не запускалось;
  • “Метод объекта не обнаружен” значит, что метода нет.
// Есть ли экспортный метод в общем модуле. Тело метода не выполняется:
// при ста аргументах платформа отказывает до входа в него.
// Истина - метод есть, Ложь - выдуман, Неопределено - проверить не удалось.
Функция ЕстьМетодОбщегоМодуля(ИмяМодуля, ИмяМетода) Экспорт

	Если Метаданные.ОбщиеМодули.Найти(ИмяМодуля) = Неопределено Тогда
		Возврат Ложь; // модуля нет вовсе
	КонецЕсли;

	Аргументы = Новый Массив;
	Для Н = 1 По 100 Цикл
		Аргументы.Добавить(Формат(Н, "ЧГ=0"));
	КонецЦикла;

	Попытка
		Выполнить(ИмяМодуля + "." + ИмяМетода + "(" + СтрСоединить(Аргументы, ",") + ");");
	Исключение
		Текст = НРег(ОписаниеОшибки());
		Если СтрНайти(Текст, "слишком много фактических параметров") > 0
			Или СтрНайти(Текст, "too many actual parameters") > 0 Тогда
			Возврат Истина;
		ИначеЕсли СтрНайти(Текст, "метод объекта не обнаружен") > 0
			Или СтрНайти(Текст, "object method not found") > 0 Тогда
			Возврат Ложь;
		КонецЕсли;
		Возврат Неопределено; // другая ошибка: модуль недоступен в этом контексте и т.п.
	КонецПопытки;

	// Сюда дойдёт только метод, у которого сто параметров и больше:
	// он выполнился по-настоящему.
	Возврат Истина;

КонецФункции

На УТ 11.5 и платформе 8.3.27 функция отдаёт Ложь для ПолучитьЗначениеРеквизитаОбъекта и Истину для ЗначениеРеквизитаОбъекта. То, что тело метода при этом не запускается, мы проверили прогоном.

Где у приёма края:

  • проверяется только существование метода, число и порядок параметров остаются за кадром;
  • метод со ста параметрами и больше выполнился бы на самом деле, в типовых таких нет;
  • звать функцию надо в том контексте, где модуль доступен: клиентский модуль на сервере даст “Переменная не определена”, и ответ будет Неопределено;
  • Выполнить исполнит всё, что подставлено в ИмяМетода, поэтому туда должно попадать имя, разобранное из текста, а не произвольная строка.

Методы менеджеров и объектов проверяются тем же вызовом. Для объекта нужен экземпляр, его можно создать в памяти через СоздатьЭлемент() и не записывать. Так на Справочники.Контрагенты.НайтиПоИНН в типовой УТ 11.5 получается ответ, что такого метода нет ни у платформы, ни в модуле менеджера. А если метода нет и в общем модуле, имеет смысл поискать его в соседних модулях и в вариантах имени: без приставки “Получить”, с “Объектов” вместо “Объекта”. Так рядом с выдуманным именем появляются два настоящих.

Запрос: собрать все ошибки за один проход

У запросов обратная ситуация. Неверное поле платформа замечает и без выполнения: Новый Запрос(Текст).НайтиПараметры() компилирует текст и бросает исключение с позицией. Неудобство в том, что исключение одно на компиляцию.

Пример с нашего стенда, задание “остатки по складам”, промпт без описания метаданных:

ВЫБРАТЬ
	ОстаткиТоваровНаСкладах.Склад КАК Склад,
	КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ОстаткиТоваровНаСкладах.Номенклатура) КАК КоличествоПозиций,
	СУММА(ОстаткиТоваровНаСкладах.КоличествоОстаток) КАК ВНаличии
ИЗ
	РегистрНакопления.ТоварыНаСкладах.Остатки(&КонецПериода, ) КАК ОстаткиТоваровНаСкладах
ГДЕ
	ОстаткиТоваровНаСкладах.КоличествоОстаток <> 0
СГРУППИРОВАТЬ ПО
	ОстаткиТоваровНаСкладах.Склад

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

{(8, 26)}: Поле не найдено "ОстаткиТоваровНаСкладах.КоличествоОстаток"

Сами по себе такие ошибки безопасны, их видно сразу. Раздражает другое: каждая следующая всплывает только после исправления предыдущей, и на длинном запросе выходит несколько кругов “отправил модели, получил, проверил”. Настоящего имени поля платформа не подскажет ни на одном круге.

Круги можно прогнать программно. Нашли ошибку, заменили проблемное место заглушкой, скомпилировали снова. Поле заменяется на NULL, выдуманная таблица на ближайшую настоящую, ЗНАЧЕНИЕ(...) тоже на NULL. Скелет цикла:

Для Проход = 1 По 40 Цикл
	Попытка
		Запрос = Новый Запрос(СтрСоединить(Строки, Символы.ПС));
		Запрос.НайтиПараметры(); // компиляция без выполнения
		Прервать; // ошибок больше нет
	Исключение
		Ош = РазобратьОшибку(ОписаниеОшибки()); // строка, колонка, имя
	КонецПопытки;
	Ошибки.Добавить(Ош);
	Если Ош.Вид = "Синтаксис" Тогда
		Прервать; // дальше платформа текст не читает
	КонецЕсли;
	// ошибочное поле подменяем на NULL и компилируем снова
	Строки[Ош.Строка - 1] = ЗаменитьВСтроке(Строки[Ош.Строка - 1], Ош.Колонка, Ош.Имя, "NULL");
КонецЦикла;

Подсказку с настоящими именами даёт СхемаЗапроса: у каждого источника по его псевдониму есть список доступных полей, в том числе полей виртуальных таблиц с суффиксами. Для КоличествоОстаток из этого списка выходят ВНаличииОстаток и КОтгрузкеОстаток.

На синтаксической ошибке цикл обрывается, потому что дальше неё компилятор текст не разбирает. Одну такую ошибку стоит знать в лицо, потому что ответ платформы её не объясняет:

ВЫБРАТЬ ПЕРВЫЕ 10
	В.Код,
	В.Наименование,
	В.НаименованиеПолное
ИЗ
	Справочник.Валюты КАК В

Платформа пишет “Ожидается имя” и указывает на В в последней строке. Причина в том, что В занято языком запросов (В (...), В ИЕРАРХИИ) и псевдонимом быть не может. Таблицу по первой букве называют машинально и люди, и модели.

Чего так не найти

  • Поля переменной, тип которой не виден из текста. Выборка.Поле, параметр процедуры, результат своей функции: вывода типов нет. Тип определяется только там, где он очевиден из кода, например после СоздатьЭлемент(), НайтиПоКоду(), ТЧ.Добавить() или в Для Каждого Стр Из Объект.Товары.
  • Запроса с настоящими именами и неверным смыслом. Он выполнится и вернёт правдоподобное число. Его ловит только сверка результата с эталоном, это отдельная методика, она разобрана в статье про проверку запроса 1С от нейросети.
  • Окружения вставки. Код, вырезанный из модуля, ссылается на переменные модуля и соседние процедуры. Это предупреждения, а не ошибки, и в счёт ложных срабатываний ниже они не входят.

Самый дешёвый способ сократить число выдуманных имён ещё до проверки - дать модели структуру базы в промпте. Как её выгрузить и сколько её влезает, разобрано в статье про метаданные для нейросети. Если правка касается формы, у неё свои ловушки: имена обработчиков и видимость полей из файлов формы не угадать, об этом отдельный разбор.

На чём проверяли

УТ 11.5.22.67, платформа 8.3.27. Набор из 28 кейсов: 19 с одной ошибкой (7 запросов и 12 фрагментов кода) и 9 без ошибок. Все 28 разобраны верно.

Ложные срабатывания мерили на коде самой типовой: он компилируется и работает, значит, любая найденная в нём ошибка ложная. Взяли три случайные выборки по 60 процедур. Первая дала 10 ложных ошибок, вторая 3, после исправлений все три выборки прошли чисто, 60 из 60. Третью выборку сняли уже после всех исправлений, на настройке она не использовалась.

Готовая обработка

Все приёмы выше вместе со сверкой имён по метаданным собраны в обработку проверки кода и запросов нейросети. В неё вставляется текст из чата, по кнопке выходит таблица: строка, что не так и как это называется в вашей базе. Список ошибок одной кнопкой превращается в текст для обратной вставки в чат. Запрос можно прогнать на 10 строк, а кнопка “Пример с ошибками” соберёт демонстрационный запрос и код из метаданных вашей же базы. В базу обработка не пишет и к нейросети не обращается.

Для ошибок смысла, когда запрос выполнился и вернул не те строки, нужен другой инструмент: стенд проверки запросов нейросети с тридцатью эталонами к УТ 11.5.

Bunu sizin əvəzinizə həll edə bilərəm

Для каждого нового вопроса руководителя приходится собирать отдельную выгрузку и объяснять цифры вручную. Вопросы о продажах и запасах на понятном языке с проверяемыми расчётами. Сначала разбираемся в показателях и качестве исходных данных.

Qiyməti
450 000 - 600 000 ₸анализ задачи и погружение; на выходе отчёт и оценка дальнейших работ, внедрение отдельно

Yazmaq tezdir? Özünüz ölçün

Проверка кода и запросов нейросети: выдуманные имена и как они называются в вашей базе 1С

Emalı aç

INFOSTART TECH EVENT 2026: конференция для 1с-специалистов. если собираетесь, регистрируйтесь по нашей ссылке. Регистрация →

Bunu da oxuyun

Как учится нейросеть, объяснённое кодом 1С: потеря, градиент и шаг на модели, обученной прямо на сервере

Обучение нейросети обычно объясняют формулами. Здесь оно разложено на процедуры модуля 1С: что такое вес, потеря, градиент, шаг AdamW и скорость обучения, с куском кода и числом из настоящего прогона на каждый термин. Модель на 21 920 параметров выучила сорок фраз за 2,96 часа счёта на встроенном языке, а второй прогон на заголовках наших статей занял 3,2 часа. Плюс рецепт, который сократил работу в 349 раз, проверка производных без чужих библиотек и граница, где встроенный язык заканчивается.

Как дать нейросети доступ к 1С, чтобы она видела только разрешённое пользователю

Коннектор нейросети к 1С обычно работает под одной учёткой с полными правами, и роли с ограничениями на уровне записей для модели пропадают. Разбираем, как это проверить у себя, какие пять приёмов прав не возвращают и как отправить запрос модели в сеанс спросившего. Код, замер на демо-базе УТ 11.5 и требования к шлюзу.

Ошибка подключения MCP к базе 1С: справочник кодов ответа HTTP-сервиса

Нейросеть не видит базу 1С, а индикатор подключения зелёный. Почти всегда виновата веб-публикация, и она сама говорит об этом кодом ответа. Таблица кодов от 401 до 502 с местом поломки, командами проверки и скриптом на Node, который проходит все ступени по очереди.