Agent 原理
Nephele 的 Agent 不是聊天机器人,而是一个能动手干活的助手。它理解你的意图后,会自己规划步骤、调用工具、观察结果、调整策略,直到把事情做完。
这套机制的核心是 ReAct 循环(Reasoning + Acting):先思考,再行动,观察结果,再思考下一步。但 Nephele 还会在这之前做一个快速规则检查——如果是很明确的简单指令,直接执行,不浪费 LLM 算力。
两条执行路径
Agent 处理你的请求时,会优先走第一条路径,走不通才进入第二条:
路径一:规则引擎(零延迟)
对于"打开 Chrome"、"列出桌面文件"这类意图明确的简单命令,Agent 先用内置的规则引擎直接解析,匹配到对应工具就立即执行。全程不调用 LLM,响应是瞬时的。
路径二:ReAct 循环(LLM 推理)
复杂或模糊的请求进入 ReAct 循环。Agent 和 LLM 之间多轮交互,每轮 LLM 决定调用什么工具,Agent 执行后把结果喂回去,直到任务完成或达到上限。
| 规则引擎 | ReAct 循环 | |
|---|---|---|
| 延迟 | 毫秒级 | 秒级(取决于模型和网络) |
| 使用 LLM | 否 | 是 |
| 适合场景 | 明确的开/关/查指令 | 分析、创作、多步任务 |
| 工具调用次数 | 1 次 | 最多 20 次 |
三种工作模式
Agent 根据你的设置选择模型来源:
| 模式 | 模型 | 规则引擎 | LLM 推理 | 特殊工具 |
|---|---|---|---|---|
| LOCAL | 本地 Ollama | ✅ | ✅ ReAct | 无 |
| CLOUD | 云端 Axioma Breeze | ✅ | ✅ ReAct | 无 |
| CLOUD_MAX | 云端 Axioma Breeze | ✅ | ✅ ReAct | cloud_search(实时搜索) |
提示
LOCAL 模式完全离线,数据不出设备。CLOUD 和 CLOUD_MAX 需要联网,消耗疲劳值(Stamina)。疲劳值每日自动恢复,用完后可切换到**云晶(Credits)**双池计费继续用。
LOCAL 与云端的本质区别
不是"有没有网络",而是模型跑在哪里:
- LOCAL:Ollama 运行在本地,上下文窗口约 8K,由本地的 Token 预算和自动压缩机制管理长度。
- CLOUD / CLOUD_MAX:请求发送到 Nephele 云端服务,由云端管理上下文。输出上限 8192 tokens,最大 20 轮工具调用。
两者的 ReAct 循环结构是一样的,但本地模式多了一些针对 8B 小模型的保护机制(如 Token 预算、重复调用检测)。
ReAct 循环:一步一脚印
以 LOCAL 模式为例,一次完整的 ReAct 交互如下:
- 构建请求 —— 把 system prompt(含工具说明、用户记忆、当前时间)+ 对话历史 + 你的新消息打包发给 Ollama
- 流式接收 —— Ollama 返回思维链(thinking)和正文(content),Agent 实时转发给 UI
- 工具调用 —— 如果 LLM 决定调用工具,Agent 执行工具,把结果格式化后追加到对话历史
- 循环判断 —— 任务没完成就回到第 1 步,继续下一轮
CLOUD_MAX 模式的流程相同,只是换成了向 Nephele API 发送 SSE 流式请求,并且支持一次收集多个工具调用再批量执行(解决早期多工具丢失的 bug)。
迭代上限
两种模式的硬上限都是 20 次工具调用。达到上限后 Agent 会停止并告知你"任务可能未完全完成"。
停止机制
你可以随时点击停止按钮,Agent 会在以下位置检查取消信号:
- 每轮迭代开始前
- SSE 流接收过程中
- 串行工具执行间隙
停止后,已执行的工具结果不会被撤销,但后续工具调用会取消。
Token 管理(LOCAL 模式特有)
本地 8B 模型的上下文窗口有限,Agent 会自动管理对话长度:
| 阈值 | 行为 |
|---|---|
| 4800 tokens | 触发自动压缩:保留 system prompt + 最近 4 条消息,中间历史折叠成摘要 |
| 5500 tokens | 软限制:下轮请求注入"请简洁回答"的提示 |
| 7000 tokens | 硬限制:禁用工具,强制 LLM 直接总结并结束 |
压缩有断路器保护:如果连续 3 次压缩后仍超过阈值,直接强制总结,防止无限循环。
技巧
CLOUD 和 CLOUD_MAX 模式没有这些本地 Token 限制,上下文由 Nephele 云端服务管理。
工具系统
意图感知的工具加载
Agent 不会一次性把所有 53 个工具的详细参数都塞给 LLM,而是按需加载:
- LOCAL 模式:根据你的输入关键词,ToolRegistry 只筛选相关工具的 schema。比如提到"浏览器"就加载浏览器工具,提到"Python"就加载脚本工具。无关工具只列名字,不占 token。
- CLOUD_MAX 模式:初始只加载 Tier 1 核心工具(约 10 个常工具 +
tool_search)。其他工具在<available-tools>块里按类别列名字。LLM 需要时调用tool_search动态加载具体 schema。这会把每轮输入 token 从约 3000 降到约 500。
并行执行
如果一轮里 LLM 要求调用多个工具,Agent 会判断哪些可以并行:
- LOCAL 模式:只有 6 个只读工具可以并行(
read_file、search_files、grep_content、web_fetch、browser_snapshot、eagle_search),其余串行。 - CLOUD_MAX 模式:根据每个工具自身的
concurrency_safe属性决定,并行工具用 ThreadPoolExecutor(最多 4 个线程)同时执行。
run_python 永远不会被并行,且执行前需要你在弹窗中确认代码内容(可编辑)。
记忆系统
Agent 的记忆分两层,都存储在本地 ~/.nephele_workshop/memory/:
用户画像(MEMORY.md)
Agent 通过 memory_update 工具把你在对话中提到的偏好写入这里,例如:
- 创作风格(赛博朋克、水墨风等)
- 常用发布平台
- 个人习惯设置
最大 1500 字符,超过会截断。只有写入过实际内容的画像才会注入 system prompt,默认空模板不占 token。
最近对话日志
每天一个文件,记录对话摘要(如"[上下文压缩] 用户要求整理插画")。Agent 加载最近 2 天的日志,最大 1000 字符。
技巧
你可以在设置里关闭记忆功能,或一键重置画像。LOCAL 模式下所有记忆只存在于本地设备。
子 Agent 委派
遇到复杂任务时,Agent 可以调用 delegate_tasks 把任务拆成多个子任务。每个子任务由一个子 Agent 处理。
限制:
- 最多 6 个子任务
- 单个超时 120 秒
- CloudMAX 模式:真正并行(ThreadPoolExecutor,最多 4 个并发)
- 本地模式:串行执行(非并行)
子 Agent 有一些额外约束:
- 不能继续委派其他子 Agent(防止无限递归)
- 不能执行需要用户确认的操作(如
run_python)
内部还做了反模式检测:如果你要求找参考图,主 Agent 不应该用 delegate_tasks 拆成多个找图子任务,因为 find_references 内部已经并行搜索多个平台了。
安全与真实性约束
run_python 确认
执行 Python 代码前会弹出确认窗口,展示完整代码和描述。你可以取消、直接确认、或编辑后再确认。
图片压缩
Agent 接收图片附件时,会自动压缩到最长边 1536px、JPEG 质量 85%,减少 base64 传输体积和 token 消耗。GIF 等动画格式保持原样。
真实性硬约束(Cloud MAX)
Cloud MAX 的系统 prompt 中嵌入了最高优先级约束:
- 禁止编造任何 ID、URL、文件路径、图片信息
- 只能使用工具返回值中真实出现的数据
- 工具返回 0 结果时,如实告知"未找到",不要虚构数据填充
- 反搜 URL 必须经过
resolve_source_url解析才能作为"原作者"报告
工具错误自修正
工具失败后,Agent 会在结果前加上 [ERROR] 标签,并附加可操作的提示:
- "找不到文件" → 提示用
search_files确认路径 - "权限不足" → 提示尝试用户主目录下的路径
- "超时" → 提示可重试或换方式
事件流架构
Agent 不是"说完一段话再显示",而是实时流式输出:
- 思维链(thinking)实时显示
- 正文(content)逐字出现
- 工具调用开始/结束都有通知
- 配额、 stamina 消耗实时更新
Agent 核心通过纯生成器产出事件(AgentEvent 子类),再由 AgentWorker 转成 Qt Signal 发给 QML 界面。这种设计让 Agent 可以跑在后台线程,不会卡住 UI。
主要事件类型:
| 事件 | 说明 |
|---|---|
StreamChunk | 正文文本片段 |
ThinkingChunk | 思维链片段 |
ToolStart | 工具开始执行 |
ToolFinish | 工具执行完成(含成功/失败状态和结果) |
NavigateView | 需要切换界面视图 |
RateLimitUpdate | 疲劳值配额更新 |
StaminaCost | 单次请求 stamina 消耗 |
CreditsUpdate | 云晶余额更新 |
LoopError | 循环出错(网络/认证/服务不可用) |
LoopDone | 一轮对话完成 |
操作日志与撤销
每轮 Agent 对话会被记录到 OperationJournal,生成一个唯一 round ID。完成时会在消息末尾注入 <!--UNDO:round_id--> 标记。这意味着某些操作未来可能支持撤销(目前标记已埋入,UI 层待实现)。