Skip to content

Sonicwanjie/Qwen-TensorRT-LLM

 
 

Repository files navigation

总述

背景介绍

  • 介绍本工作是 NVIDIA TensorRT Hackathon 2023 的参赛题目,本项目使用TRT-LLM完成对Qwen-7B-Chat实现推理加速。相关代码已经放在release/0.1.0分支,感兴趣的同学可以去该分支学习完整流程。
  • 本项目release/0.5.0分支和TensorRT-LLM官方仓库release/0.5.0分支对齐,所有功能均在该分支上面进行测试。
  • main分支目前和TensorRT-LLM官方仓库v0.6.1对齐,该版本已经支持Qwen,但是可能支持的功能特性还有不足,故我们决定继续更新该仓库。
  • 最新triton容器23.11还未完整支持tensorrt-llm 0.6.1,需要用triton的建议先用本项目的release/0.5.0分支。

功能概述

  • FP16 / BF16(实验性)
  • INT8 Weight-Only & INT8 Smooth Quant & INT4 Weight-Only & INT4-AWQ & INT4-GPTQ
  • INT8 KV CACHE
  • Tensor Parallel(多卡并行)
  • 基于gradio搭建web demo
  • 支持triton部署api,结合inflight_batching实现最大吞吐/并发。
  • 支持fastapi搭建兼容openai请求的api,并且支持function call调用。
  • 支持cli命令行对话。
  • 支持langchain接入。

支持的模型

相关教程:

软硬件要求

  • Linux最佳,已安装docker,并且安装了nvidia-docker(安装指南),Windows理论也可以,但是还未测试,感兴趣可以自己研究一下。
  • 有英伟达显卡(30系,40系,V100/A100等),以及一定的显存、内存、磁盘。结合Qwen官方推理要求,预估出下面的要求,详见表格(仅编译期最大要求),仅供参考:
Model Size Quantization GPU Memory Usage (GB) CPU Memory Usage (GB) Disk Usage (GB)
1.8B fp16 5 15 11
int8 smooth quant 5 15 22
int8 weight only 4 12 9
int4 weight only 4 10 7
int4 gptq (raw) 4 10 6
int4 gptq (manual) 5 13 14
int4 awq 5 13 18
7B fp16 21 59 42
int8 smooth quant 21 59 84
int8 weight only 14 39 28
int4 weight only 10 29 21
int4 gptq (raw) 10 29 16
int4 gptq (manual) 21 51 42
int4 awq 21 51 56
14B fp16 38 106 75
int8 smooth quant 38 106 150
int8 weight only 24 66 47
int4 weight only 16 46 33
int4 gptq (raw) 16 46 26
int4 gptq (manual) 38 90 66
int4 awq 38 90 94
72B fp16 181 506 362
int8 smooth quant 181 506 724
int8 weight only 102 284 203
int4 weight only 61 171 122
int4 gptq (raw) 61 171 98
int4 gptq (manual) 181 434 244
int4 awq 181 434 406

运行指南

准备工作

  1. 由于TensorRT-LLM 还未发布0.6.1 docker镜像,需要自己编译docker镜像,可参考该文档,注意:一定要从0.6.1分支开始编译,否则可能会存在不兼容。如果官方后续有发布对应镜像(一般为Triton镜像),可以参考之前的文档进行部署,参考链接

    • 这里提供一个编译好的TensorRT-LLM镜像(不含triton),版本为0.6.1,理论上支持Compute Capability为7.0/8.0/8.6/8.9/9.0的显卡,不确定自己Compute Capability的,可以去官网https://developer.nvidia.com/cuda-gpus查询,使用下面的代码拉取镜像,并且重命名一下。

      docker pull registry.cn-guangzhou.aliyuncs.com/tlntin/tensorrt_llm:v0.6.1
      docker tag registry.cn-guangzhou.aliyuncs.com/tlntin/tensorrt_llm:v0.6.1 tensorrt_llm/release
    • AutoDL镜像,同样不含triton,版本为0.6.1,无卡用户可以体验玩玩,链接

  2. 拉取本项目代码

    git clone https://github.com/Tlntin/Qwen-TensorRT-LLM.git
    cd Qwen-TensorRT-LLM
  3. 进入项目目录,然后创建并启动容器,同时将本地qwen代码路径映射到/app/tensorrt_llm/examples/qwen路径,然后打开8000和7860端口的映射,方便调试api和web界面。

    docker run --gpus all \
      --name trt_llm \
      -d \
      --ipc=host \
      --ulimit memlock=-1 \
      --restart=always \
      --ulimit stack=67108864 \
      -p 8000:8000 \
      -p 7860:7860 \
      -v ${PWD}/examples/qwen:/app/tensorrt_llm/examples/qwen \
      tensorrt_llm/release sleep 8640000
  4. 进入docker容器里面的qwen路径,安装提供的Python依赖

    cd /app/tensorrt_llm/examples/qwen/
    pip install -r requirements.txt
  5. 下载模型,例如QWen-7B-Chat模型,然后将文件夹重命名为qwen_7b_chat,最后放到qwen/路径下即可。

  6. 修改编译参数(可选)

    • 默认编译参数,包括batch_size, max_input_len, max_new_tokens, seq_length都存放在default_config.py
    • 默认模型路径,包括hf_model_dir(模型路径)和tokenizer_dir(分词器路径)以及int4_gptq_model_dir(手动gptq量化输出路径),可以改成你自定义的路径。
    • 对于24G显存用户,直接编译即可,默认是fp16数据类型,max_batch_size=2
    • 对于低显存用户,可以降低max_batch_size=1,或者继续降低max_input_len, max_new_tokens
    • 默认的seq_lenght是2048,有的模型是8192有的是2048,一般看config.json里面这个参数对应的数值是啥,如果没改对后面会警告或者报错提醒一下(准备加入这个功能)。

运行指南(fp16模型)

  1. 编译。

    • 编译fp16(注:--remove_input_padding--enable_context_fmha为可选参数,可以一定程度上节省显存)。
    python3 build.py --remove_input_padding --enable_context_fmha
    • 编译 int8 (weight only)。
    python3 build.py --use_weight_only --weight_only_precision=int8
    • 编译int4 (weight only)
    python3 build.py --use_weight_only --weight_only_precision=int4
    • 对于如果单卡装不下,又不想用int4/int8量化,可以选择尝试tp = 2,即启用两张GPU进行编译 (注:tp功能目前只支持从Huggingface格式构建engine)
    python3 build.py --world_size 2 --tp_size 2
  2. 运行。编译完后,再试跑一下,输出Output: "您好,我是来自达摩院的大规模语言模型,我叫通义千问。<|im_end|>"这说明成功。

    • tp = 1(默认单GPU)时使用python直接运行run.py
    python3 run.py
    • tp = 2(2卡用户,或者更多GPU卡)时,使用mpirun命令来运行run.py
    mpirun -n 2 --allow-run-as-root python run.py
  3. 验证模型精度。可以试试跑一下summarize.py,对比一下huggingface和trt-llm的rouge得分。对于网络不好的用户,可以从网盘下载数据集,然后按照使用说明操作即可。

    python3 summarize.py --backend=hf
    • 跑trt-llm版
    python3 summarize.py --backend=trt_llm
    • 注:如果用了网盘的数据集,解压后加载就需要多两个环境变量了,运行示范如下:
    HF_DATASETS_OFFLINE=1 TRANSFORMERS_OFFLINE=1 python3 summarize.py --backend=hf
    或者
    HF_DATASETS_OFFLINE=1 TRANSFORMERS_OFFLINE=1 python3 summarize.py --backend=trt_llm
    • 一般来说,如果trt-llm的rouge分数和huggingface差不多,略低一些(1以内)或者略高一些(2以内),则说明精度基本对齐。
  4. 测量模型吞吐速度和生成速度。需要下载ShareGPT_V3_unfiltered_cleaned_split.json这个文件。

    • 可以通过wget/浏览器直接下载,下载链接
    • 也可通过百度网盘下载,链接: https://pan.baidu.com/s/12rot0Lc0hc9oCb7GxBS6Ng?pwd=jps5 提取码: jps5
    • 下载后同样放到examples/qwen/路径下即可
    • 测量前,如果需要改max_input_length/max_new_tokens,可以直接改default_config.py即可。一般不推荐修改,如果修改了这个,则需要重新编译一次trt-llm,保证两者输入数据集长度统一。
    • 测量huggingface模型
    python3 benchmark.py --backend=hf --dataset=ShareGPT_V3_unfiltered_cleaned_split.json --hf_max_batch_size=1
    • 测量trt-llm模型 (注意:--trt_max_batch_size不应该超过build时候定义的最大batch_size,否则会出现内存错误。)
    python3 benchmark.py --backend=trt_llm --dataset=ShareGPT_V3_unfiltered_cleaned_split.json --trt_max_batch_size=1

运行指南(Smooth Quant篇)

  1. 注意:运行Smooth Quant需要将huggingface模型完全加载到GPU里面,用于构建int8标定数据集,所以需要提前确保你的显存够大,能够完全加载整个模型。

  2. 将Huggingface格式的数据转成FT(FastTransformer)需要的数据格式

    python3 hf_qwen_convert.py --smoothquant=0.5
  3. 开始编译trt_engine

    • 普通版
    python3 build.py --use_smooth_quant
    • 升级版(理论上运行速度更快,推理效果更好,强烈推荐)
    python3 build.py --use_smooth_quant --per_token --per_channel
  4. 编译完成,run/summarize/benchmark等等都和上面的是一样的了。

运行指南(int8-kv-cache篇)

  1. 注意:运行int8-kv-cache需要将huggingface模型完全加载到GPU里面,用于构建int8标定数据集,所以需要提前确保你的显存够大,能够完全加载整个模型。

  2. 将Huggingface格式的数据转成FT(FastTransformer)需要的数据格式。

python3 hf_qwen_convert.py --calibrate-kv-cache
  1. 编译int8 weight only + int8-kv-cache
python3 build.py --use_weight_only --weight_only_precision=int8 --int8_kv_cache

运行指南(int4-gptq篇)

  1. 需要安装auto-gptq模块,并且升级transformers模块版本,最低要求4.32.0。(注:安装完模块后可能会提示tensorrt_llm与其他模块版本不兼容,可以忽略该警告)
pip install auto-gptq optimum
  1. 手动获取标定权重(可选)
  • 转权重获取scale相关信息,默认使用GPU进行校准,需要能够完整加载模型。(注:对于Qwen-7B-Chat V1.0,可以加上--device=cpu来尝试用cpu标定,但是时间会很长)
python3 gptq_convert.py
  • 编译TensorRT-LLM Engine
python build.py --use_weight_only \
                --weight_only_precision int4_gptq \
                --per_group
  • 如果想要节省显存(注:只能用于单batch),可以试试加上这俩参数来编译Engine
python build.py --use_weight_only \
                --weight_only_precision int4_gptq \
                --per_group \
                --remove_input_padding \
                --enable_context_fmha
  1. 使用官方int4权重,例如Qwen-xx-Chat-Int4模型(推荐)
  • 编译模型,注意设置hf模型路径和--quant_ckpt_path量化后权重路径均设置为同一个路径,下面是1.8b模型的示例(其他模型也是一样操作)
python build.py --use_weight_only \
                --weight_only_precision int4_gptq \
                --per_group \
                --hf_model_dir Qwen-1_8B-Chat-Int4 \
                --quant_ckpt_path Qwen-1_8B-Chat-Int4
  • 运行模型,这里需要指定一下tokenizer路径
python3 run.py --tokenizer_dir=Qwen-1_8B-Chat-Int4

运行指南(int4-awq篇)

  1. 需要下载并安装nvidia-ammo模块,下面是一个安装代码参考,注意不要安装cuda版,而是安装通用版,否则会有bug。
pip install nvidia_ammo-0.3.0-cp310-cp310-linux_x86_64.whl
  1. 修改ammo代码,加上qwen支持(不加上会报错),下面是一个简单的参考案例:
  • 先在vscode,任意写一个python文件,导入下面的函数
from tensorrt_llm.models.quantized.ammo import quantize_and_export
  • 然后contrl + 鼠标左按键,单击quantize_and_export函数,查看它的内部实现。
  • model_lookup中,加上下面这段代码,用来支持Qwen
    ("qwen", ): "qwen",
  • 修改后长这样:
model_lookup = {
    ("llama", "mistral"): "llama",
    ("gptj", ): "gptj",
    ("falcon", "rw"): "falcon",
    ("baichuan", ): "baichuan",
    ("mpt", ): "mpt",
    ("gpt2", ): "gpt2",
    ("chatglm", ): "chatglm",
    ("qwen", ): "qwen",
}
  • before
if export_path:
    with torch.inference_mode():
        export_model_config(
            model,
            model_type,
            torch.float16,
            export_dir=export_path,
            inference_tensor_parallel=tensor_parallel_size,
        )
    logger.info(f"Quantized model exported to :{export_path}")
  • after
if export_path:
    with torch.inference_mode():
        if qformat == "int4_awq" and model_type == "qwen":
            torch.save(model.state_dict(), export_path)
        else:
            export_model_config(
                model,
                model_type,
                torch.float16,
                quantization=qformat,
                export_dir=export_path,
                inference_tensor_parallel=tensor_parallel_size,
            )
    logger.info(f"Quantized model exported to :{export_path}")
  1. 运行int4-awq量化代码,导出校准权重。
python3 quantize.py --export_path ./qwen_7b_4bit_gs128_awq.pt
  1. 运行build.py,用于构建TensorRT-LLM Engine。
python build.py --use_weight_only \
                --weight_only_precision int4_awq \
                --per_group \
                --quant_ckpt_path ./qwen_7b_4bit_gs128_awq.pt
  1. 如果想要节省显存(注:只能用于单batch),可以试试加上这俩参数来编译Engine
python build.py --use_weight_only \
                --weight_only_precision int4_awq \
                --per_group \
                --remove_input_padding \
                --enable_context_fmha \
                --quant_ckpt_path ./qwen_7b_4bit_gs128_awq.pt

其他应用

  1. 尝试终端对话。运行下面的命令,然后输入你的问题,直接回车即可。

    python3 cli_chat.py
  2. 部署api,并调用api进行对话。

    • 部署api
    python3 api.py
    • 另开一个终端,进入qwen/client目录,里面有4个文件,分别代表不同的调用方式。
    • async_client.py,通过异步的方式调用api,通过SSE协议来支持流式输出。
    • normal_client.py,通过同步的方式调用api,为常规的HTTP协议,Post请求,不支持流式输出,请求一次需要等模型生成完所有文字后,才能返回。
    • openai_normal_client.py,通过openai模块直接调用自己部署的api,该示例为非流式调用,请求一次需要等模型生成完所有文字后,才能返回。。
    • openai_stream_client.py,通过openai模块直接调用自己部署的api,该示例为流式调用。
    • 注意:需要pydantic模块版本>=2.3.2,否则将会出现ChatCompletionResponse' object has no attribute 'model_dump_json'报错,参考issue
  3. 尝试网页对话(可选,需要先部署api)。运行下面的命令,然后打开本地浏览器,访问:http://127.0.0.1:7860 即可

    python3 web_demo.py
    • 默认配置的web_demo.py如下:
    demo.queue().launch(share=False, inbrowser=True)
    • 如果是服务器运行,建议改成这样
    demo.queue().launch(server_name="0.0.0.0", share=False, inbrowser=False) 
    • web_demo参数说明
      • share=True: 代表将网站穿透到公网,会自动用一个随机的临时公网域名,有效期3天,不过这个选项可能不太安全,有可能造成服务器被攻击,不建议打开。
      • inbrowser=True: 部署服务后,自动打开浏览器,如果是本机,可以打开。如果是服务器,不建议打开,因为服务器也没有谷歌浏览器给你打开。
      • server_name="0.0.0.0": 允许任意ip访问,适合服务器,然后你只需要输入http://[你的ip]: 7860就能看到网页了,如果不开这个选择,默认只能部署的那台机器才能访问。
      • share=False:仅局域网/或者公网ip访问,不会生成公网域名。
      • inbrowser=False: 部署后不打开浏览器,适合服务器。
  4. web_demo运行效果(测试平台:RTX 4080, qwen-7b-chat, int4 weight only)

TRT-LLM.for.Qwen-7B.mp4

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 100.0%