跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表

目录

  1. 项目概述
  2. 1. 环境准备
  3. 2. 后端搭建:让 AI 模型准备好接客
  4. 定义请求体的数据模型,这决定了小程序要传什么数据过来
  5. 初始化 FastAPI 应用
  6. 关键步骤:配置 CORS(跨域资源共享)
  7. 因为小程序的前端域名和咱们后端域名不同,不配置这个,请求会被浏览器拦截。
  8. 这里替换成你部署在后端服务器上的 Cogito 模型 API 地址
  9. 一个健康检查接口,用来测试后端是否正常启动
  10. 3. 前端开发:构建小程序的对话界面
  11. 3.1 页面布局与样式
  12. 3.2 核心逻辑与网络请求
  13. 4. 关键问题与优化方案
  14. 4.1 应对网络延迟:给用户一个“正在处理”的反馈
  15. 4.2 管理对话长度与上下文
  16. 在 main.py 的 chatwithai 函数中,添加一个裁剪历史的函数
  17. 在 chatwithai 函数中调用
  18. 4.3 提升回复质量与安全性
  19. 在 main.py 中,添加一个后处理函数
  20. 在 chatwithai 函数中,提取回复后调用
  21. 5. 总结
  • 💰 8折买阿里云服务器限时8折了解详情
PythonWeChatAI大前端

基于 Cogito-V1-Preview-Llama-3B 的微信小程序 AI 对话集成指南

详细讲解了在微信小程序中集成 Cogito-V1-Preview-Llama-3B 模型实现 AI 对话功能的完整流程。内容包括后端 FastAPI 服务搭建、前端聊天界面开发、网络请求逻辑、对话历史管理以及针对延迟和上下文的优化方案。通过代理模式连接小程序与 AI 模型,解决了跨域通信、状态管理及用户体验问题,提供了可落地的代码示例与最佳实践。

技术博主发布于 2026/4/5更新于 2026/4/2012 浏览

项目概述

本文介绍如何在微信小程序中集成 AI 对话功能,使用 Cogito-V1-Preview-Llama-3B 模型。核心流程为:用户输入 -> 小程序 -> 后端服务器 -> AI 模型 -> 返回结果。

1. 环境准备

在动手写代码之前,需理清整体流程。目标是用户在微信小程序里输入问题,小程序将问题发送给部署好的 AI 模型服务器,服务器处理完再把答案传回小程序显示给用户。

你需要准备的东西:

  1. 一个微信小程序账号:去微信公众平台注册,拿到小程序的 AppID。
  2. 一个后端服务器:需要有一个运行 AI 模型的服务器,并成功部署了 Cogito-V1-Preview-Llama-3B 模型,拿到它的 API 访问地址(例如 https://your-server-address/v1/chat/completions)。
  3. 代码编辑器:小程序前端用微信开发者工具,后端推荐使用 VS Code。

关于模型选择:Cogito-V1-Preview-Llama-3B 参数量是 30 亿,在轻量级模型里表现均衡,对话能力、逻辑推理都够用,生成速度也相对较快。最关键的是,它对服务器资源要求没那么高,部署和运行的成本更友好,非常适合作为小程序的后端服务。

2. 后端搭建:让 AI 模型准备好接客

后端的工作很简单,就是提供一个 API 接口。小程序发来一段对话内容,后端调用 Cogito 模型生成回复,然后再把回复传回去。这里用 Python 的 FastAPI 来写,因为它轻快,适合这种 IO 密集型的网络服务。

首先,确保你的服务器上已经部署好了模型,并且知道怎么用代码去调用它。假设模型服务本身已经在运行并提供了 API。

第一步,安装必要的包:

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 # 角色,比如 "user" 或 "assistant"
    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=["*"],
)

# 这里替换成你部署在后端服务器上的 Cogito 模型 API 地址
MODEL_API_URL = "https://your-mirror-server-address/v1/chat/completions"

@app.post("/chat")
async def chat_with_ai(request: ChatRequest):
    """
    处理小程序发来的聊天请求。
    """
    # 准备请求给 AI 模型的数据
    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:
            # 将请求转发给真正的模型 API
            response = await client.post(MODEL_API_URL, json=payload)
            response.raise_for_status() # 如果请求失败(状态码不是 2xx),抛出异常
            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"}

代码说明:

  1. CORSMiddleware 是重中之重,没有它,小程序无法调用这个接口。
  2. 我们定义了一个 /chat 接口,它接收包含对话历史的 messages。这样我们就能实现多轮对话,模型能根据之前的聊天记录来理解上下文。
  3. 后端在这里主要起代理和适配器的作用。它接收小程序的请求,转换成模型 API 认识的格式,发过去,再把模型的回复'翻译'成小程序认识的简单格式({"reply": "..."})传回去。
  4. 错误处理很重要。网络请求、模型服务、数据解析都可能出错,用 try…except 包起来,给前端返回明确的错误信息,而不是直接崩溃。

运行后端: 在服务器上,运行:

uvicorn main:app --host 0.0.0.0 --port 8000 --reload 

这样,你的后端服务就在 http://你的服务器 IP:8000 上跑起来了。可以用浏览器访问 http://你的服务器 IP:8000/health 测试一下。

3. 前端开发:构建小程序的对话界面

后端准备好了,现在来打造小程序的前端。主要做两件事:做一个好看的聊天界面,以及编写逻辑去调用我们刚写好的后端接口。

3.1 页面布局与样式

我们创建一个聊天页面 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>
                <view>
                    <image wx:if="{{item.role === 'user'}}" src="/images/user-avatar.png"></image>
                    <image wx:else src="/images/ai-avatar.png"></image>
                </view>
                <view>
                    <text>{{item.content}}</text>
                    <!-- 加载指示器 -->
                    <view wx:if="{{item.role === 'assistant' && item.loading}}">
                        <text>.</text><text>.</text><text>.</text>
                    </view>
                </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);
}
.loading-dots text {
    animation: blink 1.4s infinite;
    font-size: 40rpx;
    margin-right: 4rpx;
}
.loading-dots text:nth-child(2) {
    animation-delay: 0.2s;
}
.loading-dots text:nth-child(3) {
    animation-delay: 0.4s;
}
@keyframes blink {
    0%, 100% { opacity: 0.2; }
    50% { opacity: 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;
}
3.2 核心逻辑与网络请求

界面有了,灵魂在 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; // 空消息或正在发送时,不做任何事
        }
        // 1. 先把用户的消息显示在界面上
        const userMessage = { role: 'user', content: inputValue };
        const newList = [...messageList, userMessage];
        this.setData({
            messageList: newList,
            inputValue: '', // 清空输入框
            isSending: true,
        });
        // 2. 在界面上添加一个'AI 正在思考'的占位消息
        const thinkingMessage = { role: 'assistant', content: '', loading: true };
        this.setData({ messageList: [...newList, thinkingMessage] });
        // 3. 准备请求数据:发送整个对话历史,让 AI 知道上下文
        const requestMessages = newList.map(msg => ({ role: msg.role, content: msg.content }));
        try {
            // 4. 调用我们自己的后端接口
            const response = await new Promise((resolve, reject) => {
                wx.request({
                    url: `${API_BASE_URL}/chat`, // 你的后端/chat 接口
                    method: 'POST',
                    data: {
                        messages: requestMessages,
                        max_tokens: 300 // 控制回复长度
                    },
                    header: {
                        'content-type': 'application/json'
                    },
                    success: resolve,
                    fail: reject
                });
            });
            if (response.statusCode === 200) {
                // 5. 请求成功,用 AI 的回复替换掉'正在思考'的占位消息
                const aiReply = response.data.reply;
                const finalList = [...newList];
                finalList.pop(); // 移除 loading 占位
                finalList.push({ role: 'assistant', content: aiReply });
                this.setData({ messageList: finalList });
                // 保存到本地缓存
                wx.setStorageSync('aiChatHistory', finalList);
            } else {
                // 处理后端返回的业务错误(如状态码 400, 500 等)
                throw new Error(`请求失败:${response.statusCode}`);
            }
        } catch (error) {
            // 6. 处理网络错误或请求异常
            console.error('发送消息失败:', error);
            wx.showToast({
                title: '网络好像不太给力,请稍后再试',
                icon: 'none'
            });
            // 出错时,移除'正在思考'的占位消息
            const finalList = [...newList];
            finalList.pop();
            this.setData({ messageList: finalList });
        } finally {
            // 7. 无论成功失败,都重置发送状态
            this.setData({ isSending: false });
        }
    },
})

关键点解析:

  1. 对话历史管理:每次发送消息,都把整个 messageList 传给后端。这样模型就能看到之前所有的对话,实现连贯的多轮聊天。同时,我们把历史记录在本地 (wx.setStorageSync),用户下次打开小程序还能看到。
  2. 用户体验优化:用户一发送消息,我们立即在界面上显示他的提问,并添加一个'AI 正在思考'的动画效果。这让用户感知到程序正在工作,而不是卡住了。等收到 AI 回复后,再替换这个占位符。
  3. 错误处理:用 try…catch 包裹网络请求。如果失败,给用户一个友好的提示(而不是一堆错误代码),并清理界面上的加载状态。

4. 关键问题与优化方案

把基础功能跑通只是第一步,真要上线,还得解决一些实际体验问题。

4.1 应对网络延迟:给用户一个'正在处理'的反馈

AI 生成文本需要时间,尤其是网络慢的时候。如果用户点了发送,界面毫无反应好几秒,他很可能以为程序坏了,会反复点击。我们的方案是前面提到的'立即显示 + 加载动画'。在 sendMessage 函数里,先更新界面,再发起网络请求。这个视觉反馈至关重要。

4.2 管理对话长度与上下文

模型能处理的上下文长度是有限的(比如 4096 个 token)。如果聊天历史太长,要么会出错,要么会丢失最早的信息。 优化方案: 在后端 /chat 接口处理请求之前,可以对传入的 messages 列表做一个裁剪。

# 在 main.py 的 chat_with_ai 函数中,添加一个裁剪历史的函数
def trim_messages(messages: List[ChatMessage], max_history_turns: int = 10) -> List[ChatMessage]:
    """
    保留最近 N 轮对话,并确保总 token 数不会太长(这里简化处理,按轮次裁剪)。
    更精细的做法是计算 token 数,但需要模型对应的 tokenizer。
    """
    # 简单策略:只保留最近 max_history_turns 轮对话。
    # 通常保留用户和 AI 的最近几次交替发言即可。
    if len(messages) <= max_history_turns * 2: # 假设一轮包含用户和 AI 各一条消息
        return messages
    return messages[-(max_history_turns * 2):]

# 在 chat_with_ai 函数中调用
@app.post("/chat")
async def chat_with_ai(request: ChatRequest):
    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 轮对话(10 条消息)发给模型,既能维持一定的上下文,又不会超限。

4.3 提升回复质量与安全性

直接从模型生成的回复,有时可能不符合我们的要求,或者包含我们不希望出现的内容。 优化方案: 在后端返回给小程序之前,对 AI 的回复进行一次'后处理'。

# 在 main.py 中,添加一个后处理函数
def postprocess_reply(text: str) -> str:
    """
    对模型生成的回复进行后处理。
    1. 过滤敏感词。
    2. 确保回复格式友好(如去掉多余的空行)。
    3. 如果回复太短或无意义,可以返回一个默认提示。
    """
    # 示例:简单的敏感词过滤(实际应用需要更完善的词库)
    sensitive_words = ["暴力", "仇恨"] # 示例词库,请根据实际情况扩充
    for word in sensitive_words:
        if word in text:
            text = text.replace(word, "**")
    # 示例:如果回复过短,可能是模型没理解,提示用户重新提问
    if len(text.strip()) < 5:
        return "我好像没太明白你的意思,能换个方式问问吗?"
    # 整理格式
    text = text.strip()
    return text

# 在 chat_with_ai 函数中,提取回复后调用
@app.post("/chat")
async def chat_with_ai(request: ChatRequest):
    # ... 前面的请求和获取 ai_reply 的代码 ...
    processed_reply = postprocess_reply(ai_reply)
    return {"reply": processed_reply}

这是一个简单的示例,真实场景可能需要接入更专业的内容审核 API。

5. 总结

走完这一趟,你会发现,在微信小程序里集成一个像 Cogito-V1-Preview-Llama-3B 这样的 AI 对话功能,核心思路就是'前端收集对话,后端转发处理'。技术难点不在于算法本身,而在于如何在小程序的框架下,做好网络通信、状态管理和用户体验。

这套方案跑起来后,效果还是挺不错的。对话比较流畅,响应速度也能接受。当然,在实际运营中可能会遇到新问题,比如流量大了服务器压力怎么办,回复内容如何更精准地控制。这些问题都可以在现有框架上继续优化,比如给后端加个缓存,或者对不同的用户提问做更细致的分类处理。

如果你正准备做类似的功能,建议你先按这个流程把最小可用的版本搭起来,让对话能跑通。然后再根据你的具体业务需求,去添加历史记录清空、多主题对话、语音输入等更酷的功能。最重要的是,多从用户角度想想,怎么让这个 AI 助手用起来更自然、更贴心。

  • 💰 8折买阿里云服务器限时8折购买
  • 🦞 5分钟部署阿里云小龙虾了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog

更多推荐文章

查看全部
  • Copilot 企业认证后强制使用 GPT-4o 的底层逻辑与应对策略
  • MogFace 人脸检测模型 WebUI 优化:ONNX Runtime 加速至 28ms
  • 基于 FastAPI 的 Web 上位机系统设计与实现
  • 企业级 Code RAG 与代码库 Copilot 架构设计指南
  • Rust WebAssembly 与 Three.js 结合的高性能 3D 粒子系统
  • 本地化部署 GraphRAG+LangChain+Ollama 驱动 Llama 3.1 集成 Neo4j 实战
  • C++ 类和对象基础详解
  • C++物理引擎稳定性提升的关键设计原则
  • Stable Diffusion 3.5 FP8 模型在 AIGC 平台的应用与优化
  • 医疗 AI 可信革命全栈实现(下)
  • C++17 PMR 内存管理详解:memory_resource 与 polymorphic_allocator
  • 前端表单验证策略:防止无效数据提交
  • 论文解读:使用人类反馈训练语言模型遵循指令
  • Windows 下使用 Git 从 GitHub 拉取项目到本地的完整步骤
  • 博客系统 GitHub 第三方登录集成教程
  • Windows 程序启动失败:Visual C++ 运行库缺失修复方案
  • 群晖 Photos 零 GPU 实现人脸识别与 AI 相册功能
  • JDK 17 安装与配置指南
  • 英伟达开源 DreamDojo:4.4 万小时数据破解机器人数据鸿沟
  • 精易模块 Excel 操作实战:中小学生成绩管理系统

相关免费在线工具

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online