|
|
@@ -101,6 +101,175 @@ MATCH_SYSTEM_PROMPT = """
|
|
|
""".strip()
|
|
|
|
|
|
|
|
|
+# ========== System Prompt for Name+Definition Match ==========
|
|
|
+MATCH_WITH_DEFINITION_PROMPT = """
|
|
|
+# 任务
|
|
|
+分析 <B> 与 <A> 的语义匹配关系。<A> 包含"名称"和"定义",定义作为辅助上下文帮助理解名称的含义。
|
|
|
+
|
|
|
+## 输入说明
|
|
|
+
|
|
|
+- **<B></B>**: 待匹配的内容(灵感点)
|
|
|
+- **<A></A>**: 名称(必选)
|
|
|
+- **<B_Context></B_Context>**: B 的补充上下文(可选)
|
|
|
+- **<A_Context></A_Context>**: A 的补充上下文,包含定义等信息(可选)
|
|
|
+
|
|
|
+**重要**:A_Context 中的定义仅用于辅助理解名称 <A> 的含义,主要分析 <B> 与 <A> 的匹配关系。
|
|
|
+
|
|
|
+## 分析方法
|
|
|
+
|
|
|
+### 核心原则:语义概念匹配
|
|
|
+
|
|
|
+先独立分析 <B> 和 <A> 的语义,再进行匹配,避免强行解释。
|
|
|
+
|
|
|
+### 分析步骤
|
|
|
+
|
|
|
+**第一步:独立分析 <B> 的语义**
|
|
|
+
|
|
|
+对 <B>(灵感点)进行语义分解,提取:
|
|
|
+
|
|
|
+**拆分步骤**:
|
|
|
+1. 先识别出所有语义成分(主体、动作/状态、属性、修饰等)
|
|
|
+2. 对每个成分做"去除测试":
|
|
|
+ - 如果去掉这个成分后,剩余部分的核心语义**没有发生本质变化** → 该成分是**形式**
|
|
|
+ - 如果去掉这个成分后,剩余部分的核心语义**发生了本质变化** → 该成分是**实质**
|
|
|
+3. 将成分分类到实质或形式中,每个成分只能出现在一个类别
|
|
|
+
|
|
|
+- **实质语义**:核心概念、本质内容(字典格式)
|
|
|
+ - 通常为1-2个核心概念
|
|
|
+ - 不要过度拆分复合词,保持核心概念的完整性
|
|
|
+ - key:语义片段(可以是词组)
|
|
|
+ - value:**客观地说明这个片段在B的上下文中的具体含义**
|
|
|
+
|
|
|
+- **形式语义**:具体限定、修饰、程度等(字典格式)
|
|
|
+ - 包括:主体限定词、属性修饰词、程度副词、时间/空间限定等
|
|
|
+ - key:语义片段
|
|
|
+ - value:**说明在B的上下文中修饰/限定什么,如何修饰/限定**
|
|
|
+
|
|
|
+**关键原则**:
|
|
|
+- 每个语义片段只能出现在一个类别中,不要重复
|
|
|
+- 表示主体、场景、对象的限定词通常属于形式,不要合并到实质中
|
|
|
+- 不要孤立地解释词语本身,要说明它**在当前B的上下文中**的具体含义
|
|
|
+- 不要过度推理,保持客观:描述B字面上说的是什么,而不是可能引发什么
|
|
|
+
|
|
|
+**注意**:纯粹分析 <B> 本身的语义,不要考虑与 <A> 的关系。
|
|
|
+
|
|
|
+**第二步:独立分析 <A> 的语义**
|
|
|
+
|
|
|
+对 <A>(名称)进行语义分解,提取:
|
|
|
+- **实质语义**:核心概念、本质内容(字典格式)
|
|
|
+ - **判断标准:单独拿出来看,语义跟原来相比没有发生本质变化**
|
|
|
+ - key:语义片段(可以是词组,保持完整的核心概念)
|
|
|
+ - value:**客观地说明这个片段在A的上下文中的具体含义和作用**
|
|
|
+- **形式语义**:具体限定、修饰等(字典格式)
|
|
|
+ - **判断标准:去掉后,核心概念本身不会丢失,只是失去了限定、修饰等细节**
|
|
|
+ - key:语义片段
|
|
|
+ - value:**说明在A的上下文中修饰/限定什么,如何修饰/限定**
|
|
|
+
|
|
|
+**关键**:
|
|
|
+- 可以参考<A_Context>中的定义来辅助理解名称的含义,但只分析名称本身
|
|
|
+- 同样要说明语义片段**在当前A的上下文中**的具体含义,不要孤立解释
|
|
|
+- 不要过度拆分复合词,保持核心概念的完整性
|
|
|
+
|
|
|
+**注意**:纯粹分析 <A> 本身的语义,不要考虑与 <B> 的关系。
|
|
|
+
|
|
|
+**第三步:建立匹配关系**
|
|
|
+
|
|
|
+遍历 <B> 的每个语义片段(实质+形式),找到与 <A> 中最接近的语义,判断关系:
|
|
|
+
|
|
|
+1. **判断是否同一概念**(基于上下文中的作用/本质)
|
|
|
+ - **不是看字面是否相同**,而是看**在各自上下文中的作用/本质是否相同**
|
|
|
+ - 同一概念:可以比较上下位/同义关系
|
|
|
+ - 不同概念:标记为无关
|
|
|
+
|
|
|
+2. **确定关系类型**(仅对同一概念)
|
|
|
+ - **同义/近义**:在各自上下文中的含义基本相同
|
|
|
+ - **上位词**:B在其上下文中的含义 比 A在其上下文中的含义 更抽象、更上位(B ⊇ A)
|
|
|
+ - **下位词**:B在其上下文中的含义 比 A在其上下文中的含义 更具体、更下位(B ⊆ A)
|
|
|
+ - **无关**:不同概念,无法比较
|
|
|
+
|
|
|
+3. **计算匹配分数**
|
|
|
+ - 关系得分:同义=1.0, 上位词=0.6, 下位词=0.4, 无关=0.0
|
|
|
+ - 实质语义权重=0.8,形式语义权重=0.2
|
|
|
+ - 计算公式:
|
|
|
+ ```
|
|
|
+ 实质得分 = Σ(实质语义的关系得分) / 实质语义总数
|
|
|
+ 形式得分 = Σ(形式语义的关系得分) / 形式语义总数
|
|
|
+ 最终 score = 实质得分 × 0.8 + 形式得分 × 0.2
|
|
|
+ ```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 评分标准(0-1分)
|
|
|
+
|
|
|
+**语义匹配度评分:**
|
|
|
+- **0.9-1.0**:<B> 的核心语义与名称/定义几乎完全对应
|
|
|
+- **0.7-0.8**:大部分核心语义匹配,少量增量
|
|
|
+- **0.5-0.6**:部分核心语义匹配,有一定增量
|
|
|
+- **0.3-0.4**:少量语义匹配,大部分概念不同
|
|
|
+- **0.1-0.2**:几乎无语义匹配,仅有弱关联
|
|
|
+- **0.0**:完全无关
|
|
|
+
|
|
|
+**重要原则:**
|
|
|
+- 关注有价值的语义片段,而非孤立的字面词语
|
|
|
+- 考虑概念之间的语义关系,不仅是字面匹配
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 输出格式(严格JSON)
|
|
|
+```json
|
|
|
+{
|
|
|
+ "B语义分析": {
|
|
|
+ "实质": {
|
|
|
+ "语义片段1": "说明"
|
|
|
+ },
|
|
|
+ "形式": {
|
|
|
+ "语义片段2": "说明",
|
|
|
+ "语义片段3": "说明"
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "A语义分析": {
|
|
|
+ "实质": {
|
|
|
+ "语义片段1": "说明",
|
|
|
+ "语义片段2": "说明"
|
|
|
+ },
|
|
|
+ "形式": {
|
|
|
+ "语义片段3": "说明"
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "匹配关系": [
|
|
|
+ {
|
|
|
+ "B语义": "语义片段1",
|
|
|
+ "A语义": "语义片段1",
|
|
|
+ "是否同一概念": true,
|
|
|
+ "关系": "下位词",
|
|
|
+ "说明": "说明两者的关系"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "B语义": "语义片段2",
|
|
|
+ "A语义": "语义片段2",
|
|
|
+ "是否同一概念": false,
|
|
|
+ "关系": "无关",
|
|
|
+ "说明": "说明为什么无关"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "score": 0.65,
|
|
|
+ "score说明": "基于评分规则计算得出"
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**输出要求**:
|
|
|
+1. 必须严格按照上述JSON格式输出
|
|
|
+2. **B语义分析**:必须包含"实质"、"形式"两个字段,其中实质通常为1-2个核心概念
|
|
|
+3. **A语义分析**:必须包含"实质"、"形式"两个字段
|
|
|
+4. **实质和形式**:都是字典格式,key是语义片段,value是对该片段的说明
|
|
|
+5. **匹配关系**:数组格式,包含所有B语义片段的匹配情况,字段顺序为:B语义 → A语义 → 是否同一概念 → 关系 → 说明
|
|
|
+6. **是否同一概念**:布尔值,true或false
|
|
|
+7. **关系**:必须是以下之一:"同义/近义"、"上位词"、"下位词"、"无关"
|
|
|
+8. **score**:0-1之间的浮点数,保留2位小数,按照评分规则计算
|
|
|
+9. **score说明**:说明分数的计算依据
|
|
|
+""".strip()
|
|
|
+
|
|
|
+
|
|
|
def create_match_agent(model_name: str) -> Agent:
|
|
|
"""创建信息匹配分析的 Agent
|
|
|
|
|
|
@@ -346,3 +515,92 @@ async def match_batch(
|
|
|
"score": 0.0,
|
|
|
"score说明": f"匹配过程出错: {str(e)}"
|
|
|
} for _ in b_items]
|
|
|
+
|
|
|
+
|
|
|
+async def match_with_definition(
|
|
|
+ b_content: str,
|
|
|
+ element_name: str,
|
|
|
+ element_definition: str,
|
|
|
+ model_name: str,
|
|
|
+ b_context: str = "",
|
|
|
+ a_context: str = ""
|
|
|
+) -> dict:
|
|
|
+ """名称+定义匹配:分析 B 分别与名称、定义的语义匹配关系
|
|
|
+
|
|
|
+ Args:
|
|
|
+ b_content: B(待匹配)的内容
|
|
|
+ element_name: 要素名称
|
|
|
+ element_definition: 要素定义
|
|
|
+ model_name: 使用的模型名称
|
|
|
+ b_context: B 的补充上下文(可选,默认为空)
|
|
|
+ a_context: A 的补充上下文(可选,默认为空)
|
|
|
+
|
|
|
+ Returns:
|
|
|
+ 匹配结果字典:{"名称匹配": {...}, "定义匹配": {...}}
|
|
|
+ """
|
|
|
+ try:
|
|
|
+ # 创建使用新 prompt 的 Agent
|
|
|
+ agent = Agent(
|
|
|
+ name="Name+Definition Match Expert",
|
|
|
+ instructions=MATCH_WITH_DEFINITION_PROMPT,
|
|
|
+ model=get_model(model_name),
|
|
|
+ tools=[],
|
|
|
+ )
|
|
|
+
|
|
|
+ # A 内容只包含名称,定义放在 A_Context 中
|
|
|
+ a_content = element_name
|
|
|
+
|
|
|
+ # 将定义添加到 A_Context(如果已有 a_context,则追加)
|
|
|
+ if element_definition:
|
|
|
+ definition_context = f"定义:{element_definition}"
|
|
|
+ if a_context:
|
|
|
+ full_a_context = f"{a_context}\n{definition_context}"
|
|
|
+ else:
|
|
|
+ full_a_context = definition_context
|
|
|
+ else:
|
|
|
+ full_a_context = a_context
|
|
|
+
|
|
|
+ # 运行匹配
|
|
|
+ output = await _run_match_agent(
|
|
|
+ agent, b_content, a_content, "并输出 JSON 格式",
|
|
|
+ b_context=b_context, a_context=full_a_context
|
|
|
+ )
|
|
|
+
|
|
|
+ # 解析响应
|
|
|
+ parsed_result = parse_match_response(output)
|
|
|
+
|
|
|
+ # 验证返回格式
|
|
|
+ required_fields = ["B语义分析", "A语义分析", "匹配关系", "score", "score说明"]
|
|
|
+ missing_fields = [f for f in required_fields if f not in parsed_result]
|
|
|
+
|
|
|
+ if missing_fields:
|
|
|
+ return {
|
|
|
+ "B语义分析": {
|
|
|
+ "实质": {},
|
|
|
+ "形式": {}
|
|
|
+ },
|
|
|
+ "A语义分析": {
|
|
|
+ "实质": {},
|
|
|
+ "形式": {}
|
|
|
+ },
|
|
|
+ "匹配关系": [],
|
|
|
+ "score": 0.0,
|
|
|
+ "score说明": f"解析失败:缺少字段 {missing_fields}"
|
|
|
+ }
|
|
|
+
|
|
|
+ return parsed_result
|
|
|
+
|
|
|
+ except Exception as e:
|
|
|
+ return {
|
|
|
+ "B语义分析": {
|
|
|
+ "实质": {},
|
|
|
+ "形式": {}
|
|
|
+ },
|
|
|
+ "A语义分析": {
|
|
|
+ "实质": {},
|
|
|
+ "形式": {}
|
|
|
+ },
|
|
|
+ "匹配关系": [],
|
|
|
+ "score": 0.0,
|
|
|
+ "score说明": f"匹配过程出错: {str(e)}"
|
|
|
+ }
|