乐于分享
好东西不私藏

我给自己写了个桌面 AI 助手:40+ 技能、多 Agent 编排、上下文自动压缩

我给自己写了个桌面 AI 助手:40+ 技能、多 Agent 编排、上下文自动压缩

这篇文章想聊的不是"AI 又能做什么了",而是一个具体的工程问题:如果要把大模型真正塞进日常办公流程,桌面端这一侧需要写些什么代码。

一、起点:为什么非要做成桌面应用

一年前我的工作流大概是这样的:浏览器开着某个对话框,本地开着一堆 Word 和 Excel,中间靠 Ctrl+C / Ctrl+V 手动搬运。模型很聪明,但它看不见我的文件,也动不了我的文件。

这个断层带来两个具体的麻烦。

第一个是搬运成本。一份 80 页的 PDF,要么手动切成十几段贴进去,要么放弃。第二个是数据边界。合同、财务表、内部资料,粘贴进网页对话框这件事本身就让人心里打鼓。

于是有了 Sigma。定位很朴素——一个本地优先的桌面级 AI 助手:Electron 装在自己电脑上,Python 后端跑在 localhost,文件读写就在本机文件系统里发生,模型能力通过 API 拿,数据不做多余的旅行。

听起来简单,真正做下去会发现,难点全在"让模型可靠地干活"这件事上。

二、六层架构:每一层解决一个具体问题

先把整体摊开看。

自上而下六层,每层的存在都有明确理由:

用户层是 Electron 30 打包的 Windows 桌面端,另外挂了一个浏览器扩展。扩展的作用后面会讲到,它让 AI 能操作你已经登录过的真实浏览器,而不是另起一个干净的无痕窗口——这个差别在实际使用中相当关键。

前端层是 React 18 + TypeScript + Vite。除了对话面板,还有 Excalidraw 无限画布、项目文件树、多格式文档预览,以及代码 / Word / Excel 三套 Diff 视图。为什么要做 Diff?因为 AI 改文件这件事,人必须看得见改了什么。

服务层是 FastAPI + Uvicorn,跑在 localhost:8765。对话走 SSE 流式,浏览器桥接走 WebSocket,文件变更主动推送到前端。

引擎层是整个系统的心脏,四个模块:ToolLoop 工具循环、ContextManager 上下文管理、SkillManager 技能调度、CustomAgentManager 自定义 Agent 分发。这一层的代码量和调试时间,大概占了整个项目的六成。

能力层是 40 多个可插拔技能,从 Office 文档读写到视频合成。

外部服务这层则是各种 API:模型网关、微信开放平台、邮箱、企业工商数据等等。

架构图看着规整,但真正决定体验好坏的,是引擎层里那几个不太起眼的设计决策。

三、ToolLoop:模型不是一问一答

新手最容易误解的一点:以为 Agent 就是"模型输出一段 JSON,程序照着执行"。

实际上完成一个稍微复杂的任务,模型需要在思考 → 调用工具 → 观察结果 → 再思考这个环上转很多圈。让它转得又快又稳,就是 ToolLoop 要干的事。

几个我认为值得单独说的设计:

双协议共用一套循环。 Anthropic 的 Messages API 和 OpenAI 的 Chat Completions,在工具调用的报文结构、流式分片格式上都不一样。Sigma 在引擎层做了统一抽象,同一个技能定义自动导出两种 schema。换模型改配置即可,业务代码一行不动。

两级技能暴露。 这是省 Token 的关键。40 多个技能,如果把完整说明书全塞进系统提示,光是"使用手册"就要吃掉几万 Token。Sigma 的做法是先只注入一句话摘要,模型判断需要用某个技能时,才把那份技能的完整 skill.md 加载进上下文。相当于给模型一个目录,而不是一整套百科全书。

并行工具调度。 互不依赖的调用用 asyncio.gather 一次性发出去。读五个文件、搜三个关键词,都是并发完成的,不排队。

人在环中。 有个叫 ask_user 的工具——遇到方向不明确、有多个方案要选,模型可以主动弹出问卷,任务暂停等你回答。这比它自己瞎猜然后跑偏两千 Token 要划算得多。另外工具执行超过 15 秒会自动转入后台,前端不会卡死。

可追溯。 每次工具执行前后都做文件快照对比,生成 diff 推给前端。加上 TodoList 任务进度自动注入上下文——长任务最怕的就是模型跑到一半忘了自己在干什么。

四、上下文管理:让长任务不失忆

这一块是我踩坑最多的地方。

场景很典型:一个跨十几轮的任务,读了二十个文件,搜了五十次网页,工具返回的长文本不断堆积。到第十五轮的时候上下文爆了,模型开始胡言乱语,或者干脆报错。

Sigma 的处理逻辑是 compact_if_needed

  • 用量超过 50% 自动触发压缩:保留最近 2 轮完整交互,更早的消息交给 LLM 自己凝练成一份 800 字以内的摘要,跨请求持久化;
  • 用量到 80% 启动截断保护,强制裁剪,宁可丢细节也不让请求崩掉;
  • 全程有个 ContextTracker 做中英混合的 Token 估算,适配 1M / 200K 等不同窗口,用量百分比实时推到前端界面上——你能看见自己的上下文烧到哪儿了。

为什么摘要要交给 LLM 而不是写规则截断?因为规则不知道什么重要。一句"已确认客户要求交付 Word 而不是 PPT"可能只有二十个字,但丢了它整个任务就废了。

还有一个容易忽略的点:会话隔离。技能激活集合、文档缓存、历史摘要,全部按 session_id 隔离在内存里,客户端断开就取消任务。多开几个窗口干不同的活,互不干扰。

五、多 Agent:从聊天机器人到编排平台

单个 Agent 的上限很明显——上下文就那么大,任务一多就顾不过来。

所以 Sigma 后来演化成了一个编排平台:主 Agent 只管理解意图、拆解任务、汇总结果,真正的脏活派给子 Agent。

四种编排方式各有各的用处:

自定义 Agent 是给用户的口子。你可以创建一个专属 Agent,配上自己的人设提示词、工具白名单、甚至独立的模型配置。比如"企业尽调 Agent"只给它工商查询相关的工具,它就不会跑去写视频脚本。用 @ 提及触发,结果自动回注主会话。

sub_agent 解决并行问题。用 ThreadPoolExecutor 同时跑多个子 Agent,每个有独立上下文窗口,不占主对话的 Token。要读十五个文件、要同时改三个模块,派出去就行。

longread 专门对付超长文档。按 Token 数切片,片与片之间保留 10% 重叠防止信息断在接缝处,然后多个 Agent 分头读,最后汇总。

deep_research 是把并行用到极致的一个流水线,下面单独讲。

六、40+ 技能:一份声明教会模型新本事

技能系统的设计目标只有一个:加一个新能力,不应该是件麻烦事

具体实现是声明式的 BaseTool 基类。你只需要:

  1. 声明 name / description / parameters
  2. 实现 execute()
  3. 写一份 skill.md 说明书

剩下的框架全包了——参数必填与枚举校验、权限检查钩子、统一的 ToolResult 返回结构、双协议 schema 自动导出。

skill.md 这个设计我挺满意的。它本质上是用文档代替微调:模型没见过你的新工具,但它读得懂一份写清楚的使用说明。什么时候该用、参数怎么填、有哪些坑,写进 md 里按需注入,模型立刻就会了。

技能目前分五组,覆盖了办公场景里绝大部分重复劳动。其中有几个是我自己天天在用的:

  • 文档全文检索支持近义词扩展。搜"预算"能顺带把"费用""成本"一起搜出来,这个在翻旧资料时救了我不少次;
  • 浏览器自动化走的是前面提到的扩展通道,操作的是你已登录的真实浏览器,所以能干那些需要登录态的事;
  • 企业尽调把工商信息、股权结构、被执行 / 失信 / 限高记录一次拉全,签合同前跑一遍,比人工查快太多。

七、一个真实案例:深度调研流水线

讲完机制,看一个把这些东西全用上的场景。

deep_research 的完整链路是这样跑的:

第一步拆解。 输入一个主题,比如"某细分行业的竞争格局",系统自动拆成 6 个以上研究维度——市场规模、竞争格局、技术路线、政策环境、商业模式、风险因素。

第二步并行搜索。 每个维度派一个独立子 Agent,各自执行 10 次以上不同关键词的联网搜索。六个维度乘十次,一轮下来 60+ 次搜索,中英文关键词都试。这些子 Agent 上下文互相隔离,谁也不会污染谁。

第三步交叉验证。 汇总各维度结果,多源信息比对。这一步的价值在于:单一来源经常有错,三个来源都说同一个数字,可信度就完全不同。我特意让它区分"已确认"和"待核实",而不是把所有信息一律当真。

第四步交付。 输出结构化调研报告(Word)和汇报演示文稿(PPT),排版一次做完。

效率上的差别是量级的。这套流程人工做,一个人认真搜一天也就覆盖两三个维度;跑一遍 deep_research,分钟级出结果,而且搜索广度是人做不到的。

当然它不是万能的——公开信息里没有的东西它也搜不出来,专业判断仍然得靠人。它省掉的是"信息搜集"这段最枯燥的体力活。

八、几个踩过的坑

写在最后,可能比架构图更有参考价值。

Token 是真金白银,省它要从架构上省。 两级技能暴露、子 Agent 独立上下文、上下文自动压缩,这三个设计加起来省下的 Token,比任何提示词优化技巧都多一个数量级。

并行的收益比想象中大。 很多人做 Agent 只想着让模型更聪明,其实"同一轮把互不依赖的调用一次性发出去"这个简单改动,对体感速度的提升非常直接。

可视化不是锦上添花。 Token 用量条、TodoList 进度、文件 diff——这些东西看着是 UI 细节,实际上是信任的基础设施。你敢让 AI 改你的文件,前提是你看得见它改了什么。

人在环中比全自动更实用。 早期我追求"一句话搞定一切",后来发现让模型在关键岔路口停下来问一句,整体效率反而更高。它猜错的成本,远大于问一句的成本。

写在最后

Sigma 现在的样子,是本地化部署、技能可插拔、多 Agent 协作。往前看还有很多事没做完,但至少在自己的电脑上,AI 已经从"一个会聊天的网页"变成了"一个能干活的同事"。

本文的全部技术示意图,由 Sigma 自己写 HTML、自己截图生成;正文排版、图片上传到微信图床、存入草稿箱,也是它一步步跑完的。

如果你也在折腾类似的东西,欢迎留言交流。