FastGPT+ChatGLM3-6b搭建知识库

前言:我用fastgpt直接连接chatglm3,没有使用oneai,不是很复杂,只需要对chatglm3项目代码做少量修改就能支持使用embeddings,向量模型用的m3e,效果还可以

我的配置:
处理器:i5-13500
显卡:RTX 4060Ti 16GB
内存:64GB
本文只是记录本人搭建过程,避免遗忘,写的不清楚望理解!

以下文件全部传至阿里云盘
1.ChatGLM3-6b代码
https://github.com/THUDM/ChatGLM3
模型很大,建议云盘下载
2.FastGPT
https://github.com/labring/FastGPT
3.向量模型m3e
https://huggingface.co/moka-ai/m3e-base

https://modelscope.cn/models/xrunda/m3e-base/files

注意:先安装合适的cuda和cudnn版本
cuda下载地址
https://developer.nvidia.com/cuda-toolkit-archive
cudnn下载地址
https://developer.nvidia.com/cudnn
安装步骤请参考
https://blog.csdn.net/Mind_programmonkey/article/details/99688839

部署步骤:

1.下载Anaconda

清华大学镜像网站速度很快
https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/?C=M&O=D
在这里插入图片描述
找到适合你系统的文件下载,我用的最新的
安装anaconda
执行以下命令创建chatglm3-6b的conda环境

conda create -n chatglm3-demo python=3.10
conda activate chatglm3-demo

请注意,chatglm3-6b项目需要 Python 3.10 或更高版本
创建完成后进入ChatGLM3-main\composite_demo目录中
在这里插入图片描述

注意:建议把requirements.txt中的torch删掉,稍后重新安装,这个torch会下载成cpu版本的,用gpu运行会报错

然后执行

pip install -r requirements.txt

此外,使用 Code Interpreter 还需要安装 Jupyter 内核:

ipython kernel install --name chatglm3-demo --user

安装torch和torchvision

注意版本!!!
刚刚创建的conda环境是python3.10版本,torch和torchvision要和python版本对应
torch-2.0.0+cu117-cp310-cp310-win_amd64.whl
torchvision-0.15.0+cu117-cp310-cp310-win_amd64.whl
文件已传云盘
如果你需要的torch和torchvision不是这两个,请到下面网站查询下载
https://download.pytorch.org/whl/

在conda环境中安装torch和torchvision
进入torch和torchvision所在路径下
执行

pip install torch-2.0.0+cu117-cp310-cp310-win_amd64.whl
pip install torchvision-0.15.0+cu117-cp310-cp310-win_amd64.whl

我把模型和代码放在同级目录下
在这里插入图片描述
然后配置系统环境变量,新建两个环境变量,如下,MODEL_PATH填写你模型的路径
在这里插入图片描述
在这里插入图片描述
然后打开client.py修改下处
在这里插入图片描述修改完
运行以下命令在本地加载模型并启动 demo:

streamlit run main.py

如果正常启动,证明环境和代码没有问题!
接下来配置openai_api.py实现知识库

2.配置openai_api.py实现知识库

1.修改openai_api.py在这里插入图片描述
2.进入D:\AI\ChatGLM3-main\openai_api_demo
在这里插入图片描述
执行代码

python openai_api.py

会报错,提示缺少loguru或者sse_starlette或者fastapi等等等
缺少哪个包执行哪个包的安装语句就可,如下

pip install 包名
例如:pip install fastapi

等待安装完成再次运行python openai_api.py,安装完缺少的包就可运行成功了
在这里插入图片描述
打开postman进行测试
在这里插入图片描述
请求体代码

{"model": "string","messages": [{"role": "user","content": "你好","name": "string","function_call": {"name": "string","arguments": "string"}}],"temperature": 0.8,"top_p": 0.8,"max_tokens": 0,"stream": false,"functions": {},"repetition_penalty": 1.1
}

运行成功
3.接下来修改openai_api.py代码,建议直接复制以下代码替换openai_api.py中所有代码


import time
from contextlib import asynccontextmanager
from typing import List, Literal, Optional, Unionimport os
import torch
import uvicorn
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from loguru import logger
from pydantic import BaseModel, Field
from sse_starlette.sse import EventSourceResponse
from transformers import AutoTokenizer, AutoModel
import numpy as np
import tiktoken
from sentence_transformers import SentenceTransformer
from sklearn.preprocessing import PolynomialFeaturesfrom utils import process_response, generate_chatglm3, generate_stream_chatglm3@asynccontextmanager
async def lifespan(app: FastAPI):  # collects GPU memoryyieldif torch.cuda.is_available():torch.cuda.empty_cache()torch.cuda.ipc_collect()app = FastAPI(lifespan=lifespan)app.add_middleware(CORSMiddleware,allow_origins=["*"],allow_credentials=True,allow_methods=["*"],allow_headers=["*"],
)class ModelCard(BaseModel):id: strobject: str = "model"created: int = Field(default_factory=lambda: int(time.time()))owned_by: str = "owner"root: Optional[str] = Noneparent: Optional[str] = Nonepermission: Optional[list] = Noneclass ModelList(BaseModel):object: str = "list"data: List[ModelCard] = []class FunctionCallResponse(BaseModel):name: Optional[str] = Nonearguments: Optional[str] = Noneclass ChatMessage(BaseModel):role: Literal["user", "assistant", "system", "function"]content: str = Nonename: Optional[str] = Nonefunction_call: Optional[FunctionCallResponse] = Noneclass DeltaMessage(BaseModel):role: Optional[Literal["user", "assistant", "system"]] = Nonecontent: Optional[str] = Nonefunction_call: Optional[FunctionCallResponse] = Noneclass ChatCompletionRequest(BaseModel):model: strmessages: List[ChatMessage]temperature: Optional[float] = 0.8top_p: Optional[float] = 0.8max_tokens: Optional[int] = Nonestream: Optional[bool] = Falsefunctions: Optional[Union[dict, List[dict]]] = None# Additional parametersrepetition_penalty: Optional[float] = 1.1class ChatCompletionResponseChoice(BaseModel):index: intmessage: ChatMessagefinish_reason: Literal["stop", "length", "function_call"]class ChatCompletionResponseStreamChoice(BaseModel):index: intdelta: DeltaMessagefinish_reason: Optional[Literal["stop", "length", "function_call"]]class UsageInfo(BaseModel):prompt_tokens: int = 0total_tokens: int = 0completion_tokens: Optional[int] = 0class ChatCompletionResponse(BaseModel):model: strobject: Literal["chat.completion", "chat.completion.chunk"]choices: List[Union[ChatCompletionResponseChoice, ChatCompletionResponseStreamChoice]]created: Optional[int] = Field(default_factory=lambda: int(time.time()))usage: Optional[UsageInfo] = None@app.get("/v1/models", response_model=ModelList)
async def list_models():model_card = ModelCard(id="chatglm3-6b")return ModelList(data=[model_card])@app.post("/v1/chat/completions", response_model=ChatCompletionResponse)
async def create_chat_completion(request: ChatCompletionRequest):global model, tokenizerif len(request.messages) < 1 or request.messages[-1].role == "assistant":raise HTTPException(status_code=400, detail="Invalid request")gen_params = dict(messages=request.messages,temperature=request.temperature,top_p=request.top_p,max_tokens=request.max_tokens or 1024,echo=False,stream=request.stream,repetition_penalty=request.repetition_penalty,functions=request.functions,)logger.debug(f"==== request ====\n{gen_params}")if request.stream:generate = predict(request.model, gen_params)return EventSourceResponse(generate, media_type="text/event-stream")response = generate_chatglm3(model, tokenizer, gen_params)usage = UsageInfo()function_call, finish_reason = None, "stop"if request.functions:try:function_call = process_response(response["text"], use_tool=True)except:logger.warning("Failed to parse tool call")if isinstance(function_call, dict):finish_reason = "function_call"function_call = FunctionCallResponse(**function_call)message = ChatMessage(role="assistant",content=response["text"],function_call=function_call if isinstance(function_call, FunctionCallResponse) else None,)choice_data = ChatCompletionResponseChoice(index=0,message=message,finish_reason=finish_reason,)task_usage = UsageInfo.parse_obj(response["usage"])for usage_key, usage_value in task_usage.dict().items():setattr(usage, usage_key, getattr(usage, usage_key) + usage_value)return ChatCompletionResponse(model=request.model, choices=[choice_data], object="chat.completion", usage=usage)async def predict(model_id: str, params: dict):global model, tokenizerchoice_data = ChatCompletionResponseStreamChoice(index=0,delta=DeltaMessage(role="assistant"),finish_reason=None)chunk = ChatCompletionResponse(model=model_id, choices=[choice_data], object="chat.completion.chunk")yield "{}".format(chunk.json(exclude_unset=True))previous_text = ""for new_response in generate_stream_chatglm3(model, tokenizer, params):decoded_unicode = new_response["text"]delta_text = decoded_unicode[len(previous_text):]previous_text = decoded_unicodefinish_reason = new_response["finish_reason"]if len(delta_text) == 0 and finish_reason != "function_call":continuefunction_call = Noneif finish_reason == "function_call":try:function_call = process_response(decoded_unicode, use_tool=True)except:print("Failed to parse tool call")if isinstance(function_call, dict):function_call = FunctionCallResponse(**function_call)delta = DeltaMessage(content=delta_text,role="assistant",function_call=function_call if isinstance(function_call, FunctionCallResponse) else None,)choice_data = ChatCompletionResponseStreamChoice(index=0,delta=delta,finish_reason=finish_reason)chunk = ChatCompletionResponse(model=model_id, choices=[choice_data], object="chat.completion.chunk")yield "{}".format(chunk.json(exclude_unset=True))choice_data = ChatCompletionResponseStreamChoice(index=0,delta=DeltaMessage(),finish_reason="stop")chunk = ChatCompletionResponse(model=model_id, choices=[choice_data], object="chat.completion.chunk")yield "{}".format(chunk.json(exclude_unset=True))yield '[DONE]'class EmbeddingRequest(BaseModel):input: List[str]model: strdef num_tokens_from_string(string: str) -> int:"""Returns the number of tokens in a text string."""encoding = tiktoken.get_encoding('cl100k_base')num_tokens = len(encoding.encode(string))return num_tokensdef expand_features(embedding, target_length):poly = PolynomialFeatures(degree=2)expanded_embedding = poly.fit_transform(embedding.reshape(1, -1))expanded_embedding = expanded_embedding.flatten()if len(expanded_embedding) > target_length:# 如果扩展后的特征超过目标长度,可以通过截断或其他方法来减少维度expanded_embedding = expanded_embedding[:target_length]elif len(expanded_embedding) < target_length:# 如果扩展后的特征少于目标长度,可以通过填充或其他方法来增加维度expanded_embedding = np.pad(expanded_embedding, (0, target_length - len(expanded_embedding)))return expanded_embedding@app.post("/v1/embeddings")
async def get_embeddings(request: EmbeddingRequest
):# 计算嵌入向量和tokens数量embeddings = [embeddings_model.encode(text) for text in request.input]# 如果嵌入向量的维度不为1536,则使用插值法扩展至1536维度embeddings = [expand_features(embedding, 1536) if len(embedding) < 1536 else embeddingfor embedding in embeddings]# Min-Max normalization 归一化embeddings = [embedding / np.linalg.norm(embedding) for embedding in embeddings]# 将numpy数组转换为列表embeddings = [embedding.tolist() for embedding in embeddings]prompt_tokens = sum(len(text.split()) for text in request.input)total_tokens = sum(num_tokens_from_string(text) for text in request.input)response = {"data": [{"embedding": embedding, "index": index, "object": "embedding"}for index, embedding in enumerate(embeddings)],"model": request.model,"object": "list","usage": {"prompt_tokens": prompt_tokens,"total_tokens": total_tokens,},}return responseif __name__ == "__main__":# model_path = "THUDM/chatglm3-6b"model_path = os.environ.get('MODEL_PATH', 'chatglm3-6b')tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)model = AutoModel.from_pretrained(model_path, trust_remote_code=True).cuda()# 多显卡支持,使用下面两行代替上面一行,将num_gpus改为你实际的显卡数量# from utils import load_model_on_gpus# model = load_model_on_gpus("D:\AI\chatglm3-6b", num_gpus=2)model = model.eval()embeddings_model = SentenceTransformer('D:\AI\m3e-base', device='cpu')uvicorn.run(app, host='0.0.0.0', port=8000, workers=1)

修改如下两处内容即可
在这里插入图片描述
然后再次执行

python openai_api.py

会提示缺包,按上面方法pip安装即可,执行成功即可开始部署FastGPT

3.部署FastGPT

1.需要Linux进行部署,windows有自带的虚拟化功能,可以安装Linux系统,参考
https://zhuanlan.zhihu.com/p/666301493
部署Ubuntu 20.04
因为我装的有Linux虚拟机,就直接在虚拟机上部署了
2.安装Docker、Docker-Compose
3.打开Fast-GPT代码,复制docker-compose.yml文件到Linux系统上
在这里插入图片描述
修改以下地方
在这里插入图片描述

pg的账号密码,我没改,和代码中一样,镜像用的阿里云
在这里插入图片描述
mongo的账号密码,我没改,和代码中一样,镜像用的阿里云
在这里插入图片描述
修改阿里云镜像和url地址
4.执行docker-compose.yml文件
在该文件目录下执行

docker compose up -d

在这里插入图片描述
成功后即可打开,默认3000端口
在这里插入图片描述
登录,默认root,密码1234
点击应用,新建
在这里插入图片描述
在这里插入图片描述
左边框框不用管,因为我们是直连ChatGLM3-6b,直接访问即可
在这里插入图片描述
执行成功!
在这里插入图片描述
知识库内容,新建数据,然后绑定到应用里即可,后续再详细写
在这里插入图片描述
在这里关联完即可问它知识库里的内容了

以上所用所有文件及程序:
https://www.alipan.com/s/Goc66oWkVEw
提取码: 8uv1
ChatGLM3-6b文件和模型不能分享,请到下面链接下载
链接:https://pan.baidu.com/s/1V_y-10Ixx7bFNUuQ9NhF9w
提取码:2s14

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/241008.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VideoPoet: Google的一种用于零样本视频生成的大型语言模型

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

【C++进阶02】多态

一、多态的概念及定义 1.1 多态的概念 多态简单来说就是多种形态 同一个行为&#xff0c;不同对象去完成时 会产生出不同的状态 多态分为静态多态和动态多态 静态多态指的是编译时 在程序编译期间确定了程序的行为 比如&#xff1a;函数重载 动态多态指的是运行时 在程序运行…

【Java异常】聊聊异常可能带来的坑

一个活生生的案例 本周帮同事排查了一个问题&#xff0c;比较诡异的是他通过测试&#xff0c;并没有找到根本原因&#xff0c;只是发现有对应的错误日志。 但是其实并没有将堆栈信息打印出来。很难看出问题。添加了 e.printStackTrace(); get exception in exter: / by zero显…

HP笔记本电脑进入BIOS的方法主要有两种,它们使用场合不同

BIOS&#xff08;基本输入输出系统&#xff09;是一种实用程序&#xff0c;它在你按下电源按钮后启动并加载操作系统。无论是要更新HP笔记本电脑的BIOS系统&#xff0c;还是清除前一个系统中的错误&#xff0c;第一步都是进入BIOS实用程序。 在按键输入BIOS设置并对其进行修改…

循环神经⽹络中的梯度算法GRU

1. 什么是GRU 在循环神经⽹络中的梯度计算⽅法中&#xff0c;我们发现&#xff0c;当时间步数较⼤或者时间步较小时&#xff0c;**循环神经⽹络的梯度较容易出现衰减或爆炸。虽然裁剪梯度可以应对梯度爆炸&#xff0c;但⽆法解决梯度衰减的问题。**通常由于这个原因&#xff0…

Java开发框架和中间件面试题(3)

14.Spring事务中的隔离级别有哪几种&#xff1f; 在TransactionDefinition接口中定义了五个表示隔离级别的常量&#xff1a; 1⃣️ISOLATION DEFAULT&#xff1a;使用后端数据库默认的隔离级别&#xff0c;Mysql默认采用的可重复读隔离级别&#xff1b;Oracle默认采用的读已提…

在Linux下探索MinIO存储服务如何远程上传文件

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;网络奇遇记、Cpolar杂谈 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. 创建Buckets和Access Keys二. Linux 安装Cpolar三. 创建连接MinIO服务公网地…

JavaWeb—html, css, javascript, dom,xml, tomcatservlet

文章目录 快捷键HTML**常用特殊字符替代:****标题****超链接标签****无序列表、有序列表****无序列表**:ul/li 基本语法**有序列表ol/li:****图像标签(img)**** 表格(table)标签****表格标签-跨行跨列表格****form(表单)标签介绍****表单form提交注意事项**div 标签p 标签sp…

Linux命令-查看内存、GC情况及jmap 用法

查看进程占用内存、CPU使用情况 1、查看进程 #jps 查看所有java进程 #top 查看cpu占用高进程 输入m &#xff1a;根据内存排序 topMem: 16333644k total, 9472968k used, 6860676k free, 165616k buffers Swap: 0k total, 0k used, 0k free, 6…

Kubernetes 的用法和解析(K8S 日志方案) -- 8

一、统一日志管理的整体方案 通过应用和系统日志可以了解Kubernetes集群内所发生的事情&#xff0c;对于调试问题和监视集群活动来说日志非常有用。对于大部分的应用来说&#xff0c;都会具有某种日志机制。因此&#xff0c;大多数容器引擎同样被设计成支持某种日志机制。 对…

MySQL——复合查询

目录 一.基本查询回顾 二. 多表查询 三.自连接 四.子查询 1.单行子查询 2.多行子查询 3.多列子查询 4.在from子句中使用子查询 5.合并查询 一.基本查询回顾 准备数据库&#xff1a; 查询工资高于500或岗位为MANAGER的雇员&#xff0c;同时还要满足他们的姓名首字母为…

【IntelliJ IDEA】打开项目Git突然无法识别解决方案

这个问题也是我今天突然偶尔遇到的&#xff0c;当时没在意&#xff0c;项目打开之后又关闭&#xff0c;后来很久才又打开&#xff0c;发现项目明明有git版本控制的&#xff0c;咋突然开发工具右下角没有标识了&#xff0c;然后检查了一下git配置还报错了。 其实从图上我们可以看…

服务器经常死机怎么办?如何处理

关于服务器死机这一话题相信大家是不会陌生的&#xff0c;平时在使用服务器的过程中&#xff0c;或多或少都是会有遇到过。轻则耽误业务开展&#xff0c;重则造成数据丢失&#xff0c;相信每个人都不想碰到服务器死机的情况。下文我也简单的介绍下服务器死机的原因以及对应的预…

安装vcpkg管理opencv的安装+MFC缺失的解决

第一步&#xff0c;出现#include没有办法找到opencv头文件的问题&#xff0c;无法解决 在VC的提示下&#xff0c;安装了vcpkg&#xff0c;然后用vcpkg命令来帮助安装opencv&#xff0c;过程十分顺利。 1. cmd 到命令行窗口&#xff1b; 2. 建立src文件夹&#xff0c;并进入…

Python入门学习篇(五)——列表字典

1 列表 1.1 定义 ①有序可重复的元素集合 ②可以存放不同类型的数据 ③个人理解:类似于java中的数组1.2 相关方法 1.2.1 获取列表长度 a 语法 len(列表名)b 示例代码 list2 [1, 2, "hello", 4] print(len(list2))c 运行结果 1.2.2 获取列表值 a 语法 列表名…

001 图书增删改查 SSM MySQL

技术框架&#xff1a;Spring SpringMVC Mybatis JSP MySQL 001 图书增删改查 SSM MySQL package com.demo.controller;import com.demo.pojo.Book; import com.demo.service.BookService; import org.springframework.beans.factory.annotation.Autowired; import org.spri…

Log4net 教程

一、Log4net 教程 在CodeProject上找到一篇关于Log4net的教程&#xff1a;log4net Tutorial&#xff0c;这篇博客的作者是&#xff1a;Tim Corey &#xff0c;对应源代码地址为&#xff1a; https://github.com/TimCorey/Log4netTutorial&#xff0c;视频地址为&#xff1a;Ap…

C#上位机与欧姆龙PLC的通信04---- 欧姆龙plc的存储区

1、存储区概念 欧姆龙PLC将整个数据存储器分为10个区&#xff1a;输入继电器区、输出继电器区、内部辅助继电器区、特殊继电器区、保持继电器区、暂存继电器区、定时/计数器区、数据存储区、辅助存储继电器区、链接继电器区。 输入输出继电器区 CP1E系列PLC输入继电器区有16…

acwing linux 第七讲 环境变量、管道、常用命令、附录

文章目录 管道 概念 要点 举例 环境变量 查看 修改 常用环境变量 常用命令 系统状况 文件权限 文件检索 查看文件内容 用户相关 其他工具 安装软件 附录 Linux权限 本节课讲解的是管道&#xff0c;环境变量&#xff0c;以及常用命令 管道 概念 管道类似文…

Qt/C++视频监控Onvif工具/组播搜索/显示监控画面/图片参数调节/OSD管理/祖传原创

一、前言 能够写出简单易用而又不失功能强大的组件&#xff0c;一直是我的追求&#xff0c;简单主要体现在易用性&#xff0c;不能搞一些繁琐的流程和一些极难使用的API接口&#xff0c;或者一些看不懂的很难以理解的函数名称&#xff0c;一定是要越简单越好。功能强大主要体现…