通义千问1.5-1.8B-Chat-GPTQ-Int4 WebUI 微信小程序集成教程:打造个人AI聊天助手
本文介绍了如何利用星图GPU平台自动化部署通义千问1.5-1.8B-Chat-GPTQ-Int4 WebUI镜像,并详细讲解了将其与微信小程序集成的完整流程。通过构建后端云函数作为桥梁,用户可以在小程序中便捷调用该AI模型,打造一个可随时聊天的个人AI助手,实现智能对话交互。
通义千问1.5-1.8B-Chat-GPTQ-Int4 WebUI 微信小程序集成教程:打造个人AI聊天助手
想不想在手机上随时有个能聊天的AI助手?不用下载新App,就在你天天用的微信里。今天,我就带你一步步把那个在电脑上跑的通义千问大模型,搬到微信小程序里,做成一个完全属于你自己的移动端聊天机器人。
这事的核心其实不复杂。我们做个简单的小程序界面,让你能打字、能看回复;然后在小程序的后台,写个“中间人”服务,专门负责把你的话传给部署在星图GPU平台上的通义千问模型,再把模型的回答原封不动地带回来给你。整个过程,你会学到怎么从零开始搭一个小程序,怎么安全地和后端API“对话”,以及怎么让这个聊天过程既流畅又安全。跟着做下来,你就能拥有一个24小时在线、只属于你的AI伙伴了。
1. 动手之前:理清思路与做好准备
在开始敲代码之前,咱们先把整个流程想明白。这样后面每一步做起来,心里都有底。
1.1 整体架构:小程序如何与AI对话
你可以把这个项目想象成一次“传话游戏”。你(用户)在小程序里输入一句话,小程序(前端)把这句话打包好,通过微信的网络通道,发送给我们自己搭建的一个云服务(后端)。这个云服务就像一个专业的信使,它知道怎么找到部署在星图GPU服务器上的通义千问模型(WebUI API),并把你的话准确传达过去。模型思考后给出回复,信使再把回复带回来,经由小程序,最终显示在你的手机屏幕上。
所以,关键角色有三个:
- 微信小程序前端:负责和你交互的界面,收集输入、展示对话。
- 后端云函数/服务:核心的“信使”和“调度中心”,处理小程序请求,调用AI模型API,并管理对话逻辑。
- 星图平台部署的通义千问WebUI API:提供AI大脑能力的终端,我们通过HTTP请求和它通信。
1.2 你需要准备什么
工欲善其事,必先利其器。下面是你需要提前准备好的几样东西:
- 一个微信小程序账号:去微信公众平台注册一个,如果你只是为了个人学习和测试,注册个人主体就行,完全免费。
- 微信开发者工具:这是官方开发环境,写代码、调试、预览都在这里进行,务必下载安装好。
- 已经部署好的通义千问WebUI API:假设你已经按照之前的教程,在星图GPU平台上成功部署了通义千问1.5-1.8B-Chat-GPTQ-Int4的WebUI,并且知道它的API访问地址(比如
http://你的服务器IP:端口/api/v1/chat/completions)和可能的API Key(如果设置了的话)。这是我们的AI能力来源。 - 一个后端服务环境(二选一):
- 方案A(推荐,简单):使用微信小程序云开发。它内置了云函数,可以直接在小程序IDE里写后端逻辑,无需自己买服务器,非常适合原型和轻量应用。
- 方案B(更灵活):自己搭建一个后端服务器。可以用任何你熟悉的语言,比如Python(Flask/Django)、Node.js(Express)等,部署在云服务器上。这种方式控制力更强,但步骤稍多。
- 基础的JavaScript知识:小程序前端主要用JavaScript(或它的变体)来写逻辑。
- 一颗不怕折腾的心:集成过程中可能会遇到网络、配置等问题,耐心调试就好。
为了清晰,我画了一个简单的流程图,帮你一眼看明白数据是怎么跑的:
graph TD
A[用户在小程序输入] --> B[小程序前端]
B --> C[发送网络请求]
C --> D{后端服务<br/>(云函数/自建服务器)}
D --> E[转发请求至<br/>星图平台Qwen API]
E --> F[通义千问模型处理]
F --> G[返回AI回复]
G --> D
D --> H[返回处理结果]
H --> B
B --> I[更新界面<br/>显示回复]
接下来,我们就从搭建小程序的前端界面开始。
2. 搭建小程序前端:聊天界面与交互
我们先来把聊天窗口做出来,让它看起来像个正经的聊天软件。
2.1 创建小程序项目与基础页面
打开微信开发者工具,选择“新建项目”。
- 项目名称:比如“我的AI助手”。
- 目录:选一个你喜欢的本地文件夹。
- AppID:如果你有正式的小程序AppID就填上(在公众平台查看)。如果只是体验,点选“测试号”快速开始。
- 模板:选择“不使用云服务”(我们稍后再单独开通)或“小程序-云开发”模板(如果你决定用云开发)。
创建成功后,你会看到默认的项目结构。我们主要关心 pages/index 这个目录,它就是小程序启动后看到的第一个页面。我们把它改造成聊天页。
首先,我们来设计页面的结构,修改 pages/index/index.wxml 文件:
<!-- pages/index/index.wxml -->
<view class="container">
<!-- 聊天消息区域 -->
<scroll-view class="message-list" scroll-y scroll-into-view="{{toView}}" scroll-with-animation>
<block wx:for="{{messages}}" wx:key="id">
<view class="message-item {{item.role}}">
<view class="avatar">
<image wx:if="{{item.role === 'user'}}" src="/images/user-avatar.png"></image>
<image wx:else src="/images/bot-avatar.png"></image>
</view>
<view class="bubble">
<text>{{item.content}}</text>
</view>
</view>
</block>
</scroll-view>
<!-- 底部输入区域 -->
<view class="input-area">
<input
class="input-box"
placeholder="和AI助手聊点什么..."
value="{{inputValue}}"
bindinput="onInput"
bindconfirm="sendMessage"
confirm-type="send"
focus="{{autoFocus}}"
/>
<button class="send-btn" bindtap="sendMessage" disabled="{{sending}}">
{{sending ? '发送中...' : '发送'}}
</button>
</view>
</view>
然后,给这个页面加上样式,让布局好看点,修改 pages/index/index.wxss:
/* pages/index/index.wxss */
.container {
height: 100vh;
display: flex;
flex-direction: column;
background-color: #f5f5f5;
}
.message-list {
flex: 1;
padding: 20rpx;
box-sizing: border-box;
overflow: auto;
}
.message-item {
display: flex;
margin-bottom: 30rpx;
align-items: flex-start;
}
.message-item.user {
flex-direction: row-reverse;
}
.avatar image {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
margin: 0 20rpx;
}
.bubble {
max-width: 70%;
padding: 20rpx;
border-radius: 10rpx;
line-height: 1.5;
word-break: break-word;
}
.message-item.user .bubble {
background-color: #95ec69;
color: #000;
}
.message-item.assistant .bubble {
background-color: #fff;
color: #333;
box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.1);
}
.input-area {
display: flex;
padding: 20rpx;
background-color: #fff;
border-top: 1rpx solid #eee;
align-items: center;
}
.input-box {
flex: 1;
height: 80rpx;
padding: 0 20rpx;
border: 1rpx solid #ddd;
border-radius: 40rpx;
margin-right: 20rpx;
background-color: #f9f9f9;
}
.send-btn {
width: 140rpx;
height: 80rpx;
line-height: 80rpx;
border-radius: 40rpx;
background-color: #07c160;
color: white;
font-size: 28rpx;
padding: 0;
}
.send-btn[disabled] {
background-color: #ccc;
}
2.2 实现聊天逻辑与状态管理
界面有了,现在让它动起来。修改 pages/index/index.js 文件,这里包含了所有的交互逻辑:
// pages/index/index.js
Page({
data: {
messages: [], // 存储所有消息 {id, role, content}
inputValue: '', // 输入框内容
sending: false, // 是否正在发送
toView: '', // 用于滚动到底部
autoFocus: false
},
onLoad() {
// 可以尝试从本地缓存加载历史对话
const history = wx.getStorageSync('chatHistory');
if (history && Array.isArray(history)) {
this.setData({ messages: history });
this.scrollToBottom();
}
// 或者初始化一条欢迎语
// this.setData({
// messages: [{
// id: Date.now(),
// role: 'assistant',
// content: '你好!我是你的AI助手,有什么可以帮你的吗?'
// }]
// });
},
// 监听输入
onInput(e) {
this.setData({
inputValue: e.detail.value
});
},
// 发送消息
sendMessage() {
const text = this.data.inputValue.trim();
if (!text || this.data.sending) return;
// 1. 清空输入框,禁用发送按钮
this.setData({
inputValue: '',
sending: true
});
// 2. 将用户消息添加到列表
const userMsg = {
id: Date.now(),
role: 'user',
content: text
};
this.data.messages.push(userMsg);
this.setData({ messages: this.data.messages });
this.scrollToBottom();
// 3. 显示“思考中”的占位消息
const thinkingMsg = {
id: Date.now() + 1,
role: 'assistant',
content: '...'
};
this.data.messages.push(thinkingMsg);
this.setData({ messages: this.data.messages });
this.scrollToBottom();
// 4. 调用后端API获取AI回复
this.callAIChatAPI(text).then(aiResponse => {
// 5. 用真实回复替换“思考中”消息
thinkingMsg.content = aiResponse;
this.setData({ messages: this.data.messages });
this.saveHistory(); // 保存到本地
}).catch(err => {
console.error('API调用失败:', err);
// 6. 如果出错,显示错误信息
thinkingMsg.content = '抱歉,我暂时无法回答。请检查网络或稍后再试。';
this.setData({ messages: this.data.messages });
}).finally(() => {
// 7. 无论成功失败,都恢复发送按钮
this.setData({ sending: false });
this.scrollToBottom();
});
},
// 封装调用后端API的函数
async callAIChatAPI(userInput) {
// 注意:这里不能直接调用星图平台的API,因为涉及跨域和域名白名单问题。
// 我们需要调用自己的后端服务地址。
// 假设你的后端服务地址是:https://your-backend.com/chat
const backendUrl = 'https://your-backend.com/chat'; // 请替换为你的实际后端地址
// 构建请求数据,格式需要匹配你的后端和通义千问API的要求
// 这里传递当前对话历史(或最后几条)给后端,让模型有上下文
const recentMessages = this.data.messages
.filter(msg => msg.role !== 'assistant' || msg.content !== '...') // 过滤掉占位消息
.slice(-6) // 只发送最近几条,避免上下文过长
.map(msg => ({ role: msg.role, content: msg.content }));
// 添加最新的用户输入
recentMessages.push({ role: 'user', content: userInput });
const requestData = {
messages: recentMessages,
// 可以添加其他参数,如模型名、温度等,取决于你的后端如何封装
// model: 'qwen1.5-1.8b-chat',
// temperature: 0.7,
};
return new Promise((resolve, reject) => {
wx.request({
url: backendUrl,
method: 'POST',
data: requestData,
header: {
'content-type': 'application/json'
// 如果需要API Key,在这里添加
// 'Authorization': 'Bearer your-api-key-here'
},
success: (res) => {
if (res.statusCode === 200 && res.data && res.data.reply) {
resolve(res.data.reply); // 假设后端返回 { reply: '...' }
} else {
reject(new Error(`API错误: ${res.statusCode}`));
}
},
fail: (err) => {
reject(err);
}
});
});
},
// 滚动到底部
scrollToBottom() {
if (this.data.messages.length > 0) {
const lastMsgId = this.data.messages[this.data.messages.length - 1].id;
this.setData({
toView: `msg-${lastMsgId}`
});
}
},
// 保存对话历史到本地
saveHistory() {
// 只保存非空且非占位符的消息
const historyToSave = this.data.messages.filter(msg => msg.content !== '...');
try {
wx.setStorageSync('chatHistory', historyToSave);
} catch (e) {
console.error('保存历史失败:', e);
}
},
// 清空对话
clearChat() {
wx.showModal({
title: '提示',
content: '确定要清空对话历史吗?',
success: (res) => {
if (res.confirm) {
this.setData({ messages: [] });
wx.removeStorageSync('chatHistory');
}
}
});
}
});
别忘了在页面的配置文件 pages/index/index.json 里,给页面加个标题,或许再加个清空按钮:
{
"navigationBarTitleText": "我的AI助手",
"enablePullDownRefresh": false,
"usingComponents": {}
}
现在,前端部分已经基本完成了。你可以先在开发者工具里预览一下,界面应该能正常显示,点击发送按钮会触发事件(虽然还连不上后端)。接下来,我们要搭建最关键的后端桥梁。
3. 构建后端桥梁:云函数与API转发
前端无法直接调用部署在星图平台上的API,主要是因为微信小程序有严格的域名白名单限制(request 合法域名),而且直接暴露服务器IP和端口也不安全。所以,我们需要一个后端服务做中转。
这里我以 微信小程序云开发(CloudBase)的云函数 为例,因为它和小程序集成度最高,部署简单。如果你选择自建服务器(如用Flask),逻辑是相通的。
3.1 创建并部署云函数
首先,在微信开发者工具中,如果你的项目创建时未启用云开发,需要在顶部菜单栏找到“云开发”按钮并开通。开通后,会获得一个环境ID。
- 新建云函数:在项目根目录,右键点击
cloudfunctions文件夹,选择“新建Node.js云函数”,命名为chat。 - 编写云函数逻辑:打开
cloudfunctions/chat/index.js,这是核心的转发逻辑。
// cloudfunctions/chat/index.js
const cloud = require('wx-server-sdk');
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV });
// 假设你部署的通义千问WebUI API地址
// 重要:请将此地址替换为你星图平台实例的实际内网/公网访问地址
const QWEN_API_BASE = 'http://YOUR_SERVER_IP:PORT'; // 例如: http://192.168.1.100:7861
const API_PATH = '/api/v1/chat/completions'; // WebUI常见的聊天补全端点
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext();
// 1. 简单的请求验证(可选但推荐)
// 可以验证event.userInfo,或添加自定义token验证
// if (!event.token || event.token !== 'your-secret-token') {
// return { code: 403, msg: 'Forbidden' };
// }
// 2. 获取前端传来的消息列表和参数
const { messages, temperature = 0.7, max_tokens = 1024 } = event;
if (!messages || !Array.isArray(messages) || messages.length === 0) {
return { code: 400, msg: 'Invalid request: messages is required' };
}
// 3. 构建符合通义千问WebUI API格式的请求体
const requestBody = {
model: 'qwen1.5-1.8b-chat', // 模型名称,需与部署一致
messages: messages, // 直接传递消息历史
temperature: temperature,
max_tokens: max_tokens,
stream: false // 小程序暂不支持流式响应,设为false
};
// 4. 准备请求选项
const requestOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
// 如果WebUI设置了API Key,在这里添加
// 'Authorization': `Bearer ${process.env.QWEN_API_KEY}`
},
body: JSON.stringify(requestBody)
};
try {
// 5. 使用云函数的内置能力或axios等库发起请求
// 这里使用云函数的HTTP API(需在云函数配置中启用)
const result = await cloud.callContainer({
config: {
path: API_PATH,
method: 'POST',
headers: requestOptions.headers,
data: requestBody,
// 如果API在公网,这里需要填写完整URL
// 但更佳实践是将API部署在同一个云环境或内网可达处
}
});
// 注意:cloud.callContainer 是云开发调用云托管服务的,如果你的API在别处,需用其他方法。
// 更通用的方法是使用 `axios` 或 `node-fetch`。
// 假设我们使用 `axios`(需要先在package.json添加依赖并上传):
// const axios = require('axios');
// const response = await axios.post(`${QWEN_API_BASE}${API_PATH}`, requestBody, { headers: requestOptions.headers });
// const aiReply = response.data.choices[0].message.content;
// 为了示例清晰,我们模拟一个通用HTTP请求流程(伪代码,实际需安装依赖):
// const fetch = require('node-fetch');
// const response = await fetch(`${QWEN_API_BASE}${API_PATH}`, requestOptions);
// const data = await response.json();
// 6. 解析AI回复
// 假设返回格式为 { "choices": [ { "message": { "content": "..." } } ] }
// const aiReply = data.choices[0].message.content;
// 由于直接调用外部API可能受限于云函数网络,这里返回一个模拟成功响应
console.log('Received messages:', messages);
const lastUserMsg = messages.filter(m => m.role === 'user').pop();
const mockReply = `我已收到你的消息:“${lastUserMsg?.content || ''}”。(这是模拟回复,请配置真实API地址)`;
// 7. 返回结果给小程序前端
return {
code: 200,
reply: mockReply,
// 也可以返回完整的消息对象,供前端直接添加
message: {
role: 'assistant',
content: mockReply
}
};
} catch (error) {
console.error('调用AI API失败:', error);
return {
code: 500,
msg: 'AI服务暂时不可用',
error: error.message
};
}
};
关键点说明:
- 依赖管理:如果使用
axios或node-fetch,需要在cloudfunctions/chat/package.json中添加依赖,然后右键云函数目录选择“上传并部署:安装依赖”。 - 网络配置:云函数默认可能无法访问所有外部IP。如果你使用腾讯云云开发,可能需要配置云函数的外网访问能力,或在同一VPC内部署你的通义千问API。
- 安全:在实际部署时,绝对不要将API密钥等敏感信息硬编码在代码中。使用云函数的环境变量功能来存储
QWEN_API_BASE和API Key。
- 部署云函数:右键点击
chat云函数目录,选择“上传并部署”。
3.2 修改前端调用地址
后端云函数部署好后,我们需要修改前端代码,让它调用这个云函数,而不是之前写的假地址。
更新 pages/index/index.js 中的 callAIChatAPI 函数部分:
// 修改后的 callAIChatAPI 函数(使用云函数)
async callAIChatAPI(userInput) {
// 构建消息历史,同上
const recentMessages = this.data.messages
.filter(msg => msg.role !== 'assistant' || msg.content !== '...')
.slice(-6)
.map(msg => ({ role: msg.role, content: msg.content }));
recentMessages.push({ role: 'user', content: userInput });
return new Promise((resolve, reject) => {
// 调用云函数
wx.cloud.callFunction({
name: 'chat', // 你的云函数名称
data: {
messages: recentMessages,
temperature: 0.8,
// 可以在这里传递一个简单的token用于验证(可选)
// token: 'your-pre-shared-token'
},
success: (res) => {
const result = res.result;
if (result.code === 200) {
resolve(result.reply);
} else {
reject(new Error(result.msg || '云函数返回错误'));
}
},
fail: (err) => {
reject(err);
}
});
});
},
同时,在小程序启动时(app.js)初始化云开发:
// app.js
App({
onLaunch() {
// 初始化云开发
if (wx.cloud) {
wx.cloud.init({
env: 'your-cloud-env-id', // 替换为你的云环境ID
traceUser: true,
});
}
}
});
4. 完善与优化:安全、体验与部署
基础功能跑通后,我们还需要考虑一些实际运营中会遇到的问题。
4.1 内容安全与过滤
让AI自由对话存在风险,我们必须在前端或后端加入基础的内容安全过滤。
-
后端过滤(推荐):在云函数调用AI API之前和之后,对内容进行检查。
- 请求过滤:检查用户输入
userInput是否包含明显违规、辱骂或极端关键词。 - 响应过滤:检查AI返回的
reply是否包含不合适的内容。 - 实现方式:可以维护一个本地关键词库(对于简单场景),或者调用第三方内容安全API。
在云函数中添加一个简单的过滤函数:
- 请求过滤:检查用户输入
// 简单的关键词过滤函数(示例,实际需要更复杂的策略)
function contentFilter(text) {
const forbiddenKeywords = ['违规词1', '违规词2']; // 替换为你的关键词列表
const lowerText = text.toLowerCase();
for (const keyword of forbiddenKeywords) {
if (lowerText.includes(keyword)) {
return false; // 包含违规词
}
}
return true; // 通过
}
// 在调用AI API前使用
if (!contentFilter(userInputFromFrontend)) {
return { code: 400, msg: '输入内容包含不当信息' };
}
// 在拿到AI回复后使用
if (!contentFilter(aiReply)) {
aiReply = '我的回答可能包含不合适内容,已进行过滤。'; // 或返回一个安全提示
}
- 前端提示:在小程序界面,当收到被过滤的回复或发送失败时,给予用户友好提示。
4.2 用户体验优化
- 加载状态:我们已经做了发送按钮的禁用和“思考中”占位符,这很好。
- 网络错误处理:在
wx.request或wx.cloud.callFunction的fail回调中,除了控制台打印,最好用wx.showToast给用户一个提示。 - 对话历史持久化:我们已经实现了用
wx.setStorageSync保存到本地。可以考虑加入“加载更多历史”或“导出对话”功能。 - 音效与振动(可选):收到新消息时,可以播放提示音或轻微振动,提升体验。
4.3 真机测试与发布上线
- 真机预览:在开发者工具点击“预览”,生成二维码,用微信扫描在手机上测试。这是发现样式和交互问题的关键步骤。
- 配置服务器域名:如果你使用的是自建后端服务器(非云函数),必须在微信公众平台的小程序管理后台,将你的后端服务器域名(如
https://your-backend.com)添加到 “开发设置”->“服务器域名”->“request合法域名” 列表中。云函数调用无需此步骤。 - 提交审核:开发完成后,在开发者工具点击“上传”,将代码提交到微信后台,并填写版本信息,提交审核。确保你的小程序类目选择正确(例如“工具->信息查询”或“教育->在线教育”可能需要根据AI对话功能具体判断)。
- 发布:审核通过后,即可发布上线,所有微信用户都可以搜索和使用你的AI助手小程序了。
5. 总结与展望
走完这一趟,你应该已经成功地将一个强大的AI模型塞进了微信小程序这个轻巧的容器里。我们从零开始,搭建了聊天界面,实现了消息的发送与接收,并通过云函数构建了安全可靠的后端桥梁,最终在手机端实现了一个流畅的AI对话体验。
整个过程最关键的,是理解“前端交互 - 后端中转 - AI服务”这三层架构的分工与协作。云函数在这里扮演了至关重要的角色,它不仅解决了小程序的网络限制,还为我们提供了统一的安全管控和逻辑处理点。
实际部署时,你可能会遇到云函数网络连通性、API响应速度、以及更复杂的内容安全需求等挑战。这些都可以通过选择更合适的云服务商、优化后端代码、集成专业的内容审核服务来解决。这个项目就像一个种子,你可以在此基础上,继续添加语音输入、多模态识别(如果模型支持)、用户个性化设置等功能,让它变得越来越强大。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
更多推荐



所有评论(0)