AgentForge-WX v0.3.0:12项更新 + 框架重新定位,把微信小程序AI对话的坑全填了
昨天发了 autoContext 自动上下文后,不少同学私信问框架的成熟度------"能不能上生产?"。老实说,之前的版本有几个硬伤我不好意思推。这周做了一件更重要的事:重新定位框架,然后集中肝了12项更新,终于敢说可以用了。
先说最重要的事:框架重新定位
之前的问题:什么都往里塞
v0.2.0 之前,框架定位是"微信小程序 AI Agent 开发框架"------听起来很酷,但实际用起来有个尴尬的问题:
不需要 AI 的功能也必须引入整个框架。
比如你只想用一个缓存管理器,或者发个订阅消息,结果 npm install 之后发现依赖了一堆 LLM、Agent、工具注册的东西,云函数包体直接超了。
更尴尬的是写文档的时候------我不知道该跟开发者说"先配 LLM"还是"不用配 LLM也能用"。因为有些模块(CacheManager、UserProfile)压根不需要 LLM,但它们和 Agent 耦合在一起,文档上说不清楚。
转折点:一个真实反馈
有个同学看了框架后问:"我只想用你的缓存和订阅消息模块,不用 AI 对话,怎么装?"
我愣了一下------没法单独装。所有模块都打包在一起,Agent 是入口,不创建 Agent 就用不了。
这让我意识到:框架本质上在干两件完全不同的事,只是我一直混在一起:
- 让小程序能用 AI 对话(需要 LLM API Key)
- 给小程序提供通用工具库(不需要 LLM,任何小程序都能用)
这两件事的用户群体、使用方式、依赖关系完全不同。
拆线:两条独立的路线
重新梳理了所有模块,按"是否需要 LLM"拆成两条线:
bash
AgentForge-WX v0.3.0
│
├── 🤖 路线一:AI对话线(需LLM)
│ │ 目标用户:想给小程序加 AI 助手的开发者
│ │ 核心依赖:LLM API Key
│ │
│ ├── Agent 核心对话引擎(工具调度+多轮对话)
│ ├── LLMConfig 模型配置(DeepSeek/OpenAI/...)
│ ├── LLMClient 模型调用(重试+降级+流式)
│ ├── ToolRegistry 工具注册中心
│ ├── defineTool 自定义工具定义
│ ├── ContextWindow 上下文窗口管理(防token爆炸)
│ ├── RateLimiter 用户级限流(防刷)
│ ├── PromptTemplate Prompt模板系统
│ ├── estimate* token估算(3个函数)
│ └── CloudMemory 云端对话记忆
│
└── 🔧 路线二:工具库线(不需LLM)
│ 目标用户:任何微信小程序开发者
│ 核心依赖:无(只需微信云开发环境)
│
├── ContentAudit 内容审核(msgSecCheck+本地敏感词)
├── CacheManager 三级缓存(内存→本地→云)
├── SubscribeHelper 订阅消息-前端授权
├── SubscribeSender 订阅消息-后端发送
├── CloudCaller 云函数调用器
├── UserProfile 用户画像存储
├── Span 链路追踪-单次调用
└── TraceRecorder 链路追踪-记录器
关键设计:两条线完全独立,互不依赖。
- 只用路线二?不需要 LLM API Key,不需要创建 Agent,直接
new CacheManager()就行 - 两条都用?路线二的工具可以注册为路线一的工具,Agent 自动调度
- 只用路线一?也没问题,框架默认自带核心工具
文档也跟着拆了
原来 README 是一个长列表,现在按两条线分别写用法:
markdown
## 🤖 路线一:AI 对话
3步搞定:1.云函数创建Agent → 2.前端创建AgentClient → 3.聊天
## 🔧 路线二:工具库
按需引入:CacheManager / SubscribeHelper / CloudCaller / ...
开发者看文档时不再困惑------你想要哪条线,直接跳到对应章节。
这对框架意味着什么
- 降低门槛:不需要 LLM 也能用,小程序开发者可以先试工具库,再考虑要不要加 AI
- 包体更小:只用路线二的模块不需要引入 LLM 相关代码
- 定位更清晰:不再纠结"AI 框架"还是"工具库"------都是,但分得很清楚
- 未来扩展有方向:新功能先问"属于哪条线",归类就清楚了
然后是12项更新
定位理清之后,开始按两条线分别补功能、修 bug。
结论先看
| 维度 | v0.2.0 | v0.3.0 |
|---|---|---|
| 导出模块 | 10个 | 21个 |
| 代码行数 | ~1600行 | ~3600行 |
| LLM调用失败 | 直接抛异常 | 指数退避重试 + 多模型降级 |
| 对话太长 | token爆了就报错 | 自动裁剪 + 摘要替代 |
| 数据库安全 | wx_db裸奔 | 白名单机制 |
| 订阅消息 | 自己写 | SubscribeHelper/Sender 全流程 |
| 用户刷接口 | 没防 | perMinute/perDay 限流 |
一、3个P0硬伤:不上生产不知道
1. autoContext 传参断了
autoContext 是上周发的那篇的核心功能------让 Agent 自动感知小程序页面信息。但实际跑起来发现,AgentClient 构造时接收了 appContext,调云函数时却没传过去。
js
// 修前:appContext 到这就断了
const callData = { message };
// 修后:打通数据流
const callData = { message };
if (this._appContext) {
callData.appContext = this._appContext;
}
数据流:globalData → client传参 → 云函数event → handler注入 → Agent增强prompt
2. LLM 调用零重试
之前的 LLMClient,DeepSeek 返回 429 或超时,直接 throw。用户看到的:"服务内部错误"。
修法:指数退避(1s → 2s),最多重试 2 次,但只对可恢复错误重试:
js
_isRetryable(err) {
const msg = err.message || '';
// 超时、429、503、500 → 可重试
if (msg.includes('timeout') || msg.includes('HTTP 429')) return true;
// 401、400 → 不重试(认证/参数错了重试也没用)
if (msg.includes('HTTP 401') || msg.includes('HTTP 400')) return false;
}
3. wx_db 没权限控制
wx_db 工具让 LLM 可以读写云开发数据库,但之前没有任何限制 ------LLM 想读哪个集合就读哪个,包括 users、orders 这种敏感数据。
js
// Agent 构造时配置白名单
const agent = new Agent({
name: 'chat',
llm: config,
allowedCollections: ['faq', 'products'], // 只允许读这两个集合
});
// wx_db 执行时校验
if (allowedCollections && !allowedCollections.includes(collection)) {
return `安全限制:集合 '${collection}' 未在白名单中`;
}
不设白名单时行为不变,向后兼容。
二、4个P1体验优化
4. navigate 跳转数据被截断
navigate 工具的跳转结果从 trace 里捞,但 trace 输出被 slice(0, 200) 截断 → JSON parse 失败 → 跳转不生效。
修法:直接在 Agent.chat 里收集 navigate 返回值,删了 handler 里 20 多行的 trace 解析代码,简化为 1 行。
5. CloudMemory 降级无提示
云数据库不可用时,CloudMemory 静默降级为本地数组,开发者完全不知道。
新增 onDegraded 回调和 isDegraded() 方法:
js
const memory = new CloudMemory({
onDegraded: (reason) => console.warn('存储降级:', reason),
});
6. parseToolCalls 崩溃保护
LLM 返回的 tool_calls 格式异常时,_parseToolCalls 直接抛错导致整个对话中断。加了 try-catch,parse 失败返回 null。
7. chatStream 体验优化
微信云函数不支持 SSE 真流式,之前就是干等。加了 onThinking 回调,前端显示"思考中●●●"动画:
js
client.chatStream('你好', {
onThinking: () => updateUI('思考中...'),
onChunk: (text) => updateUI(text),
onDone: (full) => updateUI(full),
});
三、3个P2锦上添花
8. 假工具清理
之前 weather 和 translate 是默认注册的内置工具,但它们返回的是模拟数据,LLM 调了等于白调。移入 EXTRA_TOOLS,需开发者主动注册。
9. 事件钩子
js
const agent = new Agent({
name: 'chat',
llm: config,
onLLMCall: (phase, info) => { /* before/after */ },
onToolCall: (phase, info) => { /* before/after */ },
onError: (err, context) => { /* 错误事件 */ },
});
// 也可以构造后注册
agent.on('onToolCall', (phase, info) => {
console.log(`工具${info.name} ${phase}, 参数:`, info.arguments);
});
10. LLMConfig 校验
apiKey 为空、temperature > 2、timeout < 1000 等配置问题,构造时输出警告。
四、路线一5个新功能(🤖 AI对话线)
11. 上下文窗口管理
对话长了 token 爆炸 → 成本飙升 → 超限报错。这是所有 AI 对话应用的通病。
js
const agent = new Agent({
name: 'chat',
llm: config,
maxContextTokens: 4096, // 超预算自动裁剪
});
裁剪策略:system 必保留 → 最近 2 轮优先 → 工具调用成对保留 → 老消息用摘要替代。
Token 估算用字符数(中 1.5token/字,英 1token/词),因为微信云函数装不了 tiktoken。
12. 多模型降级
主模型挂了?自动切备用:
js
const agent = new Agent({
name: 'chat',
llm: new LLMConfig({ apiKey: 'sk-xxx', model: 'deepseek-chat' }),
llmFallbacks: [
{ apiKey: 'sk-yyy', model: 'qwen-plus' },
{ apiKey: 'sk-zzz', model: 'glm-4-flash' },
],
});
降级规则:服务不可用/超时/500/503 → 降级;401/403 → 不降级(认证错了换模型也没用)。
13. 对话会话管理
同一个用户多个对话场景(客服咨询、技术问答...),用 sessionId 隔离:
js
// 前端
agent.setSession('tech_support');
await agent.chat('帮我查个bug');
// 切换到另一个场景
agent.setSession('order_inquiry');
await agent.chat('我的订单到哪了');
// 云端自动按 openid:sessionId 隔离
14. 用户级限流
防止某个用户刷爆你的 API 额度:
js
const agent = new Agent({
name: 'chat',
llm: config,
rateLimit: { perMinute: 20, perDay: 200 }, // 默认开启
});
超限返回 429,handler 自动处理。
15. Prompt 模板系统
把硬编码的 systemPrompt 改成模板:
js
const agent = new Agent({
name: 'chat',
llm: config,
promptTemplate: new PromptTemplate(
'你是{{appName}}的AI助手。今天是{{today}}。{{#features}}可用功能:{{features}}。{{/features}}'
),
promptVars: { appName: '半仙知命', features: '起名、看相、风水' },
});
// 动态更新
agent.rebuildPrompt({ features: '起名、看相' });
内置变量:{{today}}、{{weekday}}、{{time}} 自动填充,不用手动传。
五、路线二4个新功能(🔧 工具库线)
这4个功能完全不需要 LLM,任何微信小程序都能用:
16. 智能本地缓存 CacheManager
三级缓存:内存 → wx本地存储 → 云存储,带 TTL 和自动清理:
js
const cache = new CacheManager({ prefix: 'myapp' });
await cache.set('user_info', data, 3600); // 缓存1小时
const info = await cache.get('user_info');
// 缓存不存在时自动计算并缓存
const result = await cache.getOrSet('api_data', async () => {
return await fetchExpensiveData();
}, 300);
17. 订阅消息助手
前端授权 + 后端发送,一个模块搞定:
js
// 前端:请求授权
const sub = new SubscribeHelper({ templates: ['tmpl_001'] });
const { granted, denied } = await sub.requestAuth();
// 云函数:发送消息
const sender = new SubscribeSender({ retryCount: 2 });
await sender.send({ openid, templateId: 'tmpl_001', data: { thing1: { value: '您有新消息' } } });
18. 云函数调用器 CloudCaller
统一 callFunction 的错误处理 + 超时 + 重试:
js
const caller = new CloudCaller({ name: 'ai_main', timeout: 10000, retry: 1 });
const result = await caller.call('chat', { message: '你好' });
// { code: 0, data: { reply: '...' }, message: '' }
19. 用户画像存储 UserProfile
首次登录 → 记录信息 → 后续读取,标准流程一行搞定:
js
const profile = new UserProfile({ collection: 'user_profile' });
if (await profile.isNewUser(openid)) {
await profile.set(openid, { nickname: '张三', level: 1 });
}
// 增量更新
await profile.update(openid, { level: 2 });
// 数值递增(原子操作)
await profile.increment(openid, 'score', 10);
六、代码审查修了3个bug
写完 12 个功能后做了一次完整代码审查,发现:
- ContextWindow 解构缺失 :
require('./context')返回对象但 agent.js 直接当类用,instanceof报 TypeError - handler this 指向错误 :catch 块里
this._fireHook指向的是 handler 函数而非 Agent 实例 - Agent.on() 缺失:hooks 只能构造时传,无法动态注册
这三个 bug 如果不审查,上线后分别是:Agent 创建直接崩 、错误时 hooks 不触发 、运行时无法注册回调。
框架全景
css
AgentForge-WX v0.3.0(21个导出)
│
├── 🤖 AI对话线(需LLM)
│ ├── Agent 核心对话引擎
│ ├── LLMConfig 模型配置
│ ├── LLMClient 模型调用(重试+降级)
│ ├── ToolRegistry 工具注册
│ ├── defineTool 工具定义
│ ├── ContextWindow 上下文窗口管理
│ ├── RateLimiter 用户级限流
│ ├── PromptTemplate Prompt模板
│ ├── estimate* token估算(3个)
│ └── CloudMemory 云端对话记忆
│
└── 🔧 工具库线(不需LLM)
├── ContentAudit 内容审核
├── CacheManager 三级缓存
├── SubscribeHelper 订阅消息-授权
├── SubscribeSender 订阅消息-发送
├── CloudCaller 云函数调用器
├── UserProfile 用户画像
├── Span 链路追踪
└── TraceRecorder 追踪记录器
npm 安装:
bash
# 云函数端(含路线一+路线二)
npm install agentforge-wx
# 小程序端(AgentClient + UI组件)
npm install agentforge-wx-client
源码:
- 🔒 开发仓库:gitee.com/yufuwu/afwx-dev
- 🌐 公开仓库:gitee.com/yufuwu/agentforge-wx
如果觉得有用,点个赞 👍 顺便 star 一下仓库,开源项目需要你的支持。