news 2026/9/10 11:28:30

OpenMAIC 幻灯片内容生成提示模板(slide-content/user.md)深度解析:从场景信息到可解析 JSON 的完整链路

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OpenMAIC 幻灯片内容生成提示模板(slide-content/user.md)深度解析:从场景信息到可解析 JSON 的完整链路

OpenMAIC 幻灯片内容生成提示模板(slide-content/user.md)深度解析:从场景信息到可解析 JSON 的完整链路

【免费下载链接】OpenMAICOpen Multi-Agent Interactive Classroom — Get an immersive, multi-agent learning experience in just one click项目地址: https://gitcode.com/GitHub_Trending/op/OpenMAIC

导读

本文围绕 OpenMAIC(Open Multi-Agent Interactive Classroom)生成管线中的核心提示资产 packages/@openmaic/generation/templates/slide-content/user.md,完整讲解它如何把"场景信息 + 可用资源 + 输出约束"组装成一次幻灯片内容生成请求,并配合配套的系统提示 system.md 约束模型产出可直接解析的 Canvas/PPT JSON。读完本文,你将掌握该模板的变量体系、条件渲染机制、JSON 输出铁律,以及模型输出如何经由 scene-generator.ts 完成校验、修复与资产映射,最终进入教室幻灯片渲染。


一、模板的定位:生成管线中的"用户侧剧本"

在 OpenMAIC 的生成管线里,一次幻灯片内容生成由系统提示(system.md)用户提示(user.md)共同驱动:system.md 负责刻画"内容设计师"的角色、画布规格、元素类型与设计规则;user.md 则负责把当前这一页的具体任务交付给模型,包括页面标题、描述、要点、可用的媒体资源与输出硬约束。

两者的装配发生在 scene-generator.ts 的generateSlideContent中,核心调用如下:

buildPrompt(PROMPT_IDS.SLIDE_CONTENT, { title, description, keyPoints, ... })

PROMPT_IDS.SLIDE_CONTENT在 src/prompts/index.ts 中被定义为'slide-content',对应templates/slide-content/目录下的 system.md 与 user.md 两个文件。装配完成后,由aiCall(prompts.system, userPrompt, visionImages)将最终提示文本发送给模型。


二、模板结构总览

user.md 按从上到下的顺序组织为四个区段,每一段都在约束模型行为的某一个侧面:

区段内容作用
Scene InformationTitle / Description / Key Points / teacherContext提供本页的"主题事实"
Available Resources可用媒体列表 + 画布尺寸声明可用的"原料"边界
Output Requirements单页 Canvas/PPT 组件的生成目标明确交付物形态
Language Directive + Must Follow语言指令 + 8 条输出铁律约束语言与 JSON 格式

以下各节逐段拆解。


三、场景信息:变量的注入与默认值

user.md 第一段直接使用 Handlebars 风格占位符接收调用方传入的场景数据:

- **Title**: {{title}} - **Description**: {{description}} - **Key Points**: {{keyPoints}} {{teacherContext}}

这些变量在 loader.ts 的interpolateVariables中被替换。值得注意的实现细节是:占位符匹配规则为/\{\{(\w+)\}\}/g——只替换小驼峰或蛇形命名的变量(正则注释明确说明\w+刻意不触碰 kebab-case 占位符),对象类型变量会被JSON.stringify(value, null, 2)序列化,未提供的变量则原样保留、不做插值。

实际传参发生在 scene-generator.ts:

const prompts = buildPrompt(PROMPT_IDS.SLIDE_CONTENT, { title: outline.title, description: outline.description, keyPoints: (outline.keyPoints || []).map((p, i) => `${i + 1}. ${p}`).join('\n'), assignedImages: assignedImagesText, canvas_width: canvasWidth, canvas_height: canvasHeight, teacherContext, languageDirective: languageDirective || '', imageElementEnabled, generatedImageEnabled, generatedVideoEnabled, mediaElementEnabled, });

几个关键点:

  • keyPoints 编号化:大纲中的要点被转成1. …2. …的编号列表,让模型在页面布局时自然形成有条理的条目结构。
  • teacherContext:来自formatTeacherPersonaForPrompt(见 prompt-formatters.ts)。当课堂配置中存在role === 'teacher'的 Agent 时,会注入教师人设文本,并明确禁止把教师姓名/身份写进幻灯片("no 'Teacher X's tips'……"),保证幻灯片是中性、专业的视觉辅助物。
  • 画布尺寸是固定常量canvasWidth = 1000canvasHeight = 562.5,注释说明它需与viewportSize/viewportRatio保持一致。这两个占位符还属于受测试保护的"祖传命名"——assets.test.ts 中的GRANDFATHERED_NON_CAMEL_CASE_PLACEHOLDERS明确锁定slide-content/user.md: {{canvas_height}}{{canvas_width}}是仅有的非标准命名豁免项,防止未来新增不合规占位符。

四、可用资源:媒体边界与画布声明

{{#if mediaElementEnabled}} - **Available Media**: {{assignedImages}} {{/if}} - **Canvas Size**: {{canvas_width}} × {{canvas_height}} px

这里演示了 loader 的条件块机制processConditionalBlocks使用/\{\{#if (\w+)\}\}([\s\S]*?)\{\{\/if\}\}/g正则处理非嵌套条件块:条件为真则保留块内内容,否则整体移除。

mediaElementEnabled的取值逻辑在 scene-generator.ts:

const generatedImageEnabled = generatedImageEntries.length > 0; const generatedVideoEnabled = generatedVideoEntries.length > 0; const imageElementEnabled = hasAssignedImages || generatedImageEnabled; const mediaElementEnabled = imageElementEnabled || generatedVideoEnabled;

也就是说:

  • 当大纲为当前页分配了来自 PDF/素材库的图片assignedImages),或计划生成 AI 图片/视频mediaGenerations)时,mediaElementEnabled为真,模型才能看到可用媒体清单;
  • 没有任何媒体时,该块整体消失,assignedImagesText会被设为'无可用图片,禁止插入任何 image 元素'(同文件 scene-generator.ts),从提示层直接封死模型"幻觉图片"的空间。

assignedImagesText的组装同样在 scene-generator 中完成:视觉模式下图片以占位符形式列出(仅 ID + 页码 + 尺寸 + 宽高比),非视觉模式则给出包含描述文本的完整条目(formatImageDescription),并拼接 AI 生成媒体(gen_img_*/gen_vid_*)的 ID 与提示词描述。


五、输出要求与语言指令

user.md 中段的交付目标与语言指令如下:

Based on the scene information above, generate a complete Canvas/PPT component for one page. ## Language Directive {{languageDirective}}

languageDirective由 prompt-formatters.ts 的buildLanguageText生成,合并课程级语言指令与可选的本场景补充说明。模板里正文文本的语言必须与此指令一致(system.md 中亦有"Text language must match the language specified in generation requirements"的呼应约束)。


六、Must Follow:八条输出铁律与容错

user.md 的核心约束集中在Must Follow区块,原文为 5 条编号 + 若干条件性条目,合并如下:

  1. 直接输出纯 JSON,不带任何解释或描述;
  2. 不得包裹```json代码块
  3. JSON 前后不得附加任何文本
  4. 确保 JSON 格式正确、可直接被解析
  5. 启用图片元素时:src只能使用给定的图片 ID(如img_1);
  6. 启用生成视频时:mediaRef只能使用给定的生成视频媒体引用
  7. 所有 TextElement 的height必须从系统提示中的快速查找表取值

6.1 为什么要求如此苛刻?

因为模板的作者深知:模型不会 100% 遵守指令。为此,仓库在解析侧提供了多层容错——这正是 json-repair.ts 存在的意义。parseJsonResponse的解析顺序为:

  1. 精确解析:直接JSON.parse(trim())
  2. 剥离推理前缀:截掉末尾</think>/</reasoning>之后的内容再解析;
  3. 代码块提取:从```json ... ```中抓取{/[开头的片段;
  4. 正文结构扫描:用括号深度匹配算法在响应文本中定位完整的 JSON 结构;
  5. 整体解析兜底

即便提取出 JSON 片段,tryParseJson仍会依次尝试四类修复:修复被误写成字符串的键值对片段(如"height: 76""height": 76)、双转义 LaTeX 风格的反斜杠(\frac等)、补齐被截断的数组/对象括号、清理控制字符,最后才交给jsonrepair库处理。

6.2 元素级防御:模型输出不可全信

即使 JSON 整体可解析,单个元素仍可能畸形。在 scene-generator.ts 的fixElementDefaults中,每个元素都要经过:

  • stripNulls:递归剔除值为null的字段,让 DSL 规范器将其视为"缺省"而非"类型错误";
  • normalizeElement(来自@openmaic/dsl):补齐缺省字段、由包围盒推导 line 的start/end与 shape 的viewBox/path,遇到类型错误的字段fail loud
  • 规范化失败的单个元素会被丢弃并告警——注释解释得很清楚:"丢掉一个元素只是幻灯片轻微劣化,保留一个畸形元素可能拖垮整个场景"。

图片元素还会在此阶段按assignedImages的真实宽高比修正盒子尺寸(height = width / ratio,超出 462px 上限则反向缩宽)。


七、配套系统提示:元素类型的完整契约

user.md 的输出结构示例给出的是最简形态:

{"background":{"type":"solid","color":"#ffffff"},"elements":[{"id":"title_001","type":"text","left":60,"top":50,"width":880,"height":76,"content":"<p style=\"font-size:32px;\"><strong>Title Content</strong></p>","defaultFontName":"","defaultColor":"#333333"},{"id":"content_001","type":"text","left":60,"top":150,"width":880,"height":130,"content":"<p style=\"font-size:18px;\">• Point One</p><p style=\"font-size:18px;\">• Point Two</p><p style=\"font-size:18px;\">• Point Three</p>","defaultFontName":"","defaultColor":"#333333"}]}

而完整的元素契约由 system.md 定义。user.md 第 5 条铁律要求 TextElement 的height必须查表,指的正是 system.md 中的Text Height Lookup Table(line-height=1.5,含两侧各 10px 内边距):

Font Size1 line2 lines3 lines4 lines5 lines
14px436485106127
16px467094118142
18px4976103130157
20px5282112142172
24px5894130166202
28px64106148190232
32px70118166214262
36px76130184238292

system.md 还定义了shapelinechartlatextable五类元素的完整字段约束,以及八条设计规则(文本宽度计算、对齐验证、对称布局、文字背景配对、装饰线、间距标准、字号层级)。其中几条与 user.md 的输出结构示例直接相关:

  • TextElement 内部有 10px 内边距:实际文本区为(width-20) × (height-20)
  • TextElement 禁止内联 LaTeX\frac\lim\sqrt等会以字面反斜杠字符串显示,数学内容必须独立使用 LatexElement(KaTeX 渲染);
  • LineElement 的width是描边粗细而非长度:建议 2–6px,箭头部大小 =width × 3
  • LatexElement 不得生成path/viewBox/strokeWidth/fixedRatio:这些由系统自动填充,对应的实现正是 scene-generator 中的processLatexElements——它在运行时用 KaTeX 把latex字符串渲染为 HTML 并填入htmlfixedRatio: true,渲染失败的公式会被移除。

八、输出后处理:从 JSON 到真实幻灯片资产

user.md 的 "src 只能用图片 ID" 与 "mediaRef 只能用视频引用" 两条规则,其背后是完整的两阶段资产映射设计(见 scene-generator.ts 的resolveImageIds):

  1. 模型只产出逻辑 ID:图片用img_1img_2(正则^img_\d+$识别),生成媒体用gen_img_*/gen_vid_*占位符(isGeneratedMediaPlaceholder判定);
  2. 管线负责替换为真实来源resolveImageIds将图片 ID 替换为imageMapping[src]中对应的真实 URL/资产 ID;生成媒体若已在generatedMediaMapping中则直接替换,否则保留占位符交由前端渲染骨架屏后异步回填。

映射值的形态完全由调用方的imageMapping决定:浏览器端映射携带 base64 data URL,服务端映射携带资产池分配的 asset id,渲染器再通过池注册表解析。这套"模型只见 ID、管线负责解析"的设计(源码注释称之为 Plan B)大幅降低了提示复杂度,也保证了src字段不会出现幻觉 URL。

最终,所有通过校验的元素会被统一改写为type_<nanoid8>的新 ID 并补上rotate: 0,背景在solid/gradient两种形态间归一化,再与remark一起返回为GeneratedSlideContent,进入后续的动作生成与场景组装阶段。


九、测试保障:模板资产的守护者

assets.test.ts 为该模板提供了三层保护,理解它有助于你把 user.md 当作"可维护的契约"而非死文本:

  1. 文件清单测试templates/snippets/下的文件集合必须与PROMPT_IDS × {system, user}精确匹配,杜绝模板漂移;
  2. Snippet 引用测试:模板中的每个{{snippet:...}}都必须有对应snippets/*.md且非空(system.md 通过条件块按需引入 slide 系列图片/视频指令片段);
  3. 占位符命名测试:除canvas_width/canvas_height这两个祖传豁免项外,不允许新增非小驼峰命名占位符——这保证了interpolateVariables\w+替换规则始终有效。

十、一次完整生成的调用链速览

把以上内容串起来,一次基于 user.md 的幻灯片内容生成完整链路为:

大纲(SceneOutline) → generateSlideContent(scene-generator.ts) → 组装 assignedImagesText / teacherContext / 媒体开关 → buildPrompt('slide-content', …) → loadPrompt 读取 user.md + system.md → processSnippets 展开 {{snippet:...}} → processConditionalBlocks 处理 {{#if ...}} → interpolateVariables 替换 {{变量}} → aiCall(system, user, visionImages) // 模型输出纯 JSON → parseJsonResponse // 多层容错解析 → fixElementDefaults // normalizeElement 校验/修复 → processLatexElements // KaTeX 渲染公式 → resolveImageIds / normalizeGeneratedVideoRefs // 资产映射 → GeneratedSlideContent(元素 + 背景 + 备注)

全文最值得记住的一句话来自 user.md 的标题——Generation Requirements:它把"这一页讲什么、能用什么、必须怎么输出"三件事压缩进一个结构化的用户提示,再用 system.md 的元素契约与 json-repair.ts 的容错解析兜底,最终让模型输出可稳定落地的教室幻灯片。理解这套模板即理解 OpenMAIC 内容生成质量的底层保障。

【免费下载链接】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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 11:27:48

CVAT 数据标注平台 Docker 快速部署指南

CVAT 数据标注平台 Docker 快速部署指南 【免费下载链接】cvat Computer Vision Annotation Tool (CVAT) is a leading platform for building high-quality visual datasets for vision AI. It offers open-source, cloud, and enterprise products, as well as labeling serv…

作者头像 李华
网站建设 2026/9/10 11:26:31

C语言核心概念:关键字、常量、宏与指针详解

1. C语言核心概念深度解析在C语言编程中&#xff0c;关键字、常量和宏构成了代码的基础骨架&#xff0c;而指针则是这门语言的灵魂所在。作为从1972年诞生至今仍活跃在系统编程领域的元老级语言&#xff0c;C语言的这些基础概念直接影响着代码的质量和性能。我见过太多初学者在…

作者头像 李华
网站建设 2026/9/10 11:26:28

昇腾GE获取C图构建器API

GetCGraphBuilder 【免费下载链接】ge GE&#xff08;Graph Engine&#xff09;是面向昇腾的图编译器和执行器&#xff0c;提供了计算图优化、多流并行、内存复用和模型下沉等技术手段&#xff0c;加速模型执行效率&#xff0c;减少模型内存占用。 GE 提供对 PyTorch、TensorFl…

作者头像 李华
网站建设 2026/9/10 11:26:24

CANN/ge图引擎初始化函数

aclgrphBuildInitialize 【免费下载链接】ge GE&#xff08;Graph Engine&#xff09;是面向昇腾的图编译器和执行器&#xff0c;提供了计算图优化、多流并行、内存复用和模型下沉等技术手段&#xff0c;加速模型执行效率&#xff0c;减少模型内存占用。 GE 提供对 PyTorch、Te…

作者头像 李华
网站建设 2026/9/10 11:25:57

遥感图像分类实战:kNN、SVM、CNN与LSTM四模型对比

简介&#xff1a;面向遥感图像识别任务的综合算法项目&#xff0c;覆盖kNN、SVM、CNN、LSTM四种经典机器学习与深度学习模型&#xff0c;适合计算机相关专业学生开展课设、毕设或算法对比实验。压缩包共33个文件&#xff0c;以Python脚本&#xff08;6个py&#xff09;、Jupyte…

作者头像 李华
网站建设 2026/9/10 11:23:54

如何把 BMAD-METHOD 从 v4 升级到 v6:清理旧目录并迁移规划产物

如何把 BMAD-METHOD 从 v4 升级到 v6&#xff1a;清理旧目录并迁移规划产物 【免费下载链接】BMAD-METHOD Breakthrough Method for Agile Ai Driven Development 项目地址: https://gitcode.com/gh_mirrors/bm/BMAD-METHOD 如果你的项目里还装着 BMad v4&#xff08;安…

作者头像 李华