Files
projectAIpopular/实现方案_v4_模型池与工具智能体.md
tzt 747d85c3ba feat(v3): T29 收尾 + T31 dsh 功能对齐
T29 流式收尾:
- _stream_partial 每次流式调用前复位(防上次成功置位导致本次失败误抛不回退)

T31 dsh(deepseek-harness)功能对齐:
- OpenAICompatChat 重试退避:传输错误/408/429/5xx 指数退避(max_retries=2),4xx 不重试
- web_fetch 工具:公网 http/https 抓取,SSRF 防护(DNS 后拒绝私网/环回/链路本地/NAT64,
  512KB/15s/12k 上限,二进制嗅探拒绝),agent.allow_net 开关(默认开)
- 原子写入:write_file/edit_file 临时文件 + os.replace(Windows EPERM 退避)
- 慢工具线程卸载:run_command/web_fetch/search_files 独立线程 + asyncio.sleep 轮询
- search_files:os.walk 修剪依赖目录(替代 rglob 全量物化),不跟随符号链接
- run_command:危险命令黑名单独立拦截 + 显式 COMSPEC/sh 解释器执行
- 重复调用提醒:同工具同参数第 3 次起回喂系统提示 + repeat_warning 事件
- 会话重命名:PATCH /agent/sessions/{sid} + 前端 ✎
- 前端:SettingsView 适配密钥打码(留空保留),SPA 重新构建
- 新增 tests/test_agent_features.py(9 项);全量 318 测试通过
2026-09-02 00:02:24 +08:00

180 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 实现方案 v4:模型池与工具智能体
> 编写日期:2026-09git 记录)
> 状态:**当前权威增补方案**。在 v2(端云协同协作)/ v3(Web 应用化)基础上两个升级:
> ①「端云」叙事泛化为**多价位模型池**;② 新增 **zcode 式工具智能体**(模型操作工作区文件)。
> 前置:v3 已落地(异步 /chat + SSE + Vue SPA262 项测试全绿)。
---
## 0. 一页速览
- **模型池**`gateway/model_pool.py` 维护多价位异构模型条目(`local / budget / premium` 三档,
每条目 = 端点 + 凭据 + 模型名 + 单价 $/1M tokens),`roles` 把条目指派给
architect / worker / agent 三个角色;留空 = 沿用经典单模型设置(向后兼容)。
`build_v2_pipeline` 池指派优先;`V2Stats` 新增按模型 token/成本分账(`by_model`)。
- **工具智能体**`router_system/tools.py`(纯标准库)提供 WorkspaceTools
list_dir / read_file / write_file / **edit_file / search_files / run_command**
路径关押在根目录内)与 ToolLoop(通用工具循环,轮数 + token 双护栏,逐事件回调);
`gateway/agent.py` 提供 OpenAI 兼容工具调用客户端与运行服务
(事件落盘 `agent_runs/{id}/events.jsonl`),`/agent` 端点 + SSE 实时推送。
- **可选择工作目录**(参考 deepseek-harness 的"打开文件夹"体验):智能体可作用于
用户从磁盘上选择的任意项目目录(`/agent/fs` 目录浏览 + `/agent/workspaces` 最近列表),
运行记录所用目录;`run_command` 默认关闭(allow_shell 开关),开启后在工作区内执行命令
(超时熔断 + 输出截断 + Windows CREATE_NO_WINDOW)。
- **工程约束不变**`router_system` 零第三方依赖;测试全部封闭(httpx 注入/假实现);
不上分布式中间件;金额护栏沿用 api_token_cap 思想(agent 有独立 token_cap)。
## 1. 设计决策(D1–D6,不得推翻)
- **D1 价位为主轴,位置为属性**:系统按"模型成本档位"组织协作,不按"端/云"位置。
本地 llama.cpp 是 local(零边际成本)档;云端按单价分 budget / premium。
「端云协同」成为两档部署特例,命题叙事不改、系统叙事升级。
- **D2 池条目存配置不存权重**:云端模型只存端点/凭据/单价元数据;本地模型经
llama_manager 管理 .gguf。api_key 服务端持久化、接口打码返回(`api_key_set` + 前 6 位)。
- **D3 角色指派可热切换**`PUT /pool/roles``rebuild_pipeline()` 立即生效;
测试注入 `worker_cfg_override` 优先级最高(保测试封闭)。
- **D4 工具被关押在根目录**:所有路径 join 后 resolve,必须仍位于工作区根内
(防 `../` 与绝对路径逃逸);读取/写入/编辑均有长度与唯一性约束
edit_file 的 old_string 必须唯一命中,歧义即拒绝);search_files 跳过依赖/构建目录与
二进制大文件。工作区根本身可由用户选择("打开文件夹"),关押相对所选根生效。
- **D5 智能体双护栏 + shell 默认关**:轮数上限(agent.max_rounds,默认 8+
token 熔断(agent.token_cap,默认 20000);`run_command` 受 allow_shell 开关(默认关),
开启后有 shell_timeout_s 超时与输出截断;触顶强制总结,不再给工具。
- **D6 事件文件为单一事实源**:智能体过程逐条追加 events.jsonl,SSE 生成器轮询增量推送
(晚加入者从头回放);前端收到 final 即关闭连接并忽略后续回放,防止重复渲染。
## 2. 接口清单(新增)
| 端点 | 说明 |
|---|---|
| `GET /pool` | 池全量(roles + entrieskey 打码) |
| `POST /pool` | 新增/更新条目(api_key 留空 = 保留原值) |
| `DELETE /pool/{id}` | 删除条目(角色指派联动清空) |
| `PUT /pool/roles` | 角色指派(architect/worker/agent → 条目 id 或空串) |
| `POST /pool/{id}/test``GET /pool/{id}/models` | 条目连通测试 / 模型列表探测 |
| `POST /agent` | 提交任务 `{task, pool_id?, workspace?}`workspace 为所选工作目录 |
| `GET /agent/{id}/status` `/events` `/stream`(SSE) | 状态(含所用工作目录)/ 全量事件 / 实时流 |
| `GET /agent/workspace?path=&root=``GET /agent/file?path=&root=` | 工作区浏览/读取(root 指定所选目录) |
| `GET /agent/fs?path=` | 目录选择器:浏览本地目录(只列子目录,空 path 列盘符) |
| `GET /agent/workspaces``POST /agent/workspaces` | 当前+最近工作区 / 打开(可 create 新建)并设为当前 |
`/config/models``/config/ping` 抽出共用 `_list_backend_models` / `_probe_backend`
## 3. 前端(v3 四页基础上)
- 设置页新增「🗄️ 模型池」区块:三角色指派下拉、条目表格(档位徽标/单价/启用/测试/编辑/删除)、
内联添加表单(模型列表探测 datalist)。
- 新增「🤖 智能体」页(`/agent`):任务输入 + 模型选择(池条目)、工具调用时间轴
round / tool_call / tool_result / usage / final)、左侧工作区文件浏览与预览。
- 指标页新增「按模型分账」卡片(by_model 表格)。
## 4. 任务登记(T16T21,衔接 v2 表 T15 之后)
| T | 内容 | 状态 |
|---|------|------|
| T16 | 工具内核 `router_system/tools.py` + `tests/test_tools.py`11 项) | ✅ |
| T17 | 模型池 `gateway/model_pool.py` + `/pool` 端点 + 管线池解析 + by_model 分账 + 测试 | ✅ |
| T18 | 智能体 `gateway/agent.py` + `/agent` 端点(SSE)+ 测试(含越界/校验/池指派) | ✅ |
| T19 | 前端 API 层 + 设置页模型池 UI | ✅ |
| T20 | 智能体页 AgentView + 指标页分账卡 + SSE 终态去重 | ✅ |
| T21 | 集成验证:真跑 3 轮工具任务(写/列/读)+ 全量 262 测试 + 浏览器实测 | ✅ |
| T22 | 工具扩展(harness 风格):edit_file 唯一替换 / search_files 跨文件搜索 / run_commandopt-in | ✅ |
| T23 | 工作区选择:/agent/fs 目录浏览 + 最近工作区 + /agent 带 workspace + 状态记录目录 | ✅ |
| T24 | 前端:工作区选择栏(目录浏览器模态/最近/shell 开关)+ edit diff 卡 + 命令卡 | ✅ |
| T25 | 集成验证:选定真实目录跑"读→精确编辑→运行验证"全链路 + 274 测试全绿 | ✅ |
## 5. 实验设计建议(论文用)
- **位置无关性**:同一 Worker 角色分别绑 localllama.cpp)与 budget(低价 API),
跑同一数据集对比 token/成本/质量——证明架构"价位驱动"而非"位置驱动"。
- **价位帕累托曲线**agent/worker 角色在 local→budget→premium 间切换,
画成本–质量帕累托图(metrics 的 by_model 直接供数)。
## 6. 运行时目录(均 gitignore
`config/model_pool.json`(池持久化)、`agent_runs/{id}/`events.jsonl + status.json)、
`agent_workspace/`(智能体默认工作区,可在设置 agent.workspace_dir 调整)。
## 7. 增补:两级智能体(D7,T26)
- **决策 D7(价位协作延伸到智能体形态)**:`POST /agent` 支持 `executor_pool_id`——
规划者(大模型:agent 角色或经典 Architect 设置)负责拆解指令与审查裁决;
执行者(本地小模型:llama_server/openai 池条目)负责工具轮;中间状态写
`agent_runs/{id}/handoff.json`(智能体版"交流文本"instructions/acceptance/exchanges)。
- **协议**:规划者两阶段 JSONplan: instructions+acceptancereview: verdict done|redo +
reply_to_executor + final_answer),解析失败回喂重试一次再降级(对齐仓库 JSON 纪律);
redo 时裁决意见作为执行者下一轮指令,交接上限 `agent.max_handoffs`(默认 2)。
- **护栏**:规划者与执行者不得为同一池条目;执行轮 token 与整体 token_cap 共享预算;
ToolLoop 内层循环 `emit_final=False`,终态事件由外层编排统一发出(防前端 SSE 提前收口)。
- **事件**:新增 `phase`plan/execute/review,带模型名)与 `message`planner/executor 正文)
两类事件,前端以阶段徽标 + 双色消息卡渲染。
## 8. 增补:会话式智能体(D8,T27)
- **决策 D8(对齐 dsh 的会话范式)**:智能体从"一次性任务"升级为**多轮会话**——
`POST /agent/sessions` 建会话(绑定工作区/执行者配置),后续任务带 `session_id`
递交,既往轮次折叠为对话历史注入模型(近 6 轮,每条截断 1500 字);
轮次(任务/答复/工具步数/token)持久化到 `agent_runs/sessions/{sid}.json`
- **停止**`POST /agent/{id}/cancel` 取消运行中任务(asyncio cancel + 状态标记
cancelled_by_user)。
- **前端**AgentView 重构为 dsh 式对话界面——左侧会话列表、居中消息流
(用户蓝气泡 / 助手白卡)、底部 composer(工作区/执行者/命令开关收为 chips,
Enter 发送,运行中变红色停止钮);工具过程折叠收纳,历史轮次仅显示步数摘要。
- **工程**ToolLoop 增 history 参数;工具步数统一在事件写入层统计;
会话存储测试隔离(防泄漏进真实 agent_runs/sessions/)。
## 9. 增补:审批流与流式输出(D9/D10T28/T29
- **决策 D9(操作审批,对齐 dsh)**:`agent.approval_policy` = off | dangerous(默认:
写/编辑/命令询问,只读自动放行)| all;工具执行前经 approval_hook 挂起等待,
UI 两按钮(拒绝 / 允许一次),超时 `approval_timeout_s`(默认 120s)自动拒绝
fail-closed);拒绝结果回喂模型可改道;approval_request/decided 事件对入审计。
- **决策 D10token 级流式)**OpenAICompatChat 默认 stream=TrueSSE 逐段解析,
tool_calls 碎片按 index 组装、不在正文展示;include_usage 计量);流式失败自动
回退非流式一次(已有部分增量输出时如实抛出);ToolLoop 经 on_delta 转发,
DeltaThrottle ≥48 字符节流落 delta 事件;前端打字机式实时渲染 + 光标。
- **配套修复**:Vue 响应式丢失 bug——闭包持有 push 前原始对象导致过程事件不渲染,
改取响应式代理对象。
## 10. 增补:安全基线(D11T30,Mimosa 深度扫描驱动)
- **决策 D11(默认最小暴露面)**:
- **路径参数 ID 白名单**`/runs|/agent|/agent/sessions` 的路径参数只允许
`[a-zA-Z0-9_-]{1,64}`(系统生成 ID 的字符集),非法一律 404——杀灭 Windows
反斜杠穿越变体(如 `/runs/x/artifacts/..%5C..%5C..%5C.env` 直读 .env)。
- **工件双重关押**:artifacts 端点解析后必须仍在 artifacts 目录内;pipeline
`_save_artifact`/`_read_artifact` 对模型输出的工件名消毒(剥路径成分)。
- **下载关押**`/llama/download` 的 dest 解析后必须位于 models/ 内;URL 协议
白名单 http/https 在 HF 别名转换**之前**判定(防 file:/// 被拼成 HF 地址)。
- **密钥打码**GET /config 的 architect.api_key 只回前 6 位 + api_key_set
PUT 空串/缺省=保留原值(对齐 D2 池条目语义,前端"已设置,留空保留")。
- **Web 信任围栏**TrustedHostMiddleware 默认只信 localhost/127.0.0.1/[::1]
GATEWAY_TRUSTED_HOSTS 可覆盖,"*"=放行全部),防 DNS rebinding 打到本网关;
api.py `__main__` 默认绑定 127.0.0.1scripts/serve.py 本就如此)。
- **独立命令拦截**run_command 危险模式黑名单(format / rd /s / rm -rf / /
shutdown / curl|sh 等)先于审批独立拦截;shell 经显式 `"%COMSPEC%" /c` /
`/bin/sh -c` 执行(语义同 shell=True,但解释器路径受控)。
- **CSPRNG**review 抽样缺省随机源改 random.SystemRandom。
## 11. 增补:dsh 功能对齐(D12T31)
- **决策 D12(对齐 deepseek-harness 的健壮性功能)**
- **重试退避**OpenAICompatChat 非流式路径(含流式失败回退)对传输错误/
408/429/5xx 指数退避重试(max_retries=2、retry_delay_s=1.0);4xx 不重试。
- **web_fetch 工具**:抓公网 http/https 文本,dsh web_fetch 同款 SSRF 防护——
DNS 解析后拒绝私网/环回/链路本地/保留/NAT64 地址;512KB/15s/12k 字符上限、
二进制嗅探拒绝;受 `agent.allow_net` 开关(默认开),归入只读工具集。
- **原子写入**write_file/edit_file 走同目录临时文件 + os.replaceWindows
EPERM 退避一次后降级直写),防崩溃留半截文件。
- **慢工具线程卸载**run_command/web_fetch/search_files 在独立守护线程执行
asyncio.sleep 轮询等完成——补丁版 TestClient 的每请求独立事件循环不推进
run_in_executor 桥接,轮询在生产/测试两端都可靠),快工具保持内联。
- **search 修剪**os.walk 修剪依赖/构建目录(替代 rglob 全量物化),不跟随
符号链接目录,限量行为不变。
- **重复调用提醒**:同工具同参数第 3 次起在回喂结果附系统提示 + repeat_warning
事件(防模型原地打转,dsh repeat-tool-reminder 同款)。
- **会话重命名**`PATCH /agent/sessions/{sid}` + 前端会话列表 ✎ 按钮。
- **D10 收尾修复**_stream_partial 每次流式调用前复位(防上次成功置位导致
本次失败误抛而不回退)。