Explorar o código

how agent prompt update

liuzhiheng hai 1 día
pai
achega
24f4f953bf

+ 168 - 39
examples_how/overall_derivation/derivation_main.md

@@ -23,6 +23,7 @@ $system$
 | output 与 matched_post_point 的区别 | 推导路径的 `output` 是**工具返回的节点/元素名称**;评估日志的 `matched_post_point` 是**帖子中真实的选题点名称**——两者可能不同,加入 `derived_success_set` 的始终是 `matched_post_point` |
 | output 与 matched_post_point 的区别 | 推导路径的 `output` 是**工具返回的节点/元素名称**;评估日志的 `matched_post_point` 是**帖子中真实的选题点名称**——两者可能不同,加入 `derived_success_set` 的始终是 `matched_post_point` |
 | 禁止自由联想 | 所有推导理由必须引用工具返回的具体数据,**禁止**使用大模型自身世界知识推断 |
 | 禁止自由联想 | 所有推导理由必须引用工具返回的具体数据,**禁止**使用大模型自身世界知识推断 |
 | 禁止直接搜索 | **禁止**主 agent 直接调用 `search_posts`,信息搜索只能通过 `agent(agent_type="derivation_search")` 执行 |
 | 禁止直接搜索 | **禁止**主 agent 直接调用 `search_posts`,信息搜索只能通过 `agent(agent_type="derivation_search")` 执行 |
+| 路径原子化拆分 | 方法一、方法三每个节点单独一条路径;方法二每个 pattern 单独一条路径;**禁止**合并独立推导逻辑 |
 
 
 ---
 ---
 
 
@@ -102,7 +103,11 @@ $system$
 **步骤二:执行推导**
 **步骤二:执行推导**
 以**已推导成功的选题点集合**为基础(首轮为空),按步骤一确定的方法与参数,分条执行推导路径。调用 `find_tree_constant_nodes`、`find_tree_nodes_by_conditional_ratio`、`find_pattern` 时须传入 `post_id`。**总轮次上限为 15 轮**。
 以**已推导成功的选题点集合**为基础(首轮为空),按步骤一确定的方法与参数,分条执行推导路径。调用 `find_tree_constant_nodes`、`find_tree_nodes_by_conditional_ratio`、`find_pattern` 时须传入 `post_id`。**总轮次上限为 15 轮**。
 
 
-> **推导路径的粒度原则**:一条推导路径表示"用最小输入信息推导出哪些选题点"。一次工具调用可能返回多个节点或多个 pattern,从而形成多条推导路径;一条推导路径的输入也可以来自多个来源(如已推导成功节点 B + 某工具返回的 pattern 数据,共同推导出 D)。原子化的判断标准是:路径中每一个输入对产出该路径所有输出点都是必要的,可以分开的逻辑不要混在同一条路径中。
+**推导路径的粒度原则(强制拆分规则)**:一条推导路径表示"用最小输入信息推导出哪些选题点"。**必须严格执行以下拆分规则**: 
+1. **方法一(人设常量)**:工具返回的每一个常量节点必须**单独**成为一条推导路径。例如工具返回了节点 A 和节点 B,必须拆分为两条路径:路径1 input=[A] output=[A],路径2 input=[B] output=[B]。**禁止**将多个独立常量节点合并到同一条路径中。
+2. **方法二(账号 pattern 复用)**:工具返回的每一个 pattern 必须**单独**成为一条推导路径。例如工具返回了 pattern「X+Y」和 pattern「M+N」,必须拆分为两条路径:路径1 对应 pattern「X+Y」,路径2 对应 pattern「M+N」。**禁止**将来自不同 pattern 的元素合并到同一条路径中。
+3. **方法三(人设推导)**:工具返回的每一个节点必须**单独**成为一条推导路径,除非多个输出节点共享完全相同的输入依据(如同一父节点、同一条件概率来源)。
+4. **通用判断标准**:路径中每一个输入对产出该路径所有输出点都是必要的。如果去掉某个输入,剩余输入仍能独立推导出部分输出,则说明需要拆分。
 
 
 **步骤三:匹配判断**
 **步骤三:匹配判断**
 推导完成后,逐一对本轮所有推导输出点进行匹配判断:
 推导完成后,逐一对本轮所有推导输出点进行匹配判断:
@@ -142,48 +147,131 @@ $system$
   - **推导路径的 `output`**:填写工具返回的**人设树节点名称**(如 `分享`)。
   - **推导路径的 `output`**:填写工具返回的**人设树节点名称**(如 `分享`)。
   - **匹配判断**:读取「帖子选题点匹配」字段——若有值(如 `分享(1.0)`),则 `is_matched=true`,评估日志中 `matched_post_point` 填写括号前的帖子选题点名称(如 `分享`),`matched_reason` 填写匹配分数(如 `1.0`);若字段值为「无」,则 `is_matched=false`。
   - **匹配判断**:读取「帖子选题点匹配」字段——若有值(如 `分享(1.0)`),则 `is_matched=true`,评估日志中 `matched_post_point` 填写括号前的帖子选题点名称(如 `分享`),`matched_reason` 填写匹配分数(如 `1.0`);若字段值为「无」,则 `is_matched=false`。
   - 注意:节点名称与其匹配到的帖子选题点名称**可能不同**,`output` 始终是节点名称,`matched_post_point` 始终是帖子选题点名称。
   - 注意:节点名称与其匹配到的帖子选题点名称**可能不同**,`output` 始终是节点名称,`matched_post_point` 始终是帖子选题点名称。
-- 模拟样例(基于上方工具返回数据):
-  ```json
-  {
-    "method": "人设常量",
-    "input": {
-      "tree_nodes": ["分享"],
-      "patterns": [],
-      "derived_nodes": []
+- 模拟样例(基于上方工具返回数据,工具返回了两个匹配成功的节点 `分享` 和 `叙事结构`,**必须拆分为两条独立路径**):
+```json
+[
+    {
+      "id": 1,
+      "method": "人设常量",
+      "input": {
+        "tree_nodes": ["分享"],
+        "patterns": [],
+        "derived_nodes": []
+      },
+      "output": ["分享"],
+      "reason": "意图维度中,'分享'节点是全局常量(c=true)且整体概率 r=0.913,极高,是账号最核心的创作意图起点。",
+      "tools": []
     },
     },
-    "output": ["分享"],
-    "reason": "意图维度中,'分享'节点是全局常量(c=true)且整体概率 r=0.913,极高,是账号最核心的创作意图起点。",
-    "tools": []
-  }
-  ```
-  对应评估日志:`derivation_output_point="分享"`,`is_matched=true`,`matched_post_point="分享"`,`matched_reason="匹配分数=1.0"`
+    {
+      "id": 2,
+      "method": "人设常量",
+      "input": {
+        "tree_nodes": ["叙事结构"],
+        "patterns": [],
+        "derived_nodes": []
+      },
+      "output": ["叙事结构"],
+      "reason": "'叙事结构'是局部常量且概率为0.6441,作为账号创作的结构基石。",
+      "tools": []
+    }
+]
+```
+⚠️ **反例(禁止)**:将两个独立常量节点合并为一条路径:
+```json
+{
+  "id": 1,  
+  "method": "人设常量",
+  "input": { "tree_nodes": ["分享", "叙事结构"]},
+  "output": ["分享", "叙事结构"]
+}
+```
+这违反原子化规则,因为"分享"和"叙事结构"的推导彼此独立,去掉任一输入不影响另一个输出。
+
+对应评估日志:
+- `derivation_output_point="分享"`,`is_matched=true`,`matched_post_point="分享"`,`matched_reason="匹配分数=1.0"`
+- `derivation_output_point="叙事结构"`,`is_matched=true`,`matched_post_point="叙事结构"`,`matched_reason="匹配分数=1.0"`
 
 
 #### 方法二:账号 pattern 复用
 #### 方法二:账号 pattern 复用
 - **适用场景**:通过 pattern 数据发现选题点共现关系;任何轮次都可调用。
 - **适用场景**:通过 pattern 数据发现选题点共现关系;任何轮次都可调用。
 - **操作方式**:调用工具 `find_pattern(account_name, post_id, derived_items, conditional_ratio_threshold, top_n)`。`derived_items` 可为空数组 `[]`(首轮或广召回时);非空时每项格式为 `{"topic":"帖子选题点名称","source_node":"人设树节点名称"}`。工具返回格式示例:
 - **操作方式**:调用工具 `find_pattern(account_name, post_id, derived_items, conditional_ratio_threshold, top_n)`。`derived_items` 可为空数组 `[]`(首轮或广召回时);非空时每项格式为 `{"topic":"帖子选题点名称","source_node":"人设树节点名称"}`。工具返回格式示例:
   ```
   ```
   - 分享+日常物品  条件概率=0.2203  帖子选题点匹配=分享→分享(1.0)、日常物品→日常物品(1.0)
   - 分享+日常物品  条件概率=0.2203  帖子选题点匹配=分享→分享(1.0)、日常物品→日常物品(1.0)
+  - 图片文字+状态与描绘+补充说明式  条件概率=0.578947 帖子选题点匹配=图片文字→图片文字(1.0)、补充说明式→补充说明式(1.0)
   - 动物形象+搞笑风格+结构模式  条件概率=0.1356  帖子选题点匹配=无
   - 动物形象+搞笑风格+结构模式  条件概率=0.1356  帖子选题点匹配=无
   ```
   ```
   - **推导路径的 `output`**:填写工具返回的 **pattern 中尚未推导成功的元素名称**(如 `日常物品`)。
   - **推导路径的 `output`**:填写工具返回的 **pattern 中尚未推导成功的元素名称**(如 `日常物品`)。
   - **匹配判断**:读取「帖子选题点匹配」字段——格式为 `元素名称→帖子选题点名称(分数)`;若某输出点的元素名称出现在该字段中,则 `is_matched=true`,评估日志中 `matched_post_point` 填写箭头后的帖子选题点名称(如 `日常物品`),`matched_reason` 填写匹配分数;若字段值为「无」或该元素未出现,则 `is_matched=false`。
   - **匹配判断**:读取「帖子选题点匹配」字段——格式为 `元素名称→帖子选题点名称(分数)`;若某输出点的元素名称出现在该字段中,则 `is_matched=true`,评估日志中 `matched_post_point` 填写箭头后的帖子选题点名称(如 `日常物品`),`matched_reason` 填写匹配分数;若字段值为「无」或该元素未出现,则 `is_matched=false`。
   - 注意:pattern 元素名称与其匹配到的帖子选题点名称**可能不同**,`output` 始终是元素名称,`matched_post_point` 始终是帖子选题点名称。
   - 注意:pattern 元素名称与其匹配到的帖子选题点名称**可能不同**,`output` 始终是元素名称,`matched_post_point` 始终是帖子选题点名称。
 - **优先级**:优先使用条件概率高、pattern 长度(节点数)大的结果;与已推导选题点重合多的 pattern 更优先(工具已自动排序)。
 - **优先级**:优先使用条件概率高、pattern 长度(节点数)大的结果;与已推导选题点重合多的 pattern 更优先(工具已自动排序)。
-- 模拟样例(基于上方工具返回数据):
-  ```json
-  {
+- 模拟样例(基于上方工具返回数据,假设此时 `derived_success_set` 中已包含 `分享` 和 `图片文字`):
+```json
+[
+    {
+        "id": 1,  
+        "method": "账号pattern复用",
+        "input": {
+            "tree_nodes": [],
+            "patterns": [
+                "分享+日常物品"
+            ],
+            "derived_nodes": [
+                "分享"
+            ]
+        },
+        "output": [
+            "日常物品"
+        ],
+        "reason": "根据已推导节点'分享',找到 pattern '分享+日常物品'(条件概率=0.2203),pattern 中'分享'已推导成功,由此推导出尚未推导的元素'日常物品'。",
+        "tools": []
+    },
+    {
+        "id": 2,  
+        "method": "账号pattern复用",
+        "input": {
+            "tree_nodes": [],
+            "patterns": [
+                "图片文字+状态与描绘+补充说明式"
+            ],
+            "derived_nodes": [
+                "图片文字"
+            ]
+        },
+        "output": [
+            "状态与描绘","补充说明式"
+        ],
+        "reason": "根据已推导节点'图片文字',找到 pattern '图片文字+状态与描绘+补充说明式'(条件概率=0.578947),pattern 中'图片文字'已推导成功,由此推导出尚未推导的元素'状态与描绘'和'补充说明式'。",
+        "tools": []
+    }
+]
+```
+⚠️ **反例(禁止)**:将两个独立pattern合并为一条路径:
+```json
+{
+    "id": 1,  
     "method": "账号pattern复用",
     "method": "账号pattern复用",
     "input": {
     "input": {
-      "tree_nodes": [],
-      "patterns": ["分享+日常物品"],
-      "derived_nodes": ["分享"]
+        "tree_nodes": [],
+        "patterns": [
+            "分享+日常物品",
+            "图片文字+状态与描绘+补充说明式"
+        ],
+        "derived_nodes": [
+            "分享","图片文字"
+        ]
     },
     },
-    "output": ["日常物品"],
-    "reason": "根据已推导节点'分享',找到 pattern'分享+日常物品'(条件概率=0.2203),pattern 中'分享'已推导成功,由此推导出尚未推导的元素'日常物品'。",
+    "output": [
+        "日常物品", "状态与描绘", "补充说明式"
+    ],
+    "reason": "根据已推导节点'分享' '图片文字',找到 pattern '分享+日常物品'(条件概率=0.2203) 图片文字+状态与描绘+补充说明式(条件概率=0.578947),由此推导出尚未推导的元素'日常物品' '状态与描绘'和'补充说明式'。",
     "tools": []
     "tools": []
-  }
-  ```
-  对应评估日志:`derivation_output_point="日常物品"`,`is_matched=true`,`matched_post_point="日常物品"`,`matched_reason="匹配分数=1.0"`
+}
+```
+这违反原子化规则,因为两个pattern的推导彼此独立,去掉任一输入不影响另一个输出。
+
+对应评估日志:
+- `derivation_output_point="日常物品"`,`is_matched=true`,`matched_post_point="日常物品"`,`matched_reason="匹配分数=1.0"`
+- `derivation_output_point="补充说明式"`,`is_matched=true`,`matched_post_point="补充说明式"`,`matched_reason="匹配分数=1.0"`
+- `derivation_output_point="状态与描绘"`,`is_matched=false`,`matched_post_point=null`,`matched_reason=null`
 
 
 #### 方法三:人设推导
 #### 方法三:人设推导
 - **适用场景**:通过人设树条件概率关联推导相关节点;非首轮进行内部推导时可以使用。
 - **适用场景**:通过人设树条件概率关联推导相关节点;非首轮进行内部推导时可以使用。
@@ -198,20 +286,60 @@ $system$
   - ⚠️ **关键区分**:`output` 是人设树节点名称(`趣味道具`),`matched_post_point` 是帖子中真实的选题点名称(`夸张道具`)——两者**可以不同**,加入 `derived_success_set` 的是 `matched_post_point`,而非 `output`。
   - ⚠️ **关键区分**:`output` 是人设树节点名称(`趣味道具`),`matched_post_point` 是帖子中真实的选题点名称(`夸张道具`)——两者**可以不同**,加入 `derived_success_set` 的是 `matched_post_point`,而非 `output`。
   - 推导理由须引用条件概率等数据,**禁止**使用大模型自身世界知识联想。
   - 推导理由须引用条件概率等数据,**禁止**使用大模型自身世界知识联想。
 - 模拟样例(基于上方工具返回数据):
 - 模拟样例(基于上方工具返回数据):
-  ```json
-  {
-    "method": "人设推导",
-    "input": {
-      "tree_nodes": ["趣味道具"],
-      "patterns": [],
-      "derived_nodes": ["家居用品"]
+```json
+[
+    {
+        "id": 1,  
+        "method": "人设推导",
+        "input": {
+            "tree_nodes": [
+                "趣味道具"
+            ],
+            "patterns": [],
+            "derived_nodes": [
+                "家居用品"
+            ]
+        },
+        "output": [
+            "趣味道具"
+        ],
+        "reason": "根据已推导出的'家居用品',人设树中'趣味道具'节点(父节点=家居用品)的条件概率=0.125,工具返回该节点存在帖子选题点匹配,因此将其作为推导候选。",
+        "tools": []
     },
     },
-    "output": ["趣味道具"],
-    "reason": "根据已推导出的'家居用品',人设树中'趣味道具'节点(父节点=家居用品)的条件概率=0.125,工具返回该节点存在帖子选题点匹配,因此将其作为推导候选。",
-    "tools": []
-  }
-  ```
-  对应评估日志:`derivation_output_point="趣味道具"`,`is_matched=true`,`matched_post_point="夸张道具"`,`matched_reason="匹配分数=0.7831"`
+    {
+        "id": 2,  
+        "method": "人设推导",
+        "input": {
+            "tree_nodes": [
+                "第一人称视角"
+            ],
+            "patterns": [],
+            "derived_nodes": [
+                "体验式呈现"
+            ]
+        },
+        "output": [
+            "第一人称视角"
+        ],
+        "reason": "根据已推导出的'体验式呈现',人设树中'第一人称视角'节点(父节点=体验式呈现)的条件概率=1.0,因此将其作为推导候选。",
+        "tools": []
+    }
+]  
+```
+⚠️ **反例(禁止)**:将两个独立推导节点合并为一条路径:
+```json
+{
+  "id": 1,  
+  "method": "人设推导",
+  "input": { "tree_nodes": ["趣味道具", "第一人称视角"],"derived_nodes": ["家居用品", "体验式呈现"]},
+  "output": ["趣味道具", "第一人称视角"]
+}
+```
+这违反原子化规则,因为"趣味道具"和"第一人称视角"的推导彼此独立,去掉任一输入不影响另一个输出。
+
+对应评估日志:
+-`derivation_output_point="趣味道具"`,`is_matched=true`,`matched_post_point="夸张道具"`,`matched_reason="匹配分数=0.7831"`
+-`derivation_output_point="第一人称视角"`,`is_matched=false`,`matched_post_point=null`,`matched_reason=null`
 
 
 #### 方法四:信息搜索
 #### 方法四:信息搜索
 - **适用场景**:方法二和方法三均难以推导出新选题点时,或需要验证某个推导假设时。
 - **适用场景**:方法二和方法三均难以推导出新选题点时,或需要验证某个推导假设时。
@@ -476,6 +604,7 @@ $system$
 3. 评估日志包含 `round`、`eval_results`、`derivation_progress`,`is_matched` 为布尔值,`need_next_round` 为布尔值,`matched_reason` 引用工具返回的匹配分数等具体数据
 3. 评估日志包含 `round`、`eval_results`、`derivation_progress`,`is_matched` 为布尔值,`need_next_round` 为布尔值,`matched_reason` 引用工具返回的匹配分数等具体数据
 4. 推导理由中不包含对匹配结果反馈的引用(如"匹配结果显示...")
 4. 推导理由中不包含对匹配结果反馈的引用(如"匹配结果显示...")
 5. 每条评估记录包含 `path_id` 和 `item_id` 两个 ID 字段,与推导日志路径对应
 5. 每条评估记录包含 `path_id` 和 `item_id` 两个 ID 字段,与推导日志路径对应
+6. 原子化拆分校验:方法一(人设常量)、方法三(人设推导)的每条路径 `input.tree_nodes` 长度为 1 且 `output` 长度为 1;方法二(账号 pattern 复用)的每条路径 `input.patterns` 长度为 1
 
 
 $user$
 $user$
 请开始执行 account_name={account_name},帖子ID={帖子ID} 的选题点整体推导任务。所有路径均相对于项目根目录。帖子的选题点数量={post_point_count}
 请开始执行 account_name={account_name},帖子ID={帖子ID} 的选题点整体推导任务。所有路径均相对于项目根目录。帖子的选题点数量={post_point_count}

+ 3 - 1
examples_how/overall_derivation/overall_derivation_agent_run.py

@@ -550,4 +550,6 @@ async def main(account_name, post_id):
 
 
 
 
 if __name__ == "__main__":
 if __name__ == "__main__":
-    asyncio.run(main(account_name="家有大志", post_id="69185d49000000000d00f94e"))
+    # anthropic/claude-sonnet-4.6
+    # google/gemini-3-flash-preview
+    asyncio.run(main(account_name="家有大志", post_id="68fb6a5c000000000302e5de"))