当前位置: 首页 > article >正文

从0到1实现你自己的AI Chat应用

在这里插入图片描述

欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C++、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学习,人工智能等相关领域的知识和技术。关注公粽号 《机器和智能》 回复关键词 “python项目实战” 即可获取美哆商城视频资源!


博主介绍:
CSDN博客专家,CSDN优质创作者,CSDN实力新星,CSDN内容合伙人;
阿里云社区专家博主;
华为云社区云享专家;
51CTO社区入驻博主,掘金社区入驻博主,支付宝社区入驻博主,博客园博主。


《大模型项目实战:多领域智能应用开发》


🎉🎉🎉🎉🎉 重磅福利 🎉🎉🎉🎉🎉
🎉本次送2套书 ,评论区抽2位小伙伴送书
🎉活动时间:截止到 2024-10-31 10:00:00
🎉抽奖方式:评论区随机抽奖。
🎉参与方式:关注博主、点赞、收藏,评论。
❗注意:一定要关注博主,不然中奖后将无效!
🎉通知方式:通过私信联系中奖粉丝。
💡提示:有任何疑问请私信公粽号 《机器和智能》

目标基于大语言模型的 Chat 应用,是一种利用自然语言处理技术来进行对话交互的智能应用。大语言模型通过大量数据的学习和训练,能够理解自然语言表达的语义,具备智能对话的能力。当用户向 Chat 应用提出问题时,Chat 应用就会利用其学习到的知识和自然语言处理技术来理解用户的意图,然后推理生成相应的答案。我们的目标是使用 React.js 开发一个通用的 Chat 应
用程序,提供对话 Web 界面,调用 ChatGLM3 项目的 OpenAI 兼容接口,编译并部署到 Nginx。功能概要(1)Chat 交互界面该应用使用 Chat 对话模式的界面,接收用户的输入内容,并将其显示到聊天记录中。大语言模型返回的结果会回写到聊天记录中。用户与大模型交流的文本用左右位置或图标进行区分。(2)流式接口这是指 OpenAI 兼容的流式调用方式,最早由 ChatGPT 使用,目前已成为大语言模型 Chat 应用事实上的接口标准。流式访问是一种服务端逐步推送数据、客户端逐步接收结果并显示的方法,适用于处理大量数据或长时间运行的任务。(3)多轮会话多轮对话是指模型把当前的问题及上文的问答情况整合到一起,形成关于问题的上下文描述。由于在多轮会话中输入的 token 较长,问题的上下文描述得比较清楚,相关语境也构建得相对完整,所以相比于单轮对话,多轮会话生成的答案更为合理。其缺点在于随着对话轮数的增加,输入的 token 越来越长,会影响大语言模型的运算效率。所以在具体实现 Chat 应用时,要对历史对话记录进行一定的限制,以防止输入 token 过长导致模型的生成性能下降。(4)打字效果ChatGPT 采用了模拟打字的视觉效果实现行文本的逐步生成,既保证用户能在第一时间获取生成的部分文本信息,不会觉得等待时间很长,也减少了大模型一次性生成长文本导致算力过载的情况。因此,这次所开发的应用也采用了此技术来显示文本的生成过程。打字效果的实现基于 SSE 服务端推送技术。SSE 是一种 HTML5 技术,允许服务器向客户端推送数据,而不需要客户端主动请求。它能在服务端有新消息时,将消息实时推送到前
端,从而实现动态打字的聊天效果。系统架构Chat 应用是一个 B/S 结构的应用。服务端由大语言模型的 OpenAI API 服务提供,客户端使用 React.js 编写,部署于 Nginx。客户端通过浏览器访问页面,在浏览器中执行 JavaScript 代码,以将用户的输入发送至服务端,渲染页面显示服务端返回的结果。其架构图见图 1。
在这里插入图片描述
(1)大模型服务层模型推理服务由大语言模型的代码完成,如在 ChatGLM3-6B 模型的 modeling_chatglm.py 文件中,stream_chat 函数实现了流式推理。模型 API 服务则由 ChatGLM3 项目源码中的openai_api_demo/api_server.py 提供。(2)应用服务层在开发环境下由 npm 模拟一个本地应用服务,承担页面下载和请求代理的职责。而在正式运行环境中,这两个职责是由 Nginx 的页面部署服务和代理转发功能来完成的。Nginx
在配置上还要支持 SSE 推流模式。(3)客户端浏览器层通过运行在浏览器中的 HTML5 和 JavaScript 代码来与应用服务层交互。JavaScript 发出的 HTTP/HTTPS 请求经应用服务层转发到模型 API 服务。运行原理浏览器负责展现页面,调用 OpenAI 兼容接口来获取生成内容。Nginx 提供页面内容以及代理调用 OpenAI 兼容接口。页面请求和接口调用在一个域名或IP:端口内,这样可以避免跨域问题。跨域问题是指在 Web 开发中,当一个网站的客户端(前端)需要调用服务端(后端)的 API 时,请求的 URL 与页面的 URL 来自不同的域名,导致安全风险,而被浏览器拦截。openai_api.py 用于装载模型,提供 API 服务。开发(1)Node.js 安装React.js 程序的开发调试要在 Node.js 环境下进行。从 https://nodejs.org/ 中下载并安装 Node.js,然后在命令行运行node -v命令来测试它是否安装成功。(2)chat-app 新建1)新建应用新建一个名为 chat-app 的 React.js 应用,命令如下。

npm install -g create-react-app
create-react-app chat-app
cd chat-app

2)安装组件chat-app 用到两个第三方组件,一个是作为 Chat 界面的 ChatUI 框架,另一个是调用模型 API 服务的 Node.js 组件—openai-node。

npm i --save @chatui/core
npm i --save openai

源代码实现 Chat 页面和业务逻辑的代码在 src/app.js 中。它只有 61 行代码,下面完整展示出来。

import './App.css';
import React from 'react';
import '@chatui/core/es/styles/index.less';
import Chat, { Bubble, useMessages } from '@chatui/core';
import '@chatui/core/dist/index.css';
import OpenAI from 'openai';
const openai = new OpenAI({
 apiKey: 'EMPTY', dangerouslyAllowBrowser: true,
 baseURL: "http://server-llm-dev:8000/v1"
});
var message_history = [];
function App() {
 const { messages, appendMsg, setTyping, updateMsg } = useMessages([]);
 async function chat_stream(prompt, _msgId) {
 message_history.push({ role: 'user', content: prompt });
 const stream = openai.beta.chat.completions.stream({
 model: 'ChatGLM3-6B',
 messages: message_history,
 stream: true,
 });
 var snapshot = "";
 for await (const chunk of stream) {
 snapshot = snapshot + chunk.choices[0]?.delta?.content || '';
 updateMsg(_msgId, {
 type: "text",
 content: { text: snapshot.trim() }
 });
 }
 message_history.push({ "role": "assistant", "content": snapshot });
 }
 function handleSend(type, val) {
 if (type === 'text' && val.trim()) {
 appendMsg({
 type: 'text',
 content: { text: val },
 position: 'right',
 });
 const msgID = new Date().getTime();
 setTyping(true);
 appendMsg({
 _id: msgID,
 type: 'text',
 content: { text: '' },
 });
 chat_stream(val, msgID);
 }
}
function renderMessageContent(msg) {
 const { content } = msg;
 return <Bubble content={content.text} />;
}
return (
<Chat
 navbar={{ title: 'chat-app' }}
 messages={messages}
 renderMessageContent={renderMessageContent}
 onSend={handleSend}
 />
 );
}
export default App;

测试
(1)启动大模型 API 服务安装 ChatGLM3-6B 模型。API 服务则由 ChatGLM3 代码库的 openai_api_demo/api_server.py 提供。在这个文件中,/v1/embeddings 接口依赖一个较小文本向量模型 BAAI/bge-large-zh-v1.5。虽然本次开发应用程序中不会用到它,但为了保证程序能正常运行,建议先下载这个模型。

cd ChatGLM3
conda activate ChatGLM3
wget https://aliendao.cn/model_download.py
python model_download.py --e --repo_id BAAI/bge-large-zh-v1.5 \
--token YPY8KHDQ2NAHQ2SG

设定模型及文本向量模型文件所在位置,启动 API 服务,监听 8000 端口。

MODEL_PATH=./dataroot/models/THUDM/chatglm3-6b \
EMBEDDING_PATH=./dataroot/models/BAAI/bge-large-zh-v1.5 \
python openai_api_demo/api_server.py

(2)测试 chat-app客户端程序目录下运行npm start命令,以启动客户端的开发环境服务。在浏览器中打开http://localhost:3000,运行结果如图 2 所示。
在这里插入图片描述
运行发现,在 chat-app 应用中,用户可以进行流式人机对话。该应用同时支持多轮对话,也实现了打字的视觉效果。也就是说,该应用达到了原先设定的目标。(3)界面美化chat-app 是一个通用的 Chat 应用客户端,通过改变程序中的apiKey和baseURL参数,可以连接任意一个兼容 OpenAI 接口的大语言模型推理服务,当然包括在正确设置apiKey的情况下连接 OpenAI 的服务。此时,chat-app 的界面还需要进一步美化。比如,将输入框从一行变为多行以便于输入。需要在 app.js 文件的同级目录下建一个 chatui-theme.css 文件,内容如下。

.ChatFooter .Composer-input {
 background: white;
 max-height: 160px;
 border: 1px solid darkgray;
 min-height: 80px;
 height: auto;
}

在 app.js 文件中的第 6 行代码import OpenAI from ’openai’;后增加一行
命令,如下所示。import './chatui-theme.css';
重新用npm start命令运行程序,就可以看到输入框变成多行了。应用发布在程序开发调试过程中,应用依赖于 Node.js,并以“ npm start”的方式运行。对此,可以通过编译过程,将 React.js 程序编译成脱离 Node.js 的 HTML5 和 JavaScript 文件,部署到 Nginx 等应用服务器中运行。(1)编译运行以下命令编译源代码,将编译结果存放在 build 目录下。

npm run build

(2)发布将 build 目录下的所有文件复制到 Nginx 的 html 目录下即可完成部署。如果是 Windows操作系统,则 html 在 Nginx 的目录下;如果是 Linux 操作系统,其目录则可能是/usr/local/share/nginx/html 或 /usr/local/nginx/html。(3)运行首次运行 Nginx 时,在 Windows 上直接运行 nginx.exe,在 Linux 上则要运行sudo nginx命令。如果 Nginx 已运行,那么配置文件会发生改变,需要重启。可以执行以下命令。
sudo nginx -s reload
对于该命令,在 Windows 或 Linux 上的形式几乎是一样的,区别在于因为涉及权限问题,对于 Linux 系统,需要在命令前加sudo。(4)应用升级借助浏览器的缓存机制可以减少页面、JavaScript 代码的下载量。因为它会对相同请求 URL 的 HTML5 页面、JavaScript 代码进行缓存。然而,每次执行npm build命令产生的文件名是固定的,这样即使代码有调整,且 Nginx 的 html 目录下的文件已更新,但由于 URL 未发生变化,浏览器仍会从缓存中加载旧版本。为了解决这个问题,可修改 package.json 中的 version参数值,提高版本号,以编译出不同的文件名。这样浏览器会由于 URL发生变化而忽略缓存,加载文件的最新版本。(5)SSE 配置启动 Nginx 服务后,就可以使用诸如http://127.0.0.1这样不带端口的 URL 访问页面,但是可能会存在跨域问题。因为页面对应 Nginx 所在计算机的 80 端口,JavaScript 调用的是 API 服务器的 8000 端口,两者的 IP 和端口是不一样的。如果 API 服务端不处理跨域问题的话,chat-app 调 API 服务就会报跨域错误。解决的方法是在 Nginx 的 80 端口上配置一个 API 服务的路径代理。因为要支持 SSE,这个代理配置要与一般的路径代理有一定的区别。举例来说,在 baseURL 为http://server-llm-dev:8000/v1的情况下,在 Nginx 的 conf/nginx.conf 中的 server 模块下增加一个location,如下所示。

location /v1 {
 proxy_http_version 1.1;
 proxy_set_header Connection "";
 proxy_set_header X-Real-IP $remote_addr;
 proxy_set_header Host $host;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 # SSE 连接时的超时时间
 proxy_read_timeout 86400s;
 # 取消缓冲
 proxy_buffering off;
 # 关闭代理缓存
 proxy_cache off;
 # 禁用分块传输编码
 chunked_transfer_encoding off;
 # 反向代理到 SSE 应用的地址和端口
 proxy_pass http://server-llm-dev:8000/v1;
}

重启 Nginx,将 app.js 中的 baseURL 由http://server-llm-dev:8000/v1更改为http://127.0.0.1/ v1。重新编译部署后,即可发现跨域问题得以解决。
在这里插入图片描述
内容简介:本书系统地讲解了大语言模型的实战应用过程,涵盖基础知识、常见操作和应用开发3个方面,帮助大语言模型的使用者、应用开发者循序渐进地掌握大模型的原理、操作以及多个场景下的应用开发技能。

购买链接:点击购买

在这里插入图片描述


http://www.kler.cn/news/364492.html

相关文章:

  • 【Javaee】网络原理—TCP协议的核心机制
  • TCP全连接队列与 tcpdump 抓包
  • 【ChatGPT】如何通过实例提升 ChatGPT 的回答质量
  • 开拓鸿蒙测试新境界,龙测科技引领自动化测试未来
  • Android 图片相识度比较(pHash)
  • ctfshow-web入门-web31
  • 密码学----RSA算法
  • Higress 云原生网关
  • JVM监控与调优工具
  • RabbitMQ最新版本4.0.2在Windows下的安装及使用
  • mac中按照官网教程安装了 pgsql 报错 command not found: psql
  • Java项目编译不通过,IDEA无法运行或调试Unit test类
  • 移动开发(四):.NET MAUI中Android应用修改安装图标和启动页面
  • EasyExcel_动态表头的导入导出
  • 非强化学习的对齐方法
  • 稳啦!掌握缓存一致性与失效预防措施——使用缓存不可或缺的指南!
  • MQL实验(二)作业
  • 【蓝桥杯选拔赛真题77】python计算小球 第十五届青少年组蓝桥杯python选拔赛真题 算法思维真题解析
  • [deadlock]死锁导致的设备登录无响应问题
  • 深入解析Java中的锁
  • 【业务】群组服务功能重构测试总结
  • 基于ssm+vue的房源管理系统设计与实现
  • Vue前端播放rtsp视频流(vue+webrtc-streamer)
  • 使用 Pake 一键打包网页为桌面应用 / 客户端
  • 预算不够,怎么跟KOL砍价?(内附砍价模板)
  • 头部聚合公司源码质量测评!手把手教你打造高质量的碰一碰支付系统!