ChatGLM3-6B 开源双语对话模型全栈实战指南:Prompt 格式、工具调用、API 部署与微调

原创2026-10-03 11:28:45355 阅读
文章标签:大模型人工智能微调本地部署AI AgentRAG

ChatGLM3-6B 开源双语对话模型全栈实战指南:Prompt 格式、工具调用、API 部署与微调

ChatGLM3 是智谱 AI 与清华大学 KEG 实验室联合发布的对话预训练模型系列,本指南以其开源代表模型 ChatGLM3-6B 为线索,系统梳理该模型在 README.md 及仓库各 Demo 子目录中沉淀的完整使用链路:从全新的 ChatGLM3 对话格式(PROMPT.md)与模型加载,到工具调用、代码解释器、OpenAI 兼容 API 部署,再到低成本部署与 LoRA / P-Tuning v2 微调。读完本文,你将能够在自己的硬件上完成模型的本地加载、多轮对话、工具调用、API 服务化与参数高效微调,并理解每一步背后的源码实现。

一、ChatGLM3 系列概览与模型选型

ChatGLM3-6B 是 ChatGLM3 系列中的开源对话模型,在保留前两代模型"对话流畅、部署门槛低"等特性的基础上,引入了三大升级方向:

  1. 更强大的基础模型:其基础模型 ChatGLM3-6B-Base 采用更多样的训练数据、更充分的训练步数和更合理的训练策略,在语义、数学、推理、代码、知识等角度的数据集上表现出 10B 以下基础模型中的领先性能。
  2. 更完整的功能支持:采用全新设计的 Prompt 格式,除正常多轮对话外,原生支持工具调用(Function Call)、代码执行(Code Interpreter)和 Agent 任务等复杂场景。
  3. 更全面的开源序列:除对话模型外,还开源了基础模型 ChatGLM3-6B-Base、长文本对话模型 ChatGLM3-6B-32K 与 ChatGLM3-6B-128K。

模型列表与序列长度

Model Seq Length 说明
ChatGLM3-6B 8k 对话模型,支持工具调用,本指南核心对象
ChatGLM3-6B-Base 8k 基础模型,不支持工具调用
ChatGLM3-6B-32K 32k 长文本对话模型
ChatGLM3-6B-128K 128k 进一步强化长文本理解能力

注意:工具调用能力目前仅 ChatGLM3-6B 支持,Base 与 32K 模型不支持(见 tools_using_demo/README.md)。所有权重对学术研究完全开放,在填写问卷登记后亦允许免费商业使用,但需遵守 MODEL_LICENSE 开源协议。

评测结果要点

README 中给出了基于 ChatGLM3-6B-Base 在 8 个中英文典型数据集上的评测(GSM8K 72.3、MATH 25.7、BBH 66.1、MMLU 61.4、C-Eval 69.0、CMMLU 67.5、MBPP 52.4、AGIEval 53.7,均为 0-shot 或 0-shot CoT 设置,BBH 为 3-shot),并在 LongBench 上对比 ChatGLM2-6B-32K(平均 41.5)提升至 50.2,长文本场景(论文阅读、文档摘要、财报分析)人工评估效果平均提升超 50%。这些数据可在 README 原文核对,可作为选型参考,但具体表现依任务与硬件而异。

二、环境安装与代码调用

2.1 安装仓库与依赖

git clone https://github.com/THUDM/ChatGLM3
cd ChatGLM3
pip install -r requirements.txt

为了保证 torch 版本正确,请严格按照 PyTorch 官方文档的说明安装(不同 CUDA 版本对应不同 wheel)。仓库根目录的 requirements.txt 覆盖了基础 Demo 依赖,不同子目录(如 composite_demo/requirements.txt、finetune_demo/requirements.txt)还有各自独立的依赖清单。

2.2 一行代码加载模型

from transformers import AutoTokenizer, AutoModel

tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm3-6b", trust_remote_code=True)
model = AutoModel.from_pretrained("THUDM/chatglm3-6b", trust_remote_code=True, device='cuda')
model = model.eval()

response, history = model.chat(tokenizer, "你好", history=[])
print(response)
# 你好👋!我是人工智能助手 ChatGLM3 - 6B, 很高兴见到你, 欢迎问我任何问题。

response, history = model.chat(tokenizer, "晚上睡不着应该怎么办", history=history)
print(response)

需要 trust_remote_code=True,因为 ChatGLM3 的模型实现(modeling_chatglm.py)由 Hugging Face Hub 远程加载。model.chat 会自动维护多轮 history,并将对话转换为 ChatGLM3 专用格式后送进模型。

2.3 从本地加载模型

以上代码会由 transformers 自动下载模型实现与参数。网络较差时,可先通过 Git LFS 下载到本地:

git clone https://huggingface.co/THUDM/chatglm3-6b

然后改为从本地路径加载(例如 AutoModel.from_pretrained("your local path", trust_remote_code=True))。HuggingFace 下载慢时,也可以从 ModelScope 下载同款权重。

三、ChatGLM3 对话格式(Prompt 格式)详解

这是 ChatGLM3 区别于前两代模型的关键设计。PROMPT.md 指出,为避免用户输入的注入攻击,并统一 Code Interpreter、Tool 与 Agent 任务的输入,ChatGLM3 采用全新对话格式。

3.1 整体结构与对话头

一段对话由若干"对话头 + 内容"组成:

<|system|>
You are ChatGLM3, a large language model trained by Zhipu.AI. Follow the user's instructions carefully. Respond using markdown.
<|user|>
Hello
<|assistant|>
Hello, I'm ChatGLM3. What can I assist you today?

对话头占完整一行,格式为 <|role|>{metadata}。其中 <|role|> 部分使用 special token 表示,无法从文本形式被 tokenizer 编码,从而防止注入;metadata 部分为可选的纯文本。角色规定如下:

  • <|system|>:系统信息,设计上可穿插于对话中,但目前规定仅可出现在开头;
  • <|user|>:用户,不会连续出现多个;
  • <|assistant|>:AI 助手,出现前必须有一个来自 <|user|> 的信息;
  • <|observation|>:外部返回结果,必须在 <|assistant|> 的信息之后。

3.2 多轮对话样例

有且仅有 <|user|>、<|assistant|>、<|system|> 三种 role(结构与 3.1 相同,这里不再重复)。

3.3 工具调用格式

工具调用场景下,system prompt 中携带工具 JSON 描述,模型通过带 metadata 的 assistant 行发起工具调用,随后以 <|observation|> 回传结果:

<|system|>
Answer the following questions as best as you can. You have access to the following tools:
[
    {
        "name": "get_current_weather",
        "description": "Get the current weather in a given location",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "The city and state, e.g. San Francisco, CA",
                },
                "unit": {"type": "string"},
            },
            "required": ["location"],
        },
    }
]
<|user|>
今天北京的天气怎么样?
<|assistant|>
好的,让我们来查看今天的天气
<|assistant|>get_current_weather
```python
tool_call(location="beijing", unit="celsius")

<|observation|> {"temperature": 22} <|assistant|> 根据查询结果,今天北京的气温为 22 摄氏度。


可以看到,模型输出 `tool_call(...)` 形式的函数调用代码块,工具名作为 assistant 的 metadata 出现。这套约定正是 <a href="https://link.gitcode.com/i/7c808807abd4d44c52c8a75ea6463cf3" target="_blank">tools_using_demo</a> 与 API 服务器中工具调用解析逻辑的底层依据。

### 3.4 代码执行(Code Interpreter)格式

代码执行场景加入 `<|observation|>` 角色,且 `<|assistant|>` 的 metadata 为 `interpreter`。模型输出 Python 代码块,执行结果以 `<|observation|>` 返回(如 `<a href="https://link.gitcode.com/i/2f60f95c1e930021aedf9bd4198518ae" target="_blank">Image]`、`result` 代码块等),模型据此继续生成。完整示例在 [PROMPT.md</a> 中给出(包含文件读取、缺失值检查、绘制爱心等完整流程),可直接对照。

## 四、快速上手:三种开箱即用的 Demo

### 4.1 综合 Demo(Chat / Tool / Code Interpreter 三合一)

仓库提供了集成三种功能的 Streamlit 综合 Demo,使用说明见 <a href="https://link.gitcode.com/i/da3dc5ae0ff52954e5a4556bb94db1a4" target="_blank">composite_demo/README.md</a>:

```bash
conda create -n chatglm3-demo python=3.10
conda activate chatglm3-demo
pip install -r requirements.txt
# 使用 Code Interpreter 还需安装 Jupyter 内核
ipython kernel install --name chatglm3-demo --user

streamlit run main.py
  • 通过 export MODEL_PATH=/path/to/model 指定本地模型,export IPYKERNEL=<kernel_name> 自定义 Jupyter 内核;
  • 三种模式:Chat(侧边栏可调 top_p、temperature、System Prompt)、Tool(通过 tool_registry.py 注册工具)、Code Interpreter(在 Jupyter 环境中执行代码完成复杂任务,只需描述任务即可,模型会连续执行多个代码块直至完成);
  • 工具注册只需用 @register_tool 装饰函数,函数名即工具名、docstring 即工具说明,参数用 Annotated[typ, description, required] 标注:
@register_tool
def get_weather(
    city_name: Annotated[str, 'The name of the city to be queried', True],
) -> str:
    """
    Get the weather for `city_name` in the following week
    """
    ...
  • 额外技巧:生成时可点右上角 Stop 打断;刷新页面清空对话记录;Manual mode 下可用 YAML 直接指定工具列表(需手动回填工具输出)。

4.2 网页版对话 Demo

python web_demo_gradio.py
streamlit run web_demo_streamlit.py

运行后输出 Web Server 地址,浏览器打开即可使用。经项目测试,Streamlit 版更流畅。

4.3 命令行对话 Demo

运行 basic_demo/cli_demo.py:

python cli_demo.py

程序在命令行中交互式对话,输入 clear 清空历史,输入 stop 终止。源码中通过 model.stream_chat(..., top_p=1, temperature=0.01, return_past_key_values=True) 流式生成,并复用 past_key_values 加速多轮推理;也支持 MODEL_PATH / TOKENIZER_PATH 环境变量指定本地模型,注释中提示 int4 量化需在 .eval() 前加 .quantize(bits=4, device="cuda").cuda() 且必须使用 cuda。

五、工具调用(Function Call)实战

工具调用的完整方法见 tools_using_demo/README.md,同时仓库提供了两个可运行示例:tools_using_demo/cli_demo_tool.py(命令行版)与 tools_using_demo/openai_api_demo.py(API 版)。

5.1 构建 System Prompt

工具定义采用与 3.3 一致的 JSON 结构,确保格式一致可获得最优性能:

tools = [
    {
        "name": "track",
        "description": "追踪指定股票的实时价格",
        "parameters": {
            "type": "object",
            "properties": {
                "symbol": {"description": "需要追踪的股票代码"}
            },
            "required": ['symbol']
        }
    },
    {
        "name": "text-to-speech",
        "description": "将文本转换为语音",
        "parameters": {
            "type": "object",
            "properties": {
                "text": {"description": "需要转换成语音的文本"},
                "voice": {"description": "要使用的语音类型(男声、女声等)"},
                "speed": {"description": "语音的速度(快、中等、慢等)"}
            },
            "required": ['text']
        }
    }
]
system_info = {"role": "system", "content": "Answer the following questions as best as you can. You have access to the following tools:", "tools": tools}

5.2 提出问题并解析工具调用请求

注意:目前 ChatGLM3-6B 的工具调用只支持 chat 方法,不支持 stream_chat 方法。

history = [system_info]
query = "帮我查询股票10111的价格"
response, history = model.chat(tokenizer, query, history=history)
print(response)
# {"name": "track", "parameters": {"symbol": "10111"}}

返回为 JSON 字典,表示模型需要调用工具 track 并传入参数 symbol。

5.3 调用工具并以 observation 回传

自行实现工具调用逻辑后,将结果以 JSON 格式、以 role="observation" 回传(此参数不能省略):

result = json.dumps({"price": 12412}, ensure_ascii=False)
response, history = model.chat(tokenizer, result, history=history, role="observation")
print(response)
# 根据您的查询,经过API的调用,股票10111的价格是12412。

对于复杂问题,模型可能进行多次工具调用。判断依据:当返回的 response 是 dict 时表示工具调用请求(继续执行工具并回传 observation),是 str 时表示最终回复(流程结束)。这一"chat 返回 dict/str 双形态"的设计,在 openai_api_demo/utils.py 的 process_response 中也有体现。

六、OpenAI / ZhipuAI 兼容 API 部署

仓库提供了 OpenAI / ZhipuAI 格式的开源模型 API 部署代码,可作为任意基于 ChatGPT 的应用后端,核心实现为 openai_api_demo/api_server.py,基于 FastAPI + uvicorn。

6.1 启动服务

cd openai_api_demo
python api_server.py

服务默认监听 0.0.0.0:8000。源码要点:

  • 模型路径可通过环境变量 MODEL_PATH / TOKENIZER_PATH(默认 THUDM/chatglm3-6b)指定;Embedding 模型通过 EMBEDDING_PATH(默认 BAAI/bge-m3)指定;
  • 提供三个核心端点:/v1/models(列出 chatglm3-6b)、/v1/chat/completions(对话补全,支持流式与普通模式、工具调用)、/v1/embeddings(文本向量化,仅支持单 GPU);
  • 显存需求:约 14–15GB(2GB Embedding 模型 + 12–13GB FP16 LLM);
  • Token 限制提醒:OpenAI API 中的 max_tokens 等价于 HuggingFace 的 max_new_tokens 而非 max_length,例如对 6B 模型设置 8192 会因历史与提示词占位而报错;
  • 默认未注册任何工具,若需流式工具调用,可参照 tools_using_demo 实现 dispatch_tool(tool_name, tool_params) 并接入 create_chat_completion 的 function_call 分支;
  • 流式工具调用采用"先判定前 7 个字符是否包含 get_ 前缀"的启发式判断(见 contains_custom_function,源码注释明确说明这不严谨、仅供参考)。

6.2 使用 Curl 测试

chat 补全测试:

curl -X POST "http://127.0.0.1:8000/v1/chat/completions" \
-H "Content-Type: application/json" \
-d "{\"model\": \"chatglm3-6b\", \"messages\": [{\"role\": \"system\", \"content\": \"You are ChatGLM3, a large language model trained by Zhipu.AI. Follow the user's instructions carefully. Respond using markdown.\"}, {\"role\": \"user\", \"content\": \"你好,给我讲一个故事,大概100字\"}], \"stream\": false, \"max_tokens\": 100, \"temperature\": 0.8, \"top_p\": 0.8}"

标准 OpenAI 接口 agent-chat 测试(携带 tools 定义):

curl -X POST "http://127.0.0.1:8000/v1/chat/completions" \
-H "Content-Type: application/json" \
-d "{\"model\": \"chatglm3-6b\", \"messages\": [{\"role\": \"user\", \"content\": \"37乘以8加7除2等于多少?\"}], \"tools\": [{\"name\": \"track\", \"description\": \"追踪指定股票的实时价格\", \"parameters\": {\"type\": \"object\", \"properties\": {\"symbol\": {\"description\": \"需要追踪的股票代码\"}}, \"required\": []}}, {\"name\": \"Calculator\", \"description\": \"数学计算器,计算数学问题\", \"parameters\": {\"type\": \"object\", \"properties\": {\"symbol\": {\"description\": \"要计算的数学公式\"}}, \"required\": []}}], \"stream\": true, \"max_tokens\": 100, \"temperature\": 0.8, \"top_p\": 0.8}"

6.3 自定义工具的自主动调度(Agent)

OpenAI 风格的自定义工具箱自主调度接口:实现 openai_api_demo/tools/schema.py 中的工具描述脚本,并将 api_server.py 中的 AGENT_CONTROLLER 指定为 'true',即可获得:

curl -X POST "http://127.0.0.1:8000/v1/chat/completions" \
-H "Content-Type: application/json" \
-d "{\"model\": \"chatglm3-6b\", \"messages\": [{\"role\": \"user\", \"content\": \"37乘以8加7除2等于多少?\"}], \"stream\": true, \"max_tokens\": 100, \"temperature\": 0.8, \"top_p\": 0.8}"

该接口具有调度异常的自处理回复能力,无需另外实现调度算法,且用户无需 api_key。

6.4 使用 Python 脚本测试

cd openai_api_demo
python openai_api_request.py

测试成功时模型应返回一段故事。README 中同样给出了 ZhipuAI 测试脚本入口(zhipu_api_request.py)。

6.5 LangChain 集成

仓库的 langchain_demo 展示了如何把 ChatGLM3 接入 LangChain 生态:ChatGLM3.py 封装了模型调用,main.py 演示串联,tools 目录预置了 Calculator.py、Weather.py、DistanceConversion.py 三个工具,可直接与 5.1 的工具 JSON 定义配合使用。

七、低成本部署

7.1 模型量化

默认 FP16 精度加载约需 13GB 显存;显存有限时可 4-bit 量化加载:

model = AutoModel.from_pretrained("THUDM/chatglm3-6b", trust_remote_code=True).quantize(4).cuda()

量化会带来一定性能损失,但项目测试表明 4-bit 量化下仍能自然流畅生成。

7.2 CPU 部署

无 GPU 时可在 CPU 上推理(约需 32GB 内存,速度较慢):

model = AutoModel.from_pretrained("THUDM/chatglm3-6b", trust_remote_code=True).float()

7.3 Mac(Apple Silicon / AMD GPU)部署

安装 PyTorch-Nightly(版本号应为 2.x.x.dev2023xxxx 而非 2.x.x),目前 MacOS 仅支持从本地加载模型,并使用 mps 后端:

model = AutoModel.from_pretrained("your local path", trust_remote_code=True).to('mps')

加载半精度模型约需 13GB 内存;内存较小的机器(如 16GB MacBook Pro)空余内存不足时会使用硬盘虚拟内存,导致推理严重变慢。

7.4 多卡部署

单卡显存不足以容纳完整模型时,先安装 pip install accelerate,然后正常加载模型即可自动切分到多张 GPU。

7.5 专用推理加速方案

八、模型微调:全量 SFT / LoRA / P-Tuning v2

微调套件位于 finetune_demo,提供全量微调与 P-Tuning v2(LoRA 亦可通过 lora.yaml 配置使用),支持多轮对话与输入输出两种数据格式,并附有 lora_finetune.ipynb 示例。

8.1 硬件参考

默认配置下显存占用(仅供参考,随参数变化):SFT 全量微调 4 卡均分、每卡约 48346MiB;P-TuningV2 1 卡约 18426MiB;LoRA 1 卡约 14082MiB。项目仅在英伟达 Hopper(如 H100)与 Ampère(如 A100)架构上做过测试,其他架构可能出现训练问题、显存误差或推理效果差异。

8.2 数据格式

纯对话能力微调(仅微调对话能力;注意 step 较多时会削弱工具调用能力):

[
  {
    "conversations": [
      {"role": "system", "content": "<system prompt text>"},
      {"role": "user", "content": "<user prompt text>"},
      {"role": "assistant", "content": "<assistant response text>"}
    ]
  }
]

对话 + 工具能力微调(tools 字段会被 json.dumps(..., ensure_ascii=False) 自动格式化为首条 system prompt,无需手动插入):

[
  {
    "tools": [],
    "conversations": [
      {"role": "system", "content": "<system prompt text>"},
      {"role": "user", "content": "<user prompt text>"},
      {"role": "assistant", "content": "<assistant thought to text>"},
      {
        "role": "tool",
        "name": "<name of the tool to be called>",
        "parameters": {"<parameter_name>": "<parameter_value>"},
        "observation": "<observation>"
      },
      {"role": "assistant", "content": "<assistant response to observation>"}
    ]
  }
]

要点:每种角色可附带 bool 类型 loss 字段控制是否参与 loss 计算(默认 system、user 不计算);tool 不是原生角色,预处理时会自动转化为带工具调用 metadata 的 assistant(默认计算 loss)与 observation(不计算 loss);目前未实现 Code Interpreter 微调;system 为可选角色但必须位于 user 之前且每条对话只能出现一次。微调数据必须同时包含训练集与验证集(测试集可缺省或直接用验证集代替)。

8.3 配置文件

配置位于 finetune_demo/configs:ds_zero_2.json / ds_zero_3.json 为 DeepSpeed 配置;lora.yaml / ptuning_v2.yaml / sft.yaml 为三种方式的模型与训练配置。关键参数:

  • data_config:train_file / val_file / test_file(数据集路径)、num_proc(加载数据进程数);
  • max_input_length / max_output_length:输入/输出序列最大长度;
  • training_args:output_dir、max_steps、per_device_train_batch_size、dataloader_num_workers、save_strategy / save_steps、logging_strategy / logging_steps、per_device_eval_batch_size、evaluation_strategy / eval_steps、predict_with_generate 等;
  • generation_config.max_new_tokens:生成的最大新 token 数;
  • peft_config:peft_type(如 LORA)、task_type(CAUSAL_LM);
  • LoRA 参数:r(秩)、lora_alpha(缩放因子)、lora_dropout(dropout 概率);
  • P-TuningV2 参数:num_virtual_tokens(虚拟 token 数量)。

8.4 启动微调

单机多卡 / 多机多卡(需安装 deepspeed):

cd finetune_demo
OMP_NUM_THREADS=1 torchrun --standalone --nnodes=1 --nproc_per_node=8  finetune_hf.py  data/AdvertiseGen/  THUDM/chatglm3-6b  configs/lora.yaml

单机单卡:

cd finetune_demo
python finetune_hf.py  data/AdvertiseGen/  THUDM/chatglm3-6b  configs/lora.yaml

从检查点继续微调:第四个参数传 yes(自动从最后一个 Checkpoint 继续)或断点号数字(如 600 从序号 600 的 Checkpoint 继续):

cd finetune_demo
python finetune_hf.py  data/AdvertiseGen/  THUDM/chatglm3-6b  configs/lora.yaml yes

8.5 使用微调后的模型

在 inference_hf.py 中验证:

python inference_hf.py your_finetune_path --prompt your prompt

在其他 Demo 中使用:LoRA 与 P-TuningV2 不合并模型,路径记录在 adapter_config.json(若原始模型位置变更需同步修改 base_model_name_or_path)。参照 finetune_demo/inference_hf.py 中的 load_model_and_tokenizer:若目录含 adapter_config.json 则用 AutoPeftModelForCausalLM.from_pretrained 加载,否则用 AutoModelForCausalLM.from_pretrained,再用该函数替换各 Demo 的模型加载方式即可。

8.6 微调排障提示

  1. 训练前会打印首条训练数据的 Sanity Check:每行依次为 detokenized string、token_id、target_id,-100 表示该 token 不参与 loss 计算;
  2. _prepare_model_for_training 会把可训练参数转为 torch.float32(默认开启;若 half 训练有问题可切回,显存可能增加);
  3. 若显存不足,可尝试将模型代码 modeling_chatglm.py 中 torch.utils.checkpoint.checkpoint 的 use_reentrant 改为 True;
  4. 微调后的模型可用任何支持 peft 加载的推理加速框架;
  5. 本仓库数据集格式与 ZhipuAI API 微调格式有差异:messages 对应本仓库 conversation 字段;API 的 jsonl 需改名 json。

九、常见问题与注意事项

  1. 模型输出准确性:ChatGLM3-6B 规模较小且受概率随机性影响,无法保证输出完全准确,且输出容易被用户输入误导;项目不承担开源模型及代码导致的数据安全、舆情风险或滥用风险,请遵守 MODEL_LICENSE 并避免将模型用于未经安全评估和备案的服务。
  2. 版本同步:所有模型最新更新会率先在 HuggingFace 发布,ModelScope 与 WiseModel 因未同步需要手动更新。
  3. 工具调用限制:目前仅支持 chat 方法;API 服务器的 contains_custom_function 用 get_ 前缀启发式判断工具调用,仅供演示参考。
  4. 部署门槛:FP16 约 13GB 显存(API 服务约 14–15GB),CPU 约 32GB 内存,量化与多卡可进一步降低成本;运行环境请以仓库 requirements.txt 与各子目录 requirements 为准。

至此,从模型选型、Prompt 格式理解、多形态 Demo、工具调用、API 服务化到低成本部署与微调的完整链路已全部打通,你可以在此基础上按需组合,构建自己的 ChatGLM3-6B 应用。

登录后查看全文
ChatGLM3