OpenMAIC「大师讲授」模式深度解析:用 lecture-style 技能设计连续讲授型多智能体课堂
【免费下载链接】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)是一键构建沉浸式多智能体学习体验的开源项目。在其 agent-runtime 技能体系中,lecture-style(大师讲授)是一套面向「系统讲解型课程」的课堂设计技能:一门课由一位讲师的声音从头讲到尾,页面服务于论证而非打断论证。本文以 skills/agent-runtime/lecture-style/SKILL.md 为主体,结合同目录的结构化约束文件、stage-design基础构建流程、generate_scene/set_roster等运行时工具的源码实现,完整拆解该技能的设计形态、页面密度规则、旁白撰写规范、阵容写法、约束检查机制及其与workshop-style/deep-interactive的分工。读完本文,你将掌握如何识别一个「大师课」请求、如何规划并逐页生成一场 slide 载体的连续讲授课堂,以及风格如何通过brief、persona、materialFacts三个字段真实传入生成器。
一、技能定位:什么是 lecture-style
lecture-style的中文标题是「大师讲授」,其 frontmatter 描述给出了明确的触发条件与边界:
- 适用场景:lecture、masterclass、对一个学科的系统讲解(「大师课」「系统讲解」「讲透」),或任何「收获在于理解而非动手」的主题;用户直接点名该风格时同样启用。
- 不适用场景:动手实操型课程应使用
workshop-style;以操纵某种机制为核心目标的课程应使用deep-interactive。
从源码看,技能的可发现性由 lib/server/agent-runtime/skills.ts 承载:loadSkills()解析每个技能目录下的SKILL.mdfrontmatter,availableSkillsPromptBlock()把 name/description/location 渲染进系统提示,模型在请求匹配时通过 pi 的原生read工具读取 SKILL.md 全文。每个技能目录允许携带一个可选的outline-constraints.json结构化约束文件——它与 frontmatter 刻意分离:frontmatter 是「模型可见的契约」,约束文件是「检查器的契约」,避免每次 schema 调整都改动模型实际读到的正文(见skills.ts中listBuiltinSkills的实现注释)。
lecture-style 不是孤立存在的。stage-design是构建任何 stage 的地基——规划方式、工具调用顺序、阵容书写、旁白再合成时机、收尾条件——它在所有主题技能之下生效;主题技能(lecture-style、deep-interactive、vocational 等)决定 stage 里装什么。SKILL.md 开头也明确强调:「stage-designstill governs how the stage is built — outline, roster, one page pergenerate_scene, audio before done. This skill governs what the stage contains and how it sounds.」因此使用 lecture-style 时应先阅读 skills/agent-runtime/stage-design/SKILL.md。
二、课堂形态(The shape):slide 载体的连续论证
lecture-style 对整门课的页面结构有明确的形态约束,这是与其它风格最显著的分野:
- 第 1 幕必须是
slide,且要「真正地开场」:提出这个主题要回答的问题、为什么它值得花一小时、这堂课将如何展开。它既不是定义页,也不是目录页。 - 主体是
slide页面,以「弧」(arc)组织。一条弧由 3 到 5 页构成,把同一个想法从「断言」推到「后果」:先给出主张(claim),再讲底下的机制(mechanism),然后用真实案例检验它。弧与弧首尾相接,整堂课从不重新开始。 - 检查点(checkpoint)必须稀少:大约每 4 到 5 页一个
quiz,位置在一条弧收束、下一条弧开启的接缝处,测试的是学习者能否应用弧里的思想,而不是复述字句。SKILL.md 用一句犀利的判据划清边界:「两页里放两个 quiz,那不是讲座,那是中间夹着幻灯片的测验。」 - 至多一个
interactive页面,放在全课机制感最强的那一个概念上——那个「光靠讲真的传不过去、学习者必须亲眼看它动起来」的地方。如果一个主题有两个这样的概念,放第二个尚可辩护;出现第三个,说明这个请求根本不是讲座,deep-interactive更合适。 - 收尾收在论证上,而不是要点罗列:这堂课确立了什么、刻意留下了什么没讲、好奇的学习者下一步该往哪走。
这一形态不是纯文字约定,它被机器可检查地固化在同目录的 skills/agent-runtime/lecture-style/outline-constraints.json 中:
{ "allowedTypes": ["slide", "quiz", "interactive"], "firstSceneType": "slide", "typeMix": [ { "type": "slide", "minRatio": 0.65 }, { "type": "quiz", "min": 1, "max": 3 }, { "type": "interactive", "max": 2 } ] }即:本课只允许slide/quiz/interactive三种页面类型;第 1 幕必须是slide;slide至少占 65%;quiz至少 1 个、至多 3 个;interactive至多 2 个。约束文件注释还专门说明:旁白长度与口吻——本风格最响的部分——不是结构性内容,无法在此检查,它们经由keyPoints、阵容 persona 与逐页materialFacts传入。
三、约束检查机制:从大纲到持久化页面的机器校验
约束文件的价值在于它被真实执行。skills.ts提供了两条检查路径:
checkOutlineAgainstSkill(outlines, constraints):对模型产出的课程大纲做机器检查,返回人类可读的违规清单。检查项覆盖场景总数上下限、非法类型、第 1 幕类型、typeMix 的 min/max/minRatio、interactive 页的 widgetType 与 widgetOutline 必填字段、连续两页同 widgetType 等。checkScenesAgainstSkill(scenes, constraints):对实际持久化的页面做同样的检查。generate_scene每次落盘一页后都会调用它,违规以 tool-result diagnostic 的形式回传给 agent,由 agent 决定是否重新规划。
skills.ts中一个值得注意的设计决策:检查只返回诊断、不做自动重写。注释写道——「一个计划是一个连贯的整体,机械地把某页类型翻来翻去满足比例,产出的课程读起来像被 linter 拼出来的」。违规信息回到 agent 手里,由它判断如何修复;持久化也永远不会被该检查回滚。
在 tests/agent-runtime/skills.test.ts 中有一个专门测试组pedagogy style skills,用「对比法」验证两个风格约束的互斥性:
- 一个 masterclass 形态的页面组合(
slide为主体、第 5 页一个quiz、第 8 页一个simulationinteractive)通过checkOutlineAgainstSkill检查时,对 lecture-style 返回[](零违规)。 - 同一个 masterclass 组合拿去喂 workshop-style 的约束,会被判定违规(interactive 至少 3、quiz 至少 2)。
- 反之,workshop 形态的页面组合(slide/interactive 交错)喂给 lecture-style,会产生「slide 不足 65%」「interactive 超过上限」两类违规。
这意味着:一个请求若在两种风格下反复重生成,产出的课程必须肉眼可辨地不同——这正是「风格是有实质约束、而非口头承诺」的测试锚点。测试还断言两种风格的 SKILL.md 内容都包含materialFacts、brief、set_roster、voiceDesign这些字段名以及「exactly one teacher」,确保风格能被正确地传入生成器实际读取的字段。
四、页面密度:命题式的 keyPoints 与贯穿全课的案例
lecture-style 明确声明「密度是特性」:一页只说一件事的讲座页,是浪费的一页。具体规则:
- 每个主体页携带4 到 6 条
keyPoints,而且它们是命题,不是标签——「利率上升先压估值再压盈利」,而不是「利率影响」。 - 一页装载「一个主张加让它站住的证据」:定义及其边界、机制加一个走通的案例、对比加一条区分两边的判据。
- 每条弧必须命名一个真实案例——一家公司、一项研究、一段历史、一段代码——并让它反复出现。SKILL.md 的批评非常具体:「一堂课每页都换一个新鲜但没讲透的例子,等于什么都没教。」(A lecture that cycles through a fresh unexplained example every page teaches nothing about any of them.)
在generate_scene的参数层,keyPoints由工具参数驱动。看 lib/server/agent-runtime/generation-tools.ts 中generate_scene的参数定义与SceneOutline的组装逻辑:
title、type、brief三个字段为必填,brief承载这一页的教学意图与内容纲要。materialFacts是可选字符串数组,直接落入SceneOutline.keyPoints。instruction可选,仅对已有slide页生效(作为editDirective传入,并把现有元素/背景作为baselineContent)。media可选但上限 8 项,每项必须是具体的 HTTP(S) URL 或同源路径,占位符与 data URL 会被拒绝。
也就是说:讲座页的命题式要点、旁白里的真实案例,最终都通过brief与materialFacts被写进每页的生成调用。一次generate_scene调用是这一页的持久化检查点(durable checkpoint)——页面只在调用返回后才会在中断中存活,这与stage-design中「页面落盘才算数」的纪律一致。
五、旁白即讲座:连续、推进、权威的口吻
这是风格「被听到」的地方,也是 SKILL.md 花最多篇幅的地方:
- 每个主体页都有一段连续而绵长的教师独白——一行四到六句话,而不是一行caption,一页有好几行。学习者应当能闭着眼睛也能跟得上。
- 旁白必须向前推进。每一行接住上一行结尾的想法:陈述它、解释机制、再带一个具体案例走完整条机制,直到结论不可避免。
- 语域是「一个权威在一屋子人面前出声思考」——完整句子、笃定、不慌不忙,偶尔在解决难点前先把「难在哪」点出来。
- 助教极少开口,且只在「全场已经在想同一个问题」时替大家问出来,然后由讲师长篇作答。每条弧至多一次这样的问答。
- 本风格明令禁止:没有实质内容的「大家想一想」式提问、复述幻灯片标题的单行caption、以及打气式表达(「太棒了」「让我们开始吧」)。
SKILL.md 给出的正反例非常直观:
- 好:「我们先把定义钉住——所谓久期,不是债券还剩多少年,而是价格对利率的敏感度……接下来看 2022 年的例子,同样的加息幅度,为什么二十年期的跌幅是五年期的四倍多。」
- 坏:「这一页讲久期。久期很重要。下面我们来看例子。」
从实现侧看,旁白最终以speechaction 落到页面 action 序列里。generate_scene在内容生成后调用generateSceneActions(actionGenerator),产出经过filterKnownActions过滤掉 DSL 未知的 action 类型,再通过buildCompleteScene组装成完整场景持久化。stage-design还专门提示:若旁白文本被patch_stage改写,必须对该页调用generate_tts重新合成,否则「改过但没重新合成的旁白会作为无声页发货」。
六、阵容(The roster):一位讲师加一位提问助教
lecture-style 的阵容哲学是「越少越好」:「runtime 只允许恰好一位老师,而在本风格里,这位老师就是讲师——整门课都是他的声音。拥挤的教室会拆散一场讲座。」
- 用
set_roster写阵容:一位资深领域权威,语气沉稳克制(calm, measured delivery),外加一位职责单一的助教——在弧的边界处提出那个尖锐的问题。 - 把讲授方式写进 persona 文本,把节奏写进
voiceDesign.delivery——「calm measured authoritative, unhurried」而非「lively energetic」。
对照 lib/server/agent-runtime/roster-tools.ts 的参数定义,set_roster的每个 agent 可携带:
| 字段 | 说明 |
|---|---|
name | 展示名,使用课堂语言 |
role | 必须恰好 1 个teacher,其余为assistant/student,agent 总数至少 2 |
persona | 2 到 3 句具体描述,用课堂语言写明个性与教学/学习风格,不能是角色标签 |
voiceDesign | identity(性别+年龄+角色)、texture(音高+音质)、delivery(情绪+语速)三个子字段 |
voice | TTS 绑定,格式为providerId::voiceId,必须来自list_voices的返回或register_voice的返回,禁止自造 id |
avatar/color/priority | 可省略,自动从默认池与调色板轮转;priority 按角色推导(teacher=10,assistant=7,student 4-6) |
值得注意的实现约束:set_roster会对voice绑定做目录校验——绑定必须存在于list_voices报告的声库中(排除未服务 provider、无 key provider 与付费展示音色,这些不可能真正合成),否则直接报错voice-not-in-catalog并列出可用绑定。这是「只绑定模型被展示过的声音」的 fail-closed 纪律。阵容落盘到stage.generatedAgentConfigs,并同时写入stage.agentIds,之后的页面内容与旁白都按这套阵容生成——所以stage-design强调 roster 必须在生成任何页面前定稿,晚了就有一半课程「从没见过自己的阵容」。
七、把风格传进生成器:只有写进字段的文本才会被看到
lecture-style(以及所有主题技能)面对一个关键的结构性约束:没有大纲生成器。课程在对话里规划好之后,直接调用create_stage,然后逐页调用generate_scene,每页带一个显式 brief;而页面内容与旁白由互不相见的独立调用生成——各自只能看到「本页的 brief、页面内容与阵容」。因此 SKILL.md 给出了三条必须遵守的传递纪律:
- 把弧结构和密度期望写进每页
generate_scene的brief; - 把讲授方式写进
set_roster的每个 persona; - 把旁白指令放进每页
generate_scene.materialFacts——例如「旁白为连续讲述,四到六句一段,先定义再机制再案例」「本页复用前一页的同一家公司作为案例」。
SKILL.md 对此有一句锋利的结论:「在提示词里点名这个技能什么用都没有;只有你放进那些字段的文本才会被看见。」(Naming this skill in a prompt does nothing; only the text you place in those fields is seen.) 这一点在测试中也有印证:skills.test.ts专门断言两个风格技能的内容都包含materialFacts、brief、set_roster、voiceDesign这些「生成器实际读取的字段」。
create_stage/generate_scene/list_scenes等工具的实际行为可以在 lib/server/agent-runtime/generation-tools.ts 中核对:generate_scene要求 1-based 的整数order、非空title与brief;复用 order 会替换该页;对pbl类型有专门的类型变更保护(改类型会销毁项目,因此被阻止);interactive 之外的类型传入widgetType/widgetOutline会被拒绝。
八、场景命名:用学科自己的语言命名步骤
lecture-style 的场景标题应当是「讲座自己的步骤」,使用学科语言:
- 好:「久期到底在度量什么」「同样加息,为什么长债跌得更狠」「三个反例,和它们的共同点」
- 坏:「概念介绍」「案例分析」「本课总结」
这与workshop-style(命令式命名,如「把这段循环改成能跑的」)和deep-interactive(命名学习者做什么或发现什么,如「拖动倾角,看射程怎么变」)形成三种可辨识的命名风格。
九、风格边界:什么时候它不是讲座
lecture-style 明确规定了「拒绝转向」的情形:如果用户想要的是练习一项技能、产出自己的东西、或完成一组习题,应当用一句话说明,并改用workshop-style——「把练习请求包进一场讲座,产出的是一门学习者只能观看、无法使用的课。」(Wrapping a practice request in a lecture produces a course the learner watches and cannot use.)
更完整的风格光谱(均位于 skills/agent-runtime 目录):
| 风格 | 核心判据 |
|---|---|
lecture-style | 收获在于理解;一页一节连续论证;旁白是完整讲述 |
workshop-style | 收获在于带走一项技能;概念后紧跟动手页;旁白是引导性短句、提问多于陈述 |
deep-interactive | 主题内含机制/变量/过程/结构;绝大多数页面是可操纵的 interactive 页,slide 只留给开场与收束 |
三种风格共享同一个stage-design构建序列(对话中定计划 →create_stage→set_roster→ 逐页generate_scene→list_scenes核对 → 检查每页旁白有音频),但在「stage 里装什么、怎么发声」上各自为政。判别一款请求该用哪种风格,看的是学习者的预期收获而非主题本身。
十、从请求到成品:一次 lecture-style 课堂的完整路径
综合以上全部内容,一个「大师课」请求在 OpenMAIC 中的落地路径可以总结为:
- 触发:请求匹配 lecture-style 的 description(「系统讲解」「大师课」「讲透」等),pi 原生
read载入 SKILL.md(skills.ts中的skillReadFromTranscript让激活状态成为可恢复的持久记录)。 - 规划:对话中与用户敲定页面计划(每页的 title、type、brief),用
ask_user确认——没有大纲工具,计划就是你的话加用户的签字。 - 创建:
create_stage建 stage(系列课程可同时传folderId),拿到stageId。 - 阵容:
list_voices查询可绑定声库 →set_roster写入「1 位沉稳权威讲师 + 1 位提问助教」,讲授方式在 persona、节奏在voiceDesign.delivery。 - 逐页生成:每页一次
generate_scene(order递增),brief 携带弧结构与密度期望,materialFacts携带旁白指令与复用案例;interactive 页最多一个、quiz 每 4-5 页一个。 - 校验:每页落盘后
checkScenesAgainstSkill对实际页面做约束检查,违规以诊断形式回传;最后用list_scenes核对全部页面已持久化、按stage-design的要求确认每页旁白 action 都有audioId音频。
这条路径的每一步都能在 lib/server/agent-runtime 的skills.ts、generation-tools.ts、roster-tools.ts与 skills/agent-runtime/stage-design/SKILL.md 中找到对应实现与纪律——风格不是提示词里的形容词,而是贯穿「规划 → 生成 → 机器校验 → 测试锚定」全链路的可执行约束。
【免费下载链接】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),仅供参考