Phi-3-Mini-128K集成微信小程序开发:打造个人AI知识库助手

张开发
2026/5/2 23:40:41 15 分钟阅读

分享文章

Phi-3-Mini-128K集成微信小程序开发:打造个人AI知识库助手
Phi-3-Mini-128K集成微信小程序开发打造个人AI知识库助手最近在折腾AI应用发现一个挺有意思的事儿很多强大的AI模型比如微软开源的Phi-3-Mini能力很强但咱们普通开发者想把它变成一个随时能用的手机应用门槛还是不低。要么得懂复杂的后端部署要么得研究各种API调用。正好微信小程序大家都很熟开发起来也方便。我就琢磨着能不能把这两者结合起来用Phi-3-Mini-128K当“大脑”用微信小程序当“窗口”做一个专属于自己的移动端AI知识库助手。你可以把它当成一个随身携带的智能笔记本随时记录想法、查询资料、总结信息而且所有对话记录都保存在自己手机里安全又方便。今天这篇文章我就把自己从零搭建这个“个人AI助手”的全过程分享出来。我会重点讲怎么把云上的模型API和小程序前端“粘”在一起怎么设计一个简单好用的聊天界面以及怎么在小程序里安全地管理你的对话历史。整个过程涉及前端UI、后端API调用和本地数据存储算是一个比较完整的全栈小案例。如果你对AI应用落地感兴趣或者想学学怎么把前沿模型用到实际产品里那这篇文章应该能给你一些直接的参考。咱们不聊太虚的架构就讲能跑通的代码和能复现的步骤。1. 项目整体思路与准备工作在动手写代码之前咱们先把这个小工具要干什么、怎么干想清楚。我的核心目标是在微信小程序里创建一个能和Phi-3-Mini模型对话的界面并且把聊天记录存在本地。整个流程可以拆解成这么几步后端模型服务我们需要一个能提供Phi-3-Mini模型推理能力的API服务。这部分我们选择用现成的云服务或者自己熟悉的部署方式比如通过一些AI模型服务平台得到一个可以调用的API地址和密钥。前端微信小程序这是用户直接操作的部分。需要设计聊天界面、处理用户输入、把问题发送给后端API并把模型返回的答案展示出来。数据桥梁小程序不能直接调用任意网络地址需要在小程序管理后台配置合法的API域名。同时API调用通常需要身份验证比如API Key。数据存储为了让对话体验连贯我们需要把历史聊天记录保存下来。考虑到个人使用和隐私优先选择小程序的本地存储。你需要提前准备好的东西一个微信小程序账号去微信公众平台注册一个并创建一个小程序项目拿到你的AppID。Phi-3-Mini模型的API访问权限你可以使用微软Azure AI Studio提供的托管服务或者其他支持该模型的云平台如Groq、Together AI等获取到API的端点地址和API密钥。这是整个项目的“燃料”。基础的开发环境微信开发者工具是必须的。对JavaScript/TypeScript和小程序框架有基本了解会更轻松。一个“中转”或“代理”的思路可选但重要由于小程序对请求域名有严格限制直接调用第三方API可能会遇到问题。一个常见的做法是自己搭建一个简单的后端服务比如用Node.js Express作为代理小程序只跟自己的这个后端服务通信再由这个后端服务去调用真正的模型API。这样也方便统一管理API密钥避免在前端暴露敏感信息。本文为了简化我们先讨论直接调用的场景并指出其中的注意事项。思路理清了咱们就从最直观的小程序界面开始做起。2. 构建微信小程序聊天界面用户第一眼看到的是界面所以咱们先把这个聊天窗口搭起来。微信小程序的开发模式大家应该不陌生主要是wxml模板、wxss样式、js逻辑和json配置这几种文件。2.1 设计页面布局与样式我设计了一个比较经典的聊天界面上面是聊天记录区域下面是输入框和发送按钮。首先在index.wxml里我们把结构搭出来!-- index.wxml -- view classcontainer !-- 标题栏 -- view classheader text我的AI知识库助手/text /view !-- 聊天消息列表区域 -- scroll-view classmessage-list scroll-y scroll-into-view{{scrollToId}} scroll-with-animation block wx:for{{messages}} wx:keyid view idmsg-{{index}} classmessage-item {{item.role}} !-- 角色头像 -- image classavatar src{{item.role user ? /images/user-avatar.png : /images/bot-avatar.png}}/image view classmessage-content !-- 消息文本使用text组件支持长按复制 -- text classtext selectable{{item.content}}/text !-- 消息时间 -- text classtime{{item.time}}/text /view /view /block /scroll-view !-- 输入区域 -- view classinput-area textarea classinput-box placeholder请输入您的问题... bindinputonInput value{{inputValue}} maxlength500 auto-height fixed / button classsend-btn bindtapsendMessage disabled{{isLoading}} {{isLoading ? 思考中... : 发送}} /button /view /view光有结构不行还得好看。在index.wxss里我们加一些样式让界面看起来更舒服/* index.wxss */ .container { height: 100vh; display: flex; flex-direction: column; background-color: #f5f5f5; } .header { padding: 20rpx; background-color: #07c160; color: white; text-align: center; font-weight: bold; font-size: 36rpx; } .message-list { flex: 1; padding: 20rpx; box-sizing: border-box; overflow-y: auto; } .message-item { display: flex; margin-bottom: 30rpx; animation: fadeIn 0.3s ease; } .message-item.user { flex-direction: row-reverse; } .message-item.user .message-content { align-items: flex-end; } .avatar { width: 80rpx; height: 80rpx; border-radius: 50%; flex-shrink: 0; } .user .avatar { margin-left: 20rpx; } .assistant .avatar { margin-right: 20rpx; } .message-content { max-width: 70%; display: flex; flex-direction: column; } .user .message-content { align-items: flex-end; } .text { padding: 20rpx; border-radius: 12rpx; font-size: 32rpx; line-height: 1.5; word-break: break-word; } .user .text { background-color: #95ec69; color: #000; } .assistant .text { background-color: #fff; color: #333; border: 1rpx solid #e0e0e0; } .time { font-size: 24rpx; color: #999; margin-top: 8rpx; } .input-area { display: flex; padding: 20rpx; background-color: #fff; border-top: 1rpx solid #e0e0e0; align-items: flex-end; } .input-box { flex: 1; min-height: 80rpx; max-height: 200rpx; padding: 20rpx; border: 1rpx solid #ddd; border-radius: 10rpx; font-size: 32rpx; margin-right: 20rpx; background-color: #fafafa; } .send-btn { width: 140rpx; height: 80rpx; line-height: 80rpx; border-radius: 10rpx; background-color: #07c160; color: white; font-size: 32rpx; padding: 0; } .send-btn[disabled] { background-color: #ccc; color: #666; } keyframes fadeIn { from { opacity: 0; transform: translateY(10rpx); } to { opacity: 1; transform: translateY(0); } }这样一个基础的聊天界面就有了雏形。接下来我们要让这个界面“活”起来。2.2 实现页面交互逻辑界面是静态的逻辑是动态的。我们在index.js里处理用户输入、发送消息、接收回复以及更新界面。// index.js Page({ data: { messages: [], // 存储所有消息 inputValue: , // 输入框内容 isLoading: false, // 是否正在加载等待AI回复 scrollToId: // 用于控制滚动到底部 }, onLoad: function() { // 页面加载时尝试从本地存储加载历史消息 this.loadHistoryMessages(); }, // 监听输入框变化 onInput: function(e) { this.setData({ inputValue: e.detail.value }); }, // 加载本地历史消息 loadHistoryMessages: function() { const that this; wx.getStorage({ key: chatMessages, success: function(res) { if (res.data) { that.setData({ messages: res.data }, () { that.scrollToBottom(); // 加载后滚动到底部 }); } } }); }, // 保存消息到本地 saveMessagesToLocal: function() { wx.setStorage({ key: chatMessages, data: this.data.messages }); }, // 发送消息 sendMessage: function() { const userInput this.data.inputValue.trim(); if (!userInput || this.data.isLoading) { return; } // 1. 清空输入框 this.setData({ inputValue: }); // 2. 添加用户消息到列表 const userMessage { id: Date.now(), role: user, content: userInput, time: this.getCurrentTime() }; this.data.messages.push(userMessage); this.setData({ messages: this.data.messages }); this.scrollToBottom(); // 3. 显示“AI正在思考”的占位消息 const thinkingMessageId Date.now() 1; const thinkingMessage { id: thinkingMessageId, role: assistant, content: ..., time: this.getCurrentTime() }; this.data.messages.push(thinkingMessage); this.setData({ messages: this.data.messages, isLoading: true }); this.scrollToBottom(); // 4. 调用AI API获取回复 this.callPhi3MiniAPI(userInput, thinkingMessageId); }, // 调用Phi-3-Mini API (这里是关键步骤) callPhi3MiniAPI: function(userInput, targetMessageId) { const that this; // 注意这里需要替换成你实际的API端点、密钥以及调整请求体格式 const apiUrl https://your-phi3-api-endpoint.com/v1/chat/completions; // 示例地址请替换 const apiKey your-api-key-here; // 你的API密钥 wx.request({ url: apiUrl, method: POST, header: { Content-Type: application/json, Authorization: Bearer ${apiKey} // 常见的认证方式 }, data: { model: phi-3-mini-128k-instruct, // 根据实际模型名调整 messages: [ // 可以选择发送部分历史上下文这里简单只发最新一条 { role: user, content: userInput } ], max_tokens: 500, temperature: 0.7, stream: false // 小程序处理流式响应较复杂先设为false }, success: function(res) { console.log(API调用成功:, res); if (res.statusCode 200 res.data res.data.choices res.data.choices[0]) { const aiResponse res.data.choices[0].message.content; that.updateAIMessage(targetMessageId, aiResponse); } else { that.updateAIMessage(targetMessageId, 抱歉我好像遇到了一点问题无法生成回答。); } }, fail: function(err) { console.error(API调用失败:, err); that.updateAIMessage(targetMessageId, 网络请求失败请检查网络连接或API配置。); }, complete: function() { that.setData({ isLoading: false }); that.saveMessagesToLocal(); // 请求完成后保存到本地 } }); }, // 更新AI的回复消息 updateAIMessage: function(messageId, newContent) { const messages this.data.messages; for (let i 0; i messages.length; i) { if (messages[i].id messageId) { messages[i].content newContent; messages[i].time this.getCurrentTime(); // 更新时间为回复时间 this.setData({ messages: messages }); this.scrollToBottom(); break; } } }, // 滚动到底部 scrollToBottom: function() { const lastIndex this.data.messages.length - 1; if (lastIndex 0) { this.setData({ scrollToId: msg-${lastIndex} }); } }, // 获取当前时间字符串 getCurrentTime: function() { const now new Date(); return ${now.getHours().toString().padStart(2, 0)}:${now.getMinutes().toString().padStart(2, 0)}; }, // 清空聊天记录 clearChat: function() { const that this; wx.showModal({ title: 提示, content: 确定要清空所有聊天记录吗, success(res) { if (res.confirm) { that.setData({ messages: [] }); wx.removeStorage({ key: chatMessages, success: function() { wx.showToast({ title: 已清空 }); } }); } } }); } })到这里一个具备基本交互功能的小程序前端就完成了。你可以输入文字点击发送前端会尝试调用一个API。但最关键的一步——如何正确、安全地调用Phi-3-Mini的API——我们还需要仔细配置。3. 连接Phi-3-Mini模型API前端界面做好了现在要把它的“大脑”接上。这一步是整个项目的核心也是容易踩坑的地方。3.1 配置小程序网络请求微信小程序出于安全考虑限制了网络请求的域名。你不能随意请求一个网址。所以你获取到的Phi-3-Mini API地址例如https://api.example.com必须添加到小程序的服务器域名白名单中。操作步骤登录微信公众平台。进入你的小程序管理后台。找到“开发”-“开发管理”-“开发设置”。在“服务器域名”部分找到“request合法域名”。将你的模型API的域名例如https://api.example.com添加进去。重要域名必须备案且支持HTTPS。如果API服务商提供的地址是IP可能需要通过域名访问或者使用其他方案如云函数、自建代理。3.2 处理API密钥与请求格式API密钥是访问模型的凭证绝对不能直接硬编码在小程序的前端代码里因为前端代码可以被轻易反编译获取。这是一个严重的安全隐患。更安全的做法是使用云函数或自建代理创建云函数在小程序云开发环境中创建一个云函数例如callAI。在云函数中调用API将你的API密钥保存在云函数的环境变量中。小程序前端只调用这个云函数由云函数去请求真正的模型API并将结果返回给前端。云函数示例Node.js// cloudfunctions/callAI/index.js const cloud require(wx-server-sdk); cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }); const axios require(axios); // 需要安装axios依赖 exports.main async (event, context) { const { userMessage } event; const API_URL process.env.PHI3_API_URL; // 从环境变量读取 const API_KEY process.env.PHI3_API_KEY; // 从环境变量读取 try { const response await axios.post(API_URL, { model: phi-3-mini-128k-instruct, messages: [{ role: user, content: userMessage }], max_tokens: 500, temperature: 0.7, }, { headers: { Content-Type: application/json, Authorization: Bearer ${API_KEY} } }); return { success: true, data: response.data }; } catch (error) { console.error(调用模型API失败:, error); return { success: false, error: error.message }; } };修改小程序前端调用将callPhi3MiniAPI函数中的wx.request改为调用云函数。// 修改后的 callPhi3MiniAPI 函数部分 wx.cloud.callFunction({ name: callAI, // 你的云函数名 data: { userMessage: userInput }, success: (res) { // 处理云函数返回的结果 if (res.result.success) { const aiResponse res.result.data.choices[0].message.content; that.updateAIMessage(targetMessageId, aiResponse); } else { that.updateAIMessage(targetMessageId, 服务暂时不可用 res.result.error); } }, fail: (err) { console.error(云函数调用失败:, err); that.updateAIMessage(targetMessageId, 网络请求失败); } });关于请求格式不同的模型服务提供商其API接口规范可能略有不同。上述示例使用的是与OpenAI Chat Completions API兼容的格式。你需要根据你使用的具体服务商的文档调整url、header和data中的字段。关键信息通常包括url: API端点地址。header: 认证头如Authorization: Bearer key和内容类型。data: 指定模型名称、消息列表、生成参数如max_tokens,temperature等。3.3 实现上下文对话进阶上面的例子只发送了当前用户消息。如果你想实现多轮对话让AI记住之前的聊天内容就需要在API请求中携带历史消息。我们可以修改callPhi3MiniAPI函数或云函数的入参将messages数组构建得更完整// 在准备发送给API的消息数组时 const messagesForAPI []; // 可以从本地存储的 messages 中提取最近的若干轮对话 // 注意格式转换并控制总token数不超过模型限制Phi-3-Mini-128K支持128K上下文 const recentMessages this.data.messages.slice(-10); // 取最近10条简单示例 recentMessages.forEach(msg { messagesForAPI.push({ role: msg.role, // user 或 assistant content: msg.content }); }); // 最后加入当前用户的新消息 messagesForAPI.push({ role: user, content: userInput }); // 然后将 messagesForAPI 作为参数发送这样模型就能基于更长的对话历史来生成更连贯、更准确的回复了。4. 完善功能与优化体验基础功能跑通后我们可以再打磨一下让这个小助手更好用。4.1 强化本地数据管理我们之前用了wx.setStorage来存消息但它是异步的且有大小限制单个key最大10MB。对于可能很长的聊天记录我们可以做一些优化分页或归档当消息太多时可以提示用户清理或自动将较早的对话归档。使用云开发数据库如果对话记录非常重要且需要在多设备间同步可以考虑使用微信云开发的数据库来存储但这会涉及服务端成本。数据加密可选如果对话内容非常敏感可以在存储前进行简单的加密读取时再解密。不过密钥管理本身又是一个安全问题需要权衡。4.2 增加实用特性消息操作长按消息可以弹出菜单提供“复制”、“删除”、“重新生成”等功能。对话管理可以创建不同的“会话”比如“工作笔记”、“学习计划”、“创意灵感”每个会话独立保存历史。流式输出如果模型API支持流式响应stream: true可以实现打字机效果让AI的回答一个字一个字显示出来体验更好。这需要用到WebSocket或SSE在小程序里实现起来稍复杂一些。错误处理与重试网络请求可能失败给用户友好的提示并提供重试按钮。设置页面允许用户配置API端点如果使用代理、调整模型参数如temperature等。4.3 部署与发布真机调试在微信开发者工具中预览没问题后一定要用手机扫描二维码进行真机调试测试网络请求、存储等功能是否正常。提交审核完成开发后在微信公众平台提交代码审核。注意如果你的小程序涉及AI对话可能需要补充相关类目并确保内容符合平台规范。发布上线审核通过后即可发布。你的个人AI知识库助手就能被你自己或其他受邀用户搜索和使用了。5. 总结走完这一趟一个集成了Phi-3-Mini模型的个人AI知识库助手小程序就从想法变成了现实。整个过程其实就像搭积木小程序前端负责展示和交互云上的模型API提供智能内核而我们需要做的就是用代码和配置把这两块“积木”牢固、安全地连接起来。最大的收获可能不是代码本身而是解决实际问题的思路。比如如何在前端安全地处理敏感信息API密钥如何设计数据结构来管理对话状态以及如何根据平台限制如小程序域名白名单来调整技术方案。这些经验在你做其他类似项目时同样用得上。这个项目还有很多可以深挖和优化的地方。比如引入更复杂的对话管理、实现流式响应来提升体验或者结合小程序的云开发能力做一个支持多端同步的完整知识库。但作为起点它已经具备了核心功能随时提问、智能回复、记录留存。如果你跟着做了一遍可能会遇到一些具体的报错比如域名配置问题、API格式不对、或者云函数部署失败。别担心这些都是学习过程的一部分。多看看错误信息查查文档问题总能解决。最关键的是动手去试在真实的环境里跑通整个流程那种感觉比看十篇教程都实在。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。

更多文章