1. 项目概述:从“大而全”到“小而精”的工程实践
最近在跟进Happy-LLM这个开源项目,看到第11篇学习笔记的标题时,我立刻来了兴趣。这个标题——“小模型微调、Thinking Budget和多模态拼接的工程启发”——精准地戳中了当前大模型落地应用中的几个核心痛点。它不像很多文章那样空谈“AGI未来”或“万亿参数”,而是把视角拉回到工程实践层面,探讨如何用更务实、更经济的手段,让模型在特定场景下真正“好用”起来。
简单来说,这篇笔记探讨的是三个紧密关联的工程化思路:第一,放弃对超大通用模型的盲目追逐,转而精心微调一个参数更少、更专注的“小模型”。这就像你不需要一台超级计算机来算家里的水电费,一个计算器反而更高效、成本更低。第二,引入“Thinking Budget”(思考预算)的概念,这可不是指花钱,而是指在模型推理时,有意识地控制其“思考”的深度和广度,避免它在简单问题上过度消耗算力,或者在复杂问题上思考不足。第三,探索“多模态拼接”,这不仅仅是把图像、文本、音频模型简单拼在一起,而是思考如何让不同模态的模型高效协作,像一支配合默契的乐队,共同完成一个复杂的任务。
这三个点串联起来,勾勒出一条清晰的路径:用更小的模型、更智能的推理控制、更高效的模态协作,来达成更高的性价比和更可靠的落地效果。这对于我们这些在一线搞模型部署和应用开发的工程师来说,价值巨大。无论是资源有限的创业团队,还是需要严格控制成本的大厂业务线,这套思路都能提供实实在在的参考。接下来,我就结合自己的实践和理解,对这三个核心点进行一次深度拆解。
2. 核心思路拆解:为什么是“小模型”、“思考预算”和“拼接”?
2.1 小模型微调:从“通才”到“专才”的战略转向
过去一两年,业界似乎陷入了一种“参数竞赛”的狂热,仿佛模型不够大就不好意思打招呼。但Happy-LLM的笔记点醒我们:在很多垂直场景下,一个经过精心微调的“小模型”(比如7B、13B参数级别),其表现完全可以媲美甚至超越在该领域“裸奔”的千亿大模型。
这里的逻辑很清晰:大模型是“通才”,它学习了互联网上海量的、通用的知识,能力边界很广,但针对任何一个具体领域的知识深度和任务格式,都可能不够精确。小模型微调则是培养“专才”。我们选择一个基础不错的小模型(例如Qwen-7B、Llama-3-8B),然后用高质量、高密度的领域数据(可能是几千条精心构造的指令数据)对它进行微调。这个过程,本质上是将通用知识“蒸馏”并“特化”到特定领域。
为什么LoRA成为微调的首选技术?笔记里提到了LoRA,这几乎是当前小模型微调的事实标准。它的核心优势在于“参数高效”。传统全参数微调需要更新模型所有权重,显存占用大,且容易导致模型遗忘原有的通用知识(灾难性遗忘)。LoRA则不同,它在原始模型的线性层(如Attention中的QKV矩阵、FFN层)旁,添加一组可训练的“低秩适配器”。训练时,原始的大权重矩阵被冻结,只更新这些小小的适配器。举个例子,一个70亿参数的模型,其LoRA适配器的参数量可能只有几百万甚至几十万,这使得我们可以在消费级显卡(如RTX 4090)上完成微调,且最终模型文件(原始模型+LoRA权重)部署起来也非常轻便。
实操心得:选择LoRA的秩(rank)和缩放因子(alpha)是关键。通常,rank取值在8-64之间,对于7B模型,从16或32开始尝试是稳妥的。alpha可以设置为rank的两倍左右。这并非绝对,最佳参数需要你在自己的验证集上做少量实验。一个常见的误区是认为rank越大越好,实际上过大的rank不仅增加训练成本,还可能引入过拟合。
2.2 Thinking Budget:给模型的思考装上“油门”和“刹车”
“Thinking Budget”是我认为笔记中最具工程启发性的概念。它直指大模型应用中的一个核心矛盾:我们既希望模型对复杂问题深思熟虑,又不想让它对简单问题“想太多”而浪费时间和算力。
在技术实现上,这通常与推理时的生成策略参数深度绑定。我们可以从两个层面来理解这个“预算”:
计算预算:最直接的体现是最大生成长度(max_new_tokens)和采样温度(temperature)。对于一个知识问答,可能512个token就足够了;但对于一篇长文总结,可能需要2048个token。提前设置一个合理的上限,就是控制“思考”的篇幅。Temperature则控制着输出的随机性,低温度(如0.1)让模型更确定、更简洁,高温度(如0.8)让模型更发散、更具创造性,但也可能更啰嗦。
“思考深度”预算:这更接近“思考”的本质。一些先进的技术可以实现这一点:
- 提示工程:在系统提示(System Prompt)中明确指令。“请用最简洁的语言回答,不超过三句话。”这就是一种预算约束。
- 自洽性采样(Self-Consistency)或思维链(CoT)规划:对于复杂推理问题,我们可以让模型先生成多个推理路径(Chain of Thought),然后选择最一致或最可信的答案。这里的“生成多个路径”就是一种预算分配——分配更多的计算资源去探索不同的可能性。
- 推测解码(Speculative Decoding)等高级推理技术:用小模型“草拟”答案,再用大模型快速验证和修正,这本质上是在分配不同模型的计算预算,以换取整体延迟的降低。
注意事项:Thinking Budget不是固定值,而应该是一个动态策略。在工程实现上,可以设计一个简单的分类器,根据用户问题的复杂度(可通过问题长度、关键词、意图识别来初步判断),动态调整后续推理模型的max_new_tokens和temperature参数。例如,简单QA类问题使用“快速模式”(低max_token,低temperature),创意写作类问题使用“深度模式”(高max_token,适中temperature)。
2.3 多模态拼接:从“单体巨兽”到“模块化舰队”
“多模态拼接”听起来很前沿,但其工程内核是解耦与集成。与其等待一个能完美理解所有模态的“全能单体模型”,不如将任务拆解,让擅长不同模态的专家模型各司其职,然后通过一个清晰的协议将它们的结果“拼接”起来。
一个典型的拼接流程可能是这样的:
- 用户输入:一张商品图片 + 文字“这个多少钱?”
- 模态一(视觉专家):专用视觉模型(如CLIP、BLIP)或视觉编码器,负责从图片中提取结构化信息:“这是一个蓝色的陶瓷咖啡杯,带有logo。”
- 模态二(文本专家):大语言模型(LLM)接收来自视觉专家的文本描述和用户的原始文本问题。
- 信息融合与推理:LLM基于拼接后的多模态信息进行推理:“用户提供了一个蓝色陶瓷杯的图片描述,并询问价格。我需要查询该商品的价格信息。”
- 调用外部能力:LLM可以决定是否需要调用“知识库查询工具”或“商品数据库API”来获取具体价格,然后将最终答案返回给用户。
在这个流程中,“拼接”发生在两个关键点:一是将视觉模型的输出“拼接”成LLM可以理解的文本提示词;二是LLM将内部推理结果与外部工具调用的结果“拼接”成最终回复。
工程启发:这种架构的优势非常明显。首先,它降低了技术门槛,团队可以分别迭代视觉模型和语言模型,甚至替换其中任何一个模块,而无需重新训练一个庞然大物。其次,它提升了可解释性和可控性,每个模块的输入输出都是清晰的,便于调试和增加监管逻辑。最后,它是成本高效的,你可以为视觉任务选择一个性价比高的专用小模型,而不必为整个多模态大模型支付高昂的推理成本。
3. 实战演练:构建一个带思考预算的电商客服小模型
理论说得再多,不如动手实践。我们假设一个场景:为一家线上数码商店构建一个智能客服助手。它的主要任务是处理商品咨询、简单故障排查和订单状态查询。我们需要一个响应快、成本低、且回答准确的模型。
3.1 阶段一:领域数据准备与LoRA微调
1. 数据收集与清洗:我们的数据主要来自几个方面:历史客服对话记录(脱敏后)、产品手册Q&A、以及我们自己根据常见问题构造的指令数据。数据清洗是关键,要剔除无关信息、统一格式。我们采用Alpaca指令格式:
{ “instruction”: “用户的问题”, “input”: “(可选的上下文,如商品ID)”, “output”: “理想的客服回答” }例如:
{ “instruction”: “我的蓝牙耳机连接不上手机怎么办?”, “input”: “产品型号:SoundX Pro”, “output”: “您好,关于SoundX Pro耳机连接问题,请尝试以下步骤:1. 确保耳机已充电。2. 将手机蓝牙关闭再打开,并忘记已配对的‘SoundX Pro’设备。3. 长按耳机充电仓上的配对按钮5秒至白灯闪烁,重新在手机蓝牙列表中搜索并连接。如果仍无法解决,请提供您的手机型号,我将为您进一步排查。” }2. 模型与工具选型:
- 基座模型:我们选择
Qwen2.5-7B-Instruct。它在中文理解、指令跟随和推理能力上取得了很好的平衡,且7B的尺寸在微调和部署上都非常友好。 - 微调框架:使用
Transformers+PEFT(Parameter-Efficient Fine-Tuning) 库。PEFT库官方支持LoRA,API简洁。 - 训练框架:
DeepSpeed(如果你有多卡)或Accelerate(单卡/多卡统一接口)。这里我们以单卡为例。
3. LoRA微调关键代码与参数解析:
from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments from peft import LoraConfig, get_peft_model, TaskType from trl import SFTTrainer import torch # 1. 加载模型和分词器 model_name = “Qwen/Qwen2.5-7B-Instruct” model = AutoModelForCausalLM.from_pretrained( model_name, torch_dtype=torch.bfloat16, # 使用BF16节省显存并保持精度 device_map=“auto”, trust_remote_code=True ) tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True) tokenizer.pad_token = tokenizer.eos_token # 设置填充token # 2. 配置LoRA lora_config = LoraConfig( task_type=TaskType.CAUSAL_LM, r=32, # LoRA秩,决定适配器的大小 lora_alpha=64, # 缩放因子,通常设为r的2倍 lora_dropout=0.1, # 防止过拟合的Dropout target_modules=[“q_proj”, “k_proj”, “v_proj”, “o_proj”, “gate_proj”, “up_proj”, “down_proj”], # 针对Qwen2.5结构,作用于Attention和FFN层 bias=“none” ) model = get_peft_model(model, lora_config) model.print_trainable_parameters() # 查看可训练参数量,通常只有原模型的0.1%-1% # 3. 配置训练参数 training_args = TrainingArguments( output_dir=“./qwen-7b-sales-lora”, num_train_epochs=3, # 对于指令微调,3-5个epoch通常足够 per_device_train_batch_size=4, # 根据显存调整,RTX 4090 24G可设为4 gradient_accumulation_steps=8, # 模拟更大的批次大小 learning_rate=2e-4, # LoRA常用学习率 fp16=True, # 使用混合精度训练,A100/V100可用bf16 logging_steps=10, save_strategy=“epoch”, evaluation_strategy=“epoch”, # 如果有验证集 remove_unused_columns=False, push_to_hub=False, # 可上传至Hugging Face Hub ) # 4. 创建Trainer并开始训练 trainer = SFTTrainer( model=model, args=training_args, train_dataset=train_dataset, # 你的训练数据集 eval_dataset=eval_dataset, # 可选的验证数据集 dataset_text_field=“text”, # 数据集中包含格式化指令的字段名 max_seq_length=1024, # 根据你的数据长度设置 tokenizer=tokenizer, ) trainer.train()关键参数解读:
r=32:这是LoRA的秩。它决定了适配器矩阵的大小。越大表示微调能力越强,但也会增加训练参数量和过拟合风险。对于7B模型,从16或32开始是合理的。target_modules:指定将LoRA适配器添加到哪些层。对于LLaMA、Qwen这类Decoder-only的Transformer,通常添加到注意力(q_proj, k_proj, v_proj, o_proj)和前馈网络(gate_proj, up_proj, down_proj)的线性层。这是影响微调效果的关键。per_device_train_batch_size=4和gradient_accumulation_steps=8:这相当于有效的总批次大小为4 * 8 = 32。因为单卡显存有限,无法一次性加载大批次数据,所以先计算小批次的梯度,累积多个小批次后再一次性更新权重,达到大批次训练的效果,有利于训练稳定。
3.2 阶段二:设计并集成Thinking Budget策略
微调好的模型是一个“专才”,但我们还需要它成为一个“聪明的专才”。我们设计一个简单的服务端逻辑来实现Thinking Budget。
1. 请求分类器(轻量级):在请求到达核心LLM之前,我们先用一个快速的规则或极小的文本分类模型(如BERT-tiny)对用户问题进行分类,判断其复杂度和意图。
def classify_query(user_query): “”” 简单规则分类,实际项目可使用微调的小型分类模型。 返回一个预算配置字典。 “”” query_lower = user_query.lower() # 简单查询:问候、肯定/否定、简单确认 simple_keywords = [“你好”, “在吗”, “谢谢”, “好的”, “行”, “不对”] # 复杂查询:包含“为什么”、“如何”、“步骤”、“对比”、“故障”等需要推理的词汇 complex_keywords = [“为什么”, “怎么”, “如何”, “步骤”, “原因”, “故障”, “对比”, “推荐”] if any(kw in query_lower for kw in simple_keywords): return {“mode”: “fast”, “max_new_tokens”: 128, “temperature”: 0.1} elif any(kw in query_lower for kw in complex_keywords): return {“mode”: “deep”, “max_new_tokens”: 1024, “temperature”: 0.7} else: # 默认中等复杂度,如普通商品咨询 return {“mode”: “normal”, “max_new_tokens”: 512, “temperature”: 0.3}2. 动态推理参数调用:在调用我们微调好的Qwen模型时,传入分类器返回的预算参数。
from transformers import pipeline # 加载基础模型和LoRA权重 model = AutoModelForCausalLM.from_pretrained(“Qwen/Qwen2.5-7B-Instruct”, …) model = PeftModel.from_pretrained(model, “./qwen-7b-sales-lora”) # 加载LoRA适配器 model = model.merge_and_unload() # 可选:将LoRA权重合并回原模型,简化部署 tokenizer = AutoTokenizer.from_pretrained(“Qwen/Qwen2.5-7B-Instruct”) generator = pipeline(“text-generation”, model=model, tokenizer=tokenizer) def generate_response(user_query, context=None): # 1. 获取思考预算 budget = classify_query(user_query) # 2. 构建提示词 prompt = f“””你是一个专业的数码产品客服助手。请根据以下信息回答问题。 商品上下文:{context if context else ‘无’} 用户问题:{user_query} 回答:””” # 3. 根据预算生成 response = generator( prompt, max_new_tokens=budget[‘max_new_tokens’], temperature=budget[‘temperature’], do_sample=True if budget[‘temperature’] > 0 else False, pad_token_id=tokenizer.eos_token_id, ) return response[0][‘generated_text’].replace(prompt, “”).strip()通过这个机制,对于“你好”这样的问候,模型会快速生成一个简短的礼貌回复(fast模式);对于“请对比一下A手机和B手机的摄像头参数”,模型会获得更多的“思考篇幅”和一定的创造性空间(deep模式),来组织一个结构化的对比回答。
3.3 阶段三:引入多模态拼接处理图片咨询
现在,客服系统需要处理用户发送的商品图片来咨询问题。我们引入一个视觉模型来“看懂”图片。
1. 视觉专家模型选型与调用:我们选择BLIP-2模型,因为它能同时完成视觉问答(VQA)和图像描述(Image Captioning),且模型相对高效。在实际工程中,我们可以使用其图像描述能力,将图片转化为文本。
from PIL import Image from transformers import Blip2Processor, Blip2ForConditionalGeneration import torch # 加载BLIP-2模型(这里以较小的Flan-T5 XXL版本为例) device = “cuda” if torch.cuda.is_available() else “cpu” processor = Blip2Processor.from_pretrained(“Salesforce/blip2-flan-t5-xxl”) vision_model = Blip2ForConditionalGeneration.from_pretrained(“Salesforce/blip2-flan-t5-xxl”, torch_dtype=torch.float16).to(device) def describe_image(image_path): “””使用BLIP-2生成对图片的详细文本描述。””” image = Image.open(image_path).convert(‘RGB’) inputs = processor(images=image, return_tensors=“pt”).to(device, torch.float16) # 生成描述,可以调整参数控制描述长度和多样性 generated_ids = vision_model.generate(**inputs, max_new_tokens=100, num_beams=5) description = processor.batch_decode(generated_ids, skip_special_tokens=True)[0].strip() return description2. 多模态拼接流程集成:当用户上传图片并附带问题时,我们的服务流程变为:
def handle_multimodal_query(image_path, user_text_query): # 步骤1:视觉专家“看”图说话 image_description = describe_image(image_path) # 示例输出:“一张黑色笔记本电脑的图片,屏幕显示着编程界面,品牌logo在机身一角。” # 步骤2:拼接多模态信息,构建给LLM的提示词 context_for_llm = f“用户提供了一张图片,图片描述如下:{image_description}” # 步骤3:调用我们微调好的、带有Thinking Budget的客服LLM # 此时,用户的问题(user_text_query)和图片描述(context_for_llm)一起作为LLM的输入 full_response = generate_response(user_text_query, context=context_for_llm) return full_response # 模拟调用 # 用户行为:上传一张电脑图片,问“这款电脑玩大型游戏卡吗?” answer = handle_multimodal_query(“laptop.jpg”, “这款电脑玩大型游戏卡吗?”) print(answer) # 理想输出:“根据图片描述,这是一台黑色笔记本电脑。仅从外观无法判断具体型号和配置。玩大型游戏(如3A大作)的流畅度主要取决于显卡(如RTX 4060以上)、CPU和散热。请您提供电脑的具体型号或配置单,我可以为您做更准确的评估。”在这个流程中,BLIP-2模型充当了“视觉翻译官”,将非结构化的像素信息转换成了LLM能够理解的结构化文本描述。然后,这个描述被“拼接”到用户的文本问题之前,共同输入给我们微调的客服LLM。LLM综合这两部分信息,生成最终的客服回答。这就完成了一次完整的“多模态拼接”任务。
4. 工程化部署与优化要点
将上述三个模块(微调模型、预算策略、多模态拼接)整合成一个稳定、高效的服务,还需要考虑以下工程细节。
4.1 模型服务化与性能优化
1. 模型合并与量化:训练完成后,可以使用merge_and_unload()方法将LoRA权重合并回原模型,得到一个完整的.bin文件,这样在部署时只需加载单个文件,简化流程。为了进一步降低部署资源需求,可以对合并后的模型进行量化。
- GPTQ/AWQ量化:这两种是主流的权重量化方法,能在几乎不掉精度的情况下,将模型显存占用减少到原来的1/3或1/4(如7B模型从14GB FP16降到3.5-4GB INT4)。使用
auto-gptq或llama.cpp库可以很方便地完成。# 使用auto-gptq进行量化示例(需先安装) python -m auto_gptq.llama_qat.quantize_model \ --model_path ./merged_qwen_7b \ --output_path ./qwen_7b_gptq \ --bits 4 \ --group_size 128 - vLLM或TGI部署:对于生产环境,推荐使用
vLLM或Text Generation Inference (TGI)这样的高性能推理引擎。它们通过PagedAttention等技术极大地优化了显存利用和吞吐量,支持动态批处理,非常适合高并发场景。
2. API服务搭建:使用FastAPI或Flask将模型封装成HTTP API。关键是要做好异步处理和请求队列,避免高并发时服务崩溃。
from fastapi import FastAPI, BackgroundTasks from pydantic import BaseModel import asyncio from your_model_module import generate_response, handle_multimodal_query # 导入前面的函数 app = FastAPI() request_queue = asyncio.Queue() # … (启动后台工作线程消费队列) class TextRequest(BaseModel): query: str context: str = None class ImageRequest(BaseModel): image_url: str # 或使用File上传 query: str @app.post(“/chat”) async def chat(request: TextRequest): # 可在此处加入请求分类(Thinking Budget) budget = classify_query(request.query) # 将生成任务放入队列,避免阻塞 response = await asyncio.to_thread(generate_response, request.query, request.context) return {“response”: response} @app.post(“/chat_with_image”) async def chat_with_image(request: ImageRequest): # 1. 下载或读取图片 # 2. 调用多模态处理流程 response = await asyncio.to_thread(handle_multimodal_query, request.image_url, request.query) return {“response”: response}4.2 成本监控与弹性伸缩
Thinking Budget的另一个重要维度是经济预算。我们需要监控每次API调用的实际消耗。
- 计算成本:记录每次推理消耗的Token数(输入+输出)和耗时。可以设置告警,当平均Token数异常升高时,检查是否预算分类器失效或遇到了新型复杂问题。
- 缓存策略:对于高频的、答案固定的简单问题(如“营业时间?”“退货政策?”),可以将模型回答的结果缓存起来(如使用Redis),直接返回,避免不必要的模型调用。
- 分级服务:根据用户套餐或问题紧急程度,实施不同的Thinking Budget策略。免费用户使用
fast模式,付费VIP用户使用deep模式。
4.3 持续迭代与数据飞轮
一个成功的AI客服系统不是一蹴而就的。
- 收集bad cases:将所有模型回答不满意(被用户差评、人工客服接管)的对话记录下来。
- 数据标注与扩充:定期对这些bad cases进行修正和标注,生成新的高质量指令数据。
- 增量微调:每隔一段时间(如每月),用新的数据对模型进行一轮增量LoRA微调,让模型持续进化,适应新的产品和用户问法。
- A/B测试:当有新的模型版本(如调整了LoRA参数、更新了基座模型)或新的Thinking Budget策略时,通过A/B测试来量化评估其效果(如满意度提升、平均响应时间下降),用数据驱动决策。
5. 常见问题与避坑指南
在实际操作中,你肯定会遇到各种各样的问题。下面是我总结的一些典型问题及其解决方案。
| 问题现象 | 可能原因 | 排查与解决思路 |
|---|---|---|
| 微调后模型“胡说八道”或失去基础能力 | 1. 学习率过高。 2. 训练数据质量差、噪声大。 3. 过度拟合(训练轮次太多)。 4. LoRA的 target_modules设置不当,影响了关键层。 | 1.降低学习率,尝试从1e-4, 5e-5开始。 2.严格清洗数据,确保指令清晰、答案准确。可先用小数据集测试。 3.早停(Early Stopping),监控验证集损失,不再下降时即停止。 4.检查 target_modules,对于Qwen/Llama架构,确保覆盖了注意力(q,k,v,o)和FFN(gate,up,down)层。 |
| LoRA微调效果不明显 | 1. 数据量太少。 2. LoRA秩( r)太小。3. 基座模型与任务完全不匹配。 | 1.增加高质量数据,指令微调通常需要数千条优质数据。 2.适当增大 r值,从8, 16, 32逐步尝试。3.更换基座模型,选择在通用能力上更强或与任务领域更接近的模型。 |
| 推理速度慢,吞吐量低 | 1. 模型未量化,显存占用高。 2. 未使用高性能推理引擎。 3. max_new_tokens设置过大。 | 1.对模型进行GPTQ/AWQ量化,显著降低显存和加速。 2.部署时使用vLLM或TGI。 3.优化Thinking Budget策略,为多数请求设置合理的 max_new_tokens。 |
| 多模态拼接中,视觉描述不准确 | 1. BLIP等视觉模型本身能力有限。 2. 图片过于复杂或模糊。 3. 生成的描述文本太长,包含无关细节。 | 1.尝试更强的视觉模型,如GPT-4V API(成本高)或开源的CogVLM2。 2.前处理图片,如裁剪核心区域、增强分辨率。 3.在调用视觉模型时,通过提示词控制,如“请用一句话描述图片中的主要物体和场景”。 |
| Thinking Budget分类器不准 | 1. 规则过于简单。 2. 用户问题复杂多样,难以用规则覆盖。 | 1.升级为轻量级文本分类模型,如用几百条标注数据微调一个BERT-tiny,比规则更鲁棒。2.采用多级分类,先分大类(简单/复杂),复杂类中再细分(技术问题、对比问题、创意问题等),对应更精细的预算。 |
| 服务内存泄漏或GPU显存溢出 | 1. 代码中存在未释放的模型或张量引用。 2. 请求堆积,动态批处理导致显存峰值过高。 | 1.使用with torch.no_grad():包装推理代码,并注意及时将变量移出GPU(.cpu())。2.在vLLM/TGI中限制并发数和最大批处理大小。实现请求队列和超时机制,拒绝过量请求。 |
最后再分享一个关键技巧:关于LoRA权重合并。在开发测试阶段,我们可以使用PeftModel动态加载LoRA权重,方便快速迭代。但在生产部署时,强烈建议使用merge_and_unload()将LoRA权重合并到基础模型中。这样做有两个巨大好处:第一,推理时只需加载一个模型文件,速度更快,加载更简单;第二,可以对这个合并后的模型进行量化操作(如GPTQ),从而获得极致的推理效率。合并后的模型就是一个标准的Transformers模型,可以像任何其他模型一样被vLLM等引擎加载。