微信小程序集成 AI 对话功能:基于 Cogito 模型部署指南
本文介绍如何在微信小程序中集成智能对话功能。用户可以在小程序里提问,并获得 AI 生成的回答。实现这一功能需要解决小程序调用外部 AI 接口、网络延迟处理及对话历史存储等问题。
本方案选用 Cogito-V1-Preview-Llama-3B 模型,该模型体积适中且能力均衡,适合部署在服务器上为小程序提供服务。
在微信小程序中集成 AI 对话功能的完整流程。主要步骤包括:准备小程序账号与后端服务器;使用 Python FastAPI 搭建后端 API,对接 Cogito 模型并提供 CORS 支持;开发小程序前端页面,实现聊天界面布局、消息发送及历史缓存;针对网络延迟、上下文长度限制及内容安全等关键问题进行优化。最终实现了一个流畅的多轮对话体验。
本文介绍如何在微信小程序中集成智能对话功能。用户可以在小程序里提问,并获得 AI 生成的回答。实现这一功能需要解决小程序调用外部 AI 接口、网络延迟处理及对话历史存储等问题。
本方案选用 Cogito-V1-Preview-Llama-3B 模型,该模型体积适中且能力均衡,适合部署在服务器上为小程序提供服务。
在动手写代码之前,需先理清流程:用户在微信小程序输入问题,小程序将请求发送给后端服务器,服务器调用 AI 模型处理后返回答案。
由于微信小程序不能直接随意访问外网,需要一个后端服务器作为中间人。该服务器部署在 GPU 平台上,运行 Cogito 模型。
你需要准备的东西:
https://your-server-address/v1/chat/completions)。关于模型选择:Cogito-V1-Preview-Llama-3B 参数量为 30 亿,在轻量级模型中表现均衡,对话能力和逻辑推理够用,生成速度较快,对服务器资源要求较低,适合作为小程序后端服务。
后端工作主要是提供一个 API 接口。小程序发送对话内容,后端调用 Cogito 模型生成回复并传回。这里使用 Python 的 FastAPI 框架,因其轻快,适合 IO 密集型网络服务。
首先确保服务器已部署好模型并能通过代码调用。
第一步,安装必要的包:
pip install fastapi uvicorn httpx
httpx 用于作为 HTTP 客户端,请求部署的模型服务。
第二步,编写核心的后端 API: 在项目根目录创建 main.py 文件。
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
import httpx
import json
from pydantic import BaseModel
from typing import List, Optional
# 定义请求体的数据模型
class ChatMessage(BaseModel):
role: str
content: str
class ChatRequest(BaseModel):
messages: List[ChatMessage]
max_tokens: Optional[int] = 500
# 初始化 FastAPI 应用
app = FastAPI(title="小程序 AI 对话后端")
# 配置 CORS(跨域资源共享)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 替换成你部署在 GPU 平台上的 Cogito 模型 API 地址
MODEL_API_URL = "https://your-mirror-server-address/v1/chat/completions"
@app.post("/chat")
async def chat_with_ai(request: ChatRequest):
"""处理小程序发来的聊天请求。"""
payload = {
"model": "cogito-v1-preview-llama-3b",
"messages": [msg.dict() for msg in request.messages],
"max_tokens": request.max_tokens,
"stream": False
}
async with httpx.AsyncClient(timeout=30.0) as client:
try:
response = await client.post(MODEL_API_URL, json=payload)
response.raise_for_status()
result = response.json()
ai_reply = result["choices"][0]["message"]["content"]
return {"reply": ai_reply}
except httpx.RequestError as e:
raise HTTPException(status_code=503, detail=f"无法连接 AI 服务:{str(e)}")
except (KeyError, IndexError, json.JSONDecodeError) as e:
raise HTTPException(status_code=500, detail=f"解析 AI 响应时出错:{str(e)}")
except Exception as e:
raise HTTPException(status_code=500, detail=f"服务器内部错误:{str(e)}")
@app.get("/health")
async def health_check():
return {"status": "ok", "service": "mini-program-ai-backend"}
代码说明:
CORSMiddleware 是重中之重,没有它,小程序无法调用此接口。/chat 接口,接收包含对话历史的 messages,支持多轮对话。{"reply": "..."}。运行后端: 在服务器上运行:
uvicorn main:app --host 0.0.0.0 --port 8000 --reload
服务将在 http://你的服务器 IP:8000 上运行,可通过浏览器访问 /health 测试。
创建聊天页面 pages/chat/chat。
chat.wxml
<!-- pages/chat/chat.wxml -->
<view>
<scroll-view scroll-y scroll-into-view="{{'msg-' + (messageList.length - 1)}}" scroll-with-animation>
<block wx:for="{{messageList}}" wx:key="index">
<view>
<image wx:if="{{item.role === 'user'}}" src="/images/user-avatar.png"></image>
<image wx:else src="/images/ai-avatar.png"></image>
<text>{{item.content}}</text>
<view wx:if="{{item.role === 'assistant' && item.loading}}">
<text>.</text><text>.</text><text>.</text>
</view>
</view>
</block>
</scroll-view>
<view>
<input value="{{inputValue}}" bindinput="onInput" placeholder="输入你的问题..." confirm-type="send" bindconfirm="sendMessage" focus="{{autoFocus}}" />
<button bindtap="sendMessage" disabled="{{isSending}}"> {{isSending ? '发送中' : '发送'}} </button>
</view>
</view>
chat.wxss
/* pages/chat/chat.wxss */
.chat-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%;
}
.bubble {
max-width: 65%;
padding: 20rpx 30rpx;
border-radius: 12rpx;
margin: 0 20rpx;
word-break: break-word;
line-height: 1.5;
}
.user .bubble {
background-color: #95ec69;
color: #000;
}
.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;
padding: 20rpx 30rpx;
border: 1rpx solid #ddd;
border-radius: 40rpx;
margin-right: 20rpx;
font-size: 28rpx;
}
.send-btn {
background-color: #07c160;
color: white;
border-radius: 40rpx;
padding: 0 40rpx;
font-size: 28rpx;
}
.send-btn[disabled] {
background-color: #ccc;
}
chat.js
// pages/chat/chat.js
const API_BASE_URL = 'https://your-backend-server.com';
Page({
data: {
inputValue: '',
messageList: [],
isSending: false,
autoFocus: true,
},
onLoad() {
const history = wx.getStorageSync('aiChatHistory');
if (history && Array.isArray(history)) {
this.setData({ messageList: history });
}
},
onInput(e) {
this.setData({ inputValue: e.detail.value });
},
async sendMessage() {
const { inputValue, messageList, isSending } = this.data;
if (!inputValue.trim() || isSending) return;
const userMessage = { role: 'user', content: inputValue };
const newList = [...messageList, userMessage];
this.setData({
messageList: newList,
inputValue: '',
isSending: true,
});
const thinkingMessage = { role: 'assistant', content: '', loading: true };
this.setData({ messageList: [...newList, thinkingMessage] });
const requestMessages = newList.map(msg => ({ role: msg.role, content: msg.content }));
try {
const response = await new Promise((resolve, reject) => {
wx.request({
url: `${API_BASE_URL}/chat`,
method: 'POST',
data: { messages: requestMessages, max_tokens: 300 },
header: { 'content-type': 'application/json' },
success: resolve,
fail: reject,
});
});
if (response.statusCode === 200) {
const aiReply = response.data.reply;
const finalList = [...newList];
finalList.pop();
finalList.push({ role: 'assistant', content: aiReply });
this.setData({ messageList: finalList });
wx.setStorageSync('aiChatHistory', finalList);
} else {
throw new Error(`请求失败:${response.statusCode}`);
}
} catch (error) {
console.error('发送消息失败:', error);
wx.showToast({ title: '网络好像不太给力,请稍后再试', icon: 'none' });
const finalList = [...newList];
finalList.pop();
this.setData({ messageList: finalList });
} finally {
this.setData({ isSending: false });
}
},
});
关键点解析:
messageList,实现多轮聊天。历史记录保存在本地缓存。AI 生成文本需要时间。方案是'立即显示 + 加载动画',让用户感知程序正在工作。
模型上下文长度有限。可在后端接口处理前裁剪传入的 messages 列表。
# 在 main.py 中添加裁剪函数
def trim_messages(messages: List[ChatMessage], max_history_turns: int = 10) -> List[ChatMessage]:
if len(messages) <= max_history_turns * 2:
return messages
return messages[-(max_history_turns * 2):]
# 在 chat_with_ai 中调用
trimmed_messages = trim_messages(request.messages, max_history_turns=5)
payload = {
"model": "cogito-v1-preview-llama-3b",
"messages": [msg.dict() for msg in trimmed_messages],
# ... 其他参数
}
只保留最近 5 轮对话,维持上下文且不超限。
可对 AI 回复进行后处理,过滤敏感词或调整格式。
def postprocess_reply(text: str) -> str:
sensitive_words = ["暴力", "仇恨"]
for word in sensitive_words:
if word in text:
text = text.replace(word, "**")
if len(text.strip()) < 5:
return "我好像没太明白你的意思,能换个方式问问吗?"
return text.strip()
在微信小程序中集成 AI 对话功能,核心思路是'前端收集对话,后端转发处理'。技术难点在于小程序框架下的网络通信、状态管理和用户体验优化。
建议先按流程搭建最小可用版本,再根据业务需求添加历史记录清空、语音输入等功能。最重要的是从用户角度考虑,让 AI 助手用起来更自然。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online