Qwen2.5-72B-Instruct实战:用vLLM构建流式响应API供Web端调用
Qwen2.5-72B-Instruct实战:用vLLM构建流式响应API供Web端调用
1. 引言:当大模型遇见流式响应
想象一下,你正在和一个智能助手对话,你问了一个复杂的问题。如果它要等上十几秒,把所有答案都“憋”出来再一次性展示给你,这个过程是不是既漫长又枯燥?你可能会怀疑它是不是卡住了,或者干脆失去耐心。
这就是传统大模型API调用方式的一个痛点。而今天,我们要解决的问题,就是让Qwen2.5-72B这样的“巨无霸”模型,也能像真人聊天一样,实现“边想边说”的流式响应体验。
本文将带你一步步实战,完成以下目标:
- 部署:使用vLLM高效部署经过GPTQ-Int4量化的Qwen2.5-72B-Instruct模型。
- 构建:创建一个支持流式响应的API服务。
- 调用:通过一个简洁的Web前端(Chainlit)来调用这个API,体验流畅的对话。
无论你是想为自己的产品集成一个智能对话功能,还是单纯想体验一下顶尖大模型的流式交互魅力,这篇教程都将为你提供一个清晰、可落地的路径。我们直接从部署好的环境开始,跳过繁琐的安装,聚焦于核心的API构建与调用。
2. 认识我们的主角:Qwen2.5-72B-Instruct-GPTQ-Int4
在开始动手之前,我们先快速了解一下即将要部署的模型。这能帮助我们更好地理解后续的配置和可能遇到的情况。
2.1 模型简介:更强的知识量与编程能力
Qwen2.5-72B-Instruct是通义千问大模型系列的最新成员,拥有720亿参数。相比前代,它主要在以下几个方面有了显著提升:
- 知识更广,能力更强:特别是在编程和数学领域,得益于专业数据的训练,表现大幅提升。
- 更懂指令,更长输出:能更好地遵循复杂指令,支持生成超过8K tokens的长文本,并且在理解表格、生成JSON等结构化数据方面表现优异。
- 超长上下文:支持长达128K tokens的上下文长度,足以处理一本中篇小说或一份超长的技术文档。
- 多语言支持:涵盖中文、英语、法语、日语、韩语等超过29种语言。
2.2 量化技术:GPTQ-Int4让大模型“瘦身”
720亿参数的原始模型对硬件要求极高。为了让我们能在消费级显卡或云端实例上运行它,这里使用了GPTQ量化技术。
- 什么是量化? 简单说,就是把模型参数从高精度(如FP16)转换为低精度(如INT4)。就像把一张高清图片压缩成体积更小的文件,虽然会损失一些细节,但核心内容得以保留。
- GPTQ-Int4:这是一种先进的4位整数量化方法,能在几乎不损失模型精度的情况下,将模型显存占用减少到原来的约1/4。这意味着原本需要多张A100才能加载的模型,现在一张RTX 4090或许就能跑起来。
我们即将部署的,就是这个“瘦身”后的高效版本:Qwen2.5-72B-Instruct-GPTQ-Int4。
3. 环境准备与模型服务验证
我们的实战从一个已经预置好环境的云工作空间开始。首先,我们需要确认模型服务是否已经成功启动。
3.1 验证vLLM服务状态
模型是通过vLLM部署的。vLLM是一个专为LLM推理设计的高吞吐量、内存高效的服务引擎,特别适合生产环境。我们可以通过查看日志来确认服务状态。
打开终端或WebShell,执行以下命令:
cat /root/workspace/llm.log 如果看到类似下面的输出,特别是包含 Uvicorn running on 和 model_name 等信息,就说明vLLM服务已经成功加载了我们的Qwen2.5模型,并在8000端口上监听API请求。
INFO 07-28 10:30:15 llm_engine.py:197] Initializing an LLM engine (v0.3.3) with config: model=Qwen2.5-72B-Instruct-GPTQ-Int4, ... INFO 07-28 10:32:45 model_runner.py:186] CUDA allocated: 39.2 GB INFO 07-28 10:32:45 model_runner.py:187] CUDA cache: 0 B INFO 07-28 10:32:45 model_runner.py:188] CPU allocated: 2.1 GB INFO 07-28 10:32:45 model_runner.py:189] CPU cache: 0 B INFO 07-28 10:32:46 llm_engine.py:347] # GPU blocks: 1430, # CPU blocks: 512 INFO 07-28 10:32:46 api_server.py:1071] Started server process [12345] INFO 07-28 10:32:46 api_server.py:1074] Waiting for application startup. INFO 07-28 10:32:46 api_server.py:1089] Application startup complete. INFO 07-28 10:32:46 api_server.py:1094] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit) 关键点:看到 Uvicorn running on http://0.0.0.0:8000 就成功了。模型加载可能需要几分钟,请耐心等待日志输出完成。
4. 构建流式响应API:与vLLM对话
vLLM内置了OpenAI兼容的API服务器。这意味着我们可以像调用ChatGPT的API一样来调用它。流式响应的秘密,就藏在API的一个参数里。
4.1 理解vLLM的API端点
vLLM主要提供了两个对我们有用的端点:
/v1/completions:用于文本补全。/v1/chat/completions:用于对话补全(更常用)。
由于我们部署的是Instruct指令微调模型,最适合使用对话接口。其请求格式与OpenAI API几乎一致。
4.2 流式请求的核心:stream=True
要让API返回流式响应,我们只需要在发送请求时,设置一个参数:"stream": true。
当vLLM收到这个标志后,它就不会一次性生成全部内容再返回,而是会以Server-Sent Events (SSE) 的形式,将生成的token逐个、或分批地推送给客户端。
下面是一个最基础的Python代码示例,展示如何向本地vLLM服务发送一个流式对话请求:
import requests import json # vLLM服务的地址 api_url = "http://localhost:8000/v1/chat/completions" # 请求头 headers = { "Content-Type": "application/json" } # 请求体:注意 `stream` 参数 data = { "model": "Qwen2.5-72B-Instruct-GPTQ-Int4", # 指定我们部署的模型 "messages": [ {"role": "user", "content": "请用简单的语言解释一下什么是量子计算。"} ], "stream": True, # !!!这就是开启流式的关键 !!! "max_tokens": 512 } # 发送POST请求,并设置stream=True让requests也以流式方式接收 response = requests.post(api_url, headers=headers, json=data, stream=True) # 处理流式响应 if response.status_code == 200: for line in response.iter_lines(): if line: # 每一条数据格式为:data: {...} decoded_line = line.decode('utf-8') if decoded_line.startswith('data: '): json_str = decoded_line[6:] # 去掉'data: '前缀 if json_str != '[DONE]': try: chunk = json.loads(json_str) # 提取并打印当前生成的文本片段 content = chunk['choices'][0]['delta'].get('content', '') if content: print(content,, flush=True) # 逐段打印,不换行 except json.JSONDecodeError: pass print() # 最终换行 else: print(f"请求失败,状态码:{response.status_code}") print(response.text) 运行这段代码,你会看到答案是一个词一个词(或一个短句一个短句)地“流”出来的,模拟了真实的打字或思考过程。
5. Web前端集成:使用Chainlit打造聊天界面
有了流式API,我们还需要一个好看又好用的界面来调用它。Chainlit是一个专门为构建LLM应用设计的前端框架,可以快速搭建出类似ChatGPT的交互界面,并且原生支持流式输出。
5.1 启动Chainlit应用
在我们的预置环境中,Chainlit应用已经配置好。通常,你可以在工作空间找到一个入口或通过特定命令启动。启动后,你会看到一个Web访问链接(通常是http://localhost:7860或类似的端口)。
打开这个链接,你就会进入一个清爽的聊天界面。
5.2 在Chainlit中调用流式API
Chainlit应用的后端代码(通常是app.py)已经写好了与vLLM API交互的逻辑。其核心思想和我们上面写的Python示例类似,但更加集成化。关键步骤是:
- 配置客户端:创建一个指向
http://localhost:8000的OpenAI兼容客户端。 - 发起流式请求:使用这个客户端,向
/v1/chat/completions端点发起请求,并设置stream=True。 - 处理流式响应:在Chainlit的回调函数中,逐个接收SSE事件,并将
delta.content实时发送到前端界面。
下面是一个简化的Chainlit后端代码片段,展示了核心逻辑:
import chainlit as cl from openai import OpenAI # 使用OpenAI库,因为vLLM兼容其API # 配置客户端,指向本地vLLM服务 client = OpenAI( base_url="http://localhost:8000/v1", # vLLM API地址 api_key="token-abc123" # vLLM默认不需要key,但某些配置可能需要,这里可以随意填 ) @cl.on_message async def main(message: cl.Message): # 创建一个Chainlit消息对象,用于流式输出 msg = cl.Message(content="") await msg.send() # 准备请求参数,关键:stream=True stream = client.chat.completions.create( model="Qwen2.5-72B-Instruct-GPTQ-Int4", messages=[ {"role": "system", "content": "你是一个乐于助人的AI助手。"}, {"role": "user", "content": message.content} ], stream=True, # 开启流式 max_tokens=1024 ) # 处理流式响应 async for chunk in stream: if chunk.choices[0].delta.content is not None: # 将每个流式片段添加到消息中 await msg.stream_token(chunk.choices[0].delta.content) # 流式结束,更新消息状态 await msg.update() 5.3 实际体验:提问与流式响应
现在,回到Chainlit的Web界面。
- 在底部的输入框里,输入你的问题,例如:“写一首关于春天的五言绝句。”
- 点击发送。
你会立刻看到界面上的AI助手开始“思考”并逐字输出答案,就像真正的对话一样。这种即时反馈的体验,远比等待一个完整的响应要好得多。
6. 关键配置与实用技巧
为了让整个流程运行得更顺畅,这里有一些关键的配置点和实用技巧。
6.1 vLLM部署参数解析
当初启动vLLM服务时,一些参数决定了服务的性能和行为。了解它们有助于你按需调整:
--model:指定模型路径或名称。--served-model-name:API中使用的模型名称,不指定则默认使用--model的值。--max-model-len:模型支持的最大上下文长度,需要根据模型能力设置(如Qwen2.5-72B支持128K)。--gpu-memory-utilization:GPU显存利用率,默认为0.9,在显存紧张时可调低。--quantization:指定量化方法,例如gptq。--api-key:如果不想开放访问,可以设置API密钥。
一个完整的启动命令可能类似这样(我们的环境已预配置):
python -m vllm.entrypoints.api_server \ --model Qwen2.5-72B-Instruct-GPTQ-Int4 \ --served-model-name Qwen2.5-72B-Instruct-GPTQ-Int4 \ --max-model-len 8192 \ --gpu-memory-utilization 0.85 \ --quantization gptq \ --port 8000 6.2 提升流式体验的API参数
在调用API时,除了stream=True,还有其他参数可以优化体验:
temperature(默认0.7):控制输出的随机性。值越低(如0.2),输出越确定、保守;值越高(如1.0),输出越有创意、随机。top_p(默认1.0):核采样参数。通常与temperature配合使用,只考虑累积概率达到top_p的最小token集合。max_tokens:限制生成的最大token数,防止生成过长内容。stop:指定停止序列,当模型生成这些字符串时停止。
例如,想要更稳定、更简短的答案:
{ "model": "Qwen2.5-72B-Instruct-GPTQ-Int4", "messages": [...], "stream": true, "max_tokens": 300, "temperature": 0.3 } 6.3 常见问题与排查
- 问题:Chainlit前端显示“连接错误”或长时间无响应。
- 排查:首先回到WebShell,用
cat /root/workspace/llm.log或curl http://localhost:8000/v1/models检查vLLM API服务是否真的在运行且健康。
- 排查:首先回到WebShell,用
- 问题:流式输出卡顿,或一次性输出一大段。
- 排查:这可能是网络或服务器处理速度导致的。确保
stream=True参数已正确设置。在Chainlit代码中,检查await msg.stream_token()是否在异步循环中被正确调用。
- 排查:这可能是网络或服务器处理速度导致的。确保
- 问题:模型回答不符合预期。
- 排查:检查发送的
messages格式是否正确。对于Instruct模型,通常需要包含system和user角色。也可以通过system提示词来强约束模型行为。
- 排查:检查发送的
7. 总结:从部署到交互的完整链路
回顾一下,我们完成了一个完整的、可用于生产的流式大模型应用搭建:
- 模型准备:我们使用了经过GPTQ-Int4量化的Qwen2.5-72B-Instruct模型,在保持强大能力的同时大幅降低了部署门槛。
- 服务部署:利用vLLM的高性能推理引擎,一键部署模型为OpenAI兼容的API服务,并验证了服务状态。
- API调用:掌握了vLLM流式API(
/v1/chat/completions)的核心调用方法,关键在于设置"stream": true参数。 - 前端集成:通过Chainlit框架,快速构建了一个美观且支持流式输出的Web聊天界面,将后端API的能力以用户体验极佳的方式呈现出来。
这套组合(vLLM + Chainlit)的优势在于:
- 高效:vLLM的PagedAttention等技术极大优化了推理速度和显存使用。
- 标准:OpenAI兼容的API,生态工具丰富,易于集成。
- 体验好:流式响应从根本上改善了用户与大型语言模型交互的体验。
- 快:Chainlit让你在几分钟内就能拥有一个功能完善的演示或产品原型。
你现在已经拥有了一个功能强大的智能对话后端和一个体验流畅的前端界面。你可以基于此,进一步开发更复杂的应用,如知识库问答、自动文档生成、代码助手等,让这个720亿参数的“大脑”为你创造更多价值。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 ZEEKLOG星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。