通义千问1.8B-Chat-GPTQ-Int4部署教程:Docker容器内vLLM服务启动与端口映射

想快速体验一个轻量级但功能强大的中文对话模型吗?通义千问1.8B-Chat-GPTQ-Int4版本,就是一个绝佳的选择。它体积小巧,对硬件要求不高,但对话能力却相当出色。

今天,我就带你手把手完成这个模型的部署。我们将使用vLLM这个高效的推理引擎,在Docker容器里启动模型服务,并配置好端口映射,让你能轻松地从外部访问。最后,我们还会用一个简洁的Web界面(Chainlit)来验证服务是否正常,并和模型聊上几句。

整个过程清晰明了,即使你是刚接触模型部署的新手,也能跟着步骤顺利完成。准备好了吗?我们开始吧。

1. 环境准备与快速部署

部署的第一步,是确保我们有一个干净、可用的环境。这里我们选择Docker,它能帮我们隔离环境,避免各种依赖冲突,让部署过程变得简单。

1.1 获取模型与启动脚本

首先,你需要获取模型文件和配套的启动脚本。通常,这些资源会打包在一起。假设你已经下载了一个名为 qwen1.5-1.8b-chat-gptq-int4 的模型目录,里面包含了模型权重和必要的配置文件。

同时,你还需要一个启动服务的Python脚本,我们把它命名为 start_vllm_service.py。这个脚本的核心是使用vLLM库来加载模型并启动一个API服务。

一个基础的 start_vllm_service.py 脚本内容如下:

from vllm import AsyncEngineArgs, AsyncLLMEngine
from vllm.engine.arg_utils import AsyncEngineArgs
from vllm.entrypoints.openai.api_server import run_server
import argparse
import os

def main():
    parser = argparse.ArgumentParser(description="启动 Qwen1.5-1.8B-Chat-GPTQ-Int4 的 vLLM OpenAI API 服务")
    parser.add_argument("--model", type=str, required=True, help="模型路径")
    parser.add_argument("--tensor-parallel-size", type=int, default=1, help="张量并行大小")
    parser.add_argument("--host", type=str, default="0.0.0.0", help="服务监听地址")
    parser.add_argument("--port", type=int, default=8000, help="服务监听端口")
    parser.add_argument("--api-key", type=str, default=None, help="可选的API密钥")
    parser.add_argument("--served-model-name", type=str, default=None, help="服务模型名称,默认为模型路径名")

    args = parser.parse_args()

    # 设置引擎参数
    engine_args = AsyncEngineArgs(
        model=args.model,
        tensor_parallel_size=args.tensor_parallel_size,
        gpu_memory_utilization=0.9, # GPU内存利用率
        max_model_len=4096, # 模型最大上下文长度
        quantization="gptq", # 指定GPTQ量化
        dtype="float16",
        trust_remote_code=True, # 信任远程代码(对于Qwen模型可能需要)
    )

    # 启动服务
    run_server(
        engine_args=engine_args,
        host=args.host,
        port=args.port,
        api_key=args.api_key,
        served_model_name=args.served_model_name or os.path.basename(args.model),
    )

if __name__ == "__main__":
    main()

这个脚本做了几件事:定义命令行参数、配置vLLM引擎、最后启动一个兼容OpenAI API格式的服务。

1.2 编写Dockerfile

接下来,我们需要创建一个Docker镜像。Dockerfile定义了镜像的构建步骤。

创建一个名为 Dockerfile 的文件,内容如下:

# 使用一个包含CUDA的Python基础镜像
FROM nvcr.io/nvidia/pytorch:23.10-py3

# 设置工作目录
WORKDIR /app

# 复制模型文件和启动脚本
COPY ./qwen1.5-1.8b-chat-gptq-int4 /app/model
COPY ./start_vllm_service.py /app/

# 安装必要的Python包
# vllm版本请根据实际情况调整,确保兼容性
RUN pip install vllm==0.3.3 -i https://pypi.tuna.tsinghua.edu.cn/simple
RUN pip install fastapi uvicorn -i https://pypi.tuna.tsinghua.edu.cn/simple

# 暴露服务端口
EXPOSE 8000

# 设置容器启动命令
CMD ["python", "/app/start_vllm_service.py", "--model", "/app/model", "--host", "0.0.0.0", "--port", "8000"]

这个Dockerfile基于NVIDIA官方的PyTorch镜像,它已经包含了CUDA环境。然后我们把模型和脚本复制进去,安装vLLM等依赖,最后指定容器启动时运行的命令。

1.3 构建镜像与运行容器

现在,打开终端,进入包含 Dockerfile、模型目录和脚本的文件夹。

第一步,构建Docker镜像:

docker build -t qwen1.8b-vllm:latest .

这行命令会根据当前目录下的Dockerfile构建一个名为 qwen1.8b-vllm 的镜像。

第二步,运行Docker容器,并进行端口映射:

这是关键的一步。我们要把容器内部的8000端口,映射到宿主机的某一个端口(例如9000),这样我们才能从外面访问服务。

docker run -d \
  --name qwen1.8b-service \
  --gpus all \
  -p 9000:8000 \
  -v /path/to/your/logs:/app/logs \
  qwen1.8b-vllm:latest

解释一下参数:

  • -d:让容器在后台运行。
  • --name:给容器起个名字,方便管理。
  • --gpus all:将宿主机的所有GPU分配给容器使用(确保你的Docker已配置GPU支持)。
  • -p 9000:8000端口映射。将宿主机的9000端口映射到容器的8000端口。以后我们访问 http://你的主机IP:9000 就相当于访问了容器内的服务。
  • -v /path/to/your/logs:/app/logs:可选。将宿主机的一个目录挂载到容器内,用于持久化日志。
  • 最后是镜像名。

运行命令后,容器就启动了。你可以用 docker logs -f qwen1.8b-service 来查看实时日志,等待模型加载完成。当你看到类似 "Uvicorn running on http://0.0.0.0:8000" 的日志时,说明服务启动成功了。

2. 验证服务与使用Chainlit前端

服务跑起来了,我们怎么知道它真的在工作呢?最直接的方法就是调用一下。我们可以用简单的curl命令测试,但更直观的方法是使用一个轻量级的Web前端——Chainlit。

2.1 验证API服务

首先,用最基础的curl命令测试一下服务的健康状态和基础功能。

# 测试服务是否存活
curl http://localhost:9000/v1/models

# 发送一个简单的对话请求
curl http://localhost:9000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen1.5-1.8b-chat-gptq-int4",
    "messages": [
      {"role": "user", "content": "你好,请介绍一下你自己。"}
    ],
    "max_tokens": 100
  }'

如果第一个命令返回了模型信息,第二个命令返回了模型生成的回复,那就证明我们的vLLM API服务运行正常,并且端口映射 -p 9000:8000 生效了。

2.2 使用Chainlit创建聊天界面

命令行测试虽然有效,但不够友好。我们用一个Python脚本快速搭建一个Web界面。创建一个名为 chat_frontend.py 的文件:

import chainlit as cl
from openai import AsyncOpenAI
import asyncio

# 配置客户端,指向我们部署的vLLM服务
# 注意:这里的 base_url 就是我们的宿主机地址和映射的端口
client = AsyncOpenAI(
    base_url="http://localhost:9000/v1", # 对应 -p 9000:8000 映射
    api_key="no-api-key-required" # vLLM服务如果没有设置api-key,这里可以随意填写
)

@cl.on_message
async def main(message: cl.Message):
    """
    当用户发送消息时触发
    """
    # 创建一个消息对象来显示回复过程
    msg = cl.Message(content="")
    await msg.send()

    # 调用我们部署的模型API
    response = await client.chat.completions.create(
        model="qwen1.5-1.8b-chat-gptq-int4", # 模型名称,与启动时一致
        messages=[
            {"role": "system", "content": "你是一个乐于助人的AI助手。"},
            {"role": "user", "content": message.content}
        ],
        max_tokens=512,
        stream=True, # 启用流式输出,体验更好
    )

    # 流式接收并显示回复
    async for chunk in response:
        if chunk.choices[0].delta.content is not None:
            await msg.stream_token(chunk.choices[0].delta.content)

    # 流式传输完成
    await msg.update()

@cl.on_chat_start
async def start():
    """
    聊天会话开始时触发
    """
    await cl.Message(content="你好!我是基于通义千问1.8B模型运行的AI助手。请问有什么可以帮您?").send()

这个脚本使用Chainlit库,它内部调用了OpenAI客户端的接口。关键点在于 base_url="http://localhost:9000/v1",它告诉客户端去连接我们宿主机9000端口提供的服务,这个请求会被Docker自动转发到容器的8000端口。

2.3 启动Chainlit前端

在安装了Chainlit (pip install chainlit) 之后,运行以下命令启动前端界面:

chainlit run chat_frontend.py -w

-w 参数会自动打开你的默认浏览器,访问Chainlit的界面(通常是 http://localhost:8000,注意这是Chainlit自己的端口,不是模型服务的端口)。现在,你就可以在浏览器里和刚刚部署好的通义千问模型对话了。

3. 关键配置与问题排查

部署过程中可能会遇到一些小问题,这里总结几个关键点和排查方法。

3.1 端口冲突与映射

问题:启动容器时提示端口被占用。 解决-p 宿主机端口:容器端口 中的“宿主机端口”如果已被其他程序使用,就会冲突。你可以换一个端口,比如 -p 9001:8000

问题:容器运行了,但宿主机 localhost:9000 访问不通。 排查

  1. 确认容器状态:docker ps 查看容器是否在运行。
  2. 确认端口映射:docker port qwen1.8b-service 查看容器的端口映射情况。
  3. 检查防火墙:确保宿主机的防火墙没有阻止9000端口的访问。

3.2 GPU与显存问题

问题:容器启动失败,日志显示CUDA或GPU相关错误。 解决

  • 确保宿主机有NVIDIA GPU并安装了正确版本的驱动。
  • 确保Docker已配置NVIDIA Container Toolkit。可以运行 docker run --rm --gpus all nvidia/cuda:12.1.0-base-ubuntu22.04 nvidia-smi 测试。
  • 模型虽小,但仍需一定显存。如果显存不足,可以在 start_vllm_service.pyAsyncEngineArgs 中调整 gpu_memory_utilization(如0.8)或考虑使用 --tensor-parallel-size 1

3.3 模型加载失败

问题:日志显示模型文件找不到或加载错误。 解决

  • 检查Dockerfile中的 COPY 指令路径是否正确。
  • 确认模型文件目录结构完整,包含 config.json, model.safetensors (或 .bin) 等必要文件。
  • 对于Qwen模型,可能需要 trust_remote_code=True 参数,我们的脚本中已经设置。

4. 总结

回顾一下,我们今天完成了几件关键事情:

  1. 环境封装:通过编写Dockerfile,我们将模型、vLLM引擎和所有依赖打包进一个独立的容器,保证了环境的一致性和可移植性。
  2. 服务部署:使用vLLM启动了兼容OpenAI API的模型推理服务,这是当前高效服务LLM的流行方案。
  3. 网络打通:通过Docker的 -p 参数,实现了容器内外端口的映射,使得外部应用可以方便地访问容器内的服务。
  4. 前端验证:借助Chainlit快速搭建了一个对话式Web界面,直观地验证了整套部署流程的成功。

这种“Docker + vLLM + 端口映射”的模式非常实用。它不仅适用于通义千问1.8B这个模型,也可以作为其他类似规模LLM部署的模板。你可以轻松地更换模型路径,调整启动参数,来部署你自己感兴趣的模型。

下一步,你可以尝试:

  • 调整vLLM的生成参数(如 temperature, top_p),获得不同风格的回复。
  • 将Chainlit前端替换成更复杂的Web应用,或者集成到你的其他项目中。
  • 探索vLLM更多高级特性,如批处理推理、持续批处理等,以提升服务吞吐量。

希望这篇教程能帮你顺利踏上大模型本地部署和实践之路。动手试试,体验一下与自己部署的AI对话的乐趣吧!


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐