昨天提到了提到 system prompt系统提示词那他这个和user prompt用户提示词用户角色的提示词到底有什么区别为什么system prompt不能太多为什么要使用多Agent架构直接使用1个Agent 只要它具有更强大的工作能力是不是就一个agent就足够了首先回答问题1.system prompt 和 user prompt 从大模型的设计上和设计时就已经区分开大模型在训练的时候就被专门用特定的标记Token区分不同的角色。system提示词相当于“上帝视角/元指令”。用户的所有输入全都以system的提示词最高标准去对齐。2.system prompt 不要直接写入user prompt的开头位置虽然也可以否则多轮对话后就会因为上下文压缩和剪枝导致 注意力权重下降。 而system prompt不会发生该问题。 例如我们可以在 用户提示词的输入框开头写下请以一个 测试工程师 、高级质量工程师的角色来分析如下代码并生成测试用例 这个其实就属于我们把system prompt的提示词 写入了user prompt。3.system prompt不宜过多越精简越好。一般建议300-1000tokens。大了反而会导致注意力丢失只关注首尾规则丢失中间。 大模型的上下文大小越来越大都是为了用户和skill、工具的内容。然而系统提示词不建议过大。4.单agent架构下完全可以做到并行处理即一个单独任务独立的线程处理虽然都是同一个agent和LLM交互但是上下文隔离。 但因system prompt 定义不能越多越好上面问题3 已经回答了。 多agent可以做到跨角色的agent的协作和抵抗。也就是说 质量保障、测试工程师 Agent vs 开发工程师 Agent。 否则开发工程师自己测试自己代码永远都觉的是正确的。我们用一个生动的例子用“蜜蜂采蜜与酿蜜”来做这个比方蜜蜂它吃进去花粉和花蜜在体内加工既能产出对人类和自然极有价值的“蜂蜜”有用输出也会排出无用的渣滓拉屎/剪枝。和 Agent / 大模型的 Token 治理一一对应起来蜂巢与蜜蜂的“吞吐系统”大比方1. 蜜蜂的胃Context Window 上下文窗口胃的容量 大模型的Total Context Window比如 128k Token。蜜蜂的胃容量是有限的不管是吸进去的花蜜、吞进去的花粉、正在酿造的蜂蜜还是准备排出的渣滓全都要占胃的空间2. 蜜蜂吸进去和存着的东西输入 Token / Input Tokens蜜蜂飞出去采蜜吃进肚子里的各种东西对应大模型输入的各个部分主食蜜水System Prompt 元规则 相当于蜜蜂维持生命必须先喝的那一口底蜜压肚子的基础。不管干啥活这部分基础规则始终占着胃里的固定空间。高浓度花粉(水分少的干性花粉Tools / Functions 定义 高营养但极其硬核、占地方挂载的工具越多就像蜜蜂塞了一肚子浓缩花粉还没开始酿蜜胃就被塞饱一大半了。飞过的路线与采到的花蜜液体花蜜露Messages 历史对话 用户的提问 蜜蜂一路飞一路吸花蜜源源不断地聊天、输入长文档。吸得越多肚子里的液体就积得越多。未过滤的花粉壳与杂质以往 Tool 返回的几万行冗余日志/数据 Agent 跑终端或查数据库吐出来的一大堆垃圾日志就像蜜蜂吸进肚子里那些无法被酿成蜂蜜的粗糙花粉壳纯粹死死堵在胃里极占地方。3. 产出蜂蜜 vs 排出渣滓输出给我们用户的回答内容 Response vs 剪枝 Pruning 把肚子的空间腾出来吐出真正的蜂蜜吐蜜 大模型最终给用户的真正的有效回答。蜜蜂在胃里经过一系列复杂的生物酶转化大模型 Transformer 推理思考把吸进去的粗糖转化成极具价值的蜂蜜吐进蜂巢返回给用户。关键约束蜜蜂在吐蜜之前胃里必须留有足够的压强和空间否则胃装太满它连转化生成蜜的空间都没有直接卡死。排出花渣/废料上下文剪枝 排渣/拉屎上下文剪枝。蜜蜂在酿蜜的过程中会把那些无法转化成蜂蜜的硬壳、杂质和多余水分排出体外剪枝/清理历史废话。拉屎剪枝的意义把肚子里没用的花渣赶快排出去腾出胃里的空间蜜蜂才能继续吸新花蜜输入新问题、吐出更多浓郁的蜂蜜输出长回答进入正题大模型的基本工作过程 本次我们举例2个实例1用户一次问题Agent和LLM 2轮交互2 用户和Agent有2次问题交互示例一用户一次问答Agent和LLM 有2轮交互下面以OpenAI API 协议为例 展示一个典型用户一次问答 但是Agent和LLM需要进行****2轮对话的过程。场景设定天气与服装推荐 Agent工具get_current_weather获取实时天气目标用户询问城市天气并要求根据天气推荐穿着。Agent第一次和LLM交互 LLM仅返回格式化工具调用信息1.1 客户端/ Agent 发送请求 (Request)Agent 把System Prompt、User Message以及定义的Tools Schema组装发给大模型。POST /v1/chat/completionsContent-Type: application/json{“model”:“gpt-4o”,“temperature”:0.2,“messages”[{“role”:“system”,“content”:“你是一个智能生活助手。你需要根据用户提问先查询天气再给出穿衣建议。如果需要调用工具请直接输出 Function Call。”},{“role”:“user”,“content”:“今天北京的天气怎么样我该穿什么衣服”}],“tools”[{“type”:“function”,“function”{“name”:“get_current_weather”,“description”:“获取指定城市的当前天气情况”,“parameters”{“type”:“object”,“properties”{“location”{“type”:“string”,“description”:“城市名称例如北京、上海”}},“required”[“location”]}}}]}1.2 LLM 返回响应 (Response)大模型发现回答问题需要先拿到实际数据因此不直接返回文本而是返回tool_calls指令。这时候 Agent需要执行 工具获取 天气信息。HTTP/ 1.1 200 OKContent-Type: application/json{“id”:“chatcmpl-round1-call”,“choices”[{“index”:0,“message”{“role”:“assistant”,“content”:null,“tool_calls”[{“id”:“call_weather”,“type”:“function”,“function”{“name”:“get_current_weather”,“arguments”:“{“location”: “北京”}”}}]},“finish_reason”:“tool_calls”}]}Agent 调用tool_calls后解析出函数名get_current_weather和参数{location: 北京}。调用天气 API得到天气数据结果{location: 北京, temperature: 8°C, condition: 微风多云转晴}第二轮和LLM交互2.1 客户端/ Agent 发送更新后的上下文请求Agent必须把第 1 轮的原始对话、LLM 吐出的tool_calls消息以及工具执行返回的tool结果全部拼接到messages队列中发回给 LLM。POST /v1/chat/completionsContent-Type: application/json{“model”:“gpt-4o”,“temperature”:0.2,“messages”[{“role”:“system”,“content”:“你是一个智能生活助手。你需要根据用户提问先查询天气再给出穿衣建议。如果需要调用工具请直接输出 Function Call。”},{“role”:“user”,“content”:“今天北京的天气怎么样我该穿什么衣服”},{“role”:“assistant”,“content”:null,“tool_calls”[{“id”:“call_weather”,“type”:“function”,“function”{“name”:“get_current_weather”,“arguments”:“{“location”: “北京”}”}}]},{“role”:“tool”,“tool_call_id”:“call_weather”,“content”:“{“location”: “北京”, “temperature”: “8°C”, “condition”: “微风多云转晴”}”}],“tools”[ … ]}2.2 LLM 返回最终答案 (Response)大模型结合了完整上下文用户需求 工具执行结果生成最终的自然语言总结。HTTP/ 1.1 200 OKContent-Type: application/json{“id”:“chatcmpl-round2-final”,“choices”[{“index”:0,“message”{“role”:“assistant”,“content”:“今天北京的天气为多云转晴伴有微风气温约为 8°C。\n\n穿衣建议天气较冷建议穿着风衣、轻薄羽绒服或夹克内搭羊毛衫或保暖内衣。早晚温差较大请注意保暖”},“finish_reason”:“stop”}]}上下文可以看到第二轮和LLM请求包含了所有过往的历史状态包括工具调用的 JSON 参数和返回日志。这也是为什么需要“上下文剪枝Pruning”来降低 KV Cache 消耗的原因。示例二、 用户 和 Agent 2次对话的示例用户与 Agent 进行2 次对话2 轮交互在底层 API 维度上主要是上下文messages数组的持续累加。下面以 OpenAI标准的 API 格式展示完整的协议交互场景设定代码优化与提问第 1 次对话用户发送一段 Python 代码请求优化。第 2 次对话用户针对第 1 次的回答追问“解释其中某句代码的含义”。第 1 次用户与 Agent 对话Agent 拼接静态的 System Prompt 和用户的第 1 个提问。POST /v1/chat/completions Content-Type: application/json { ”model”: ”gpt-4o”, ”temperature”: 0.3, ”messages”: [ { ”role”: ”system”, ”content”: ”你是一个资深的 Python 架构师回答要求言简意赅只推荐符合 PEP 8 规范的最优解。” }, { ”role”: ”user”, ”content”: ”请用列表推导式把这个循环写得更简洁\nresult []\nfor x in range(10):\n if x % 2 0:\n result.append(x * 2)” } ] }大模型生成第 1 次的回答返回给 Agent 并展示给用户。 此时大模型返回了 优化后的代码。HTTP/1.1 200 OK Content-Type: application/json { ”id”: ”chatcmpl-turn1-response”, ”choices”: [ { ”index”: 0, ”message”: { ”role”: ”assistant”, ”content”: ”你可以使用带有条件判断的列表推导式重构为一行\n\npython\nresult [x * 2 for x in range(10) if x % 2 0]\n” }, ”finish_reason”: ”stop” } ] }第 2 次用户与 Agent 对话追问肯定不会再次把第一次返回的 优化代码再发一次了核心工程细节大模型本质是“无状态”的。为了让大模型“记住”刚才讨论过的代码Agent必须把第 1 轮的user提问和assistant回答完整拼接到messages队列里再附上用户的第 2 次提问。POST /v1/chat/completions Content-Type: application/json { ”model”: ”gpt-4o”, ”temperature”: 0.3, ”messages”: [ { ”role”: ”system”, ”content”: ”你是一个资深的 Python 架构师回答要求言简意赅只推荐符合 PEP 8 规范的最优解。” }, { ”role”: ”user”, ”content”: ”请用列表推导式把这个循环写得更简洁\nresult []\nfor x in range(10):\n if x % 2 0:\n result.append(x * 2)” }, { ”role”: ”assistant”, ”content”: ”你可以使用带有条件判断的列表推导式重构为一行\n\npython\nresult [x * 2 for x in range(10) if x % 2 0]\n” }, { ”role”: ”user”, ”content”: ”其中的 if x % 2 0 为什么要放在最后面而不是放在 x * 2 前面” } ] }大模型读取了包含完整历史的 messages基于上下文回答追问。HTTP/1.1 200 OK Content-Type: application/json { ”id”: ”chatcmpl-turn2-response”, ”choices”: [ { ”index”: 0, ”message”: { ”role”: ”assistant”, ”content”: ”这是 Python 列表推导式的语法规则\n1. **过滤器if放在最后**用于在元素进入计算前进行筛选。只有满足条件 x % 2 0 的元素才会传给最左侧的表达式。\n2. **转换表达式x * 2放在最前**只有当需要三元运算符如 x * 2 if x 5 else x时if-else 才会写在表达式位置。” }, ”finish_reason”: ”stop” } ] }多轮对话工程状态记忆由 Agent 维护大模型服务器不帮你保存会话历史。每一次新的用户提问Agent 客户端都要把前面的所有user和assistant消息完整重新上传一遍。静态前缀命中 API 缓存在第 2 次请求中开头的System Prompt以及第 1 轮的问答完全没有改变。API 厂商如 OpenAI、DeepSeek的 Prompt Caching 机制 会自动命中这部分前缀第 2 次请求中这部分重用 Token 会打折且首字响应极快。一个是降低了token的消耗量和提高了响应速度。