GLM-4源码包实战:推理、微调与二次开发避坑指南
简介这份资源是智谱GLM-4大模型的官方代码仓库源码压缩包面向希望深入研究与二次开发GLM-4的开发者、算法工程师及高校研究人员可用于本地推理部署、模型微调与多模态能力验证等场景。包内共78个文件以Python源码为主体涵盖基础对话、视觉转写、批量推理、OpenAI接口服务及vLLM命令行等示例脚本同时配有Markdown说明文档、YAML配置、JSON数据与TypeScript前端资源并附有示意图与许可证文件压缩包约7.57MB目录按basic_demo、composite_demo、finetune_demo等模块划分结构清晰便于按需查阅。目前已有307人学习下载。读者可从中获得完整的仓库目录结构、官方示例代码与配置模板快速理解GLM-4的调用方式与微调流程为后续实验与工程落地提供可直接参考的代码基础。1. 拿到 glm4 代码仓库源码 zip 包先别急着解压上周有个做智能客服的朋友丢给我一个压缩包说“这是 glm4 的代码仓库源码你帮我看看能不能跑”。我解压一看目录里既有模型推理脚本也有训练配置、数据处理工具和一堆示例 notebook典型的“全家桶”式仓库。很多人拿到这种 zip 包的第一反应是找requirements.txt然后pip install -r结果装到一半就卡在某个 CUDA 版本不匹配的包上——这就是我踩过的第一个坑。这个仓库源码包的价值不在于“一键跑通”而在于它把 GLM-4 系列模型的推理、微调、量化、部署几条链路都摊开给你看。适合两类人一是想在自己机器上跑通 GLM-4 推理、做本地问答或文档助手的开发者二是想基于官方代码做领域微调、改 tokenizer 或换推理后端的熟手。下面我按“这仓库长什么样 → 怎么把推理跑起来 → 微调链路怎么改 → 避坑 → 二次开发”的顺序拆。2. 仓库结构与技术栈先看清目录再动手2.1 顶层目录都放了什么解压后先别装依赖花五分钟把目录扫一遍。这类 GLM-4 仓库的典型结构大致是这样不同版本会有出入以你手上的为准glm4-repo/ ├── README.md ├── requirements.txt ├── setup.py ├── configs/ # 模型与训练配置 │ ├── model_config.json │ └── lora_config.yaml ├── glm4/ │ ├── __init__.py │ ├── modeling_glm4.py # 模型结构定义 │ ├── tokenization_glm4.py # tokenizer │ └── configuration_glm4.py ├── inference/ │ ├── chat.py # 命令行对话入口 │ ├── api_server.py # OpenAI 兼容接口 │ └── batch_infer.py ├── finetune/ │ ├── train_sft.py # 监督微调 │ ├── train_lora.py # LoRA 微调 │ └── dataset.py ├── tools/ │ ├── convert_ckpt.py # 权重格式转换 │ └── quantize.py # 量化脚本 └── examples/ └── quickstart.ipynb看到modeling_glm4.py和tokenization_glm4.py这两个文件说明仓库自带模型实现不依赖外部 transformers 的远程代码——这是好事版本可控但也意味着你得自己保证 transformers 版本和它兼容。inference/和finetune/分开说明推理和训练是两条独立链路可以只跑其中一条。2.2 技术栈与依赖关系核心依赖绕不开这几样PyTorch模型计算、transformers加载与生成接口、accelerate多卡与显存优化、peftLoRA 微调、sentencepiece 或 tiktoken分词。量化链路通常还会带 bitsandbytes 或 GPTQ 相关包。我一般会先看requirements.txt里有没有钉死版本号torch2.1.0 transformers4.40.0 accelerate0.28.0 peft0.9.0 sentencepiece0.1.99 bitsandbytes0.43.0提示transformers这种带的包千万别随手升级。仓库里的modeling_glm4.py往往调用了特定版本的内部 API升一个小版本就可能报AttributeError。判断依赖是否完整有个笨办法但很有效先只装torch和transformers然后python -c from glm4.modeling_glm4 import Glm4ForCausalLM能 import 成功再往下装。缺什么补什么比一次性装完再排查快得多。2.3 模型权重和代码是分开的zip 包里通常只有代码权重得单独下载。仓库的configs/model_config.json里会写模型维度、层数、注意力头数这些结构参数但真正的.safetensors或.bin文件不在包里。常见做法是把权重放到一个本地目录然后在推理脚本里用--model_path指过去。如果你手上只有代码没有权重chat.py跑到加载那一步就会报OSError: Cant load weights这不是代码问题别在代码里找半天。3. 把推理链路跑起来从命令行对话到 API 服务3.1 环境准备与最小验证先建独立环境别污染系统 Pythonconda create -n glm4 python3.10 -y conda activate glm4 pip install torch --index-url https://download.pytorch.org/whl/cu121 pip install -r requirements.txtCUDA 版本按你显卡驱动来cu121只是示例。装完做一次最小验证确认模型能加载、能生成一个 tokenimport torch from glm4.modeling_glm4 import Glm4ForCausalLM from glm4.tokenization_glm4 import Glm4Tokenizer model_path ./weights/glm4-base # 权重目录 tokenizer Glm4Tokenizer.from_pretrained(model_path) model Glm4ForCausalLM.from_pretrained( model_path, torch_dtypetorch.bfloat16, # 显存不够改 float16 device_mapauto # 多卡自动切分 ) model.eval() inputs tokenizer(你好请介绍一下你自己, return_tensorspt).to(model.device) with torch.no_grad(): out model.generate(**inputs, max_new_tokens64) print(tokenizer.decode(out[0], skip_special_tokensTrue))这段代码的关键在三个参数torch_dtype决定显存占用bf16 比 fp16 数值更稳但需要较新显卡device_mapauto让 accelerate 自动把层分到多张卡上单卡也能用max_new_tokens控制生成长度调试时先设小一点避免等太久。如果这一步报显存不足先降max_new_tokens再考虑量化。3.2 命令行对话入口怎么用inference/chat.py一般是个交互式循环读用户输入、拼对话模板、调 generate、打印回复。核心逻辑大致是# inference/chat.py 简化版 history [] while True: query input(User: ) if query.strip() in (exit, quit): break # 按 GLM-4 的对话格式拼接角色标记不能省 prompt build_chat_prompt(query, history) inputs tokenizer(prompt, return_tensorspt).to(model.device) outputs model.generate( **inputs, max_new_tokens512, do_sampleTrue, # 采样模式回复更自然 temperature0.7, top_p0.9, repetition_penalty1.1 # 防止复读 ) reply tokenizer.decode(outputs[0][inputs[input_ids].shape[1]:], skip_special_tokensTrue) print(Assistant:, reply) history.append((query, reply))build_chat_prompt是容易翻车的地方。GLM-4 有固定的角色标记格式类似[gMASK]sop|user|...|assistant|如果你自己拼字符串漏了标记模型会答非所问或者把用户的话复述一遍。血泪经验先用仓库自带的tokenizer.apply_chat_template如果有生成一次打印出来对照别手写。do_sampleTrue配合temperature和top_p是采样三件套。做事实问答时把temperature调到 0.10.3做创意写作再放到 0.8 以上。repetition_penalty超过 1.2 容易让句子变得生硬1.1 左右比较稳。3.3 起一个 OpenAI 兼容接口inference/api_server.py通常基于 FastAPI 或 Flask把模型包成/v1/chat/completions接口方便现有前端或 LangChain 类框架直接接。启动方式一般是python inference/api_server.py --model_path ./weights/glm4-base --port 8000 --host 0.0.0.0服务端核心是把请求体里的messages转成对话模板再走 generatefrom fastapi import FastAPI from pydantic import BaseModel app FastAPI() class ChatRequest(BaseModel): messages: list temperature: float 0.7 max_tokens: int 512 app.post(/v1/chat/completions) def chat(req: ChatRequest): prompt build_chat_prompt_from_messages(req.messages) inputs tokenizer(prompt, return_tensorspt).to(model.device) outputs model.generate( **inputs, max_new_tokensreq.max_tokens, temperaturereq.temperature, do_samplereq.temperature 0 ) text tokenizer.decode(outputs[0][inputs[input_ids].shape[1]:], skip_special_tokensTrue) return {choices: [{message: {role: assistant, content: text}}]}注意do_sample和temperature的联动temperature 为 0 时应该关采样走贪心否则某些 transformers 版本会警告甚至报错。另外这个接口是同步阻塞的并发上来会排队生产环境得换成流式输出加异步队列仓库里的示例一般只做到“能调通”的程度。4. 微调链路拆解SFT 与 LoRA 怎么接4.1 数据格式与 dataset.py微调第一步不是改模型是看finetune/dataset.py期望什么格式。常见的是 JSONL每行一条对话{messages: [{role: user, content: 帮我写个冒泡排序}, {role: assistant, content: def bubble_sort(arr): ...}]}dataset.py里会做三件事读 JSONL、用 tokenizer 的 chat template 拼成一条序列、把 assistant 部分之外的 token 的 label 设成 -100不计算损失。这段逻辑如果写错模型会学着去预测用户的问题训练 loss 降得很快但效果很差。检查方法随机抽一条样本把labels里非 -100 的部分 decode 出来应该只有 assistant 的回复。# 关键只对 assistant 回复计算 loss input_ids tokenizer(prompt response).input_ids prompt_len len(tokenizer(prompt).input_ids) labels [-100] * prompt_len input_ids[prompt_len:]4.2 LoRA 微调脚本参数train_lora.py是大多数人会用的入口因为全量微调显存吃不消。典型启动命令python finetune/train_lora.py \ --model_path ./weights/glm4-base \ --data_path ./data/sft.jsonl \ --output_dir ./output/lora-v1 \ --lora_r 16 \ --lora_alpha 32 \ --lora_dropout 0.05 \ --learning_rate 2e-4 \ --num_train_epochs 3 \ --per_device_train_batch_size 2 \ --gradient_accumulation_steps 8 \ --max_seq_length 2048lora_r是低秩矩阵的秩16 是常用起点任务越复杂可以往上加但显存也涨lora_alpha一般设成2 * rlearning_rate在 LoRA 场景下比全量微调大一个量级2e-4 到 5e-4 都常见。gradient_accumulation_steps是显存不够时的后悔药——batch_size 设 2、累积 8 步等效 batch 就是 16。训练完output_dir里只有 adapter 权重几十 MB不是完整模型。推理时要先加载 base 再挂 adapterfrom peft import PeftModel base Glm4ForCausalLM.from_pretrained(model_path, torch_dtypetorch.bfloat16) model PeftModel.from_pretrained(base, ./output/lora-v1) model model.merge_and_unload() # 合并后推理更快merge_and_unload把 LoRA 权重融进 base省掉推理时的额外计算但合并后就没法再单独调 adapter 了建议保留原始 adapter 目录。4.3 训练过程看什么指标别只盯 loss。SFT 的 loss 降到 1 以下不代表模型变好可能只是过拟合。我一般会同时看训练 loss 是否平稳下降、每隔几百步用固定几条验证 prompt 生成一次看输出质量、显存是否稳定突然涨可能是某条样本超长没截断。max_seq_length一定要设超长样本不截断会直接 OOM。5. 避坑与排查这几个坑我替你踩过了5.1 现象import 就报 AttributeError原因transformers版本和仓库代码不匹配modeling_glm4.py调用了新版本删掉或改名的内部函数。解决严格按requirements.txt钉版本别用pip install -U。如果已经装乱pip install transformers4.40.0 --force-reinstall重来。5.2 现象生成结果全是重复句子或乱码原因对话模板拼错或者skip_special_tokens没开导致特殊标记混进输出。解决先打印拼好的 prompt 原文对照官方格式decode 时确认skip_special_tokensTrue检查 tokenizer 是否和权重配套不同版本 tokenizer 词表可能不同。5.3 现象多卡加载后只有一张卡在跑原因device_mapauto需要 accelerate 正确识别可见显卡或者环境变量CUDA_VISIBLE_DEVICES没设对。解决nvidia-smi确认卡数echo $CUDA_VISIBLE_DEVICES确认可见范围必要时显式传device_mapbalanced或手动指定每层设备。5.4 现象LoRA 训练 loss 不降原因学习率太小沿用了全量微调的 1e-5、数据 label 全被设成 -100、或者 adapter 没挂到正确的 target_modules 上。解决先确认 labels 有非 -100 部分再把学习率提到 2e-4 试跑 50 步看 loss 是否动。5.5 现象量化后输出质量断崖下跌原因量化脚本默认用了较激进的位宽如 4bit 全量化或者校准数据分布和实际场景差太远。解决先试 8bit 看质量是否可接受4bit 时优先量化线性层、保留 embedding 和 lm_head 高精度校准集用你自己的业务文本而不是通用语料。6. 二次开发改哪里、怎么验证拿到这套源码做二次开发改动点通常集中在三处对话模板、推理后端、微调数据管线。对话模板在tokenization_glm4.py或chat.py的build_chat_prompt里如果你要做多轮工具调用得在这里加 function call 的标记格式改完用固定几条 case 回归确认普通对话没被破坏。推理后端如果想换 vLLM 或 TensorRT-LLMmodeling_glm4.py里的 attention 实现要能对上最省事的做法是保留原模型定义、只把 generate 换成外部引擎的调用接口层不动。微调数据管线是最值得改的。dataset.py里加一个字段校验和长度过滤能省掉大量训练中途 OOM 的麻烦def filter_sample(sample, tokenizer, max_len2048): ids tokenizer.apply_chat_template(sample[messages]) if len(ids) max_len: return None # 超长直接丢别截断 assistant 回复 if not any(m[role] assistant for m in sample[messages]): return None # 没有回复的样本不能用于 SFT return sample验证方法我习惯分三层单条样本过一遍 tokenizer 看 label 对不对跑 20 步看 loss 是否在动训完用 10 条业务问题对比 base 和 adapter 的输出人工打分。三层都过再上量。改造点文件验证方式对话模板tokenization_glm4.py / chat.py打印 prompt 对照 多轮回归推理后端inference/api_server.py同输入对比新旧输出一致性数据过滤finetune/dataset.py抽样 decode labels量化策略tools/quantize.py量化前后同 prompt 质量对比最后说个习惯每次改完modeling_glm4.py或 tokenizer我都会先跑一个“最小冒烟脚本”——加载模型、生成 20 个 token、打印结果确认没崩再动别的。这个脚本不到 30 行但帮我省过好几次“改了半天发现是环境问题”的时间。希望这套拆法能帮你把这个 zip 包真正跑起来、改得动。本文还有配套的精品资源点击获取