diff --git a/__pycache__/mcp_server.cpython-310.pyc b/__pycache__/mcp_server.cpython-310.pyc index e06d1636..0d8d94d1 100644 Binary files a/__pycache__/mcp_server.cpython-310.pyc and b/__pycache__/mcp_server.cpython-310.pyc differ diff --git a/mcp_server.py b/mcp_server.py index 9889235d..c0e22a26 100644 --- a/mcp_server.py +++ b/mcp_server.py @@ -2549,8 +2549,15 @@ A股交易时间: 上午 9:30-11:30,下午 13:00-15:00 # 如果没有原生工具调用,尝试从文本内容中解析 if not native_tool_calls and assistant_message.content: content = assistant_message.content - # 检查是否包含工具调用标记 - if '' in content or '```tool_call' in content or '"tool":' in content: + # 检查是否包含工具调用标记(包括 DSML 格式) + has_tool_markers = ( + '' in content or + '```tool_call' in content or + '"tool":' in content or + 'DSML' in content or # DeepSeek DSML 格式 + '|DSML|' in content # 全角竖线版本 + ) + if has_tool_markers: logger.info(f"[Agent Stream] 尝试从文本内容解析工具调用") logger.info(f"[Agent Stream] 内容预览: {content[:500]}") text_tool_calls = self._parse_text_tool_calls(content) @@ -2947,6 +2954,7 @@ A股交易时间: 上午 9:30-11:30,下午 13:00-15:00 支持的格式: 1. value 2. ```tool_call\n{"name": "xxx", "arguments": {...}}\n``` + 3. DeepSeek DSML 格式: <|DSML|function_calls> <|DSML|invoke name="xxx"> <|DSML|parameter name="yyy" string="true">value 返回: [{"name": "tool_name", "arguments": {...}}, ...] """ @@ -3006,6 +3014,47 @@ A股交易时间: 上午 9:30-11:30,下午 13:00-15:00 except: pass + # 格式4: DeepSeek DSML 格式(使用全角竖线 |) + # <|DSML|function_calls> <|DSML|invoke name="search_research_reports"> <|DSML|parameter name="query" string="true">AI概念股 + # 注意:| 是全角字符 + dsml_pattern = r'<[|\|]DSML[|\|]function_calls>(.*?)' + dsml_matches = re.findall(dsml_pattern, content, re.DOTALL) + + for dsml_content in dsml_matches: + # 解析 invoke 标签 + invoke_pattern = r'<[|\|]DSML[|\|]invoke\s+name="(\w+)">(.*?)' + invoke_matches = re.findall(invoke_pattern, dsml_content, re.DOTALL) + + for func_name, params_str in invoke_matches: + arguments = {} + # 解析参数: <|DSML|parameter name="xxx" string="true/false">value + param_pattern = r'<[|\|]DSML[|\|]parameter\s+name="(\w+)"\s+string="(true|false)">(.*?)' + param_matches = re.findall(param_pattern, params_str, re.DOTALL) + + for param_name, is_string, param_value in param_matches: + param_value = param_value.strip() + if is_string == "false": + # 不是字符串,尝试解析为数字或 JSON + try: + arguments[param_name] = json.loads(param_value) + except: + # 尝试转为整数或浮点数 + try: + arguments[param_name] = int(param_value) + except: + try: + arguments[param_name] = float(param_value) + except: + arguments[param_name] = param_value + else: + # 是字符串 + arguments[param_name] = param_value + + tool_calls.append({ + "name": func_name, + "arguments": arguments + }) + logger.info(f"[Text Tool Call] 解析到 {len(tool_calls)} 个工具调用: {tool_calls}") return tool_calls