小程序 AI 能力集成实战

系统讲解小程序 AI 能力集成:OCR 与图像识别、语音识别与合成、大模型接口接入与服务端调度、前端流式体验设计,以及内容安全与合规边界,帮助开发者在小程序中安全高效地落地 AI 功能。

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 能力在可控范围内真正成为业务增长引擎。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「miniprogram」更多文章

  1. 小程序国际化与多语言支持
  2. 小程序后端架构与 BFF 层设计
  3. web-view 与 H5 混合开发实战