ChatGLM-6B云服务器部署教程

news2024/11/19 15:39:26

目录

  • 一、准备服务器
    • 1.购买服务器
    • 2.开机进入终端
    • 3.进入终端
  • 二、部署ChatGLM
    • 1.执行命令
    • 2.本地代理访问地址
      • 2.1 结果如下
      • 2.2 api接口一样操作
  • 三、Fastapi流式接口
    • 1.api_fast.py
      • 1.2 将api_fast.py上传到服务器
    • 2.准备插件
    • 3.访问地址

博客园地址:https://www.cnblogs.com/cnwanj/p/17486351.html

一、准备服务器

服务器地址:https://www.autodl.com

1.购买服务器

在这里插入图片描述

2.开机进入终端

在这里插入图片描述

3.进入终端

在这里插入图片描述

参考链接:https://zhuanlan.zhihu.com/p/614323117

二、部署ChatGLM

1.执行命令

cd ChatGLM-6B/

# 执行web页面
python web_demo.py

# 执行api接口
python api.py

2.本地代理访问地址

# 本地打开cmd
ssh -CNg -L 6006:127.0.0.1:6006 root@region-xx.seetacloud.com -p 29999

# 访问地址
http://127.0.0.1:6006

2.1 结果如下

在这里插入图片描述

2.2 api接口一样操作

在这里插入图片描述

参考链接:https://www.autodl.com/docs/ssh_proxy/

三、Fastapi流式接口

现在市面上好多教chatglm-6b本地化部署,命令行部署,webui部署的,但是api部署的方式企业用的很多,官方给的api没有直接支持流式接口,调用起来时间响应很慢,这次给大家讲一下流式服务接口如何写,大大提升响应速度

1.api_fast.py

from fastapi import FastAPI, Request
from sse_starlette.sse import ServerSentEvent, EventSourceResponse
from fastapi.middleware.cors import CORSMiddleware
import uvicorn
import torch
from transformers import AutoTokenizer, AutoModel
import argparse
import logging
import os
import json
import sys

def getLogger(name, file_name, use_formatter=True):
    logger = logging.getLogger(name)
    logger.setLevel(logging.INFO)
    console_handler = logging.StreamHandler(sys.stdout)
    formatter = logging.Formatter('%(asctime)s    %(message)s')
    console_handler.setFormatter(formatter)
    console_handler.setLevel(logging.INFO)
    logger.addHandler(console_handler)
    if file_name:
        handler = logging.FileHandler(file_name, encoding='utf8')
        handler.setLevel(logging.INFO)
        if use_formatter:
            formatter = logging.Formatter('%(asctime)s - %(name)s - %(message)s')
            handler.setFormatter(formatter)
        logger.addHandler(handler)
    return logger

logger = getLogger('ChatGLM', 'chatlog.log')

MAX_HISTORY = 5

class ChatGLM():
    def __init__(self, quantize_level, gpu_id) -> None:
        logger.info("Start initialize model...")
        self.tokenizer = AutoTokenizer.from_pretrained(
            "THUDM/chatglm-6b", trust_remote_code=True)
        self.model = self._model(quantize_level, gpu_id)
        self.model.eval()
        _, _ = self.model.chat(self.tokenizer, "你好", history=[])
        logger.info("Model initialization finished.")
    
    def _model(self, quantize_level, gpu_id):
        model_name = "THUDM/chatglm-6b"
        quantize = int(args.quantize)
        tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm-6b", trust_remote_code=True)
        model = None
        if gpu_id == '-1':
            if quantize == 8:
                print('CPU模式下量化等级只能是16或4,使用4')
                model_name = "THUDM/chatglm-6b-int4"
            elif quantize == 4:
                model_name = "THUDM/chatglm-6b-int4"
            model = AutoModel.from_pretrained(model_name, trust_remote_code=True).float()
        else:
            gpu_ids = gpu_id.split(",")
            self.devices = ["cuda:{}".format(id) for id in gpu_ids]
            if quantize == 16:
                model = AutoModel.from_pretrained(model_name, trust_remote_code=True).half().cuda()
            else:
                model = AutoModel.from_pretrained(model_name, trust_remote_code=True).half().quantize(quantize).cuda()
        return model
    
    def clear(self) -> None:
        if torch.cuda.is_available():
            for device in self.devices:
                with torch.cuda.device(device):
                    torch.cuda.empty_cache()
                    torch.cuda.ipc_collect()
    
    def answer(self, query: str, history):
        response, history = self.model.chat(self.tokenizer, query, history=history)
        history = [list(h) for h in history]
        return response, history

    def stream(self, query, history):
        if query is None or history is None:
            yield {"query": "", "response": "", "history": [], "finished": True}
        size = 0
        response = ""
        for response, history in self.model.stream_chat(self.tokenizer, query, history):
            this_response = response[size:]
            history = [list(h) for h in history]
            size = len(response)
            yield {"delta": this_response, "response": response, "finished": False}
        logger.info("Answer - {}".format(response))
        yield {"query": query, "delta": "[EOS]", "response": response, "history": history, "finished": True}


def start_server(quantize_level, http_address: str, port: int, gpu_id: str):
    os.environ['CUDA_DEVICE_ORDER'] = 'PCI_BUS_ID'
    os.environ['CUDA_VISIBLE_DEVICES'] = gpu_id

    bot = ChatGLM(quantize_level, gpu_id)
    
    app = FastAPI()
    app.add_middleware( CORSMiddleware,
        allow_origins = ["*"],
        allow_credentials = True,
        allow_methods=["*"],
        allow_headers=["*"]
    )
    
    @app.get("/")
    def index():
        return {'message': 'started', 'success': True}
    
    @app.post("/chat")
    async def answer_question(arg_dict: dict):
        result = {"query": "", "response": "", "success": False}
        try:
            text = arg_dict["prompt"]
            ori_history = arg_dict["history"]
            logger.info("Query - {}".format(text))
            if len(ori_history) > 0:
                logger.info("History - {}".format(ori_history))
            history = ori_history[-MAX_HISTORY:]
            history = [tuple(h) for h in history] 
            response, history = bot.answer(text, history)
            logger.info("Answer - {}".format(response))
            ori_history.append((text, response))
            result = {"query": text, "response": response,
                      "history": ori_history, "success": True}
        except Exception as e:
            logger.error(f"error: {e}")
        return result

    @app.post("/stream")
    def answer_question_stream(arg_dict: dict):
        def decorate(generator):
            for item in generator:
                yield ServerSentEvent(json.dumps(item, ensure_ascii=False), event='delta')
        result = {"query": "", "response": "", "success": False}
        try:
            text = arg_dict["prompt"]
            ori_history = arg_dict["history"]
            logger.info("Query - {}".format(text))
            if len(ori_history) > 0:
                logger.info("History - {}".format(ori_history))
            history = ori_history[-MAX_HISTORY:]
            history = [tuple(h) for h in history]
            return EventSourceResponse(decorate(bot.stream(text, history)))
        except Exception as e:
            logger.error(f"error: {e}")
            return EventSourceResponse(decorate(bot.stream(None, None)))

    @app.get("/clear")
    def clear():
        history = []
        try:
            bot.clear()
            return {"success": True}
        except Exception as e:
            return {"success": False}

    @app.get("/score")
    def score_answer(score: int):
        logger.info("score: {}".format(score))
        return {'success': True}

    logger.info("starting server...")
    uvicorn.run(app=app, host=http_address, port=port)


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Stream API Service for ChatGLM-6B')
    parser.add_argument('--device', '-d', help='device,-1 means cpu, other means gpu ids', default='0')
    parser.add_argument('--quantize', '-q', help='level of quantize, option:16, 8 or 4', default=16)
    parser.add_argument('--host', '-H', help='host to listen', default='0.0.0.0')
    parser.add_argument('--port', '-P', help='port of this service', default=8800)
    args = parser.parse_args()
    start_server(args.quantize, args.host, int(args.port), args.device)

1.2 将api_fast.py上传到服务器

在这里插入图片描述

2.准备插件

# 安装sse-starlette
pip install sse-starlette

# 启动命令
python api_fast.py

3.访问地址

ps:本地cmd启动代理

在这里插入图片描述

参考链接:https://blog.csdn.net/weixin_43228814/article/details/130063010

参考材料:

  • 服务器地址:https://www.autodl.com
  • 服务器配置:https://zhuanlan.zhihu.com/p/614323117
  • 本地代理:https://www.autodl.com/docs/ssh_proxy/
  • 流式接口;https://blog.csdn.net/weixin_43228814/article/details/130063010

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

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

相关文章

【裸机开发】中断系统 —— IRQ 中断服务函数(汇编部分)

IRQ 和前面的Reset 函数不大一样,当一个IRQ中断产生时,我们也不知道这个IRQ中断来自哪个外设,因此,需要先获取到中断ID,随后才会跳转到真正的中断服务函数执行处理逻辑。 整个 IRQ 中断处理可以看做是包含了两个部分&…

CSS查缺补漏之选择器

最近在复盘CSS基础知识,发现很多CSS选择器里面还是大有学问,需要详细总结一番,以备差缺补漏~ 作为CSS基础的一大类别,选择器又分为多种类别,本篇内容默认读者已了解并掌握基础选择器【通配符选择器】、【元素选择器】…

springboot+vue项目之MOBA类游戏攻略分享平台(java项目源码+文档)

风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的MOBA类游戏攻略分享平台。项目源码以及部署相关请联系风歌,文末附上联系信息 。 💕💕作者&#xf…

自动化测试框架Playwright安装以及使用

最近,微软开源了一个非常强大的自动化项目叫 playwright-python 它支持主流的浏览器,包含:Chrome、Firefox、Safari、Microsoft Edge 等,同时支持以无头模式、有头模式运行,并提供了同步、异步的 API,可以…

C++学习——第二节课-输入输出

大家好,我是涵子。今天我们来学习C中的输入输出。 一、电脑中的输入输出 日常生活中常见的电脑、手机、电视机外部接口,也就是I/O(输入/输出)接口部分,其样式、种类较多,不同的接口配置也体现了设备的档次…

SpringBoot整合jwt+redis+随机验证码+Vue的登录功能

一、运行效果展示 !注意:前端的Vue项目中要引入element-ui和axios # npm安装element-ui、axios npm insatll element-ui -S npm install axios -S # 在main中引入 // 引入ElementUI import ElementUI from element-ui import element-ui/lib/theme-chalk…

springboot动态加载json文件

resources下面的配置文件,application文件修改启动会实时加载新的内容 其他的文件属于静态文件,打包后会把文件打入jar里面,修改静态文件启动不会加载新的内容 Resource areacode nre FileSystemResource("config" File.separa…

技术分享——数据安全之数据分类方法小集

背景 2021年6月10日,《中华人民共和国数据安全法》(以下简称“《数安法》”)通过了第十三届全国人民代表大会常务委员会第二十九次会议并予以发布,标志着我国数据安全工作进入到有法可依的新阶段。 本文通过梳理现有的部分法规、…

Fiddler Orchestra从安装到实战演练

上次谈到了Fiddler Orchestra用户指南,这次笔者把自己的实战演练分享大家,闲话少说,步骤如下: 1、根据前面文章《Fiddler Orchestra用户指南》,Fiddler Orchestra客户端和控制器只能运行在至少支持.NET Standard 2.0的…

Redis入门(一)

第1章 NoSQL 1.1 NoSQL数据库 1.1.1 NoSQL是什么 (1)NoSQL(Not Only SQL ),意即“不仅仅是SQL”,泛指非关系型的数据库。 (2)NoSQL不拘泥于关系型数据库的设计范式,放弃了通用的技术标准&…

MyAQL事务

目录 ----------------------MySQL 事务-------------------------------- 1.事务的概念 2.事务的ACID特点 ●原子性 ●一致性 ●隔离性 事务隔离级别的作用范围分为两种: ●持久性 3.事务控制语句 案例: 4…

【Elacticsearch】 倒排索引的查增删改原理

关联文章:【Elacticsearch】 原理/数据结构/面试经典问题整理_东方鲤鱼的博客-CSDN博客 建立索引的原理 当向协调节点发送请求以索引新文档时,将执行以下操作: 所有在Elasticsearch集群中的节点都包含:有关哪个分片存在于哪个节点…

深度学习入门笔记1--梯度下降之--为什么是负方向--为什么局部下降最快的是负梯度方向

本节目标理解梯度下降的原理,主要围绕以下几个问题展开: 梯度下降法的用途?什么是梯度?为什么是负的梯度为什么局部下降最快的方向就是梯度的负方向。 需要的知识储备:一级泰勒展开公式 向量内积计算公式 1. 梯度下…

Sui主网升级至V1.3.0版本

Sui主网现已升级至V1.3.0版本,升级要点如下所示: 将协议版本更新至12 开始在Narwhal中使用BatchV2,新增VersionedMetadata允许更精细的追踪Narwhal批处理延迟。有关详细信息,请参阅#12178和#12290。 将协议版本更新至13 弃用0…

wtmp日志读取

wtmp日志介绍 之前遇到一个AIX服务器登录不上,但是能ping通的事情。一开始我怀疑是sshd服务坏掉了,但是使用telnet也无法登录。好在这台机器所在的机房就在我隔壁,于是外接显示器,直接上机操作。好在直接通过物理介质还是能登录得…

全球企业KVM贡献榜公布,腾讯云再添1项核心突破

6月14日,在全球虚拟化顶级技术峰会 KVM Forum 上,2023年度全球企业 KVM 开源贡献榜正式发布。腾讯云成为中国唯一连续七年入围的云厂商。 作为云计算的关键底层技术,云厂商需要利用KVM对物理机进行虚拟化,提供云端的池化算力。作为…

如何「假装」自己做过性能测试?

简历: 熟练掌握后端性能、压力测试 面试官: 你们是怎么做性能测试的? 我: 主要是对后端服务模块进行性能测试,我们上一个项目是是一个群聊项目,类似于QQ群,大家可以在一个群里聊天&#xf…

视觉SLAM十四讲——ch10实践(后端2)

视觉SLAM十四讲——ch10的实践操作及避坑 0. 实践前小知识介绍1. 实践操作前的准备工作2. 实践过程2.1 g2o原生位姿图2.2 李代数上的位姿图优化 3. 遇到的问题及解决办法3.1 在运行pose_graph_g2o_lie时出现错误 0. 实践前小知识介绍 视觉SLAM(Simultaneous Locali…

基于Java菜匣子优选系统设计实现(源码+lw+部署文档+讲解等)

博主介绍: ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ 🍅 文末获取源码联系 🍅 👇🏻 精…

粒子群算法(Particle Swarm Optimization(PSO)附简单案例及详细matlab源码)

作者:非妃是公主 专栏:《智能优化算法》 博客地址:https://blog.csdn.net/myf_666 个性签:顺境不惰,逆境不馁,以心制境,万事可成。——曾国藩 文章目录 专栏推荐序一、概论二、粒子群算法原理…