全部文章

私有化部署大模型并使用FastApi暴露访问接口(glm4-9b-chat)

流程

glm4-9b-chat模型部署

了解模型说明

再部署任何模型之前,我们都可以去官网或者github上或者modelscope了解模型的详细信息,例如glm-4-9b-chat的详细说明:

image

最低硬件要求:如果希望运行官方提供的最基础代码 (transformers 后端) 您需要:
  • Python >= 3.10
  • 显存不少于 32 GB
如果希望运行官方提供的本文件夹的所有代码,还需要:
  • Linux 操作系统 (Debian 系列最佳)
  • 大于 8GB 显存的,支持 CUDA 或者 ROCM 并且支持 BF16 推理的 GPU 设备。(FP16 精度无法训练,推理有小概率出现问题)
如果具备符合上述要求的本地硬件资源,可以尝试进行私有化部署glm4-9b-chat进行测试,这里,我们以一张 4 * 3090 显卡的本地服务器配置进行部署演示。
  • Step 1. 使用 Xshell 远程连接 服务器
  • Step 2. 下载GLM 4 的官方GitHub项目文件
首先进入GLM 4 官方GitHub地址:https://github.com/THUDM/GLM-4/tree/main , 找到远程仓库的链接:
在Xshell中执行如下代码:
git clone https://github.com/THUDM/GLM-4.git
如果全部文件显示100%下载,且在当前路径下生成一个 GLM-4文件夹,说明项目文件已经下载成功。
  • Step 3. 安装独立的虚拟环境
  Conda创建虚拟环境的意义在于提供了一个隔离的、独立的环境,用于Python项目和其依赖包的管理。每个虚拟环境都有自己的Python运行时和一组库。这意味着我们可以在不同的环境中安装不同版本的库而互不影响。例如,可以在一个环境中使用Python 3.8,而在另一个环境中使用Python 3.9。对于大模型来说,建议Python版本3.10以上。创建的方式也比较简单,使用以下命令创建一个新的虚拟环境:
 # myenv 是你想要给环境的名称,python=3.8 指定了要安装的Python版本。你可以根据需要选择不同的名称和/或Python版本。

conda create --name glm4 python=3.11
创建完独立的虚拟环境后,需要进入该虚拟环境进行后续的操作。使用以下命令进入glm 4 的Python 虚拟环境:
 conda activate glm4
  • Step 5. 安装GLM 4 项目依赖
进入GLM 4文件夹后,执行如下命令一次性安装全部依赖。执行命令如下:
 # 进入指定路径
cd GLM-4/basic_demo

# 执行如下命令安装依赖
pip install -r requirements.txt
  • Step 5. 下载glm 4-9b-chat的模型权重
国内用户建议使用ModelScope下载地址 , 国外用户建议使用 huggingface下载地址
在远程服务器终端,先安装 modelscope 第三方依赖包,执行代码:
pip install modelscope
然后新建一个.py文件,执行命令如下:
vim download_models.py
写入如下代码:
# 文件中的内容如下:

#!/usr/bin/env python3
# -*- coding: utf-8 -*- 

# 先安装 pip install modelscope

from modelscope.hub.snapshot_download import snapshot_download

snapshot_download('ZhipuAI/glm-4-9b-chat', cache_dir='./', revision='master')
写入 download_models.py 文件后,保存退出,输入如下代码执行.py文件,等待glm-4-9b-chat模型下载完成即可。
python download_models.py
待下载完成后,会在当前路径下生成一个ZhipuAI的文件夹,里面会存储着glm4-9b-chat的全部模型权重文件:
cd ZhipuAI

cd glm-4-9b-chat/ && ll
  • Step 6. 启动模型服务
大模型的官方GitHub项目一般都会提供多种与大模型的交互形式,最常用的就是 基于命令行的交互对话、基于Gradio/Streamlit构建的WebUI交互页面,以及最普遍使用的基于OpenAI API的API接口规范。
而不论哪种形式,其需要我们修改的内容并不多,主要基于以下两点对官方提供的源代码脚本进行更改:
  1. 大模型的加载路径
  2. 服务启动的默认参数
我们以OpenAI API Server 为例。首先将模型的加载路径替换为本地的实际存储路径:
然后根据自己服务器的实际情况,灵活调整启动服务的参数:(在代码文件的最后面)
保存配置修改后,执行如下代码:
python openai_api_server.py
如果启动成功,会出现如下图所示内容:
在四卡3090的服务器上显存占用情况如下:

glm4-9b-chat模型调用

当启动了glm4-9b模型服务以后,如果我们想在代码程序中调用,就要分两种情况:
1.如果Python调用环境与部署glm4-9b-chat模型的环境为同一台服务器
2.如果调用环境和部署环境不是同一台机器
 
无论是那种情况都需要对Jupyter进行环境注册和配置,参照:《配置大模型开发环境(Jupyter Lab)
 
配置好环境之后,就可以直接进行调用测试,比如:我们可以使用Jupyter Lab 或者 Pycharm进行测试,核心代码如下:
from openai import OpenAI

base_url = "http://192.168.110.131:8000/v1/"
client = OpenAI(api_key="EMPTY", base_url=base_url)

messages = [{"role": "user", "content": "你好,请你介绍一下你自己"}]

response = client.chat.completions.create(
    model="glm-4",
    messages=messages,
)

print(response.choices[0].message.content)

 流式输出调用

 通过FastApi封装成对外API接口

项目结构:

image

项目依赖文件

 requirements.txt:

# fastapi依赖
executing==2.0.1
asttokens==2.4.1
six==1.16.0
blinker>=1.6.2
fastapi==0.111.0

# langchain依赖
langchain==0.2.7
langchain_community==0.2.7

loguru==0.7.2

zhipuai==2.1.2

安装所有依赖:

pip install -r requirement.txt

 封装调用大模型api逻辑

chat.py:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-


from fastapi import Body, HTTPException
from typing import List, Union, Optional

# 使用LangChain调用ChatGLM3-6B的依赖包
from langchain.chains.llm import LLMChain
from langchain_community.llms.chatglm3 import ChatGLM3
from langchain_core.messages import AIMessage
from langchain_core.prompts import PromptTemplate

# 日志包
from loguru import logger


def chat(query: str = Body("", description="用户的输入"),
         # model_name: str = Body("chatglm3-6b", description="基座模型的名称"),
         model_name: str = Body("glm4-9b-chat", description="基座模型的名称"),
         temperature: float = Body(0.8, description="大模型参数:采样温度", ge=0.0, le=2.0),
         max_tokens: Optional[int] = Body(None, description="大模型参数:最大输入Token限制"),
         ):
    """
    :param query: 用户输入的问题
    :param model_name: 使用哪个大模型作为后端服务
    :param temperature: 采样温度
    :param max_tokens: 最大输入Token限制
    :return:  大模型的回复结果
    """

    logger.info("Received query: {}", query)
    logger.info("Model name: {}", model_name)
    logger.info("Temperature: {}", temperature)
    logger.info("Max tokens: {}", max_tokens)

    # 使用LangChain调用glm4-9b-chat 或者 ChatGLM3-6B服务
    try:
        # 使用LangChain调用ChatGLM3-6B服务
        template = """{query}"""
        prompt = PromptTemplate.from_template(template)

        endpoint_url = "http://192.168.110.131:9091/v1/chat/completions"

        llm = ChatGLM3(
            endpoint_url=endpoint_url,
            model_name=model_name,
            temperature=temperature,
            max_tokens=max_tokens,
        )

        llm_chain = prompt | llm
        response = llm_chain.invoke(query)

        if response is None:
            raise ValueError("Received null response from LLM")

        return {"LLM Response": response}

    except ValueError as ve:
        # 捕获值错误并返回400响应
        raise HTTPException(status_code=400, detail=str(ve))
    except Exception as e:
        # 捕获所有其他异常并返回500响应
        raise HTTPException(status_code=500, detail="Internal Server Error: " + str(e))

 启动FastApi服务

api_router.py

 

#!/usr/bin/env python3
# -*- coding: utf-8 -*-


# FastAPI教程地址:https://fastapi.tiangolo.com/tutorial/first-steps/

from fastapi import FastAPI
from chat.chat import chat
import uvicorn

app = FastAPI(
    description="FuFan Chat Web API Server"
)

# 使用路由函数的方式定义,在动态添加路由或在运行时修改路由配置时更为灵活。
app.post("/api/chat",
         tags=["Chat"],
         summary="大模型对话交互接口",
         )(chat)

if __name__ == '__main__':

    uvicorn.run(app, host='192.168.110.131', port=8000)

postman调用接口测试 

 测试数据:

# http://192.168.110.131:8000/api/chat

{
    "query":"你好,请你介绍一下你自己",
    "model_name":"glm4-9b-chat", # 或者 chatglm3-6b
    "temperature":0.8,
    "max_tokens":4096
}

image

如果报错:

 

  File "/home/util/anaconda3/envs/fufan-chat-api/lib/python3.11/site-packages/charset_normalizer/api.py", line 10, in <module>
    from charset_normalizer.md import mess_ratio
AttributeError: partially initialized module 'charset_normalizer' has no attribute 'md__mypyc' (most likely due to a circular import)


## 解决办法

pip install --force-reinstall charset-normalizer==3.1.0

 

posted @ 2025-10-09 20:36  指尖下的世界  阅读(4)  评论(0)    收藏  举报