微信小程序AI聊天源码:流式输出与LLM对接实战
简介这份资源是一套微信小程序AI聊天页面的完整前端源码面向希望快速上手小程序对接大语言模型的开发者与学习者尤其适合想体验AI对话能力、验证人设设定效果的入门到中级人员。压缩包共6个文件约386KB包含wxml页面结构、wxss样式、js逻辑、json配置以及bot与user两张png头像图片覆盖了聊天界面从布局到交互的核心环节。借助这套代码读者可以快速搭建一个可运行的AI对话页面并根据需要为模型设定不同人设例如儿童教育领域专家、商城客服或法律顾问同时调整回复语气、提出个性化要求直观感受LLM在小程序端的落地方式。目前已有978人学习下载说明该示例在同类入门资源中具有一定参考热度。整体结构精简、上手门槛低适合作为小程序接入大语言模型的练手项目或二次开发起点。1. 从一条消息的旅程说起这个 AI 聊天小程序到底能干什么你打开微信进入一个小程序输入“帮我写一段 Python 快速排序”两秒后屏幕上逐字蹦出代码和解释。这背后不是魔法而是一条完整的链路小程序前端采集输入通过 WebSocket 或 HTTPS 把消息送到后端后端再转发给大语言模型 API拿到流式响应后原路推回前端逐字渲染。这套源码要解决的就是把这条链路从零搭出来——包含聊天页面 UI、消息收发逻辑、LLM 接口对接、会话上下文管理以及一个能跑起来的后端服务。它适合两类人一是想快速拥有一个可演示的 AI 聊天入口的前端开发者二是想研究小程序如何与语言模型交互的全栈学习者。你不需要从零设计消息协议也不用纠结流式渲染怎么写源码里已经把这些坑填过一遍了。2. 技术栈与目录结构拿到源码先看什么2.1 前端技术选型与页面组成微信小程序原生开发是这套源码的基底。没有用 uni-app 或 Taro 这类跨端框架原因很直接聊天场景对输入框聚焦、键盘弹起、scroll-view 滚动到底部的控制要求很细原生 API 的响应最可控。页面层面通常包含三个核心文件pages/chat/chat.wxml负责消息列表和输入栏的结构pages/chat/chat.js管理消息数组、滚动位置和发送逻辑pages/chat/chat.wxss处理气泡样式和流式光标动画。消息列表用scroll-view包裹每条消息是一个view通过wx:for渲染。输入栏固定在底部用fixed定位配合padding-bottom适配 iPhone 安全区。流式输出时最后一条 AI 消息会有一个闪烁的光标实现方式是在文本末尾追加一个带 CSS 动画的view。// pages/chat/chat.js 核心数据结构 Page({ data: { messages: [], // 消息列表每条含 role、content、id inputValue: , // 输入框当前内容 scrollTop: 0, // 控制 scroll-view 滚动位置 isStreaming: false // 是否正在接收流式响应 }, onInput(e) { this.setData({ inputValue: e.detail.value }) }, // 发送消息时先插入用户消息再插入一条空的 AI 消息占位 sendMessage() { const text this.data.inputValue.trim() if (!text || this.data.isStreaming) return const userMsg { role: user, content: text, id: Date.now() } const aiMsg { role: assistant, content: , id: Date.now() 1 } this.setData({ messages: [...this.data.messages, userMsg, aiMsg], inputValue: , isStreaming: true }) this.scrollToBottom() this.requestLLM(text) } })这段代码的关键在于isStreaming这个状态位。它同时承担两个职责防止用户在 AI 回复过程中重复发送以及让输入框在流式期间保持禁用态。messages数组里每条消息的id用时间戳生成是为了在流式更新时能精确定位到那条 AI 消息并只更新它的content而不是整个数组重建。常见做法是用setData的路径语法messages[${index}].content来局部更新性能比全量替换好很多。2.2 后端服务与 LLM 对接层后端通常是一个 Node.js 服务用 Express 或 Koa 起 HTTP 接口同时用ws库开一个 WebSocket 通道。为什么不用纯 HTTP 轮询因为流式输出需要服务端主动推送WebSocket 的全双工特性天然适合。如果不想维护 WebSocket也可以用 SSEServer-Sent Events但小程序对 SSE 的支持不如 WebSocket 直接。目录结构大致如下project-root/ ├── miniprogram/ # 小程序前端代码 │ ├── pages/chat/ # 聊天页面 │ ├── utils/request.js # 封装 WebSocket 和 HTTP 请求 │ └── app.js # 全局配置存后端地址 ├── server/ # 后端服务 │ ├── index.js # 入口启动 HTTP 和 WebSocket │ ├── llm.js # LLM API 调用封装 │ └── session.js # 会话上下文管理 └── package.jsonserver/llm.js是核心对接层。它接收用户消息和会话 ID从session.js取出历史上下文拼成 LLM 需要的消息格式然后发起流式请求。以常见的 OpenAI 兼容接口为例// server/llm.js 流式调用封装 const axios require(axios) async function streamChat(messages, onChunk) { const response await axios.post( https://api.example.com/v1/chat/completions, { model: gpt-3.5-turbo, // 模型名按实际服务商填写 messages: messages, // 包含历史上下文的消息数组 stream: true // 开启流式返回 }, { headers: { Authorization: Bearer ${process.env.LLM_API_KEY} }, responseType: stream } ) let buffer response.data.on(data, chunk { buffer chunk.toString() const lines buffer.split(\n) buffer lines.pop() // 最后一行可能不完整留到下次 for (const line of lines) { if (line.startsWith(data: ) line ! data: [DONE]) { const json JSON.parse(line.slice(6)) const delta json.choices[0]?.delta?.content || if (delta) onChunk(delta) // 每收到一个片段就回调 } } }) }这里有几个容易翻车的点。buffer的存在是因为 TCP 流不保证每次data事件都对应一个完整的 SSE 行必须自己缓存拼接。lines.pop()把可能不完整的最后一行留到下一次处理这是流式解析的标准操作。onChunk回调把增量文本传给 WebSocket 的发送函数最终推到小程序端。API Key 放在环境变量里不要硬编码在源码中这是基本的安全习惯。2.3 会话上下文管理session.js维护一个内存中的 Mapkey 是会话 IDvalue 是消息数组。每次用户发消息先把用户消息 push 进去调用 LLM 拿到完整回复后再把 AI 消息 push 进去。这样下一轮对话时历史上下文就自然带上了。// server/session.js 简易上下文管理 const sessions new Map() const MAX_TURNS 10 // 最多保留最近 10 轮对话 function getContext(sessionId) { return sessions.get(sessionId) || [] } function appendMessage(sessionId, role, content) { const history sessions.get(sessionId) || [] history.push({ role, content }) // 超出轮数限制时从头部丢弃最早的消息 if (history.length MAX_TURNS * 2) { history.splice(0, history.length - MAX_TURNS * 2) } sessions.set(sessionId, history) }MAX_TURNS控制上下文长度防止 token 消耗过快和请求体过大。生产环境建议把 Map 换成 Redis否则服务重启后所有会话丢失。会话 ID 由小程序端在首次进入聊天页时生成存在storage里后续每次请求都带上。3. 跑起来从零到发出第一条消息3.1 环境准备与依赖安装你需要三样东西微信开发者工具、Node.js 环境建议 16 以上、一个可用的 LLM API Key。源码根目录下执行npm install安装后端依赖主要就是express、ws、axios这几个。小程序端不需要 npm 安装微信开发者工具直接打开miniprogram目录即可。后端启动前在server目录下新建.env文件写入你的 API Key 和接口地址LLM_API_KEY你的密钥 LLM_BASE_URLhttps://api.example.com/v1 PORT3000然后在server/index.js里用dotenv加载这些变量。启动命令是node index.js看到控制台输出Server running on port 3000就说明后端就绪。3.2 小程序端配置与联调打开miniprogram/app.js把globalData.serverUrl改成你本机的 IP 加端口比如http://192.168.1.100:3000。注意不能用localhost因为开发者工具和手机真机的网络环境不同真机调试必须用局域网 IP。微信开发者工具里需要勾选“不校验合法域名”否则小程序会拦截非 HTTPS 请求。正式发布时后端必须上 HTTPS 并配置到小程序后台的 request 合法域名列表里。联调时先在模拟器里发一条“你好”观察三个地方小程序控制台的messages数组是否更新、后端控制台是否打印收到请求、Network 面板是否有 WebSocket 帧往来。如果消息发出去了但没回复大概率是 API Key 无效或接口地址填错后端会报 401 或 404。3.3 流式渲染的触发时机小程序端收到 WebSocket 消息后需要区分是增量片段还是完整消息。常见做法是在协议里加一个type字段type: chunk表示增量type: done表示结束。收到chunk时用setData更新最后一条 AI 消息的content收到done时把isStreaming置回false。// utils/request.js 中的 WebSocket 消息处理 socket.onMessage(res { const data JSON.parse(res.data) const messages this.data.messages const lastIndex messages.length - 1 if (data.type chunk) { // 只更新最后一条消息的内容避免全量 setData this.setData({ [messages[${lastIndex}].content]: messages[lastIndex].content data.content }) this.scrollToBottom() } else if (data.type done) { this.setData({ isStreaming: false }) } })路径语法messages[${lastIndex}].content是微信小程序setData的性能优化手段它只更新指定路径的数据不会触发整个列表的重新渲染。消息多的时候这个差别很明显全量更新会卡顿。4. 避坑与常见问题那些让你怀疑人生的报错4.1 消息发出去了但 AI 不回复现象是小程序端显示用户消息AI 占位消息一直空白isStreaming卡在true。原因通常是后端请求 LLM 时抛了异常但没有把错误推回前端。解决方式是在streamChat外层包try/catch捕获到错误时通过 WebSocket 发送一条type: error的消息前端收到后把占位消息内容改成“请求失败请重试”同时把isStreaming置回false。另外检查 API Key 是否过期、接口地址是否带了多余的斜杠。4.2 流式输出文字闪烁或重复现象是 AI 回复的文字一会儿重复一会儿跳变。原因是setData更新时用了全量messages替换而 WebSocket 消息到达顺序和setData的异步渲染产生了竞争。解决方式是坚持用路径语法局部更新并且在后端保证每个chunk只发送一次。如果后端用了多个进程或集群WebSocket 连接可能被分配到不同实例导致消息乱序这时需要引入 Redis 的 pub/sub 来统一分发。4.3 真机上键盘弹起遮挡输入框模拟器里输入框位置正常真机上键盘弹起后输入框被挡住。原因是小程序的adjust-position属性默认是true但fixed定位的输入栏不会自动上移。解决方式是把输入栏的bottom值绑定到一个动态数据监听bindfocus和bindblur事件聚焦时把bottom设为键盘高度失焦时归零。键盘高度可以通过wx.onKeyboardHeightChange获取。4.4 上下文太长导致请求超时或费用飙升现象是聊了十几轮后响应越来越慢API 账单涨得飞快。原因是session.js里没有做上下文截断历史消息无限增长。解决方式是设置MAX_TURNS并在超出时从头部丢弃或者用摘要方式把早期对话压缩成一句话再拼进上下文。另一个技巧是只保留最近几轮的用户消息和 AI 回复中间的系统提示词单独维护不参与截断。4.5 小程序审核被拒类目与内容合规现象是代码没问题但提交审核被驳回。原因是聊天类小程序需要选择正确的服务类目并且 AI 生成内容需要有人工审核或过滤机制。解决方式是在后端接入内容安全接口对用户输入和 AI 输出做敏感词过滤同时在提交审核时准备好类目说明材料。这个坑不解决代码写得再好也上不了线。5. 二次开发换模型、加功能、做自己的 AI 助手5.1 替换 LLM 服务商源码默认对接的是 OpenAI 兼容接口换成其他服务商时只需要改server/llm.js里的请求地址、模型名和认证方式。如果服务商的流式格式不是标准 SSE比如返回的是 JSON Lines那就把buffer解析部分的data:前缀判断去掉直接JSON.parse(line)。参数方面temperature控制随机性聊天场景建议 0.7 左右max_tokens限制单次回复长度防止 AI 话太多。5.2 增加多会话切换当前源码是单会话模式所有消息存在一个数组里。要改成多会话需要在session.js里把 Map 的 key 从固定值改成动态会话 ID小程序端增加一个会话列表页面用wx.setStorageSync存会话索引。切换会话时重新拉取对应历史消息渲染到聊天页。这个改造的核心是会话 ID 的生成和传递建议用uuid库生成避免时间戳冲突。5.3 加入语音输入与图片理解语音输入可以用微信小程序的wx.getRecorderManager录音然后把音频文件上传到后端调用语音转文字接口拿到文本再走聊天流程。图片理解则需要后端支持多模态模型把图片转成 base64 或上传到对象存储后把 URL 传给 LLM。这两个功能都会增加请求体积注意小程序的wx.uploadFile有大小限制图片建议压缩后再传。5.4 一个我踩过的坑有一次我把MAX_TURNS设成了 50觉得上下文越长 AI 越聪明。结果聊到第 20 轮时请求体超过了 100KB后端直接超时前端卡在isStreaming状态无法恢复。更麻烦的是 API 按 token 计费那一晚上烧掉了不少额度。从那以后我每次改上下文相关参数都强制走一遍“发 30 条消息看响应时间和费用”的验证流程。另外isStreaming一定要加超时兜底比如 30 秒没收到done就自动重置否则用户会以为小程序卡死。希望这些经验帮到你少走点弯路。本文还有配套的精品资源点击获取

相关新闻

artcraft:降低创作门槛的数字化工具技术路线与实战经验

artcraft:降低创作门槛的数字化工具技术路线与实战经验

1. 从“artcraft”这个名字说起:它到底想解决什么问题第一次看到“artcraft”这个词,我脑子里蹦出来的第一反应是“艺术”加“手艺”的组合。这不是一个随便拼凑的名字,它背后指向的是一类非常具体的需求:把艺术创作和手工制作这两…

2026/10/18 23:26:29 阅读更多 →
酒店评论情感分析系统:基于逻辑回归与XGBoost的Flask应用

酒店评论情感分析系统:基于逻辑回归与XGBoost的Flask应用

简介:这是一份面向计算机相关专业学生和开发者的酒店评论情感分析系统项目,可用于毕业设计或课程作业。项目基于机器学习与自然语言处理技术,内置Flask Web应用程序,用户输入评论文本即可获得情感预测结果,同时提供了逻…

2026/10/18 23:26:29 阅读更多 →
Cursor 怎样设置中文:把界面语言改到 TaoToken 的完整配置与验证

Cursor 怎样设置中文:把界面语言改到 TaoToken 的完整配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 23:26:29 阅读更多 →

最新新闻

Java Swing飞翔的小鸟游戏实战:课设高分与完整源码解析

Java Swing飞翔的小鸟游戏实战:课设高分与完整源码解析

简介:飞翔的小鸟游戏Java实现源码及配套详细教程,面向Java初学者与需要完成期末大作业、课程设计或毕业设计的学生,提供一套可直接运行、便于二次开发的完整小游戏项目,个人手打九十八分并获导师认可。资源共四十五个文件&#xf…

2026/10/19 0:23:01 阅读更多 →
中文教育场景下的AIGC检测:原理、应用与教师实操指南

中文教育场景下的AIGC检测:原理、应用与教师实操指南

1. 从“AI代写泛滥”到“检测刚需”:中文教育场景的需求拆解一个学期末,某高校的A老师连续收到三篇“风格突变”的课程论文。第一篇措辞工整但缺乏个人视角,第二篇引用了大量教材原文却没有任何延伸思考,第三篇连标点符号都规范得…

2026/10/19 0:23:01 阅读更多 →
Spring Boot单体商城源码:从扣库存到JWT鉴权的电商后端实战解析

Spring Boot单体商城源码:从扣库存到JWT鉴权的电商后端实战解析

简介:面向Java中高级开发者与商城系统学习者的单商户商城小程序项目源码包,基于Spring Boot、MyBatis、Thymeleaf、Redis及Maven构建,并融入微服务拆分、小程序接口对接、数据库设计、OAuth2安全认证、Docker部署与监控测试等电商开发核心知识…

2026/10/19 0:23:01 阅读更多 →
TransE模型Python实战:基于fb15k的知识图谱嵌入与链接预测

TransE模型Python实战:基于fb15k的知识图谱嵌入与链接预测

简介:TransE是知识图谱嵌入领域的经典模型,核心思想是将头实体、关系和尾实体映射为向量,并满足hr≈t。面向知识图谱研究者和NLP开发者的这份Python实现,选用fb15k数据集进行训练,能够处理一对多、多对多关系&#xff…

2026/10/19 0:23:01 阅读更多 →
AI Agent概念串烧:从智能体闭环到工具调用、记忆机制与落地实践

AI Agent概念串烧:从智能体闭环到工具调用、记忆机制与落地实践

最近聊AI Agent的场合明显变多了,但有意思的是,十次聊天里至少有六次大家说的不是同一件事。有人说Agent就是能自己写报告的聊天框,有人说是一串能自动处理订单的任务流,还有人直接把工作流中间加一个“智能判断”就叫Agent了。这…

2026/10/19 0:22:01 阅读更多 →
Hermes Agent能力分层:会话、工具、MCP与记忆的工程化解耦

Hermes Agent能力分层:会话、工具、MCP与记忆的工程化解耦

1. 这不是又一个“智能体框架”:Hermes Agent 的能力分层到底在解决什么问题?看到“Hermes Agent能力篇:会话、工具、MCP、记忆”这个标题,我第一反应是——得先按下暂停键。过去两年里,我参与过不下七个不同团队的智能…

2026/10/19 0:22:01 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介:本资源为电源技术方向的学术研究文档,聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略,面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址: https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集,共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →