update pay promo
This commit is contained in:
112
mcp_server.py
112
mcp_server.py
@@ -2495,7 +2495,13 @@ class MCPAgentIntegrated:
|
|||||||
"""
|
"""
|
||||||
主流程(流式输出)- 使用原生 OpenAI Tool Calling API
|
主流程(流式输出)- 使用原生 OpenAI Tool Calling API
|
||||||
|
|
||||||
支持 vLLM 的 --enable-auto-tool-choice --tool-call-parser qwen3_coder
|
支持 vLLM 的 --enable-auto-tool-choice --tool-call-parser minimax_m2
|
||||||
|
MiniMax-M2.1 工具调用格式:
|
||||||
|
<minimax:tool_call>
|
||||||
|
<invoke name="function_name">
|
||||||
|
<parameter name="param_key">param_value</parameter>
|
||||||
|
</invoke>
|
||||||
|
</minimax:tool_call>
|
||||||
"""
|
"""
|
||||||
logger.info(f"[Agent Stream] 处理查询: {user_query}")
|
logger.info(f"[Agent Stream] 处理查询: {user_query}")
|
||||||
if chat_history:
|
if chat_history:
|
||||||
@@ -2885,11 +2891,27 @@ A股交易时间: 上午 9:30-11:30,下午 13:00-15:00
|
|||||||
"execution_time": execution_time,
|
"execution_time": execution_time,
|
||||||
})
|
})
|
||||||
|
|
||||||
# 将工具结果添加到消息历史(简化格式,因为模型可能不支持标准 tool 消息)
|
# 将工具结果添加到消息历史
|
||||||
|
# 使用模拟的 tool_calls + tool 消息结构,保持与原生工具调用一致
|
||||||
result_str = json.dumps(result, ensure_ascii=False) if isinstance(result, (dict, list)) else str(result)
|
result_str = json.dumps(result, ensure_ascii=False) if isinstance(result, (dict, list)) else str(result)
|
||||||
|
# 先添加一个包含 tool_calls 的 assistant 消息
|
||||||
messages.append({
|
messages.append({
|
||||||
"role": "user",
|
"role": "assistant",
|
||||||
"content": f"[工具调用结果] {tool_name}: {result_str[:3000]}"
|
"content": None,
|
||||||
|
"tool_calls": [{
|
||||||
|
"id": tool_call_id,
|
||||||
|
"type": "function",
|
||||||
|
"function": {
|
||||||
|
"name": tool_name,
|
||||||
|
"arguments": json.dumps(arguments, ensure_ascii=False)
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
# 然后添加 tool 结果
|
||||||
|
messages.append({
|
||||||
|
"role": "tool",
|
||||||
|
"tool_call_id": tool_call_id,
|
||||||
|
"content": result_str[:3000]
|
||||||
})
|
})
|
||||||
|
|
||||||
logger.info(f"[Tool Call] 执行成功,耗时 {execution_time:.2f}s")
|
logger.info(f"[Tool Call] 执行成功,耗时 {execution_time:.2f}s")
|
||||||
@@ -2916,9 +2938,23 @@ A股交易时间: 上午 9:30-11:30,下午 13:00-15:00
|
|||||||
"execution_time": execution_time,
|
"execution_time": execution_time,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# 将错误信息添加到消息历史(使用与成功情况一致的格式)
|
||||||
messages.append({
|
messages.append({
|
||||||
"role": "user",
|
"role": "assistant",
|
||||||
"content": f"[工具调用失败] {tool_name}: {error_msg}"
|
"content": None,
|
||||||
|
"tool_calls": [{
|
||||||
|
"id": tool_call_id,
|
||||||
|
"type": "function",
|
||||||
|
"function": {
|
||||||
|
"name": tool_name,
|
||||||
|
"arguments": json.dumps(arguments, ensure_ascii=False)
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
messages.append({
|
||||||
|
"role": "tool",
|
||||||
|
"tool_call_id": tool_call_id,
|
||||||
|
"content": f"工具执行失败: {error_msg}"
|
||||||
})
|
})
|
||||||
|
|
||||||
logger.error(f"[Tool Call] 执行失败: {error_msg}")
|
logger.error(f"[Tool Call] 执行失败: {error_msg}")
|
||||||
@@ -3088,16 +3124,21 @@ A股交易时间: 上午 9:30-11:30,下午 13:00-15:00
|
|||||||
else:
|
else:
|
||||||
# 处理剩余的 buffer
|
# 处理剩余的 buffer
|
||||||
if buffer:
|
if buffer:
|
||||||
# 过滤掉可能残留的工具调用标签
|
# 过滤掉可能残留的工具调用标签(包括不完整标签)
|
||||||
buffer_filtered = self._filter_tool_call_tags(buffer)
|
buffer_filtered = self._filter_tool_call_tags(buffer)
|
||||||
if parse_state == "thinking":
|
if parse_state == "thinking":
|
||||||
|
if buffer_filtered:
|
||||||
thinking_content += buffer_filtered
|
thinking_content += buffer_filtered
|
||||||
yield self._format_sse("thinking_chunk", {"content": buffer_filtered})
|
yield self._format_sse("thinking_chunk", {"content": buffer_filtered})
|
||||||
|
# 确保 thinking 状态正确结束
|
||||||
yield self._format_sse("thinking_end", {"content": thinking_content})
|
yield self._format_sse("thinking_end", {"content": thinking_content})
|
||||||
else:
|
else:
|
||||||
final_summary += buffer_filtered
|
|
||||||
if buffer_filtered:
|
if buffer_filtered:
|
||||||
|
final_summary += buffer_filtered
|
||||||
yield self._format_sse("summary_chunk", {"content": buffer_filtered})
|
yield self._format_sse("summary_chunk", {"content": buffer_filtered})
|
||||||
|
elif parse_state == "thinking":
|
||||||
|
# buffer 为空但仍在 thinking 状态,确保正确结束
|
||||||
|
yield self._format_sse("thinking_end", {"content": thinking_content})
|
||||||
|
|
||||||
logger.info(f"[Summary] 流式总结完成,思考内容长度: {len(thinking_content)}")
|
logger.info(f"[Summary] 流式总结完成,思考内容长度: {len(thinking_content)}")
|
||||||
|
|
||||||
@@ -3191,10 +3232,26 @@ A股交易时间: 上午 9:30-11:30,下午 13:00-15:00
|
|||||||
})
|
})
|
||||||
|
|
||||||
# 将工具结果添加到消息历史
|
# 将工具结果添加到消息历史
|
||||||
|
# 使用模拟的 tool_calls + tool 消息结构,保持与原生工具调用一致
|
||||||
result_str = json.dumps(result, ensure_ascii=False) if isinstance(result, (dict, list)) else str(result)
|
result_str = json.dumps(result, ensure_ascii=False) if isinstance(result, (dict, list)) else str(result)
|
||||||
|
# 先添加一个包含 tool_calls 的 assistant 消息
|
||||||
messages.append({
|
messages.append({
|
||||||
"role": "user",
|
"role": "assistant",
|
||||||
"content": f"[工具调用结果] {tool_name}: {result_str[:3000]}"
|
"content": None,
|
||||||
|
"tool_calls": [{
|
||||||
|
"id": tool_call_id,
|
||||||
|
"type": "function",
|
||||||
|
"function": {
|
||||||
|
"name": tool_name,
|
||||||
|
"arguments": json.dumps(arguments, ensure_ascii=False)
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
# 然后添加 tool 结果
|
||||||
|
messages.append({
|
||||||
|
"role": "tool",
|
||||||
|
"tool_call_id": tool_call_id,
|
||||||
|
"content": result_str[:3000]
|
||||||
})
|
})
|
||||||
|
|
||||||
logger.info(f"[Tool Call] 执行成功,耗时 {execution_time:.2f}s")
|
logger.info(f"[Tool Call] 执行成功,耗时 {execution_time:.2f}s")
|
||||||
@@ -3221,9 +3278,23 @@ A股交易时间: 上午 9:30-11:30,下午 13:00-15:00
|
|||||||
"execution_time": execution_time,
|
"execution_time": execution_time,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# 将错误信息添加到消息历史(使用与成功情况一致的格式)
|
||||||
messages.append({
|
messages.append({
|
||||||
"role": "user",
|
"role": "assistant",
|
||||||
"content": f"[工具调用失败] {tool_name}: {error_msg}"
|
"content": None,
|
||||||
|
"tool_calls": [{
|
||||||
|
"id": tool_call_id,
|
||||||
|
"type": "function",
|
||||||
|
"function": {
|
||||||
|
"name": tool_name,
|
||||||
|
"arguments": json.dumps(arguments, ensure_ascii=False)
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
messages.append({
|
||||||
|
"role": "tool",
|
||||||
|
"tool_call_id": tool_call_id,
|
||||||
|
"content": f"工具执行失败: {error_msg}"
|
||||||
})
|
})
|
||||||
|
|
||||||
logger.error(f"[Tool Call] 执行失败: {error_msg}")
|
logger.error(f"[Tool Call] 执行失败: {error_msg}")
|
||||||
@@ -3322,12 +3393,25 @@ A股交易时间: 上午 9:30-11:30,下午 13:00-15:00
|
|||||||
def _filter_tool_call_tags(self, text: str) -> str:
|
def _filter_tool_call_tags(self, text: str) -> str:
|
||||||
"""过滤掉文本中的工具调用标签(总结阶段不应包含工具调用)"""
|
"""过滤掉文本中的工具调用标签(总结阶段不应包含工具调用)"""
|
||||||
import re
|
import re
|
||||||
# 过滤 MiniMax 格式
|
# 过滤完整的 MiniMax 格式
|
||||||
text = re.sub(r'<minimax:tool_call>.*?</minimax:tool_call>', '', text, flags=re.DOTALL)
|
text = re.sub(r'<minimax:tool_call>.*?</minimax:tool_call>', '', text, flags=re.DOTALL)
|
||||||
# 过滤其他格式
|
# 过滤其他完整格式
|
||||||
text = re.sub(r'<tool_call>.*?</tool_call>', '', text, flags=re.DOTALL)
|
text = re.sub(r'<tool_call>.*?</tool_call>', '', text, flags=re.DOTALL)
|
||||||
text = re.sub(r'```tool_call.*?```', '', text, flags=re.DOTALL)
|
text = re.sub(r'```tool_call.*?```', '', text, flags=re.DOTALL)
|
||||||
text = re.sub(r'<[|\|]DSML[|\|]function_calls>.*?</[|\|]DSML[|\|]function_calls>', '', text, flags=re.DOTALL)
|
text = re.sub(r'<[|\|]DSML[|\|]function_calls>.*?</[|\|]DSML[|\|]function_calls>', '', text, flags=re.DOTALL)
|
||||||
|
|
||||||
|
# 过滤不完整的标签(流结束时可能残留)
|
||||||
|
# MiniMax 不完整标签: <minimax:tool_call>... 没有闭合
|
||||||
|
text = re.sub(r'<minimax:tool_call>.*$', '', text, flags=re.DOTALL)
|
||||||
|
# 不完整的开始标签: <minimax:, <minimax:t, <minimax:tool, 等
|
||||||
|
text = re.sub(r'<minimax:?[a-z_]*$', '', text)
|
||||||
|
# 不完整的 think 标签
|
||||||
|
text = re.sub(r'<think>.*$', '', text, flags=re.DOTALL)
|
||||||
|
text = re.sub(r'</?thi?n?k?>?$', '', text)
|
||||||
|
# 其他不完整标签
|
||||||
|
text = re.sub(r'<tool_call>.*$', '', text, flags=re.DOTALL)
|
||||||
|
text = re.sub(r'<[|\|]DSML[|\|]function_calls>.*$', '', text, flags=re.DOTALL)
|
||||||
|
|
||||||
return text.strip()
|
return text.strip()
|
||||||
|
|
||||||
def _parse_text_tool_calls(self, content: str) -> List[Dict[str, Any]]:
|
def _parse_text_tool_calls(self, content: str) -> List[Dict[str, Any]]:
|
||||||
|
|||||||
Reference in New Issue
Block a user