update pay promo

This commit is contained in:
2026-02-04 19:06:36 +08:00
parent 3e59fb75ff
commit 1091354f61

View File

@@ -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]]: