THUDM / ChatGLM3

ChatGLM3 series: Open Bilingual Chat LLMs | 开源双语对话语言模型
Apache License 2.0
13.43k stars 1.56k forks source link

使用tools_using_demo的openai_api_demo报错,无法使用工具调用 #849

Closed April0809 closed 8 months ago

April0809 commented 8 months ago

System Info / 系統信息

Python3.10 CUDA12.1 ubuntu20.04

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

No response

Information / 问题信息

Reproduction / 复现过程

1、使用openai_api_demo里面的api_server.py启动模型 2、使用tools_using_demo中的openai_apidemo.py进行工具调用测试 3、直接报422错误:

[registered tool] {'description': 'Generates a random number x, s.t. range[0] <= x < range[1]',
 'name': 'random_number_generator',
 'params': [{'description': 'The random seed used by the generator',
             'name': 'seed',
             'required': True,
             'type': 'int'},
            {'description': 'The range of the generated numbers',
             'name': 'range',
             'required': True,
             'type': 'tuple[int, int]'}]}
[registered tool] {'description': 'Get the current weather for `city_name`',
 'name': 'get_weather',
 'params': [{'description': 'The name of the city to be queried',
             'name': 'city_name',
             'required': True,
             'type': 'str'}]}

 我是一个名为 ChatGLM3-6B 的人工智能助手,是基于清华大学 KEG 实验室和智谱 AI 公司于 2023 年共同训练的语言模型开发的。我的任务是针对用户的问题和要求提供适当的答复和支持。2024-02-20 11:15:57.614 | INFO     | __main__:<module>:90 -
=========== next conversation ===========
Traceback (most recent call last):
  File "/data/sx/ChatGLM3-main/tools_using_demo/openai_api_demo.py", line 93, in <module>
    run_conversation(query, tools=tools, stream=True)
  File "/data/sx/ChatGLM3-main/tools_using_demo/openai_api_demo.py", line 22, in run_conversation
    response = client.chat.completions.create(**params)
  File "/data/software/anaconda3/envs/glm-demo/lib/python3.10/site-packages/openai/_utils/_utils.py", line 275, in wrapper
    return func(*args, **kwargs)
  File "/data/software/anaconda3/envs/glm-demo/lib/python3.10/site-packages/openai/resources/chat/completions.py", line 663, in create
    return self._post(
  File "/data/software/anaconda3/envs/glm-demo/lib/python3.10/site-packages/openai/_base_client.py", line 1200, in post
    return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls))
  File "/data/software/anaconda3/envs/glm-demo/lib/python3.10/site-packages/openai/_base_client.py", line 889, in request
    return self._request(
  File "/data/software/anaconda3/envs/glm-demo/lib/python3.10/site-packages/openai/_base_client.py", line 980, in _request
    raise self._make_status_error_from_response(err.response) from None
openai.UnprocessableEntityError: Error code: 422 - {'detail': [{'type': 'dict_type', 'loc': ['body', 'tools', 'dict[any,any]'], 'msg': 'Input should be a valid dictionary', 'input': ['random_number_generator', 'get_weather'], 'url': 'https://errors.pydantic.dev/2.6/v/dict_type'}, {'type': 'dict_type', 'loc': ['body', 'tools', 'list[dict[any,any]]', 0], 'msg': 'Input should be a valid dictionary', 'input': 'random_number_generator', 'url': 'https://errors.pydantic.dev/2.6/v/dict_type'}, {'type': 'dict_type', 'loc': ['body', 'tools', 'list[dict[any,any]]', 1], 'msg': 'Input should be a valid dictionary', 'input': 'get_weather', 'url': 'https://errors.pydantic.dev/2.6/v/dict_type'}]}

4、仔细看了一下代码,发现可能是tools应该为数组类型而不是dict,将tool_register.py中的

_TOOL_DESCRIPTIONS = {} 修改为 _TOOL_DESCRIPTIONS = []

register_tool方法中48行
_TOOL_DESCRIPTIONS[tool_name] = tool_def 修改为 _TOOL_DESCRIPTIONS.append(tool_def)

def get_tools() -> dict: 改为 def get_tools() -> list[Any]:

5、可以成功进行天气的工具调用:

[registered tool] {'description': 'Generates a random number x, s.t. range[0] <= x < range[1]',
 'name': 'random_number_generator',
 'params': [{'description': 'The random seed used by the generator',
             'name': 'seed',
             'required': True,
             'type': 'int'},
            {'description': 'The range of the generated numbers',
             'name': 'range',
             'required': True,
             'type': 'tuple[int, int]'}]}
[registered tool] {'description': 'Get the current weather for `city_name`',
 'name': 'get_weather',
 'params': [{'description': 'The name of the city to be queried',
             'name': 'city_name',
             'required': True,
             'type': 'str'}]}

 我是一个名为 ChatGLM3-6B 的人工智能助手,是基于清华大学 KEG 实验室和智谱 AI 公司于 2023 年共同训练的语言模型开发的。我的任务是针对用户的问题和要求提供适当的答复和支持。2024-02-20 11:23:41.664 | INFO     | __main__:<module>:90 -
=========== next conversation ===========
get_weather
 ```python
tool_call(city_name='北京')

2024-02-20 11:23:43.607 | INFO | main:run_conversation:61 - Function Call Response: {'arguments': '{"city_name": "北京"}', 'name': 'get_weather'} 2024-02-20 11:23:45.309 | INFO | main:run_conversation:65 - Tool Call Response: {'current_condition': {'temp_C': '-4', 'FeelsLikeC': '-8', 'humidity': '23', 'weatherDesc': [{'value': 'Sunny'}], 'observation_time': '12:06 AM'}}

北京当前的天气情况如下:现在的温度是 -4℃,体感温度是 -8℃,湿度为 23%,天气状况为晴朗。这个信息是在 12:06 AM 查询得到的。 6、但是在使用随机数工具会报错:

[registered tool] {'description': 'Generates a random number x, s.t. range[0] <= x < range[1]',
 'name': 'random_number_generator',
 'params': [{'description': 'The random seed used by the generator',
             'name': 'seed',
             'required': True,
             'type': 'int'},
            {'description': 'The range of the generated numbers',
             'name': 'range',
             'required': True,
             'type': 'tuple[int, int]'}]}
[registered tool] {'description': 'Get the current weather for `city_name`',
 'name': 'get_weather',
 'params': [{'description': 'The name of the city to be queried',
             'name': 'city_name',
             'required': True,
             'type': 'str'}]}

 我是一个名为 ChatGLM3-6B 的人工智能助手,是基于清华大学 KEG 实验室和智谱 AI 公司于 2023 年共同训练的语言模型开发的。我的任务是针对用户的问题和要求提供适当的答复和支持。2024-02-20 11:24:37.491 | INFO     | __main__:<module>:90 -
=========== next conversation ===========
random_number_generator
 ```python
tool_call(seed=6, range=(1996, 2024))

Traceback (most recent call last): File "/data/sx/ChatGLM3-main/tools_using_demo/openai_api_demo.py", line 94, in run_conversation(query, tools=tools, stream=True) File "/data/sx/ChatGLM3-main/tools_using_demo/openai_api_demo.py", line 61, in run_conversation logger.info(f"Function Call Response: {function_call.model_dump()}") AttributeError: 'NoneType' object has no attribute 'model_dump'



请问这个问题该如何解决

### Expected behavior / 期待表现

能正常工具调用
zRzRzRzRzRzRzR commented 8 months ago

AttributeError: 'NoneType' object has no attribute 'model_dump' 这个问题是你pydamic库版本不对么

不过为什么会出现NoneType

April0809 commented 8 months ago

是直接conda新建了个环境,只装了requirements中的依赖 打印了一下chunk的内容:

=========== next conversation ===========
random_number_generator
python
tool_call(seed=6, range=[1996, 2024])

Chunk: ChatCompletionChunk(id='', choices=[Choice(delta=ChoiceDelta(content='', function_call=None, role='assistant', tool_calls=None), finish_reason='function_call', index=0, logprobs=None)], created=1708409455, model='chatglm3', object='chat.completion.chunk', system_fingerprint=None)

虽然出现了tool_call,但是choice里面的function_call=None

April0809 commented 8 months ago

AttributeError: 'NoneType' object has no attribute 'model_dump' 这个问题是你pydamic库版本不对么

不过为什么会出现NoneType

这个应该是

function_call = chunk.choices[0].delta.function_call
logger.info(f"Function Call Response: {function_call.model_dump()}")

function_args = json.loads(function_call.arguments)
 tool_response = dispatch_tool(function_call.name, function_args)
logger.info(f"Tool Call Response: {tool_response}")

这段代码要获取到function_call,但是这个是None导致的

zRzRzRzRzRzRzR commented 8 months ago

没有复现出来,昨天也跑了一下,不过,GLM3 6B工具调用能力确实可能出现召回失败的可鞥

jsxyhelu commented 8 months ago

GLM3 6B的“工具调用” 这块有相关文档吗?为什么要专门写一个 tool_register.py 来实现?其它的比如openai,比如zhipu,相比较而言要简单许多的~

zRzRzRzRzRzRzR commented 8 months ago

GLM3 6B的“工具调用” 这块有相关文档吗?为什么要专门写一个 tool_register.py 来实现?其它的比如openai,比如zhipu,相比较而言要简单许多的~

这是老一点的工具盗用方法,相当于另一种声明工具的办法,你可以查看langchain tool这个demo,这个demo工具声明就是langchain的方式,很容易,其实工具声明的本质就是提示词模板修改

jsxyhelu commented 8 months ago

GLM3 6B的“工具调用” 这块有相关文档吗?为什么要专门写一个 tool_register.py 来实现?其它的比如openai,比如zhipu,相比较而言要简单许多的~

这是老一点的工具盗用方法,相当于另一种声明工具的办法,你可以查看langchain tool这个demo,这个demo工具声明就是langchain的方式,很容易,其实工具声明的本质就是提示词模板修改

嗯,可以考虑如果旧了就取消掉。但是如果能够方便理解原理,最好还是留着。

GZ315200 commented 7 months ago

same issue

HuDiLee commented 3 months ago

"仔细看了一下代码,发现可能是tools应该为数组类型而不是dict,将tool_register.py中的",你的方法成功解决了我调用工具失败的问题,感谢。我想知道你是如何得出tools该为list,期待解答。