67 lines
2.8 KiB
Python
67 lines
2.8 KiB
Python
from typing import Any
|
||
|
||
|
||
def extract_facts(context: dict[str, Any]) -> list[dict]:
|
||
previous = context.get('previous_episodes', [])
|
||
current = context.get('episode_content', '')
|
||
entities = context.get('entities', [])
|
||
reference_time = context.get('reference_time', '')
|
||
|
||
previous_section = ''
|
||
if previous:
|
||
import json
|
||
previous_section = f'\n<历史上下文>\n{json.dumps(previous, ensure_ascii=False)}\n</历史上下文>\n'
|
||
|
||
entities_text = '\n'.join(
|
||
f' [{i}] {e.get("name", "")}({e.get("entity_type", "未知")})' for i, e in enumerate(entities)
|
||
)
|
||
|
||
user_prompt = f"""
|
||
{previous_section}
|
||
<当前会议内容>
|
||
{current}
|
||
</当前会议内容>
|
||
|
||
<已抽取实体>
|
||
{entities_text}
|
||
</已抽取实体>
|
||
|
||
<参考时间>
|
||
{reference_time}
|
||
</参考时间>
|
||
|
||
抽取规则:
|
||
1. 从<当前会议内容>中抽取上述<已抽取实体>之间的**事实关系**。
|
||
2. 每条关系必须涉及两个**不同**的实体。
|
||
3. 返回 JSON 数组,格式:
|
||
[{{
|
||
"source_entity_name": "源实体名称(必须来自上方的实体列表)",
|
||
"target_entity_name": "目标实体名称(必须来自上方的实体列表)",
|
||
"relation_type": "关系类型,如 负责、汇报、隶属于、参与、目标值、截止于、影响、依赖于",
|
||
"fact": "一句自然语言的事实描述,保留原文中所有具体细节(数值、时间、地点等)",
|
||
"valid_at": "该事实开始成立的时间(ISO 8601格式,如 2025-04-30T00:00:00Z),不明确则留空",
|
||
"invalid_at": "该事实不再成立的时间,不明确则留空",
|
||
"evidence": "原文中的关键证据短句",
|
||
"qualifiers": ["限定条件列表,如数值、范围、状态、截止时间等"],
|
||
"confidence": 置信度0到1之间
|
||
}}]
|
||
|
||
4. relation_type 避免使用"关联""涉及"等空泛词,优先使用具体谓词:
|
||
负责、汇报、目标值、当前值、低于、高于、要求、督导、推进、支撑、依赖、计划、完成、截止于、参与、隶属于、分管、协调、审批
|
||
|
||
5. 层次关系(结构隶属)使用以下固定 relation_type:
|
||
HAS_PROJECT: 部门管辖项目(Department -> Project)
|
||
HAS_METRIC: 项目拥有指标(Project -> Metric)
|
||
PART_OF: 实体属于某个上级实体
|
||
|
||
6. 同一对实体之间可能既有层次关系(HAS_PROJECT)也有事实关系(负责、汇报),需要分别抽取。
|
||
|
||
7. fact 必须是一句完整的自然语言事实,保留所有具体信息(人名、数值、产品名、地点等)。
|
||
|
||
8. 如果根据上下文可以判断事实的开始/结束时间,填入 valid_at / invalid_at。
|
||
"""
|
||
return [
|
||
{'role': 'system', 'content': '你是一个专业的事实关系抽取专家。从会议记录中抽取实体间的结构化事实关系。'},
|
||
{'role': 'user', 'content': user_prompt},
|
||
]
|