
OpenMAIC 模拟组件生成提示词模板解析从 user.md 到可交互仿真 Widget 的完整生成规范【免费下载链接】OpenMAICOpen Multi-Agent Interactive Classroom — Get an immersive, multi-agent learning experience in just one click项目地址: https://gitcode.com/GitHub_Trending/op/OpenMAIC导读本文深入解析 OpenMAICOpen Multi-Agent Interactive Classroom中交互式模拟组件simulation widget的核心生成规范以 packages/openmaic/generation/templates/simulation-content/user.md 为主体骨架并结合配套的 system.md 与底层生成管线源码完整还原一条从学科概念到可运行 HTML 模拟器的提示词工程实践。读完本文你将掌握该模板的占位符体系、强制功能清单、移动端布局与按钮状态机约束、postMessage 双端通信协议以及如何在 OpenMAIC 的生成管线中驱动这套模板产出合格的交互式模拟组件。在 OpenMAIC 的教学场景中模拟组件是一键生成沉浸式多智能体课堂的核心呈现形态之一学生可以在一个自包含的 HTML 页面内通过滑块调节物理、化学、生物等学科参数观察模拟结果的实时变化。整个生成过程由成对的提示词模板system.md系统提示 user.md用户提示驱动本文所分析的user.md正是这条链路上约束功能完整性与交互质量的关键一环。一、模板在生成管线中的定位user.md 与 system.md 的协作关系在 OpenMAIC 的生成包 packages/openmaic/generation 中每一类内容slide、quiz、simulation、diagram、code、game、visualization3d 等都拥有成对模板system.md承载模型角色的系统约束输出结构、协议代码、质量检查清单user.md承载每次生成时随任务动态注入的用户侧指令。simulation-content/user.md的结构清晰体现了这种分工Create a simulation widget for: {{conceptName}} ## Concept Overview {{conceptOverview}} ## Key Points {{keyPoints}} ## Variables to Expose {{variables}} ## Design Idea {{designIdea}} ## Language {{languageDirective}}前六行是任务参数区通过{{双花括号}}占位符接收上游传入的动态变量从---分隔线之后开始则是对每次生成都恒定生效的强制性功能要求Mandatory Features涵盖结构、移动端响应式、按钮逻辑、Canvas、交互性、视觉打磨六个维度。这种参数区 恒定约束区的模板结构让一次提示词调用既能保持输出的一致性又能针对不同学科概念灵活切换主题。二、占位符变量如何被注入loader 与 scene-generator 的调用链模板中的{{conceptName}}、{{keyPoints}}等占位符并非静态文本而是由生成管线在运行时填充。整条调用链如下提示词加载器 src/prompts/loader.ts 提供loadPrompt与buildPrompt两个核心函数loadPrompt(simulation-content)会读取templates/simulation-content/目录下的system.md与user.mdinterpolateVariables则通过/\{\{(\w)\}\}/g正则将变量逐个替换进模板。注意其实现细节\w只匹配 camelCase / snake_case 命名kebab-case 占位符会被有意保留不动这是模板作者需要遵守的命名约束assets.test.ts 中专门测试了这一约定。场景生成器 src/scene-generator.ts 中的generateWidgetContent根据 widget 类型分发提示词当widgetType simulation时选择PROMPT_IDS.SIMULATION_CONTENT并按如下映射填充变量模板占位符注入来源说明conceptNamewidgetOutline.concept或outline.title模拟主题名称如 Tablecloth Pull TrickconceptOverviewoutline.description概念概述来自场景大纲的描述字段keyPointsoutline.keyPoints.join(\n)关键知识点列表按行拼接为多行文本variableswidgetOutline.keyVariables.join(, )需要暴露给学生的可调参数名列表designIdea固定为空字符串设计思路当前实现中默认留空languageDirective调用方传入的languageDirective语言指令控制生成内容的语言值得一提的是 src/scene-generator.ts 中的兜底逻辑如果大纲没有显式指定 widgetType系统会将交互式大纲默认回退为 simulation类型这从侧面说明模拟组件是 OpenMAIC 交互式内容中最通用、最基础的形态。三、强制功能结构一个合规模拟组件的四个必备部件模板在Mandatory Features的开头即声明生成的 HTML 必须具备四个结构性要素内嵌 JSON 配置在script typeapplication/json idwidget-config标签中嵌入完整的 widget 配置将变量定义、预设方案、概念元信息与运行时逻辑分离。控制面板为每个暴露的变量提供滑块slider控件学生可以直观地调整参数。Canvas 可视化以canvas或 SVG 作为主体画布承载模拟的图形化表现并要求尺寸自适应。预设按钮提供常见场景的快捷预设一键将参数组合切换到特定演示场景。这四者的配合关系是widget-config里的 JSON 是数据契约控制面板是输入通道Canvas 是输出通道预设按钮是快捷导航。配套的system.md给出了这个 JSON 配置的标准 Schema{ type: simulation, concept: projectile_motion, description: ..., variables: [ { name: angle, label: Launch Angle, min: 0, max: 90, default: 45, unit: ° } ], presets: [ { name: Hit the target, variables: { angle: 30, velocity: 25 } } ] }其中variables数组的每个元素都包含name变量标识必须与 HTML 元素 id 对应、label界面显示名、min/max取值范围、default默认值、unit单位。这个 Schema 同时被 src/scene-types.ts 中的WidgetConfig类型承接——scene-types.ts将模型产出的配置归一化为WidgetConfigBase类型保证后续装配进场景 DSL 时类型安全。四、移动端响应式禁止控制面板与画布重叠模板将移动端响应式列为CRITICAL关键级别约束这是历史实践中最容易翻车的环节。具体硬性要求包括控制面板不得与 Canvas 在移动端发生重叠使用flex-col md:flex-row的弹性布局实现移动端纵向堆叠、桌面端左右并排控制面板高度上限max-h-[40vh] md:max-h-screen超出部分允许滚动画布容器最小高度min-h-[300px]保证在窄屏下依然可见触控友好的控件尺寸最小触摸目标 44px。配套的system.md给出了推荐的移动端安全布局模板并提供了三种可选的移动端布局方案纵向堆叠 / 底部抽屉 / 侧边折叠面板同时明确要求测试 320px、375px、414px、768px 四个典型视口宽度body classflex flex-col min-h-screen md:flex-row !-- Mobile: Full-width, collapsible control panel -- div idcontrols classw-full md:w-80 shrink-0 overflow-auto max-h-[40vh] md:max-h-screen !-- Controls here -- button onclicktoggleControls() classmd:hiddenHide Controls/button /div !-- Canvas area gets remaining space -- div classflex-1 min-h-[300px] relative canvas idcanvas/canvas /div /body此外system.md对触控体验还有更细的要求滑块在移动端应加大滑柄最小 24px、为按钮添加touch-action: manipulation防止双击缩放、在 Canvas 上使用touch-action: none以便自定义手势处理。五、按钮逻辑与状态机启动 / 暂停 / 重新开始的正确语义模板对主按钮行为给出了严格定义这是用户侧模板中内容最密集、也最容易实现出错的部分启动→ 开始运行模拟暂停→ 暂停正在运行的模拟重新开始→ 重置到初始状态然后重新开始。配套的system.md进一步把状态模型落实为{ running, paused, ended }三态并给出错误与正确实现的对照。一个非常典型的 bug 是按钮文字变成了重新开始但点击后却没有真正重置——原因在于重置函数没有把所有状态变量位置、速度、时间等全部归零。正确实现的参考代码如下let state { running: false, ended: false, posX: 50, velocity: 0 }; function handleMainButton() { if (state.ended) { // If simulation ended, reset first resetSimulation(); } else if (state.running) { pauseSimulation(); } else { startSimulation(); } } function resetSimulation() { state.running false; state.ended false; state.posX 50; // Reset to initial position! state.velocity 0; // Reset velocity! updateButton(启动); draw(); } // When simulation hits boundary/ends: function onSimulationEnd() { state.running false; state.ended true; updateButton(重新开始); } function updateButton(text) { document.getElementById(mainBtn).innerText text; }模板特别强调按钮文字必须如实反映点击后将发生的动作——启动/开始对应启动、暂停对应暂停、继续对应恢复、重新开始/重试对应先重置再重新开始。一个按钮不应仅凭文字变化来暗示不同的行为而是必须由清晰的状态机驱动。ended状态必须与running分开跟踪否则容易出现模拟卡死模拟结束但按钮无响应的缺陷。六、postMessage 双端通信协议widget 与宿主课堂的桥接这是system.md中技术要求最高的部分。生成的模拟组件并不是孤立页面而是被嵌入 OpenMAIC 的 iframe 宿主中运行需要通过postMessage与父级课堂环境通信。模板要求 HTML必须包含消息监听器响应四类 widget 动作消息类型行为SET_WIDGET_STATE接收state对象按变量名找到对应滑块/输入框并更新值触发input事件驱动模拟刷新HIGHLIGHT_ELEMENT为目标元素添加紫色脉冲描边3 秒后自动移除ANNOTATE_ELEMENT在目标元素附近弹出教学批注气泡约 4 秒后自动消失REVEAL_ELEMENT显示被隐藏的元素监听器的核心骨架来自system.mdwindow.addEventListener(message, function(event) { const { type, target, state, content } event.data; switch (type) { case SET_WIDGET_STATE: if (state) { Object.entries(state).forEach(([key, value]) { const slider document.getElementById(key -slider) || document.querySelector([data-var key ]); if (slider) { slider.value value; slider.dispatchEvent(new Event(input, { bubbles: true })); } }); } break; case HIGHLIGHT_ELEMENT: // ... 添加脉冲描边3 秒后清除 break; case ANNOTATE_ELEMENT: // ... 创建教师批注 tooltip break; case REVEAL_ELEMENT: // ... 恢复元素显示 break; } });这四类消息与 OpenMAIC 的教师动作Teacher Actions一一对应。在 src/action-parser.ts 中解析器会把 LLM 输出的widget_setState等动作标准化为 Action 对象并且有一个值得注意的防御性处理如果模型遗漏了state字段解析器会默认填充为{}避免以state: undefined的形式发给 iframe 导致监听器解引用崩溃。这在 widget-actions-direct-pipeline.test.ts 中有对应的单测覆盖。从宿主侧看components/scene-renderers/InteractiveIframeHost.tsx 实现了PooledIframe组件iframe 常驻内存以保留文档状态宿主通过postMessagetargetOrigin 为*下发SET_WIDGET_STATE、element-picker:arm等消息。安全上iframe 的 sandbox刻意省略了allow-same-origin使嵌入文档处于唯一的 null origin从而阻断 LLM 生成的 HTML 脚本访问宿主应用的 cookies、localStorage 和 DOM——这是 postMessage 成为唯一父↔iframe 通信通道的根本原因。七、元素命名约定让高亮与批注可寻址为了让HIGHLIGHT_ELEMENT、ANNOTATE_ELEMENT能通过 CSS 选择器精准命中目标模板规定了严格的元素 id 命名规范滑块id{variable_name}-slider如idangle-slider、idvelocity-slider按钮id{action}-btn如idstart-btn、idreset-btn数据显示id{variable_name}-display如idacceleration-display这套约定与SET_WIDGET_STATE中document.getElementById(key -slider)的查找逻辑直接耦合是保证父级下发的状态能命中控件的前提。模板同时要求滑块支持[data-varkey]属性作为备选寻址方式提高实现的容错性。八、可见动画让启动一眼可辨模板将用户点击启动后必须有明显可见的动画列为 CRITICAL 要求并提供了正面与反面示例反面BAD地球只是静态的二维圆只有数字在变化——用户点击启动后什么都看不出在动令人困惑正面GOOD地球可见地旋转、太阳位置移动、昼夜分界线推移——点击启动后画面立刻有反馈令人满足。实现要点是运动物体必须真实发生位置、旋转或形态变化并建议叠加多重视觉线索物体位置/角度变化、时钟/计时器更新、颜色高亮、粒子效果。模板给出了旋转动画的参考写法ctx.rotate(rotationAngle)配合rotationAngle 0.02 * state.speed的增量更新。这一条规则的背后是真实的教学体验教训模拟组件如果看起来没反应无论逻辑多正确在课堂演示中都等于无效。九、Canvas 尺寸、数据展示与 UI 覆盖层避让Canvas 自适应使用ResizeObserver或window resize事件实现自动重排禁止使用固定像素尺寸并要为移动端控制面板的高度预留空间。对象定位避让计算模拟对象位置时必须为顶部 HUD 和底部控制区预留边距避免对象被 UI 覆盖。模板给出了参考实现// GOOD: Reserve space for UI elements const TOP_MARGIN 100; // Space for HUD/stats at top const BOTTOM_MARGIN 200; // Space for controls at bottom const playableHeight canvas.height - TOP_MARGIN - BOTTOM_MARGIN; const objectY baseY - BOTTOM_MARGIN - (value / maxValue) * playableHeight;数据展示实时数值需要清晰可见建议使用等宽字体monospace显示数字、单位保持一致可考虑不遮挡模拟画面的浮动信息面板。十、常见 Bug 对照表模板沉淀的避坑清单system.md末尾整理了一张高频 bug 对照表可以视为模拟组件生成器的经验知识库Bug原因解决方案重置无效按钮调用了错误的函数确保重置函数重置所有状态变量移动端画布重叠使用了固定定位使用 flex/grid 响应式类模拟卡死缺少ended状态将ended与running分开跟踪按钮无响应状态逻辑错误用清晰的状态机定义状态转换触控异常触摸目标过小最小 44px 触摸目标、加大滑块与之并列的还有输出格式硬约束模型必须只返回一个完整的 HTML 文档不包裹 markdown 代码围栏不输出多余解释全文中恰好一个!DOCTYPE html、一个/html禁止重复内容。这些约束直接服务于下游的 HTML 提取逻辑src/scene-generator.ts 中会从模型响应中解析代码块或裸 HTML。十一、收尾的质量检查清单模板要求模型在输出前完成逐项自查这同时也是开发者审查生成结果的验收清单移动端 320px 宽度下控制面板不与画布重叠重置按钮能恢复到精确的初始状态按钮文字与按钮动作正确对应触摸目标不小于 44pxCanvas 能随窗口缩放正确重排状态机清晰running / paused / endedresetSimulation()重置所有状态变量桌面与移动浏览器均可运行无重复 HTML恰好一个!DOCTYPE html模拟对象不被 UI 覆盖层遮挡有可见动画运行时物体明显移动/旋转动画足够明显用户能一眼判断模拟正在运行。十二、如何在本仓库中进一步验证查看完整的系统侧约束与参考代码simulation-content/system.md追踪模板加载与变量注入机制src/prompts/loader.ts、src/prompts/index.ts查看 simulation 分支的变量映射与 HTML 提取src/scene-generator.ts验证 widget 动作解析与 state 兜底src/action-parser.ts、widget-actions-direct-pipeline.test.ts查看 iframe 宿主的 postMessage 通信与沙箱安全策略InteractiveIframeHost.tsx验证模板资产完整性、占位符命名规范与 snippet 引用assets.test.ts结语simulation-content/user.md虽然只是一份数十行的提示词模板但它浓缩了 OpenMAIC 交互式模拟组件生成的完整质量基线从占位符驱动的动态任务注入到移动端布局、按钮状态机、postMessage 通信协议、命名约定、可见动画与避坑清单每一行约束都对应着可被测试用例和宿主代码验证的工程实践。理解这份模板不仅能帮助开发者复现 OpenMAIC 的模拟组件生成能力也为自建 LLM 生成型交互组件的提示词设计提供了可迁移的范式——尤其是清晰的状态机 可寻址的 DOM 约定 双端消息协议这组黄金三角值得在同类系统中借鉴。【免费下载链接】OpenMAICOpen Multi-Agent Interactive Classroom — Get an immersive, multi-agent learning experience in just one click项目地址: https://gitcode.com/GitHub_Trending/op/OpenMAIC创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考