1. 结果摘要
今日页的文字输入已通过 RecordUnderstandingGateway 调用 record-understanding-v2,由 CloudBase hy3 生成未确认候选。生产函数运行在 Nodejs20.19,超时 60 秒,开启云端依赖安装;旧的 record-understanding 保留为短期回退,不再接收客户端新请求。
本次故障不是模型排队繁忙。云函数在约 10ms 内失败,最终从云端日志确认根因是 AI SDK 将 cloudbase.SYMBOL_DEFAULT_ENV 当作普通环境 ID 拼接,触发:
```text
TypeError: Cannot convert a Symbol value to a string
```
修复方式是使用 AI 请求路径支持的 cloudbase.SYMBOL_CURRENT_ENV,并将生产调用迁移到 Node 20 新函数。
2. 用户侧现象
- 今日页发送文字后只显示“AI 服务暂时繁忙,尚未生成记录”。
- 客户端只能看到 UNDERSTANDING_MODEL_FAILED 和业务 requestId。
- 开发者工具同时出现 TDesign t.woff 的 ERR_CACHE_MISS,但该警告只影响图标字体缓存,与 AI 云函数失败无关。
- 早期还出现过候选组件路径找不到、文字输入每输入一个字符就失焦等独立问题,均已分别修复,不能与模型故障混为一谈。
## 3. 排查过程
### 3.1 先按层隔离
1. 确认文字消息已进入今日页处理函数,排除输入组件和发送事件问题。
2. 使用客户端返回的业务 requestId 查询 CloudBase 函数日志。
3. 对比函数执行耗时:约 10ms 即失败,说明不是模型生成超时或排队。
4. 增加脱敏诊断日志,分别捕获模型创建、请求抛错、空响应和错误响应。
5. 核对仓库配置与云端真实配置,发现仓库要求 Node 20,但旧函数实际仍运行 Node 16。
### 3.2 处理运行时漂移
- cloudbaserc.json 已声明 Nodejs20.19,但旧函数创建时固定为 Nodejs16.13。
- CLI 的配置更新提示成功,云端详情仍显示 Node 16;底层 SCF 接口进一步明确返回“函数 Runtime 不支持修改”。
- 为避免删除函数和中断服务,新建 record-understanding-v2,复用同一源码目录,首次创建时指定 Node 20。
- 客户端网关切换到 v2,旧函数暂时保留为回退。
### 3.3 定位 SDK 根因
迁移 Node 20 后,脱敏日志终于保留了原始异常类型:
```text
TypeError: Cannot convert a Symbol value to a string
```
检查当前锁定版本的 @cloudbase/node-sdk 源码发现:
- 普通请求路径会分别处理 SYMBOL_CURRENT_ENV 与 SYMBOL_DEFAULT_ENV。
- AI 请求适配器只识别 SYMBOL_CURRENT_ENV。
- 传入 SYMBOL_DEFAULT_ENV 时,AI 路径会把 Symbol 当作字符串环境 ID 使用。
因此最终将模型初始化改为:
```ts
const app = cloudbase.init({
env: cloudbase.SYMBOL_CURRENT_ENV,
timeout: 60_000,
});
```
## 4. 同期完成的会话修正
- 本地今日会话升级为 schema v2。
- 存储键按稳定 userId 与 Asia/Shanghai 自然日隔离。
- 跨日创建空会话,不继续展示昨天的对话或草稿。
- 当天每个用户最多保留最近 80 条消息。
- 页面停留跨午夜时,在下一次输入前切换到当天会话。
## 5. 最终工程边界
- 小程序只通过 RecordUnderstandingGateway 请求业务结果,不直接依赖模型 SDK。
- AI 云函数只生成未确认候选,不写健康记录。
- 用户确认后才由 records 云函数写入正式数据。
- 日志只记录错误码、请求标识、输入长度、候选数量和 token 汇总,不记录健康原文。
- CloudBase 是过渡适配层,接口契约继续为未来自有服务器迁移保留。
## 6. 验证清单
每次修改 AI 云函数后至少完成:
1. 执行 npm run check,保证类型、领域规则、网关契约和云函数构建全部通过。
2. 执行 tcb config diff fn <function>,核对仓库配置和云端配置。
3. 执行 tcb fn detail <function>,确认实际运行时、超时、代码大小、依赖安装和部署状态。
4. 在开发者工具或真机使用可信微信上下文发送一条真实文字记录。
5. 成功时确认返回候选;失败时按业务 requestId 查询函数日志。
6. 确认日志没有原始健康文本、OpenID、密钥或完整模型提示词。
## 7. 可复用经验
1. 前端的通用错误文案不能作为根因。必须保留稳定错误码和可关联的请求标识。
2. “部署成功”只代表代码包上传完成,不代表运行时、依赖和真实调用链正确。
3. 仓库配置不是云端事实。配置漂移必须通过云端详情和底层接口核验。
4. 对不可原地升级的运行时,优先使用版本化新函数迁移,验证后再决定旧函数下线时间。
5. 第三方 SDK 的同名环境常量不一定适用于所有模块;出现类型异常时应检查当前锁定版本源码,而不是继续猜测额度或网络问题。
6. 日志诊断要覆盖对象创建、请求抛错、错误响应和无效输出四个阶段,同时保持健康数据最小披露。
7. 浏览器、渲染层和业务云函数的错误要分层判断。TDesign 字体缓存警告不能解释服务端 AI 失败。
## 8. 相关提交
- 8dc1703:绑定云函数环境并修正候选组件路径。
- a8fdd51:修正文字输入焦点。
- 0113e60:按自然日隔离今日会话并补充 AI 响应诊断。
- ca801c9:记录模型请求异常。
- d130935:覆盖模型初始化异常。
- 6282aa7:切换 Node 20 的 record-understanding-v2。
- 246952e:使用 SYMBOL_CURRENT_ENV 初始化 AI 模型。