zai2api-py / tests /test_multiple_tools.py
keungliang's picture
Upload 31 files
fd21f34 verified
#!/usr/bin/env python3
"""
测试多个工具调用的处理逻辑
"""
import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from app.utils.sse_tool_handler import SSEToolHandler
def test_multiple_tool_calls():
"""测试多个工具调用的处理"""
handler = SSEToolHandler("test-model", stream=False)
print("🧪 测试多个工具调用处理\n")
# 模拟真实的多工具调用序列(基于日志)
test_chunks = [
# 第一个工具调用开始
{
"phase": "tool_call",
"edit_content": '<glm_block view="">{"type": "mcp", "data": {"metadata": {"id": "call_5y5gir0mygx", "name": "mcp__playwright__browser_navigate", "arguments": "{\\"url\\":\\"https://www.bil", "result": "", "display_result": "", "duration": "...", "status": "completed", "is_error": false, "mcp_server": {"name": "mcp-server"}}, "thought": null, "ppt": null, "browser": null}}</glm_block>',
"edit_index": 24
},
# 第一个工具调用参数补充
{
"phase": "tool_call",
"edit_content": 'ibili.com\\"}',
"edit_index": 194
},
# 第一个工具调用结束
{
"phase": "other",
"edit_content": 'null, "display_result": "", "duration": "...", "status": "completed", "is_error": false, "mcp_server": {"name": "mcp-server"}}, "thought": null, "ppt": null, "browser": null}}</glm_block>',
"edit_index": 219
},
# 第二个工具调用开始
{
"phase": "tool_call",
"edit_content": '<glm_block view="">{"type": "mcp", "data": {"metadata": {"id": "call_j8r24x6xtg", "name": "mcp__playwright__browser_snapshot", "arguments": "{}", "result": "", "display_result": "", "duration": "...", "status": "completed", "is_error": false, "mcp_server": {"name": "mcp-server"}}, "thought": null, "ppt": null, "browser": null}}</glm_block>',
"edit_index": 406
},
# 第二个工具调用结束
{
"phase": "other",
"edit_content": 'null, "display_result": "", "duration": "...", "status": "completed", "is_error": false, "mcp_server": {"name": "mcp-server"}}, "thought": null, "ppt": null, "browser": null}}</glm_block>',
"edit_index": 566
},
# 第三个工具调用开始(重复的 navigate)
{
"phase": "tool_call",
"edit_content": '<glm_block view="">{"type": "mcp", "data": {"metadata": {"id": "call_scvwo0xaoil", "name": "mcp__playwright__browser_navigate", "arguments": "{\\"url\\":\\"https://www.bil", "result": "", "display_result": "", "duration": "...", "status": "completed", "is_error": false, "mcp_server": {"name": "mcp-server"}}, "thought": null, "ppt": null, "browser": null}}</glm_block>',
"edit_index": 753
},
# 第三个工具调用参数补充
{
"phase": "tool_call",
"edit_content": 'ibili.com\\"}',
"edit_index": 925
},
# 第三个工具调用结束
{
"phase": "other",
"edit_content": 'null, "display_result": "", "duration": "...", "status": "completed", "is_error": false, "mcp_server": {"name": "mcp-server"}}, "thought": null, "ppt": null, "browser": null}}</glm_block>',
"edit_index": 950
}
]
tool_calls_completed = []
for i, chunk in enumerate(test_chunks, 1):
print(f"处理块 {i}: edit_index={chunk['edit_index']}, phase={chunk['phase']}")
# 记录处理前的工具状态
old_tool_id = handler.tool_id
old_tool_name = handler.tool_name
old_has_tool_call = handler.has_tool_call
# 处理块
results = list(handler.process_sse_chunk(chunk))
# 检查是否有新工具调用开始
if handler.tool_id != old_tool_id and handler.tool_id:
print(f" 🎯 新工具调用开始: {handler.tool_name} (id: {handler.tool_id})")
# 检查是否有工具调用完成
if old_has_tool_call and not handler.has_tool_call:
tool_calls_completed.append({
"name": old_tool_name or "unknown",
"id": old_tool_id
})
print(f" ✅ 工具调用完成: {old_tool_name or 'unknown'}")
print(f" 当前状态: has_tool_call={handler.has_tool_call}, tool_id={handler.tool_id}")
print()
print(f"📊 测试结果:")
print(f" 完成的工具调用数量: {len(tool_calls_completed)}")
for i, tool in enumerate(tool_calls_completed, 1):
print(f" {i}. {tool['name']} (id: {tool['id']})")
# 验证是否正确处理了所有工具调用
expected_tools = [
"mcp__playwright__browser_navigate",
"mcp__playwright__browser_snapshot",
"mcp__playwright__browser_navigate"
]
completed_tool_names = [tool['name'] for tool in tool_calls_completed]
if completed_tool_names == expected_tools:
print("\n✅ 测试通过!正确处理了所有工具调用")
print("📝 结论:重复的工具调用是上游发送的,我们的处理逻辑是正确的")
return True
else:
print(f"\n❌ 测试失败!")
print(f" 期望: {expected_tools}")
print(f" 实际: {completed_tool_names}")
return False
if __name__ == "__main__":
success = test_multiple_tool_calls()
if success:
print("\n🎯 总结:")
print("1. 我们的 API 代理正确处理了每个不同的工具调用")
print("2. 重复的工具调用是上游 Z.AI 模型发送的,不是我们的问题")
print("3. 每个工具调用都有不同的 ID,说明这是模型的有意行为")
print("4. 可能的原因:模型重试、验证操作、或处理复杂任务的策略")
else:
print("\n❌ 需要进一步调试处理逻辑")