This commit is contained in:
ai-business-hql
2025-11-18 19:33:08 +08:00
parent 63e05b96f4
commit 5e95b97c46
3 changed files with 51 additions and 8 deletions
+47 -4
View File
@@ -2,7 +2,7 @@
Author: ai-business-hql qingli.hql@alibaba-inc.com
Date: 2025-06-16 16:50:17
LastEditors: ai-business-hql ai.bussiness.hql@gmail.com
LastEditTime: 2025-11-17 15:09:44
LastEditTime: 2025-11-18 19:18:30
FilePath: /comfyui_copilot/backend/service/mcp-client.py
Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
'''
@@ -63,6 +63,51 @@ async def comfyui_agent_invoke(messages: List[Dict[str, Any]], images: List[Imag
tuple: (text, ext) where text is accumulated text and ext is structured data
"""
try:
# ------------------------------------------------------------------
# Sanitize messages to avoid provider validation errors
# Some backends (e.g. Bedrock via ConverseStream) reject requests if
# the final assistant message content ends with trailing whitespace.
# We defensively strip only *trailing* whitespace from assistant text
# segments, preserving internal spaces and formatting.
# ------------------------------------------------------------------
def _strip_trailing_whitespace_from_messages(
msgs: List[Dict[str, Any]]
) -> List[Dict[str, Any]]:
cleaned: List[Dict[str, Any]] = []
for msg in msgs:
role = msg.get("role")
# Only touch assistant messages to minimize impact
if role != "assistant":
cleaned.append(msg)
continue
msg_copy = dict(msg)
content = msg_copy.get("content")
# Simple string content
if isinstance(content, str):
msg_copy["content"] = content.rstrip()
# OpenAI / Agents style list content blocks
elif isinstance(content, list):
new_content = []
for part in content:
if isinstance(part, dict):
part_copy = dict(part)
# Common text block key is "text"
text_val = part_copy.get("text")
if isinstance(text_val, str):
part_copy["text"] = text_val.rstrip()
new_content.append(part_copy)
else:
new_content.append(part)
msg_copy["content"] = new_content
cleaned.append(msg_copy)
return cleaned
messages = _strip_trailing_whitespace_from_messages(messages)
# Get session_id and config from request context
session_id = get_session_id()
config = get_config()
@@ -141,9 +186,7 @@ You must adhere to the following constraints to complete the task:
- If you cannot find the information needed to answer a query, consider using bing_search to obtain relevant information. For example, if search_node tool cannot find the node, you can use bing_search to obtain relevant information about those nodes or components.
- If search_node tool cannot find the node, you MUST use bing_search to obtain relevant information about those nodes or components.
- **DEBUG Intent** - When the user's intent is to debug workflow execution problems, runtime errors, or troubleshoot failed workflows (keywords: "debug", "调试", "工作流报错", "执行失败", "workflow failed", "node error", "runtime error", "不能运行", "出错了"), respond with: "Please click the 🪲 button in the bottom right corner to trigger debug"
- **WORKFLOW REWRITE Intent** - [Critical!] When the user's intent is to functionally modify, enhance, or add NEW features to the current workflow OR modify the current canvas (keywords: "修改当前工作流", "更新工作流", "在当前工作流中添加", "添加功能", "enhance current workflow", "modify workflow", "add to current workflow", "update current workflow", "添加LoRA", "加个upscale", "add upscaling", "修改当前画布", "更新画布", "在画布中", "modify current canvas", "update canvas", "change canvas"), you MUST handoff to the Workflow Rewrite Agent immediately. This is for feature enhancements, not error fixes.
- [Critical!] **WORKFLOW REWRITE Intent** - When the user's intent is to functionally modify, enhance, or add NEW features to the current workflow OR modify the current canvas (keywords: "修改当前工作流", "更新工作流", "在当前工作流中添加", "添加功能", "enhance current workflow", "modify workflow", "add to current workflow", "update current workflow", "添加LoRA", "加个upscale", "add upscaling", "修改当前画布", "更新画布", "在画布中", "modify current canvas", "update canvas", "change canvas"), you MUST always handoff to the Workflow Rewrite Agent immediately.
- **ERROR MESSAGE ANALYSIS** - When a user pastes specific error text/logs (containing terms like "Failed", "Error", "Traceback", or stack traces), prioritize providing troubleshooting help rather than invoking search tools. Follow these steps:
1. Analyze the error to identify the root cause (error type, affected component, missing dependencies, etc.)
+2 -2
View File
@@ -87,7 +87,7 @@ def create_workflow_rewrite_agent():
**Tool Usage Guidelines:**
- get_current_workflow(): Get current workflow from checkpoint or session
- search_node(node_class, keywords, limit): 优先使用的节点检索工具。
- search_node_local(node_class, keywords, limit): 优先使用的本地已经安装好的节点的检索工具。
* 当你已经有候选节点类名(例如从其它工具返回的 class_name,如 "LayerColor: BrightnessContrastV2")时,将该类名作为 node_class 传入,keywords 传入与功能相关的少量关键词(如 ["brightness", "contrast"]),工具会先通过 /api/object_info/{node_class} 精确获取该节点的完整定义,如果命中则直接返回该节点信息。
* 当你只有功能/参数描述而没有明确类名时,可以将 node_class 置为空字符串 "",仅在 keywords 中传入 1~3 个尽量具体的英文或中文关键词(例如 "brightness"、"contrast"、"saturation"、"锐化" 等),工具会在所有节点中按名称、显示名、分类及输入参数名进行模糊搜索,返回带有 class_name、hit_params 和 score 的候选列表。
* 避免在 keywords 中使用过于宽泛的词(例如 "image"、"图像" 等),否则会导致搜索结果过多且不精确。
@@ -110,7 +110,7 @@ def create_workflow_rewrite_agent():
始终以用户的实际需求为导向,提供专业、准确、高效的工作流改写服务。
""",
tools=[get_rewrite_expert_by_name, get_current_workflow, search_node, get_node_infos, update_workflow, remove_node],
tools=[get_rewrite_expert_by_name, get_current_workflow, search_node_local, get_node_infos, update_workflow, remove_node],
config={
"max_tokens": 8192,
** config
+2 -2
View File
@@ -110,9 +110,9 @@ async def get_node_infos(node_class_list: list[str]) -> str:
return json.dumps({"error": f"Failed to get node infos of {','.join(node_class_list)}: {str(e)}"})
@function_tool
async def search_node(node_class: str = "", keywords: list[str] = None, limit: int = 10) -> str:
async def search_node_local(node_class: str = "", keywords: list[str] = None, limit: int = 10) -> str:
"""
综合节点搜索工具(node_class + keywords 联合检索):
节点的搜索工具(node_class + keywords 联合检索):
1. 优先使用 node_class 按节点类名精确查询。
2. 如果没有命中,则在全部节点中使用 node_class 和 keywords 做联合模糊搜索:
- 关键词会在节点类名、名称、显示名、分类、描述以及输入参数名中匹配。