搭建一个大模型API服务

搭建一个大模型API服务

本文将介绍如何使用SWIFT框架搭建一个大模型API服务,以方便后续做RAG、Agent的开发工作。

环境准备

基础环境

  • 操作系统:Ubuntu 18.04.5 LTS (GNU/Linux 3.10.0-1127.el7.x86_64 x86_64)
  • Anaconda3:Anaconda3-2023.03-1-Linux-x86_64
  • 根据服务器网络情况配置好conda源和pip源,此处使用的是超算山河源

创建一个新的conda环境:

conda create --name swift python=3.8

激活刚刚创建的conda环境:

conda activate swift

下载SWIFT源码(v1.6.1):

git clone https://github.com/modelscope/swift.git

切换到SWIFT路径:

cd /yldm0226/swift

安装SWIFT:

pip install -e .[llm]

检查服务器cuda版本是否与当前安装的pytorch对应,如果不对应,需要将pytorch版本降低到≤服务器cuda版本;使用nvidia-smi查看cuda版本:

当前cuda版本为11.7; 然后使用conda list检查swift环境中pytorch的版本:

pytorch版本为2.2.0,从官网查询可知2.2.0版本最低支持的cuda版本为11.8,这大于服务器cuda版本11.7,因此需要将pytorch降低到支持cuda11.7的版本,从官网查询可知目前最高的可支持cuda11.7的版本为2.0.1。执行下述命令更换pytorch版本:

pip install torch==2.0.1 torchvision==0.15.2 torchaudio==2.0.2

注:如果pytorch版本与服务器cuda版本不对应,程序不会报错,而是会输出下面的警告,此时SWIFT会将模型权重加载到CPU上。推理速度非常慢:

UserWarning: CUDA initialization: The NVIDIA driver on your system is too old (found version 11070). Please update your GPU driver by downloading and installing a new version from the URL: http://www.nvidia.com/Download/index.aspx Alternatively, go to: https://pytorch.org to install a PyTorch version that has been compiled with your version of the CUDA driver. (Triggered internally at ../c10/cuda/CUDAFunctions.cpp:108.)

将大模型权重下载到本地,可以在ModelScopeHuggingFace选择对应模型下载,这里以Qwen1.5-14B-Chat为例:

git clone https://www.modelscope.cn/qwen/Qwen1.5-14B-Chat.git

搭建API服务

启动服务端

单卡部署

CUDA_VISIBLE_DEVICES=0 swift deploy --model_type qwen1half-14b-chat --model_id_or_path /yldm0226/models/Qwen1.5-14B-Chat

CUDA_VISIBLE_DEVICES可以指定使用哪块GPU进行部署;model_type表示你选择的模型类型,类型需是SWIFT框架支持的模型种类的一种,可以在此处查询所有支持的模型;--model_id_or_path表示模型在ModelScope Hub中的model_id或者本地路径,当指定本地路径时,代码会优先加载本地路径中的模型权重。

部署成功后,可以看到以下输出:

INFO:     Started server process [82478]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

多卡部署

RAY_memory_monitor_refresh_ms=0 CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 swift deploy --model_type qwen1half-14b-chat --model_id_or_path /yldm0226/models/Qwen1.5-14B-Chat --tensor_parallel_size 8

同样的,在部署成功后可以看到以下输出:

INFO:     Started server process [100001]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

可以通过nvidia-smi命令查看多卡部署的显存占用情况:

客户端测试

curl

想要快速测试API的可用性,可以使用curl:

curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen1half-14b-chat",
"messages": [{"role": "user", "content": "请介绍一下API服务"}],
"max_tokens": 1024,
"temperature": 0
}'

model与部署时的model_type一致。

可以得到下面形式的响应:

{"model":"qwen1half-14b-chat","choices":[{"index":0,"message":{"role":"assistant","content":"API(Application Programming Interface,应用程序编程接口)服务是一种接口,它允许不同的软件应用程序之间进行交互和数据共享。API是一组预定义的规则、协议和工具,开发者可以使用它来调用或访问某个应用程序、平台或服务的功能,而无需了解其底层实现细节。简单来说,它就像一个“桥梁”,使得开发者能够编写自己的程序,通过这个接口来获取数据、执行操作或者触发特定功能。\n\nAPI服务通常分为以下几种类型:\n\n1. **Web API**:基于HTTP协议,用于Web应用间的通信,如RESTful API,它以HTTP请求(GET、POST、PUT、DELETE等)的形式发送数据。\n\n2. **SDK API**:软件开发工具包(Software Development Kit)中的API,提供了特定平台或服务的编程接口,如Google Maps API、Facebook API等。\n\n3. **企业级API**:企业内部或外部提供的API,用于内部系统集成,如CRM系统API、支付API等。\n\n4. **机器学习/AI API**:如Google Cloud的机器学习API,允许开发者使用预训练模型进行预测或处理任务。\n\n5. **API Gateway**:一种服务,它集中管理多个API,提供安全、路由、缓存等功能,如AWS API Gateway。\n\n通过API服务,开发者可以快速地扩展功能、集成第三方服务,提高开发效率,同时促进了软件生态系统的繁荣。"},"finish_reason":null}],"usage":{"prompt_tokens":23,"completion_tokens":294,"total_tokens":317},"id":"chatcmpl-f7fa52fbf7de45f1bc1a31e369482a19","object":"chat.completion","created":1709258739}

swift

也可以使用swift框架去编写客户端代码,下面是一个简单的示例:

from swift.llm import get_model_list_client, XRequestConfig, inference_client

model_list = get_model_list_client()
model_type = model_list.data[0].id
print(f'model_type: {model_type}')

# 直接输出
query = '山东的省会在哪里?'
request_config = XRequestConfig(seed=42)
resp = inference_client(model_type, query, request_config=request_config)
response = resp.choices[0].message.content
print(f'query: {query}')
print(f'response: {response}')

# 流式输出
history = [(query, response)]
query = '这有什么好吃的?'
request_config = XRequestConfig(stream=True, seed=42)
stream_resp = inference_client(model_type, query, history, request_config=request_config)
print(f'query: {query}')
print('response: ', end='')
for chunk in stream_resp:
    print(chunk.choices[0].delta.content, end='', flush=True)
print()

第一个问题'山东的省会在哪里?'使用的是直接返回response的方式,第二个问题'这有什么好吃的?'使用的是流式输出的方式,可以根据需要选择对应的方式。

运行程序,可以得到以下输出:

query: 山东的省会在哪里?
response: 山东省的省会是济南。
query: 这有什么好吃的?
response: 山东作为中国的一个大省,美食丰富多样,这里有许多著名的特色菜肴和小吃。以下是一些你可能会感兴趣的:

1. 热干面(不是山东本地的,但济南也有人喜欢):源于武汉,但在山东也有类似面食。
2. 鲁菜:山东菜系,以济南菜为代表,如糖醋黄河鲤鱼、九转大肠、葱烧海参、锅包肉等,口味偏重,讲究原汁原味。
3. 烤鸭:虽然以北京最有名,但山东济南的烤鸭店也有特色。
4. 鲅鱼水饺:山东沿海城市如青岛的特色,用新鲜鲅鱼做馅,鲜美可口。
5. 豆腐脑:搭配薄饼、香菜、榨菜,是早餐的常见选择。
6. 煎饼:山东大煎饼,尤其是临沂煎饼,薄脆可卷各种食材。
7. 油旋:济南特色小吃,类似油条但更细,酥脆可口。

这只是冰山一角,山东各地还有许多其他美食,如鲁西南驴肉火烧、莱阳梨、胶东海鲜等,去山东旅行不妨尝试一下。

posted @ 2024-03-01 10:31  一蓑烟雨度平生  阅读(4119)  评论(0编辑  收藏  举报