微信小程序接入AI API实现智能问答功能(以百度智能云为例)

1.老规矩,先讲故事

这天我的微信小程序想实现接入一个AI页面实现用户AI智能问答功能,但发现网络上大家都比较吝啬,要么要开会员,要么不分享。导致我走了好多弯路,最后也明白了一些道理,掌握了一些新的知识。

2.AI问答功能的实现

这部分直接上代码吧(主要两个文件,小程序前端页面js文件与服务端云函数index.js文件)

//页面js文件
const app = getApp()

Page({
  data: {
    chatList: [],
    inputValue: '',
    loading: false,
    scrollToView: '',
    loadingText: '发送中...'
  },

  onLoad() {
    // 初始化聊天列表
    this.setData({
      chatList: [{
        role: 'assistant',
        content: '你好!我是徒步小智,有什么我可以帮你的吗?'
      }]
    })
  },

  onInput(e) {
    this.setData({
      inputValue: e.detail.value
    })
  },

  async sendMessage() {
    if (!this.data.inputValue.trim() || this.data.loading) return

    const userMessage = this.data.inputValue.trim()
    this.setData({
      chatList: [...this.data.chatList, {
        role: 'user',
        content: userMessage
      }],
      inputValue: '',
      loading: true,
      loadingText: '正在思考中...'
    })

    this.scrollToBottom()

    try {
      const maxRetries = 2
      let retryCount = 0
      let success = false

      while (retryCount <= maxRetries && !success) {
        try {
          //wx.cloud.callFunction调用该云函数
          const response = await wx.cloud.callFunction({
            name: 'aiChat',
            data: {
              message: userMessage
            }
          })

          if (response.result && response.result.data && response.result.data.result) {
            this.setData({
              chatList: [...this.data.chatList, {
                role: 'assistant',
                content: response.result.data.result
              }],
              loading: false,
              loadingText: '发送中...'
            })
            success = true
          } else {
            throw new Error('无效的响应数据')
          }
        } catch (error) {
          retryCount++
          if (retryCount <= maxRetries) {
            this.setData({
              loadingText: `重试第${retryCount}次...`
            })
            await new Promise(resolve => setTimeout(resolve, 1000))
          } else {
            throw error
          }
        }
      }

      this.scrollToBottom()
    } catch (error) {
      console.error('AI API调用失败:', error)
      this.setData({
        chatList: [...this.data.chatList, {
          role: 'assistant',
          content: '抱歉,我现在有点忙,请稍后再试。'
        }],
        loading: false,
        loadingText: '发送中...'
      })
      wx.showToast({
        title: '请求超时,请稍后重试',
        icon: 'none',
        duration: 2000
      })
    }
  },

  scrollToBottom() {
    const length = this.data.chatList.length
    if (length > 0) {
      this.setData({
        scrollToView: `msg-${length - 1}`
      })
    }
  }
})
//云函数/cloudfunctions/aiChat/index.js文件
const cloud = require('wx-server-sdk')
const axios = require('axios')

cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV
})

//定义一个云函数入口,使用async声明异步函数
exports.main = async (event, context) => {
  //从事件对象中解构出用户输入的message参数
  const { message } = event

  try {
    //axios({ method: 'POST', ... })使用axios发起POST请求
    const response = await axios({
      method: 'POST',
      url: 'https://qianfan.baidubce.com/v2/chat/completions',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer bce-v3/xxxxxx/xxxxxx'
      },
      data: {
        model: "ernie-3.5-8k",
        messages: [
          {
            role: "user",
            content: message
          }
        ]
      }
    })

    // 从响应数据中提取AI助手的回复内容
    const aiContent = response.data.choices[0].message.content

    return {
      code: 200,
      data: {
        result: aiContent
      }
    }
  } catch (error) {
    console.error('API调用错误:', error)
    return {
      code: 500,
      error: error.message
    }
  }
}

3.需要注意的问题

1.跨域问题

先说一下,我使用的是百度智能云千帆大模型服务与开发平台ModelBuilder。这是他的官方api调用示例


curl -X POST 'https://qianfan.baidubce.com/v2/chat/completions'   -H 'Content-Type: application/json'   -H 'Authorization: Bearer bce-v3/ALTAK-*****************/2d7*****************'   -d '{
    "model": "ernie-3.5-8k",
    "messages": [
        {
            "role": "user",
            "content": "你好"
        }
    ]
  }'

 我在postman上面进行测试,发现上面是完全可行的,但当我页面js文件使用 wx.request()无法实现AI API的调用。这让我十分不解,我也去配置了不检验域名,设置了域名白名单。还是无法解决,后来将调用API放进云函数使用axios网络请求库解决实现了调用。

真相大白

经过我的不蟹探究,最后发现是跨域问题。

一、跨域问题的本质
  1. 浏览器安全策略

    • 跨域限制(CORS)是浏览器强制的安全机制

    • 只存在于浏览器环境(包括小程序)

    • 服务端之间的通信没有跨域概念

  2. 错误表现示例

    // 前端直接调用会出现的错误
    Access to XMLHttpRequest at 'https://qianfan.baidubce.com/...' from origin 'https://your-domain.com'
    has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource
二、两种场景对比
场景1:前端直接调用(失败)
sequenceDiagram
    participant 浏览器/小程序 as 前端
    participant 百度API as 服务端
    前端->>服务端: wx.request(带Authorization头)
    服务端-->>前端: 响应(无CORS头)
    浏览器拦截响应 ❌

关键问题

  1. 百度API响应头没有设置 Access-Control-Allow-Origin: *

  2. 浏览器/小程序引擎拒绝解析响应

场景2:云函数中转(成功)
sequenceDiagram
    participant 浏览器/小程序 as 前端
    participant 云函数 as 服务端
    participant 百度API as 服务端
    前端->>云函数: wx.cloud.callFunction(安全)
    云函数->>百度API: axios请求(服务端到服务端)✅
    百度API-->>云函数: 原始响应(无CORS限制)
    云函数-->>前端: 返回清洗后的数据

成功关键

  1. 前端与云函数同源(或云函数已配置CORS)

  2. 云函数到百度API是服务端间通信,不受浏览器策略限制


三、云函数的优势详解
  1. 网络层面

    • 云函数部署在腾讯云/阿里云等服务器

    • 默认拥有公网访问能力

    • 无需处理证书、代理等复杂配置

  2. 协议层面

    • 服务端之间使用标准HTTP/HTTPS协议

    • 无需处理CORS、OPTIONS预检请求

  3. 安全层面

    • 前端永远看不到API密钥

    • 可在云函数做请求限流、内容过滤

    • 避免直接暴露API端点

在我的例子中,前端wx.request链接https://qianfan.baidubce.com服务端会发生跨域问题使无法正确返回,如果放云函数里使用axios方法就是服务端-服务端,就不会有不会有跨域问题

四、为什么小程序用wx.request失败?

根本原因链

小程序未配置域名白名单 → 百度API未设置CORS头 → 小程序引擎拦截响应 → 开发者工具Network显示请求被blocked

具体限制

  1. 小程序要求所有请求域名必须加入request合法域名列表

  2. 即使你配置了qianfan.baidubce.com,百度服务器也不会返回CORS头

  3. 双重限制下必然失败


五、最终结论

通过云函数中转的本质,是把原本需要浏览器处理的跨域请求,转换为服务端之间的自由通信。这种方案:

  • ✅ 彻底规避跨域问题

  • ✅ 提升安全性

  • ✅ 符合企业级应用规范

这是所有主流应用(如ChatGPT、文心一言官方应用)采用的架构设计,也是唯一符合安全规范的实现方式。

2.超时问题

在我的跨域问题解决后又发生了一个问题:
 

{"errorCode":-1,"errorMessage":"Invoking task timed out after 3 seconds","statusCode":433}

于是首先我在\miniprogram\cloudfunctions\aiChat\config.json中设置了

{
  "permissions": {
    "openapi": []
  },
  "timeout": 60,
  "triggers": [],
  "memorySize": 256
} 

但发现不起作用,于是,我又在云开发里设置超时时间改为了33s,成功解决了该问题(AI思考时间一般较长,默认3s肯定无法正确返回数据)

🆗,又是被bug上了一课的一天,下课!(看到这了,点个赞呗!)

### 集成AI功能微信小程序 #### 小程序AI API对接基础 在开发过程中,为了使微信小程序能够利用人工智能技术,开发者通常会通过网络请求的方式调用微信官方或其他第三方提供的AI服务API。这涉及到使用`wx.request()`方法来发送HTTP(S)请求到指定的服务端口,从而获取由该服务处理后的响应数据[^1]。 ```javascript // 发起AI服务请求示 wx.request({ url: 'https://example.com/ai-service', // 替换为目标AI服务的实际URL method: 'POST', data: { text: "待分析的文字内容" }, header: { 'content-type': 'application/json' // 默认值 }, success(res){ console.log('成功接收到来自AI服务的数据:', res.data); } }) ``` #### 使用模态对话框展示AI结果 当从小程序向外部AI服务发起请求并接收到返回的结果之后,可以考虑采用模态对话框的形式将这些信息呈现给用户。这样不仅可以让用户体验更加友好,同时也便于管理界面上的信息流控制。 ```javascript function showAIData(data){ wx.showModal({ title: '来自AI的建议', content: JSON.stringify(data), showCancel:false, confirmText:"知道了", success:function(){ // 用户点击确认按钮后的逻辑... } }) } ``` #### 数据缓存优化体验 考虑到某些情况下频繁访问同一份AI资源可能会造成不必要的延迟或浪费流量,因此合理运用本地存储机制(如`wx.setStorageSync`)保存已经获得过的有效期内的数据副本不失为一种提高效率的好办法[^2]。 ```javascript try{ var cachedData = wx.getStorageSync('cached_ai_data'); if(cachedData !== ''){ // 如果存在未过期的有效缓存,则直接显示 showAIData(JSON.parse(cachedData)); }else{ // 否则重新请求最新数据,并更新缓存 requestAndCacheNewData(); } }catch(e){} ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值