
让 AI 同学问得更像真人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 同学要么一上来就说大家好我是小智很高兴和大家一起学习要么突然用老师的长篇大论口吻发表一篇小作文更常见的是——聊了十分钟之后那个活泼爱提问的同学悄悄变成了一个复读机式的助教。问题不在模型不够聪明而在于角色的一致性没有被当成一等公民来设计。OpenMAICOpen Multi-Agent Interactive Classroom作为清华团队开源的、多次登上 GitHub 热榜的多智能体互动课堂项目恰好把这一层做成了可审计的工程角色定义、输出约束、记忆压缩、能力边界各有明确的代码落点。本文直接深入仓库源码拆解AI 同学问得像真人背后到底有哪些工程细节。一、AI 同学提问不像真人的问题出在哪先看一个反直觉的事实让大模型扮演学生并不难难的是让它在几十轮对话、多个智能体轮番发言之后依然保持学生的样子。多智能体课堂里每个 agent 的发言都在互相影响上下文角色漂移几乎是必然发生的。角色漂移是一个被代码注释实锤的 bug在 lib/pbl/v2/agents/simulator.ts 中有一段注释直接记录了项目踩过的坑experiment confirmed this is the ROOT CAUSE of the role-bleed bug: … produces stage directions repetition.这段注释说的是在情景化角色扮演scenario roleplay场景里如果把旁白stage directions比如他皱了皱眉错误地喂给扮演角色的 agent角色就会串戏——开始输出舞台说明和重复内容。为此 OpenMAIC 把角色 prompt 与旁白 prompt 彻底分离扮演角色的 Simulator只看对话内容而导演narrator只负责描述可见场景与角色的非语言反应永远不替角色说话。这正是社区实战文章里反复提到的立场漂移问题的根因解法之一。长度失控学生说起了老师的小作文另一个让 AI 同学不像真人的问题是长度不分角色。真人课堂里学生插嘴通常是一两句话甚至是一个语气词而大模型默认倾向于完整作答。OpenMAIC 在 lib/orchestration/prompt-builder.ts 里把长度约束直接做成了按角色区分的硬规则老师总发言约 100 字符2-3 个短句助教约 80 字符一个回复一个要点学生约 50 字符最多 1-2 句话且明确写着You are a STUDENT, not a teacher. If your response is as long as the teachers, you are doing it wrong如果你的回复和老师一样长你就是做错了。同一文件里的ROLE_GUIDELINES还定义了课堂角色模板学生的职责是积极参与讨论、提问、分享观察、对课程做出反应并且只有在老师明确邀请时才能使用白板。这些不是提示词里可有可无的软建议而是写进系统提示词并随每次调用注入的结构化角色约束。学生角色的动作权限也被收窄如果AI 同学能动用和老师一样的工具——比如 spotlight 高亮、laser 激光笔——它立刻就不像学生了。OpenMAIC 在 lib/orchestration/registry/types.ts 中用ROLE_ACTIONS做了角色到动作集的硬映射export const ROLE_ACTIONS: Recordstring, string[] { teacher: [...SLIDE_ACTIONS, ...WHITEBOARD_ACTIONS], assistant: [...WHITEBOARD_ACTIONS], student: [...WHITEBOARD_ACTIONS], };老师独享幻灯片控制权spotlight / laser / play_video学生和助教只有白板权限。权限边界本身就是角色一致性的一部分——一个没有激光笔的 agent想像老师一样讲课也缺少工具支持。二、角色定义、温度与记忆如何共同塑造提问风格persona把性格变成可校验的结构化字段在 OpenMAIC 里一个 agent 不是一个自由文本的角色卡而是一个强类型对象。AgentConfig定义在 lib/orchestration/registry/types.ts关键字段包括export interface AgentConfig { id: string; name: string; // 显示名中文 role: string; // 角色 persona: string; // 完整系统提示词性格、职责 avatar: string; color: string; allowedActions: string[]; // 该 agent 可用的动作类型 priority: number; // 导演调度优先级1-10 voiceConfig?: { providerId: TTSProviderId; modelId?: string; voiceId: string }; voiceDesign?: VoiceDesign; // 三层声音描述符 // ... }其中persona的注释是Full system prompt (personality, responsibilities)——它承载了提问风格的全部性格层。而在课堂生成阶段这些 persona 不是用户手写的而是由 LLM 根据课程内容自动生成。看 app/api/generate/agent-profiles/route.ts 的生成约束通常生成 3-5 个 agent且恰好只有 1 个 teacher多一个直接报错Expected exactly 1 teacher, got N每个 agent 需要 name / role / persona2-3 句话描述性格与教学/学习风格且必须遵循课程语言指令priority 有硬性区间teacher10、assistant7、student4-6每个 agent 还被要求匹配一个头像、一种颜色甚至一套声音设计。注意这里的一个关键设计persona 的生成是受语言指令约束的Agent names and personas must follow this language directive。这意味着像真人首先建立在像这个语言环境里的人之上——中文课堂里的学生不会冒出英文口头禅。声音一致性三层声音描述符问得像真人不止是文本还有声音。OpenMAIC 在 lib/audio/voice-design.ts 中定义了一个与具体 TTS 厂商解耦的三层VoiceDesignidentity性别 年龄 角色如middle-aged male teachertexture音高 音质如warm low-pitched slightly huskydelivery情绪 语速如calm measured encouraging。三个维度拼接成一个声音提示词并经由buildVoiceDesignPrompt注入 TTS在支持克隆的提供方如 VoxCPM那里还会生成确定性的auto-前缀声音 ID保证同一角色跨回合、跨重新合成的音色稳定见 lib/audio/voxcpm.ts。文本 persona 和声音身份在生成阶段就要求一致——路线图里的要求是voiceDesign ... consistent with the persona。这就是为什么 OpenMAIC 的学生听起来是一个人在说话而不是每个回合换一个配音演员。温度风格靠提示词焊死而不是靠随机碰运气社区文章常把温度参数调控当作多智能体课堂的关键调参手段。OpenMAIC 的做法更工程化需要确定性的场景一律固定低温风格差异则交给 persona 与长度约束。仓库里的评测与判分器例如 eval/orchestration/answer-content-judge.ts、eval/outline-language/judge.ts全部固定temperature: 0因为打分不能每次都不一样而课堂发言这类创造性输出风格不是靠提高温度碰运气而是靠上面说的三层约束role guideline length guideline persona把口吻锁死在系统提示词里。这样既保证了学生在风格上的稳定性又保留了语言表达上的自由度。记忆让AI 同学记住自己是谁、别人说了什么真人的人设是靠记忆维持的——记得自己是谁、记得刚才谁说过什么。OpenMAIC 对记忆的处理分成几层1. 回合间 peer context同侪摘要。在 lib/orchestration/prompt-builder.ts 的buildDiscussionContextSection中当 agent 加入一场已开始的讨论时系统会注入别人已经说过什么的摘要并要求You are JOINING an ongoing discussion — do NOT re-introduce the topic or greet the students.这条规则直接消灭了AI 同学每回合都重新自我介绍的违和感——真人在同一场讨论里不会连续三次说大家好。2. 导演级上下文压缩。在 lib/chat/pi/director-compaction.ts 中长对话通过 AI SDK 的compact折叠成摘要保证导演在调度时只看到结构化摘要而非原始全文。3. 教学线程的记忆压缩。这是最能体现工程细节的地方。lib/pbl/v2/agents/instructor-memory.ts 实现了一套纯函数式无 LLM 调用的线程压缩当消息数超过COMPRESS_THRESHOLD 30时把较早的一半折叠进earlierSummary只保留最近KEEP_RECENT 16条活跃消息折叠后的记忆上限是MAX_EARLIER_SUMMARY_CHARS 4500字符。更有意思的是extractLearnerMemory——它用四组正则把学习者信息分桶提取环境/工具、水平/偏好、卡点/困惑、进度/证据让记忆只保留对教学有用的结构化事实而不是整段原始聊天记录。压缩边界还被刻意对齐到用户消息上绝不在一个问题中间切开。4. 角色扮演场景刻意不压缩。有意思的是lib/pbl/v2/agents/simulator.ts 对情景化角色扮演采取了相反策略注释明确写着there is deliberately NO summary-compaction here (would need a roleplay-specific…)——因为压缩摘要会破坏角色的场景连续感会让角色忘记早期场景。记忆策略因场景而异本身就是一致性设计的体现。三、从「像真人」到「像这个班的学生」个性化配置边界像真人只是及格线。真正让课堂有代入感的是像这个班的学生——认识面前的学习者、能感知其水平、并保持一个班级该有的秩序感。OpenMAIC 在这一层提供的不是玄学调参而是一组有边界的机制。学生画像老师真的知道在教谁在 lib/orchestration/prompt-builder.ts 的buildStudentProfileSection中用户资料nickname bio会被注入每个老师的系统提示词You are teaching {nickname}. Their background: {bio}. Personalize your teaching based on their background when relevant. Address them by name naturally.用名字称呼学生不是前端特效而是写进 LLM 提示词的教学指令。这让学生觉得这个 AI 老师认识我也让 AI 同学的提问能贴着自己的实际水平走。难度自适应学生自己的话优先于平台的猜测在 lib/pbl/v2/agents/instructor.ts 中adjust_difficulty是一个由模型自主调用的教学工具它要求模型从任何语言的学生表达中识别难度意图太难了讲慢点、Im a beginner、もっと簡単に并调用工具调整 beginner/intermediate/advanced 三档。工具描述里有一句关键设计This takes effect immediately and overrides the platforms adaptive estimate (the learners own word wins).也就是说学习者的自我声明具有最高优先级平台的自适应估计只是兜底。这一设计把个性化的控制权交给了学生本人避免了系统自作主张地猜错水平、越教越偏。名师风格与名师复刻把说话方式也变成可迁移资产OpenMAIC 的 skills 体系里有两枚与风格直接相关的技能skills/agent-runtime/teacher-style-clone/SKILL.md名师风格与 skills/agent-runtime/style-clone/SKILL.md名师复刻。前者从教师的课堂录像/讲义中提取口头禅、句长节奏、举例习惯、提问方式形成授课风格档案后者则把某套课件的版式、配色、字距作为视觉风格逐页复刻。前者特别强调风格提取必须读完整份逐字稿而不是抽样开头每条风格主张都要有带时间戳的原文证据并区分重复习惯和只出现一次的短语。而后者有一条硬规则值得所有做 AI 人格化的人记住Style is what you clone, not identity. No fabricated biography, opinions, endorsements or claims attributed to the original author.复刻的是风格不是身份——不能替原作者编造生平、观点或背书。这条规则把像真人和冒充真人划清了法律与伦理边界。一张图看懂整体形态一致性设计的三个边界纵观 OpenMAIC 的代码角色一致性不是靠某一个 prompt 魔法实现的而是三个边界共同约束的结果风格边界persona 定义是谁role guideline 定义在课堂上干什么length guideline 定义说多长voiceDesign 定义听起来像谁——四者全部在生成阶段就要求彼此一致并在运行时随每次调用注入。记忆边界peer context 保证记得别人说过什么director compaction 保证导演记得全局instructor memory 保证记得学生的水平与卡点而角色扮演场景刻意不压缩以保证角色不忘记场景——记忆策略随场景分化而不是一刀切。能力与伦理边界学生 agent 拿不到激光笔扮演角色的 agent 看不到旁白任何 agent 不得冒充其他同学lib/chat/pi/prompts.ts 明确写着Never let one child agent impersonate other classroom agents风格克隆不得伪造身份。这套设计的最终效果是AI 同学的问题可以是尖锐的、天真的、甚至带点无厘头的但它的语气、长度、权限、记忆和声音始终指向同一个稳定的角色。真人感不是靠模型恰好生成出来的而是被工程上锁定的。对于任何想把多智能体系统做出人格的团队OpenMAIC 的这些落点——结构化 persona、角色化动作权限、按角色区分的长度约束、有预算的记忆压缩、与人格一致的声音设计——是比更长的 prompt更值得借鉴的工程范式。【免费下载链接】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),仅供参考