GLM-4 icon indicating copy to clipboard operation
GLM-4 copied to clipboard

使用llama-factory进行lora微调后,推理正常,但是tools调用异常

Open kaixindeyouxia opened this issue 1 year ago • 15 comments

System Info / 系統信息

操作系统=ubuntu20.04 显卡=4 x v100 model=glm-9b-chat python=3.11.8 llama-factory=0.8.3 transformers=4.43.3 vllm=0.5.3.post1

Who can help? / 谁可以帮助到您?

No response

Information / 问题信息

  • [ ] The official example scripts / 官方的示例脚本
  • [ ] My own modified scripts / 我自己修改的脚本和任务

Reproduction / 复现过程

通过llama-factory对glm-9b-chat模型进行lora微调,使用Supervised Fine-Tuning,主要是微调自我意识,然后将微调后的模型导出,修改GLM-4-main/basic_demo/openai_api_server.py文件,设置MODEL_PATH = '/opt/glm-9b-chat-lora',启动openai_api_server.py,通过接口正常的推理没有问题,一切正常 然后进行tool调用时报错,报错信息如下:

ERROR:    Exception in ASGI application
Traceback (most recent call last):
  File "/root/anaconda3/envs/glm/lib/python3.11/site-packages/uvicorn/protocols/http/httptools_impl.py", line 399, in run_asgi
    result = await app(  # type: ignore[func-returns-value]
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/anaconda3/envs/glm/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py", line 70, in __call__
    return await self.app(scope, receive, send)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/anaconda3/envs/glm/lib/python3.11/site-packages/fastapi/applications.py", line 1054, in __call__
    await super().__call__(scope, receive, send)
  File "/root/anaconda3/envs/glm/lib/python3.11/site-packages/starlette/applications.py", line 123, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/root/anaconda3/envs/glm/lib/python3.11/site-packages/starlette/middleware/errors.py", line 186, in __call__
    raise exc
  File "/root/anaconda3/envs/glm/lib/python3.11/site-packages/starlette/middleware/errors.py", line 164, in __call__
    await self.app(scope, receive, _send)
  File "/root/anaconda3/envs/glm/lib/python3.11/site-packages/starlette/middleware/cors.py", line 85, in __call__
    await self.app(scope, receive, send)
  File "/root/anaconda3/envs/glm/lib/python3.11/site-packages/starlette/middleware/exceptions.py", line 65, in __call__
    await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
  File "/root/anaconda3/envs/glm/lib/python3.11/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app
    raise exc
  File "/root/anaconda3/envs/glm/lib/python3.11/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
    await app(scope, receive, sender)
  File "/root/anaconda3/envs/glm/lib/python3.11/site-packages/starlette/routing.py", line 756, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/root/anaconda3/envs/glm/lib/python3.11/site-packages/starlette/routing.py", line 776, in app
    await route.handle(scope, receive, send)
  File "/root/anaconda3/envs/glm/lib/python3.11/site-packages/starlette/routing.py", line 297, in handle
    await self.app(scope, receive, send)
  File "/root/anaconda3/envs/glm/lib/python3.11/site-packages/starlette/routing.py", line 77, in app
    await wrap_app_handling_exceptions(app, request)(scope, receive, send)
  File "/root/anaconda3/envs/glm/lib/python3.11/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app
    raise exc
  File "/root/anaconda3/envs/glm/lib/python3.11/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
    await app(scope, receive, sender)
  File "/root/anaconda3/envs/glm/lib/python3.11/site-packages/starlette/routing.py", line 72, in app
    response = await func(request)
               ^^^^^^^^^^^^^^^^^^^
  File "/root/anaconda3/envs/glm/lib/python3.11/site-packages/fastapi/routing.py", line 278, in app
    raw_response = await run_endpoint_function(
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/anaconda3/envs/glm/lib/python3.11/site-packages/fastapi/routing.py", line 191, in run_endpoint_function
    return await dependant.call(**values)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/GLM-4-main/basic_demo/openai_api_server.py", line 369, in create_chat_completion
    output = await anext(predict_stream_generator)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/GLM-4-main/basic_demo/openai_api_server.py", line 453, in predict_stream
    async for new_response in generate_stream_glm4(gen_params):
  File "/opt/GLM-4-main/basic_demo/openai_api_server.py", line 206, in generate_stream_glm4
    inputs = tokenizer.apply_chat_template(messages, add_generation_prompt=True, tokenize=False)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/anaconda3/envs/glm/lib/python3.11/site-packages/transformers/tokenization_utils_base.py", line 1833, in apply_chat_template
    rendered_chat = compiled_template.render(
                    ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/anaconda3/envs/glm/lib/python3.11/site-packages/jinja2/environment.py", line 1304, in render
    self.environment.handle_exception()
  File "/root/anaconda3/envs/glm/lib/python3.11/site-packages/jinja2/environment.py", line 939, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<template>", line 1, in top-level template code
TypeError: can only concatenate str (not "NoneType") to str

Expected behavior / 期待表现

是我微调的问题吗,希望微调后能实现原来glm-9b-chat的tool调用能力

kaixindeyouxia avatar Aug 26 '24 09:08 kaixindeyouxia

不支持Function Call 功能,因为 vLLM 官方仓库统一没有支持该功能(无论何种模型)

zhipuch avatar Aug 27 '24 01:08 zhipuch

不支持Function Call 功能,因为 vLLM 官方仓库统一没有支持该功能(无论何种模型)

我用的GLM-4-main/basic_demo/openai_api_server.py脚本,原始模型支持Function Call,微调后就不支持了,这是怎么回事

kaixindeyouxia avatar Aug 27 '24 02:08 kaixindeyouxia

GLM4中openai的demo底座是vllm,vllm不支持Function Call https://zhipu-ai.feishu.cn/wiki/VpncwoWn4i2ZsDkWSqYcbtwSnWd

zhipuch avatar Aug 27 '24 03:08 zhipuch

但是原始模型使用openai_api_server.py是支持function call的啊,为什么微调后,再用openai_api_server.py就不支持了,如果想要支持,我需要改哪些。

kaixindeyouxia avatar Aug 27 '24 08:08 kaixindeyouxia

v100不支持bf16,微调只能用bf16进行

zhipuch avatar Aug 27 '24 09:08 zhipuch

v100支持bf16,我微调成功了

kaixindeyouxia avatar Aug 28 '24 01:08 kaixindeyouxia

截屏2024-08-28 10 39 27 这是英伟达官方给出的,v100在计算的时候可能是用fp32来模拟bf16

zhipuch avatar Aug 28 '24 02:08 zhipuch

那你的意思是微调的时候选择fp32或者fp16?

kaixindeyouxia avatar Aug 28 '24 02:08 kaixindeyouxia

那你的意思是微调的时候选择fp32或者fp16?

微调的时候最好是bf16,fp16可能会出现溢出问题,推理的时候fp16可以成功运行,但也会有很小概率溢出,fp32的话相对这两个精度会慢,资源消耗也会大

zhipuch avatar Aug 28 '24 05:08 zhipuch

其实我想要的是微调后仍然能通过openai_api_server.py支持function call

kaixindeyouxia avatar Aug 28 '24 05:08 kaixindeyouxia

其实我想要的是微调后仍然能通过openai_api_server.py支持function call

请问你这问题解决了吗,我使用llama-factory,显卡是4090并采用bf16精度微调工具,也是报错这个

243006306 avatar Sep 12 '24 03:09 243006306

问题没有解决,总感觉哪里有问题,但是glm的人也不给实质性的回答。我在哔哩哔哩上问过别人,那个人说他也遇到这个问题,解决不了就放弃使用function call了。

kaixindeyouxia avatar Sep 19 '24 06:09 kaixindeyouxia

问题没有解决,总感觉哪里有问题,但是glm的人也不给实质性的回答。我在哔哩哔哩上问过别人,那个人说他也遇到这个问题,解决不了就放弃使用function call了。

你没“复习”,“遗忘也正常”。 微调是会调整内部参数权重,训练数据要有你新增的数据集,也要有你期望要保留功能的数据集。然后,保留功能的数据集,占比还要比你新增的数据集多很多。

上面说的,是我看到glm的人,在chatglm和 glm 项目,有回复过。意思就是上面的那样。 微调后,会遗忘。不想遗忘原来的,在微调时,就需要学习少量新的 + 大量复习旧的。

mingyue0094 avatar Sep 23 '24 21:09 mingyue0094

我微调后,个人的看法是, 个人 会把 开源的 5+5+5+7+6+4 这样的多边形战士。调整后,多半会变成 7+2+3+5 的多边形战士。调的好的可以做到 10+2+3+5 的多边形战士。

mingyue0094 avatar Sep 23 '24 21:09 mingyue0094

我微调后,个人的看法是, 个人 会把 开源的 5+5+5+7+6+4 这样的多边形战士。调整后,多半会变成 7+2+3+5 的多边形战士。调的好的可以做到 10+2+3+5 的多边形战士。

我们这个问题不是说的微调没效果,我们的问题是微调后只要Agent触发函数调用就会报错

243006306 avatar Sep 24 '24 01:09 243006306

+1

305607610 avatar Oct 15 '24 07:10 305607610

@kaixindeyouxia 环境版本: vllm=0.5.3 transformers=4.44.0 我的建议是,如果想用glm4-9b-chat+lora微调+工具调用,可以在openai_api_server.py用lora_request传递lora微调模型,运行openai_api_server.py,这样就可以两者兼得。(我是用langchain那套方法测试工具调用的)

如果用命令行启动vllm serve服务,vllm不支持工具调用,但是它并发推理是真的快。还有个问题,我用命令行参数传递lora模型,貌似也不起作用,不知道为什么。

如果是llama-factory训练lora之后将lora和glm4-9b-chat进行merge,合并之后的模型运行openai_api_server.py调用工具,会有报错。 [(https://github.com/THUDM/GLM-4/issues/607)]

Jimmy-L99 avatar Oct 24 '24 08:10 Jimmy-L99

我成功复现你的问题了,问题出现在template模版上,llama-factory到处merge后的模型文件时,替换了glm-4-9b-chatchat_template 目前的解决方案是修改llama-factory微调merge后权重的tokenizer_config.json文件,替换chat_template 为:

  "chat_template": "[gMASK]<sop>{% for item in messages %}{% if item['tools'] is defined %}<|system|>\n你是一个名为 GLM-4 的人工智能助手。你是基于智谱AI训练的语言模型 GLM-4 模型开发的,你的任务是针对用户的问题和要求提供适当的答复和支持。\n\n# 可用工具{% set tools = item['tools'] %}{% for tool in tools %}{% if tool['type'] == 'function' %}\n\n## {{ tool['function']['name'] }}\n\n{{ tool['function'] | tojson(indent=4) }}\n在调用上述函数时,请使用 Json 格式表示调用的参数。{% elif tool['type'] == 'python' %}\n\n## python\n\n当你向 `python` 发送包含 Python 代码的消息时,该代码将会在一个有状态的 Jupyter notebook 环境中执行。\n`python` 返回代码执行的输出,或在执行 60 秒后返回超时。\n`/mnt/data` 将会持久化存储你的文件。在此会话中,`python` 无法访问互联网。不要使用 `python` 进行任何网络请求或者在线 API 调用,这些在线内容的访问将不会成功。{% elif tool['type'] == 'simple_browser' %}\n\n## simple_browser\n\n你可以使用 `simple_browser` 工具。该工具支持以下函数:\n`search(query: str, recency_days: int)`:使用搜索引擎进行查询并显示结果,可以使用 `recency_days` 参数控制搜索内容的时效性。\n`mclick(ids: list[int])`:获取一系列指定 id 的页面内容。每次调用时,须选择3-10个页面。选择多个角度的页面,同时尽可能选择可信任的信息来源。考虑到部分页面是无法加载的,你也可以多打开一些可能有用的页面而不用担心内容过多。\n`open_url(url: str)`:打开指定的 URL。\n\n使用 `【{引用 id}†{引用文本}】` 来引用内容。\n\n操作步骤:1. 使用 `search` 来获得信息列表; 2. 使用 `mclick` 来获取指定 ID 页面的内容; 3. 根据获得的内容进行回复。在回复中应当引用信息来源。\n 如果用户提供了 URL,也可以用 `open_url` 直接打开页面。\n如果初次搜索结果没有找到合适的信息,也可以再次使用 `search` 进行搜索。{% elif tool['type'] == 'cogview' %}\n\n## cogview\n\n如果用户的请求中包含了对图像的描述,你可以使用 `cogview` 来生成图像并展示给用户。你需要向 `cogview` 发送图像描述,规则:\n- 发送给 `cogview` 的消息必须使用英语。用户的中文描述必须完全翻译为英语。\n- 应当尽可能详细地描述图像生成的需求,需求描述约 100 英文单词。\n- 保持用户原始描述的意图。不要虚构内容或者没见过的人物。\n- 如无特殊说明,所在地为中国,持有中国立场并遵循中国社会主义价值观。{% endif %}{% endfor %}{% endif %}{% if item['content'] %}<|{{ item['role'] }}|>{{ item['metadata'] }}\n{{ item['content'] }}{% endif %}{% endfor %}{% if add_generation_prompt %}<|assistant|>{% endif %}",

重新执行python openai_api_server.py服务后,向服务器发送工具调用的请求即可。 随后我们将在LLaMA-Factory仓库中提交修复代码。 更多信息可以参考issue:https://github.com/THUDM/GLM-4/issues/607

sixsixcoder avatar Nov 07 '24 10:11 sixsixcoder

@sixsixcoder 非常感谢,改天我试试。

kaixindeyouxia avatar Nov 13 '24 01:11 kaixindeyouxia