本节摘要:本节是全册的概念字典,用剧场语言把 CAMEL 的五个核心概念一次过手:任务提示(任务卡)、角色设定(戏路)、启示式提示(剧本)、消息集合(台词记录)、终止条件(谢幕口令)。每个概念都给出在框架里的对应物与一个反例,读完后你能对任意双智能体需求做一次完整的"道具清点"。
1.1 节立起两位主角时,出现过一句"开场剧本",也出现过"任务卡",两个词只差几个字,含义却完全不同——这是初学者最容易跌的第一个坑。干脆在动手之前把道具箱摊开,五样东西逐个验明正身。本节不写新代码,但每个概念都配一个"合格样品"和一个"常见次品",你以后写配置时可以逐项对号。
任务提示(Task Prompt),剧场里的任务卡。它是人类交给系统的那句原始需求,"开发一个股票交易机器人"。它有两个特征:面向最终结果而非中间步骤;写得越短越好——细化是任务分解器(Task Specifier)的活,人类只负责说清想要什么。常见次品是人类越俎代庖,把任务卡写成八百字的伪需求文档,结果分解器拿到的是已经变形的二手信息,反而拆不出结构。
角色设定(Role Name 与角色描述),戏路。两个词决定两侧演员的行为收敛度:"股票交易员"与"Python 程序员"是合格样品,"用户"与"助手"是典型次品。CAMEL 论文消融实验给出过依据:角色具体性每提升一档,对话停留在任务轨道上的轮数显著增加。角色设定还包括一句话的职责边界描述,比如给交易员补一句"你只提需求与验收,不写代码"——边界句比能力句更能防跑偏。
启示式提示(Inception Prompting),剧本本体。它是写进每个智能体系统消息里的那段开场设定,包含角色、目标、约束、输出格式、终止口令。它和任务提示的区别一句话说清:任务提示说"演什么",启示式提示说"怎么演、不许怎么演"。第 2.2 节会用整节篇幅拆它,本节你只需记住它在道具箱里的位置——体积最大、最值得精雕的那件。
消息集合(Dialogue History),台词记录。每一轮的指令与方案按时间顺序累积,记作 D_t = 指令1、方案1、指令2、方案2 直到第 t 轮。两侧演员每轮作答时看到的都是同一份记录的不同视角投影:用户侧读完整历史来决定下一条指令,助理侧读完整历史来保持方案连贯。次品做法是每轮只传最新一条消息——便宜,但两侧会迅速失去共同语境,方案前后矛盾。
终止条件(Termination),谢幕口令。CAMEL 的默认机制是用户侧输出任务完成标记(经典实现里是 CAMEL_TASK_DONE 字样),框架检测到标记即停演;工程实践中还要叠加两条保险:轮次上限与令牌预算。次品是只依赖标记不设上限——一旦提示写坏、两侧陷入循环客套,你的 API 账单会替你记住这个疏忽。
这张图的信息量在两个出口:右下角的两个谢幕出口产物不同——正常谢幕的对话数据结构完整,可直接进第 4 章的数据流水线;强制谢幕的数据只能标记为截断样本。工程上有一条经验:如果强制谢幕的比例超过三成,先别调模型,回去修剧本——多数时候是任务卡太大,十轮根本演不完。
拿一个新需求走一遍流程。需求:"帮我整理一份竞品分析报告"。清点如下:
# 道具清点:竞品分析报告任务 props = { # 任务提示:一句话,面向结果 "task_prompt": "完成一份针对三款主流笔记软件的竞品分析报告", # 角色设定:具体到职责,而非泛称 "assistant_role": "产品分析师,擅长从公开信息中提炼产品差异化要点", "user_role": "市场部主管,只提分析要求并验收结论,不替分析师干活", # 启示式提示:本节只列骨架,完整写法见 2.2 "inception_skeleton": ["角色与专长", "总目标", "每轮行为约束", "输出格式", "终止口令"], # 终止条件:标记加双保险 "termination": ["用户侧输出任务完成标记", "轮次上限 12", "令牌预算 24000"], } for k, v in props.items(): # 逐项打印清点结果 print(f"{k:>20} : {v}")
task_prompt : 完成一份针对三款主流笔记软件的竞品分析报告 assistant_role : 产品分析师,擅长从公开信息中提炼产品差异化要点 user_role : 市场部主管,只提分析要求并验收结论,不替分析师干活 inception_skeleton : ['角色与专长', '总目标', '每轮行为约束', '输出格式', '终止口令'] termination : ['用户侧输出任务完成标记', '轮次上限 12', '令牌预算 24000']
注意这条需求的轮次上限给了 12 而不是交易机器人案例的 10:分析报告类任务的方案流长、指令流短,谢幕天然来得慢。轮次上限跟着任务形态走,这是第 3.3 节调参的伏笔。再看一个更小的验证脚本,确认两侧演员拿到剧本后是否真的各司其职:
def inspect_roles(session): """两侧系统消息各含一份剧本,验证关键约束是否到位。""" a_msg = session.assistant_agent.system_message u_msg = session.user_agent.system_message checks = { "助理侧含输出格式约束": "方案" in a_msg, "助理侧含一次只交付一步": ("一步" in a_msg) or ("一个" in a_msg), "用户侧含指令式行为约束": "指令" in u_msg, "用户侧含谢幕口令": "CAMEL_TASK_DONE" in u_msg, } for name, ok in checks.items(): print(f"{'通过' if ok else '缺失'} — {name}") return all(checks.values()) # inspect_roles(session) 返回 True 才算道具齐全,可以开演。
通过 — 助理侧含输出格式约束 通过 — 助理侧含一次只交付一步 通过 — 用户侧含指令式行为约束 通过 — 用户侧含谢幕口令
这个自检函数建议固化成你项目的固定工位:每次改完提示先跑它,四项全过再花真金白银开演。提示工程的成本大头不在生成,在于坏剧本烧掉的一整场戏。
最后澄清三组容易混淆的词。第一组,任务提示与任务分解:前者是输入,后者是框架内的一个可选智能体环节,开了它,任务卡会被自动细化——细节留给 2.3 节。第二组,角色设定与启示式提示:前者是名字加一句边界,后者是完整剧本,前者会被后者引用。第三组,CAMEL 的用户智能体与人:人只在戏外,开演前递任务卡、谢幕后收数据;如果某轮必须人来介入,那属于第 4.2 节评论家在环的范畴,不属于基础对手戏。
五样道具清点完毕。下一节从"想演什么"换挡到"值不值得演":这台剧场的看家本领、适用剧目与三条止损线。