我们有个内部用的 Electron 工具,前阵子加了个 AI 助手——选中内容问一下、长文档总结一下那种。Web 里做过对话,本以为搬进 Electron 是体力活,结果 Electron 的多进程模型 + 桌面端的离线场景,给我整出一堆 Web 里根本碰不到的事。盘成 6 条清单,要在 Electron / 桌面端集成对话的可以照着躲坑。
1. 别在渲染进程里直接发 AI 请求
第一反应是在渲染进程(前端那层)直接 fetch 模型接口,能跑。但 API 密钥就暴露在渲染进程里了,Electron 的渲染进程不比浏览器安全。正确姿势:密钥放主进程,渲染进程通过 IPC 把对话请求转给主进程,由主进程去请求模型,再把流式结果一段段 IPC 回来。 渲染层永远摸不到密钥。
2. 流式结果走 IPC,要自己切片回传
主进程拿到的是 SSE 流,不能等全部收完再一次性丢回渲染进程——那就没有"打字机"效果了。我用 webContents.send 每收到一个 chunk 就回传一段,渲染进程监听着往气泡里追加。记得回传时带上一个请求 id,不然多个对话窗口的流会串台。
3. 离线了要立刻知道,别让用户对着空气说话
桌面应用经常在没网的环境跑(出差、内网)。Web 端用户对断网有预期,桌面端用户默认你"装在我电脑上就该能用"。我用 navigator.onLine 加主进程的网络探测双重判断,没网就把输入框禁掉并提示"AI 助手需要联网",别让消息发出去石沉大海。
4. 本地缓存能救命
桌面端有个 Web 没有的福利:本地存储不要钱、还快。我把历史对话和已经问过的相同问题缓存到本地(用了个轻量的本地库存)。好处一是离线能翻历史,二是重复问题直接命中缓存不打模型,省 token。这条在我们这种问答重复率高的内部工具上,省了大概三成请求。
5. 窗口关了,流要 abort
用户问着问着把对话窗口关了,主进程那条请求还在跑、还在计费。我监听窗口的 closed,对应的请求统统 abort。Web 里 SPA 切路由也有类似问题,但 Electron 多窗口下更容易漏。
6. 更新提示别盖住对话框
小事但烦人:Electron 的自动更新弹窗有次正好盖在对话输入区上,用户打字打一半被挡。把 AI 助手的浮层 z-index 和更新提示的层级理了一遍才消停。桌面端的窗口层级比 Web 复杂,多留意。
一个没整明白的遗留
多窗口共享同一份对话上下文这事我做得不干净——目前每个窗口各自维护,开两个窗口问同一个文档会各算各的上下文。想做成主进程统一管上下文、窗口只是视图,但 IPC 同步的状态一多就容易乱,暂时搁置。谁在 Electron 里做过跨窗口状态同步,求个稳妥方案。
模型这头说一句:我没在本地塞模型(桌面端跑大模型不现实),对话能力是主进程去调[讯飞](agent.xfyun.cn/home?ch=Age… | | ---------------------------------------------) MaaS 的现成 API 拿的,按 token 用,离线就降级,省得我在每台机器上折腾模型环境。
桌面端集成 AI,难点真不在对话 UI,在多进程和离线这些 Web 不操心的地方。你们在 Electron / Tauri 里接 AI 都遇过啥坑?评论区交个底 👇