ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

ChatGLM-4本地部署实战:vLLM推理、魔塔Embedding与LoRA微调

ChatGLM-4本地部署实战:vLLM推理、魔塔Embedding与LoRA微调 最近在尝试本地部署大模型时发现很多教程要么只讲理论要么代码和配置七零八落尤其是涉及 vLLM 这种高性能推理框架时环境依赖和参数调优经常让人头疼。本文将围绕ChatGLM-4整合一套从零开始的完整实战方案涵盖vLLM 高效部署、魔塔ModelScopeEmbeddings 接入、以及基础的模型微调。无论你是想快速体验大模型能力的新手还是需要在项目中集成私有化模型的开发者都能从本文找到可复现的代码和清晰的避坑指南。1. 背景与核心概念为什么是这套组合在深入实操之前我们先理清几个核心概念理解它们各自扮演的角色以及组合使用的优势。ChatGLM-4是智谱AI推出的最新一代开源双语大语言模型。相比前代它在推理、代码和数学能力上都有显著提升。对于开发者而言其完全开源的特性使得我们可以在自己的硬件上进行部署、研究和定制避免了云API的调用费用和网络延迟。vLLM是一个专为大模型推理设计的高吞吐量、低延迟服务框架。它的核心创新在于PagedAttention算法能够高效管理模型推理过程中的注意力键值KV缓存从而在有限显存下实现更高的并发吞吐量。简单说用 vLLM 部署 ChatGLM-4可以在同样的 GPU 上服务更多的用户请求或者更快地返回单个请求的结果。魔塔ModelScopeEmbeddings指的是阿里云魔塔社区提供的文本向量化模型。Embedding 模型能将文本转换为高维向量是实现语义搜索、检索增强生成RAG等高级应用的基础。使用魔塔的 Embedding 模型可以方便地获得高质量的中文文本向量并与 ChatGLM-4 结合构建本地知识库应用。模型微调是指利用特定领域的数据对预训练好的大模型进行额外的训练使其在该领域的任务上表现更佳。对于 ChatGLM-4我们可以使用 LoRA、QLoRA 等参数高效微调方法在消费级显卡上实现对模型能力的定制。这套组合的价值在于vLLM解决了“如何高效、稳定地服务大模型”的问题魔塔 Embeddings解决了“如何让大模型理解并利用外部知识”的问题模型微调则解决了“如何让通用大模型适应我的专属业务”的问题。三者结合便能构建一个强大且可控的本地大模型应用栈。2. 环境准备与版本说明工欲善其事必先利其器。一个清晰、隔离的环境是成功的第一步。为了避免包冲突强烈建议使用 Conda 或 venv 创建独立的 Python 环境。2.1 硬件与基础软件要求操作系统推荐 Ubuntu 20.04/22.04 LTS 或 Windows 11 WSL2。本文主要基于 Linux 环境演示Windows 用户可通过 WSL2 获得近乎一致的体验。GPU至少需要 16GB 显存如 RTX 4080, RTX 3090来运行 ChatGLM-4 的 INT4 量化版本。如需微调显存需求会更高。显存不足可考虑使用量化等级更高的模型或云服务器。Python版本 3.9 或 3.10。3.11及以上版本可能存在某些库的兼容性问题。CUDA版本 11.8 或 12.1。需与后续安装的 PyTorch 和 vLLM 版本匹配。2.2 创建并激活 Python 环境# 使用 conda conda create -n chatglm4-demo python3.10 -y conda activate chatglm4-demo # 或者使用 venv python -m venv chatglm4-demo source chatglm4-demo/bin/activate # Linux/Mac # chatglm4-demo\Scripts\activate # Windows2.3 安装核心依赖我们将分步安装以便更好地管理依赖。首先安装 PyTorch请根据你的 CUDA 版本前往 PyTorch 官网 获取最准确的安装命令。例如对于 CUDA 12.1pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121接下来安装 vLLM。vLLM 对版本非常敏感特别是与 CUDA 和 PyTorch 的兼容性。# 安装 vLLM 及其所有可选依赖包括用于Web UI的 pip install vllm[all] # 验证安装 python -c import vllm; print(vllm.__version__)然后安装魔塔 ModelScope 和 transformers 库用于加载 Embedding 模型和 ChatGLM-4 原版模型。pip install modelscope transformers最后安装模型微调常用的工具包。pip install datasets accelerate peft trl bitsandbytes scipy3. 使用 vLLM 高效部署 ChatGLM-4vLLM 提供了极简的 API 和命令行工具来启动一个高性能的模型服务。我们将演示两种最常用的方式离线启动和 OpenAI 兼容 API 服务启动。3.1 方式一离线加载与推理这种方式适合快速测试模型是否能正常加载和进行单次推理。首先你需要一个 Hugging Face 账户并申请 ChatGLM-4 的模型权重访问权限因为它是开源但需要同意的。获得权限后你可以使用transformers库直接加载但这里我们使用 vLLM 的LLM类它能自动应用 PagedAttention 优化。创建一个 Python 脚本test_offline.py# test_offline.py from vllm import LLM, SamplingParams # 1. 定义模型路径 # 方式A: 从 Hugging Face Hub 加载 (需先登录 huggingface-cli) # model_path THUDM/chatglm4-9b # 方式B: 从本地路径加载 (假设你已下载模型至 ./models/chatglm4-9b) model_path ./models/chatglm4-9b # 2. 初始化 vLLM 引擎 # tensor_parallel_size 指张量并行度单卡设为1。如果你的模型是量化版需指定 dtype 和 quantization 参数。 print(正在加载模型这可能需要几分钟...) llm LLM(modelmodel_path, tensor_parallel_size1, trust_remote_codeTrue, # ChatGLM 需要此参数 max_model_len8192) # 根据模型上下文长度设置 # 3. 配置采样参数 sampling_params SamplingParams(temperature0.8, top_p0.95, max_tokens512) # 4. 准备提示词 prompts [ 请用中文介绍一下你自己。, Python 中如何快速反转一个列表, ] # 5. 生成文本 print(开始生成...) outputs llm.generate(prompts, sampling_params) # 6. 输出结果 for output in outputs: prompt output.prompt generated_text output.outputs[0].text print(f提示: {prompt!r}\n生成: {generated_text!r}\n{-*50})运行脚本python test_offline.py如果一切顺利你将看到模型的自我介绍和代码回答。LLM()初始化过程会加载模型并编译内核首次运行较慢后续推理会非常快。3.2 方式二启动 OpenAI 兼容的 API 服务推荐这是生产环境更常用的方式。vLLM 可以启动一个与 OpenAI API 格式完全兼容的 HTTP 服务方便集成到各种应用中。使用vllm命令行工具一行命令即可启动vllm serve ./models/chatglm4-9b \ --port 8000 \ --trust-remote-code \ --max-model-len 8192 \ --api-key “your-api-key-here” # 可选增加基础安全serve: 启动服务命令。./models/chatglm4-9b: 你的模型本地路径。--port: 服务端口默认为 8000。--trust-remote-code: 对 ChatGLM 等自定义模型必需。--max-model-len: 模型支持的最大上下文长度。--api-key: 设置一个 API 密钥客户端调用时需在 Header 中提供用于简单鉴权。服务启动后你可以使用任何 HTTP 客户端进行调用。例如使用curlcurl http://localhost:8000/v1/completions \ -H “Content-Type: application/json” \ -H “Authorization: Bearer your-api-key-here” \ -d ‘{ “model”: “./models/chatglm4-9b“, “prompt”: “中国的首都是哪里”, “max_tokens”: 100, “temperature”: 0.7 }’或者使用 Python 的openai库需要pip install openaifrom openai import OpenAI client OpenAI( api_key“your-api-key-here”, base_url“http://localhost:8000/v1” ) response client.completions.create( model“./models/chatglm4-9b“, prompt“中国的首都是哪里”, max_tokens100 ) print(response.choices[0].text)这种部署方式使得前端应用、LangChain、Dify 等框架都能无缝接入你的本地大模型。4. 集成魔塔ModelScopeEmbeddings有了强大的语言模型下一步是让它能“查阅资料”。我们需要一个 Embedding 模型将文本知识库转换为向量。这里我们选用魔塔社区的中文 Embedding 模型text2vec-base-chinese。创建一个脚本embedding_demo.py# embedding_demo.py from modelscope.models import Model from modelscope.preprocessors import Preprocessor from modelscope.pipelines import pipeline from modelscope.utils.constant import Tasks # 1. 指定模型 model_id ‘damo/nlp_corom_sentence-embedding_chinese-base‘ # 2. 创建 Embedding pipeline # 首次运行会自动从魔塔下载模型 embed_pipe pipeline(Tasks.sentence_embedding, modelmodel_id, device‘cuda‘) # 或 ‘cpu‘ # 3. 准备文本 sentences [‘今天天气真好‘, ‘人工智能是未来的趋势‘, ‘我喜欢编程‘] # 4. 生成向量 embeddings embed_pipe(inputsentences) print(f“输入句子: {sentences}“) print(f“向量维度: {len(embeddings[0])}“) # 通常为 768 维 print(f“前10个向量值示例: {embeddings[0][:10]}“) # 5. 计算相似度 (示例计算第一句和第二句的余弦相似度) import numpy as np vec1 np.array(embeddings[0]) vec2 np.array(embeddings[1]) cosine_sim np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2)) print(f“今天天气真好‘ 与 ‘人工智能是未来的趋势‘ 的余弦相似度: {cosine_sim:.4f}“)运行此脚本你将看到每个句子被转换成一个 768 维的向量并且可以计算句子间的语义相似度。在实际的 RAG 应用中你会将文档块向量化后存入向量数据库如 Chroma, Milvus当用户提问时先检索出相关文档块再连同问题一起交给 ChatGLM-4 生成答案。5. 基于 LoRA 的模型微调实战微调能让 ChatGLM-4 更擅长特定任务比如法律咨询、医疗问答或公司内部知识处理。我们将使用 Hugging Face 的peft库进行 LoRA 微调这是一种参数高效的方法只需训练极少量参数。5.1 准备训练数据数据需要整理成特定的 JSON 格式。这里我们创建一个简单的指令遵循数据集data/train.jsonl每行一个 JSON 对象。{“instruction”: “将以下中文翻译成英文。“, “input”: “深度学习很有趣。“, “output”: “Deep learning is interesting.“} {“instruction”: “总结下面这段话。“, “input”: “vLLM是一个高性能推理框架...“, “output”: “vLLM是用于大模型的高性能推理框架。“} {“instruction”: “写一首关于春天的诗。“, “input”: ““, “output”: “春风吹绿柳枝头细雨润物悄无声...“}5.2 编写微调脚本创建一个完整的训练脚本finetune_lora.py。这个脚本包含了数据加载、模型加载、LoRA 配置、训练循环和保存。# finetune_lora.py import json from datasets import Dataset from transformers import AutoTokenizer, AutoModelForCausalLM, TrainingArguments from peft import LoraConfig, get_peft_model, TaskType from trl import SFTTrainer import torch # 0. 参数设置 MODEL_PATH “./models/chatglm4-9b“ # 基础模型路径 OUTPUT_DIR “./output/chatglm4-lora“ # 输出目录 DATA_PATH “./data/train.jsonl“ # 训练数据 # 1. 加载 Tokenizer 和模型 tokenizer AutoTokenizer.from_pretrained(MODEL_PATH, trust_remote_codeTrue) # ChatGLM 的 tokenizer 可能没有 pad_token需要设置 if tokenizer.pad_token is None: tokenizer.pad_token tokenizer.eos_token model AutoModelForCausalLM.from_pretrained( MODEL_PATH, trust_remote_codeTrue, torch_dtypetorch.bfloat16, # 根据你的 GPU 支持情况选择bfloat16 节省显存 device_map“auto“ # 自动分配模型层到多 GPU ) model.enable_input_require_grads() # 为 LoRA 兼容性 # 2. 配置 LoRA lora_config LoraConfig( task_typeTaskType.CAUSAL_LM, # 因果语言模型任务 r8, # LoRA 秩 lora_alpha32, lora_dropout0.1, target_modules[“query_key_value“], # ChatGLM 的注意力层模块名 bias“none“ ) model get_peft_model(model, lora_config) model.print_trainable_parameters() # 打印可训练参数量应该只占原模型很小一部分 # 3. 加载并格式化数据集 def format_func(example): # 将 instruction, input, output 格式化成模型输入的文本 text f“Instruction: {example[‘instruction‘]}\n“ if example[‘input‘].strip(): text f“Input: {example[‘input‘]}\n“ text f“Output: {example[‘output‘]}{tokenizer.eos_token}“ # 添加结束符 return {“text“: text} with open(DATA_PATH, ‘r‘, encoding‘utf-8‘) as f: data [json.loads(line) for line in f] dataset Dataset.from_list(data) dataset dataset.map(format_func) # 4. 配置训练参数 training_args TrainingArguments( output_dirOUTPUT_DIR, per_device_train_batch_size2, # 根据显存调整 gradient_accumulation_steps4, # 模拟更大的批次大小 num_train_epochs3, logging_steps10, save_steps100, learning_rate2e-4, fp16True, # 使用混合精度训练A100/V100 等可用 remove_unused_columnsFalse, push_to_hubFalse, # 不上传到 Hub ) # 5. 创建 Trainer 并开始训练 trainer SFTTrainer( modelmodel, argstraining_args, train_datasetdataset, tokenizertokenizer, max_seq_length1024, # 根据你的数据长度调整 dataset_text_field“text“, ) print(“开始训练...“) trainer.train() # 6. 保存 LoRA 权重 trainer.model.save_pretrained(OUTPUT_DIR) tokenizer.save_pretrained(OUTPUT_DIR) print(f“训练完成模型已保存至 {OUTPUT_DIR}“)5.3 运行微调与推理运行训练脚本请确保你有足够的 GPU 显存否则需要减小per_device_train_batch_size或使用gradient_checkpointingpython finetune_lora.py训练完成后在./output/chatglm4-lora目录下会保存 LoRA 的权重文件如adapter_model.bin和配置文件。如何使用微调后的模型你需要同时加载基础模型和 LoRA 权重。使用 vLLM 加载时需要先将 LoRA 权重与基础模型合并或者使用支持动态加载 LoRA 权重的服务方式vLLM 正在完善此功能。一个简单的方法是使用transformers加载后进行推理from peft import PeftModel from transformers import AutoTokenizer, AutoModelForCausalLM base_model_path “./models/chatglm4-9b“ lora_path “./output/chatglm4-lora“ tokenizer AutoTokenizer.from_pretrained(base_model_path, trust_remote_codeTrue) model AutoModelForCausalLM.from_pretrained(base_model_path, trust_remote_codeTrue, device_map“auto“) model PeftModel.from_pretrained(model, lora_path) # 加载 LoRA 权重 model model.merge_and_unload() # 合并权重到基础模型 # 进行推理 inputs tokenizer(“Instruction: 翻译以下句子。\nInput: Hello, world!\nOutput:“, return_tensors“pt“).to(model.device) outputs model.generate(**inputs, max_new_tokens50) print(tokenizer.decode(outputs[0], skip_special_tokensTrue))6. 常见问题与排查思路在部署和微调过程中你可能会遇到以下典型问题。问题现象常见原因解决思路vLLM 启动失败报 CUDA 或 torch 相关错误CUDA 版本、PyTorch 版本、vLLM 版本不兼容。1. 使用nvcc --version和python -c “import torch; print(torch.__version__)“确认版本。2. 查阅 vLLM 官方文档的版本兼容性表格。3. 尝试在干净的虚拟环境中重新安装匹配的版本。加载 ChatGLM-4 模型时卡住或报trust_remote_code错误模型需要执行自定义代码但未授权。网络问题导致下载失败。1. 确保在LLM()或from_pretrained()中设置了trust_remote_codeTrue。2. 检查网络或提前将模型下载到本地指定本地路径。embeddings huggingfaceembeddings()报错这是 LangChain 的写法直接使用transformers或modelscope时接口不同。包未安装或版本冲突。1. 确认你安装的是modelscope而非huggingface-hub除非你用 Hugging Face 的模型。2. 按照本文第 4 节使用modelscope.pipelines。3. 检查transformers和modelscope版本尝试升级或安装指定版本。微调时 GPU 显存不足OOM批次大小太大、模型太大、未使用量化或梯度检查点。1. 减小per_device_train_batch_size。2. 增大gradient_accumulation_steps以保持总批次大小。3. 使用bitsandbytes库进行 4-bit/8-bit 量化加载模型QLoRA。4. 在TrainingArguments中设置gradient_checkpointingTrue。vLLM API 服务调用返回 401 或 403 错误启动服务时设置了--api-key但客户端调用时未提供或密钥错误。1. 检查客户端请求头Authorization: Bearer your-api-key是否正确。2. 或者暂时移除--api-key参数启动服务进行测试仅限内网安全环境。生成的文本重复或无意义采样参数temperature,top_p设置不当。提示词Prompt编写不佳。1. 调整temperature较低如 0.2 更确定较高如 0.8 更多样、top_p通常 0.9-0.95。2. 优化提示词明确指令和格式。参考 ChatGLM-4 的官方提示词模板。7. 最佳实践与工程建议将技术跑通只是第一步要用于实际项目还需遵循一些工程实践。1. 模型管理与版本化将下载好的基础模型、微调后的 LoRA 权重、Embedding 模型都纳入版本管理如 Git LFS或专门的模型仓库。为每次重要的微调实验打上标签记录超参数和训练数据版本。2. 服务化与监控使用systemd或supervisor管理vllm serve进程确保服务崩溃后能自动重启。为 vLLM API 服务配置 Nginx 反向代理添加 SSL 证书、限流和更完善的认证。暴露并监控服务的关键指标如请求延迟P50, P99、吞吐量Tokens/s、GPU 显存和利用率。vLLM 支持与 Prometheus 集成。3. 安全与权限切勿将未加任何认证的模型服务暴露在公网。生产环境务必使用--api-key并考虑实现更复杂的认证鉴权中间件。对用户输入进行严格的过滤和清理防止提示词注入攻击。4. 性能优化量化如果显存紧张优先考虑使用 GPTQ、AWQ 等量化技术压缩模型vLLM 对此有良好支持。例如使用--quantization awq参数启动服务。批处理利用 vLLM 的异步接口和批处理能力同时处理多个请求以提高 GPU 利用率。参数调整根据你的硬件和需求调整--max-num-seqs最大并发序列数、--gpu-memory-utilization等 vLLM 启动参数。5. 提示词工程对于 ChatGLM-4遵循其约定的对话格式能获得更稳定的输出。例如在系统提示中明确其角色和能力。对于 RAG 应用精心设计检索到的上下文与用户问题的拼接方式Prompt Template这对最终答案的质量影响巨大。从在本地成功运行 ChatGLM-4到用 vLLM 将其封装成高性能 API再到接入 Embedding 模型构建知识库最后通过微调赋予其专业领域能力这条路径涵盖了当前私有化大模型应用的核心环节。每个环节都有其技术细节和优化空间建议先从本文的完整流程跑通建立感性认识再针对每个环节深入探索。例如深入研究 vLLM 的源码以理解其内存管理机制尝试不同的 LoRA 超参数对微调效果的影响或者对比不同 Embedding 模型在业务数据上的效果。大模型本地部署的门槛正在快速降低现在正是动手实践、积累经验的好时机。如果在操作中遇到新的问题欢迎在评论区交流探讨。
返回列表