Products
GG网络技术分享 2026-04-16 04:29 1
先说一句, 写这篇文章的时候,我的咖啡已经凉到可以直接当冰块砸键盘了。别问我为啥这么激动——主要原因是单智能体代码里藏着的 Context Engineering 简直像是暗黑料理, 一言难尽。 入口即化,却让人胃疼。
下面的文字会像一条不靠谱的山路, 时而上坡、时而下坠,甚至会突然出现一只野猫提醒你「别忘了加表格」!如果你想要的是干净利落的技术文档, 那请立刻关掉页面;如果你想要的是「烂」得有味道、带点情绪的碎碎念,那就继续往下看吧,蚌埠住了!。

单智能体其实就是只有一个“大脑”的机器人,它负责全局规划 + 分步 ReAct 循环。全局规划像是先画好地图, 然后每走一步都把地图摊在桌子上翻来覆去——灵活性高到可以随时改道, 搞起来。 但也正主要原因是只有一颗心脏,血压波动会让它在关键时刻“心脏骤停”。
Reflection 到 PlanningTool下面这段代码是我们常见的「思考‑行动‑观察」循环里 用来判断模型是否已经足够「满意」的 Reflection 数据结构:
class Reflection:
is_sufficient: bool = Field(
description="Wher provided summaries are sufficient to answer user's question."
)
knowledge_gap: str = Field(
description="A description of what information is missing or needs clarification."
)
follow_up_queries: List = Field(
description="A list of follow-up queries to address knowledge gap."
)
这玩意儿其实在说:「兄弟,你给我的摘要够用了么?」如果不够,就给出 knowledge_gap 并列出后续查询,我们都经历过...。
你想... 再往下一层, 是负责生成、更新、追踪计划的 PlanningTool
class PlanningTool:
"""A planning tool that allows agent to create and manage plans for solving complex tasks."""
name: str = "planning"
description: str = _PLANNING_TOOL_DESCRIPTION
parameters: dict = {
"type": "object",
"properties": {
"command": {"description": "...", "enum": , "type": "string"},
"plan_id": {"description":"Unique identifier...", "type":"string"},
// …… 省略大量参数说明
},
"required": ,
"additionalProperties": False,
}
这里面最坑的是「command」字段,一不小心就会让整个计划变成「删除全部」的灾难操作。😅 所以在实际使用中,一定要加上「二次确认」这种防呆措施,说到点子上了。。
线性增长+窗口截断 是单智能体最常见的问题。每一步 ReAct 都把历史消息全部塞进模型输入,导致 Token 数呈指数级飙升。于是出现两大症状:
解决方案?压缩!但压缩本身又是一把双刃剑:压得太狠,你会失去细节;压得不够,又浪费算力。 要我说... 于是诞生了各种「Context Cache」「摘要服务」「RAG 多路复用」等奇葩玩法。
class SearchQueryList:
query: List = Field
rationale: str = Field
# 这里本来应该只有两行代码, 却被同事粘贴了三段无关会议纪要……
# ----------------------------------------------------
# 2024-03-12 项目进度:
# - 完成需求评审
# - 开始实现 UI
# ----------------------------------------------------
| 特性 | Gemini FullStack | OpenManus Flow | Deer‑Flow |
|---|---|---|---|
| 全局Plan管理 | ✔️ 强制节点顺序,易调试,但灵活性低。 | ✔️ 动态创建子Plan,支持即时插拔。 | ❌ 采用隐式上下文传递,需要额外Supervisor。 |
| Step 隔离 | ✖️ 全历史滚动,容易爆 token。 | ✔️ 每 Step 使用独立 Plan 状态 + 当前任务描述。 | ✔️ Worker 只拿到自己需要的 Context Fragment。 |
| 并行检索 | ✅ LangGraph Send 多线程实现。 | ❌ 默认串行,需要自行 并发模块。 | ✅ 内置分布式搜索框架,可自定义调度策略。 |
| 反思机制 | 🧠 专门 ReAct 节点做质量评估。 | 🧩 Flow 中通过 Planner
调用工具判断是否满足需求。 | |
| 注:星级仅为主观感受,实际选型请结合团队实力与业务场景。 | |||
ReAct 本质上是三段式:
.当 ReAct 循环超过四轮以后你会发现模型开始忘记一开始的问题,只记得最近一次工具调用的参数。这叫信息漂移**。 反思一下。 解决办法之一是每轮都把"原始用户意图"* 用一个专门字段强制写入 Context, 比方说:
state = original_user_question
messages.append
你没事吧? 这样即使历史被截断,模型仍然能抓住核心需求。不过这种硬邦邦的方式也会让 Prompt 看起来像是"拼接广告语", 阅读体验极差——恰恰符合我们「烂」文章的精神!😂
| # 实验组 | Description | Total Tokens | Satisfaction 满意度估计* |
|---|---|---|---|
| A – Pure ReAct | No global plan, pure step‑by‑step.≈ 12 400 tokens | 62% | |
| *满意度基于人工评审打分,仅供参考。 | |||
上手。 *实验结论很明显:有 Plan 的情况下 即使多了一点开发成本,也能显著降低 Token 消耗并提升答案质量。不过 要注意 **Plan 更新频率** —— 如果每一步都重新生成整个 Plan,那就和纯 ReAct 没区别了只是多了一层无意义的包装而已 🤦♀️.
"budget_remaining":10` 的字段,让模型自行决定是否继续调用工具。 "max_repeat_penalty"/
`stop` 条件防止无限循环。Dumb idea? 不敢说 但是很多团队已经开始在 System Prompt 前面套上一层 Meta Prompt,用来自动抽取关键实体并生成结构化 JSON,然后把 JSON 当作真正的 Context 输入模型。这种做法能把几千字的自然语言压缩到几百字以内,一边保留关键信息。「元 Prompt」本身也是一种 Mini‑Agent, 它负责清洗和归纳,这样主 Agent 就只需要专注于业务推理啦! 🎉,纯正。
看完这篇乱七八糟却充满情绪波动的文章,你应该明白:
图啥呢? 再说说送上一句古老而永恒的话:「技术不怕复杂,就怕没人懂。」愿你的单智能体能够在嘈杂的数据海洋中保持清醒,也愿你的阅读体验能够在这篇故意“烂”的文章里找到一点点乐趣。 祝编码愉快! 🎈
Demand feedback