Browse Source

feat: 改进语义匹配 - 引入"是否可比较"判断,拆分同义/近义

主要改动:
1. 判断逻辑:从"是否同一概念"改为"是否可比较"
   - 不可比较的情况:
     - 元概念 vs 具体概念(如"概念" vs "期待")
     - 抽象层级相差过大(2级以上)
     - 本体范畴完全不同(如物理对象 vs 心理状态)
   - 新增"不可比较原因"字段,明确说明为什么不可比较
   - 防止强行匹配问题(如"假期期待" vs "内容和概念")

2. 关系类型拆分:
   - 旧:"同义/近义" (1.0分)
   - 新:"同义" (1.0分) + "近义" (0.9分)
   - 同义:含义完全相同,可以互相替换
   - 近义:含义非常接近,但有细微差异

3. 相关性分数标准:明确6档评分标准
   - 1.0:完全同义,可以互相替换
   - 0.8-0.9:高度相关,只有细微差异
   - 0.6-0.7:明显相关,有语义重叠或上下位关系
   - 0.4-0.5:一般相关,有语义关联或主题相关性
   - 0.2-0.3:弱相关,只有间接关联(因果、触发等)
   - 0.0-0.1:几乎无关或完全无关

4. 输出格式更新:
   - 匹配关系中新增"是否可比较"和"不可比较原因"字段
   - 关系类型从4种增加到5种

5. calculate_score_by_code 更新:
   - 关系得分映射新增"近义": 0.9

效果:
- 避免元概念与具体概念的强行匹配
- 更严格的可比较性检查
- 更细粒度的关系类型区分
- 更明确的相关性评分标准

测试结果:
- "迷惑行为" vs "感受/思考" → 不可比较(本体范畴不同)
- 相关性分数 = 0.2(弱相关,只有触发关系)
- 最终分数 = 0.04

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
yangxiaohui 2 weeks ago
parent
commit
5fe0c61350
1 changed files with 46 additions and 24 deletions
  1. 46 24
      lib/match_analyzer.py

+ 46 - 24
lib/match_analyzer.py

@@ -183,20 +183,29 @@ MATCH_WITH_DEFINITION_PROMPT = """
 - 形式语义(修饰词、限定词等)不单独匹配,因为它们脱离实质语义就失去意义
 - 形式语义的差异可以在score说明中提及,作为参考信息
 
-1. **判断是否同一概念**(基于上下文中的作用/本质)
-   - **参考B语义说明和A语义说明**,判断在各自上下文中的作用/本质是否相同
-   - **不是看字面是否相同**,而是看**在各自上下文中的作用/本质是否相同**
-   - 同一概念:可以比较上下位/同义关系
-   - 不同概念:标记为无关
-
-2. **确定关系类型**(仅对同一概念)
-   - **同义/近义**:在各自上下文中的含义基本相同
+1. **判断是否可比较**(基于抽象层级和本体范畴)
+   - **参考B语义说明和A语义说明**,判断两个语义是否处于可比较的层级
+   - **不可比较的情况**(直接标记为"无关"):
+     - **元概念 vs 具体概念**:元概念(如"概念"、"内容"、"事物"、"要素"、"方面"、"维度"、"属性"等用于描述其他概念的抽象术语)不能与具体概念(如"期待"、"行为"、"猫咪"等实际指代特定事物的词)比较
+     - **抽象层级相差过大**:相差2级以上(如"存在" vs "猫的行为")
+     - **本体范畴完全不同**:不同的基本范畴(如数学概念 vs 生物实体、物理对象 vs 心理状态等,除非有明确的跨域映射关系)
+   - **可比较的情况**:
+     - 同级具体概念(如"期待" vs "焦虑")
+     - 有明确上下位关系(如"情感" vs "期待")
+     - 有交叉或关联关系(如"工作压力" vs "假期期待")
+   - **输出要求**:
+     - 如果不可比较:输出 "是否可比较": false, "不可比较原因": "说明为什么不可比较", "关系": "无关"
+     - 如果可比较:输出 "是否可比较": true, 继续判断关系类型
+
+2. **确定关系类型**(仅对可比较的语义)
+   - **同义**:在各自上下文中的含义完全相同,可以互相替换
+   - **近义**:在各自上下文中的含义非常接近,但有细微差异
    - **上位词**:B在其上下文中的含义 比 A在其上下文中的含义 更抽象、更上位(B ⊇ A)
    - **下位词**:B在其上下文中的含义 比 A在其上下文中的含义 更具体、更下位(B ⊆ A)
-   - **无关**:不同概念,无法比较
+   - **无关**:虽然可比较,但没有明确的语义关系
 
 3. **计算规则分数**
-   - 关系得分:同义=1.0, 上位词=0.6, 下位词=0.4, 无关=0.0
+   - 关系得分:同义=1.0, 近义=0.9, 上位词=0.6, 下位词=0.4, 无关=0.0
    - 只基于实质语义匹配计算规则分数
    - 计算公式:
      ```
@@ -209,6 +218,13 @@ MATCH_WITH_DEFINITION_PROMPT = """
      - 语义距离:核心概念之间的距离
      - 上下文契合度:在各自上下文中的关联程度
      - 表达意图的一致性
+   - **评分标准**(严格遵守):
+     - **1.0**:<B> 和 <A> 完全同义,可以互相替换,表达完全相同的含义
+     - **0.8-0.9**:高度相关,核心语义非常接近,只有细微差异
+     - **0.6-0.7**:明显相关,有明确的语义重叠或上下位关系
+     - **0.4-0.5**:一般相关,有一定的语义关联或主题相关性
+     - **0.2-0.3**:弱相关,只有间接关联(如因果、触发等)
+     - **0.0-0.1**:几乎无关或完全无关
    - 给出相关性分数(0-1之间的浮点数,保留2位小数)
    - 给出相关性说明
 
@@ -261,18 +277,19 @@ MATCH_WITH_DEFINITION_PROMPT = """
       "B语义说明": "从B实质语义分析中复述该片段的说明",
       "A语义": "语义片段1",
       "A语义说明": "从A实质语义分析中复述该片段的说明",
-      "是否同一概念": true,
+      "是否可比较": true,
       "关系": "下位词",
       "说明": "说明两者的关系"
     },
     {
       "B语义": "语义片段2",
       "B语义说明": "从B实质语义分析中复述该片段的说明",
-      "A语义": "语义片段2",
+      "A语义": "概念",
       "A语义说明": "从A实质语义分析中复述该片段的说明",
-      "是否同一概念": false,
+      "是否可比较": false,
+      "不可比较原因": "A是元概念(用于描述其他概念的术语),B是具体概念,抽象层级完全不同",
       "关系": "无关",
-      "说明": "说明为什么无关"
+      "说明": "元概念不能与具体概念比较"
     }
   ],
   "规则分数": 0.2,
@@ -289,16 +306,20 @@ MATCH_WITH_DEFINITION_PROMPT = """
 2. **B语义分析**:必须包含"实质"、"形式"两个字段,其中实质通常为1-2个核心概念
 3. **A语义分析**:必须包含"实质"、"形式"两个字段
 4. **实质和形式**:都是字典格式,key是语义片段,value是对该片段的说明
-5. **匹配关系**:数组格式,**只包含实质语义的匹配**,字段顺序为:B语义 → B语义说明 → A语义 → A语义说明 → 是否同一概念 → 关系 → 说明
+5. **匹配关系**:数组格式,**只包含实质语义的匹配**,字段顺序为:
+   - B语义 → B语义说明 → A语义 → A语义说明 → 是否可比较
+   - 如果是否可比较=false:添加"不可比较原因"字段
+   - 关系 → 说明
 6. **B语义说明和A语义说明**:必须从前面的实质语义分析中复述,保持一致
-7. **是否同一概念**:布尔值,true或false
-8. **关系**:必须是以下之一:"同义/近义"、"上位词"、"下位词"、"无关"
-9. **规则分数**:0-1之间的浮点数,保留2位小数,基于匹配关系计算
-10. **规则分数说明**:说明规则分数的计算依据
-11. **相关性分数**:0-1之间的浮点数,保留2位小数,整体相关性评估
-12. **相关性说明**:说明相关性分数的判断依据
-13. **score**:0-1之间的浮点数,保留2位小数,= 0.8 × 规则分数 + 0.2 × 相关性分数
-14. **score说明**:说明最终分数的计算过程,可以提及形式语义的差异作为补充
+7. **是否可比较**:布尔值,true或false
+8. **不可比较原因**:字符串,仅在是否可比较=false时提供,说明为什么不可比较
+9. **关系**:必须是以下之一:"同义"、"近义"、"上位词"、"下位词"、"无关"
+10. **规则分数**:0-1之间的浮点数,保留2位小数,基于匹配关系计算
+11. **规则分数说明**:说明规则分数的计算依据
+12. **相关性分数**:0-1之间的浮点数,保留2位小数,整体相关性评估
+13. **相关性说明**:说明相关性分数的判断依据
+14. **score**:0-1之间的浮点数,保留2位小数,= 0.8 × 规则分数 + 0.2 × 相关性分数
+15. **score说明**:说明最终分数的计算过程,可以提及形式语义的差异作为补充
 """.strip()
 
 
@@ -338,7 +359,8 @@ def calculate_score_by_code(match_result: dict) -> float:
     """
     # 关系得分映射
     RELATION_SCORES = {
-        "同义/近义": 1.0,
+        "同义": 1.0,
+        "近义": 0.9,
         "上位词": 0.6,
         "下位词": 0.4,
         "无关": 0.0