Использование нейросети для обновления расширений 1С: GPT, Git и анализ эффективности на 33 реальных проектах

24.10.25

Разработка - Рефакторинг и качество кода

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

Архитектура решения

 

 

Схема сопоставления и общий процесс

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

Таблица содержит три стороны:

  • метод конфигурации до обновления;
  • метод расширения конфигурации до обновления;
  • метод конфигурации после обновления.

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

Основные сценарии обновления

  1. Метод не изменён в обновлённой конфигурации: ничего делать не нужно.
  2. Метод удалён в обновлённой конфигурации: сложный случай для автоматизации. Мы удаляем метод из расширения, затем вручную анализируем изменения и переносим доработки, если они всё ещё актуальны.
  3. Метод изменён в обновлённой конфигурации: здесь мы применяем автоматизацию — используем Git и GPT.

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

Алгоритм обработки изменённых методов

  1. Предварительная обработка: очищаем тела методов, синхронизируем параметры и вызовы ПродолжитьВызов.
  2. Трёхстороннее слияние через Git: в большинстве случаев проходит успешно. Ошибки редки и выявляются на этапе проверки конфигурации или тестирования.
  3. Разрешение конфликтов с помощью GPT: в конфликт попадают только действительно спорные места. Иногда одного метода недостаточно для принятия решения, иногда доработку невозможно перенести технически. Поэтому GPT — ассистент, а не замена программиста. При корректной настройке промпта удалось автоматизировать разрешение большинства конфликтов.
     

Использование Git для трёхстороннего слияния

Исходно мы рассматривали несколько инструментов для трёхстороннего слияния, но по итогу остановились на Git:

  • KDiff3 — слишком «мягкий» алгоритм. Может объединить изменения без конфликта, даже если одна сторона удалила блок, а другая его изменила. Кроме того, не поддерживает полноценный консольный режим.
  • GNU Diff3 — не умеет корректно игнорировать пробелы, из-за чего создаёт множество лишних конфликтов.
  • Git — оптимален: строг в конфликтных случаях и гибко настраивается.

В Git мы включили трёхсторонний стиль конфликтов — двух сторон иногда недостаточно: git config merge.conflictstyle diff3.

После появления конфликтов заменяем метки на читаемые с помощью регулярных выражений:

"(?<=^<<<<<<< ).*" -> "THEIRS"
"(?<=^\|\|\|\|\|\|\| ).*" -> "BASE"
"(?<=^>>>>>>> ).*" -> "OURS"

 

Подключение GPT к процессу разрешения конфликтов

Настройка параметров модели

Для автоматического разрешения конфликтов мы экспериментировали с моделями и промптами. Выводы практические, но не универсальные — многое зависит от модели, задачи и промпта.

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

Параметры моделей

Задача требует точности, не творчества. Наилучшие рабочие значения в наших экспериментах:

  • top_p = 0.3 — ограничивает набор вероятных токенов,
  • temperature = 0.1 — регулирует случайность выбора.

Значения ниже приводили к зацикливанию и малой гибкости, выше — к лишней вариативности.
 

Обычные vs Reasoning-модели

Reasoning-модели медленнее и полезны, когда нужен краткий вывод в ответе. Когда у моделей есть возможность расписать решение перед выдачей ответа, обычные модели показали лучший результат.
 

Цельный запрос vs Цепочка запросов

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

Подробный vs Краткий промпт

Избыточная детализация вредна: модель тонет в мелочах. Оптимально — краткий, формализованный промпт с минимальным набором структурированных входных данных. Практические правила для входных данных:

  • Не передавать метод целиком — достаточно конфликтного фрагмента и нескольких строк контекста до/после. Большие куски кода повышают риск галлюцинаций и опечаток.
  • Явно показывать построчные различия (мы использовали SequenceMatcher в Python). Без явного указания отличий модель чаще упускает изменения или находит несуществующие.
     

Промпт и структура данных

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

Ты опытный разработчик 1С. Перед тобой блок кода с git-конфликтами (трёхстороннее слияние). А также список различий, полученных в результате сравнения.

## Стороны конфликта:
BASE - Исходная (базовая) версия конфигурации от 1С до изменений.
THEIRS - Новая версия от вендора (1С) — изменения, которые пришли с обновлением.
OURS - Наши кастомные изменения в конфигурации.

## Основные принципы:
1. **Безопасность прежде всего** - не допускать нерабочий код
2. **Максимальное сохранение изменений** - где возможно объединять
3. **Чёткие приоритеты** - минимум неоднозначностей
4. **Сохранение комментариев** - если комментарий находится в блоке, который остаётся — комментарий тоже должен остаться.
5. **Никаких изменений вне конфликтных маркеров** - все строки, не затронутые конфликтами, должны быть сохранены в исходном виде, включая регистр символов, пунктуацию и пустые строки.

## Правила разрешения конфликтов:
 - Удаления - ВСЕГДА удаляем (имеет высший приоритет). Даже если другая сторона изменила логический блок.
 - Изменения и Добавления - ВСЕГДА сохраняем, если не мешают удаления.

### Особые случаи (в остальных случаях действуй по общим правилам):
1. **Используются инструкции препроцессора #Удаление и #КонецУдаления или #Вставка и #КонецВставки** - значит OURS - это не исходный код конфигурации, а расширение, надстройка над BASE.
   - В этом случае сначала не обращай внимание на OURS, возьми целиком код из THEIRS.
   - Если это #Удаление и #КонецУдаления - то в коде THEIRS вставь только инструкции препроцессора, чтобы в них остался аналогичный логический блок, который мы исходно отмечали.
   - Если это #Вставка и #КонецВставки - то в коде THEIRS вставь целиком с #Вставка до #КонецВставки, который мы исходно добавляли.
   - Если код в блоках #Удаление и #КонецУдаления и #Вставка и #КонецВставки дублирует логику в THIERS, то доработка избыточна - берем THEIRS без инструкций препроцессора.
2. **Конфликт изменений метаданных текущего метода** - имя метода берем из OURS, параметры метода берем из THEIRS, но переносим туда все доработки OURS, если это возможно.

## Алгоритм действий (действуй по шагам для каждого конфликта отдельно):
1. Выпиши подробно, какие логические блоки изменений были в OURS и THEIRS относительно BASE согласно различиям. ВАЖНО! В различиях не указано где удаление и добавление, а где изменение - твоя задача это определить.
   - Сравни OURS и BASE. Выпиши информацию по каждому отличающемуся блоку (Изменения, Удаления, Добавления).
   - Сравни THEIRS и BASE. Выпиши информацию по каждому отличающемуся блоку (Изменения, Удаления, Добавления).
2. Определи в каком порядке должны быть вставлены отличающиеся логические блоки. Если порядок не играет роли - ориентируйся на строки кода до и после конфликта.
3. Рассуди, какой должен получиться результат после разрешения конфликта.

## Примеры
### Удаление + изменение
BASE:   function init() {}
OURS:   (удалили)
THEIRS: function init() { update(); } U94; Игнорируем
RESULT: (нет функции)

### Объединение полей
BASE:   { x: 1 }
OURS:   { x: 1, y: 2 }
THEIRS: { x: 1, z: 3 }
RESULT: { x: 1, y: 2, z: 3 }

### Конфликт изменений
BASE:   timeout: 100 + 100
OURS:   timeout: 100 + 200
THEIRS: timeout: 500 + 100
RESULT: timeout: 500 + 200

# Ответ:
- Выполни подробный анализ КАЖДОГО конфликта (`<<<<<<< THEIERS`, `||||||| BASE` `=======`, `>>>>>>> OURS`) согласно алгоритму действий.
- ВАЖНО! В самом конце предоставь полный блок кода после разрешения конфликтов в блоке ```bsl (```bsl\n``` - для пустого результата).

# Исходные данные:
## Блок кода:
```bsl
{{ code }}```

{% for conflict in conflicts %}
## КОНФЛИКТ {{ loop.index }}
Различия OURS и BASE:
```text
{{ conflict.diff_ours_base }}```
Различия THEIRS и BASE:
```text
{{ conflict.diff_theirs_base }}```

{% endfor %}

Промпт делится на несколько логических частей. Каждая из которых добавлена для конкретной цели:
 

1. Контекст задачи

Короткое вступление («Ты опытный разработчик 1С…») задаёт роль и контекст модели. Это помогает ограничить стиль ответа и направить поведение в нужное русло. Без этого модель склонна к «творчеству» или выдаче комментариев вне кода.
 

2. Описание сторон конфликта (BASE / THEIRS / OURS)

Определяет термины, чтобы модель не путала источники изменений. Это снижает риск логических ошибок при слиянии.
 

3. Принципы и правила разрешения конфликтов

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

4. Особые случаи

Обработка препроцессорных инструкций (#Удаление, #Вставка) и конфликтов в сигнатуре методов. Эти ситуации часто ломают автоматическое слияние, поэтому мы ввели отдельные указания, как действовать.
 

5. Алгоритм действий

Подробный пошаговый план, по которому модель должна работать с каждым конфликтом:

  • выделить различия между версиями,
  • определить тип изменений (удаление, добавление, изменение),
  • составить итоговый результат. Это помогает избежать типичных «догадок» модели и заставляет её рассуждать последовательно.
     

6. Примеры

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

7. Формат вывода

Жёсткое требование выдать результат в виде блока bsl гарантирует в большинстве случаев предсказуемый формат в ответе. Это позволяет парсить результат без дополнительной фильтрации.
 

8. Подстановка данных в шаблон

В шаблоне предусмотрены динамические блоки. Для заполнения шаблона мы использовали шаблонизатор jinja2 в Python, но в 1С можно реализовать аналогичный алгоритм.

•    code — блок кода с конфликтами и несколькими строками контекста.
•    loop.index — порядковый номер конфликта (удобно при логировании).
•    conflict.diff_ours_base — различия между базовой конфигурацией и расширением до обновления.
•    conflict.diff_theirs_base — различия между базовой конфигурацией и обновлённой конфигурацией.

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

Пример работы

Для демонстрации процесса возьмём конкретный метод конфигурации, который изменился в конфигурации после обновления и был заменен в расширении.
 

Конфигурация до обновления (BASE)

Процедура ПодразделениеПриИзменении(Элемент)
	
	ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(Список, "Подразделение", Подразделение,,, ЗначениеЗаполнено(Подразделение));
	ОбновитьСписокСостоянияНаСервере();
	
КонецПроцедуры


Конфигурация после обновления (THEIRS)

Процедура ПодразделениеПриИзменении(Элемент)
	
	ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(Список, "Подразделение", Подразделение,,, ЗначениеЗаполнено(Подразделение));
	ОбновитьСписокСостоянияНаКлиенте();
	
КонецПроцедуры


Расширение конфигурации до обновления (OURS)

Процедура Расширение_ПодразделениеПриИзмененииВместо(Элемент)
	
	ОтборыСписковКлиентСервер.ИзменитьЭлементОтбораСписка(Список, "Подразделение", Подразделение, ЗначениеЗаполнено(Подразделение), ВидСравненияКомпоновкиДанных.ВИерархии);
	ОбновитьСписокСостоянияНаСервере();
	
КонецПроцедуры


Работа Git 

Git получил на вход все три стороны (BASE, THEIRS, OURS) и выполнил стандартное трёхстороннее слияние.

На этом этапе мы получили файл с конфликтами, который не может быть применён напрямую в конфигурацию, но может послужить входными данными для GPT:

Процедура Расширение_ПодразделениеПриИзмененииВместо(Элемент)
	
<<<<<<< THEIRS
	ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(Список, "Подразделение", Подразделение,,, ЗначениеЗаполнено(Подразделение));
	ОбновитьСписокСостоянияНаКлиенте();
||||||| BASE
	ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(Список, "Подразделение", Подразделение,,, ЗначениеЗаполнено(Подразделение));
	ОбновитьСписокСостоянияНаСервере();
=======
	ОтборыСписковКлиентСервер.ИзменитьЭлементОтбораСписка(Список, "Подразделение", Подразделение, ЗначениеЗаполнено(Подразделение), ВидСравненияКомпоновкиДанных.ВИерархии);
	ОбновитьСписокСостоянияНаСервере();
>>>>>>> OURS
	
КонецПроцедуры


Работа GPT 

GPT получили на вход промпт основанный на шаблоне:

//Начало шаблона промпта

# Исходные данные:
## Блок кода:
```bsl
Процедура Расширение_ПодразделениеПриИзмененииВместо(Элемент)
	
<<<<<<< THEIRS
	ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(Список, "Подразделение", Подразделение,,, ЗначениеЗаполнено(Подразделение));
	ОбновитьСписокСостоянияНаКлиенте();
||||||| BASE
	ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(Список, "Подразделение", Подразделение,,, ЗначениеЗаполнено(Подразделение));
	ОбновитьСписокСостоянияНаСервере();
=======
	ОтборыСписковКлиентСервер.ИзменитьЭлементОтбораСписка(Список, "Подразделение", Подразделение, ЗначениеЗаполнено(Подразделение), ВидСравненияКомпоновкиДанных.ВИерархии);
	ОбновитьСписокСостоянияНаСервере();
>>>>>>> OURS
	
КонецПроцедуры```

## КОНФЛИКТ 1
Различия OURS и BASE:
```text
-  	ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(Список, "Подразделение", Подразделение,,, ЗначениеЗаполнено(Подразделение));
+  	ОтборыСписковКлиентСервер.ИзменитьЭлементОтбораСписка(Список, "Подразделение", Подразделение, ЗначениеЗаполнено(Подразделение), ВидСравненияКомпоновкиДанных.ВИерархии);
...

Различия THEIRS и BASE:

...
-  	ОбновитьСписокСостоянияНаСервере();
+  	ОбновитьСписокСостоянияНаКлиенте();

На основе этого промпта GPT выполнила пошаговый анализ каждого конфликта и предложила итоговый вариант кода без конфликтных маркеров:

Анализирую конфликт по шагам:

1. Анализ изменений:
   - OURS vs BASE:
     * Изменение: Заменили вызов `ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка` на `ОтборыСписковКлиентСервер.ИзменитьЭлементОтбораСписка` с изменёнными параметрами
     * Оставили без изменений вызов `ОбновитьСписокСостоянияНаСервере()`
   - THEIRS vs BASE:
     * Изменили вызов `ОбновитьСписокСостоянияНаСервере()` на `ОбновитьСписокСостоянияНаКлиенте()`
     * Оставили без изменений вызов `ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка`

2. Порядок изменений:
   - Оба изменения независимы и могут быть объединены

3. Результат:
   - Сохраняем изменённый вызов установки отбора из OURS
   - Сохраняем изменённый вызов обновления списка из THEIRS

Итоговый код:
```bsl
Процедура Расширение_ПодразделениеПриИзмененииВместо(Элемент)
	
	ОтборыСписковКлиентСервер.ИзменитьЭлементОтбораСписка(Список, "Подразделение", Подразделение, ЗначениеЗаполнено(Подразделение), ВидСравненияКомпоновкиДанных.ВИерархии);
	ОбновитьСписокСостоянияНаКлиенте();
	
КонецПроцедуры

Результат можно получить регулярным выражением из блока bsl в конце ответа модели.


Проверка результата 

Корректность обновления мы проверяем через сравнение результатов Git и GPT. Визуально сверяем различия между слиянием Git и кодом, полученным от GPT. Это позволяет быстро выявить участки, где модель могла допустить ошибки.

 

 

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


Результаты GPT-обновления 1С на реальных проектах

Для оценки эффективности мы взяли несколько крупных проектов обновления.

Статистика общая:

  • Всего методов — 3632.
  • Не требовали обновления — 2447.
  • Удалены — 130.
  • Изменены — 1055.

Статистика изменённых методов:

  • Автоматически обновлены Git — 720.
  • Переданы в GPT — 335.
    • Успешно обновлены — 202 (60%).
    • Ошибка — 133 (40%).

Таким образом, использование GPT позволило сократить количество ручных правок с 335 до 133.

Все результаты GPT проходили сверку, однако в простых случаях сравнение с конфликтами Git занимало считанные минуты.

 

Выводы и рекомендации

  • Git уверенно справляется с большинством изменений, но не избавляет от конфликтов.
  • GPT существенно снижает объём ручной работы при их разрешении — более половины конфликтов удалось обработать автоматически.
  • Полной автономности ждать не стоит: модель не заменяет разработчика, но становится надёжным инструментом, особенно при хорошо выстроенном промпте и чётких правилах обработки.

Вступайте в нашу телеграмм-группу Инфостарт

ИИ GPT нейросети обновление 1С расширения

См. также

Инструментарий разработчика Нейросети Платные (руб)

Первые попытки разработки на 1С с использованием больших языковых моделей (LLM) могут разочаровать. LLMки сильно галлюцинируют, потому что не знают устройства конфигураций 1С, не знают нюансов синтаксиса. Но если дать им подсказки с помощью MCP, то результат получается кардинально лучше. Далее в публикации: MCP для поиска по метаданым 1С, справке синтакс-помошника и проверки синтаксиса.

15250 руб.

25.08.2025    48041    100    27    

112

Разработка Инструментарий разработчика Работа с интерфейсом Адаптация типовых решений Нейросети 1C:Бухгалтерия 1C:ERP 1С:ЗУП 1С:КА 1С:УНФ 1С:УТ 1С:Розница 1С:ДО 1С:ERP Управление предприятием 2 Платные (руб)

Разработка "Дизайнер форм 1С" реализована в виде расширения 1С и является универсальным инструментом для разработки прототипа форм с целью демонстраций, технических заданий и т.д. Без участия разработчика с возможностью экспорта в файл внешней обработки и генерации формы используя искусственный интеллект.

36600 руб.

28.08.2025    7357    2    2    

6

Нейросети 1С 8.3 1С:Управление торговлей 11 Управленческий учет Платные (руб)

Обработка подключения фотокамер Canon и Nikon к Управление торговлей 11.4 для потоковой загрузки фотографий в карточки товаров с автоматическим удалением фона

23180 руб.

24.06.2021    11937    5    7    

16

Нейросети 1С:Предприятие 8 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Управление нашей фирмой 3.0 Платные (руб)

Умный Excel" - ИИ-супердвигатель, который превращает часы работы в минуты! Технологии будущего уже здесь: загрузил Excel "магия ИИ" готовый результат

8540 руб.

02.07.2025    3602    2    0    

6

Нейросети Пользователь 1С:Предприятие 8 1С:Управление нашей фирмой 1.6 1С:Управление торговлей 11 1С:Управление нашей фирмой 3.0 Оптовая торговля, дистрибуция, логистика Россия Управленческий учет Платные (руб)

Расширение "Искусственный интеллект и нейросети в 1С: Работа с отзывами маркетплейсов" предназначено для применения искусственного интеллекта в повседневной деятельности селлеров на маркетплейсах. Среди функций - работа с отзывами, вопросами и чатами покупателей, диалог с нейросетями, генерация картинок, заполнение описаний номенклатуры и другое.

6100 руб.

03.04.2024    14504    7    0    

12

Мастера заполнения Нейросети 1С:Предприятие 8 1C:Бухгалтерия 1С:Управление торговлей 11 Платные (руб)

Расширение для заполнения описания товара (номенклатуры) с помощью модели ИИ ChatGPT с ключевыми словами. Расширение формирует продающее описание товара по его наименованию с помощью модели искусственного интеллекта. Будет полезно для владельцев интернет магазинов, каталогов товаров и продающих через маркетплейсы. Адаптировано для основных конфигураций: УТ, ЕРП, КА, УНФ. Прошло аудит на 1cfresh.com. Версия для автоматического заполнения

5084 руб.

13.03.2023    22579    52    50    

80

Нейросети Программист 1С 8.3 1С 8.5 Бесплатно (free)

ИИ помощник со встроенным MCP сервером, который работает прямо внутри Конфигуратора. Автодополнение кода, ревью, исправление ошибок, доработка методов, документирующие комментарии — всё без переключения из Конфигуратора.

20.03.2026    3977    Sergey_Borisovi4    45    

68

Инструментарий разработчика Нейросети Программист 1С 8.3 Россия Бесплатно (free)

Инструмент для ежедневной работы в Конфигураторе: рефакторинг, поиск методов в конфигурации и исправление ошибок — всё через ИИ. Работает через Qwen CLI, z.ai, Google или локальные модели. Рассказываю, как это устроено.

17.03.2026    14660    hawkmax    148    

80
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. roman72 403 27.10.25 10:29 Сейчас в теме
Явно ошибка когда пишут про использование на 335 проектах, а в тексте цифра 335 - это число правок.
Удивительное совпадение цифр.
5. 1c-izh 106 28.10.25 10:41 Сейчас в теме
(1) спасибо! действительно опечатка — на 33 проектах (чуть позже поправлю, т.к. при редактировании материал снимется с публикации и вновь уйдет на модерацию)
2. so-quest 140 27.10.25 10:36 Сейчас в теме
По факту - вы просто поленились писать свой парсер и решили эту обязанность возложить на нейросеть?
3. dmpas 420 27.10.25 13:25 Сейчас в теме
(2)
вы просто поленились писать свой *** и решили эту обязанность возложить на нейросеть

так в этом и суть, нет? :-)
roman72; 1c-izh; +2 Ответить
6. 1c-izh 106 28.10.25 11:02 Сейчас в теме
(2) Поясним архитектуру нашего подхода: парсер у нас реализован и активно применяется в продукте «1C: Автоматизированное обновление измененных конфигураций», а GPT в данном случае используется как второй этап, который подключается только там, где парсер не справился с разрешением конфликта.

В статье мы привели пример с Git — во-первых, в качестве эксперимента, а во-вторых, чтобы сделать материал максимально полезным и универсальным для сообщества разработчиков.
4. wonderboy 671 28.10.25 09:11 Сейчас в теме
Александр, какую модель использовали?
Светлый ум; +1 Ответить
Для отправки сообщения требуется регистрация/авторизация