Open 812781385 opened 3 months ago
这是因为受到对话历史的干扰了,您现在给的历史是:
messages = [
{"role":"system","content":"### 你好!有什么我可以帮助你的吗?"},
{"role":"user","content":"帮我查下一下这首船的信息:477795600"},
{"role":"assistant","content":"这艘船的信息如下:\n\n- 船舶ID: 477795600\n- MMSI 号码: 477795600\n- IMO 编号: 9620293\n\n请注意,这些数据可能会有延迟。如果有其他具体问题或者需要更多的帮助,请随时告诉我。"},
{"role":"user","content":"帮我查下一下这首船的信息:227745780"}
]
这个历史的里的用户问题是明显需要调用工具的,但是历史却没有function call的messages,直接就给了Assistant的回复。这会让模型认为“历史里我就是不调用工具回答的,那我回答新问题自然也不用调用工具”。
解决方法一:确保历史里该调用工具的历史都有对应的function call messages,比如
messages = [
{"role":"system","content":"### 你好!有什么我可以帮助你的吗?"},
{"role":"user","content":"帮我查下一下这首船的信息:477795600"},
{"role":"assistant","content": "", "function_call": ...}, ## 工具调用!!!
{"role":"function","content": ...}, ## 工具结果!!!
{"role":"assistant","content":"这艘船的信息如下:\n\n- 船舶ID: 477795600\n- MMSI 号码: 477795600\n- IMO 编号: 9620293\n\n请注意,这些数据可能会有延迟。如果有其他具体问题或者需要更多的帮助,请随时告诉我。"},
{"role":"user","content":"帮我查下一下这首船的信息:227745780"}
]
解决方法二(不一定稳定):使用function_choice(又名tool_choice)功能向模型强调要调用工具:https://github.com/QwenLM/Qwen-Agent/blob/main/examples/function_calling.py#L76
这是因为受到对话历史的干扰了,您现在给的历史是:
messages = [ {"role":"system","content":"### 你好!有什么我可以帮助你的吗?"}, {"role":"user","content":"帮我查下一下这首船的信息:477795600"}, {"role":"assistant","content":"这艘船的信息如下:\n\n- 船舶ID: 477795600\n- MMSI 号码: 477795600\n- IMO 编号: 9620293\n\n请注意,这些数据可能会有延迟。如果有其他具体问题或者需要更多的帮助,请随时告诉我。"}, {"role":"user","content":"帮我查下一下这首船的信息:227745780"} ]
这个历史里的用户问题在于,历史其实并没有提供任何功能调用,直接就给了我们模型的想法。这让模型认为“历史里我就是不会自动回答的,那我回答新问题自然也就不用调用了”。
解决方法一:确保该历史调用函数都可用,比如
messages = [ {"role":"system","content":"### 你好!有什么我可以帮助你的吗?"}, {"role":"user","content":"帮我查下一下这首船的信息:477795600"}, {"role":"assistant","content": "", "function_call": ...}, ## 工具调用!!! {"role":"function","content": ...}, ## 工具结果!!! {"role":"assistant","content":"这艘船的信息如下:\n\n- 船舶ID: 477795600\n- MMSI 号码: 477795600\n- IMO 编号: 9620293\n\n请注意,这些数据可能会有延迟。如果有其他具体问题或者需要更多的帮助,请随时告诉我。"}, {"role":"user","content":"帮我查下一下这首船的信息:227745780"} ]
解决方法二(不一定稳定):使用function_choice(又名tool_choice)功能向模型强调要调用的工具:https://github.com/QwenLM/Qwen-Agent/blob/main/examples/function_calling.py#L76
你好,我把多轮记录组合进去。当拿到接口数据后再次调用模型的时候,他又返回function_call。
我的代码:
from qwen_agent.llm import get_chat_model
import requests, json
import os
client = get_chat_model({
'model': 'qwen:32b',
'model_server': 'http://127.0.0.1:11434/v1',
'generate_cfg': {
'top_p': 0.5
}
})
def get_ship(args):
return str({'ShipID': 636016918, 'mmsi': 636016918, 'imo': 9254513, 'nationality': '利比里亚', 'name': 'BAO LAI', 'callsign': 'D5IJ8', 'shiptype': 70, 'length': 1900, 'width': 320, 'left': 190, 'trail': 280, 'draught': 9700, 'dest': 'LIANYUNGANG,CN', 'dest_std': '', 'destcode': '', 'eta': '07-01 19:00', 'eta_std': '2024-07-01 19:00:00', 'navistat': 0, 'lon': 119393350, 'lat': 34748566, 'hdg': 28300, 'cog': 15250, 'sog': 0, 'rot': 0, 'lasttime': 1720402545})
tools = [
{
"name": "get_ship",
"description": "获取船舶详情信息",
"parameters": {
"type": "object",
"properties": {
"mmsi": {
"type": "string",
"description": "船舶mmsi, " "例如: 13324313",
}
},
"required": ["mmsi"],
},
},
]
messages = [
{'role': 'system', 'content': '### 你好!有什么我可以帮助你的吗?\n 作为你的智能伙伴,我既能写文案、想点子,又能陪你聊天、答疑解惑。'},
{'role': 'user', 'content': '帮我查下一下这首船的信息:477795600'},
{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "477795600"}'}},
{'role': 'function', 'name': 'get_ship', 'content': "{'ShipID': 477795600, 'mmsi': 477795600, 'imo': 9620293, 'nationality': '中国香港', 'name': '坤燕', 'callsign': 'VRIS5', 'shiptype': 70, 'length': 1120, 'width': 190, 'left': 140, 'trail': 150, 'draught': 5000, 'dest': 'MY TMI', 'dest_std': '', 'destcode': '', 'eta': '07-05 20:00', 'eta_std': '2024-07-05 20:00:00', 'navistat': 1, 'lon': 111338333, 'lat': 2115000, 'hdg': None, 'cog': 30000, 'sog': 0, 'rot': 0, 'lasttime': 1720402664}"}, {'role': 'assistant', 'content': '船名:坤燕(英文名称:VRIS5)\n国籍:中国香港\nIMO号:9620293\n类型:70型(这通常表示是货船,但具体船型可能需要参照更详细的分类标准)\n长度:112米\n宽度:19米\n吃水深度:5米\n当前目的地:MY TMI(这可能是马来西亚的 Tanjung Pelepas 代码,但建议进一步确认)\n预计到达时间:07-05 20:00(这个日期格式是月/日/时,这里可能是指2024年7月5日20点)\n\n船位信息:\n- 最新经纬度:经度11.564814°E,纬度21.25°N\n- 航向(hdg):没有记录\n- 真航速(cog):0节\n- 对地航速(sog):0节\n- 旋转速率(rot):0°\n- 更新时间:1720402664秒(这个数值是 Unix 时间戳,转换成日期大约是2024年9月13日左右,具体时间需进一步转换)\n\n请注意,这些信息可能会有延迟或不准确,特别是在船舶实时位置和动态方面。如需最准确的信息,请参考官方船位追踪服务或者相关海事部门的更新。'},
{'role': 'user', 'content': '这首呢:351690000'},
{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "351690000"}'}},
{'role': 'function', 'name': 'get_ship', 'content': "{'ShipID': 351690000, 'mmsi': 351690000, 'imo': 0, 'nationality': '巴拿马', 'name': 'PAN FREESIA', 'callsign': 'H3BC', 'shiptype': 70, 'length': 2920, 'width': 450, 'left': 100, 'trail': 500, 'draught': 0, 'dest': 'ZHOUSHAN,CN', 'dest_std': '', 'destcode': '', 'eta': '06-17 03:30', 'eta_std': '2024-06-17 03:30:00', 'navistat': 5, 'lon': 122008878, 'lat': 30158660, 'hdg': 29500, 'cog': 11860, 'sog': 51, 'rot': 0, 'lasttime': 1720402566}"},
{'role': 'assistant', 'content': '船名:PAN FREESIA(呼叫信号:H3BC)\n国籍:巴拿马\nIMO号:未提供\n类型:70型(通常表示货船,但具体船型可能需要参照更详细的分类标准)\n长度:292米\n宽度:45米\n吃水深度:无数据\n当前目的地:ZHOUSHAN-CN(舟山,中国的一个海港城市)\n预计到达时间:06-17 03:30(这个日期格式是月/日/时,这里可能是指2024年6月17日3点30分)\n\n船位信息:\n- 最新经纬度:经度122.015189°E,纬度30.264433°N\n- 航向(hdg):295°\n- 对地航速(cog):约118.6节(考虑到数据的可能误差,这个值可能不准确)\n- 真航速(sog):51节\n- 旋转速率(rot):0°\n- 更新时间:1720402566秒(这个数值是 Unix 时间戳,转换成日期大约是2024年9月13日左右,具体时间需进一步转换)\n\n请注意,这些信息可能会有延迟或不准确,特别是在船舶实时位置和动态方面。如需最准确的信息,请参考官方船位追踪服务或者相关海事部门的更新。'},
{'role': 'user', 'content': '明白了'},
{'role': 'assistant', 'content': '很高兴能够帮到你!如果你有关于其他船只的信息查询,或者需要任何其他帮助,请随时告诉我。祝你有美好的一天!'},
{'role': 'user', 'content': '636016918'},
]
res_stream = []
pending_function_call = None
pending_arguments = ""
for res_stream in client.chat(messages=messages, functions=tools, stream=True):
if 'function_call' in res_stream[0]:
if pending_function_call is None:
pending_function_call = res_stream[0]['function_call']['name']
pending_arguments = res_stream[0]['function_call']['arguments']
try:
params = json.loads(pending_arguments)
print('------->>>>>', params)
if 'mmsi' in params and params['mmsi'].endswith('"'):
mmsi = params['mmsi'].replace('"', '')
print('-- mmsi --<<', mmsi)
except json.JSONDecodeError:
continue
messages.append(res_stream[0])
function_name = messages[-1]['function_call']['name']
function_to_call = get_ship
function_args = json.loads(messages[-1]['function_call']['arguments'])
function_response = function_to_call(function_args)
print('.....接口返回:', function_response)
messages.append({
'role': 'function',
'name': function_name,
'content': function_response,
})
print('......新的messages给模型', messages)
newres_stream = []
for newres_stream in client.chat(messages=messages, functions=tools, stream=True):
print('.....newres_stream', newres_stream)
else:
print('........未进入funcitoncal', res_stream)
运行结果: .....newres_stream [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get', 'arguments': ''}}] .....newres_stream [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': ''}}] .....newres_stream [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': ''}}] .....newres_stream [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': ''}}] .....newres_stream [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': ''}}] .....newres_stream [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"'}}] .....newres_stream [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"m'}}] .....newres_stream [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mms'}}] .....newres_stream [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi'}}] .....newres_stream [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi":'}}] .....newres_stream [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "'}}] .....newres_stream [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "6'}}] .....newres_stream [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "63'}}] .....newres_stream [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "636'}}] .....newres_stream [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "6360'}}] .....newres_stream [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "63601'}}] .....newres_stream [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "636016'}}] .....newres_stream [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "6360169'}}] .....newres_stream [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "63601691'}}] .....newres_stream [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "636016918'}}] .....newres_stream [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "636016918"}'}}] .....newres_stream [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "636016918"}'}}]
这个for循环看起来写得不对。。。
请参考 https://github.com/QwenLM/Qwen-Agent/blob/main/qwen_agent/agents/fncall_agent.py#L46 或者直接使用 FnCallAgent 这类高级的抽象。llm.chat是个偏底层的抽象。
这个for循环看起来写得不对。。。
请参考 https://github.com/QwenLM/Qwen-Agent/blob/main/qwen_agent/agents/fncall_agent.py#L46 或者直接使用 FnCallAgent 这类高级的抽象。llm.chat是个偏底层的抽象。
我的代码使用的是这个示例,for循环也是一样的啊:https://github.com/QwenLM/Qwen-Agent/blob/main/examples/function_calling.py 如果使用FnCallAgent的话,怎么调用,有示例不?
这个for循环看起来写得不对。。。 请参考 https://github.com/QwenLM/Qwen-Agent/blob/main/qwen_agent/agents/fncall_agent.py#L46 或者直接使用 FnCallAgent 这类高级的抽象。llm.chat是个偏底层的抽象。
我的代码使用的是这个示例,for循环也是一样的啊:https://github.com/QwenLM/Qwen-Agent/blob/main/examples/function_calling.py 如果使用FnCallAgent的话,怎么调用,有示例不?
您的代码,有部分不该放进for循环的代码被放进for循环了。
FnCallAgent 和 Assistant 这个类的用法差不多: https://github.com/QwenLM/Qwen-Agent/blob/main/examples/assistant_add_custom_tool.py 区别是 FnCallAgent 相比 Assistant 少了 RAG 功能(Assistant支持传pdf files而FnCallAgent 不支持。图省事用 Assistant 也可以)
模型mssages过多的时候,出现这个带花的提示是咋回事啊?:
模型mssages过多的时候,出现这个带花的提示是咋回事啊?:
{
"role": "assistant",
"content": ": \n✿FUNCTION✿: get_ship\n✿ARGS✿: {\"mmsi\": \"538008251\"} \n"
}
模型mssages过多的时候,出现这个带花的提示是咋回事啊?:
模型mssages过多的时候,出现这个带花的提示是咋回事啊?:
{ "role": "assistant", "content": ": \n✿FUNCTION✿: get_ship\n✿ARGS✿: {\"mmsi\": \"538008251\"} \n" }
这个正常情况下是应该会被解析成function call的message的(用户看不到花)。有什么脚本可以供我们复现吗
模型mssages过多的时候,出现这个带花的提示是咋回事啊?:
模型mssages过多的时候,出现这个带花的提示是咋回事啊?:
{ "role": "assistant", "content": ": \n✿FUNCTION✿: get_ship\n✿ARGS✿: {\"mmsi\": \"538008251\"} \n" }
这个正常情况下是应该会被解析成function call的message的(用户看不到花)。有什么脚本可以供我们复现吗
就用我上面的脚本,然后多来几轮对话就会复现在。 后面我用了from qwen_agent.agents import Assistant 我用了8轮对话也很不稳定
我使用from qwen_agent.llm import get_chat_model时候,调用模型,如果messages里有历史,则无法命中functioncall,这是为啥? 使用如下:
同样的数据发送会频繁出现不同的结果:
代码片段: client = get_chat_model({ 'model': 'qwen:32b', 'model_server': 'http://127.0.0.1:11434/v1' }) messages = [ {"role":"system","content":"### 你好!有什么我可以帮助你的吗?"}, {"role":"user","content":"帮我查下一下这首船的信息:477795600"}, {"role":"assistant","content":"这艘船的信息如下:\n\n- 船舶ID: 477795600\n- MMSI 号码: 477795600\n- IMO 编号: 9620293\n\n请注意,这些数据可能会有延迟。如果有其他具体问题或者需要更多的帮助,请随时告诉我。"}, {"role":"user","content":"帮我查下一下这首船的信息:227745780"} ]
res_stream = [] for res_stream in client.chat( messages=messages, functions=tools, stream=True ): print(res_stream)
第一次结果: [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get', 'arguments': ''}}] [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': ''}}] [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': ''}}] [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': ''}}] [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': ''}}] [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"'}}] [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"m'}}] [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mms'}}] [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi'}}] [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi":'}}] [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "'}}] [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "2'}}] [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "22'}}] [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "227'}}] [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "2277'}}] [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "22774'}}] [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "227745'}}] [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "2277457'}}] [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "22774578'}}] [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "227745780'}}] [{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_ship', 'arguments': '{"mmsi": "227745780"}'}}]
第二次结果: [{'role': 'assistant', 'content': '我'}] [{'role': 'assistant', 'content': '我需要'}] [{'role': 'assistant', 'content': '我需要更多信息'}] [{'role': 'assistant', 'content': '我需要更多信息才能'}] [{'role': 'assistant', 'content': '我需要更多信息才能查询'}] [{'role': 'assistant', 'content': '我需要更多信息才能查询船舶'}] [{'role': 'assistant', 'content': '我需要更多信息才能查询船舶的'}] [{'role': 'assistant', 'content': '我需要更多信息才能查询船舶的详细'}] [{'role': 'assistant', 'content': '我需要更多信息才能查询船舶的详细资料'}] [{'role': 'assistant', 'content': '我需要更多信息才能查询船舶的详细资料,'}] [{'role': 'assistant', 'content': '我需要更多信息才能查询船舶的详细资料,如'}] [{'role': 'assistant', 'content': '我需要更多信息才能查询船舶的详细资料,如M'}] [{'role': 'assistant', 'content': '我需要更多信息才能查询船舶的详细资料,如MMS'}] [{'role': 'assistant', 'content': '我需要更多信息才能查询船舶的详细资料,如MMSI'}] [{'role': 'assistant', 'content': '我需要更多信息才能查询船舶的详细资料,如MMSI号码'}] [{'role': 'assistant', 'content': '我需要更多信息才能查询船舶的详细资料,如MMSI号码、'}] [{'role': 'assistant', 'content': '我需要更多信息才能查询船舶的详细资料,如MMSI号码、IMO'}] [{'role': 'assistant', 'content': '我需要更多信息才能查询船舶的详细资料,如MMSI号码、IMO编号'}] [{'role': 'assistant', 'content': '我需要更多信息才能查询船舶的详细资料,如MMSI号码、IMO编号或者'}] [{'role': 'assistant', 'content': '我需要更多信息才能查询船舶的详细资料,如MMSI号码、IMO编号或者具体的'}] [{'role': 'assistant', 'content': '我需要更多信息才能查询船舶的详细资料,如MMSI号码、IMO编号或者具体的船'}] [{'role': 'assistant', 'content': '我需要更多信息才能查询船舶的详细资料,如MMSI号码、IMO编号或者具体的船名'}] [{'role': 'assistant', 'content': '我需要更多信息才能查询船舶的详细资料,如MMSI号码、IMO编号或者具体的船名。'}]