From 1ed004fbb11713d3579465af92eb647f15a8f524 Mon Sep 17 00:00:00 2001 From: fengxiangdebaozi <10845145+fengxiangdebaozi@user.noreply.gitee.com> Date: Thu, 25 Jun 2026 22:50:10 +0800 Subject: [PATCH] =?UTF-8?q?fix(ai=E5=86=99=E4=BD=9C):=20=E5=BC=B1=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E4=B9=9F=E8=83=BD=E7=9C=9F=E6=AD=A3=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E6=8A=80=E8=83=BD=E8=84=9A=E6=9C=AC(=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E4=BC=98=E5=85=88=E7=9A=84=E5=BC=BA=E6=8F=90=E7=A4=BA)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 弱模型在 lead agent 能执行 py 脚本、在 ai写作子智能体却不能:根因是子智能体的 _MATERIAL_OUTPUT_CONTRACT 过度强调"只输出 JSON",弱模型据此跳过工具执行直接吐空 JSON。 对齐 lead agent 的 skill_system 强框架,把契约改成"执行优先": - 第一步强制先用 bash 实际运行技能脚本(给出 cd 技能目录 && python3 scripts/..py 的命令形态), 严禁不调用工具就直接输出 JSON/凭记忆编造 - JSON 输出降级为第二步"检索完成后再整理" - task 末尾追加"现在立刻开始执行检索"的强指令,进一步推动弱模型先动手 Co-Authored-By: Claude Opus 4.8 (1M context) --- .../agents/ai_writing/nodes/_skill_agent.py | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/offline-backend-20260512/backend/packages/harness/deerflow/agents/ai_writing/nodes/_skill_agent.py b/offline-backend-20260512/backend/packages/harness/deerflow/agents/ai_writing/nodes/_skill_agent.py index cfc5f316..b87f65e3 100644 --- a/offline-backend-20260512/backend/packages/harness/deerflow/agents/ai_writing/nodes/_skill_agent.py +++ b/offline-backend-20260512/backend/packages/harness/deerflow/agents/ai_writing/nodes/_skill_agent.py @@ -58,15 +58,23 @@ _REAL_AGENT_MAX_TURNS = 16 _REAL_AGENT_TIMEOUT_SECONDS = 300 _MATERIAL_OUTPUT_CONTRACT = ( - "你的任务:严格按上面挂载的检索技能(SKILL.md)的说明,用相应工具检索与「写作意图」相关的**真实素材**。\n" - "- 必须按技能说明实际调用工具完成检索(读取知识库文件 / 调用内网检索接口 / MCP 等),**不得凭记忆编造**。\n" - "- **某个检索词返回 0 条或报「请求超时」时,不要就此放弃**:请把它换成更核心、更简短的检索词再试一次" - "(去掉「竞选/诉讼/政策/动向」等话题后缀,只保留核心实体,例如「特朗普竞选」→「特朗普」、" - "「特朗普法律诉讼」→「特朗普」;多词时只留最关键的那个词)。\n" - "- **只要有任何检索词成功拿到了数据,就必须把这些数据全部收下并输出**,绝不能因为别的检索词没出结果/超时就丢弃已经检索到的素材。\n" - "- 检索完成后,**只输出一个 JSON 对象**(不要解释、不要 markdown 代码块、用英文双引号),把检索到的真实素材列出:\n" + "你的任务:用上面挂载的检索技能( 里的 SKILL.md)按它的说明**实际执行检索**," + "收集与「写作意图」相关的真实素材。\n" + "\n" + "【第一步 · 必须真正执行技能,绝不能跳过】\n" + "- 你**必须先实际调用工具去检索**,再谈输出。技能通常自带脚本——按 SKILL.md 的说明用 **bash** 运行它," + "例如:`cd <技能目录> && python3 scripts/xxx.py \"检索词\"`(具体脚本名/参数以 SKILL.md 为准)," + "或调用它说明里的内网接口 / MCP 工具。\n" + "- **严禁不调用任何工具就直接输出 JSON**,更不许凭记忆编造素材。哪怕你“觉得”知道答案,也必须真的去检索。\n" + "- 对每个检索方向各执行一次;可多次调用工具覆盖不同角度。\n" + "- 某个检索词返回 0 条或报「请求超时」时**不要放弃**:换成更核心、更短的检索词再试一次" + "(去掉「竞选/诉讼/政策/动向」等后缀,只留核心实体,如「特朗普竞选」→「特朗普」)。\n" + "\n" + "【第二步 · 检索完成后再整理输出】\n" + "- 把工具**实际返回**的真实素材整理成一个 JSON 对象(不要解释、不要 markdown 代码块、用英文双引号):\n" '{"materials": [{"title": "标题", "content": "素材正文摘录(尽量保留原文, <=500字)", "source": "来源", "url": "原文链接(可空)", "published_at": "日期(可空)"}]}\n' - "- content 必须来自检索到的真实内容;只有当**所有**检索词(含简化后重试)都没拿到任何素材时,才输出 {\"materials\": []}。" + "- content 必须来自工具实际返回的内容;只要有任何检索词拿到数据就**全部收下**,不要因别的检索词没结果而丢弃。\n" + "- 只有当你**确实执行了检索、且所有检索词(含简化重试)都没有结果**时,才输出 {\"materials\": []}。" ) @@ -318,6 +326,12 @@ async def run_skill_via_real_agent( if keywords: task_lines.append(f"可参考的检索方向:{', '.join(keywords[:8])}") task_lines.append(f"目标素材数量约 {max_results} 条。") + # 弱模型强提示:明确要求「先动手执行技能脚本」,避免它直接吐空 JSON 不检索。 + task_lines.append( + f"现在请**立刻开始执行检索**:按上面挂载技能的 SKILL.md,用 bash 运行它的脚本" + f"(如 `cd {skill_dir or '<技能目录>'} && python3 scripts/...py \"检索词\"`)实际检索," + "先执行工具拿到真实数据,再整理输出 JSON;不要不检索就直接输出。" + ) task = "\n".join(task_lines) sub_cfg = SubagentConfig(