【万字真言】如何提升大模型抽取结构化信息的速度

目录

一、问题和需求

二、部署量化模型

2.1 使用ollama部署

2.1.1 ollama部署的代码

2.1.2 测试ollama部署的gguf模型的推理速度

2.2 使用vllm部署量化模型

2.2.1 获取量化版本模型

2.2.2 安装VLLM

2.2.3 部署模型

2.3 测试三个模型

三、为什么4位量化模型速度还比FP16更慢

3.1 查看上面两个模型的量化设置

3.2 查询设备和对应支持模型

四、尝试不同的框架

4.1 llama.cpp源码构建项目

4.2 下载gguf模型

4.3 启动模型

4.4 GPU未识别如何解决

4.5 测试模型服务

五、结论

5.1 模型抽取json信息慢的核心原因

5.2 无关因素

六、参考文章


一、问题和需求

我们在利用qwen3-4B正常的bfloat16模型做信息抽取的过程中,速度很慢,需要40s。经过测试发现,要让模型进行较好的,稳定的json输出信息,pydantic模型是不能缺少的。

我得出暂时的结论,整个抽取信息的速度主要取决两个因素:

1. pydantic模型总体的量。

2. 模型的”聪明程度”,越聪明的模型,想的越多,输出越慢。

具体的测试可以看我之前的博客:

Langchain如何让大模型结构化输出指定的字段信息-CSDN博客

如何把整个信息流程提速?先做到可以用,再做到好用。

提升模型抽取信息的速度的思路主要有三个:

1.参数量不变,部署量化版本的模型。如:qwen3-4B-bfloat4。

2.把pydantic模型简化成两个部分,做到并发调用模型,然后拼接json信息。

3.使用程序化的代码做预处理:先用正则表达式或规则程序抽取能抽取的信息,再把不能抽取的信息给大模型处理,减轻模型的任务量。

4. 部署参数量更小,但是量化精度不要太低的模型,尝试写不同的提示词,抛弃pydantic模型校验输出,得到速度更快的输出。

二、部署量化模型

2.1 使用ollama部署

2.1.1 ollama部署的代码

本身使用ollama部署的模型都是GGUF的模型,比较简单。模型的详细信息在下面网站中。

qwen3:4b/model

ollama run qwen3:4b

使用代码调用ollama模型服务:



from langchain_ollama import ChatOllama
from langchain_openai import ChatOpenAI
def get_ollama_llm(MODEL_PATH:str,MODEL_URL:str, temperature:Optional[float] = 0.1):
    '''通过ollama调用llm,返回langchain的llm对象'''
    # 方法一:MODEL_URL="http://localhost:11434"
    # ollama_llm = ChatOllama(
    #     model=MODEL_PATH,
    #     base_url=MODEL_URL,  # Ollama服务地址
    #     temperature=temperature,
    #     extra_body={
    #     "top_k": 20, 
    #     "chat_template_kwargs": {"enable_thinking": False},
    #     },    
    # )
    # 方法二:MODEL_URL="http://localhost:11434/v1"
    ollama_llm = ChatOpenAI(
        streaming=True,
        openai_api_base=MODEL_URL,  # VLLM 服务地址
        model_name=MODEL_PATH,
        temperature=temperature,
        # max_tokens=max_tokens,
        openai_api_key="EMPTY",  # 本地部署不需要 API key,但需要设置一个非空值
        extra_body={
        "top_k": 20, 
        "chat_template_kwargs": {"enable_thinking": False},
        }, 
    )
 
    return ollama_llm
if __name__ == "__main__":
    text = "讲个笑话"
 
    llm = get_ollama_llm(MODEL_PATH="qwen3:4b",MODEL_URL="http://localhost:11434/v1")
    # llm = get_api_llm()
 
    # 非思考模式 prompt后面加上一个/no_think
    # logger.info(llm.invoke(f"{text} /no_think")) # 直接调用
    # print(llm.invoke(text).content)
 
    # 简单的控制台流式输出调试
    for chunk in llm.stream(f"{text}"):  # 同步流式方法
        print(chunk.content, end="", flush=True)  # 无需异步环境

但是非常可惜,我使用了很多方法来让模型不思考,直接输出,模型都还是会思考输出。

尝试了下面的方法:

1.运行模型的时候,ollama run qwen3:4b /no_think 

2. 调用模型的时候提供如代码所示的参数和,提示词中写 /no_think 

3. 重新构建qwen3-4B.modelfile,里面的模版中给定no_think

4. 使用之前的通过VLLM部署模型的qwen3_nonthinking.jinja文件夹的内容。

如果读者有解决方法,可以评论区留意讨论。

2.1.2 测试ollama部署的gguf模型的推理速度

# 启用100%GPU来跑模型

export OLLAMA_USE_GPU=1

# 显示模型推理速度详情

ollama run qwen3:4b –verbose

2.2 使用vllm部署量化模型

我之前是有用过vllm部署qwen3-4B-bfloat16非量化版本的模型。教程如下,可以参考一下环境安装。

超详细VLLM框架部署qwen3-4B加混合推理探索!!!_vllm qwen3-CSDN博客

2.2.1 获取量化版本模型

模型选择一:动态量化模型,支持思考和非思考模式

Qwen3-4B-unsloth-bnb-4bit · 模型库

模型选择二:普通量化模型,支持思考和非思考模式

Qwen3-4B-bnb-4bit · 模型库

模型选择三:普通量化模型,仅支持非思考模式

Qwen3-4B-Instruct-2507-bnb-4bit · 模型库

模型选择四:普通量化模型,仅支持思考模式

Qwen3-4B-Thinking-2507-unsloth-bnb-4bit · 模型库

上述模型,可以按照自己的需求选择下载。

动态量化模型和普通的量化模型的区别如下:

场景

推荐配置

理由

移动端/低显存设备

模型二

显存占用更小,满足基础问答、摘要等需求

数学/代码/长文本推理

模型一

保留关键层精度,减少量化误差

工具调用(MCP)

模型一

保障函数解析准确性,避免工具调用失败

注:两者均使用 ​​NF4量化+双量化(Double Quant)​​,核心量化技术一致

可以理解成动态量化模型,并不是把全部的层都量化了,还保留了部分bfloat16精度的层。

以模型一下载为例子:

 # 下载modelscope

pip install modelscope

modelscope download –model unsloth/Qwen3-4B-unsloth-bnb-4bit –local_dir /root/model/Qwen3-4B-unsloth-bnb-4bit

2.2.2 安装VLLM

conda create -n vllmtest python=3.12 -y

conda activate vllmtest

# 下载vllm

pip install –upgrade vllm 

pip install “vllm>=0.8.5” -i https://mirrors.aliyun.com/pypi/simple/

PS: 如果之前有成功安装过VLLM包的虚拟环境,可以用克隆到新的虚拟环境,这样后续操作就不会把原来可以用的环境搞的不能用

conda create -n vllmtest –clone vllm

下载bitsandbytes包,bitsandbytes是为了适配4bit动态量化模型调用的库

pip install bitsandbytes>=0.45.3
pip install –upgrade vllm

注,目前最新版vLLM已支持Unsloth动态量化模型,目前Unsloth团队已完成dense模型优化,MoE模型兼容vLLM版目前还未上线。即目前vLLM只支持unsloth/Qwen3-1.7B-unsloth-bnb-4bit、nsloth/Qwen3-4B-unsloth-bnb-4bit、unsloth/Qwen3-8B-unsloth-bnb-4bit、unsloth/Qwen3-14B-unsloth-bnb-4bit、unsloth/Qwen3-32B-unsloth-bnb-4bit四款模型。
下载的版本信息如下:

2.2.3 部署模型

vLLM – Qwen

上述官网教程中,按图点击蓝色字体,会自动下载一个chat模版

vllm serve /root/model/Qwen3-4B-unsloth-bnb-4bit –max-model-len 15000 –gpu-memory-utilization 0.5 –chat-template /root/model/qwen3_nonthinking.jinja –host 0.0.0.0 –port 8000 –served-model-name Qwen3-4B

这样启动模型,上述是常见的配置。

模型加载仅3.36G显存,给6G显存就够用了。

2.3 测试三个模型

下述测试的提示词,任务都是一样的。仅模型本身不一样。

启动的命令

# 16bit

vllm serve /root/model/Qwen3-4B –max-model-len 5000 –gpu-memory-utilization 0.85 –chat-template /root/model/Qwen3-4B/qwen3_nonthinking.jinja –host 0.0.0.0 –port 8000 –served-model-name Qwen3-4B

# 4bit仅支持非思考

vllm serve /root/model/Qwen3-4B-Instruct-2507-bnb-4bit –max-model-len 5000 –gpu-memory-utilization 0.85 –host 0.0.0.0 –port 8000 –served-model-name Qwen3-4B

# 4bit混合量化

vllm serve /root/model/Qwen3-4B-unsloth-bnb-4bit –max-model-len 5000 –gpu-memory-utilization 0.85 –chat-template /root/model/Qwen3-4B/qwen3_nonthinking.jinja –host 0.0.0.0 –port 8000 –served-model-name Qwen3-4B

模型一:qwen3-4B-NF4

单请求

耗时: 50.01秒,信息抽取效果好

模型二:qwen3-4B-NF4混合版

单请求:

耗时: 65.36秒,信息抽取效果差,会自己编造数据。

模型三:qwen3-4B-FP16

单请求:

耗时: 44.92秒,信息抽取效果好

三、为什么4位量化模型速度还比FP16更慢

3.1 查看上面两个模型的量化设置

“quantization_config”: {
  “load_in_4bit”: true,               // 启用4位量化
  “quant_method”: “bitsandbytes”,     // 量化工具库(BitsandBytes)
  “bnb_4bit_quant_type”: “nf4”,        // 量化类型:NF4(正态分布优化)
  “bnb_4bit_use_double_quant”: true,   // 启用双重量化(二次压缩元数据)
  “bnb_4bit_compute_dtype”: “bfloat16” // 计算时反量化为bfloat16精度

   “bnb_4bit_quant_storage”: “uint8”    // 实际存储为​​4位压缩格式​​,但以uint8数组封装
}

这样可以知道,这两个bnb-4bit模型,实际存储是uint4,但是以unit8数组封装存储。这样可以降低模型大小和显存资源。运算的时候先把nf4反向计算成bfloat16,再以bfloat16来进行计算。因此速度会比直接运行bfloat16的模型qwen3-4B更慢。

总结,bnb4位量化模型能够减小资源开销,但是会略微降低计算速度,因为计算的时候要多进行一步。

3.2 查询设备和对应支持模型

输入下面命令可以查询设备软硬件情况

nvidia-smi -q

比如我的设备是T4,架构是Turing。然后去查询支持哪些运算。

架构

计算能力

INT8加速

INT4加速

FP8加速

Turing

7.5

❌(软件模拟)

Ampere

8.0+

Turing 架构的GPU支持 FP16 和 INT8 计算,int4类型可能需要推理框架兼容。

但是我发现个很奇怪的现象。通过Ollama部署的GGUF类型的qwen3-4B也是int4。也支持跑运行。

四、尝试不同的框架

4.1 llama.cpp源码构建项目

使用包安装llama.cpp


cc --version
 

下载 cmake包

sudo apt update && sudo apt install build-essential cmake

克隆仓库并进入目录:

git clone https://github.com/ggml-org/llama.cpp
cd llama.cpp

然后使用 CMake 构建 llama.cpp:

cmake -B build
cmake --build build --config Release

如果报错,是因为网络不能连外网的问题。

就设置下面的命令,这样就不会用CURL自动下载模型,需要自己手动下载模型。

cmake -B build -DCMAKE_BUILD_TYPE=Release -DLLAMA_CURL=OFF

然后根据自己设备情况,构建项目,8核心CPU一起构建。

cmake –build build –config Release -j 8

这一步的目的是一会会出现一个build目录,在里面可以执行GPU支持的命令。

判断是否构建成功

./build/bin/llama-server –version

出现一个cuda yes就属于识别到了GPU,后续也可以根据启动服务,查看显存是否有消耗和模型回答速度也可以知道有没有启动GPU推理。

4.2 下载gguf模型

Qwen3-4B-Instruct-2507-GGUF · 模型库

模型名称

大小

比特数

特点

适用场景

​Q4_K_M​

~2.60GB

4-bit

​强烈推荐!​​ 精度和速度的最佳平衡点

​绝大多数用户的首选​​,通用任务、聊天、编程

​Q4_K_S​

~2.38GB

4-bit

比K_M体积稍小,精度稍低

显存稍微紧张时的备选

​Q5_K_M​

~2.89GB

5-bit

比Q4精度更高,体积稍大

对输出质量要求更高的场景

​Q3_K_M​

~2.08GB

3-bit

体积小,速度快,精度损失明显

显存有限(如4-6G),追求速度

​IQ4_XS​

​1.67GB​

4-bit(智能)

​体积最小的实用之选​

​显存极度紧张(4G以下)的保底选择​

​Q6_K​

~3.31GB

6-bit

精度非常高,接近原始模型

非常注重精度,且显存充足(8G+)

​F16​

​8.05GB​

16-bit

​原始无损精度​

​研究用途​​,需要绝对精确的实验结果

下载ggfu文件到本地

modelscope download –model unsloth/Qwen3-4B-Instruct-2507-GGUF  Qwen3-4B-Instruct-2507-Q4_K_M.gguf –local_dir /root/model/Qwen3-4B-Instruct-2507-Q4_K_M.gguf

4.3 启动模型

参数总结速查表

./llama-cli –help

./llama-server –help

常见的

​类别​

​参数​

​作用​

​推荐值​

​模型加载​


-hf、
-m

从 Hugging Face 加载模型、从本地加载模型


Qwen/Qwen3-8B-GGUF:Q8_0


--jinja

启用 Jinja 模板引擎

必选

​GPU 加速​


-ngl

GPU 卸载层数

把模型的多少层给GPU处理(需高显存)


-fa

启用 FlashAttention 加速

推荐启用


-sm

多 GPU 拆分模式


row

​采样控制​


--temp

温度(输出随机性)


0.6
(低随机)


--top-k

Top-K 采样


20


--top-p

Top-P(核心)采样


0.95


--min-p

最小概率过滤


0
(禁用)

​上下文管理​


-c

上下文长度


40960
(长文本)


-n

最大生成长度


32768


--no-context-shift

禁用上下文滚动

长对话必选

​推理优化​


--reasoning-format

思维链格式


deepseek

这里可以看到模型总层数是36 

命令行启动

./llama-cli -m /root/model/Qwen3-4B-Instruct-2507-Q4_K_M.gguf/Qwen3-4B-Instruct-2507-Q4_K_M.gguf –jinja –color -ngl 36 -c 5000 –temp 0.5 –top-p 0.9

API服务启动命令

./llama-server -m /root/model/Qwen3-4B-Instruct-2507-Q4_K_M.gguf/Qwen3-4B-Instruct-2507-Q4_K_M.gguf –jinja –reasoning-format deepseek -ngl 99 -fa -sm row –temp 0.6 –top-k 20 –top-p 0.95 –min-p 0 -c 10000 -n 10000 –no-context-shift –port 8002

参数​

​缩写​

​推荐值​

​作用​


--gpu-layers


-ngl


50

​GPU 卸载层数​​:T4 显存有限,需根据 
nvidia-smi
监控调整(避免 OOM)


--cont-batching


-cb

启用

​连续批处理​​:合并多个请求,吞吐量提升 3-5 倍


--batch-size


-b


2048

​逻辑批大小​​:控制并行处理的 token 总数


--ubatch-size


-ub


512

​物理批大小​​:单次 GPU 计算的 token 数(需匹配显存)


--threads


-t


8

​生成线程数​​:匹配 CPU 物理核心数(日志显示你有 8 线程)


--threads-batch


-tb


8

​批处理线程数​​:预处理阶段并行度


--flash-attn


-fa

启用

​Flash Attention​​:加速注意力计算(需编译支持)


--dynatemp-range


0.4-0.8

​动态温度​​:替代 
--temp 0.6
,平衡速度与质量

4.4 GPU未识别如何解决

启动服务,发现回答速度很慢,而且GPU显存也没有消耗。

说明当初构建项目的时候,没有成功识别到自己的GPU。需要删除build目录重新构建。

# 启用 GGML_CUDA 并指定 T4 架构(计算能力 7.5)根据自己GPU计算能力修改数字

# 退回~/llama.cpp

cd ~/llama.cpp/

# 清理旧构建
rm -rf build

# 关闭CURL

cmake -B build -DCMAKE_BUILD_TYPE=Release -DLLAMA_CURL=OFF

# 启用 GGML_CUDA 并指定 T4 架构(计算能力 7.5)根据自己GPU计算能力修改数字
cmake -B build -DGGML_CUDA=ON -DCMAKE_CUDA_ARCHITECTURES=75 -DCMAKE_BUILD_TYPE=Release

# 启用8核CPU构建项目

cmake –build build –config Release -j 8

# 查看构建情况

./build/bin/llama-server –version

​成功标志​​:输出应包含 
CUDA: ON
或 
GGML_CUDA: enabled

4.5 测试模型服务

使用API启动服务后,可以在网页http://localhost:8002/ # 根据自己的端口号修改 # 使用本地的模型

测试了一个大文本输入,输入处理速度很快,输出处理也挺快 47.53tokens/s 比 vllm 部署的 快一倍。 



from langchain_openai import ChatOpenAI
def get_llamacpp_llm(MODEL_PATH:str,MODEL_URL:str, temperature:Optional[float] = 0.1):
    '''通过本地调用llm,返回langchain的llm对象'''
    llm = ChatOpenAI(
        streaming=True,
        openai_api_base=MODEL_URL,  # VLLM 服务地址
        model_name=MODEL_PATH,
        temperature=temperature,
        # max_tokens=max_tokens,
        openai_api_key="EMPTY",  # 本地部署不需要 API key,但需要设置一个非空值
    )
    return llm
 
if __name__ == "__main__":
    # python -m get_model.get_llm
    # uv run -m get_model.get_llm
    text = "讲个笑话"
 
    llm = get_llamacpp_llm(MODEL_PATH="Qwen3-4B-Instruct-2507-Q4_K_M.gguf",MODEL_URL="http://0.0.0.0:8002/v1")
    
 
    # print(llm.invoke(text).content)
    
    # 简单的控制台流式输出调试
    for chunk in llm.stream(f"{text}"):  # 同步流式方法
        print(chunk.content, end="", flush=True)  # 无需异步环境

测试抽取结构化信息效果挺好的,稳定在20.8s左右,连续测试5次都是这个速度。

五、部署参数量更小的模型

5.1 部署参数量更小的模型

使用 llamacpp部署下述两个模型

Qwen3-0.6B-Q8_0.gguf   GPU资源 1.4 G

输入速度6300 tokens/s 输出速度 157 tokens/s

耗时 3.83s 但是理解能力不行。

Qwen3-1.7B-Q8_0.gguf  GPU资源 2.6 G

输入 4368tokens/s 输出 90tokens/s

速度 6.74s 速度还可以 , 速度和api调用的qwen-flash 差不多

5.2 最终方案

构建Arbitration类,将文本分成两个部分利用 LLM 和程序化方法一起输出json信息。提高效率。

使用llama.cpp部署Qwen3-1.7B-Q8_0.gguf 模型。

不使用Pydantic模型来校验模型输出信息,因为qwen3系列模型json输出能力还可以,可以添加一个程序来处理模型可能输出 “`json  “`这样的情况。

优点:稳定输出,速度和质量比较平衡。

存在个问题,没有办法并发处理,因为本地GPU只有一个,llama.cpp推理框架没有做并发处理,两个请求同时访问本地模型的话就会速度减半。这部分要自己对请求做控制、

六、结论

6.1 模型抽取json信息慢的核心原因

llama.cpp 来部署GGUF量化模型Qwen3-4B-Instruct-2507-Q4_K_M.gguf 日志如下:

对输入处理速度 1829 token/s  模型输出速度 50 token/s。

模型输入处理了1811 tokens花了 0.989s 输出了562tokens处理花了11.19s

硬件设备提升或换更小更快的模型(但是要注意平衡输出质量),如果模型输出速度能达到100token/s的话,抽取速度就可以提升100%,可以达到6-7s,如果有两个GPU,实例化两个模型,也可以做到并发处理,也可以达到3-4s。文本分块且并发调用阿里云的大模型,可以达到3-4s。对于隐私部分调用本地模型,对于非隐私部分调用阿里云的api,并行处理也可以达到6-7s。(本地模型)

6.2 无关因素

注意:因为信息抽取任务,本身是简单的任务,目的是快速准确抽取出文本的json信息。

和下面的因素无关:(下述因素是给一个较为复杂的任务通过工程化操作让大模型输出更优质的内容,以时间换模型输出质量,和提高模型抽取json信息速度无关)

不同的prompt或更友好的prompt。调用外部工具。多次和大模型进行交互。比如先让模型输出纠错OCR内容,输出md格式,再对md格式进行处理。多次对模型输出进行处理。提供模型合适的上下文。

七、参考文章

【AGI】Qwen3模型高效微调_qwen3 微调-CSDN博客

实战 vLLM:成功部署 DeepSeek 32B (FP8 量化 + Eager Mode)_–enforce-eager-CSDN博客

名词解释:vllm,大模型量化;以及如何在vllm实现大模型量化-CSDN博客

大模型推理慢?一文搞懂 FP16、INT8 到 INT4 的量化加速套路_npu推理大模型占用率低-CSDN博客

为什么你的vLLM并没有想象中那么快?Wan2.1-I2V-14B-720P推理优化的“最后一公里”…-CSDN博客

大模型推理加速实战,vLLM 部署 Llama3 的量化与批处理优化指南_vllm ppl-CSDN博客

vLLM参数详细说明-CSDN博客

CUDA计算能力与GPU兼容性指南_cuda compute capability-CSDN博客

一文了解模型精度(FP16、FP8等),所需显存计算以及量化概念!

模型量化技术概述及 GGUF/GGML 文件格式解析,了解 Q4_0、Q4_1、Q4_K 和 Q4_K_M 的区别_q4km量化-CSDN博客

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
乌咪的头像 - 鹿快
评论 抢沙发

请登录后发表评论

    暂无评论内容