瀏覽代碼

refactor: reflect after agent loop break

Talegorithm 13 小時之前
父節點
當前提交
dbdfd1972c
共有 1 個文件被更改,包括 16 次插入95 次删除
  1. 16 95
      agent/core/runner.py

+ 16 - 95
agent/core/runner.py

@@ -969,6 +969,8 @@ class AgentRunner:
                 # 重新计算 start_history_length
                 side_branch_ctx.start_history_length = len(history) - len(side_messages)
 
+        break_after_side_branch = False  # 侧分支退出后是否 break 主循环
+
         for iteration in range(config.max_iterations):
             # 更新活动时间(表明trace正在活跃运行)
             if self.trace_store:
@@ -1002,7 +1004,11 @@ class AgentRunner:
             # Context 管理(仅主路径)
             needs_enter_side_branch = False
             if not side_branch_ctx:
-                # 检查是否强制进入侧分支(API 手动触发)
+                # 侧分支退出后需要 break 主循环
+                if break_after_side_branch and not config.force_side_branch:
+                    break
+
+                # 检查是否强制进入侧分支(API 手动触发或自动压缩流程)
                 if config.force_side_branch:
                     needs_enter_side_branch = True
                     logger.info(f"强制进入侧分支: {config.force_side_branch}")
@@ -1521,12 +1527,16 @@ class AgentRunner:
 
                 continue  # 继续循环
 
-            # 无工具调用,任务完成
-            break
+            # 无工具调用
+            # 如果在侧分支中,已经在上面处理过了(不会走到这里)
+            # 主路径无工具调用 → 任务完成,检查是否需要完成后反思
+            if not side_branch_ctx and config.knowledge.enable_completion_extraction and not break_after_side_branch:
+                config.force_side_branch = ["reflection"]
+                break_after_side_branch = True
+                logger.info("任务完成,进入完成后反思侧分支")
+                continue
 
-        # 任务完成后复盘提取
-        if config.knowledge.enable_completion_extraction:
-            await self._extract_knowledge_on_completion(trace_id, history, config)
+            break
 
         # 清理 trace 相关的跟踪数据
         self._context_warned.pop(trace_id, None)
@@ -1595,95 +1605,6 @@ class AgentRunner:
 
         return new_history
 
-    async def _run_reflect(
-        self,
-        trace_id: str,
-        history: List[Dict],
-        config: RunConfig,
-        reflect_prompt: str,
-        source_name: str,
-    ) -> None:
-        """
-        执行反思提取:LLM 对历史消息进行反思,直接调用 knowledge_save 工具保存经验。
-
-        Args:
-            trace_id: Trace ID(作为知识的 message_id)
-            history: 当前对话历史
-            config: 运行配置
-            reflect_prompt: 反思 prompt
-            source_name: 来源名称(用于区分压缩时/完成时)
-        """
-        try:
-            reflect_messages = list(history) + [{"role": "user", "content": reflect_prompt}]
-            reflect_messages = self._add_cache_control(
-                reflect_messages, config.model, config.enable_prompt_caching
-            )
-
-            # 只暴露 knowledge_save 工具,让 LLM 直接调用
-            knowledge_save_schema = self._get_tool_schemas(["knowledge_save"])
-
-            reflect_result = await self.llm_call(
-                messages=reflect_messages,
-                model=config.model,
-                tools=knowledge_save_schema,
-                temperature=0.2,
-                **config.extra_llm_params,
-            )
-
-            tool_calls = reflect_result.get("tool_calls") or []
-            if not tool_calls:
-                logger.info("反思阶段无经验保存 (source=%s)", source_name)
-                return
-
-            saved_count = 0
-            for tc in tool_calls:
-                tool_name = tc.get("function", {}).get("name")
-                if tool_name != "knowledge_save":
-                    continue
-
-                tool_args = tc.get("function", {}).get("arguments") or {}
-                if isinstance(tool_args, str):
-                    tool_args = json.loads(tool_args) if tool_args.strip() else {}
-
-                # 注入来源信息(LLM 不需要填写这些字段)
-                tool_args.setdefault("source_name", source_name)
-                tool_args.setdefault("source_category", "exp")
-                tool_args.setdefault("message_id", trace_id)
-
-                try:
-                    await self.tools.execute(
-                        "knowledge_save",
-                        tool_args,
-                        uid=config.uid or "",
-                        context={
-                            "store": self.trace_store,
-                            "trace_id": trace_id,
-                            "knowledge_config": config.knowledge,
-                        },
-                    )
-                    saved_count += 1
-                except Exception as e:
-                    logger.warning("保存经验失败: %s", e)
-
-            logger.info("已提取并保存 %d 条经验 (source=%s)", saved_count, source_name)
-
-        except Exception as e:
-            logger.error("知识反思提取失败 (source=%s): %s", source_name, e)
-
-    async def _extract_knowledge_on_completion(
-        self,
-        trace_id: str,
-        history: List[Dict],
-        config: RunConfig,
-    ) -> None:
-        """任务完成后执行全局复盘,提取经验保存到知识库。"""
-        logger.info("任务完成后复盘提取: trace=%s", trace_id)
-        await self._run_reflect(
-            trace_id, history, config,
-            reflect_prompt=config.knowledge.get_completion_reflect_prompt(),
-            source_name="completion_reflection",
-        )
-
     # ===== 回溯(Rewind)=====
 
     async def _rewind(