|
|
@@ -26,7 +26,7 @@ from typing import AsyncIterator, Optional, Dict, Any, List, Callable, Literal,
|
|
|
from agent.trace.models import Trace, Message
|
|
|
from agent.trace.protocols import TraceStore
|
|
|
from agent.trace.goal_models import GoalTree
|
|
|
-from agent.tools.builtin.knowledge import _get_structured_knowledge, _batch_update_knowledge
|
|
|
+from agent.tools.builtin.knowledge import _get_structured_knowledge, _batch_update_knowledge, save_knowledge
|
|
|
from agent.trace.compaction import (
|
|
|
CompressionConfig,
|
|
|
filter_by_goal_status,
|
|
|
@@ -228,13 +228,8 @@ class AgentRunner:
|
|
|
self.utility_llm_call = utility_llm_call
|
|
|
self.config = config or AgentConfig()
|
|
|
self.skills_dir = skills_dir
|
|
|
- # 确保 experiences_path 不为 None,且文件存在
|
|
|
+ # 保留 experiences_path 参数以向后兼容,但不再使用(经验已迁移到知识系统)
|
|
|
self.experiences_path = experiences_path or "./.cache/experiences.md"
|
|
|
- if not os.path.exists(self.experiences_path):
|
|
|
- os.makedirs(os.path.dirname(self.experiences_path), exist_ok=True)
|
|
|
- with open(self.experiences_path, "w", encoding="utf-8") as f:
|
|
|
- f.write("")
|
|
|
- logger.info(f"自动创建经验文件: {self.experiences_path}")
|
|
|
self.goal_tree = goal_tree
|
|
|
self.debug = debug
|
|
|
self._cancel_events: Dict[str, asyncio.Event] = {} # trace_id → cancel event
|
|
|
@@ -243,6 +238,9 @@ class AgentRunner:
|
|
|
# 研究流程状态管理(每个 trace 独立)
|
|
|
self._research_states: Dict[str, Dict[str, Any]] = {} # trace_id → research_state
|
|
|
|
|
|
+ # 知识保存跟踪(每个 trace 独立)
|
|
|
+ self._saved_knowledge_ids: Dict[str, List[str]] = {} # trace_id → [knowledge_ids]
|
|
|
+
|
|
|
# ===== 核心公开方法 =====
|
|
|
|
|
|
async def run(
|
|
|
@@ -356,11 +354,16 @@ class AgentRunner:
|
|
|
status = "failed"
|
|
|
error = error or "Agent 没有产生 assistant 文本结果"
|
|
|
|
|
|
+ # 获取保存的知识 ID
|
|
|
+ trace_id = final_trace.trace_id if final_trace else config.trace_id
|
|
|
+ saved_knowledge_ids = self._saved_knowledge_ids.get(trace_id, [])
|
|
|
+
|
|
|
return {
|
|
|
"status": status,
|
|
|
"summary": summary,
|
|
|
- "trace_id": final_trace.trace_id if final_trace else config.trace_id,
|
|
|
+ "trace_id": trace_id,
|
|
|
"error": error,
|
|
|
+ "saved_knowledge_ids": saved_knowledge_ids, # 新增:返回保存的知识 ID
|
|
|
"stats": {
|
|
|
"total_messages": final_trace.total_messages if final_trace else 0,
|
|
|
"total_tokens": final_trace.total_tokens if final_trace else 0,
|
|
|
@@ -670,20 +673,18 @@ class AgentRunner:
|
|
|
"""
|
|
|
初始化研究流程状态
|
|
|
|
|
|
- 研究流程阶段:
|
|
|
- 1. knowledge_search: 知识库检索
|
|
|
- 2. experience_search: 经验库检索
|
|
|
- 3. research_decision: 决定是否需要调研
|
|
|
- 4. research: 执行调研(如果需要)
|
|
|
- 5. planning: 制定计划
|
|
|
- 6. execution: 正常执行
|
|
|
+ 研究流程阶段(已简化):
|
|
|
+ 1. research_decision: 决定是否需要调研(知识和经验已自动注入到 GoalTree)
|
|
|
+ 2. research: 执行调研(如果需要)
|
|
|
+ 3. planning: 制定计划
|
|
|
+ 4. execution: 正常执行
|
|
|
"""
|
|
|
# 提取任务描述
|
|
|
task_desc = self._extract_task_description(messages)
|
|
|
|
|
|
- # 初始化研究状态
|
|
|
+ # 初始化研究状态(直接从 research_decision 开始,因为知识已自动注入)
|
|
|
self._research_states[trace_id] = {
|
|
|
- "stage": "knowledge_search", # 当前阶段
|
|
|
+ "stage": "research_decision", # 直接进入决策阶段
|
|
|
"task_desc": task_desc,
|
|
|
"knowledge_found": False,
|
|
|
"experience_found": False,
|
|
|
@@ -692,9 +693,10 @@ class AgentRunner:
|
|
|
"planning_completed": False,
|
|
|
"knowledge_results": [],
|
|
|
"experience_results": [],
|
|
|
+ "decision_guide_injected": False, # 防止重复注入决策引导
|
|
|
}
|
|
|
|
|
|
- logger.info(f"[Research Flow] 初始化研究流程: {task_desc[:50]}...")
|
|
|
+ logger.info(f"[Research Flow] 初始化研究流程(知识已自动注入): {task_desc[:50]}...")
|
|
|
|
|
|
def _extract_task_description(self, messages: List[Dict]) -> str:
|
|
|
"""从消息中提取任务描述"""
|
|
|
@@ -725,37 +727,7 @@ class AgentRunner:
|
|
|
stage = research_state["stage"]
|
|
|
task_desc = research_state["task_desc"]
|
|
|
|
|
|
- if stage == "knowledge_search":
|
|
|
- return f"""
|
|
|
-## 🔍 研究流程 - 阶段 1: 知识库检索
|
|
|
-
|
|
|
-当前任务: {task_desc}
|
|
|
-
|
|
|
-**请立即执行以下操作**:
|
|
|
-1. 使用 `search_knowledge(query="{task_desc[:100]}")` 检索知识库
|
|
|
-2. 检查返回的知识是否足够完成任务
|
|
|
-3. 如果找到相关知识,记录下来并继续下一阶段
|
|
|
-
|
|
|
-注意:这是强制步骤,必须先检索知识库再继续。
|
|
|
-"""
|
|
|
-
|
|
|
- elif stage == "experience_search":
|
|
|
- knowledge_results = research_state.get("knowledge_results", [])
|
|
|
- knowledge_summary = f"找到 {len(knowledge_results)} 条相关知识" if knowledge_results else "未找到相关知识"
|
|
|
-
|
|
|
- return f"""
|
|
|
-## 🔍 研究流程 - 阶段 2: 经验库检索
|
|
|
-
|
|
|
-知识库检索结果: {knowledge_summary}
|
|
|
-
|
|
|
-**请立即执行以下操作**:
|
|
|
-1. 使用 `get_experience(query="{task_desc[:100]}", k=3)` 检索经验库
|
|
|
-2. 结合知识库和经验库的结果,评估是否需要进行调研
|
|
|
-3. 如果经验和知识库不足时,必须调用子agent来执行调研
|
|
|
-注意:这是强制步骤,必须检索经验库。
|
|
|
-"""
|
|
|
-
|
|
|
- elif stage == "research":
|
|
|
+ if stage == "research":
|
|
|
# 读取 research.md 的内容
|
|
|
research_skill_content = ""
|
|
|
research_skill_path = os.path.join(
|
|
|
@@ -770,7 +742,7 @@ class AgentRunner:
|
|
|
research_skill_content = "(无法加载 research.md 内容)"
|
|
|
|
|
|
return f"""
|
|
|
-## 📚 研究流程 - 阶段 4: 执行调研
|
|
|
+## 📚 研究流程 - 执行调研
|
|
|
|
|
|
现有信息不足,需要进行调研。
|
|
|
|
|
|
@@ -783,7 +755,7 @@ class AgentRunner:
|
|
|
|
|
|
elif stage == "planning":
|
|
|
return f"""
|
|
|
-## 📋 研究流程 - 阶段 5: 制定计划
|
|
|
+## 📋 研究流程 - 制定计划
|
|
|
|
|
|
调研已完成(或无需调研),现在请制定执行计划。
|
|
|
|
|
|
@@ -799,50 +771,38 @@ class AgentRunner:
|
|
|
return ""
|
|
|
|
|
|
def _build_research_decision_guide(self, research_state: Dict[str, Any]) -> str:
|
|
|
- """构建调研决策阶段的引导消息(追加在经验检索消息后)"""
|
|
|
- knowledge_results = research_state.get("knowledge_results", [])
|
|
|
+ """构建调研决策阶段的引导消息(基于已自动注入的知识和经验)"""
|
|
|
experience_results = research_state.get("experience_results", [])
|
|
|
task_desc = research_state.get("task_desc", "")
|
|
|
|
|
|
- # 构建知识库摘要
|
|
|
- knowledge_summary = "### 知识库检索结果\n\n"
|
|
|
- if knowledge_results:
|
|
|
- knowledge_summary += f"找到 {len(knowledge_results)} 条相关知识:\n\n"
|
|
|
- for i, item in enumerate(knowledge_results[:5], 1): # 最多显示 5 条
|
|
|
- tags = item.get("tags", [])
|
|
|
- summary = item.get("summary", "")
|
|
|
- knowledge_summary += f"{i}. [{', '.join(tags)}] {summary[:150]}...\n"
|
|
|
- if len(knowledge_results) > 5:
|
|
|
- knowledge_summary += f"\n(还有 {len(knowledge_results) - 5} 条知识未显示)\n"
|
|
|
- else:
|
|
|
- knowledge_summary += "❌ 未找到相关知识\n"
|
|
|
-
|
|
|
- # 构建经验库摘要
|
|
|
- experience_summary = "\n### 经验库检索结果\n\n"
|
|
|
+ # 构建经验摘要
|
|
|
+ experience_summary = ""
|
|
|
if experience_results:
|
|
|
- experience_summary += f"找到 {len(experience_results)} 条相关经验\n"
|
|
|
+ experience_summary = f"✅ 已自动检索到 {len(experience_results)} 条相关经验(见上方 GoalTree 中的「📚 相关知识」)\n"
|
|
|
else:
|
|
|
- experience_summary += "❌ 未找到相关经验\n"
|
|
|
+ experience_summary = "❌ 未找到相关经验\n"
|
|
|
|
|
|
return f"""
|
|
|
---
|
|
|
|
|
|
## 🤔 调研决策
|
|
|
|
|
|
-{knowledge_summary}
|
|
|
{experience_summary}
|
|
|
|
|
|
-### 决策选项
|
|
|
+### 决策指南
|
|
|
+
|
|
|
+**当前状态**:系统已自动检索知识库和经验库,相关内容已注入到上方的 GoalTree 中(查看 Current Goal 下的「📚 相关知识」部分)。
|
|
|
+
|
|
|
+**请根据已注入的知识和经验,选择下一步行动**:
|
|
|
|
|
|
-**选项 1: 无需调研,直接制定计划**
|
|
|
-- 如果现有知识和经验已经足够
|
|
|
+**选项 1: 知识充足,直接制定计划**
|
|
|
+- 如果上方显示的知识和经验已经足够完成任务
|
|
|
- 直接使用 `goal` 工具制定执行计划
|
|
|
|
|
|
-**选项 2: 需要深入调研** ⭐
|
|
|
-- 如果现有知识不足,需要进行网络搜索、文档查阅等调研
|
|
|
+**选项 2: 知识不足,需要调研** ⭐
|
|
|
+- 如果上方没有显示相关知识,或现有知识不足以完成任务
|
|
|
- **立即调用 `agent` 工具启动调研子任务**:
|
|
|
-- 如果没有经验/知识,必须要先调研才可以继续执行
|
|
|
-- 无论任务描述是否确定。都需要先调研
|
|
|
+
|
|
|
```python
|
|
|
agent(
|
|
|
task=\"\"\"针对任务「{task_desc[:100]}」进行深入调研:
|
|
|
@@ -860,12 +820,14 @@ agent(
|
|
|
- strategy: 策略经验
|
|
|
|
|
|
调研完成后,系统会自动进入计划阶段。
|
|
|
-\"\"\"
|
|
|
+\"\"\",
|
|
|
+ skills=["research"] # 注入调研指南
|
|
|
)
|
|
|
```
|
|
|
|
|
|
**重要提示**:
|
|
|
-- 如果知识库和经验库都没有找到相关内容,必须选择调研!但只需要简单调研,最多设立两个goal。
|
|
|
+- 如果 GoalTree 中没有显示「📚 相关知识」,说明知识库为空,必须先调研
|
|
|
+- 调研应该简洁高效,最多设立两个 goal
|
|
|
"""
|
|
|
|
|
|
async def _handle_research_flow_transition(
|
|
|
@@ -882,53 +844,13 @@ agent(
|
|
|
|
|
|
stage = research_state["stage"]
|
|
|
|
|
|
- # 阶段 1: 知识库检索完成
|
|
|
- if stage == "knowledge_search" and tool_name == "search_knowledge":
|
|
|
- # 提取知识检索结果
|
|
|
- # tool_result 现在总是 dict,包含 {"text": ..., "metadata": ...}
|
|
|
- items = []
|
|
|
- if isinstance(tool_result, dict):
|
|
|
- metadata = tool_result.get("metadata", {})
|
|
|
- items = metadata.get("items", [])
|
|
|
-
|
|
|
- self._update_research_stage(
|
|
|
- trace_id,
|
|
|
- "experience_search",
|
|
|
- knowledge_found=len(items) > 0,
|
|
|
- knowledge_results=items
|
|
|
- )
|
|
|
- logger.info(f"[Research Flow] 知识检索完成,找到 {len(items)} 条知识")
|
|
|
-
|
|
|
- # 阶段 2: 经验库检索完成
|
|
|
- elif stage == "experience_search" and tool_name == "get_experience":
|
|
|
- # 提取经验检索结果
|
|
|
- experience_items = []
|
|
|
- if isinstance(tool_result, dict):
|
|
|
- experience_items = tool_result.get("items", [])
|
|
|
- elif isinstance(tool_result, str):
|
|
|
- # 解析字符串结果
|
|
|
- try:
|
|
|
- import json
|
|
|
- parsed = json.loads(tool_result)
|
|
|
- experience_items = parsed.get("items", [])
|
|
|
- except:
|
|
|
- pass
|
|
|
-
|
|
|
- self._update_research_stage(
|
|
|
- trace_id,
|
|
|
- "research_decision",
|
|
|
- experience_found=len(experience_items) > 0,
|
|
|
- experience_results=experience_items
|
|
|
- )
|
|
|
- logger.info(f"[Research Flow] 经验检索完成,找到 {len(experience_items)} 条经验")
|
|
|
-
|
|
|
- # 阶段 3: 调研决策(通过 assistant 的文本回复判断)
|
|
|
- # 这个阶段的转换在 assistant 回复后处理,不在这里
|
|
|
+ # 阶段 1: 调研决策(通过 assistant 的文本回复或 agent 工具调用判断)
|
|
|
+ # 这个阶段的转换在 assistant 回复后处理,或检测到 agent 工具调用
|
|
|
|
|
|
- # 阶段 4: 调研完成
|
|
|
+ # 阶段 2: 调研完成
|
|
|
# 情况 1: 检测到 save_knowledge 调用(直接调研)
|
|
|
# 情况 2: 检测到 agent 工具执行完成(子 agent 调研)
|
|
|
- elif stage == "research":
|
|
|
+ if stage == "research":
|
|
|
if tool_name == "save_knowledge":
|
|
|
# 直接调研:检测到 save_knowledge 调用
|
|
|
self._update_research_stage(
|
|
|
@@ -946,7 +868,7 @@ agent(
|
|
|
)
|
|
|
logger.info(f"[Research Flow] 调研完成(子 agent 调研),进入计划阶段")
|
|
|
|
|
|
- # 阶段 5: 计划完成(检测到 goal 工具调用)
|
|
|
+ # 阶段 3: 计划完成(检测到 goal 工具调用)
|
|
|
elif stage == "planning" and tool_name == "goal":
|
|
|
# 检查是否创建了 goal tree
|
|
|
if goal_tree and goal_tree.goals:
|
|
|
@@ -1150,9 +1072,14 @@ agent(
|
|
|
query_text=current_goal.description,
|
|
|
top_k=3,
|
|
|
context={"runner": self},
|
|
|
- tags_filter=["strategy"] # 只检索经验(strategy 标签)
|
|
|
)
|
|
|
if relevant_exps:
|
|
|
+ # 保存到 goal 对象
|
|
|
+ current_goal.knowledge = relevant_exps
|
|
|
+ logger.info(f"[Knowledge Injection] 已将 {len(relevant_exps)} 条知识注入到 goal {current_goal.id}: {current_goal.description[:40]}")
|
|
|
+ logger.debug(f"[Knowledge Injection] 注入的知识 IDs: {[exp.get('id') for exp in relevant_exps]}")
|
|
|
+ # 持久化保存 goal_tree
|
|
|
+ await self.trace_store.update_goal_tree(trace_id, goal_tree)
|
|
|
self.used_ex_ids = [exp['id'] for exp in relevant_exps]
|
|
|
parts = [f"[{exp['id']}] {exp['content']}" for exp in relevant_exps]
|
|
|
_cached_exp_text = "## 参考历史经验\n" + "\n\n".join(parts)
|
|
|
@@ -1163,6 +1090,10 @@ agent(
|
|
|
self.used_ex_ids,
|
|
|
)
|
|
|
else:
|
|
|
+ current_goal.knowledge = []
|
|
|
+ logger.info(f"[Knowledge Injection] goal {current_goal.id} 未找到相关知识")
|
|
|
+ # 持久化保存 goal_tree
|
|
|
+ await self.trace_store.update_goal_tree(trace_id, goal_tree)
|
|
|
_cached_exp_text = ""
|
|
|
logger.info(
|
|
|
"经验检索: goal='%s', 未找到相关经验",
|
|
|
@@ -1170,29 +1101,22 @@ agent(
|
|
|
)
|
|
|
except Exception as e:
|
|
|
logger.warning("经验检索失败: %s", e)
|
|
|
+ current_goal.knowledge = []
|
|
|
_cached_exp_text = ""
|
|
|
|
|
|
- # 如果处于 experience_search 阶段,自动转换到 research_decision 阶段
|
|
|
- research_state = self._get_research_state(trace_id)
|
|
|
- if research_state and research_state["stage"] == "experience_search":
|
|
|
- self._update_research_stage(
|
|
|
- trace_id,
|
|
|
- "research_decision",
|
|
|
- experience_found=len(relevant_exps) > 0 if relevant_exps else False,
|
|
|
- experience_results=relevant_exps if relevant_exps else []
|
|
|
- )
|
|
|
- logger.info(f"[Research Flow] 经验检索完成(自动触发),找到 {len(relevant_exps) if relevant_exps else 0} 条经验,进入调研决策阶段")
|
|
|
-
|
|
|
# 经验注入:goal切换时注入相关历史经验 - 改为 user 消息
|
|
|
# 或者在 research_decision 阶段注入调研决策引导
|
|
|
- if _cached_exp_text or (research_state and research_state["stage"] == "research_decision"):
|
|
|
+ if _cached_exp_text or (research_state and research_state["stage"] == "research_decision" and not research_state.get("decision_guide_injected", False)):
|
|
|
exp_content = _cached_exp_text if _cached_exp_text else ""
|
|
|
|
|
|
# 如果处于 research_decision 阶段,追加引导消息
|
|
|
- if research_state and research_state["stage"] == "research_decision":
|
|
|
+ if research_state and research_state["stage"] == "research_decision" and not research_state.get("decision_guide_injected", False):
|
|
|
if exp_content:
|
|
|
exp_content += "\n\n"
|
|
|
exp_content += self._build_research_decision_guide(research_state)
|
|
|
+ # 标记已注入,防止重复
|
|
|
+ research_state["decision_guide_injected"] = True
|
|
|
+ logger.info("[Research Flow] 已注入调研决策引导消息")
|
|
|
|
|
|
if exp_content: # 确保有内容才注入
|
|
|
user_msg = {"role": "user", "content": exp_content}
|
|
|
@@ -1399,6 +1323,16 @@ agent(
|
|
|
}
|
|
|
)
|
|
|
|
|
|
+ # 跟踪保存的知识 ID
|
|
|
+ if tool_name == "save_knowledge" and isinstance(tool_result, dict):
|
|
|
+ metadata = tool_result.get("metadata", {})
|
|
|
+ knowledge_id = metadata.get("knowledge_id")
|
|
|
+ if knowledge_id:
|
|
|
+ if trace_id not in self._saved_knowledge_ids:
|
|
|
+ self._saved_knowledge_ids[trace_id] = []
|
|
|
+ self._saved_knowledge_ids[trace_id].append(knowledge_id)
|
|
|
+ logger.info(f"[Knowledge Tracking] 记录保存的知识 ID: {knowledge_id}")
|
|
|
+
|
|
|
# --- 支持多模态工具反馈 ---
|
|
|
# execute() 返回 dict{"text", "images", "metadata"} 或 str
|
|
|
if isinstance(tool_result, dict):
|
|
|
@@ -1594,10 +1528,54 @@ created_at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
|
|
|
structured_entries.append(entry)
|
|
|
|
|
|
if structured_entries:
|
|
|
- os.makedirs(os.path.dirname(self.experiences_path), exist_ok=True)
|
|
|
- with open(self.experiences_path, "a", encoding="utf-8") as f:
|
|
|
- f.write("\n\n" + "\n\n".join(structured_entries))
|
|
|
- logger.info(f"已提取并保存 {len(structured_entries)} 条结构化经验")
|
|
|
+ # 保存经验为知识(strategy 标签)
|
|
|
+ saved_count = 0
|
|
|
+ for entry in structured_entries:
|
|
|
+ try:
|
|
|
+ # 从 entry 中提取信息
|
|
|
+ lines = entry.split("\n")
|
|
|
+ ex_id = ""
|
|
|
+ intents = []
|
|
|
+ states = []
|
|
|
+ content = ""
|
|
|
+
|
|
|
+ for line in lines:
|
|
|
+ if line.startswith("id:"):
|
|
|
+ ex_id = line.split(":", 1)[1].strip()
|
|
|
+ elif line.startswith("tags:"):
|
|
|
+ tags_match = _re2.search(r"intent:\s*\[(.*?)\].*state:\s*\[(.*?)\]", line)
|
|
|
+ if tags_match:
|
|
|
+ intents_str = tags_match.group(1).strip("'\"")
|
|
|
+ states_str = tags_match.group(2).strip("'\"")
|
|
|
+ intents = [i.strip().strip("'\"") for i in intents_str.split(",") if i.strip()]
|
|
|
+ states = [s.strip().strip("'\"") for s in states_str.split(",") if s.strip()]
|
|
|
+ elif line.startswith("- ") and not line.startswith("- 经验ID:"):
|
|
|
+ content = line[2:].strip()
|
|
|
+
|
|
|
+ # 构建 scenario(从 intent 和 state 生成)
|
|
|
+ scenario_parts = []
|
|
|
+ if intents:
|
|
|
+ scenario_parts.append(f"意图: {', '.join(intents)}")
|
|
|
+ if states:
|
|
|
+ scenario_parts.append(f"状态: {', '.join(states)}")
|
|
|
+ scenario = " | ".join(scenario_parts) if scenario_parts else "通用经验"
|
|
|
+
|
|
|
+ # 调用 save_knowledge 保存为 strategy 标签的知识
|
|
|
+ await save_knowledge(
|
|
|
+ scenario=scenario,
|
|
|
+ content=content,
|
|
|
+ tags_type=["strategy"],
|
|
|
+ urls=[],
|
|
|
+ agent_id="runner",
|
|
|
+ score=3,
|
|
|
+ trace_id=trace_id
|
|
|
+ )
|
|
|
+ saved_count += 1
|
|
|
+ except Exception as e:
|
|
|
+ logger.warning(f"保存经验失败: {e}")
|
|
|
+ continue
|
|
|
+
|
|
|
+ logger.info(f"已提取并保存 {saved_count}/{len(structured_entries)} 条结构化经验到知识库")
|
|
|
else:
|
|
|
logger.warning("未能解析出符合格式的经验条目,请检查 REFLECT_PROMPT。")
|
|
|
logger.debug(f"LLM Raw Output:\n{reflection_text}")
|
|
|
@@ -1644,16 +1622,17 @@ created_at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
|
|
|
import re as _re
|
|
|
update_map = {}
|
|
|
for line in eval_block.splitlines():
|
|
|
- m = _re.search(r"ID:\s*(ex_\S+)\s*\|\s*Result:\s*(\w+)", line)
|
|
|
+ # 匹配新的知识 ID 格式:knowledge-xxx 或 research-xxx
|
|
|
+ m = _re.search(r"ID:\s*((?:knowledge|research)-\S+)\s*\|\s*Result:\s*(\w+)", line)
|
|
|
if m:
|
|
|
- ex_id, result = m.group(1), m.group(2).lower()
|
|
|
+ knowledge_id, result = m.group(1), m.group(2).lower()
|
|
|
if result in ("helpful", "harmful"):
|
|
|
- update_map[ex_id] = {"action": result, "feedback": ""}
|
|
|
+ update_map[knowledge_id] = {"action": result, "feedback": ""}
|
|
|
elif result == "mixed":
|
|
|
- update_map[ex_id] = {"action": "helpful", "feedback": ""}
|
|
|
+ update_map[knowledge_id] = {"action": "helpful", "feedback": ""}
|
|
|
if update_map:
|
|
|
count = await _batch_update_knowledge(update_map, context={"runner": self})
|
|
|
- logger.info("经验评估完成,更新了 %s 条经验", count)
|
|
|
+ logger.info("知识评估完成,更新了 %s 条知识", count)
|
|
|
except Exception as e:
|
|
|
logger.warning("经验评估解析失败(不影响压缩): %s", e)
|
|
|
|