from openai import OpenAI
from typing import List, Dict
import json
from langchain_text_splitters import MarkdownHeaderTextSplitter, CharacterTextSplitter
import requests
import json
from modelsAPI.model_api import OpenaiAPI



Ontology = ["舰艇", "系统", "设备", "零部件", "故障", "修理", "维修项目","操作项目","保养"]
Relationships = ["包含", "组成", "解决", "用于", "使用","具有"]

# 节点类型及其属性定义

NODE_TYPES = {
    "舰艇": ["名称","型号", "弦号", "设计单位", "总装工厂", "所属部队"],
    "系统": ["名称", "技术责任单位", "生产单位", "级别"],
    "设备": ["名称", "型号", "技术责任单位", "生产单位", "技术状态", "生产日期", "启用时间","运行时间","运行条件"],
    "零部件": ["名称", "型号", "技术责任单位", "生产单位"],
    "故障": ["故障现象名称", "故障原因", "故障影响", "故障类型", "发生时间", "处置情况", "修复情况"],
    "修理": ["修理方案","修理人员", "修理时间", "修理工具", "备品备件", "修理类型", "维修项目"],
    "维修项目": ["名称","维修项目编号", "组成编码", "维修设备名称", "维修间隔期", "维修级别", "页码", "安全防护要求", "安全注意事项","工具","备品备件","消耗材料","人力人员","修理步骤"],
    "操作项目": ["名称", "操作项目编号", "安全防护", "注意事项","保障设施、保障设备（工具）", "人力人员", "操作步骤"],
    "保养" : ["保养人员","保养时间","保养工具","保养频率"]
}

Ontology_DESCRIPTION = {
    "舰艇": ["代表一艘完整海上作战或保障平台的实体，是所有系统、设备和零部件的最高层级载体。区别于“系统”或“设备”，舰艇具有独立的型号、弦号和部队归属，不可作为其他舰艇的组成部分。"],
    "系统": ["舰艇中实现某一类功能（如动力、导航、通信）的集成化功能单元，由多个设备协同组成。与“设备”不同，系统本身不直接对应物理装置，而是逻辑/功能层面的集合；与“舰艇”不同，系统不具备独立航行能力或部队归属。"],
    "设备": ["安装在舰艇上、具有独立型号和运行状态的物理装置，可被启停、监控运行时间，并可能产生故障。区别于“零部件”，设备是可独立更换或维修的功能单元；区别于“系统”，设备是具体硬件而非功能集合。"],
    "零部件": ["构成设备的不可再拆分的基础物理元件（如轴承、电路板、密封圈），通常无独立运行状态或启用时间。与“设备”关键区别在于：零部件不能单独运行，也不记录运行时间或技术状态变更。"],
    "故障": ["设备或系统在运行中出现的异常状态或失效事件，必须包含具体现象（如“无法启动”）、原因（如“电源短路”）及影响。区别于“修理”或“保养”，故障是问题本身，而非应对措施；不包含操作步骤或人员信息。"],
    "修理": ["针对已发生故障所执行的一次性修复行为，包含具体时间、人员、工具、方案和所关联的维修项目。区别于“保养”，修理是响应式、非周期性的；区别于“维修项目”，修理是实际发生的实例，而非标准化规程。"],
    "维修项目": ["标准化、可重复执行的维修任务规程，规定了某类设备或系统在特定条件下应如何维修，包含编号、步骤、材料、安全要求等。区别于“修理”，维修项目是模板或规范，而非具体事件；不包含实际发生时间或人员。"],
    "操作项目": ["舰艇正常运行中需执行的标准操作流程（如启动主机、校准雷达），强调操作步骤与安全保障。区别于“维修项目”，操作使用项目用于日常使用而非维护"],
    "保养" : ["按计划周期性执行的预防性维护活动（如润滑、清洁、检测），目的是延缓性能退化。"]
}

RELATIONSHIP_TYPES = {
    "包含": ["舰艇包含系统", "系统包含设备","设备包含零部件","修理包含维修项目"],
    "解决": ["修理解决故障", "维修项目解决故障"],
    "使用": ["设备使用操作项目", "设备使用保养","设备使用维修项目"],
    "具有": ["设备具有故障","零部件具有故障"]
}

def create_extraction_prompt(
    text: str,
    ontology: List[str],
    Ontology_DESCRIPTION: Dict[str, List[str]],
    relationships: List[str],
    node_types: Dict[str, List[str]],
    relationship_types: Dict[str, List[str]]
) -> str:
    # 构建已有本体的定义（用于上下文）
    ontology_def_descriptions = []
    for etype in ontology:
        clean_etype = etype.strip()
        if clean_etype in Ontology_DESCRIPTION:
            desc = "；".join(Ontology_DESCRIPTION[clean_etype])
            ontology_def_descriptions.append(f"- {clean_etype}：{desc}")
        else:
            ontology_def_descriptions.append(f"- {clean_etype}：无明确定义")

    # 构建关系示例
    rel_examples = []
    for rtype, examples in relationship_types.items():
        for ex in examples[:1]:
            rel_examples.append(f"  - {ex}")

    prompt = f"""你是一个专业的舰艇维修领域本体工程师。请基于以下文本片段，**识别潜在的、尚未定义的抽象概念类别（即本体类型）和语义关系类型**。

> ⚠️ 重要说明：
> - **本体（Ontology Class）是抽象概念类别**，是对特定领域中概念体系的形式化、结构化规范，用于明确定义该领域内的实体类型（类）。
> - 请**不要推荐具体实体或实例名称**，只推荐**可作为一类事物统称的新概念**。
> - 如果文本中的内容**可归入已有本体**（见下文列表），则**不要**将其视为新本体。
> - 抽取本体在文本中应该具有代表性，而不是简单的一个名词，能够代表一类事物，抽取出很多实体和对应的属性

### 已有本体类型（禁止重复推荐）：
{chr(10).join(ontology_def_descriptions)}

### 已有关系类型（禁止重复推荐）：
- {"、".join(relationships)}
典型用法示例：
{chr(10).join(rel_examples)}

### 待分析文本：
{text.strip()}

### 你的任务：
1. **推荐新的本体类型（抽象概念）**  
   仅当文本中隐含一个**尚未被现有本体覆盖的通用类别**时才提出。例如：
   - 文本存在"主要功能"这种章节，当前本体没有，可推荐"功能"
   - 文本提到“子系统”，而当前本体已存在"系统"，因此不合适。
   
   每个新本体需包含：
   - `name`：中文名称（抽象名词，非专有名词）；
   - `definition`：清晰定义其内涵、作用及与已有本体的区别；
   - `suggested_attributes`：建议的通用属性（如编号、时间、状态等，非具体值）。

2. **推荐新的关系类型**  
   仅当存在**未被现有关系表达的语义连接**时提出。例如：“依赖于”“触发”“源自”等。
   每个新关系需包含：
   - `name`：动词性短语（如“依赖于”）；
   - `description`：语义解释；
   - `example`：格式为 “[本体A] [关系] [本体B]”，如 “维修项目 依赖于 备品备件”。

   
3. **推荐已有本体的属性**：
    如果文本中提及的属性适用于已有本体类型，请直接在已有本体的定义中补充建议属性，无需在新本体中重复。
    - `name`：属性名称；
    - `applicable_to`：适用的已有本体类型列表。

4. **输出严格为 JSON 格式**，无任何额外文本：

{{
  "new_entities": [
    {{
      "name": "新抽象本体名称",
      "definition": "该本体在舰艇维修领域的定义与边界",
      "suggested_attributes": ["属性1", "属性2"]
    }}
  ],
  "new_relationships": [
    {{
      "name": "新关系名称",
      "description": "关系语义说明",
      "example": "X 关系名 Y"
    }}
  ],
    "existing_entity_attributes": [
    {{
      "name": "属性名称",   
        "applicable_to": "已有本体"]
    }}
]

}}

注意：
- 若无新概念，对应字段返回空列表 []。
- 禁止输出具体实例（如“SC-887”“2024年检修”）。
- 定义需体现**抽象性、通用性、可复用性**。
- 不要生成一些实体，如果没有就不要推荐

示例1：
输入文本为：

# 1.1 警告

【最高级别警告】情境意识：始终保持对船舶位置、周围交通、水文气象、船舶状态和仪器读数的全面了解。自满是最大的危险。

【最高级别警告】有效沟通：船-岸、驾驶台-机舱、驾驶台内部、舵手-引航员之间的沟通必须清晰、无误、复诵确认。语言障碍是重大事故根源。

【警告】严格遵守规则：必须严格遵守《国际海上避碰规则》、《国际海上人命安全公约》、《港口特殊规定》及公司安全管理体系。

【警告】疲劳管理：严禁在过度疲劳状态下值班或操作。合理安排休息，必要时立即报告。

思考过程：
首先，我需要仔细分析给定的文本片段，识别潜在的、尚未定义的抽象概念类别（本体类型）和语义关系类型。文本是关于舰艇操作中的警告和规则，内容涉及情境意识、有效沟通、遵守规则、疲劳管理等。

"情境意识"：这是一个抽象概念，指操作人员对环境的全面了解。在已有本体中，没有直接对应的概念。舰艇、系统、设备等都是物理或功能实体，而"情境意识"是操作人员的认知状态。它不是故障、修理或维修项目；它更像是一个操作要求或状态。已有本体中，"操作项目"是标准操作流程，但"情境意识"不是流程，而是一种意识状态。所以，可能需要一个新的本体。

定义：情境意识应定义为一种认知状态，涉及操作人员对环境、船舶状态和相关因素的持续感知和理解。区别于已有本体：它不是实体（如设备），也不是事件（如故障），而是操作人员的心理状态。

属性：可能包括状态（如良好、中等、差）、时间（如更新时间）、影响因素（如天气条件）。

"严格遵守规则"：提到规则如《国际海上避碰规则》。规则是具体的文档。已有本体中，没有"规则"作为类别。"维修项目"是维修规程，但这里是操作规则。

文本说"遵守《国际海上避碰规则》"，所以"规则"是一个概念。但"规则"在本体中可能太泛；在舰艇领域，"规则"可以指安全规则或操作规则。

现有本体有"操作项目"，是标准操作流程，但规则是更广泛的法规。所以，可能需要"规则"作为新本体。

定义：规则是强制性的操作规范，由国际公约或公司制定，用于指导船舶操作以确保安全。

情境意识：可能是一个新本体。
规则：如《国际海上避碰规则》，可能需要"安全规则"。
我需要确保这些是尚未定义的抽象概念。

检查已有本体：

舰艇：不相关。
系统：不相关。
设备：不相关。
零部件：不相关。
故障：不相关。
修理：不相关。
维修项目：维修规程，不相关。
操作项目：标准操作流程，如"启动主机"，但"情境意识"不是流程，是状态。
保养：预防性维护，不相关。
所以，"情境意识"似乎是一个新本体。

类似地，"规则"：已有"操作项目"是操作规程，但规则是法规，如避碰规则。

现在，定义新本体：

情境意识：

name: "情境意识"
definition: 操作人员对船舶环境、状态和相关因素的实时感知和理解能力，是确保安全操作的认知基础。区别于已有本体：它不是物理实体、事件或规程，而是操作人员的心理状态。
suggested_attributes: ["状态", "更新时间", "影响因素"]
安全规则：

name: "规则"
definition: 由国际公约或公司制定的强制性操作规范，用于指导船舶在特定情境下的安全行为，确保符合法规要求。区别于"操作项目"：安全规则是外部约束，而操作项目是内部执行的流程。
suggested_attributes: ["编号", "发布机构", "生效日期", "适用范围"]


列出潜在新本体：

情境意识：文本直接使用，未在本体中。
安全规则：文本提到具体规则，未被覆盖。
现在，关于关系类型。

文本中，有"必须严格遵守规则"，所以"遵守"可能是一个关系。

但已有关系有"用于"、"使用"，"遵守"可能是一个新关系。

已有关系：包含、组成、解决、用于、使用、具有。

"遵守"不在其中。

所以，可能需要新关系"遵守"。

例如，"操作项目 遵守 规则"。

但关系是语义连接。

检查是否有未被表达的关系。

例如：

情境意识 影响 操作安全
但"影响"可能不标准。
文本中，"情境意识"是警告内容，所以它可能被"要求"或"强调"。

但关系类型需要是动词性。

可能的关系：

"要求"：如"警告 要求 情境意识"
但"警告"不是本体；文本中"警告"是类别。
在文本中，有"【最高级别警告】"，但"警告"本身可能不是本体；它是一个事件。

在已有本体，没有"警告"。但任务是基于文本，文本中"警告"是作为标签。

然而，在本体工程中，"警告"可能被视为一种事件或规则。

但已有本体有"故障"，但警告不是故障。

或许"警告"可以是新本体，但文本中是"【最高级别警告】"，是内容，不是类别。

文本是警告内容，所以"情境意识"是内容。

我认为"情境意识"、"安全规则"、"疲劳状态"是候选。

现在，精简。

情境意识：必须推荐，因为它直接出现。
安全规则：规则如《国际海上避碰规则》，需要类别。
疲劳状态：疲劳是状态。
但"疲劳管理"是活动，不是状态。文本说"疲劳管理：严禁在过度疲劳状态下值班"，所以"疲劳状态"是核心。

在本体中，状态可以是属性。

但"疲劳状态"作为本体。

现在，检查是否已有。

在已有列表，没有"状态"本体；"故障"有状态，但故障是事件。

"故障"有状态，但"疲劳状态"是人员状态。

所以，应该新。

类似地，"情境意识"是状态。

或许可以合并，但最好分开。

定义：

情境意识：

name: "情境意识"
definition: 操作人员对船舶环境、航行状态和相关因素的实时感知与理解能力，是安全操作的关键认知要素。区别于已有本体：它不是物理实体、功能单元或事件，而是操作人员的主观认知状态。
suggested_attributes: ["认知等级", "更新时间", "环境因素"]
安全规则：

name: "规则"
definition: 由国际组织或公司制定的强制性操作规范，规定船舶在特定情境下必须遵守的安全行为准则。区别于"操作项目"：安全规则是外部法规约束，而操作项目是内部执行的标准化流程。
suggested_attributes: ["规则编号", "发布机构", "生效日期", "适用场景"]
疲劳状态：

现在，关系类型。

文本中，有"必须严格遵守规则"，所以关系"遵守"。

已有关系中没有"遵守"。

所以，新关系"遵守"。

name: "遵守"
description: 操作或规程必须符合安全规则的要求，表示强制性遵循。
example: "操作项目 遵守 安全规则"
其他可能关系：如"影响"，但"情境意识"影响操作，但"影响"可能太泛。


suggested_attributes:

情境意识: ["认知等级", "更新时间", "环境因素"]
规则: ["规则编号", "发布机构", "生效日期", "适用范围"]
关系:

name: "遵守"
description: 操作规程或行为必须符合安全规则的要求，体现强制性约束。
example: "操作项目 遵守 规则"

所以输出为：
example1

示例2：
输入为：
# 2 概述

本文档介绍了螺旋桨主要功能、组成、维修工作指导、器材保障等内容。

舰船螺旋桨（推进器）是将主机动力转化为推力的核心装置。它通常由多个（常见3-6叶）桨叶组成，叶片复杂的曲面设计能高效搅动水流。

主要分为两大类：固定螺距螺旋桨（FPP） 结构简单坚固；可调螺距螺旋桨（CPP）可通过转动桨叶改变螺距，无需改变主机转速即可调节推力大小和方向，机动性更优。

现代大型船舶螺旋桨多为特种铜合金铸造，直径可达 10 米以上。其设计、制造和安装精度要求极高，直接影响船舶的推进效率、振动和噪音水平。

思考过程：
首先，我需要仔细分析给定的文本片段，识别潜在的、尚未定义的抽象概念类别（本体类型）和语义关系类型。文本是螺旋桨主要功能、组成、维修工作指导、器材保障等内容。后面详细阐述舰船螺旋桨（推进器）

的组成部分，以及主要分为两大类。结合已有的本体，该类内容主要属于系统、设备、零部件等本体，因此没有新本体衍生。

所以输出为：
[]

"""

    return prompt
example1 = '''
{
"new_entities": [
{
"name": "情境意识",
"definition": "操作人员对船舶环境、航行状态、水文气象及仪器读数等要素的实时感知与综合理解能力，是保障安全操作的认知基础。区别于已有本体：它不是物理实体（如设备）、功能事件（如故障）或操作规程（如操作项目），而是操作人员的主观认知状态。",
"suggested_attributes": ["认知等级", "更新时间", "环境因素"]
},
{
"name": "规则",
"definition": "由国际公约（如《国际海上避碰规则》）或公司制定的强制性操作规范，规定船舶在特定情境下必须遵守的安全行为准则。区别于已有本体：它不是内部执行流程（如操作项目），而是外部法规约束，具有法律效力和强制性。",
"suggested_attributes": ["规则编号", "发布机构", "生效日期", "适用范围"]
},
],
"new_relationships": [
{
"name": "遵守",
"description": "操作规程或行为必须符合规则的要求，体现强制性约束关系。区别于已有关系：它表示外部法规对内部操作的强制要求，而非功能关联或物理组成。",
"example": "操作项目 遵守 规则"
}
]
}
'''
def generate_Ontology_relationship(
    text: List[str],
    ontology: List[str],
    Ontology_DESCRIPTION: Dict[str, List[str]],
    relationships: List[str],
    node_types: Dict[str, List[str]],
    relationship_types: Dict[str, List[str]]
):
    new_entities_result = []
    new_relationships_result = []

    for ins in text:
        final_prompt = create_extraction_prompt(
            text=ins,
            ontology=ontology,
            Ontology_DESCRIPTION=Ontology_DESCRIPTION,
            relationships=relationships,
            relationship_types=relationship_types,
            node_types=node_types
        )
        final_prompt = final_prompt.replace("example1",example1)
        res_str = OpenaiAPI.openai_chat(final_prompt)

        # 处理 API 调用失败
        if res_str is None:
            print("⚠️ 跳过当前 chunk：API 调用失败")
            continue

        # 尝试解析 JSON
        try:
            res = json.loads(res_str)
        except json.JSONDecodeError as e:
            print(f"❌ JSON 解析失败: {e}")
            print(f"原始响应内容: {repr(res_str)}")
            continue

        # 安全访问字段
        new_entities = res.get("new_entities", [])
        new_relationships = res.get("new_relationships", [])
        nwe_entity_attributes = res.get("existing_entity_attributes", [])

        print(f"推荐新本体：{new_entities}")
        print(f"推荐新关系：{new_relationships}")
        print(f"推荐新属性：{nwe_entity_attributes}")


        new_entities_result.append(new_entities)
        new_relationships_result.append(new_relationships)

    # 可选：最后汇总输出
    print("\n=== 最终结果 ===")
    print("所有新本体:", new_entities_result)
    print("所有新关系:", new_relationships_result)
    print("所有新属性:", nwe_entity_attributes)
    return new_entities_result,new_relationships_result,nwe_entity_attributes


# if __name__ == "__main__":
#     text = """
#      # 1）螺旋桨本体

# 功能与特性：能量转换的核心。它将主机的旋转动能转化为水流的反作用力（推力）。其特性由材料（如镍铝青铜、锰青铜）、桨叶数（3-6叶）、盘面比、螺距比等决定，直接影响效率、空泡和振动性能。

# 相互关系：直接安装在尾轴（螺旋桨轴） 末端，其扭矩由尾轴传递，其推力通过推力轴承传递给船体。

# 2）轴系

# 功能与特性：动力传递的桥梁。包括：

# 推力轴及推力轴承：承受螺旋桨产生的巨大轴向推力，并将其传递给船体结构，是决定船舶能否前进、后退的关键。

# 中间轴：连接主机输出端与推力轴/尾轴。

# 尾轴（螺旋桨轴）：穿过尾轴管，末端安装螺旋桨，工作环境恶劣（浸没海水中），通常需包覆铜套防腐。

# 相互关系：将主机的旋转输出与螺旋桨本体刚性连接，形成一个完整的动力传递链。推力轴承是轴系与船体结构之间的关键受力界面。

# 3）尾轴管与密封系统功能与特性：

# 尾轴管：固定于船体尾端，支撑尾轴并形成从船内（机舱）到船外（海水）的通道。

# 密封系统（首尾密封）：绝对关键的安全设备。防止海水沿尾轴流入机舱（尾密封），同时防止润滑油泄漏（首尾密封均有此功能）。通常采用唇式密封或面式密封，材料耐磨、耐腐蚀。

# 相互关系：为尾轴提供支撑和润滑（油润滑或水润滑），其密封系统直接保护尾轴并确保机舱安全，与轴系和船体结构紧密集成。

# 4）毂帽与导流罩功能与特性：

# 毂帽：安装在螺旋桨毂后端，呈流线型，用于减少桨毂后部产生的涡流阻力，提高效率。

# 导流罩（如桨毂涡流消除器）：安装在桨毂前方，改善流入桨叶的水流状态，尤其适用于肥大船型，能提升效率、减少振动。

# 相互关系：直接安装在螺旋桨本体的毂上，是其水动力性能的优化附件。

# 系统相互关系总结：

# 主机驱动轴系旋转，轴系末端的尾轴带动螺旋桨本体旋转。螺旋桨产生的推力通过尾轴传递至推力轴承，最终作用在船体上使其运动。尾轴管及密封系统为这一旋转运动提供支撑、润滑和至关重要的水密保障。毂帽和导流罩则作为螺旋桨本体的附件，优化其水动力性能。所有子设备协同工作的核心目标，是确保主机功率被高效、平稳、可靠地转化为推进船舶前进的有效推力。 任何一环失效（如密封泄漏、轴承损坏）都将导致整个推进系统瘫痪。
# """ 
#     content = []
#     content.append(text)
#     generate_Ontology_relationship(content,ontology=Ontology,Ontology_DESCRIPTION=Ontology_DESCRIPTION,relationships=Relationships,relationship_types=RELATIONSHIP_TYPES,node_types=NODE_TYPES)

