跳到主要内容

部署OpenAI兼容API服务并进行流式聊天

vLLM-MTT 支持通过提供OpenAI兼容的API接口,使得开发者可以使用与调用OpenAI API几乎相同的方式,来调用部署在vLLM-MTT上的模型,简化了大模型推理的部署和使用。

部署API服务:

python -m vllm.entrypoints.openai.api_server \
--model ${converted_model_dir} \
--served-model-name ${model_name} \
--trust-remote-code \
--tensor-parallel-size ${tp_size} \
-pp 1 \
--block-size 64 \
--max-model-len 2048 \
--disable-log-stats \
--disable-log-requests \
--device "musa"

可以在启动服务的同一容器下启动新终端并进行测试发送请求调用API。如需重新设置环境变量参考:快速开始-环境变量设置

# 通过api调用模型
curl http://0.0.0.0:8000/v1/chat/completions -H "Content-Type: application/json" -d '{
"model": "'"$model_name"'",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Who won the NBA final series in 2020?"}
]
}'
注意

model对应的模型字符串应和server端传入的--served-model-name参数内容保持一致。如果不传入--served-model-name参数,则model应使用${converted_model_dir}

示例输出:

{
"id": "cmpl-64f6804bfd87460fa8a756d901702667",
"object": "chat.completion",
"created": 1734934742,
"model": "Qwen2.5-72B-Instruct",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "The Los Angeles Lakers won the NBA Finals in 2020, defeating the Miami Heat in six games. This was the Lakers' 17th NBA championship, tying them with the Boston Celtics for the most in league history. The series MVP was LeBron James."
},
"logprobs": null,
"finish_reason": "stop",
"stop_reason": null
}
],
"usage": {
"prompt_tokens": 32,
"total_tokens": 88,
"completion_tokens": 56
}
}

(可选)进行流式聊天

确保API服务处于运行状态,运行以下程序(根据需要修改VLLM_API_URL):

python stream_chat.py --model-id ${model_name}
stream_chat.py
import requests
import json
import time
import readline
import threading
import sys
import argparse
import os

VLLM_API_URL = "http://localhost:8000/v1/chat/completions"

HISTORY_FILE = ".chat_history"
try:
readline.read_history_file(HISTORY_FILE)
except FileNotFoundError:
pass


def stream_vllm_response(messages, model):
global thinking_flag
headers = {"Content-Type": "application/json"}
payload = {"model": model, "messages": messages, "stream": True}

token_count = 0
start_time = time.time()

with requests.post(
VLLM_API_URL, headers=headers, json=payload, stream=True
) as response:

output_buffer = ""

for line in response.iter_lines():
if line:
try:
data = json.loads(line.decode("utf-8")[6:])
if "choices" in data and data["choices"]:
token = data["choices"][0]["delta"].get("content", "")
if token:
print(token, end="", flush=True)
token_count += 1
except json.JSONDecodeError:
continue

elapsed_time = time.time() - start_time
tokens_per_sec = token_count / elapsed_time if elapsed_time > 0 else 0
print(
f"\n\n[Model Metrics] Tokens: {token_count}, Time: {elapsed_time:.2f}s, Tokens/s: {tokens_per_sec:.2f}"
)


if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Interactive chat client for vLLM with streaming."
)
parser.add_argument(
"--model-id",
dest="model_id",
type=str,
required=True,
help="Specify the serve model name ",
)
args = parser.parse_args()

messages = [{"role": "system", "content": "You are a helpful AI assistant."}]

while True:
try:
user_input = input("\nUser: ")
readline.write_history_file(HISTORY_FILE)
except (KeyboardInterrupt, EOFError):
print("\n聊天结束。")
break

if user_input.lower() in ["exit", "quit"]:
print("聊天结束。")
break

messages.append({"role": "user", "content": user_input}) # record user input
stream_vllm_response(messages, args.model_id)
messages.append({"role": "assistant", "content": ""})

样例输出:

(base) mccxadmin@mccx:~$ python stream_chat.py --model-id ${model_name}

User: hi
Okay, so I need to figure out what to do next. The user just sent "hi," which is a friendly greeting. I should respond in a welcoming manner. Maybe start by acknowledging their greeting and then offer assistance. I should keep it open-ended so they feel comfortable asking for help. Something like, "Hello! How can I assist you today?" That sounds good because it's polite and inviting. I think that's a solid approach.
</think>

Hello! How can I assist you today?

[Model Metrics] Tokens: 101, Time: 1.16s, Tokens/s: 87.11

User: 你是谁?
我是DeepSeek-R1,一个由深度求索公司开发的智能助手,我擅长通过思考来帮您解答复杂的数学,代码和逻辑推理等理工类问题。
</think>

我是DeepSeek-R1,一个由深度求索公司开发的智能助手,我擅长通过思考来帮您解答复杂的数学,代码和逻辑推理等理工类问题。

[Model Metrics] Tokens: 76, Time: 0.85s, Tokens/s: 88.96

User: 8.11和8.9哪个大
嗯,我现在要解决的问题是“8.11和8.9哪个大”。首先,我需要明确这两个数字的含义。看起来它们都是小数,但小数点后的数字位数不同,一个是两位小数,一个是单数小数。我得先弄清楚这两位小数代表什么。

首先,我得回忆一下小数点后的数字代表的是什么。小数点后的第一位是十分位,第二位是百分位。所以,8.11中的1在十分位,第二个1在百分位;而8.9中的9在十分位,后面没有小数点后的数字了。这意味着8.9实际上可以看作是8.90。

现在,我需要比较的是8.11和8.90。为了方便比较,我可以将它们对齐小数点的位置。8.11和8.90,整数部分都是8,所以我要比较的是小数部分。小数部分,8.11的小数部分是0.11,而8.90的小数部分是0.90。

接下来,我需要比较0.11和0.90。因为小数部分的数值越大,整个数就越大。所以,我得想一下,0.11和0.90哪个更大。

为了更直观地理解,我可以把它们转换成分数来比较。0.11等于11/100,0.90等于90/100。显然,90/100大于11/100,所以0.90大于0.11。

因此,8.90比8.11大。也就是说,8.9比8.11大。

不过,我有点疑惑,因为有时候人们可能会觉得小数点后的位数多的数更大,但实际上并不是这样的。小数点后的位数多只是意味着精度更高,而不是数值大小。所以,8.9和8.11相比,8.9更大。

我再举个例子来验证一下。比如,我有8.11元和8.9元。8.11元等于8元1角1分,而8.9元等于8元9角。明显,8元9角比8元1角1分要多,所以8.9元大于8.11元。这进一步证明了我的结论是正确的。

总的来说,通过将小数点后的数字进行比较,或者将小数转换成分数或实际金额来比较,都能够得出8.9大于8.11的结论。
</think>

8.98.11 大。

[Model Metrics] Tokens: 566, Time: 6.32s, Tokens/s: 89.58

(可选)使用 KuaE-Chat 快速体验网页对话

KuaE Chat 是摩尔线程自主开发的简易网页对话体验前端,旨在帮助用户快速完成大模型部署的验证。其集成了包括模型后端一键部署、一键切换、数学公式渲染、深度思考等实用功能。

配合 vLLM-MTT 使用 KuaE Chat 请参考指南。因为 vLLM-MTT 与 vLLM-MUSA 本质上都通过 vLLM 暴露 OpenAI 兼容格式的推理服务 API,所以使用上没有明显差异。