Контекст AnimaGeo для генерации стилей с помощью AI¶
Используйте этот документ как стабильный контекст для языковой модели, которая
должна создавать JSON-файлы стилей AnimaGeo по запросу на естественном языке.
Он написан для моделей, не знакомых с кодовой базой. Машиночитаемая схема
лежит рядом: docs/ai_style_json_schema.json.
Задача для модели¶
Дано:
- Запрос на стиль на естественном языке.
- Этот файл контекста.
- При желании — компактная сводка конструкции.
Вернуть:
- Корректный объект JSON-стиля AnimaGeo.
- При необходимости — код на Python DSL AnimaGeo, но только когда запрос
требует явной стилизации именованных элементов или процедурной логики,
которой не место в общем файле стиля. Этот код должен быть самостоятельным
файлом
.pyна DSL, загружаемым черезscene.loadCode(path)послеscene.loadGGB(...); это не должен быть код внутри наследникаAnimaGeoScene, и он не должен вызыватьscene.element(...). - Короткие заметки о принятых допущениях, о том, что осталось за рамками запроса, и о том, как применять стиль.
Когда пользователь просит «только JSON», верните только объект JSON-стиля без Markdown. В остальных случаях используйте такую форму ответа:
STYLE_JSON:
```json
{ ... }
```
PYTHON_DSL:
```python
# опустите эту секцию, если она не нужна; если она есть — это ровно
# содержимое файла .py, передаваемого в scene.loadCode(...), а не управление сценой
...
```
NOTES:
- ...
Не выдумывайте новые ключи стиля. Используйте только канонические ключи из этого документа и JSON Schema. Не вставляйте комментарии внутрь JSON.
Контракт секции NOTES¶
NOTES — это не пересказ каждого ключа стиля. В них фиксируются решения,
допущения, риски и ограничения, которые могут понадобиться вызывающей стороне
для последующих правок. Держите каждую заметку короткой и конкретной. Где
уместно, указывайте имена элементов, вычисленные значения и выбранный слой.
Добавляйте NOTES всякий раз, когда происходит что-то из перечисленного:
- Запрос неоднозначен. Укажите принятую трактовку — например, какая именно окружность, треугольник, угол или группа подписей имелась в виду.
- Цель выбрана из
construction_summary. Скажите, что выбрано и на каком основании, например «выбран отрезокaкак самый длинный видимый отрезок, длина 5.98». - Элемент конструкции может визуально накладываться на другой. В частности, если выделяемый отрезок одновременно является стороной многоугольника, упомяните, что контур многоугольника дублирует отрезок и что порядок слоёв имеет значение.
- Возвращается код Python DSL. Объясните, почему одного JSON-стиля не хватило,
например: «маркеров углов треугольника не существовало, поэтому DSL создаёт
их через
Angle(...)». - Python DSL сознательно не использован для вычислимого запроса, потому что
предоставленной сводки хватило. Объясните, что результат сведён к именованным
элементам и реализован через
overlay.per_name. - Пользователь просит что-то за пределами генерации стиля. Скажите, что
управление сценой, анимация, рендер и код экспорта не генерируются; можно
вернуть только JSON-стиль и, при необходимости, DSL, совместимый с
loadCode. - Формулировки на естественном языке требуют численной или цветовой трактовки: «слегка», «тонкий», «крупный», «школьный стиль», «акцент», «светлая палитра» и подобные. Укажите выбранные значения или палитру.
- Применяются относительные изменения. Укажите исходное и целевое значения,
например
font_size.main: 8.67 -> 5.78. - Стилизация GeoGebra сохраняется, игнорируется или выборочно перебивается. Скажите, какие свойства переопределены, а какие остались из слоя импорта.
- Меняется видимость. Назовите точные затронутые имена или типы — особенно когда скрываются подписи или объекты.
- Включаются или настраиваются блоки автоматики, такие как
overlay.angle_radiusилиoverlay.label_placement. - Есть несколько допустимых стратегий, и выбор влияет на дальнейшие правки. Назовите выбранную стратегию и осмысленную альтернативу.
- Требуемый выбор невозможно сделать надёжно, потому что
construction_summaryне предоставлена или потому что цель отсутствует, скрыта либо описана недостаточно.
Не используйте NOTES, чтобы замаскировать некорректный результат. Если
запрошенный эффект нельзя выразить ни JSON-стилем, ни DSL, совместимым с
loadCode, — скажите об этом в NOTES и оставьте неподдерживаемую часть
неприменённой.
Основная модель¶
AnimaGeo сначала загружает пакетный builtin.json, а затем накладывает
пользовательский JSON-стиль глубоким слиянием. Поэтому сгенерированный
JSON-стиль может быть коротким. В нём должны быть значения, важные для запроса,
а не копия всех встроенных умолчаний.
Действующий стиль отрисованного элемента определяется по приоритету:
elem.style
→ overlay.per_name
→ overlay.per_type
→ elem.ggb_style
→ defaults.<type>
→ внутренний стиль геометрии
→ запасное значение рендерера
Что это значит:
elem.style— явный код на Python или DSL, он всегда важнее остальных.overlay.per_nameнацелен на один именованный элемент и важнее правил по типу.overlay.per_typeнацелен на все элементы типа и важнее визуального импорта из GeoGebra.elem.ggb_style— нормализованный визуальный стиль, импортированный из GeoGebra.- Если
import.enabledравноfalse, resolver полностью пропускаетelem.ggb_style. Геометрия, имена, зависимости иelem.ggb_rawостаются доступными. defaults.<type>— базовые значения, которые используются, когда ключ не задан ни на одном вышестоящем слое.- Внутренний стиль геометрии — низкоуровневый стиль, уже сохранённый на элементе помощниками геометрии или парсера, но не помеченный как явная запись пользователя.
visible— особый случай: сначала побеждает явный стиль из DSL или API, затем видимость времени выполнения из Show/Hide/addAllGeometry (она важнее слоёв стиля), а импортированная видимость конструкции живёт отдельно отelem.ggb_style.
Короткое правило:
presets = переиспользуемые токены
defaults = базовые значения по типам элементов
import = как читать и адаптировать визуальные значения GeoGebra
overlay = стилизация проекта после импорта
reference = метаданные эталонного холста
rendering = флаги сцены, экспорта и рендера, а не стилизация объектов
elem.style / Python DSL = явные локальные правки
Секции верхнего уровня JSON-стиля¶
Разрешённые ключи верхнего уровня:
name: необязательная строка.version: необязательное число или строка.presets: переиспользуемые семантические константы.defaults: базовый стиль по типам.reference: необязательные метаданные эталонного холста.overlay: переопределения поверх импорта и автоматика.rendering: флаги рендера уровня сцены.import: правила импорта и адаптации визуального стиля GeoGebra.
Избегайте произвольных полей с метаданными. При загрузке во время выполнения неизвестные ключи верхнего уровня вызывают предупреждение и игнорируются, но соответствующая JSON Schema их отвергает.
Единицы¶
Все визуальные значения, оканчивающиеся на _px, заданы в пиксельных единицах
стиля. Сюда входят:
- диаметр точки:
size_px - толщина линии и дуги:
stroke_width_px - радиус дуги угла:
arc_size_px - сдвиг между несколькими дугами угла:
arc_shift_px - размер маркера прямого угла:
right_angle_size_px - размеры засечек:
tick_length_px,tick_width_px,tick_shift_px,tick_radius_px - размеры наконечника стрелки:
arrow_length_px,arrow_width_px - смещения подписей:
label_offset_px,label_radial_offset_px - размер шрифта подписи:
font_size_px
Значения непрозрачности — числа от 0 до 1. Цвета — строки hex вида
#rrggbb. Ссылки на пресеты — строки вроде color.main.
Если пользователь просит сделать размер точки ровно вдвое больше толщины
линии, помните, что size_px — это диаметр точки. Задайте
point_size.main = 2 * line_width.main, если только из запроса явно не следует
другой локальный смысл.
Имена типов элементов¶
Используйте эти имена типов в defaults и overlay.per_type:
pointsegmentlinerayvectoranglepolygoncirclearccirclesectorconicfunctionimplicitcurve
decoration встречается во встроенных стилях как общий помощник для пресетов
засечек, но отрисовываемым типом элемента не является.
Канонические ключи стиля¶
Видимость и подписи (для всех типов)¶
visible: bool; отрисовывается ли объект. Изменения видимости во время выполнения могут перебить слои стиля.label_visible: bool.label_text: строка TeX, часто"$A$"или"$\\alpha$".label_mode:label,valueилиlabel_value; определяет, что именно отрисовывается — подпись, вычисленное значение илиlabel = value.label_value_precision: целое число знаков после запятой для вычисленных значений.label_value_strip_zeros: bool.label_angle_unit:degreeилиradian.label_value_separator: строка, обычно" = ".label_color: hex или ссылка на пресет.label_anchor: одно изTL,TC,TR,ML,MC,MR,BL,BC,BR. Подпись из GeoGebra без явногоlabel_anchorсохраняет размещение GeoGebra для типа своего элемента; заданныйlabel_anchorпереключает её на общее размещение.label_offset_px:[dx, dy].label_radial_offset_px: радиальное смещение для подписей углов.label_placement_locked: bool; запрещает автоматическому размещению двигать подпись.label_hint_px:[dx, dy], ось y вверх; где должен быть центр подписи относительно опорной точки элемента (точка, середина отрезка, вершина угла). Мягкая просьба: авторазмещение сохраняет подсказанную сторону и по-прежнему обходит наложения. Удобнее, чемlabel_offset_px+label_placement_locked, когда известна только сторона.font_size_px: размер шрифта подписи.
Обводка¶
stroke: hex или ссылка на пресет.stroke_width_px: толщина линии, кривой, дуги.stroke_opacity:0..1.stroke_dash_ratio:nullили число от0до1; не-nullозначает пунктир (доля штриха в периоде).stroke_dash_period_px: штрих + промежуток в px (по умолчаниюrendering.dash_period_px, 10).0.65при10даёт штрих 6.5 px и промежуток 3.5 px.stroke_linecap:butt,roundилиsquare.right_angle_joint:auto,bevel,miterилиround.
Заливка¶
fill: hex или ссылка на пресет.fill_opacity:0..1.
Точки¶
size_px: диаметр точки.point_shape:circle,square,diamond,triangle_up,triangle_down,triangle_left,triangle_right,crossилиplus.
Углы¶
angle_range:minorилиreflex.arc_size_px: базовый радиус дуги угла.arc_shift_px: радиальный сдвиг между концентрическими дугами угла приtick_count > 1.right_angle_size_px: размер квадратного маркера.right_angle_marker: bool; принудительно включает квадратный маркер. Не задавайте это глобально вoverlay.per_type.angleтолько потому, что пользователь просит изменить размер маркера прямого угла; для размера естьright_angle_size_px, а определение прямого угла оставьте автоматическим, если только пользователь явно не просит превратить все или названные углы в маркеры прямого угла.auto_radius: bool; приfalseэлемент выходит из-подoverlay.angle_radius.tick_count: для углов означает число концентрических дуг.
Засечки отрезков и векторов¶
tick_count: число меток равенства.tick_style:lineилиwave.tick_length_px: длина засечки.tick_width_px: толщина обводки засечки.tick_shift_px: расстояние между несколькими засечками.tick_radius_px: радиус скругления дляtick_style = "wave".
Наконечники векторов¶
arrow_length_pxarrow_width_px
Слои¶
z_index: основной слой объекта.z_index_fill: слой заливки дляcirclesector.
За что отвечают секции¶
presets¶
Используйте для переиспользуемых токенов: именованных цветов, размеров точек,
толщин линий, радиусов углов, размеров шрифта, пресетов засечек и стрелок. Сами
по себе пресеты ничего не делают. На них должны ссылаться defaults,
overlay, rendering или import.
Предпочитайте семантические ссылки на пресеты дублированию литеральных цветов
и размеров в JSON-стиле. Встроенный стиль уже определяет распространённые
семантические токены: color.main, color.accent, color.aux,
color.strong, line_width.main, line_width.bold, line_width.aux,
point_size.main, point_size.bold, point_size.aux и соответствующие токены
font_size. Используйте эти роли, чтобы конструкция сохраняла смысловое
назначение, а пользователь мог поменять саму палитру или масштаб в одном месте.
Рекомендуемые смыслы:
main: обычная геометрия, линии по умолчанию;strong: основные объекты из условия задачи, когда на плотном чертеже им нужно оставаться заметными;aux: вспомогательные и второстепенные объекты построения;accent: искомый результат, фокусный элемент, точка внимания.
Типичные группы:
{
"presets": {
"color": {
"main": "#000000",
"accent": "#d05456",
"aux": "#808080",
"strong": "#000000",
"angle_fill": "#eeeeee",
"background": "#ffffff"
},
"point_size": { "main": 6, "bold": 9, "aux": 4 },
"line_width": { "main": 1.5, "bold": 2.5, "aux": 0.75 },
"angle_radius": { "main": 20, "shift": 3, "right": 17 },
"font_size": { "main": 14, "bold": 16, "aux": 12 },
"tick": {
"main": {
"tick_length_px": 9,
"tick_width_px": 1.5,
"tick_shift_px": 2
}
},
"arrow": {
"main": {
"arrow_length_px": 11,
"arrow_width_px": 7.5
}
}
}
}
defaults¶
Используйте для базового стиля по типам. Это удобно, когда пользователь хочет
стилевую тему для сцен, созданных в Python или DSL, либо запасные значения на
случай, когда импорт GeoGebra отключён. defaults имеет более низкий
приоритет, чем импортированный стиль GeoGebra, поэтому надёжно перебить
визуальные решения из .ggb через него не получится.
Используйте defaults для:
- «По умолчанию точки — чёрные кружки».
- «Базовая толщина линии — 1.5 px».
- «У углов радиус по умолчанию 20 px, если GeoGebra его не задаёт».
Не используйте defaults, когда пользователь говорит, что импортированные
значения GeoGebra нужно перебить. Для этого есть overlay.per_type.
overlay.per_type¶
Используйте для правил уровня проекта, которые применяются после импорта ко всем элементам типа. Это лучший слой для запросов вроде:
- «Сделать все точки одного размера и чёрными».
- «Сделать у всех прямых, отрезков, лучей и окружностей одинаковую толщину».
- «Задать дугам углов отдельную толщину».
- «Сделать заливку всех углов одного цвета».
- «Использовать один размер шрифта для всех подписей».
- «Сделать метки равенства на отрезках одного размера».
Поскольку overlay.per_type стоит выше elem.ggb_style, он перебивает
визуальные решения, импортированные из GeoGebra, и действует также на
элементы, созданные в DSL.
overlay.per_name¶
Используйте только для именованных исключений, которые входят в запрошенный переиспользуемый стиль или опираются на предоставленную сводку конструкции.
Хорошие примеры:
- «Сделать точку A красной».
- «Скрыть подписи у xAxis и yAxis».
- «Сделать у угла alpha двойную дугу».
- «Поставить на отрезке AB две метки равенства».
Если сводки конструкции нет, не выдумывайте имена элементов. Предлагаемые
правила для именованных элементов кладите в секцию Python DSL AnimaGeo только
как закомментированные заготовки — или используйте overlay.per_type, если
правило действительно глобальное.
overlay.angle_radius¶
Используйте для автоматического масштабирования радиусов углов. Это не прямой ключ визуального стиля, а блок автоматики:
"overlay": {
"angle_radius": {
"enabled": true,
"exp": 0.3,
"min_px": 14,
"max_arm_fraction": 0.55,
"apply_to_right": false
}
}
Применяйте, когда в запросе сказано, что дуги углов должны оставаться
читаемыми и на маленьких, и на больших углах. Для конкретного угла, который
должен сохранить фиксированный радиус, используйте auto_radius: false.
Если пользователь просит автоматическое согласование или подбор размера углов
и при этом просит, чтобы один названный маркер угла был чуть крупнее другого,
оставьте overlay.angle_radius.enabled = true и добавьте небольшое
переопределение overlay.per_name.<angle>.arc_size_px для этого угла. Не
отключайте слой автоматики углов, если пользователь явно не просит вручную
зафиксировать размеры.
overlay.label_placement¶
Используйте для автоматической раскладки подписей. Её можно включить и для статических сцен:
"overlay": {
"label_placement": {
"enabled": true,
"distance_px": 6,
"padding_px": 2,
"angle_gap_arc_px": 3,
"angle_gap_sides_px": 3
}
}
Для анимаций используйте:
keyframe_snapshots: true— раскладка подписей для анимации по ключевым кадрам; работает только вместе сenabled: true.dynamic_angles: true— только вместе со снимками ключевых кадров или явным динамическим авторазмещением в Python.canonicalize_anchor: true— только когда важна плавная интерполяция подписей.
reference¶
Используйте для эталонного холста, под который настраивался стиль. Это метаданные в JSON-стиле, и во время выполнения их можно переопределить:
Допустимые значения reference.source — manual, source_view и ggb_view.
Сам прямоугольник источника, размещаемый на этом эталонном холсте, задаётся
параметром content во время выполнения, а не полем JSON-стиля. Физический
размер вывода — это параметр export времени выполнения:
scene.loadGGB(
"scene.ggb",
style="style.json",
content={"source": "rendered_bounds", "padding": 12},
export={"size": {"width": 1600, "height": 1200}},
)
Используйте reference, когда пользователь просит переиспользуемый стиль,
откалиброванный под известный размер холста. Не кладите итоговые размеры SVG
или MP4 в JSON-стиль; физический вывод описывается блоком export времени
выполнения.
Параметры content времени выполнения (не ключи JSON-стиля)¶
Начиная с версии библиотеки 1.6.2 блок content времени выполнения принимает
ещё три параметра масштабирования декораций. Это параметры API времени
выполнения, как и content.source; никогда не выводите их внутри JSON-стиля.
Если запрос требует такого поведения, упомяните в NOTES, что это параметр
content времени выполнения:
content.prominence: число, по умолчанию1.0(ограничено диапазоном0.01..100). Единый множитель размера декораций, применяемый во время рендера. Раскладка, кадрирование и размещение подписей вычисляются при номинальном значении (1.0) и не затрагиваются; prominence масштабирует только ту плотность, относительно которой определяются размеры декораций (точки, обводки, шрифты подписей, маркеры).content.decoration_scale_source:frame(по умолчанию),reference,outputилиggb. Определяет, относительно какой плотности вычисляются декорации:frameследует за фактическим кадром экспорта (на этом построенfitView);referenceпересчитывает плотностьrendered_boundsот эталона стиля по всему исходному виду, поэтому заметность декораций не зависит от выбранного кадрирования;outputпривязывает размер декораций к масштабу экспорта геометрии, поэтому пиксельный размер декораций фиксирован и задаётся только через prominence;ggbмасштабирует декорации равномерно с холстом вывода, как аплет GeoGebra (decoration_px = authored_px × (output_width / ggb_view_width) × prominence).content.label_bounds:reserve(по умолчанию) илиexclude. Приcontent.source = "rendered_bounds"значениеexcludeкадрирует только по геометрии, игнорируя вынесенные наружу подписи;reserveне даёт подписям у края обрезаться.
Все три параметра включаются явно; умолчания библиотеки не изменились.
rendering¶
Используйте для поведения сцены и экспорта, а не для стилизации объектов:
background: фон сцены.line_cap: окончание линий по умолчанию.dash_period_px: период пунктира по умолчанию в px (штрих + промежуток),10.right_angle_joint: стиль соединения по умолчанию для маркеров прямого угла.polygon_boundary_layer:"top", чтобы рисовать стороны многоугольника поверх заливок; иначеnull.points_display:auto,only_labelsилиonly_points.label_anchor: якорь подписи по умолчанию.label_value_precision: точность числовых подписей по умолчанию на уровне сцены.fast_value_labels:true(по умолчанию); анимированные подписи со значением не компилируют LaTeX на каждом кадре.label_contrast:off(по умолчанию) илиauto(перекрашивать подписи на заливках близкой яркости);label_contrast_threshold: разница яркости,0.35.color_interpolation:oklab(по умолчанию) илиsrgb, для анимации цветов.
Не кладите в rendering размеры точек, толщины обводок, цвета заливок,
размеры шрифта и параметры засечек. Не кладите туда angle_radius и
label_placement: эти блоки автоматики живут в overlay.
import¶
Используйте только для визуальной адаптации, специфичной для GeoGebra. На элементы, созданные в DSL, эта секция не влияет.
Используйте import.colors, import.point_size, import.line_width или
import.policy, когда запрос о том, как переводить сырые значения GGB:
- «Переназначить синий GeoGebra на фирменный синий».
- «Квантовать импортированные толщины линий в 1, 2 или 4».
- «Умножить импортированные размеры точек на 1.5».
- «Игнорировать всю визуальную стилизацию GeoGebra и использовать умолчания стиля».
Отключить визуальный импорт:
Если import.enabled равно false, геометрия и elem.ggb_raw остаются
доступными, но импортированные цвета, размеры и подписи не становятся базой
для рендера.
Выбирайте стратегию импорта осознанно:
- Сохранить стиль GeoGebra: оставьте
import.enabledнезаданным илиtrueи добавьте только те ключиoverlay, которые пользователь просил изменить. Не перестилизовывайте посторонние ключи. - Адаптировать стиль GeoGebra: оставьте слой импорта включённым и используйте
import.colors,import.point_size,import.line_widthили отдельные поляimport.policy, чтобы преобразовать сырые визуальные значения GGB до overlay. - Заменить стиль GeoGebra: задайте
import.enabled=false, опишите нужную базу вdefaultsи используйтеoverlayтолько для правил уровня проекта и именованных исключений. Это лучше, чем копировать в overlay каждое поле, пришедшее из GeoGebra, лишь бы его нейтрализовать.
import.policy поддерживает литеральные значения и строки мини-DSL:
"const:3""scale:1.5""quantize:[1,2,4]""remap:{'#1565c0':'#0066cc'}""match_element""auto"
Поля политики:
size_pxstroke_width_pxarc_size_pxlabel_offset_pxlabel_colorlabel_visiblevisiblelabel_textlabel_modelabel_value_precisionlabel_value_strip_zeroslabel_angle_unitlabel_value_separatorangle_rangetick_countfont_size_pxstrokefillfill_opacitypoint_shapestroke_opacitystroke_dash_ratiostroke_dash_period_pxstroke_linecap
Как выбрать правильный слой¶
Пользуйтесь таблицей решений:
| Запрос пользователя | Куда класть |
|---|---|
| «Все импортированные точки чёрные и одного размера» | overlay.per_type.point |
| «Все подписи 14 px» | overlay.per_type для каждого подходящего типа — или defaults, если перебивать GGB не требуется |
| «Унифицировать подписи точек» | Задавайте стиль подписей только в overlay.per_type.point; не включайте принудительно подписи у прямых, углов и прочих типов, если они не названы явно |
| «У всех линий одинаковая толщина» | overlay.per_type для линейных типов |
| «У всех линий одинаковая толщина и без прозрачности, остальное из GeoGebra» | Задавайте только stroke_width_px и stroke_opacity; не задавайте stroke, если пользователь явно не просил изменить цвет линий |
| «У дуг углов своя толщина» | overlay.per_type.angle.stroke_width_px |
| «Заливка углов — бледно-жёлтая» | overlay.per_type.angle.fill и fill_opacity |
| «Углы без линий, только заливка» | overlay.per_type.angle.stroke_width_px = 0, stroke_opacity = 0, fill_opacity = 1; не меняйте цвет fill, если пользователь не назвал цвет заливки для углов |
«r_shift между дугами угла равен 3» |
overlay.per_type.angle.arc_shift_px |
| «Маркер прямого угла вдвое крупнее» | overlay.per_type.angle.right_angle_size_px; не выставляйте right_angle_marker=true глобально |
| «У меток на отрезках одинаковая длина, толщина и шаг» | Поля засечек в overlay.per_type.segment |
| «У отрезка AB две засечки» | overlay.per_name.AB.tick_count, если AB существует; иначе — Python DSL AnimaGeo |
| «Переназначить цвета GeoGebra» | import.colors или import.policy.stroke/fill |
| «Игнорировать стилизацию GeoGebra» | import.enabled=false плюс defaults с нужной базой |
| «Чтобы подписи не наезжали друг на друга» | overlay.label_placement |
| «Сделать дуги очень острых углов читаемыми» | overlay.angle_radius |
| «Сдвинуть подпись A на [10, -4]» | overlay.per_name.A.label_offset_px, если A существует; иначе — Python DSL AnimaGeo |
Запросы, которые не сводятся к чистому стилю¶
Когда пользователь говорит «остальное пусть будет из GeoGebra», считайте
защищённым слоем импорта GGB каждое неупомянутое визуальное свойство.
Например, «одинаковая толщина линий и без прозрачности» меняет
stroke_width_px и stroke_opacity, но не должно менять цвет stroke. Чтобы
задать stroke у линий, нужна отдельная фраза вроде «сделать линии чёрными».
Прилагательные цвета относятся только к тому классу объектов, который они
определяют. Например, «коричневые точки» означает, что fill и stroke точек
могут стать коричневыми; это не значит, что коричневыми должны стать заливки
углов, заливки многоугольников или обводки линий.
Точно так же запросы про подписи, привязанные к классу объектов, относятся
только к этому классу. «Подписи точек» — это overlay.per_type.point.label_*,
а не подписи всех типов элементов.
Не задавайте label_visible, если в запросе речь только об унификации,
перестилизации или изменении размера подписей. Задавайте label_visible
только тогда, когда пользователь явно просит показать или скрыть подписи.
Когда пользователь просит скрыть подписи у конкретных названных точек,
используйте overlay.per_name.<name>.label_visible = false только для этих
имён. Не скрывайте подписи у всего типа point.
Если сводка конструкции предоставлена и пользователь просит выделить один
существующий объект — например, «окружность», — предпочитайте
overlay.per_name для видимого именованного объекта. Используйте
overlay.per_type.circle только тогда, когда запрос явно про все окружности.
Некоторые запросы не стоит решать одним лишь переиспользуемым JSON-стилем:
- Изменения геометрии: добавить, удалить или сдвинуть точки, изменить построение, создать новые отрезки, вычислить пересечения.
- Выбор, зависящий от содержимого, который нельзя выразить через тип или известное имя: «покрасить самый длинный отрезок», «отметить только равные стороны», «выделить наибольший угол», «покрасить все точки внутри окружности».
- Динамическая процедурная логика: стиль по условию, зависящий от измерений или других данных, доступных только во время загрузки.
- Тонкая ручная расстановка подписей для неизвестных имён элементов.
Если в construction_summary достаточно информации, чтобы детерминированно
определить имена целевых элементов, предпочитайте overlay.per_name в
JSON-стиле, а не Python DSL. Например, если в сводке есть длины отрезков, а в
запросе сказано «выделить самый длинный отрезок», выберите самый длинный
видимый отрезок из сводки и стилизуйте его по имени. Используйте Python DSL
только тогда, когда выбор нельзя разрешить по предоставленной сводке или когда
пользователь хочет, чтобы правило пересчитывалось при загрузке другой
конструкции.
Если пользователь просит выделить углы многоугольника или треугольника, а в
сводке есть вершины многоугольника, но нет готовых элементов-углов для этих
вершин, — верните DSL, который создаёт недостающие маркеры углов через
Angle(...) и стилизует эти новые элементы DSL. Не переиспользуйте посторонние
существующие объекты-углы только потому, что они названы греческими буквами.
Когда выделяется отрезок, который одновременно является стороной
импортированного многоугольника, контур многоугольника может дублировать эту
сторону. Поднимите выделенный отрезок над обычной штриховой геометрией с
z_index больше уровня обводки — например, 6, — или уберите контур
многоугольника, если границу должны задавать отдельные стороны. Не используйте
крошечные значения z-index вроде 0.4 для выделенных обводок: они окажутся
ниже обычных слоёв обводки. Добавьте запись в NOTES об этом наложении, как
предписано контрактом секции NOTES.
Для запросов, которым действительно нужна процедурная логика, верните обычный JSON-стиль плюс код на Python DSL AnimaGeo.
Секция PYTHON_DSL должна содержать только содержимое файла DSL. В неё не
должно попадать окружающее управление сценой. Никогда не генерируйте внутри
PYTHON_DSL ни AnimaGeoScene, ни construct, ни play, ни wait, ни код
анимаций Manim, ни вызовы рендера и экспорта, ни loadGGB, ни loadCode.
Веб-сервис или пользователь применит его так:
scene.loadGGB(
"scene.ggb",
style="style.json",
export={"size": {"width": 800, "height": 600}},
)
scene.loadCode("ai_post_style.py")
Пример содержимого ai_post_style.py:
# Это Python DSL AnimaGeo. Файл выполняется через scene.loadCode(...)
# уже после загрузки конструкции. Имена вроде A, AB, CD должны существовать
# в текущей Construction — обычно из loadGGB или более раннего DSL.
for el in [AB, CD]:
el.style.tick_count = 2
el.style.tick_length_px = 10
A.style.fill = "#d05456"
A.style.stroke = "#d05456"
A.style.label_color = "#d05456"
Разрешённые формы стилизации в DSL:
A.style.stroke = "#ff0000"
A.style["stroke_width_px"] = 2
style(A, B, C, fill="#000000", size_px=6)
hide(A, B)
show(C)
Не генерируйте:
def restyle(scene): ...
scene.element("A").style["fill"] = "#ff0000"
class MyScene(AnimaGeoScene): ...
Присваивания elem.style, сделанные из DSL, считаются явными и имеют высший
приоритет. Генерируйте прямые ссылки только на те имена, которые есть в
компактной сводке конструкции. Если имя неизвестно, упомяните это в NOTES или
выдайте закомментированную заготовку вместо исполняемого кода.
Формат компактной сводки конструкции¶
Не отправляйте языковой модели сырой XML из .ggb. Используйте экспортер
библиотеки, описанный в docs/construction_summary.md, когда запрос ссылается
на реальные имена, типы, импортированные стили или геометрию:
Рекомендуемый формат:
{
"schema": "animageo-construction-summary/v1",
"source": {
"kind": "ggb",
"name": "scene.ggb"
},
"viewport": {
"size": [800, 600],
"reference_size": [800, 600],
"ptUnit": 50,
"ptUnit_style": 50,
"ptUnit_ggb": 50,
"ptXZero": 400,
"ptYZero": 300,
"contentScale": 1,
"fontSize": 16
},
"stats": {
"point": 4,
"segment": 3,
"angle": 1
},
"elements": [
{
"name": "A",
"type": "point",
"visible": true,
"label_visible": true,
"geometry": {
"coords": [0, 0]
},
"ggb_style": {
"size_px": 10,
"fill": "#1565c0",
"stroke": "#000000",
"label_color": "#1565c0"
}
},
{
"name": "AB",
"type": "segment",
"visible": true,
"label_visible": false,
"construction": {
"command": "Segment",
"inputs": ["A", "B"],
"outputs": ["AB"]
},
"geometry": {
"endpoints": [[0, 0], [4, 0]],
"length": 4
},
"ggb_style": {
"stroke": "#1565c0",
"stroke_width_px": 2.5
}
},
{
"name": "alpha",
"type": "angle",
"visible": true,
"label_visible": true,
"construction": {
"command": "Angle",
"inputs": ["B", "A", "C"],
"outputs": ["alpha"]
},
"geometry": {
"vertex": [0, 0],
"side1": [1, 0],
"side2": [0.5, 0.866],
"size_rad": 1.0472,
"size_deg": 60.0,
"start_angle": 0.0,
"end_angle": 1.0472
},
"ggb_style": {
"arc_size_px": 30,
"stroke_width_px": 2,
"fill": "#000000",
"fill_opacity": 0.1
}
}
],
"groups": {
"points": ["A", "B", "C"],
"segments": ["AB", "BC", "CA"],
"angles": ["alpha"]
},
"warnings": []
}
Держите сводку компактной:
- Включайте все имена, типы, видимость и видимость подписей.
- Включайте только ту геометрию, которая полезна для решений о стиле.
- Включайте импортированный или разрешённый визуальный стиль только по тем ключам, которые относятся к задаче.
- Включайте имена зависимостей в
construction.inputsиconstruction.outputsдля отрезков, векторов, углов и многоугольников, когда они известны. - Включайте неподдерживаемые команды и предупреждения парсера, если они влияют на стилизацию.
- Опускайте сырой XML, огромные выборки точек кривых и избыточные умолчания.
Для больших конструкций ограничивайте объём стилевых данных и давайте списки типов и имён плюс сводную статистику. Если запрос нацелен на подмножество, подробно описывайте только эти элементы, а остальные — числом.
Рекомендуемое наполнение промпта¶
Надёжный запрос к API должен включать:
- Запрос пользователя на естественном языке.
- Этот файл контекста.
- JSON Schema или ссылку либо путь к ней.
- Контракт вывода:
- вернуть только корректный JSON, либо
- вернуть
STYLE_JSON, при необходимостиPYTHON_DSL, иNOTES. - Целевой сценарий:
- только импорт из GeoGebra,
- только сцены на Python и DSL,
- и то, и другое.
- Нужно ли сохранять, переназначать или перебивать импортированные визуальные стили GGB.
- При желании — компактную сводку конструкции.
- При желании — существующий фирменный JSON-стиль, который нужно править или расширить.
- Ограничения:
- цветовая палитра,
- точные размеры,
- печать или экран,
- фон,
- должны ли подписи быть видимы,
- анимация или статическая сцена.
- Разрешены ли правки именованных элементов в
overlay.per_nameили их следует вернуть как Python DSL AnimaGeo дляloadCode. - При желании — требования к раскладке времени выполнения, отдельно от
JSON-стиля:
- эталонный холст
referenceдля масштаба разработки, - источник и вписывание
content, - физический размер
export.
- эталонный холст
Проверочный список для модели¶
Прежде чем вернуть ответ, убедитесь:
- В JSON нет комментариев и висящих запятых.
- Ключи верхнего уровня допустимы.
- Каждая ссылка на пресет вида
<group>.<name>существует вpresets. - Имена типов — канонические, в нижнем регистре.
- Ключи стиля — канонические, с единицами
_pxтам, где это требуется. - Нет удалённых секций верхнего уровня (
style,technic,ggb_export,palette) и нет удалённых визуальных ключей вродеline_width,font_size,ang_rdefault,label_r_offset,strich_len. - Не генерируются удалённые ключи вроде
rendering.scale_exportиoverlay.label_placement.angle_gap_px. - Используется
font_size_px, в том числе внутриimport.policy; не генерируйтеimport.policy.font_size. overlay.per_typeиспользуется для глобальной стилизации после импорта.defaultsне используется, когда в запросе явно сказано перебить импортированные значения GGB.import.policyиспользуется только для адаптации сырых значений GGB.- Непрозрачности лежат в диапазоне
0..1. - Цвета — строки hex.
NOTESсодержат каждое обязательное решение, допущение, риск, ограничение области и выбор на основе сводки конструкции, как описано в контракте секцииNOTES.- В строках TeX для
label_textодиночная обратная косая черта TeX экранирована ровно один раз в JSON — например,"$\\alpha$"в файле JSON. Не экранируйте дважды как"$\\\\alpha$": в LaTeX это превратится в\\alphaи сломается. - Чтобы приблизить автоматические подписи углов к маркеру угла, уменьшайте
overlay.label_placement.angle_gap_arc_pxиangle_gap_sides_px. Положительныйlabel_radial_offset_pxнаоборот отодвигает подпись угла наружу, поэтому не используйте положительное радиальное смещение, чтобы выполнить просьбу «ближе к углу». - Если запросу нужна процедурная логика или работа с неизвестными именами,
выдавайте Python DSL AnimaGeo, загружаемый через
scene.loadCode(...), а не выдавайте это за общий стиль.
Полный пример¶
Запрос:
Импортировать конструкцию GeoGebra. Сделать все точки чёрными кружками одного размера, все линейные объекты — одной толщины, дуги углов тоньше, заливку углов светло-серой, все подписи 14 px, сдвиг дуг угла 3 px, а метки на отрезках — единообразными.
Хороший JSON-стиль:
{
"name": "uniform_black_geometry",
"version": 1,
"presets": {
"color": {
"main": "#000000",
"background": "#ffffff",
"angle_fill": "#eeeeee"
},
"point_size": {
"main": 6
},
"line_width": {
"main": 1.5,
"angle": 1
},
"angle_radius": {
"main": 20,
"shift": 3,
"right": 17
},
"font_size": {
"main": 14
},
"tick": {
"main": {
"tick_style": "line",
"tick_length_px": 9,
"tick_width_px": 1.5,
"tick_shift_px": 2
}
}
},
"overlay": {
"per_type": {
"point": {
"size_px": "point_size.main",
"point_shape": "circle",
"fill": "color.main",
"stroke": "color.main",
"stroke_width_px": 0,
"fill_opacity": 1,
"label_color": "color.main",
"font_size_px": "font_size.main"
},
"line": {
"stroke": "color.main",
"stroke_width_px": "line_width.main",
"label_color": "color.main",
"font_size_px": "font_size.main"
},
"segment": {
"$include": "tick.main",
"stroke": "color.main",
"stroke_width_px": "line_width.main",
"label_color": "color.main",
"font_size_px": "font_size.main"
},
"ray": {
"stroke": "color.main",
"stroke_width_px": "line_width.main",
"label_color": "color.main",
"font_size_px": "font_size.main"
},
"circle": {
"stroke": "color.main",
"stroke_width_px": "line_width.main",
"label_color": "color.main",
"font_size_px": "font_size.main"
},
"arc": {
"stroke": "color.main",
"stroke_width_px": "line_width.main",
"label_color": "color.main",
"font_size_px": "font_size.main"
},
"conic": {
"stroke": "color.main",
"stroke_width_px": "line_width.main",
"label_color": "color.main",
"font_size_px": "font_size.main"
},
"function": {
"stroke": "color.main",
"stroke_width_px": "line_width.main",
"label_color": "color.main",
"font_size_px": "font_size.main"
},
"implicitcurve": {
"stroke": "color.main",
"stroke_width_px": "line_width.main",
"label_color": "color.main",
"font_size_px": "font_size.main"
},
"polygon": {
"stroke": "color.main",
"stroke_width_px": "line_width.main",
"fill": "color.background",
"fill_opacity": 0,
"label_color": "color.main",
"font_size_px": "font_size.main"
},
"angle": {
"arc_size_px": "angle_radius.main",
"arc_shift_px": "angle_radius.shift",
"right_angle_size_px": "angle_radius.right",
"stroke": "color.main",
"stroke_width_px": "line_width.angle",
"fill": "color.angle_fill",
"fill_opacity": 1,
"label_color": "color.main",
"font_size_px": "font_size.main"
}
}
},
"rendering": {
"background": "color.background",
"line_cap": "round",
"right_angle_joint": "miter",
"points_display": "auto",
"label_anchor": "BC"
}
}
Текущая поддержка и пробелы¶
Версия библиотеки, по которой сверялся этот контекст: 1.7.0.
Уже доступно:
- Публичный экспортер сводки конструкции:
scene.exportStylePromptSummary(filepath=None, **kwargs). - Низкоуровневые помощники экспортера:
construction_to_ai_summary(...)иwrite_ai_summary(...). - Машиночитаемая схема стиля:
docs/ai_style_json_schema.json. - Валидация стиля во время выполнения через
StyleConfig.load(...)иStyleConfig.from_dict(...).