跳到正文
朱贵龙· DATA ANALYST
正在加载数据工作台…
DATA ANALYSIS SYSTEM
Initializing...42%
朱贵龙
返回首页

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

底座是开源项目,所以我把「上游原有」和「本人改动」拆开写。下面六项是我这一轮实际落的代码与脚本,每条都标了落在哪个文件。

  1. 01会话与消息持久化标准库 sqlite3 落盘:会话元信息、消息快照、附件产物索引。重启后历史仍在,意外中断的任务标 INTERRUPTED 而不冒充完成。api/persistence/store.py(新增)+ session/manager + agent/turn + server
  2. 02视觉委托链路修通网关对视觉模型强制返回 SSE 分块,原代码用非流式解析,恒报 Unexpected response type。改成流式聚合后,截屏理解 → 点击 → 输入 → 截图核对全流程跑通。api/agent/vision.py(ainvoke → astream)
  3. 03附件拖拽上传浏览器默认会在拖入文件时直接打开它。拦截 drop 事件、新增上传端点、把落盘路径转成文件引用再交给 Agent。api/routes/files.py + ChatInput.vue + api/files.ts
  4. 04一键启动 / 停止按端口 + 命令行关键字判断进程归属,只停自己的进程,不误杀同端口的其他服务;日志做脱敏。Start-DDZZzzz.ps1 / Stop-DDZZzzz.ps1
  5. 05端到端计时账本单调时钟记录 TTFT 与回合级耗时,把「感觉快」换成可复核的数字(3 次样本中位 5.547s,小样本不外推)。api/agent/timing.py
  6. 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;判断还漏了等于号。

    1. 读 calc.py 与 test_calc.py,跑 unittest——3 个测试失败
    2. 定位 apply_discount:`>` 应为 `>=`,`* 1.1` 应为 `* 0.9`
    3. 改文件、重跑测试——4 个全过,diff 可核对

    4/4 通过;缺陷态可一键重置(reset_demo.py),现场能重复演

  • C2

    文件任务:两份文档的差异比对

    同一份产品说明的 A / B 两版,定价、功能、退款政策都有出入,B 版还漏了客服邮箱。

    1. 把两份文件拖进输入框(走的是我补的拖拽上传链路)
    2. 逐段比对,指出每处差异在原文的位置
    3. 生成 Markdown 报告并落盘,缺失项标成「未知」而不是猜

    报告与来源逐条对得上;产物重启后仍能打开(持久化生效)

  • C3

    视觉任务:看屏幕 → 点击 → 打字 → 核对

    桌面上的 GUI 测试页,需要点按钮拿校验码、填进输入框、提交后自检。

    1. 截屏,交给视觉模型识别按钮位置与校验码
    2. 先虚拟点击预演落点,确认后真实点击
    3. 中文输入走剪贴板粘贴,最后截图核对状态

    截图可见结果「校验通过」;证据链含调用记录与前后截图

怎么证明它真的跑起来了

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 is

SonettoHere 是一个本地运行的 Agent 客户端:后端 FastAPI 负责 Agent 编排与工具执行,前端 Vue 3 负责对话界面,两边用 WebSocket 做流式推送。它不像网页聊天框那样只能「说」,而是有一整套工具层——文件读写、Python 执行、网络搜索、地图、待办、浏览器 MCP、屏幕操作——所以「改一个 bug」「比对两份文档」「点一下屏幕上的按钮」这类任务,它能自己走完全程。

底座是开源项目 SonettoHere(MIT)。我在它之上做的是「把它变成一个能演示、能验收、重启不丢数据」的本地版本:补了持久化、打通了视觉委托、修了网关侧的流式解析缺陷、重做了启动脚本与验收证据链。下面凡是写「我做的」,都能在代码和提交里对上;底座部分我会明确标成上游。

  • Vue 3
  • FastAPI
  • LangChain
  • LangGraph
  • WebSocket
  • SQLite
  • MCP
  • Playwright
  • PySide6

跑起来要三步

  1. 1python setup_guide.py六步初始化:环境 / 依赖 / .env / 提供商 / 人设
  2. 2配置 Base URL + API Key任意 OpenAI 兼容端点,推荐 DeepSeek
  3. 3start.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 次)。

  1. 01前端 ChatInput拖入文件 / @技能 / #工具 组装上下文
  2. 02WebSocket/ws/chat/{session_id} 双向流式通道
  3. 03run_agent_turn解析 LLM → 建图 → 流式执行 → 后处理
  4. 04LangGraph ReActmodel 节点产 tool_calls ⇄ tools 节点执行
  5. 05事件回流回调把 token / 工具结果推回界面渲染

挂在主链路上的三条支线

湾流 V6 记忆

每轮结束后由独立记忆 Agent 异步提炼,写入本地 YAML;九大主题强制校验,条目可双向关联。

工具池 · MCP

内置工具 + 外部 MCP 服务器;工具名带 server 前缀避免撞名,执行资源按 (聊天, 服务器) 归属。

模型网关

本机网关统一路由多个账号,token 自动同步;主模型换成任何 OpenAI 兼容端点即可。

几个刻意的取舍

Trade-offs
环节选择为什么
持久化选型标准库 sqlite3LangGraph 检查点续跑改造面大、风险高;sqlite3 零新依赖、可控,先满足「重启能找回历史」这条底线。
落盘时机每轮结束写快照与图执行解耦,写盘失败不阻断主对话。
视觉模型固定 glm-5v-turbo网关里的 glm-4.6v 是僵尸条目,实测报 11102 不可用,选型以实测为准。
启停脚本端口 + 命令行双判定只看端口会误杀同端口的其他服务;必须确认进程确实属于本项目才动手。

没做到的部分,也写在这里

Limits
  • 真实模型 API、HTTP 端点、浏览器 UI、Windows 进程生命周期这几项在本轮验收里标 NOT_RUN——需要对应运行环境,没有跑就不写「通过」。
  • 任务续跑(断点恢复接着跑)未实现:现在能找回历史消息,但不能把中断的那一轮接着执行。
  • TTFT 中位 5.547s 来自 3 次样本,只说明当时链路能跑,不作为稳定性或 P95 承诺。
  • 屏幕操作是不可撤销的真实动作,默认关闭;开启后屏幕边缘亮灯提示,标准流程要求先虚拟点击预演落点。

想直接看代码或自己跑一遍,入口在上游仓库: SonettoHere;本项目为其本地改造版,配置与记忆全部留在本机,演示数据均已脱敏。