通义千问1.5-1.8B-Chat-GPTQ-Int4开源大模型教程:vLLM与Redis缓存协同提升响应速度

想快速部署一个能聊天的AI模型,但又担心它反应慢、资源消耗大?今天我们就来解决这个问题。

通义千问1.5-1.8B-Chat-GPTQ-Int4是一个经过量化处理的小型对话模型,虽然参数不多,但在很多场景下足够用了。不过,直接部署的话,每次用户提问都要重新计算,响应速度可能不够理想,尤其是在多人同时使用的时候。

这篇文章要分享的,就是如何用vLLM来部署这个模型,再配上Redis缓存,让它的响应速度大幅提升。简单来说,vLLM能让模型推理更高效,Redis则能把常见问题的答案存起来,下次再问同样的问题,直接给答案,不用重新算。

我会带你一步步完成部署和优化,让你得到一个既快又省资源的AI对话服务。

1. 环境准备与快速部署

我们先从最基础的开始,把模型跑起来。

1.1 你需要准备什么

在开始之前,确保你的环境满足以下要求:

  • 操作系统:Linux(推荐Ubuntu 20.04或更高版本)
  • Python版本:Python 3.8 到 3.11
  • GPU:至少8GB显存的NVIDIA GPU(比如RTX 3070或更高)
  • 内存:建议16GB以上
  • 磁盘空间:至少10GB可用空间

如果你用的是云服务器,选择带GPU的实例就行。本地的话,确保显卡驱动和CUDA已经装好。

1.2 一键部署模型服务

最省事的方法,就是使用预置的Docker镜像。这里假设你已经有了一个配置好的环境。

首先,创建一个工作目录,然后拉取并运行镜像:

# 创建工作目录
mkdir -p ~/qwen_workspace && cd ~/qwen_workspace

# 这里假设你有一个包含了vLLM和模型的Docker镜像
# 镜像启动命令可能类似这样(具体参数根据你的镜像调整):
docker run -d \
  --name qwen-vllm \
  --gpus all \
  -p 8000:8000 \
  -v $(pwd)/data:/data \
  your_image_name:tag \
  python -m vllm.entrypoints.openai.api_server \
  --model /data/models/Qwen1.5-1.8B-Chat-GPTQ-Int4 \
  --served-model-name qwen-chat \
  --host 0.0.0.0 \
  --port 8000

这个命令做了几件事:

  1. 把容器命名为 qwen-vllm
  2. 把所有GPU都分配给容器用。
  3. 把容器的8000端口映射到主机的8000端口,这样我们才能从外面访问。
  4. 把本地的 data 目录挂载到容器里的 /data,方便放模型文件。
  5. 最后是启动vLLM的API服务器,告诉它模型在哪、服务叫什么名字。

1.3 验证模型服务

容器跑起来后,怎么知道模型加载成功了呢?最直接的办法就是看日志。

用下面的命令查看容器的日志输出:

# 查看容器日志,持续输出
docker logs -f qwen-vllm

# 或者,如果你像教程里那样把日志写到了文件,可以这样看
tail -f /root/workspace/llm.log

当你看到日志里出现类似 Uvicorn running on http://0.0.0.0:8000 以及模型加载完成的提示时,就说明服务启动成功了。

为了更保险,我们可以用个简单的命令测试一下API接口是否正常:

curl http://localhost:8000/v1/models

如果返回一个JSON,里面列出了你刚部署的模型名字(比如 qwen-chat),那就万事大吉,服务已经在8000端口上等着接收请求了。

2. 用Chainlit打造聊天前端

模型服务在后台跑起来了,但我们总不能一直用命令行 curl 来聊天。一个好用的网页界面是必须的。Chainlit 就是一个专门为AI应用设计的前端框架,配置简单,界面好看。

2.1 安装并配置Chainlit

首先,确保你在另一个终端或者另一个Python环境里操作,别跟运行模型的容器搞混了。

# 安装chainlit
pip install chainlit openai

安装好后,我们需要创建一个Chainlit的应用文件,告诉它去哪里找我们的模型。

创建一个叫 app.py 的文件,内容如下:

# app.py
import chainlit as cl
from openai import OpenAI

# 配置客户端,指向我们本地运行的vLLM服务器
client = OpenAI(
    base_url="http://localhost:8000/v1", # vLLM的API地址
    api_key="no-key-required" # vLLM默认不需要key,随便填一个就行
)

@cl.on_message
async def main(message: cl.Message):
    """
    每当用户发送消息时,这个函数就会被调用。
    """
    # 创建一个消息对象,告诉用户我们正在思考
    msg = cl.Message(content="")
    await msg.send()

    # 调用我们部署的模型
    response = client.chat.completions.create(
        model="qwen-chat", # 这个名称要和vLLM启动时设置的 --served-model-name 一致
        messages=[
            {"role": "system", "content": "你是一个乐于助人的AI助手。"},
            {"role": "user", "content": message.content}
        ],
        stream=True, # 启用流式输出,一个字一个字地显示,体验更好
        max_tokens=512
    )

    # 处理流式响应
    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()

这个脚本做了什么呢?它创建了一个Web应用,当你在前端输入问题,它就把问题包装一下,发给本地 localhost:8000 的vLLM服务,拿到模型的回答后,再“流式”地显示在网页上。

2.2 启动前端并开始聊天

配置好之后,启动Chainlit服务:

# 在 app.py 所在的目录下运行
chainlit run app.py

运行成功后,它会告诉你一个本地地址,通常是 http://localhost:8000(注意,这里可能和vLLM的端口冲突,如果冲突,Chainlit会自动换一个,比如8080)。用浏览器打开这个地址,你就能看到一个简洁的聊天界面了。

在输入框里试试问点问题,比如“你好,介绍一下你自己”。如果一切正常,你应该能看到模型思考的痕迹(流式输出的效果),然后得到一段完整的回答。

3. 引入Redis缓存,让响应飞起来

现在模型能跑了,前端也有了,但每次问问题,哪怕是一模一样的问题,模型都要重新推理一遍。这对于一些常见、固定的问题(比如“你们公司的客服电话是多少?”)来说,非常浪费资源,而且响应速度受限于模型的推理时间。

这时候,缓存就该上场了。Redis是一个内存数据库,读写速度极快,非常适合做缓存。我们的思路是:用户提问时,先看看Redis里有没有缓存过这个问题的答案,有就直接返回,没有再去调模型,然后把答案存到Redis里。

3.1 部署Redis服务

同样,用Docker部署Redis最方便:

docker run -d \
  --name redis-cache \
  -p 6379:6379 \
  redis:alpine

这条命令启动了一个Redis容器,并把它的6379端口映射到了主机。

3.2 改造后端服务:集成缓存逻辑

我们需要修改vLLM的API服务吗?其实有更优雅的办法。我们可以在vLLM前面加一个“中间层”,由这个中间层来处理缓存逻辑。这里我们用简单的FastAPI来实现。

创建一个新的文件 cached_api.py

# cached_api.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import redis
import json
import hashlib
from openai import OpenAI
import asyncio

app = FastAPI(title="Cached Qwen Chat API")

# 连接Redis和vLLM后端
redis_client = redis.Redis(host='localhost', port=6379, decode_responses=True)
vllm_client = OpenAI(base_url="http://localhost:8000/v1", api_key="no-key")

# 定义请求和响应的数据结构
class ChatRequest(BaseModel):
    model: str = "qwen-chat"
    messages: list
    max_tokens: int = 512

class ChatResponse(BaseModel):
    id: str
    object: str = "chat.completion"
    choices: list
    usage: dict

def generate_cache_key(messages: list) -> str:
    """
    根据对话消息生成一个唯一的缓存键。
    简单起见,这里把整个消息列表序列化成字符串再取哈希。
    """
    messages_str = json.dumps(messages, sort_keys=True, ensure_ascii=False)
    return f"qwen_cache:{hashlib.md5(messages_str.encode()).hexdigest()}"

@app.post("/v1/chat/completions")
async def create_chat_completion(request: ChatRequest):
    # 1. 生成缓存键
    cache_key = generate_cache_key(request.messages)

    # 2. 尝试从Redis获取缓存
    cached_response = redis_client.get(cache_key)
    if cached_response:
        print(f"缓存命中: {cache_key}")
        return json.loads(cached_response)

    print(f"缓存未命中,调用模型: {cache_key}")

    # 3. 调用原始的vLLM服务
    try:
        response = vllm_client.chat.completions.create(
            model=request.model,
            messages=request.messages,
            max_tokens=request.max_tokens
        )
        # 将响应转换为可序列化的字典
        response_dict = response.model_dump()
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"模型服务调用失败: {str(e)}")

    # 4. 将响应存入Redis,设置过期时间(例如1小时)
    redis_client.setex(cache_key, 3600, json.dumps(response_dict))

    return response_dict

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8001)

这个FastAPI应用启动在8001端口。它接收和vLLM原版API一样的请求。收到请求后,它先根据用户的问题(messages)算出一个唯一的键,然后去Redis里找。找到了就直接返回,找不到才去调用真正的vLLM服务(8000端口),拿到结果后存到Redis,再返回给用户。

3.3 修改前端连接地址

现在,我们的Chainlit前端不应该直接连vLLM(8000端口)了,而应该连我们这个带缓存的中间层(8001端口)。

修改之前的 app.py 文件,把 base_url 改一下:

# 修改 app.py 中的客户端配置
client = OpenAI(
    base_url="http://localhost:8001/v1", # 指向我们新的缓存中间层
    api_key="no-key-required"
)

然后重启Chainlit服务。

3.4 体验缓存带来的速度提升

现在,整个流程是这样的:

  1. 用户在Chainlit界面提问。
  2. 请求发送到 localhost:8001 的缓存中间层。
  3. 中间层检查Redis。
    • 如果命中缓存:毫秒级返回答案,速度极快。
    • 如果未命中缓存:转发请求给 localhost:8000 的vLLM,等模型推理完,把结果存到Redis,再返回。
  4. 用户看到答案。

你可以测试一下:第一次问“中国的首都是哪里?”,会有一个正常的模型推理等待时间。紧接着再问一次完全相同的问题,你会发现响应几乎是瞬间完成的,这就是缓存生效了!

4. 总结与进阶思考

通过上面的步骤,我们成功搭建了一个基于通义千问1.5-1.8B-Chat-GPTQ-Int4模型、vLLM推理引擎、Redis缓存和Chainlit前端的完整对话系统。这个组合带来几个明显的好处:

1. 部署简单高效:vLLM针对大模型推理做了深度优化,比直接用原始的PyTorch加载模型要快得多,也省内存。Docker化部署让环境问题一扫而空。

2. 响应速度质的飞跃:对于重复性问题,Redis缓存能将响应时间从秒级降低到毫秒级,用户体验提升巨大。这对于构建知识库问答、标准客服场景非常有用。

3. 资源利用率提高:缓存避免了不必要的GPU计算,在并发请求时,能显著降低后端模型服务的压力,让有限的GPU资源服务于更多真正需要推理的新请求。

你可以进一步探索的方向

  • 缓存策略优化:现在的缓存键是基于整个对话历史的。你可以设计更精细的策略,比如只缓存系统提示词+用户最后一条消息的组合,或者为不同的用户设置不同的缓存空间。
  • 缓存内容管理:给缓存设置合适的过期时间(TTL),或者使用LRU(最近最少使用)策略自动淘汰旧缓存,防止Redis内存被占满。
  • 架构扩展:如果用户量很大,可以考虑将FastAPI中间层和Redis也部署成集群,并引入负载均衡。甚至可以将这个缓存服务抽象出来,服务于多个不同的模型后端。
  • 监控与告警:加入日志监控,记录缓存命中率、模型响应时间等指标,能帮你更好地了解系统性能和优化空间。

这个方案的核心思想——高效推理引擎 + 智能缓存——不仅适用于通义千问,也适用于其他开源或闭源的大模型。希望这个教程能帮你快速搭建起一个既快又稳的AI应用原型。


获取更多AI镜像

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

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐