From 6228bef5ad99c6a2411cb7a6537555fcd16c56e4 Mon Sep 17 00:00:00 2001 From: zzlgreat Date: Sat, 8 Nov 2025 10:17:48 +0800 Subject: [PATCH] =?UTF-8?q?agent=E5=8A=9F=E8=83=BD=E5=BC=80=E5=8F=91?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0MCP=E5=90=8E=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- concept_api.py | 4 +- mcp_server.py | 174 ++++++++++++++++++++++++++++++++++++------------- 2 files changed, 131 insertions(+), 47 deletions(-) diff --git a/concept_api.py b/concept_api.py index 093f4bf3..329b1ded 100644 --- a/concept_api.py +++ b/concept_api.py @@ -490,7 +490,7 @@ def build_hybrid_knn_query( "field": "description_embedding", "query_vector": embedding, "k": k, - "num_candidates": min(k * 2, 500), + "num_candidates": max(k + 50, min(k * 2, 10000)), # 确保 num_candidates > k,最大 10000 "boost": semantic_weight } } @@ -591,7 +591,7 @@ async def search_concepts(request: SearchRequest): "field": "description_embedding", "query_vector": embedding, "k": effective_search_size, # 使用有效搜索大小 - "num_candidates": min(effective_search_size * 2, 1000) + "num_candidates": max(effective_search_size + 50, min(effective_search_size * 2, 10000)) # 确保 num_candidates > k }, "size": effective_search_size } diff --git a/mcp_server.py b/mcp_server.py index 2fb1abd9..14b962d9 100644 --- a/mcp_server.py +++ b/mcp_server.py @@ -1473,7 +1473,7 @@ class MCPAgentIntegrated: # 发送开始事件 yield self._format_sse("status", {"stage": "start", "message": "开始处理查询"}) - # 阶段1: Kimi 制定计划(流式) + # 阶段1: Kimi 制定计划(流式,带 DeepMoney 备选) yield self._format_sse("status", {"stage": "planning", "message": "正在制定执行计划..."}) messages = [ @@ -1481,40 +1481,81 @@ class MCPAgentIntegrated: {"role": "user", "content": user_query}, ] - # 使用流式 API 调用 Kimi - stream = self.kimi_client.chat.completions.create( - model=self.kimi_model, - messages=messages, - temperature=1.0, - max_tokens=16000, - stream=True, # 启用流式输出 - ) - reasoning_content = "" plan_content = "" + use_fallback = False - # 逐块接收 Kimi 的响应 - for chunk in stream: - if chunk.choices[0].delta.content: - content_chunk = chunk.choices[0].delta.content - plan_content += content_chunk + try: + # 尝试使用 Kimi 流式 API + stream = self.kimi_client.chat.completions.create( + model=self.kimi_model, + messages=messages, + temperature=1.0, + max_tokens=16000, + stream=True, # 启用流式输出 + ) - # 发送思考过程片段 - yield self._format_sse("thinking", { - "content": content_chunk, - "stage": "planning" + # 逐块接收 Kimi 的响应 + for chunk in stream: + if chunk.choices[0].delta.content: + content_chunk = chunk.choices[0].delta.content + plan_content += content_chunk + + # 发送思考过程片段 + yield self._format_sse("thinking", { + "content": content_chunk, + "stage": "planning" + }) + + # 提取 reasoning_content(如果有) + if hasattr(chunk.choices[0], 'delta') and hasattr(chunk.choices[0].delta, 'reasoning_content'): + reasoning_chunk = chunk.choices[0].delta.reasoning_content + if reasoning_chunk: + reasoning_content += reasoning_chunk + # 发送推理过程片段 + yield self._format_sse("reasoning", { + "content": reasoning_chunk + }) + + except Exception as kimi_error: + # 检查是否是内容风控错误(400) + error_str = str(kimi_error) + if "400" in error_str and ("content_filter" in error_str or "high risk" in error_str): + logger.warning(f"[Planning] Kimi 内容风控拒绝,切换到 DeepMoney: {error_str}") + use_fallback = True + + yield self._format_sse("status", { + "stage": "planning", + "message": "切换到备用模型制定计划..." }) - # 提取 reasoning_content(如果有) - if hasattr(chunk.choices[0], 'delta') and hasattr(chunk.choices[0].delta, 'reasoning_content'): - reasoning_chunk = chunk.choices[0].delta.reasoning_content - if reasoning_chunk: - reasoning_content += reasoning_chunk - # 发送推理过程片段 - yield self._format_sse("reasoning", { - "content": reasoning_chunk + try: + # 使用 DeepMoney 备选方案(非流式,因为 DeepMoney 可能不支持流式) + fallback_response = self.deepmoney_client.chat.completions.create( + model=self.deepmoney_model, + messages=messages, + temperature=0.7, + max_tokens=16000, + ) + + plan_content = fallback_response.choices[0].message.content + + # 发送完整的计划内容(一次性) + yield self._format_sse("thinking", { + "content": plan_content, + "stage": "planning" }) + logger.info(f"[Planning] DeepMoney 备选方案成功") + + except Exception as fallback_error: + logger.error(f"[Planning] DeepMoney 备选方案也失败: {fallback_error}") + raise Exception(f"Kimi 和 DeepMoney 都无法生成计划: {kimi_error}, {fallback_error}") + else: + # 不是内容风控错误,直接抛出 + logger.error(f"[Planning] Kimi 调用失败(非风控原因): {kimi_error}") + raise + # 解析完整的计划 plan_json = plan_content.strip() @@ -1682,29 +1723,72 @@ class MCPAgentIntegrated: }, ] - # 使用流式 API 生成总结 - summary_stream = self.kimi_client.chat.completions.create( - model="kimi-k2-turbo-preview", - messages=messages, - temperature=0.7, - max_tokens=2000, - stream=True, # 启用流式输出 - ) - + # 使用流式 API 生成总结(带 DeepMoney 备选) final_summary = "" - # 逐块发送总结内容 - for chunk in summary_stream: - if chunk.choices[0].delta.content: - content_chunk = chunk.choices[0].delta.content - final_summary += content_chunk + try: + summary_stream = self.kimi_client.chat.completions.create( + model="kimi-k2-turbo-preview", + messages=messages, + temperature=0.7, + max_tokens=2000, + stream=True, # 启用流式输出 + ) - # 发送总结片段 - yield self._format_sse("summary_chunk", { - "content": content_chunk + # 逐块发送总结内容 + for chunk in summary_stream: + if chunk.choices[0].delta.content: + content_chunk = chunk.choices[0].delta.content + final_summary += content_chunk + + # 发送总结片段 + yield self._format_sse("summary_chunk", { + "content": content_chunk + }) + + logger.info("[Summary] 流式总结完成") + + except Exception as kimi_error: + # 检查是否是内容风控错误(400) + error_str = str(kimi_error) + if "400" in error_str and ("content_filter" in error_str or "high risk" in error_str): + logger.warning(f"[Summary] Kimi 内容风控拒绝,切换到 DeepMoney: {error_str}") + + yield self._format_sse("status", { + "stage": "summarizing", + "message": "切换到备用模型生成总结..." }) - logger.info("[Summary] 流式总结完成") + try: + # 使用 DeepMoney 备选方案(非流式) + fallback_response = self.deepmoney_client.chat.completions.create( + model=self.deepmoney_model, + messages=messages, + temperature=0.7, + max_tokens=2000, + ) + + final_summary = fallback_response.choices[0].message.content + + # 发送完整的总结内容(一次性) + yield self._format_sse("summary_chunk", { + "content": final_summary + }) + + logger.info(f"[Summary] DeepMoney 备选方案成功") + + except Exception as fallback_error: + logger.error(f"[Summary] DeepMoney 备选方案也失败: {fallback_error}") + # 使用降级方案:简单拼接执行结果 + final_summary = f"执行了 {len(plan.steps)} 个步骤,其中 {len(successful_results)} 个成功。\n\n执行结果:\n{results_text[:500]}..." + yield self._format_sse("summary_chunk", { + "content": final_summary + }) + logger.warning("[Summary] 使用降级方案(简单拼接)") + else: + # 不是内容风控错误,直接抛出 + logger.error(f"[Summary] Kimi 调用失败(非风控原因): {kimi_error}") + raise # 发送完整的总结和元数据 yield self._format_sse("summary", {