Используйте Kimi K3.1 Pro API для создания агента «из изображения в CAD»
Агент «из изображения в CAD» превращает фотографии детали в редактируемую CAD‑модель.
Почему Kimi K3.1 Pro и CadQuery подходят для задачи
Kimi K3.1 Pro умеет читать четыре изображения, а затем реагировать на результат собственного кода. Упомянутый выше блог Moonshot сообщает 92,7% с инструментами и 72.8% без них в задаче BenchCAD Vision2Code, которая оценивает CAD‑код, написанный по отрендеренным видам детали. Эти числа получены на подмножестве из 1000 случаев при max усилии, а результат с инструментами использовал harness Claude Code, так что часть очков может принадлежать именно обвязке.
В бенчмарке также все четыре вида объединены в одно изображение и каждая деталь перед оценкой масштабируется к одному размеру. В моём случае отправляются четыре отдельных вида плюс один реальный размер при high усилии, поэтому число Moonshot — это скорее повод провести тест, а не его итог. На момент моих прогонах открытые веса ещё нельзя было скачать.
CadQuery выбран как формат вывода, потому что сам скрипт CadQuery — это параметрическая модель. Отверстие — это вызов с диаметром и положением, так что последующее редактирование меняет одно число, и тело перестраивается. STL даёт треугольники, и там нет slot_width, который можно поменять.
Что видит агент и что остаётся скрытым
Kimi получает четыре опорных изображения, ширину 60 мм и системный промпт. В нём фиксируются миллиметры и оси, деталь центрируется по X и Y с нижней гранью на Z=0, а также запрашиваются именованные размеры и финальное твёрдое тело в result.
После этого Kimi знает только то, что сообщают инструменты. Kimi API не запускает CadQuery, поэтому все четыре инструмента живут в приложении:
-
execute_cadзапускает программу в контейнере Docker без сети и сохраняет результат как кандидат -
inspect_cadсообщает валидность, количество тел, габаритный ящик, объём и цилиндрические грани -
render_cadрисует кандидата с тех же четырёх камер, что и эталон -
submit_cadзавершает фазу одним кандидатом
Kimi никогда не видит ни эталонного кода, ни оценки. Оценщик читает сохранённые STEP‑файлы только после завершения работы агента, так что оценка не может направлять или останавливать агента.
Оценки никогда не возвращаются в Kimi. Изображение автора.
Настройка Kimi K3.1 Pro API в Python
Чтобы использовать Kimi K3.1 Pro API в Python, нужны четыре вещи. Я тестировал всё на Linux x86_64 с такими версиями:
-
Ключ API Kimi с пополнением не менее $1, см. квикстарт K3.1 Pro
-
Python 3.12.3 с
openai3.39.0, SDK OpenAI -
cadquery2.8.0 для построения и проверки тел -
Docker 29.9.2 для песочницы
Примеры ниже — выдержки из полного проекта в репозитории GitHub, который вы сейчас клонируете.
Установите CadQuery и соберите песочницу Docker
В руководстве по установке CadQuery предпочитает conda, хотя pip на Python 3.12 тоже работает. Клонируйте репозиторий и настройте окружение:
git clone https://github.com/KhalidAbdelaty/Kimi_K3.1_Pro_API_Tutorial.git
cd Kimi_K3.1_Pro_API_Tutorial
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\Activate.ps1
pip install -r requirements.txt
cp .env.example .env # then add your MOONSHOT_API_KEY
docker build -t cad-sandbox:2.8.0 sandbox/
Образ песочницы устанавливает ту же версию CadQuery и запускается от обычного пользователя. По умолчанию Docker не задаёт лимиты CPU и памяти, см. документацию по ограничениям ресурсов, поэтому раннер выставляет их сам. На главной странице репозитория перечислены команды для запуска и оценки эксперимента, включая путь без ключа API и Docker.
Прежде чем код Kimi попадёт в контейнер, попробуйте сломать его сами. Моя тестовая программа пыталась прочитать ключ API, выйти в сеть и записать вне рабочего каталога — все три попытки были заблокированы.

Три заблокированные операции в песочнице. Изображение автора.
Сделайте первый вызов Kimi K3.1 Pro API
Это обычный SDK OpenAI, направленный на endpoint Moonshot. Устанавливайте reasoning_effort в каждом запросе, иначе по умолчанию будет max, и «думание» нельзя будет отключить.
client = OpenAI(api_key=os.environ["MOONSHOT_API_KEY"], base_url="https://api.moonshot.ai/v1")
response = client.chat.completions.create(
model="kimi-k3.1-pro",
reasoning_effort="high", # low, high, or max; the API default is max
max_completion_tokens=2048, # reasoning and answer share this cap
messages=[{"role": "user", "content": "In one sentence, what does a STEP file store?"}],
)
print(response.choices[0].message.content)
print("usage:", response.usage.model_dump(exclude_none=True))
Не указывайте temperature, top_p, n и оба penalty — в квикстарте они указаны как фиксированные. Даже одно предложение тратит большую часть completion‑токенов на рассуждения, так что выбирайте лимит с учётом этого.

Один запрос подтверждает ключ и модель. Изображение автора.
Если Kimi API для вас новинка, мой предыдущий учебник по Kimi K3 охватывает стриминг, вызов инструментов, кеширование и ввод изображений.
Создайте эталонную CAD‑модель и четыре тестовых вида
Эталонная CAD‑модель — ваш ключ ответа, чтобы каждую оценку с чем‑то точным сравнивать. Я зафиксировал свою до первого запроса — от камер до правил оценки — и ничего не менял после просмотра результатов.
Определите размеры кронштейна
Кронштейн — это «Г», где стойка примыкает к задней кромке основания. Начало координат — в центре нижней грани, ось X по ширине, фронт к −Y, Z вверх:
|
Параметр |
Значение |
Показано Kimi? |
|
Полная ширина (X) |
60 мм |
Да |
|
Глубина основания (Y) |
40 мм |
Нет |
|
Полная высота (Z) |
45 мм |
Нет |
|
Толщина пластин |
6 мм |
Нет |
|
Крепёжные отверстия |
2 × Ø6,5 мм, на расстоянии 34 мм, при Y = −3 мм |
Нет |
|
Паз на стойке |
Ширина 6 мм, длина по концам 20 мм, центр при X = 0, Z = 25,5 мм |
Нет |
Я поместил ряд отверстий и паз по центру их граней и выбрал отверстия 6,5 мм — типичный зазор под М6 — как в реальной детали. Этот выбор стал слабым местом именно этого кронштейна — ниже объясню почему.
Внутри функции сборки w, dep, h и t хранят ширину, глубину, высоту и толщину. Скрипт объединяет две пластины и вырезает элементы:
base = cq.Workplane("XY").box(w, dep, t, centered=(True, True, False))
upright = cq.Workplane("XY").center(0, dep / 2 - t / 2).box(w, t, h, centered=(True, True, False))
holes = cq.Workplane("XY").pushPoints([(-17, -3), (17, -3)]).circle(3.25).extrude(t)
slot = (cq.Workplane("XZ", origin=(0, dep / 2 - t / 2, 0)).center(0, 25.5)
.slot2D(20, 6, 90) # end-to-end length, width, angle
.extrude(t, both=True))
result = base.union(upright).cut(holes).cut(slot)
Скрипт проверяет наличие одного валидного тела ожидаемого размера перед экспортом в STEP.
Отрендерьте четыре вида фиксированными камерами
Небольшой рендерер на NumPy рисует фронтальный, верхний, правый и изометрический виды с одним и тем же кадрированием для эталона и каждого кандидата. При 512 px один пиксель покрывает примерно 0,19 мм, хотя считывание с изображения может ошибаться сильнее. Фиксированный кадр также делает слишком большую или смещённую модель заметно неправильной, а не центрирует её заново.

Четыре изображения, отправленные Kimi. Изображение автора.
Заранее зафиксируйте правила оценки
Оценщик измеряет экспортированное тело, поэтому названия параметров его не обманут. Он сечёт каждый STEP‑файл, чтобы найти отверстия, паз и обе толщины пластин, и вычисляет воксельный IoU — долю общего объёма двух тел — на сетке 0,5 мм в реальном масштабе. Допуски соответствуют пиксельной шкале: ±0,5 мм для толщин, диаметров отверстий и ширины паза и ±1 до ±1,5 мм для длин и положений, считываемых с изображений.
Один IoU недостаточен. Это грубая метрика, но я продолжаю её использовать, потому что ничего проще для сравнения тел нет. Простая «Г» без отверстий и паза даёт свыше 0,96, а корректная деталь, увеличенная на 20%, после приведения к одному размеру получает идеальные 1,0.
Поэтому каждая оценка здесь сопровождается 13 проверками «пройдено/не пройдено». Даже идеальные 1,0 означают совпадение на этой сетке, а не до микрона, и ни одно из чисел не гарантирует пригодность к производству.
Генерируйте код CadQuery из изображений с Kimi K3.1 Pro
Первый кандидат приходит из одного запроса без инструментов и запускается «как есть».
Отправьте четыре опорных вида в Kimi K3.1 Pro API
У визуального ввода Kimi используются data URL в base64 внутри массива content, и публичные URL изображений не принимаются. Системный промпт содержит правила кадра и именования, описанные выше, а пользовательское сообщение несёт четыре PNG и такой текст:
These four images show one mechanical part, a bracket. Each view uses orthographic
projection, and all four use the same scale. The camera for each view is written at the
top of the image, and a small axis triad sits in the lower-left corner.
The overall width of the part along X is 60 mm. No other dimension is given, so estimate
the rest from the images.
Write one CadQuery program that rebuilds this part as an editable parametric model.
Return the complete program in a single python code block.
Сам запрос короткий:
images = [image_part(path) for path in view_paths] # four PNGs as base64 data URLs
messages.append({"role": "user", "content": images + [{"type": "text", "text": BASELINE_PROMPT}]})
response = client.chat.completions.create(
model="kimi-k3.1-pro", reasoning_effort="high",
max_completion_tokens=32_768, messages=messages,
)
Чтобы оценить размер ввода до оплаты, отправьте те же сообщения на эндпоинт оценки токенов — оценка почти в точности совпала со счетом. Четыре изображения по 512 px — менее 2000 входных токенов.
Запустите первую программу CadQuery в песочнице
Раннер пишет код во временную папку и стартует одноразовый контейнер через docker run:
cmd = ["docker", "run", "--rm", "--network", "none", "--read-only",
"--tmpfs", "/tmp:size=64m", "--cap-drop", "ALL",
"--security-opt", "no-new-privileges",
"--memory", "1g", "--cpus", "1", "--pids-limit", "128",
"-v", f"{work}:/work", "cad-sandbox:2.8.0"]
subprocess.run(cmd, capture_output=True, text=True, timeout=60)
В первом прогоне ответ Kimi занял около минуты. Её программа назвала каждую величину из скрытого эталона — от bracket_depth = 40.0 до slot_center_z = 25.5. Получилось валидное тело, прошедшее все проверки.

Та же камера, тот же масштаб, совпадающие детали. Изображение автора.
Идеальный первый заход заставил проверить, не утекли ли данные, но PNG не несут метаданных, а ни в одном промпте нет скрытых значений. Объяснение — в коде Kimi. Как я отметил при определении кронштейна, элементы расположены так, как их бы поставил конструктор, — и Kimi поступила так же.

Kimi выводит положения элементов из середины граней. Изображение автора.
Постройте самопроверяющегося агента с вызовом инструментов на Kimi K3.1 Pro
Агент с вызовом инструментов работает в цикле. Kimi запрашивает инструмент, ваш код его запускает, а результат возвращается как сообщение инструмента до завершения работы Kimi.

Три фазы, каждая с жёсткими лимитами. Изображение автора.
Определите инструменты для запуска, инспекции и рендера CAD
Вот схема execute_cad. Она возвращает короткий результат в фиксированном формате, с последними строками трассировки при сбое:
{"type": "function", "function": {
"name": "execute_cad",
"description": "Run a complete CadQuery program in an isolated sandbox. Returns a "
"candidate id, whether it ran, and a short error if it did not.",
"parameters": {"type": "object", "properties": {
"code": {"type": "string",
"description": "The complete program. It must assign the final solid to result."}},
"required": ["code"]}}}
render_cad возвращает четыре изображения прямо внутри сообщения инструмента — тот же паттерн «посмотри ещё раз», что и в нашем учебнике по агентному зрению с Gemini. В доках Kimi этого примера нет, так что считайте это наблюдаемым поведением. Во всех трёх прогонах сообщение с role: "tool" несло части image_url, и модель их читала.
Сохраняйте полное сообщение помощника в цикле инструментов
Здесь важны три детали, и первые две — из гайда по мыслящим моделям Kimi и квикстарта:
-
На каждом шаге возвращайте полное сообщение ассистента, включая
reasoning_contentиtool_calls -
Добавляйте по одному сообщению инструмента на каждый вызов, с соответствующим
tool_call_id -
Сериализуйте сообщение с помощью
model_dump(), так как в SDK OpenAI нет типизированного поляreasoning_content
Цикл ниже следует всем трём пунктам:
message = response.choices[0].message.model_dump(exclude_none=True)
messages.append(message) # all of it, or the next turn quietly loses its reasoning
for call in message.get("tool_calls") or []:
content = run_tool(call["function"]["name"], json.loads(call["function"]["arguments"]))
messages.append({"role": "tool", "tool_call_id": call["id"], "content": content})
Не рассчитывайте, что API поймает ошибку здесь. Запрос с удалённым reasoning_content из истории всё равно проходит, хотя в доках поле обязательное, и его опускание может изменить продолжение диалога. Я бы предпочёл 400 вместо тихой ошибки.
Бюджет заложен в код цикла, где Kimi не может его изменить. Как только 3 попытки исправления израсходованы, execute_cad отвечает ошибкой, а submit_cad не принимает ничего, кроме одного валидного тела.
Что произошло на фазе исправления
Почти ничего — я едва не выкинул этот раздел по этой причине. Я рассчитывал, что цикл исправлений сделает основную работу, но Kimi едва к нему прикоснулась. Она проверила первого кандидата, отрендерила его, написала уверенное резюме о соответствии всем четырём видам и отправила ту же программу, с которой начала.
Это резюме не всегда было верным. В одном прогоне inspect_cad сообщил радиус отверстия 3,0 мм, то есть Ø6,0 мм против эталонных 6,5 мм, и Kimi всё равно отправила результат. Полмиллиметра — это меньше 3 пикселей на этих видах (своим глазам на таком масштабе я бы тоже не доверял), а в обратной связи нет указания верного диаметра.

Инструмент сообщил радиусы 3,0 мм. Изображение автора.
Редактируйте параметрическую CAD‑модель с Kimi K3.1 Pro
При бездействующем цикле исправлений тест на изменение конструкции оказался более показательным. Это мягкий тест, впрочем: изменение, затрагивающее сразу два элемента, нагрузило бы сильнее.
Попросите Kimi расширить паз
Редактирование продолжается в том же разговоре и стартует с кандидата, отправленного Kimi, а не с моего эталона:
Increase the width of the vertical slot in the upright plate from 6 mm to 9 mm.
Keep the slot's center position and its end-to-end length as they are in your model.
Do not change the mounting holes, the plate thickness, or the outer dimensions.
Kimi использовала одну из трёх разрешённых программ. Разница — в одной строке: slot_width = 6.0 на slot_width = 9.0, затем один шаг на инспекцию и рендер, и отправка.
Проверьте правку по экспортированной геометрии
Новое число в коде не доказывает, что тело изменилось. Оценщик сравнил тела до и после правки по вокселям, игнорируя только область, где паз мог стать шире:
- Паз имеет ширину 9 мм с той же длиной и центром
- Отверстия, толщина пластин и внешние габариты не изменились
- Вне области паза материал не менялся
Все проверки правки проходили каждый раз.
Правка прошла чисто, потому что slot2D() считает длину «от конца до конца», так что паз остался 20 мм, а прямой участок стал короче. Программа, которая хранила бы расстояние между центрами дуг, увеличила бы паз на 3 мм.

Правка изменила только паз. Изображение автора.
Насколько точен CAD‑агент Kimi K3.1 Pro?
Агент прошёл все скрытые проверки во всех трёх прогонах в рамках заранее установленных допусков. Таблица ниже — краткое резюме:
|
Проверка |
Результат за три прогона |
|
Скрытые проверки геометрии пройдены |
13 из 13 каждый раз |
|
Воксельный IoU с эталоном (сетка 0,5 мм) |
0,998–1,0 |
|
Диаметр отверстий (истинное значение 6,5 мм) |
6,5 мм дважды, 6,0 мм один раз — и Kimi пропустила это в своём ревью |
|
Использовано исправлений (разрешено 3) |
0 |
|
Проверки правки пройдены |
8 из 8 каждый раз |
Три прогона — это не процент успешности, лишь признак устойчивости на одном кронштейне. Отверстия 6,0 мм на фазе исправления прошли только потому, что попали ровно в допуск ±0,5 мм по диаметру — более строгий лимит провалил бы тот прогон.
Самокоррекции было нечего исправлять
Тест, который покажет, улучшает ли цикл модель, — это прогон с преднамеренной ошибкой, когда агент стартует с программы с известной неточностью. Его я бы описал отдельно от этих прогонов.
Стоимость токенов и время на прогон
Каждый прогон стоил 6,3–7,3 цента за шесть запросов и семь вызовов инструментов. Это только API‑затраты; рендер и Docker шли на моей машине.
Считайте каждый запрос по полям usage по опубликованным тарифам для kimi-k3.1-pro: за миллион токенов — $2,00 за вход, $10,00 за выход, $0,20 за cache hits и $2,00 за запись кеша на 5 минут.
|
Фаза |
Запросы |
Доля стоимости |
|
Первый запрос |
1 |
Около половины |
|
Ревью исправления |
2 |
Около четверти |
|
Правка |
3 |
Около четверти |
Первый запрос дороже, потому что там Kimi «думает». Выход — более половины счета, записи кеша — 23–35%, а cache hits почти ничего не стоят. Вот как складываются три поля ввода, согласно документации Chat Completions, упомянутой выше; можно пропустить, если ваш трекер уже делит записи кеша:
uncached = u.prompt_tokens - cached - written # the three parts sum to prompt_tokens
cost = (uncached * 2.00 + cached * 0.20 + written * 2.00 + u.completion_tokens * 10.00) / 1e6
Токены рассуждений уже учтены в completion_tokens, не добавляйте их повторно. Запись кеша на 5 минут стоит как не кэшированный ввод, поэтому кеширование промптов окупается только когда префикс читается повторно. Циклы инструментов каждый раз пересылают одну и ту же историю — здесь кеш снизил стоимость ввода до меньше 40% от базовой ставки.
Прогон занимает около трёх минут, в основном ожидание, поскольку клиент разводит запросы на 21 секунду для соблюдения лимита, который разберём в FAQ.
Где у ИИ‑генерации CAD по изображениям есть ограничения
Главное ограничение — изображения не могут нести все размеры. Мой тест добавляет ещё несколько:
- Рендеры не показывают детали меньше пикселя. Если размер важен, укажите его текстом или измерьте инструментом.
- Этот кронштейн легко угадать. Несимметричные отверстия и необычные размеры проверили бы, читает ли Kimi именно пиксели, а не привычки конструкторов.
- Флаги Docker блокируют только то, что перечисляют. Они остановили «балующийся» код из раздела настройки, но модельный код всё ещё может сжечь свою минуту CPU. В нашем гайде по защите ИИ‑агентов в контейнерах описаны следующие уровни.
- Прохождение этих проверок ничего не говорит о прочности. Нагрузки, материал, скруглённый внутренний угол, необходимый реальной детали, посадка болтов и накопление допусков — вне этого теста.
Простота кронштейна — это ограничение моего теста, а не Kimi.
Заключение
Мы построили агента, который пишет параметрический код CadQuery по четырём изображениям, проверяет получившееся тело инструментами и по запросу редактирует один элемент. Для этого кронштейна ответ на стартовый вопрос — «да». Все три прогона прошли с первого запроса в рамках заданных мной допусков, а правка паза не затронула остальную часть детали.
Цикл исправлений — часть, за которую я не поручусь, поскольку Kimi так и не нашла, что исправлять. Её ревью пропустило единственную ошибку в 0,5 мм, потому что видело пиксели, а не истинный диаметр. Я бы не обобщал результат на детали с нетипичными размерами или на фотографии реальных изделий.
Что переносится — это метод: скрыть эталон, заморозить правила оценки до первого запроса и оценивать экспортированное тело, а не код. Kimi трижды заявила о соответствии кандидата, и только оценщик показал, что дважды это было точно, а один раз — близко. Оценщик я бы оставил, а первым расширением сделал бы прогон с преднамеренной ошибкой.
Больше о подключении моделей к вашим собственным инструментам — в нашем курсе Developing AI Systems with the OpenAI API, где разбирается function calling с тем же SDK, что использует этот агент.
FAQs
Какие форматы и размеры изображений можно отправлять в Kimi K3.1 Pro API?
PNG, JPEG, GIF, WebP, BMP, HEIC и HEIF работают как data URL в base64, а SVG отклоняется даже в кодированном виде, поэтому отправляйте XML SVG‑чертежа как текст. В одном запросе можно передать любое число изображений при условии, что тело не превышает 100 МБ, а в руководстве по vision, указанном выше, рекомендуется оставаться в пределах 4096×2160. Я бы избегал анимированных GIF и WebP — Kimi может декодировать их как видео и выставить счёт соответственно.
Может ли 3D Make от Kimi заменить такого CAD‑агента?
Не для параметрической работы, судя по лонч‑блогу. 3D Make живёт в приложении и на сайте Kimi, где вы редактируете модель и скачиваете её для 3D‑печати. В блоге не упомянут доступ по API или экспорт STEP, так что slot_width для изменений всё равно потребует вашего собственного цикла инструментов.
Почему мой агент Kimi K3.1 Pro получает ошибки HTTP 429?
Сначала смотрите error.type, потому что Kimi использует 429 для трёх разных проблем. rate_limit_reached_error означает превышение лимитов по тарифу, которые растут от 3 запросов в минуту при $1 до 200 при $10. exceeded_current_quota_error говорит, что баланс исчерпан, а engine_overloaded_error — что сервера перегружены, так что лучше подождать и повторить, а не пополнять счёт.
Как снизить стоимость CAD‑агента на Kimi K3.1 Pro?
Стандартный кеш на 5 минут уже подходит для этого цикла, поскольку каждый хит продлевает его бесплатно, а мои запросы шли с интервалом 21 секунда. Если человек просматривает рендеры между шагами и паузы могут превышать 5 минут, гайд по кэшированию контекста показывает, как поставить TTL в 1 час, и запись за $4,00 за миллион токенов окупится после двух хитов. Я бы не стал брать Highspeed, если важна цена: он удваивает ставки за 2–3‑кратное ускорение.
Стоит ли использовать high или max reasoning effort для реконструкции CAD?
Начните с high — я использовал его везде. Если попробуете max (я не пробовал на этом кронштейне), стримьте ответ, потому что шлюз выдаёт 504, если нестриминговый запрос молчит 900 секунд. Лимит ответа по умолчанию — 131 072 токена и включает рассуждения, так что мой лимит 32 768 держал любой один ответ дешевле примерно 33 центов по выходу.
Представьте, что у вас есть четыре фотографии металлического монтажного уголка — Г‑образного кронштейна для крепления полки к стене — и нет его CAD‑файла. Инженеры редактируют CAD‑файлы и отправляют их в мастерские, потому что CAD хранит точные размеры. Вы можете сдвинуть отверстие или расширить паз и всё равно получить корректную деталь — с картинкой так не получится.
Нужна короткая программа на Python, которая строит кронштейн из именованных размеров, например
hole_diameter = 6.5, и сохраняет его в STEP — стандартном формате обмена между CAD‑инструментами. В техническом блоге Moonshot говорится, что Kimi K3.1 Pro хорошо справляется с такой пространственной задачей, так что я устроил ей проверку. Сможет ли Kimi K3.1 Pro превратить четыре изображения в редактируемую CAD‑модель, проверить своё решение инструментами и затем изменить один элемент, не ломая остальное?Чтобы всё было честно, я сам построил кронштейн в CadQuery, библиотеке Python для создания CAD‑моделей. Из неё же отрендерил четыре изображения и не показывал Kimi исходный CAD‑файл. В этом учебнике Kimi K3.1 Pro по API Kimi пишет программу по картинкам, а мой код запускает её и замеряет результат.
Опыт работы с CAD не обязателен, но предполагается, что вы уверенно пользуетесь Python и Docker; геометрию я буду пояснять по мере появления. Мы разберём, как:
Наш обзор Kimi K3.1 Pro охватывает запуск, бенчмарки, цены и доступ, поэтому здесь сосредоточимся на агенте.
Коротко
Я трижды просил Kimi K3.1 Pro превратить четыре фото металлического кронштейна в редактируемую 3D‑модель, используя
reasoning_effort="high", и она дала один и тот же результат каждый раз, с одним небольшим исключением: