SONETTOHERE · v4.0.0
自研 Agent
一个装在本机的 ReAct Agent:能对话,也能读文件、跑代码、查网络、看屏幕点鼠标。这一页先讲我交付了什么、怎么证明,再讲技术细节——给 HR 和业务方看前面就够,想看实现往下翻。
先看这里:我交付了什么
Highlights如果只有 30 秒,先看这四条——不堆技术词,讲清楚「我做了什么、解决了什么、怎么证明」。
- 交付主导把一个开源 Agent 改造成能交付、能演示、重启不丢数据的本地版本——能读文件、跑代码、查网络、开浏览器、看屏幕点鼠标。
- 解决真实缺陷视觉模型接口被写死成非流式、恒报错,我定位后改成流式聚合,让「看屏幕 → 点击 → 输入 → 核对」整条链路第一次跑通。
- 工程闭环补齐持久化、附件拖拽、一键启停、端到端计时账本,并搭出一套 10 项验收矩阵 + 3 个可现场复演的演示案例。
- 证据与诚实每条结论都留脚本与 JSON 证据、能重跑;没跑过的项明确标 NOT_RUN,TTFT 标注样本量,不夸大。
DDZZzzz 本地改造版 · Local Agent
装在本机、记得住你、还能自己动手的 Agent
一个跑在本地电脑上的 ReAct AI Agent:既能聊天,也能读文件、跑代码、查网络、开浏览器、看屏幕点鼠标。模型可换、工具可插、记忆存在自己硬盘里。
- 47个
- 内置工具,覆盖 10 个工具域
- 4种
- MCP 传输:stdio / SSE / HTTP / WebSocket
- 9类
- 长期记忆主题(湾流 V6)
- ≈4.8万行
- 自有代码量(不含依赖与构建产物)
我在这个项目里做了什么
My changes底座是开源项目,所以我把「上游原有」和「本人改动」拆开写。下面六项是我这一轮实际落的代码与脚本,每条都标了落在哪个文件。
- 01会话与消息持久化标准库 sqlite3 落盘:会话元信息、消息快照、附件产物索引。重启后历史仍在,意外中断的任务标 INTERRUPTED 而不冒充完成。
api/persistence/store.py(新增)+ session/manager + agent/turn + server - 02视觉委托链路修通网关对视觉模型强制返回 SSE 分块,原代码用非流式解析,恒报 Unexpected response type。改成流式聚合后,截屏理解 → 点击 → 输入 → 截图核对全流程跑通。
api/agent/vision.py(ainvoke → astream) - 03附件拖拽上传浏览器默认会在拖入文件时直接打开它。拦截 drop 事件、新增上传端点、把落盘路径转成文件引用再交给 Agent。
api/routes/files.py + ChatInput.vue + api/files.ts - 04一键启动 / 停止按端口 + 命令行关键字判断进程归属,只停自己的进程,不误杀同端口的其他服务;日志做脱敏。
Start-DDZZzzz.ps1 / Stop-DDZZzzz.ps1 - 05端到端计时账本单调时钟记录 TTFT 与回合级耗时,把「感觉快」换成可复核的数字(3 次样本中位 5.547s,小样本不外推)。
api/agent/timing.py - 06验收矩阵与演示材料10 项验收逐条跑脚本取证,配三个演示案例(改 bug / 比文档 / 视觉点击)与讲解口径文档。
artifacts/day-use-20261017/、artifacts/demo-cases/
关于「自研」的口径:底座 SonettoHere 为 开源项目(作者 Miso2233,MIT 许可),本项目是在其之上的本地改造与能力增强,不是从零原创;开发过程全程有 AI 编程助手参与,我负责目标、方案、架构取舍、代码审查与验收标准。外部模型(DeepSeek / GLM 等)是调用,不是自研模型。
三个实测案例
Verified demos都能现场复演:输入准备成脚本,跑坏了有一条命令重置回缺陷态。
- C1
代码任务:定位并修好一个真实缺陷
calc.py 里折扣算反了:满 100 本该打 9 折,实际乘了 1.1;判断还漏了等于号。
- 读 calc.py 与 test_calc.py,跑 unittest——3 个测试失败
- 定位 apply_discount:`>` 应为 `>=`,`* 1.1` 应为 `* 0.9`
- 改文件、重跑测试——4 个全过,diff 可核对
4/4 通过;缺陷态可一键重置(reset_demo.py),现场能重复演
- C2
文件任务:两份文档的差异比对
同一份产品说明的 A / B 两版,定价、功能、退款政策都有出入,B 版还漏了客服邮箱。
- 把两份文件拖进输入框(走的是我补的拖拽上传链路)
- 逐段比对,指出每处差异在原文的位置
- 生成 Markdown 报告并落盘,缺失项标成「未知」而不是猜
报告与来源逐条对得上;产物重启后仍能打开(持久化生效)
- C3
视觉任务:看屏幕 → 点击 → 打字 → 核对
桌面上的 GUI 测试页,需要点按钮拿校验码、填进输入框、提交后自检。
- 截屏,交给视觉模型识别按钮位置与校验码
- 先虚拟点击预演落点,确认后真实点击
- 中文输入走剪贴板粘贴,最后截图核对状态
截图可见结果「校验通过」;证据链含调用记录与前后截图
怎么证明它真的跑起来了
Evidence不靠截图说「已完成」,每条都留脚本与 JSON 证据,能重跑。
- 9/9工具激活真实图执行
真实 build_agent + MemorySaver 跑完整 LangGraph 图:首轮排除 MCP schema → 激活 → 第二轮带上 → 执行 → 收敛。
- 6/6主链路接线
从真实 run_agent_turn 入口进,验证动态激活在真实对话链路上同样生效。
- 9/9MCP 会话隔离
两个聊天各用各的浏览器会话:A 的状态不串到 B,A 关闭后旧引用明确报错而不改道。
- 9/9回归不退化
缓存归属、长结果不二次裁剪、嵌套技能停用、目录 ZIP 导入、用量缺失字段计数等九项。
它是什么
What it isSonettoHere 是一个本地运行的 Agent 客户端:后端 FastAPI 负责 Agent 编排与工具执行,前端 Vue 3 负责对话界面,两边用 WebSocket 做流式推送。它不像网页聊天框那样只能「说」,而是有一整套工具层——文件读写、Python 执行、网络搜索、地图、待办、浏览器 MCP、屏幕操作——所以「改一个 bug」「比对两份文档」「点一下屏幕上的按钮」这类任务,它能自己走完全程。
底座是开源项目 SonettoHere(MIT)。我在它之上做的是「把它变成一个能演示、能验收、重启不丢数据」的本地版本:补了持久化、打通了视觉委托、修了网关侧的流式解析缺陷、重做了启动脚本与验收证据链。下面凡是写「我做的」,都能在代码和提交里对上;底座部分我会明确标成上游。
- Vue 3
- FastAPI
- LangChain
- LangGraph
- WebSocket
- SQLite
- MCP
- Playwright
- PySide6
跑起来要三步
- 1
python setup_guide.py六步初始化:环境 / 依赖 / .env / 提供商 / 人设 - 2
配置 Base URL + API Key任意 OpenAI 兼容端点,推荐 DeepSeek - 3
start.bat拉起后端 + 前端,浏览器打开 localhost:5173
它能做什么
Capabilities- 代码任务闭环Code
读源码 → 定位缺陷 → 改文件 → 跑测试 → 展示 diff。工具层直接调 Python 执行环境,输出实时流式回显,可中途停止。
- file_read / edit
- run_python
- 实时输出
- 联网与地图Network
Tavily 搜索与网页提取、天气、节假日、图片理解,以及高德周边搜索 / 路线规划 / 地址解析。
- Tavily
- 高德 API
- 图片理解
- 待办与任务追踪Todo
Todoist 全量读写(任务 / 项目 / 分区 / 标签),加无状态任务清单追踪:多步任务有进度、能收敛。
- Todoist
- Task Tracker
- MCP 外部工具MCP
改 YAML 即接入外部服务器,四种传输全支持;工具名自动加前缀,热加载不用重启后端。
- stdio
- SSE
- 热加载
- 子 Agent 与后台任务Sub-agent
复杂子任务派给独立会话并行跑,长耗时工具(搜索 / 执行 / 读图)转后台,主对话用 await 取回结果。
- 后台运行
- 独立消息流
- 并行
- 技能与宏Skill / Macro
Skills 是可自主识别的技能包(Markdown + 脚本);Macros 更轻,`!名称` 触发,把私人流程固化成一条指令。
- SKILL.md
- !macro
- 可自写
- 长期记忆Memory
跨会话积累对你的了解:异步提炼、九大主题、双向关联检索;私密模式不写、失忆模式不读。
- 湾流 V6
- 写入复核
- 纯本地
- 屏幕操作Computer Use
截屏 → 视觉定位 → 虚拟点击预演 → 真实点击 / 中文输入。主模型不支持视觉时,交给视觉模型做委托识别。
- PySide6 边缘灯
- 视觉委托
- 显式开关
一条消息怎么走完
Architecture从按下回车到工具真的执行,中间是一张 LangGraph 的 ReAct 图在跑:模型节点产出工具调用,工具节点执行后回到模型,直到不再要求调用为止(单轮上限 120 次)。
- 01前端 ChatInput拖入文件 / @技能 / #工具 组装上下文
- 02WebSocket/ws/chat/{session_id} 双向流式通道
- 03run_agent_turn解析 LLM → 建图 → 流式执行 → 后处理
- 04LangGraph ReActmodel 节点产 tool_calls ⇄ tools 节点执行
- 05事件回流回调把 token / 工具结果推回界面渲染
挂在主链路上的三条支线
每轮结束后由独立记忆 Agent 异步提炼,写入本地 YAML;九大主题强制校验,条目可双向关联。
内置工具 + 外部 MCP 服务器;工具名带 server 前缀避免撞名,执行资源按 (聊天, 服务器) 归属。
本机网关统一路由多个账号,token 自动同步;主模型换成任何 OpenAI 兼容端点即可。
几个刻意的取舍
Trade-offs| 环节 | 选择 | 为什么 |
|---|---|---|
| 持久化选型 | 标准库 sqlite3 | LangGraph 检查点续跑改造面大、风险高;sqlite3 零新依赖、可控,先满足「重启能找回历史」这条底线。 |
| 落盘时机 | 每轮结束写快照 | 与图执行解耦,写盘失败不阻断主对话。 |
| 视觉模型 | 固定 glm-5v-turbo | 网关里的 glm-4.6v 是僵尸条目,实测报 11102 不可用,选型以实测为准。 |
| 启停脚本 | 端口 + 命令行双判定 | 只看端口会误杀同端口的其他服务;必须确认进程确实属于本项目才动手。 |
没做到的部分,也写在这里
Limits- 真实模型 API、HTTP 端点、浏览器 UI、Windows 进程生命周期这几项在本轮验收里标 NOT_RUN——需要对应运行环境,没有跑就不写「通过」。
- 任务续跑(断点恢复接着跑)未实现:现在能找回历史消息,但不能把中断的那一轮接着执行。
- TTFT 中位 5.547s 来自 3 次样本,只说明当时链路能跑,不作为稳定性或 P95 承诺。
- 屏幕操作是不可撤销的真实动作,默认关闭;开启后屏幕边缘亮灯提示,标准流程要求先虚拟点击预演落点。
想直接看代码或自己跑一遍,入口在上游仓库: SonettoHere;本项目为其本地改造版,配置与记忆全部留在本机,演示数据均已脱敏。