提示词构建
智能体每一步都要把 role/goal/工具/记忆拼成一段 LLM 提示。今天读提示词构建的两级流程,尤其是"滚动记忆压缩"这个应对长对话的关键机制。
两级构建
build_agent_prompt + build_agent_messages 两步的展开。提示词构建分两级:先填模板变量,再拼对话消息。
- ① 填模板(
AgentPromptBuilder):把 goals/instructions/工具塞进系统提示模板。 - ② 拼消息(
AgentLlmMessageBuilder):系统提示 + 历史 Feed → LLM 的 messages 数组。
[{role:system, 系统提示}, {role:user/assistant, 历史...}] 这个消息数组。📋 生活类比(贯穿今天):系统提示像入职时发的员工手册——规定"你是谁、能用哪些工具、要守哪些规矩",发一次基本不变;对话消息像每日工作日志——越写越厚,记着"我今天干了啥、结果如何"。每轮上工,都是"手册 + 到目前为止的日志"一起摆在 LLM 面前。
系统提示模板
agent/prompts/superagi.txt 定义智能体人设,含占位符 {goals} {instructions} {constraints} {tools},并强制 LLM 只输出符合给定 JSON schema 的内容:
# 模板要求 LLM 输出:
# thoughts: {text, reasoning, plan, criticism, speak}
# tool: {name, args}
thoughts 里还分 text/reasoning/plan/criticism——引导 LLM 结构化思考(甚至自我批评 criticism),提升决策质量。填充主变量
AgentPromptBuilder.replace_main_variables(agent/agent_prompt_builder.py:65)把 goals/instructions/constraints 转成编号列表塞进模板。
1. xxx / 2. yyy 的编号列表填进模板占位符。任务队列型工作流还会填 {current_task}/{pending_tasks}/{task_history}(replace_task_based_variables,:95),并按 token 预算截断历史。superagi.txt):GOALS:\n{goals}\n\nCONSTRAINTS:\n{constraints}输入变量:
goals=["订最便宜的机票","预算不超过1000元"]、constraints=["不要重复调用同一工具"]→ replace_main_variables 渲染后:
GOALS:1. 订最便宜的机票2. 预算不超过1000元CONSTRAINTS:1. 不要重复调用同一工具每条独立编号,LLM 更容易逐条对照遵守。
✅ 生活类比:就像给人交代活儿,与其写一大段话,不如列一张清单(checklist):1. 做 A 2. 做 B 3. 别忘了 C。每条独立、可逐项对照打勾,不容易漏。
工具渲染成 schema
add_tools_to_prompt(agent_prompt_builder.py:23)把每个工具渲染成 "工具名": 描述, args json schema: {...},并追加内置 finish 工具。
tool.args)拼进提示——告诉 LLM"你有这些工具、每个怎么用、参数怎么填"。_generate_tool_string(:53)用 tool.args 的 JSON schema 说明每个工具的参数。总会追加一个 finish 工具——让 LLM 有办法"宣布任务完成"(Day 06 的结束条件)。ToolBuilder,Day 12)——根据 DB 里 Tool 记录的 folder/file/class 名 importlib 动态导入实例化,再注入依赖(llm/resource_manager…)。迭代步默认还会放一个 ThinkingTool(Day 03)。"哪些工具进提示"由智能体配置 + 工作流决定。拼装对话消息(含记忆)
AgentLlmMessageBuilder.build_agent_messages(agent/agent_message_builder.py:26):
# :38 system 消息 = 上面填好的系统提示
# :39-53 若 history_enabled,加当前时间,把历史 agent_feeds(Day 02 的 Feed)转成消息
# 超 token 预算的旧历史 → _split_history 切出去 → 压缩成摘要(L06)
prompt = system_prompt + "\n" + "\n".join(all_feeds) # 全塞进去
问题:历史无限增长,循环几十轮后必然超 token 上限。真实版:
build_agent_messages 把 system 与历史分开,且 _split_history 把超预算的旧历史切出去交 _build_ltm_summary 压成摘要(L06)。真实版多出来的"切 + 压"两步,就是为了解决朴素版"迟早爆上下文"的硬伤。滚动记忆压缩(关键机制)
历史越来越长会超 token 上限。_split_history(agent_message_builder.py:59)把超预算的旧历史切出去,交给 _build_ltm_summary(:91)调 LLM 压缩成"长期记忆摘要"作为一条 assistant 消息。
📝 生活类比:就像长会议的会议纪要——早上讨论的细节没人全记,但会浓缩成一句"上午决定了 A、B、C";最近半小时的讨论还保留原话。摘要(浓缩远期)+ 原话(详细近期),既不啰嗦又不丢重点。
context_length_exceeded,智能体直接崩在半路。压缩后:旧历史摘要 ~500 token + 最近 5 轮 ~7500 token ≈ 8K,稳稳塞下、还接着能跑几十轮。就为了这条命,滚动压缩必不可少。👶 小白:把旧历史压成摘要,万一压掉了后面正好要用的关键信息,智能体不就"失忆"了?
👨🏫 老师:这确实是取舍,SuperAGI 尽量降低风险:只压更早的旧历史、完整保留最近几轮的详细记录;而且摘要是让 LLM 去提炼"做了 A/B/C、结论是 D"这类关键结论,不是粗暴截断。远期细节会丢一点,但这是拿"损失一点远期精度"换"上下文不爆、任务能跑完"——比第十几轮直接 context_length_exceeded 崩在半路强太多。
模板与代码分离
注意提示词放在 .txt 文件里(prompts/superagi.txt、agent_tool_input.txt、agent_tool_output.txt),代码只做"读模板 + 变量替换"。
今日小结 + 动手
🧠 今天你应该能回答
- 提示词构建的两级(填模板 / 拼消息)?
- 系统提示为什么强制 JSON schema 输出?
- 工具怎么渲染进提示?为什么总追加 finish 工具?
- 历史 Feed 怎么拼进消息?
- 滚动记忆压缩解决什么?为什么提示词放 .txt?
✋ 动手
P=superagi/agent
cat prompts/superagi.txt | head -40
sed -n '23,93p' agent_prompt_builder.py | head -40 # 填变量 + 工具渲染
sed -n '26,70p' agent_message_builder.py # 拼消息 + 切历史
grep -n '_build_ltm_summary' agent_message_builder.py