小程序端「数字员工」业务云函数提速方案(评估稿)
目标:把小程序端数字员工相关业务的体验/执行速度提升一个量级,作为引流与轻量化解决方案。
定位前提(与用户确认):小程序目前功能与 PLM 关系不大,核心只有「产品相关」+「数字员工体验」。小程序是引流 + 轻量入口,不是系统 of record。
0. 结论先行
建议做,但只迁移「体验层」,不迁移「PLM 写入层」。
- 迁移到云函数:数字员工的「体验/对话/画像展示」类业务(ai-chat 体验流、staff-detail 画像、staff-config 预设、demo 引流)——这些不写 PLM,只吃 LLM + 只读数据。
- 保留在服务端:任何真正写 PLM/114(CapabilityRuntime.create、SCSAI 对象版本化)的能力,永远留在
server.js,云函数只做「异步代理 + 结果回流」。 - 最大单点收益:把 orchestration(lite-scheduler worker 的多轮 LLM 编排)从自托管服务器搬到紧邻 LLM 网关的云函数,并改用「云数据库 watch 流式」替代现在的「180s 同步砖墙 + 1.5s 轮询」。
一句话:LLM 已经在云上(CloudBase 网关),把编排也搬到云上,PLM 留在地面。
0.5 方案修正(实现前勘误 · 2026-09-01)
动手前把代码读实,发现原方案两处必须纠正,否则会白做:
勘误 1 — 小程序端「启用 SSE」走不通。 微信 wx.request 不支持读取流式 chunk(onChunkReceived 仅部分基础库实验性支持且受限)。后端 /api/digital-staff/logs/stream SSE 端点虽在(server.js:5221),但前端无法在小程序里消费它。原 Phase 1「启用 SSE」此路不通,改为走 WebSocket(已是项目现有通道)。
勘误 2 — 体验差的真正根因是「WS 通道错配」,不是没用 SSE。
miniapp-ws.js:19的getWsBase()旧逻辑把地址推成ws://localhost:3007:小程序跑在手机/微信,localhost 是手机自己,永远连不到服务器 3007 →miniappWs.isConnected()恒 false →ai-chat永远退化成setInterval(doFetch,1500)轮询(index.vue:1294)。WS 在小程序端形同虚设。- 生产域名
https://ylxt.chat推成wss://ylxt.chat,但deploy/nginx.conf是 PLM 3000 的模板(server_name your-domain.com占位符、upstream plm_backend 127.0.0.1:3000),没有把 WS 反代到 3007;主location /还开了proxy_buffering on+ 60s 超时,连现有 SSE 也会被缓冲成非实时。
已落地修复(本轮,代码已改):
src/config/env.js增加WS_BASE_DEV/WS_BASE_PROD(空=自动推导)。src/utils/miniapp-ws.js的getWsBase()重写:显式配置优先;否则生产域名无端口 → 自动拼/ws路径(wss://ylxt.chat/ws),本地带端口 → 自动换 3007(ws://192.168.x:3007);兜底也绝不回退localhost。- 服务端
ws-bridge.js:39是独立端口监听(new WebSocket.Server({ port })、path无关),已确认 nginx 反代/ws → 127.0.0.1:3007会被正常接受;server.js:8249单进程主进程会拉起 ws-bridge 并hookIntoDigitalStaff()钩入日志系统。
修正后 Phase 1(见 §7):「WS 配置修复(代码已做)+ 部署加 nginx /ws 反代」= 实时日志红利,立刻消除 1.5s 轮询。但注意:runDigitalStaff 仍是 await request('/api/digital-staff/run') 同步等 worker 全跑完(含多轮 LLM 3-8s)才返回(index.vue:1181),WS 通了只让「执行过程日志」实时可见,不缩短首结果延迟。要真正首 token 快,仍需 run 异步化(Phase 1b)或云函数 Tier1(§2)。
1. 现状与瓶颈(带代码证据)
1.1 调用链
小程序端数字员工有两条路径,最终都落到主服务器的同步 runStaffOnce:
- 前端默认直连公网:
API_BASE_DEV = https://ylxt.chat,超时 180s(src/api/request.js:37,41)。 - 触发:
POST /api/digital-staff/run(src/api/digital-staff.js:175)。 - 主服务器分发:
server.js:5197→handleDigitalStaffNewRoutes→server/routes/digital-staff-routes.js。 - 独立 miniapp 服务端(若存在)是二次同步转发:
miniapp-routes.js:819axios POST http://localhost:${port}/api/digital-staff/run,同样 180s(miniapp-routes.js:821)。 - 执行栈:
boss-scheduler/index.js:96 runStaffOnce→lite-scheduler.js:3403 runOnce→:2416 _runWorker→:1459 _dispatchWorkerPath→CapabilityRuntime或workers/*.js。
1.2 一次执行的耗时构成(串行)
| 阶段 | 证据 | 典型耗时 |
|---|---|---|
| ① 公网 RTT(小程序→ylxt.chat) | request.js:37 | 30-80ms × 至少 2 跳(请求+轮询) |
| ② 同步等待 worker | lite-scheduler.js:2497 默认 await | 取决于下面 |
| ③ LLM 多轮串行 | capability-runtime.js:107 _callLLMViaRouter 数十处;llm-brain.js:320 await fetch 到 CloudBase 网关 | 每轮 0.5-2s,多轮累积 |
| ④ PLM/114 远程 SOAP | scsaiAgentClient.js:21,41 fetch('http://localhost:5000/api/agent') | 跨网时 +20-100ms/次 |
关键瓶颈:
- 瓶颈 A(前端感知):全程同步 + 无真正流式。后端已有 SSE(
server.js:5221 /api/digital-staff/logs/stream),但小程序端ai-chat用的是setInterval(doFetch,1500)轮询(:1124,1295)+setTimeout120s 兜底,打字机是本地模拟(:1521)——SSE 能力被白白闲置。 - 瓶颈 B(服务端):LLM 编排在远离 LLM 网关的自托管服务器上。
llm-brain.js:34端点就是 CloudBase 网关,但调用方在server.js(公网主机)。每次 LLMfetch都跨网到云网关,且多轮串行、无并发。
1.3 现有云函数(已具备,可作为基座)
- 已接入云开发:
src/App.vue:20wx.cloud.init({env:'cloudbase-d5gv82ghi897598ab'});project.config.json:25cloudfunctionRoot:"cloudfunctions/"。 - 已有 3 个云函数:
generateImage(混元生图)、imageToText(混元多模态)、batchManager(任务调度)。 - 前端封装:
src/ai/cloudAiService.js多处wx.cloud.callFunction({name:'generateImage'|'imageToText'|'batchManager'})。 - 现状云函数只用于生图/图生文,未用于文本 LLM 推理 / 数字员工执行 / PLM 调用。
2. 总体设计:三层边界(Tier)
┌─────────────────────────────────────────────────────────────┐
│ 小程序(引流/轻量) │
│ │
│ Tier1 体验层(迁云函数) 数字员工对话/画像/预设/demo │
│ └─ 真实 LLM(云网关同区) + 只读缓存,不写 PLM │
│ │
│ Tier2 真实层(云函数异步代理) 需写 PLM 的执行 │
│ └─ 云函数 → server.runStaffOnce(仅PLM写) → 结果回流云DB │
│ │
│ Tier3 系统层(永不动) PLM/114 对象创建/版本化 │
│ └─ server.js + CapabilityRuntime(持有凭据) │
└─────────────────────────────────────────────────────────────┘
Tier 1 — 迁云函数(主战场,纯提速)
- 范围:
ai-chat的「体验/引流」人格对话、staff-detail画像读取、staff-config预设、demo专区。 - 实现:新建云函数
digitalEmployee,内部直接调 CloudBase LLM 网关(llm-brain.js:34同区),无需再跨公网到 server.js。 - 数据:只读知识从服务端一次性同步到云数据库集合(建立缓存);体验结果不写 PLM。
- 合规:仍用真实 LLM + 真实只读数据,零 mock(符合「业务零容忍假数据」约束)。
Tier 2 — 云函数异步代理(真实执行不走砖墙)
- 范围:真正要落 PLM 的执行(
staff-run、loop-new、ai-chat 中切换到「真写」模式)。 - 实现:云函数
digitalEmployee的runAsyncaction 调server.runStaffOnce(携带用户凭证 token),立即返回 taskId;server 执行完把结果/日志写入云数据库集合ds_runs(server 侧加一个轻量 writer,复用现有 SSE 日志)。 - 前端:拿到 taskId 后
db.collection('ds_runs').where(taskId).watch()订阅进度,消除 180s 公网同步等待。
Tier 3 — 永不动
CapabilityRuntime.create、SCSAI/114 对象版本化、凭据管理,全部留在server.js。云函数不持有 PLM 凭据。
3. 目标调用时序(Tier1 体验流,提速核心)
小程序 ──wx.cloud.callFunction(digitalEmployee, {action:'chat'})──▶ 云函数
│ 同区调 LLM 网关(llm-brain.js:34)
│ 逐段写云DB ds_logs{logId, delta}
◀── 立即返回 logId(几十ms)
小程序 ──db.collection('ds_logs').where(logId).watch()─────────▶ 云DB
◀── 每有 delta 推送(首token 1-2s)
小程序 逐字渲染(真实流式,非本地模拟)
对比现状:现状是「小程序 → 公网 server → 串行 LLM/PLM → 等 3-8s → 一次性返回(或 1.5s 轮询)」。
4. 性能模型与量化预期
| 指标 | 现状 | 云函数方案 | 来源 |
|---|---|---|---|
| 首字节/首 token | 3-8s(全同步) | 1-2s(首 token 可见) | LLM 首 token + 云内 RTT |
| 网络 RTT(小程序→计算) | 30-80ms×2(公网) | ~10ms(云内) | 微信云开发内网 |
| LLM 调用链路 | server→公网网关 | 云函数→同区网关 | llm-brain.js:34 |
| 中间反馈 | 无(轮询 1.5s 模拟) | 真实逐字流式 | 云DB watch |
| 长任务等待上限 | 180s 同步砖墙 | 异步 taskId + watch | 取消 brick wall |
| 并发/扩缩 | 受单 server 限制 | 云函数自动扩缩 | 平台能力 |
注:绝对数字随 LLM 模型/网络波动,但相对提速来自「消除公网 RTT + LLM 同区 + 真实流式」三重叠加,量级可靠。
5. 关键设计点
- 流式靠云数据库 watch,不靠云函数返回流。微信云函数
callFunction是一次性返回;用云 DB 集合 +.watch()订阅实现真实流式(已是云开发标准做法)。这是比现在「SSE 已建但前端不用」更彻底的提速。 - 预暖冷启动:云函数冷启动 ~100-300ms。用定时触发器(类似
batchManager的保活思路)或最小实例,保证体验流首次调用不卡。 - 只读缓存一致性:Tier1 画像/知识缓存设 TTL(如 5-15min),真实数据永远以 server 为准;体验流明确「只读、不落 PLM」,避免脏数据。
- 安全边界:PLM/114 凭据、LLM key 只在
server.js与 CloudBase 网关内;云函数只转发用户 token,不接触 PLM 写凭据(满足凭据隔离)。 - 可观测:接入现有
composables/useErrorReporter.js,云函数异常上报到统一错误通道。
6. 全面评估
6.1 收益
- 引流体验质变:首 token 1-2s + 逐字流式,远超当前 3-8s 砖墙,留存/转化直接受益。
- 架构对齐定位:轻量入口跑轻量层,PLM 重活留地面,职责清晰。
- 成本可控:体验流量大但云函数+云 DB 调用便宜;PLM 重算仍在原服务器。
- 低风险扩展:复用已上线的云开发(appid 已绑定、generateImage 已跑通),非从零搭建。
6.2 风险
- 冷启动:首调延迟。→ 预暖/最小实例缓解。
- 缓存漂移:体验读缓存可能与 server 真值短暂不一致。→ TTL + 「真实路径必走 server」约束。
- 云厂商锁定:微信云开发绑定。→ 小程序本就微信独占,可接受。
- 调试:日志在云开发控制台,需接错误上报(已有 reporter)。
- 迁移期双轨:Tier1/2 并存时,体验流与真实流要走不同 action,避免串。
6.3 成本
- 云函数调用费 + 云 DB 读写费 + 云存储(图片已在用)。引流期量级小,可先放量观测;真上量再评估预留实例。
6.4 替代/补充方案(不改云函数也能部分提速,建议并行做)
- A. 修 WS 实时通道(替代 SSE):小程序端
wx.request不支持流式 chunk,SSE 走不通;但项目已有 WebSocket 通道(ws-bridge3007)。旧miniapp-ws.js把地址错配成ws://localhost:3007(手机连不到)→ 永久轮询。本轮已修env.js+miniapp-ws.js让地址正确推导(wss://ylxt.chat/ws);部署只需在 nginx 加一段/ws → 127.0.0.1:3007反代(见附录),WS 即真通,实时日志立刻生效。零云函数、零架构改动,先吃这块红利。 - B. 体验流改异步 job:即使不迁云函数,把体验对话改
runAsync+ 轮询/订阅 server 日志,也能去掉 180s 砖墙。 - C. 静态资源/画像预取:
staff-detail画像、商城数据本地缓存(workbench 已有:652缓存范式),首屏秒开。
建议:A 先落地(零成本)+ 云函数 Tier1 并行推进。A 是「今天就能提速」,云函数是「架构级提速」。
7. 实施分阶段(方案→实现→优化,迭代驱动)
- Phase 0 · 基线测量:在
ai-chat/staff-run打点,测 p50/p95 端到端延迟(已有 SSE 日志可复用)。验收:拿到现状数字基线。 - Phase 1 · 修 WS 实时通道(零云函数,代码已落地):
env.js+miniapp-ws.js已改(地址正确推导);部署加 nginx/ws反代后,前端ai-chat的 WS 即真通,替代 1.5s 轮询(前端降级逻辑已就绪:index.vue:1294)。验收:WS 连通后日志实时刷新、轮询定时器不再启动。 - Phase 2 · 云函数 digitalEmployee(Tier1):新建云函数,承载体验对话/画像/预设,调同区 LLM 网关 + 云 DB 缓存 + watch 流式。验收:体验流 p95 较基线降 ≥50%,零 mock。
- Phase 3 · Tier2 异步代理:云函数
runAsync代理真实 PLM 执行,server 写结果回云 DB,前端 watch。验收:真实执行不再 180s 砖墙,进度可见。 - Phase 4 · 灰度+度量+回滚预案:先引流/体验人格灰度,对比留存,再全量。验收:无回归、可一键回退到直连 server。
8. 待拍板问题
- Tier1 范围确认:先把「ai-chat 体验流 + staff-detail 画像」迁云函数,还是连 demo/预设一起?建议先 ai-chat + staff-detail。
- 云环境:确认
cloudbase-d5gv82ghi897598ab是否即目标环境、LLM 网关在该环境是否可直接被云函数调用(需验证llm-brain.js:34端点对云函数可达)。 - Phase 1(WS 通道)已动手:WS 地址推导修复代码已落地(env.js + miniapp-ws.js),仅差你部署侧加 nginx
/ws反代(附录片段)。是否同意我继续推进 Phase 1b(run 异步化,缩短首结果延迟)或并行启动云函数 Tier1? - 成本预算:引流期是否接受云函数/云 DB 增量账单,还是需要预留实例压测?
附:关键证据行号速查
- 前端 base/超时:
src/api/request.js:37,41 - 前端 run:
src/api/digital-staff.js:175 - 代理同步转发:
bossagents-miniapp/server/miniapp-routes.js:819,821 - 主服务器分发:
server.js:5197,3763 - 执行栈:
boss-scheduler/index.js:96→lite-scheduler.js:3403,2416,1459,2497 - Worker 签名:
boss-scheduler/workers/identify.js:13 - LLM:
llm-brain.js:34(网关),320(fetch)、capability-runtime.js:107 - PLM 远程:
scsaiAgentClient.js:21,41 - SSE 已建未用:
server.js:5221;前端轮询:pages/ai-chat/index.vue:1124,1295,1521 - 云函数基座:
src/App.vue:20、project.config.json:25、src/ai/cloudAiService.js:31+ - WS 通道修正:
src/utils/miniapp-ws.js:19(getWsBase重写)、src/config/env.js(WS_BASE_DEV/PROD)、server/services/ws-bridge.js:39(独立端口监听、path 无关)、server.js:8249(单进程拉起 ws-bridge)
附:nginx /ws 反代片段(部署侧,Phase 1 必需)
当前 deploy/nginx.conf 是 PLM 3000 模板,不含此段;请并入 bossagents 实际的 HTTPS server 块(替换 your-domain.com 为真实域名)。
# 数字员工 WebSocket 实时日志通道(server.js ws-bridge :3007)
location /ws {
proxy_pass http://127.0.0.1:3007;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_buffering off;
}
注:ws-bridge 是独立端口监听、path 无关,反代 /ws 到 3007 即被接受。前端对应地址为 wss://<域名>/ws(已由 getWsBase() 自动推导,无需改前端)。
BossAgents