开源探索时刻!在LLaMA-Factory上实现GLM-4和Qwen2的工具格式化 ...

打印 上一主题 下一主题

主题 838|帖子 838|积分 2514



众所周知,如今的大模子大多是利用通用数据练习得出,因此在不同场景和专业范畴的结果还有待改进。于是就衍生出了现如今广泛利用的微调技术,由于笔者如今地点的项目同样是与大模子打交道,也就不可避免地盯上了LLaMA-Factory。
那毕竟什么是LLaMA-Factory?我提出的PR实现了GLM-4和Qwen2的工具格式化以及工具抽取函数!



在此也附上PR链接:https://github.com/hiyouga/LLaMA-Factory/pull/4173

本篇文章让我们一起来详细了解一下如何实现~

一、什么是LLaMA-Factory?


LLaMA Factory是一个旨在遍及LLMs微调的框架,涵盖了当下主流的大模子百川、千问、LLaMA等等。其核心上风在于其灵活性与易用性。它不仅囊括了当前主流的练习技术,如天生式预练习、监督式微调(SFT)、基于人类反馈的强化学习(RLHF),以及直接偏好优化(DPO),还通过一个用户友好的界面,大幅降低了操作复杂度。无论是通过命令行还是直观的Web界面,用户都能轻松定制微调流程,即便编程履历有限也丝绝不构成障碍。

该框架已在GitHub上发布,并获得了24000+个Star。




二、发现题目


最近在利用LLaMA Factory的过程中我碰到了一个题目:

刚刚更新完代码后我需要测试一下GLM-4和Qwen2的工具调用能力,测试结果体现,只管更新已实施,这两款语言模子却未能命中任何工具。

就这个题目,我去看了formatter的实现,然后发现Qwen2的工具提示词汇仍旧残留着旧体系的痕迹——基于“react”,理论上它应当无缝对接,但现实却是事与愿违。更令人费解的是,Qwen2在回应中携带了工具的JSON信息,却未按常规定位在tool_calls对象内,而是意外地出如今相应的主体content之中,显然题目存在,debug模式启动!

断点打上开始调试这里的format和extract函数。对于GLM-4,这次新模子的工具提示词汇如今是由模子自己的tokenizer天生,区别于以往外部组装后进行embedding的做法。别的GLM-4的chat template也存在题目,对比输出中少了体系提示词`` special token;

对于Qwen2,本次新模子支持了多工具调用(单次任务返回多个tool call),之前的react extrac函数只能命中单个工具。

OK,至此题目都找到了。

三、解决方法


对于GLM-4,先将模子下到本地,写两个工具schema,用transformers加载tokenizer,之后调用tokenizer.apply_chat_template将工具过一遍tokenizer看一下输出长什么样子。

工具schema:
  1. tools = [
  2.         {
  3.             "type": "function",
  4.             "function": {
  5.                 "name": "get_current_weather",
  6.                 "description": "Get the current weather",
  7.                 "parameters": {
  8.                     "type": "object",
  9.                     "properties": {
  10.                         "location": {
  11.                             "type": "string",
  12.                             "description": "The city and state, e.g. San Francisco, CA",
  13.                         },
  14.                         "format": {
  15.                             "type": "string",
  16.                             "enum": ["celsius", "fahrenheit"],
  17.                             "description": "The temperature unit to use. Infer this from the users location.",
  18.                         },
  19.                     },
  20.                     "required": ["location", "format"],
  21.                 },
  22.             }
  23.         },
  24.         {
  25.             "type": "function",
  26.             "function": {
  27.                 "name": "calculate_gpa",
  28.                 "description": "Calculate the Grade Point Average (GPA) based on grades and credit hours",
  29.                 "parameters": {
  30.                     "type": "object",
  31.                     "properties": {
  32.                         "grades": {"type": "array", "items": {"type": "string"}, "description": "The grades"},
  33.                         "hours": {"type": "array", "items": {"type": "integer"}, "description": "The credit hours"},
  34.                     },
  35.                     "required": ["grades", "hours"],
  36.                 },
  37.             },
  38.         }
  39.     ]
复制代码

tokenizer:
  1. fromtransformers importAutoTokenizer
  2. tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH, trust_remote_code=True)
  3. messages = process_messages(messages, tools=tools, tool_choice=tool_choice)
  4. inputs = tokenizer.apply_chat_template(messages, add_generation_prompt=True, tokenize=False)
复制代码

输出:
  1. '[gMASK]<sop><|system|>\n你是一个名为 GLM-4 的人工智能助手。你是基于智谱AI训练的语言模型 GLM-4 模型开发的,你的任务是针对用户的问题和要求提供适当的答复和支持。\n\n## get_current_weather\n\n{\n "name": "get_current_weather",\n "description": "Get the current weather",\n "parameters": {\n "type": "object",\n "properties": {\n "location": {\n "type": "string",\n "description": "The city and state, e.g. San Francisco, CA"\n },\n "format": {\n "type": "string",\n "enum": [\n "celsius",\n "fahrenheit"\n ],\n "description": "The temperature unit to use. Infer this from the users location."\n }\n },\n "required": [\n "location",\n "format"\n ]\n }\n}\n在调用上述函数时,请使用 Json 格式表示调用的参数。\n\n## calculate_gpa\n\n{\n "name": "calculate_gpa",\n "description": "Calculate the Grade Point Average (GPA) based on grades and credit hours",\n "parameters": {\n "type": "object",\n "properties": {\n "grades": {\n "type": "array",\n "items": {\n "type": "string"\n },\n "description": "The grades"\n },\n "hours": {\n "type": "array",\n "items": {\n "type": "integer"\n },\n "description": "The credit hours"\n }\n },\n "required": [\n "grades",\n "hours"\n ]\n }\n}\n在调用上述函数时,请使用 Json 格式表示调用的参数。'
复制代码

之后开始分析输出的结构,起首是PRefix token `[gMASK]` 之后是system message token `<|system|>\n{{content}} ` balabala。分析之后开始组装,定义好体系提示词以及工具的后缀,以及提示词与工具之间的分隔符。组装好之后再次测试工具就会发现乐成返回了工具信息。

对于Qwen2,题目是多个工具导致正则无法命中,只需要修改正则规则即可。

原来的命中规则:
  1. regex = re.compile(r"Action:\s*([a-zA-Z0-9_]+).*?Action Input:\s*(.*)", re.DOTALL)
  2. action_match = re.search(regex, content)
复制代码

修改后的规则:
  1. regex = re.compile(r"Action:\s*([a-zA-Z0-9_]+)\s*Action Input:\s*({.*?})(?=\nAction:|\Z)", re.DOTALL)
  2. action_match = re.findall(regex, content)
复制代码

再次测试乐成返回多个工具列表。

至此该题目已经乐成解决了,我也向LLaMA-Factory提交了这个Pr,并且 LLaMA-Factory 目前也采取归并了该 PR。





说在末了

当今世界的开源盛况,不仅是技术创新与协作的生动体现,更是加速技术革新、拓宽应用边界的强盛引擎。一个又一个开源软件的爆火向我们证明了在共享与合作的土壤里,智慧能够更快地萌芽,技术也得以飞跃式发展。

神州数码云基地始终站在鼓励开源贡献的角度,积极倡导并践行开放共享的精神。我们能够看到更多云基地的小同伴们不再仅仅止步于业务的完成,而是不断拓展自己的能力,参加开源项目标探索中。

以本次PR的贡献者徐辉为例,短短一年的时间,已经乐成提交了6个PR,也希望有越来越多的小同伴们参与到开源中来,每一次贡献,无论巨细,都是推动技术进步不可或缺的一块基石。

不仅要做技术的探索者,更要成为开源的贡献者。

贡献者:徐辉| 后端开辟工程师

更多AI小知识欢迎关注“神州数码云基地”公众号,回复“AI与数字化转型”进入社群交流
版权声明:文章由神州数码武汉云基地团队实践整理输出,转载请注明出处。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

前进之路

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表