首页 / 资讯中心 / 文章详情

ChatGLM3 对话格式全解析:special token 体系与 Tool / Code Interpreter 统一输入规范

ChatGLM3 对话格式全解析:special token 体系与 Tool / Code Interpreter 统一输入规范 ★ FEATURED ARTICLE
大模型AI Agent模型推理服务微调对话系统【免费下载链接】ChatGLM3ChatGLM3 series: Open Bilingual Chat LLMs | 开源双语对话语言模型项目地址https://gitcode.com/zai-org/ChatGLM3点击查看免费下载ChatGLM3 引入了一套全新的对话格式用|role|{metadata}形式的对话头统一承载多轮对话、工具调用Tool Agent与代码解释器Code Interpreter三类任务的输入从协议层面规避用户输入的注入攻击。本文将依据仓库根目录下的 PROMPT.md 完整讲解该格式的结构、角色规定与三类样例场景并结合 composite_demo 与 tools_using_demo 中的源码实现说明这套格式在真实工程中是如何被解析、拼装与消费的。读完本文你将能够手写或程序化构造任何符合 ChatGLM3 规范的对话输入。为什么 ChatGLM3 需要一套全新的对话格式传统大模型的对话通常把历史拼成一段可读文本把角色信息写进纯文本 prompt 中。这种做法的两个明显痛点促使 ChatGLM3 重新设计输入协议见 PROMPT.md 开篇防范用户输入注入攻击如果角色标记如用户/助手只是普通文本用户完全可以在自己的输入中伪造这些标记让模型把后续内容误认为系统指令或他人对话从而劫持模型行为。统一异构任务的输入Code Interpreter、Tool Agent 等任务各自有截然不同的输入形态需要一套统一的对话协议把它们表达成同一种结构化形式方便模型在训练与推理时保持一致的理解方式。ChatGLM3 的解法是把角色从文本层抽离到special token特殊 token层对话头中的|role|部分使用模型词表内的特殊 token 表示无法从文本形式被 tokenizer 编码因此用户输入无论怎么写都无法伪造出真正的角色切换标记而紧随其后的{metadata}部分则采用纯文本表示是可选的辅助信息。整体结构若干轮对话头 内容的序列ChatGLM3 的对话格式由若干轮对话组成每一轮对话包含一个对话头和一段内容。一个典型的多轮对话结构如下|system| You are ChatGLM3, a large language model trained by Zhipu.AI. Follow the users instructions carefully. Respond using markdown. |user| Hello |assistant| Hello, Im ChatGLM3. What can I assist you today?需要特别说明的是实际中每轮对话内容并不一定以换行符结尾上例及文档中的换行只是为了排版美观PROMPT.md 中有明确注释下同。在仓库的工程实现中这套角色 内容的序列正是被逐段拼装成最终 prompt 的。以 composite_demo/conversation.py 的preprocess_text为例def preprocess_text( system: str | None, tools: list[dict] | None, history: list[Conversation], ) - str: if tools: tools json.dumps(tools, indent4, ensure_asciiFalse) prompt f{Role.SYSTEM}\n prompt system if not tools else TOOL_PROMPT if tools: tools json.loads(tools) prompt json.dumps(tools, ensure_asciiFalse) for conversation in history: prompt f{conversation} prompt f{Role.ASSISTANT}\n return prompt可以看到系统头永远位于最前之后按顺序追加每一轮Conversation的序列化结果最后预留一个|assistant|头等待模型续写——这正是上文对话头 内容结构的直接代码映射。其中TOOL_PROMPTAnswer the following questions as best as you can. You have access to the following tools:\n在有工具时替代普通 system 文本对应工具调用场景的系统提示约定。对话头规范|role|{metadata}对话头独占完整的一行格式为|role|{metadata}|role|部分使用 special token 表示无法从文本形式被 tokenizer 编码用于防止注入攻击metadata部分采用纯文本表示为可选内容用于携带额外信息如工具名、interpreter标记。四种角色的使用规定如下PROMPT.md角色含义使用规定|system|系统信息设计上可穿插于对话中但目前规定仅可以出现在开头|user|用户不会连续出现多个来自|user|的信息|assistant|AI 助手在出现之前必须有一个来自|user|的信息|observation|外部的返回结果必须在|assistant|的信息之后这些约束在源码中同样有对应体现。composite_demo/conversation.py 中的Role枚举把角色与字符串一一对应class Role(Enum): SYSTEM auto() USER auto() ASSISTANT auto() TOOL auto() INTERPRETER auto() OBSERVATION auto() def __str__(self): match self: case Role.SYSTEM: return |system| case Role.USER: return |user| case Role.ASSISTANT | Role.TOOL | Role.INTERPRETER: return |assistant| case Role.OBSERVATION: return |observation|注意这里的细节工具调用与代码执行在模型输出侧复用的都是|assistant|头区别仅在于metadata不同分别是工具名与interpreter这正是对话头 角色 可选 metadata这一设计价值的体现。另外client.py 中stream_chat将|user|与|observation|对应的 special token 显式加入eos_token_ideos_token_id [tokenizer.eos_token_id, tokenizer.get_command(|user|), tokenizer.get_command(|observation|)]即模型生成到这些特殊 token 时会自动停止从底层保证了新的一轮必须由模型侧的角色头起头这一对话约束。样例场景一多轮对话普通对话场景有且仅有|user|、|assistant|、|system|三种 role完整的示例输入如下|system| You are ChatGLM3, a large language model trained by Zhipu.AI. Follow the users instructions carefully. Respond using markdown. |user| Hello |assistant| Hello, Im ChatGLM3. What can I assist you today?为提升可读性文档中的样例在表示角色的 special token 前额外添加了一个换行符实际使用及 tokenizer 实现中均无需额外添加这一换行。这一点在真实推理链路里可以验证无论 basic_demo/cli_demo.py 通过model.stream_chat(...)直接对话还是 composite_demo/demo_chat.py 通过client.generate_stream(...)流式对话prompt 的拼装都由 tokenizer 的build_chat_input见 client.py按对话记录统一完成开发者无需手工插入换行符。样例场景二工具调用工具调用场景在系统头中注入可用工具的 JSON 声明name / description / parameters模型在需要时输出带metadata即工具名的|assistant|头并在内容中用一段tool_call(...)形式的 Python 代码块表达参数外部系统执行后把结果以|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(locationbeijing, unitcelsius) |observation| {temperature: 22} |assistant| 根据查询结果今天北京的气温为 22 摄氏度。这套输入协议在仓库中有多个直接对应的实现工具声明格式composite_demo/demo_tool.py 中的EXAMPLE_TOOL与文档示例几乎一致额外为unit声明了enum并支持在页面的 Manual mode 下用 YAML 编写后经yaml.safe_load解析成同样的 dict 结构tools_using_demo/cli_demo_tool.py 则展示了多条工具的声明列表包括track、/text-to-speech、/image_resizer、/foodimg等。对话流驱动demo_tool.py 按|assistant|头识别工具调用把output_text的首行解析为工具名按|observation|头结束调用参数通过正则extract_code取出tool_call(...)代码块再经eval(code, {tool_call: tool_call}, {})求值得到 dict最终交给dispatch_tool(tool, args)执行真实工具。工具注册机制composite_demo/tool_registry.py 与 tools_using_demo/tool_register.py 提供register_tool装饰器函数名即工具名、docstring 即工具说明、参数用Annotated[typ, description, required]标注类型/描述/是否必填注册后自动生成工具描述并可通过dispatch_tool按名调用。CLI 侧的角色切换cli_demo_tool.py 以model.chat(...)的返回值是否为 dict 判断模型是否发起了工具调用进而把下一轮输入的角色切到observation等待用户喂入外部结果否则保持user。样例场景三代码执行代码执行场景共有|user|、|assistant|、|system|、|observation|四种 role且|assistant|的 metadata 只有interpreter。模型以interpreter为 metadata 输出待执行的 Python 代码块执行引擎返回的结果以|observation|形式回填文本结果用result包裹图片结果用[Image]占位模型再据此继续推理直到任务完成。完整的示例输入如下|system| 你是一位智能AI助手你叫ChatGLM3你连接着一台电脑但请注意不能联网。在使用Python解决任务时你可以运行代码并得到结果如果运行结果有错误你需要尽可能对代码进行改进。你可以处理用户上传到电脑上的文件文件默认存储路径是/mnt/data/。 |user| #File: /mnt/data/metadata.jsonl #Size: 35380 #File uploaded 文件中是否存在缺失值或异常值 |assistant| 首先我将读取您提供的文件并查看其内容以确定是否存在缺失值或异常值。 我们从加载文件开始 |assistant|interpreter python import json # Load the uploaded file data [] with open(/mnt/data/metadata.jsonl, r) as file: for line in file: data.append(json.loads(line)) # Display the first few records to get a sense of the data data[:5] |observation| result [{file_name: aceinthehole.png, name: Ace in the Hole, type: survivor, description: Lady Luck always seems to be throwing something good your way.}, {file_name: adrenaline.png, name: Adrenaline, type: survivor, description: You are fuelled by unexpected energy when on the verge of escape.}, {file_name: aftercare.png, name: Aftercare, type: survivor, description: Unlocks potential in ones aura reading ability.}, {file_name: agitation.png, name: Agitation, type: killer, description: You get excited in anticipation of hooking your prey.}, {file_name: alert.png, name: Alert, type: survivor, description: Your acute senses are on high alert.}] |assistant| 该文件看起来包含有关某些条目的元数据每个条目有以下字段 - file_name: 文件名称 - name: 名称 - type: 类型例如 survivor 或 killer - description: 描述 接下来我将检查这些字段是否存在缺失值。 |assistant|interpreter python # Check for missing values in each column missing_values {key: sum(1 for item in data if key not in item) for key in data[0].keys()} missing_values |observation| result {file_name: 0, name: 0, type: 0, description: 0} |assistant| 每个字段都没有缺失值。这意味着每个条目都完整。 接下来我们可以检查是否存在任何潜在的异常值。这通常需要更深入的分析和对数据的了解但我可以从一些基本的统计和分布开始进行检查。为了这样做我们可以查看“type”字段的值分布看看是否有任何意外的类别。 |assistant|interpreter python # Check the distribution of values in the type column type_distribution {key: sum(1 for item in data if item[type] key) for key in set(item[type] for item in data)} type_distribution |observation| result {survivor: 116, killer: 103} |assistant| “type”字段有两个值“survivor”和“killer”。其中“survivor”有116个条目而“killer”有103个条目。 从这个初步的检查中我们没有发现任何明显的异常值。 如果您有任何特定的标准或其他字段需要检查我可以为您提供更详细的分析。您还希望我检查什么呢 |user| 帮我画一个爱心 |assistant|interpreter python import numpy as np import matplotlib.pyplot as plt # 爱心形状的参数方程 def heart(t): x 16 * np.sin(t) ** 3 y 13 * np.cos(t) - 5 * np.cos(2 * t) - 2 * np.cos(3 * t) - np.cos(4 * t) return x, y t np.linspace(0, 2 * np.pi, 1000) x, y heart(t) plt.figure(figsize(6, 6)) plt.plot(x, y, colorred) plt.axis(equal) plt.axis(off) plt.show() |observation| result [Image] |assistant| 这是一个爱心形状。我使用了参数方程来描述这个形状并使用matplotlib进行了绘制。如果您有任何其他需求或问题请随时告诉我。 |user| # End这段示例还揭示了一个文件上传约定用户在提问前用#File: 路径、#Size: 字节数、#File uploaded三行声明已上传文件及其默认存储位置/mnt/data/模型据此在代码中直接读取。仓库的 composite_demo/demo_ci.py 为 Code Interpreter 模式预置了与之完全一致的中文系统提示你是一位智能AI助手你叫ChatGLM3……文件默认存储路径是/mnt/data/。在工程实现层面代码执行场景的对话流解析集中在 demo_ci.py遇到|assistant|special token 时把前一段文本按interpreter切分并以Role.INTERPRETER记录遇到|observation|时用extract_code取出代码块交由execute(code, get_kernel())执行executedemo_ci.py内部通过jupyter_client启动的CodeKernel即一个 Jupyter 内核见 demo_ci.py运行 Python并区分text/plain文本结果与image/png图片结果——图片被转成PIL.Image展示、在对话记录中仅存[Image]占位与文档示例的[Image]结果完全对应超长结果会被truncate_length默认 1024截断并追加[TRUNCATED]标记防止观察结果淹没模型输入上下文。从规范到工程对话格式的完整闭环把 PROMPT.md 的格式规范与 composite_demo 的实现对照起来可以看到一套完整的拼装—生成—解析—回填闭环拼装prompt 侧preprocess_textconversation.py按系统头 逐轮对话 预留 assistant 头的顺序拼出输入工具场景用TOOL_PROMPT替换系统文本并追加工具 JSON。Conversation.__str__conversation.py则精确复现{角色}{metadata}\n{内容}的对话头格式例如工具调用序列化为|assistant|{tool}\n{content}代码执行序列化为|assistant|interpreter\n{content}。生成模型侧stream_chatclient.py通过tokenizer.build_chat_input编码输入并把|user|、|observation|加入eos_token_id作为停止条件流式输出的每个 token 以是否形如|...|判定special属性client.py供上层按特殊 token 分流。解析与回填应用侧三种模式Chat / Tool / Code Interpreter见 composite_demo/main.py在生成循环中遇到|assistant|头即切换角色视角工具调用 / interpreter 代码执行遇到|observation|头即注入外部结果并以|user|头作为一轮对话的终点postprocess_textconversation.py在展示时剥离这些特殊 token、并把 LaTeX 分隔符\(、\[转换为$、$$以便前端渲染。小结ChatGLM3 对话格式的本质是用不可被文本伪造的 special token充当角色边界用可选的纯文本 metadata区分同一角色下的不同任务形态普通回复、工具调用、代码执行用|observation|统一承载一切外部结果。只要遵循以下三条主线就能构造出完全合规的 ChatGLM3 输入对话序列以|system|开头|user|与|assistant|交替出现|observation|紧随|assistant|之后工具调用在系统头注入 JSON 工具声明模型侧输出|assistant|{工具名}头 tool_call(...)代码块外部结果以|observation|回填代码执行在系统头声明可运行 Python、文件默认在/mnt/data/模型侧输出|assistant|interpreter头 Python 代码块执行结果文本或[Image]以|observation|回填。对照 composite_demo/conversation.py、composite_demo/client.py 与 composite_demo/demo_ci.py 的源码可以随时验证每一个格式细节在真实推理链路中的落点。赞分享大模型AI Agent模型推理服务微调对话系统【免费下载链接】ChatGLM3ChatGLM3 series: Open Bilingual Chat LLMs | 开源双语对话语言模型项目地址https://gitcode.com/zai-org/ChatGLM3点击查看免费下载相关推荐ChatGLM3 对话格式全解析基于 System / User / Assistant / Observation 的统一提示词规范ChatGLM3 对话格式全解析基于 System / User / Assistant / Observation 的统一提示词规范 本篇文章完整解读 Ch大模型人工智能微调本地部署AI AgentRAGChatGLM3 Chat Format 对话格式规范多轮对话、工具调用与代码执行全解析ChatGLM3 Chat Format 对话格式规范多轮对话、工具调用与代码执行全解析 导读 本文基于 ChatGLM3 官方 PROMPT_en.md 文大模型人工智能微调本地部署AI AgentRAGQwopus3.6-27B-v2-GGUF训练秘籍三阶段课程学习法全解析Qwopus3.6 27B v2 GGUF训练秘籍三阶段课程学习法全解析 Qwopus3.6 27B v2 GGUF是基于Qwen3.6 27B开发的推理增强创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?
咨询建站