简介
为在使用langgraph、langchain等框架的时候可以便捷地以OpenAI兼容的接口格式切换不同大模型接口,包括外部公网API和内部自己部署的API。本文以VLLM部署Qwen2.5为例介绍如何用VLLM以OpenAI兼容的接口格式服务部署大模型服务。
更多AI前沿及其实战相关,欢迎关注微信公众号《小窗幽记机器学习》:
准备工作
安装 vllm
pip3 install vllm -i https://pypi.tuna.tsinghua.edu.cn/simple
模型下载:
huggingface-cli download --resume-download --
local
-dir-use-symlinks False Qwen/Qwen2.5-1.5B-Instruct --
local
-dir /model\_dir/Qwen/Qwen2.5-1.5B-Instruct/
部署OpenAI兼容的API服务
借助vLLM,构建一个与OpenAI API兼容的API服务十分简便,该服务可以作为实现OpenAI API协议的服务器进行部署。默认情况下,它将在 http://localhost:8000 启动服务器。您可以通过 --host 和 --port 参数来自定义地址。请按照以下所示运行命令:
vllm serve /model\_dir/Qwen/Qwen2.5-1.5B-Instruct/ --host 0.0.0.0
无需担心chat模板,因为它默认会使用由tokenizer提供的chat模板。 PS:如果没有指定
--served-model-name
,那么
curl http://localhost:8000/v1/models
的结果如下:
{
"object"
:
"list"
,
"data"
:[{
"id"
:
"/model\_dir/Qwen/Qwen2.5-1.5B-Instruct/"
,
"object"
:
"model"
,
"created"
:1742205755,
"owned\_by"
:
"vllm"
,
"root"
:
"/model\_dir/Qwen/Qwen2.5-1.5B-Instruct/"
,
"parent"
:null,
"max\_model\_len"
:32768,
"permission"
:[{
"id"
:
"modelperm-88cdb40dca404a2c85aa3833e5347c02"
,
"object"
:
"model\_permission"
,
"created"
:1742205755,
"allow\_create\_engine"
:
false
,
"allow\_sampling"
:
true
,
"allow\_logprobs"
:
true
,
"allow\_search\_indices"
:
false
,
"allow\_view"
:
true
,
"allow\_fine\_tuning"
:
false
,
"organization"
:
"*"
,
"group"
:null,
"is\_blocking"
:
false
}]}]}
可以看出
id
是"/model_dir/Qwen/Qwen2.5-1.5B-Instruct/",所以后续请求的时候,需要指定"model": "/model_dir/Qwen/Qwen2.5-1.5B-Instruct/"。
因此,可以在启动服务的时候指定model的名字:
vllm serve /model\_dir/Qwen/Qwen2.5-1.5B-Instruct/ --host 0.0.0.0 --served-model-name
"Qwen2.5-1.5B-Instruct"
那么后续可以直接指定model=
Qwen2.5-1.5B-Instruct
来使用这个部署的模型服务。
另一种启动方式:
python3 -m vllm.entrypoints.openai.api\_server --served-model-name Qwen2.5-1.5B-Instruct --model /model\_dir/Qwen/Qwen2.5-1.5B-Instruct
API测试:curl
服务启动完成之后对API进行测试:
curl http://localhost:8000/v1/chat/completions -H
"Content-Type: application/json"
-d
'{
"model": "Qwen2.5-1.5B-Instruct",
"messages": [
{"role": "system", "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant."},
{"role": "user", "content": "你是谁?"}
],
"temperature": 0.7,
"top\_p": 0.8,
"repetition\_penalty": 1.05,
"max\_tokens": 512
}'
返回结果如下:
{
"id"
:
"chat-9868ba6a478d495fa2fa1fd5be868509"
,
"object"
:
"chat.completion"
,
"created"
:1742208973,
"model"
:
"Qwen2.5-1.5B-Instruct"
,
"choices"
:[{
"index"
:0,
"message"
:{
"role"
:
"assistant"
,
"content"
:
"我是Qwen,由阿里云开发的语言模型。我被设计用来回答各种问题、创作文字,以及进行文本生成。如果您有任何问题或需要帮助,请随时告诉我,我会尽力提供支持。"
,
"tool\_calls"
:[]},
"logprobs"
:null,
"finish\_reason"
:
"stop"
,
"stop\_reason"
:null}],
"usage"
:{
"prompt\_tokens"
:32,
"total\_tokens"
:75,
"completion\_tokens"
:43},
"prompt\_logprobs"
:null}
API测试:Python
from openai import OpenAI
# Set OpenAI's API key and API base to use vLLM's API server.
openai\_api\_key =
"EMPTY"
openai\_api\_base =
"http://0.0.0.0:8000/v1"
client = OpenAI(
api\_key=openai\_api\_key,
base\_url=openai\_api\_base,
)
chat\_response = client.chat.completions.create(
model=
"Qwen2.5-1.5B-Instruct"
,
messages=[
{
"role"
:
"system"
,
"content"
:
"你是微信公众号<小窗幽记机器学习>的智能助理"
},
{
"role"
:
"user"
,
"content"
:
"介绍下微信公众号<小窗幽记机器学习>"
},
],
temperature=0.7,
top\_p=0.8,
max\_tokens=512,
extra\_body={
"repetition\_penalty"
: 1.05,
},
)
print
(
"Chat response:"
, chat\_response)
输出结果如下:
Chat response: ChatCompletion(id=
'chat-1384edb0518d44c699a11525f788aac7'
, choices=[Choice(finish\_reason=
'stop'
, index=0, logprobs=None, message=ChatCompletionMessage(content=
'微信公众号“小窗幽记机器学习”是一个专注于机器学习、人工智能和数据科学领域的知识分享平台。该公众号旨在通过原创内容、深度分析和案例研究,帮助读者理解机器学习的基础原理、算法应用以及实践方法。文章通常涵盖以下主题:\n\n1. **机器学习基础**:介绍机器学习的基本概念、分类、监督学习、无监督学习等。\n2. **算法与模型**:深入探讨各种机器学习算法(如线性回归、决策树、神经网络等)的原理和实现。\n3. **实践指南**:提供实际操作中的机器学习项目建议,包括数据预处理、模型训练和评估等步骤。\n4. **案例研究**:分析和讨论实际数据集上的机器学习应用,展示机器学习在不同领域的应用效果。\n5. **技术趋势**:关注最新的机器学习技术和研究动态,帮助读者了解行业前沿。\n\n该公众号的目标是为对机器学习感兴趣的读者提供一个学习和探索的平台,同时也为机器学习从业者提供交流和分享的社区。通过提供详细的文字解释和代码示例,使复杂的机器学习概念变得易于理解和应用。'
, refusal=None, role=
'assistant'
, audio=None, function\_call=None, tool\_calls=[]), stop\_reason=None)], created=1742209124, model=
'Qwen2.5-1.5B-Instruct'
, object=
'chat.completion'
, service\_tier=None, system\_fingerprint=None, usage=CompletionUsage(completion\_tokens=240, prompt\_tokens=39, total\_tokens=279, completion\_tokens\_details=None, prompt\_tokens\_details=None), prompt\_logprobs=None)
其实,可以看出基本就是一本正经的胡说八道。但是,毕竟小众的微信公众号,就这样子吧,不要为难Qwen了~
离线推理
from transformers import AutoTokenizer
from vllm import LLM, SamplingParams
# Initialize the tokenizer
model\_path =
"/model\_dir/Qwen/Qwen2.5-1.5B-Instruct"
tokenizer = AutoTokenizer.from\_pretrained(model\_path)
# Pass the default decoding hyperparameters of Qwen2.5-7B-Instruct
# max\_tokens is for the maximum length for generation.
sampling\_params = SamplingParams(temperature=0.7, top\_p=0.8, repetition\_penalty=1.05, max\_tokens=512)
# Input the model name or path. Can be GPTQ or AWQ models.
llm = LLM(model=model\_path)
# Prepare your prompts
prompt =
"你是谁?"
messages = [
{
"role"
:
"system"
,
"content"
:
"你是微信公众号<小窗幽记机器学习>的智能助理"
},
{
"role"
:
"user"
,
"content"
: prompt}
]
text = tokenizer.apply\_chat\_template(
messages,
tokenize=False,
add\_generation\_prompt=True
)
# generate outputs
outputs = llm.generate([text], sampling\_params)
# Print the outputs.
for
output
in
outputs:
prompt = output.prompt
generated\_text = output.outputs[0].text
print
(f
"Prompt: {prompt!r}, Generated text: {generated\_text!r}"
)
输出结果如下:
Prompt:
'<|im\_start|>system\n你是微信公众号<小窗幽记机器学习>的智能助理<|im\_end|>\n<|im\_start|>user\n你是谁?<|im\_end|>\n<|im\_start|>assistant\n'
, Generated text:
'我是微信公众号《小窗幽记机器学习》的智能助手,我负责回答读者关于机器学习、人工智能等技术问题。如果您有任何关于机器学习的问题,欢迎随时提问!'