AI 能力正在重塑小程序体验:拍照识别、语音输入、智能客服、个性化推荐……微信生态本身提供了部分原生 AI 能力(OCR、语音、图像),而更复杂的生成式 AI(大模型对话、总结、创作)则需要对接外部 AI 服务。小程序的 AI 集成有独特的挑战:前端算力弱、网络弱网多、模型密钥不能放客户端、输出还要过内容安全。本文从能力全景讲起,给出图像、语音、大模型三类集成的完整实战路径。
一、小程序 AI 能力全景
1.1 能力分层
| 能力层 | 例子 | 部署位置 |
|---|---|---|
| 原生 AI 能力 | 微信 OCR、语音转文字、图像识别 | 微信开放接口 |
| 第三方 AI SDK | 人脸、图像增强、翻译 | 服务端调用 |
| 大模型服务 | 对话、摘要、写作、Agent | 服务端 + 外部 API |
| 端上推理 | 轻量分类、关键词提取 | 小程序端(受算力限制) |
1.2 三类典型业务形态
| 业务 | AI 能力 | 关键指标 |
|---|---|---|
| 拍照识物/票据识别 | OCR + 图像识别 | 识别准确率、耗时 |
| 语音助手/语音搜索 | 语音识别 + 语义理解 | 识别率、首字延迟 |
| AI 客服/创作助手 | 大模型对话 | 首包延迟、回答质量 |
| 内容审核 | 文本/图片鉴黄涉政 | 召回率、误杀率 |
一句话:AI 集成的大部分复杂度都在服务端,小程序端要做的是「采集输入、展示输出、兜住体验」。
二、OCR 与图像识别集成
2.1 原生 OCR 能力
微信提供了 wx.serviceMarket.invokeService 调用开放能力,可做身份证、银行卡、票据等 OCR:
// 小程序端:拍照后调用 OCR 服务
async function recognizeBill(filePath) {
const res = await wx.serviceMarket.invokeService({
service: 'ocr-bill',
api: 'recognize',
data: {
img_url: filePath
},
clientMsgId: 'bill_ocr_' + Date.now()
});
const { errCode, data } = res;
if (errCode === 0) {
return parseBillFields(data.items);
}
throw new Error('OCR 识别失败:' + errCode);
}
2.2 图片上传与识别链路
受小程序上传限制影响,正确链路是「本地选图 → 压缩 → 上传服务端 → 服务端调 OCR → 回传结果」:
wx.chooseMedia 选图
↓ wx.compressImage 压缩(限制 2M 以内)
服务端接收图片
↓ 服务端调用 OCR 服务(可复用 token)
OCR 结果回传客户端渲染
// 小程序端:压缩后上传
async function uploadForOcr(filePath) {
const { tempFilePath } = await wx.compressImage({
src: filePath,
quality: 80
});
return new Promise((resolve, reject) => {
wx.uploadFile({
url: 'https://api.example.com/ocr',
filePath: tempFilePath,
name: 'image',
success: (res) => resolve(JSON.parse(res.data)),
fail: reject
});
});
}
2.3 识别结果的前端校验
OCR 结果不一定可靠,前端要做二次校验与用户确认,而不是直接采信:
| 场景 | 校验方式 |
|---|---|
| 身份证号 | 校验位算法 + 生日期逻辑 |
| 银行卡号 | Luhn 算法 + 长度校验 |
| 金额票据 | 数字格式 + 阈值合理性 |
| 车牌 | 正则 + 省份字典 |
三、语音能力集成
3.1 语音识别
微信的语音能力通过 wx.getRecorderManager 录音,再交给服务端语音识别(也可用微信开放接口):
// 小程序端:录制语音
const recorder = wx.getRecorderManager();
function startRecord() {
recorder.start({
duration: 60000,
format: 'mp3',
sampleRate: 16000,
numberOfChannels: 1
});
}
recorder.onStop((res) => {
uploadForAsr(res.tempFilePath); // 上传到服务端做识别
});
function uploadForAsr(filePath) {
wx.uploadFile({
url: 'https://api.example.com/asr',
filePath,
name: 'audio',
success: (res) => {
const data = JSON.parse(res.data);
this.setData({ transcript: data.text });
}
});
}
3.2 语音合成与播报
需要语音播报时(如叫号、语音导航),服务端调用 TTS 生成音频,小程序用 wx.createInnerAudioContext 播放:
function playTts(text) {
const audio = wx.createInnerAudioContext();
audio.src = 'https://api.example.com/tts?text=' + encodeURIComponent(text);
audio.play();
audio.onEnded(() => audio.destroy());
}
一句话:语音集成要把「采集 → 识别 → 语义 → 播报」拆成独立环节,每个环节都能单独降级(识别失败时退回文本输入)。
四、大模型接口接入与服务端调度
4.1 为什么密钥不能放前端
调用大模型 API 需要 API Key,一旦放在小程序代码里就会被逆向抓走。正确做法是客户端只发用户请求,服务端持有密钥并转发:
小程序端 → BFF/服务端 → 大模型 API
(鉴权) (持密钥、限流)
4.2 服务端调度封装
// 服务端:大模型调用封装(含限流与配额)
const LIMIT = { perUser: 20, perMinute: 5 };
async function chatCompletion(ctx, messages) {
const key = 'llm_quota:' + ctx.openid;
const used = await redis.incr(key);
if (used === 1) redis.expire(key, 86400);
if (used > LIMIT.perUser) {
throw bizError(40001, '今日对话次数已达上限');
}
// 持密钥调用大模型
const resp = await fetch(LLM_ENDPOINT, {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + process.env.LLM_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'qwen-max',
messages,
stream: ctx.stream === true
})
});
return resp;
}
4.3 并发与队列
大模型接口常有限流,高峰时需做排队与重试。简单方案用「令牌桶」控制速率,复杂方案引入任务队列:
| 方案 | 适用规模 | 特点 |
|---|---|---|
| 令牌桶限流 | 中小规模 | 实现简单,超限即拒绝 |
| 本地队列 | 单机并发可控 | 排队等待,体验更平滑 |
| 消息队列 | 大规模 | 削峰填谷,异步处理 |
4.4 提示词与上下文管理
// 服务端:系统提示词 + 会话上下文
function buildMessages(userId, userInput) {
const history = sessionStore.get(userId); // 最近 10 轮
return [
{ role: 'system', content: '你是一个专业的小程序智能助手,回答简洁、准确。' },
...history,
{ role: 'user', content: userInput }
];
}
五、前端体验设计
5.1 流式输出的渲染
大模型回复长,等待全量返回会非常煎熬。应使用流式输出,一边接收一边渲染:
// 小程序端:通过 WebSocket 接收流式结果
const socket = wx.connectSocket({
url: 'wss://api.example.com/llm/stream'
});
socket.onMessage((res) => {
const chunk = JSON.parse(res.data).delta;
this.setData({
answer: this.data.answer + chunk
});
});
5.2 AI 交互的加载态设计
| 状态 | 前端表现 |
|---|---|
| 请求中 | 打字机光标动画 + 预估等待提示 |
| 首包到达 | 立即渲染首段文字 |
| 流式中断 | 展示「回答中断,可重试」 |
| 识别失败 | 降级为文本输入,不阻塞流程 |
5.3 结果的后置校验
AI 生成内容需要做事实性兜底:金额、日期、法律条款等关键信息要与权威数据源比对,展示时标注「AI 生成,仅供参考」:
// 展示层兜底
function decorateAnswer(text) {
const warnings = detectRiskyClaims(text); // 命中金额/日期等
return {
text,
disclaimer: warnings.length > 0 ? '以上内容由 AI 生成,请以官方信息为准' : ''
};
}
六、合规与安全
6.1 内容安全双闸门
AI 生成内容必须经过内容安全校验,且应前后双闸门:服务端生成后先过审再下发,客户端展示前再做一次本地敏感词拦截:
用户输入 → 输入过滤(防注入、防敏感)
大模型生成 → 内容安全服务检测(文本+图片)
↓ 通过
回传客户端 → 客户端本地兜底拦截
// 服务端:输出内容安全检测
async function checkContent(text) {
const res = await securityService.check({ content: text });
if (res.risky) {
throw bizError(50002, '内容涉及违规,已被拦截');
}
return text;
}
6.2 隐私与《个人信息保护法》
AI 功能涉及大量用户数据处理,需特别注意:
| 数据 | 合规要求 |
|---|---|
| 用户输入内容 | 明示用途,最小化存储 |
| 语音/人脸数据 | 属于敏感个人信息,需单独授权 |
| 识别结果 | 标注使用范围,禁止转售 |
| 对话记录 | 提供删除入口,默认不用于训练 |
6.3 大模型使用规范
- 算法备案:向公众提供生成式 AI 服务需符合相关备案要求。
- 标识义务:AI 生成内容应按平台规范做标识或显著提示。
- 未成年人保护:面向未成年人的场景需限制内容范围。
- 可解释性:对关键决策保留「人审兜底」,不全盘自动化。
一句话:AI 能力越强,合规责任越重,内容安全与隐私保护是上线前的硬门槛,不是可选项。
七、总结
小程序集成 AI 能力的正确姿势是「端轻服务重」:前端负责采集输入、流式渲染与降级兜底,服务端负责持密钥、限流、调度大模型与内容安全检测。OCR、语音等原生能力可以快速接通,大模型类能力则要设计好配额、队列与上下文管理。体验上,流式输出和加载态设计决定了用户对 AI 功能的耐心;安全上,输入输出双闸门、隐私授权与算法合规缺一不可。这套 AI 集成方案可与小程序后端 BFF 架构的服务端调度体系衔接,借助监控告警观测 AI 接口耗时与成功率,再结合安全合规守住内容与隐私底线,让 AI 能力在可控范围内真正成为业务增长引擎。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。