本文作为ChatGLM系列的第三篇,主要讲到ChatGLM3做出的优化与改进;也会补充ChatGLM2和ChatGLM3与GLM1的区别(这些内容在笔者的博客中确实存在遗漏)。
ChatGLM系列解析(一)—— ChatGLM开篇之作_chatglmforconditiongeneration-CSDN博客
ChatGLM系列解析(二)—— ChatGLM2_chatglm glm2-CSDN博客
个人认为ChatGLM3的技术核心特色是自研的AgentTuning、多模态能力CogVLM和独创的多阶段增强预训练方法和更丰富的训练数据。
在能力层面的特色可以总结4点:引入特定prompt,自闭环方式解决安全注入问题;增加模型‘函数调用’和‘agent 调用’能力;代码能力;能力对齐和安全对齐。
我们先来讲下技术核心特色——AgentTuning(其余核心技术后续更新)
一、AgentTuning
1.1 motivation
LLM是可以作为Agent的,在作为Agent时,起到完成任务规划、记忆和使用对应工具的作用,这需要细粒度的Prompt方法,又需要LLM自身具备强大的性能(上下文理解、推理等能力)。
现有针对LLM Agent能力的研究主要关注设计提示(如Prompt) or 构建框架(COT、TOT)来完成某一特定代理任务,而没有从根本上提升LLM自身的通用Agent能力(笔者的理解:外在依赖为主)。
还有一些工作专注于提升LLM在某些特定方面的能力,如代码编写、论文阅读等,这通常以牺牲其通用能力和泛化能力为代价。针对上述问题,清华大学和智谱AI提出了AgentTuning。
1.2 AgentTuning作用与两步走流程
AgentTuning是一种简单而通用的方法,既可以增强LLM的Agent能力,有可以同时保持其通用LLM能力。
对于一个Agent任务,LLM代理的‘交互轨迹’可以记录为多轮对话历史(u1,a1,…,un,an)。考虑到现有的对话模型通常包括两个角色,用户和模型,ui表示来自用户的输入,ai表示来自的响应模型。每个轨迹都有一个最终奖励r∈[0,1],反映了任务的完成情况。
AgentTuning,主要包含两个步骤:
1. 构建一个覆盖多种代理任务、包含高质量交互轨迹的轻量级指令调优数据集Agent_Instruction。该数据集包含1866个经过验证的代理交互轨迹。
(交互轨迹 = 多个人类指令 + 多个代理动作/反馈)
2. 采用 混合指令微调策略 将Agent_Instruction和来自通用领域的指令混合,并对LLM进行微调。论文中,使用AgentTuning对LLama2系列模型进行微调产生AgentLM。
该策略在增强代理能力同时,保持泛化能力。
补充:AgentLM在未见过的代理任务上表现出强大的性能,同时保持了在MMLU, GSM8K, HumanEval和MT-Bench等通用任务上的能力。作者还与GPT-3.5-turbo进行了比较,发现AgentLM-70B是第一个在代理任务上与之匹敌的开源模型。
1.3 构建 Agent Instruction
构建过程由三个阶段组成:指令构建、轨迹交互 和 轨迹过滤 。这个过程完全由 GPT-3.5 (gpt-3.5-turbo-0613) 和 GPT4 (gpt-4-0613) 自动完成,使得该方法可以很容易地扩展到新的代理任务。
1.3.1 指令构建
论文在六个现实世界场景相对容易收集指令的Agent任务中构建AgentConstruct数据集,包括AlfWorld、WebShop、Mind2Web、知识图、操作系统、数据库。
1.3.1.1 普通任务
对于普通/常见的Agent任务,可以直接从相似的数据集构造指令。
1.3.1.2 数据库任务
对于数据库任务,论文选择BIRD-SQL数据集中构建指令。该数据集仅用于是SELECT语句。
论文中做了两种任务派生(将SELECT任务扩展到INSERT等):
(1)第一种:首先,论文使用(BIRD问题, 每个BIRD子任务中的参考SQL语句)来构建轨迹;然后,使用参考SQL语句查询数据库来获取对应的输出,并将其作为Agent的答案;最后,让GPT-4结合上述信息补充Agent的想法(Thought)。通过这种方式,可以直接从BIRD数据集中生成正确的轨迹。
注:这样的合成过程决定了交互的轮数 / 对话的轮数,固定为2。
补充:在这里笔者认为,补充的这个想法等同于Thought这个概念,也就是COT中的T,我认为可以将其理解为Prompt的一环,不是很确定,请大家一起讨论下这个问题。
(2)第二种:通过构建指令来提高多样性。论文中把BIRD的问题作为Prompt向GPT-4请求,并收集其与数据库的交互轨迹。收集到轨迹后,执行参考SQL语句并将结果与来自GPT-4的结果进行比较,过滤掉错误的答案,只收集正确的轨迹。
1.3.1.3 操作系统任务
对于操作系统任务来所,由于难以在终端执行OS命令来获得指令,因此论文才用了Self-Instruct方法构建任务。
首先,提示(prompt)GPT-4提出(come up with)一些与操作系统相关的任务,并人工附上任务说明、参考解决方案和评估脚本。
然后,将任务发送给另一个GPT-4实例(求解器),推理并收集其执行轨迹。
最后,任务完成后,论文运行‘参考解决方案’,并使用评估脚本将其结果与GPT-4(求解器)的结果进行比较。收集‘参考解决方案’和‘求解器’给出相同答案的轨迹。
1.3.1.4 任务补充
a. 数据库任务+self-instruct,由于BIRD仅包含SELECT数据,论文采用类似的自我指导(self-instruct)方式构造了其他类型的数据库操作(INSERT、UPDATE和DELETE)。
b. BIRD数据集:该数据集中包含超过12751个独特的问题的SQL、95个大数据库,总大小为33.4GB;涵盖区块链、曲棍球、医疗保健和教育等超过37个专业领域。
1.3.2 轨迹交互
由于Agent任务对输出格式的严格要求,论文采用了1-shot评估方法。对于每项任务,都提供了一个完整的交互过程,从数据集中。(原论文就是这么写的,笔者不懂啊,读懂啊)
For each task, we provide a complete interaction process from the training set.
在这里有两个概念:交互过程、链式思维(CoT)原理,前者用于生成多轮推理交互。后者用于补充Thought,也就是推理思维。
1.3.2.1 交互过程
本章节,主要描述‘交互过程’包含哪些步骤;多轮交互何时停止;如果出现错误了应该这么办,这几个问题。
交互过程主要包含两个部分。
首先,论文给模型一个任务描述和一个成功的1次示例(吐槽一下,这难道不是Prompt?one-shot?)
然后,开始实际的交互(开始多轮对话和推理)。
a. 论文向模型提供当前指令和必要信息
b. 基于这些信息以及之前的反馈,模型形成Thought并采取Action
c. Action影响环境,环境随后提供反馈,包括可能的变更或新信息。
d. (a, b, c) 这个过程一直持续到模型达成目标或达到其令牌限制为止。
如果,模型连续三次输出相同的结果,我们视为重复/单调失败(repetitive failure)。笔者是这么理解的,因为一个完整的轨迹包含多对(Thought,Action),如果是重复的多对(Thought,Action),那么这条轨迹的意义就不大 或者 是脏数据 或者 是低质量数据。
如果,模型的输出格式错误,则使用BLUE指标将当前这条输出(格式错误)与所有可能的Action选项进行比较,并选择最接近的匹配项作为当前步的模型Action。笔者在这里觉得就挺好理解,格式错误嘛,就从格式正确的多个候选项里面,选择最接近的。
1.3.2.2 链式思维(CoT)补充轨迹解释,增强模型理解能力
链式思考(Chain-of-Thought, CoT)方法通过拆分子任务 + 逐步推理,显著增强了大型语言模型(LLMs)的推理能力。
因此,论文采用ReAct作为推理框架,该框架在生成最终动作之前输出对应的CoT解释(称为Thought)。因此,收集到的交互轨迹中的每个动作都伴随着详细的解释Trace,从而使模型能够学习到导致该动作的推理过程。对于通过任务推导生成但没有思考过程的轨迹,我们使用GPT-4为它们补充思考内容,以保持与ReAct提示的一致性。
1.3.3 轨迹过滤
这一步就很好理解了,提升数据质量。
论文中,直接根据每个‘交互轨迹’的奖励 r 自动选择高质量轨迹。因为Mind2Web任务比较难,所以论文在这里针对不同任务分开讨论。
除Mind2Web任务:直接选择 r = 1 的‘交互轨迹’,作为高质量数据;
Mind2Web任务:选择 r >= 2/3 的’交互轨迹‘,确保能够获得足够数量的轨迹。
1.3.4 总结
在经过:指令构建、轨迹交互、以及 轨迹过滤 ,这三步之后,获得了1866条数据。
1.4 指令微调
如上文中说到,论文采用 ‘混合指令微调策略’ 将Agent_Instruction和来自通用领域的指令混合,一起使用对LLM进行微调。
通用领域:研究表明,多样化的用户Prompt(指令)可以提高模型的性能。因此,论文从ShareGPT数据集选择了 57096个GPT-3.5会话 和 3670个GPT-4会话 。最终,从GPT-4回复的高质量数据中以 1 : 4 的比例抽取GPT-4和GPT-3.5的样本。
Agent任务:也就是在章节1.3中构建的1866条数据。
混合训练MIXTURE TRAINING:上述两类任务混合一起训练时,Agent任务和通用领域都有较好的表现;混合训练主要优化的损失函数如下:可以看到,这是一个类似交叉熵和Focal Loss的损失函数,需要设置Agent任务和通用领域任务在这个损失中的影响比例,结论是当超参数 设置为0.2时,模型在未见过的保留代理任务(held-out)中都表现了强大的性能。
二、补充
在本篇章ChatGLM3—AgentTuning中,额外补充一些关于模型架构的知识。
2.1 模型架构 + 细节
在模型架构方面,ChatGLM2与ChatGLM3保持了一致性,而相较于ChatGLM,它们的结构有所不同。因此,ChatGLM3并没有对ChatGLM2进行优化。
(1)可以看到GLM是encoder-decoder结构;而GLM2和GLM3是decoder-only结构;
(2)显著缩小了词表的大小,从ChatGLM的150528个词项缩减至65024个词项;
(3)在前馈网络中,ChatGLM使用GELU(高斯误差线性单元),而ChatGLM2和GLM3采用Swish-1;
(4)ChatGLM2和ChatGLM3引入了RMSNorm,而不是ChatGLM中的LayerNorm。
# ChatGLM2 / ChatGLM3
ChatGLMForConditionalGeneration(
(transformer): ChatGLMModel(
(embedding): Embedding(
(word_embeddings): Embedding(65024, 4096)
)
(rotary_pos_emb): RotaryEmbedding()
(encoder): GLMTransformer(
(layers): ModuleList(
(0-27): 28 x GLMBlock(
(input_layernorm): RMSNorm()
(self_attention): SelfAttention(
(query_key_value): Linear(in_features=4096, out_features=4608, bias=True)
(core_attention): CoreAttention(
(attention_dropout): Dropout(p=0.0, inplace=False)
)
(dense): Linear(in_features=4096, out_features=4096, bias=False)
)
(post_attention_layernorm): RMSNorm()
(mlp): MLP(
(dense_h_to_4h): Linear(in_features=4096, out_features=27392, bias=False)
(dense_4h_to_h): Linear(in_features=13696, out_features=4096, bias=False)
)
)
)
(final_layernorm): RMSNorm()
)
(output_layer): Linear(in_features=4096, out_features=65024, bias=False)
)
)
# ChatGLM
ChatGLMForConditionalGeneration(
(transformer): ChatGLMModel(
(word_embeddings): Embedding(150528, 4096)
(layers): ModuleList(
(0-27): 28 x GLMBlock(
(input_layernorm): LayerNorm((4096,), eps=1e-05, elementwise_affine=True)
(attention): SelfAttention(
(rotary_emb): RotaryEmbedding()
(query_key_value): Linear(in_features=4096, out_features=12288, bias=True)
(dense): Linear(in_features=4096, out_features=4096, bias=True)
)
(post_attention_layernorm): LayerNorm((4096,), eps=1e-05, elementwise_affine=True)
(mlp): GLU(
(dense_h_to_4h): Linear(in_features=4096, out_features=16384, bias=True)
(dense_4h_to_h): Linear(in_features=16384, out_features=4096, bias=True)
)
)
)
(final_layernorm): LayerNorm((4096,), eps=1e-05, elementwise_affine=True)
)
(lm_head): Linear(in_features=4096, out_features=150528, bias=False)
)
2.2 杂项:位置编码 + 端上小模型
位置编码:位置编码从ChatGLM中每个GLMBlock一份提升至全局一份,提高位置信息的利用效率;
小模型:ChatGLM3共提供了1.5B 和 3B的端上模型,这些模型特别优化了算法和结构,使其能够在资源受限的设备上高效运行。例如:ChatGLM3-1.5B在标准智能手机上的响应时间减少到仅300毫秒。
资料链接:
1. ShareGPT数据集(https://huggingface.co/datasets/anon8231489123/ShareGPT_Vicuna_unfiltered