from kg_build_v2.excel_to_json import excel_to_jsondata
import json
import logging
from datetime import datetime
from typing import Optional,Dict
import requests
from collections import defaultdict

import traceback
import logging
import pandas as pd
from openpyxl import load_workbook
import json
import os
from kg_build_v2.Prompt_excel import prompt_beipinbeijian,prompt_type_excel,prompt_guzhanghuizong
from openai import OpenAI
import re
import time

# ======================
# 日志
# ======================
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
System_Name_Replace_Dict={
  "00": {
    "code": "00",
    "name": "总体及综合保障",
    "level": 1,
    "description":None,
    "children": None
  },

  "01": {
    "code": "01",
    "name": "船体结构",
    "level": 1,
    "description": "由各种结构类型组成的JC船体，包括船体壳体、舱壁、甲板、平台、上层建筑、舷台、专用结构、复合材料结构、基座及船体附体等。",
    "children": [
      { "code": "00", "name": "总论", "level": 2,"description": "通用要求"},
      { "code": "10", "name": "主船体壳体结构", "level": 2,"description": "构成水面JC主船体的壳体结构和潜艇的耐压壳体、非耐压壳体结构" },
      { "code": "20", "name": "船体舱壁结构", "level": 2,"description": "构成水面JC船体的主横舱壁、主纵舱壁、围壁、轴隧、围井及其他专用舱壁等船体舱壁结构。" },
      { "code": "30", "name": "船体甲板及平台结构", "level": 2,"description": "将水面JC主船体分为若干层的连续甲板结构（包括甲板板和骨架）及非连续甲板结构（包括平台板和骨架）。" },
      { "code": "40", "name": "上层建筑（或甲板室）结构", "level": 2,"description": "水面JC主船体l甲板以上的各层上层建筑（或甲板室）结构以及潜艇上层建筑、围壳结构等。" },
      { "code": "50", "name": "舷台结构", "level": 2,"description": "大型水面JC为扩展甲板面积而在主船体两舷外侧设置的特殊结构，以主船体外板为边界，包括与主船体相对应而又相对独立的多层甲板、舱壁及外板等结构。" },
      { "code": "60", "name": "专用结构", "level": 2,"description": "安装在主船体或上层建筑上为特殊用途设置的各种结构。" },
      { "code": "70", "name": "复合材料结构", "level": 2,"description": "应用复合材料代替金属材料的船体局部结构或全艇体结构。"},
      { "code": "80", "name": "基座结构", "level": 2,"description": "装焊于JC上用于安装和支承各种设备的底座结构。其中包括基座减振的弹性连接件。不包括随设备的弹性连接件、紧固件以及设备或机组的机架"}
    ]
  },

  "02": {
    "code": "02",
    "name": "推进系统",
    "level": 1,
    "description":"为JC推进提供动力的系统，包括能源发生系统（含H能和非H能）、动力机组及推进装置、功率传递系统和推进器、推进保障系统、推进监测和控制系统。",
    "children": [
      { "code": "00", "name": "总论", "level": 2,"description": "通用要求" },
      { "code": "10", "name": "H能源发生系统", "level": 2,"description": "通过反应堆的可控H反应产生H能，并将其转化为热能的系统。包括反应堆系统、蒸汽发生器、反应堆中间回路系统、反应堆冷却剂系统、反应堆专设安全设施、反应堆保障系统、辐射监测系统及屏蔽等。"},
      { "code": "20", "name": "非H能源发生系统", "level": 2,"description": "H能源以外的JC推进用能源发生系统。包括常压锅炉、增压锅炉等。"},
      { "code": "30", "name": "动力机组及推进装置", "level": 2,"description": "为JC提供推进动力或为发电机提供原动力的动力机组或装置。包括蒸汽轮机、柴油机、燃气轮机、主电力推进装置、辅助电力推进装置、潜艇应急推进装置、联合推进装置等。"},
      { "code": "40", "name": "功率传递系统和推进器", "level": 2,"description": "将推进机组发出的功率传递到推进器推动JCHX的系统及设备。包括齿轮传动装置、离合器和联轴器、轴、轴承和轴封、推进器等。" },
      { "code": "50", "name": "推进保障系统", "level": 2,"description": "推进系统中为主锅炉、推进机组、功率传递系统服务的系统、机械设备及附件。包括日用燃油系统、滑油系统、蒸汽系统、凝水和给水系统、循环水和冷却水系统、起动系统、进排气系统、锅炉鼓风系统和排污系统、燃气轮机引气和清洗系统等。" },
      { "code": "60", "name": "推进监测和控制系统", "level": 2,"description": "对各种推进动力装置及其保障系统实施手动或自动控制（含集中控制或机旁控制）并进行显示、报警、安全保护等项目" }
    ]
  },

  "03": {
    "code": "03",
    "name": "电力系统",
    "level": 1,
    "children": [
      { "code": "00", "name": "总论", "level": 2,"description": "通用要求"  },
      { "code": "10", "name": "供电系统", "level": 2,"description": "电力系统中提供各种电能的系统。包括柴油发电机组、蒸汽轮机发电机组、燃气轮机发电机组、热气机发电机组、电池组及其附属设备、变电设备等。" },
      { "code": "20", "name": "配电系统", "level": 2,"description": "电力系统中对电源设备产生的电能进行分配、检测，以向负载供电的系统。包括主配电系统、应急配电系统、事故配电系统、专用配电系统和接岸电设施等。" },
      { "code": "30", "name": "照明系统", "level": 2,"description": "由各种灯具、照明配电板、配电和控制电路构成的用于JC照明的系统。包括主照明系统、应急照明系统、低照度照明系统和专用灯照明系统等。" },
      { "code": "40", "name": "电气监测和控制系统", "level": 2,"description": "对JC电站、电气传动设备等实施监测和控制的系统。包括电站、电气传动、配电系统、照明系统和电池等的监测和控制。" },
      { "code": "50", "name": "发电机组保障系统", "level": 2,"description": "对JC发电机组的正常运行起保障作用的设备和动力管路系统的设计、制造、布置、安装、材料和试验验收等。包括柴油发电机组、蒸汽轮机发电机组、燃气轮机发电机组和热气机发电机组等的保障系统。" },
      { "code": "60", "name": "电缆敷设", "level": 2,"description": "包括全船电力电缆、信号电缆、控制电缆的敷设。不包括消磁电缆的敷设。" },
      { "code": "70", "name": "综合电缆系统", "level": 2,"description": "JC发电、变电、配电、监控、照明、储能、电气传动及电力推进等部分综合集成的电力系统，它可实现艇电力推进与日常负载之间能量的灵活调配。包括供电系统、配电系统、电力推进系统、能量管理系统及储能系统等。" },
      { "code": "80", "name": "电场、磁场防护系统", "level": 2,"description": "通过对JC磁场、电场的监测、控制和管理，确保JC电磁场隐身性能的系统。包括消磁系统和电场防护系统。" },
      { "code": "90", "name": "专用项目", "level": 2,"description": "包括避雷装置、日用生活电器、电力系统工作液体、电力系统备品备件和专用工具。" }
    ]
  },

  "04": {
    "code": "04",
    "name": "ZZ系统",
    "level": 1,
    "children": [
      { "code": "00", "name": "总论", "level": 2,"description": "通用要求"  },
      { "code": "10", "name": "信息感知", "level": 2,"description": "JC上用于获取目标信息，对信息进行综合分析和处理，概略测定其位置和判定其敌我属性的设备。包括射频前端设备、光频前端设备、声频设备等。" },
      { "code": "20", "name": "本JZZ指挥控制", "level": 2,"description": "用于实现单J（艇）ZZ指挥控制功能的系统、设备、模块等的总称。本组按照ZZ任务不同，主要包括ZZ态势生成，综合ZZ指挥控制，对空、对海、对水下、对陆方面ZZ综合控制，两栖ZZ、航空兵ZZ指挥控制，航空管制，无人ZBZZ控制等功能组成。" },
      { "code": "30", "name": "编队ZZ指挥", "level": 2,"description": "用于基于情报处理功能，指挥员根据分配的任务对不同任务编队实施ZZ指挥所必需的设备、软件和人员的总称。包括编队ZZ筹划、编队情报保障、编队协同ZZ指挥和编队ZZ保障等。" },
      { "code": "40", "name": "WQ控制及保障", "level": 2,"description": "主要包括雷弹发射装置，控制WQ对目标进行GJ的火力控制系统以及雷弹转运与贮存、保障系统和有关设施。" },
      { "code": "50", "name": "综合通信", "level": 2,"description": "用于实现JC内部和外部信息传输的各类通信系统以及配套的设备、设施等。具体包括内部通信保障设备、通信控制管理设备、无线通信设备、数据链设备、全J综合视频JS设备、应急遇险救生通信设备等。" },
      { "code": "60", "name": "综合导航", "level": 2,"description": "引导和保障JC平台按ZZ要求HX并提供JC运动状态信息支援的JZ系统、设备和器材的统称" },
      { "code": "70", "name": "大气海洋环境探测", "level": 2,"description": "探测、测量温度、湿度、气压、风速、海水温度、盐度、密度，以及云、降水、海雾、冰雹、雷电、浪涌等大气海洋环境要素和现象的设备，并对大气海洋环境信息接收、处理及提供相应保障服务的设备。包括大气环境探测设备、海洋环境探测设备、大气海洋环境信息接收设备、大气海洋环境信息处理及服务设备等。" },
      { "code": "80", "name": "基础保障", "level": 2,"description": "包括公共计算服务设备、密码BM设备、信息安全设备和对准保障设备等。" },
      { "code": "90", "name": "专用项目", "level": 2,"description": "包括电子试验、检测与监控设备、保障管理系统（政工保障和后勤保障）以及ZZ系统备品备件和专用工具等。" }
    ]
  },

  "05": {
    "code": "05",
    "name": "船舶保障系统",
    "level": 1,
    "description": "为JC控制、安全、供应和居住所要求的系统，包括舱室大气环境控制、消防系统、日用水系统、HSH防护系统、日用压缩空气和其他流体系统、生活保障系统、环境污染控制系统、损害管制监测与控制系统、综合平台管理系统、JC姿态控制系统等。",
    "children": [
      { "code": "00", "name": "总论", "level": 2,"description": "通用要求"  },
      { "code": "10", "name": "舱室大气环境控制系统", "level": 2,"description": "指控制舱室温度、湿度和净化空气、改善舱室环境的系统，包括日用蒸汽和供暖系统、通风系统、空气调节系统、空气再生与净化系统、冷藏系统及空气分析系统等。" },
      { "code": "20", "name": "消防系统", "level": 2,"description": "包括水消防系统、气体灭火系统、泡沫灭火系统、防爆系统及消防用品等。" },
      { "code": "30", "name": "日用水系统", "level": 2,"description": "提供JY生活或设备正常工作的海水和淡水系统，包括饮用水和洗涤水系统、甲板排水系统、日用海水系统、海水淡化装置及其系统、淡水冷却系统、机械和管路的泄水系统及舱底水系统等。" },
      { "code": "40", "name": "HSH防护系统", "level": 2,"description": "为保证HSHZZ条件下JY和ZB的ZZ能力而设置的综合防御系统，能够对HWQ、化学WQ、生物WQ等自身、载体及次生造成的危害，进行探测、防护和洗消，包括HSH监控系统、集体防护系统、水幕洗消系统和其他防护器材。" },
      { "code": "50", "name": "日用压缩空气和其他流体系统", "level": 2,"description": "包括日用压缩空气系统、其他压缩气体系统、气幕降噪系统、液压系统和专用管路系统等。" },
      { "code": "60", "name": "生活保障系统", "level": 2,"description": "为保障JY工作、生活需要而设置的居住、卫生、物品贮藏、膳食保障、休息活动以及医疗保障的舱室和设施，包括居住设施、膳食设施、服务设施、医疗设施和工作舱室设施。本组还包括船用家具和JC上小五金用品的基本要求。" },
      { "code": "70", "name": "环境污染控制系统", "level": 2,"description": "为防止海洋污染而设置的对油污水、生活污水、生活垃圾、医疗垃圾、餐厨垃圾、压载水进行处理的综合控制系统，包括油污水处理系统、生活污水处理系统、固体垃圾处理系统、餐厨垃圾处理系统、潜艇废物抛出装置和压载水处理系统。" },
      { "code": "80", "name": "损害管制监测与控制系统", "level": 2,"description": "包括对重要舱室的状态、舱室浸水、失火、通风及其他辅机进行集中监测、报警和控制。由损害管制控制台、综合报警器以及各种传感器等组成。" },
      { "code": "90", "name": "综合平台管理系统", "level": 2,"description": "ZB于JC，将平台上系统和设备的监测、控制、管理及辅助决策等功能集成为一个整体，形成的监控与管理信息系统，一般包括推进监控设备、电力监控设备、损管综合监控设备、综合J桥设备、综合保障管理系统、状态监测及维护维修设备、综合管理与决策设备以及系统共用基础设施等。" },
      { "code": "A0", "name": "JC姿态控制系统", "level": 2,"description": "利用JC上ZB的系统、设备，在JC破损、非破损状态下，为JC、JZ机及J上其他系统、ZB的正常使用提供姿态保障、提供舷侧防护及保证JC基本浮性稳性的系统，一般包括水面JC的纵倾平衡系统、横倾平衡系统、应急排水系统、压载水系统，以及潜艇潜浮系统、均衡系统、深度控制系统和操纵控制系统。" },
      { "code": "B0", "name": "专用项目", "level": 2,"description": "包括船舶保障系统工作液体、船舶保障系统备品备件和专用工具。" }
    ]
  },

  "06": {
    "code": "06",
    "name": "航空保障系统",
    "level": 1,
    "description": "JC上用于保障各型JZ机实现高效出动、安全回收、塔台飞行指挥、J面调运、油气电液供给、DY贮运加挂、维修任务支援等各类航空作业，保障JZ机安全上J并形成出动回收能力的系统，包括航空保障指挥管理系统，起飞和着J引导系统，JZ机放飞、回收及贮运系统，机载WQ保障系统，喷气燃料系统，航空电源系统，航空供气系统，JZ机辅助保障设施、JZ机维修及任务支援系统等。",
    "children": [
      { "code": "00", "name": "总论", "level": 2,"description": "通用要求"  },
      { "code": "10", "name": "航空保障指挥管理系统", "level": 2,"description": "为航空保障作业提供塔台飞行指挥、机务勤务综合指挥调度、飞行作训管理航空ZB和航空保障ZB信息管理、综合态势服务等指挥管理功能的系统。包括塔台飞行指挥设施、机务勤务综合指挥调度设施、飞行作训管理设施、航空ZB及资源信息管理设施、航空保障综合态势服务设施、航空保障作业能力评估设施等。" },
      { "code": "20", "name": "起飞和着J引导系统", "level": 2,"description": "用于指挥引导JZ机在JC上起飞和着J的系统，其采用光学、惯性、卫星等技术手段为JZ机提供位置、角度及目视引导信息，实现JZ机的安全起飞和着J。包括起飞和着J引导指挥设施、 雷达着J引导设备、光学助降设备、起降电视JS设备、微波着J引导设备、光电着J引导设备、卫星着J引导设备、甲板灯光设施等。" },
      { "code": "30", "name": "JZ机放飞系统", "level": 2,"description": "JC上保障JZ机起飞的系统。包括电磁弹射装置、飞机止动装置、喷气偏流板装置等。" },
      { "code": "40", "name": "JZ机回收系统", "level": 2,"description": "JC上保障JZ机回收的系统。包括电磁阻拦装置、液压阻拦装置、阻拦网设施、格栅装置、集成抓曳装置等。" },
      { "code": "50", "name": "JZ机贮运系统", "level": 2,"description": "用于JZ机在JC上贮存和转运的系统。包括贮运指挥设施、JZ机升降机、机库大门、 牵引设施、系留设施、调向转盘等。" },
      { "code": "60", "name": "机载WQ保障系统", "level": 2,"description": "JC上用于完成机载WQ管理、调度、贮存、转运、装配、维护等保障功能的设备与设施统称。包括机载WQ管理调度设施、机载WQ贮存装置、机载WQ转运设备、机载WQ挂卸设备、机载WQ装配维护设备等。" },
      { "code": "70", "name": "喷气燃料系统", "level": 2,"description": "为JZ机提供喷气燃料保障的系统。包括喷气燃料动力设施、喷气燃料监控设施、集成加油装置、喷气燃料安全保障设施、喷气燃料维护保障设施等。" },
      { "code": "80", "name": "航空电源系统", "level": 2,"description": "为JZ机提供航空电源保障的系统。包括航空电源供电设施、航空电源辅助保障设备、航空电源监控设施等。" },
      { "code": "90", "name": "航空供气系统", "level": 2,"description": "为JZ机提供航空氧气、氮气、压缩空气以及空调通风气体等各种气体保障的系统。包括航空气体制备设施、航空气体储用设施、压缩空气设备、航空TZ空调装置、航空供气监控设施等。" },
      { "code": "A0", "name": "JZ机辅助保障设施", "level": 2,"description": "为JZ机提供液压、冲洗、应急救援、人员保障、跑道保障等辅助保障作业的设施。包括液压保障设施、液冷保障设施、冲洗保障设施、JZ机应急救援设施、航空人员专用保障设施、跑道保障设施以及其它保障设施等。" },
      { "code": "B0", "name": "JZ机维修及任务支援系统", "level": 2,"description": "为JZ机在JC上的使用、维护、修理、训练以及数据分析、处理等各项作业提供直接保障的软、硬件设备的总称。包括维修保障设备、J基训练系统、远程维修支援系统、任务规划支持系统等。" }
    ]
  },

  "07": {
    "code": "07",
    "name": "TZ保障系统",
    "level": 1,
    "description":"JC为了保障履行陆特Z、补给、救捞、医疗卫勤、维修、海洋测量、ZC等TZ任务而配置的系统，包括陆特ZZB保障系统、无人ZB保障系统、海上补给与接收系统、救援和打捞系统、卫生勤务保障系统、维修系统、海洋测量系统、ZC系统等。",
    "children": [
      { "code": "00", "name": "总论", "level": 2,"description": "通用要求"  },
      { "code": "10", "name": "陆特ZZB保障系统", "level": 2,"description": "为登陆和TZZZZB提供ZZ支援保障的系统。包括陆特ZZB保障任务规划及指挥管理系统、陆特ZZB收放贮运系统、陆特ZZB辅助引导系统、陆特ZZB资源供应保障系统、陆特ZZB维护保障系统、陆特ZZBDY保障系统、陆特ZZB保障作业支持系统等。" },
      { "code": "20", "name": "无人ZB保障系统", "level": 2,"description": "为JZ无人ZB（JZ无人机保障见6组）提供ZZ支援保障的系统。包括无人ZB保障指挥调度及驻J管理系统、无人ZB收放贮运系统、无人ZB勤务保障系统、无人ZBDY保障系统、无人ZB辅助保障设施等。" },
      { "code": "30", "name": "海上补给与接收系统", "level": 2,"description": "JC海上HX时的补给和接收系统。包括JC之间的横向、纵向、靠帮补给和接收系统、直升机与JC之间的垂直补给系统、JC上的干货、液货存储转运系统，以及补给船的补给作业指挥管理系统。" },
      { "code": "40", "name": "救援和打捞系统", "level": 2,"description": "救生JC对水面事故（ZS）JC、ZB及落水人员等进行搜寻救助，减少其损失及伤害；对水下事故潜艇进行搜索探测，为艇员提供生命支持，协助艇员离艇脱险；对沉没于水中的JC、ZB或货物等进行打捞处置的系统。包括救援指挥管理系统、水面救助系统、水下救援系统和打捞系统等。" },
      { "code": "50", "name": "卫生勤务保障系统", "level": 2,"description": "指JC上执行本J及海上人员平时诊疗、Z时救治、转运等卫生勤务保障任务的系统。包括医疗信息管理系统、伤病员换乘系统、常规医疗系统、特勤医疗系统、JC防疫与防护设施和医疗保障系统等。" },
      { "code": "60", "name": "维修系统", "level": 2,"description": "JC上配置的对目标JC执行修理抢修操作，阻止其损害，恢复部分系统功能和HX能力的保障任务系统。" },
      { "code": "70", "name": "海洋测量系统", "level": 2,"description": "对海洋气象水文、潮汐洋流、地形地貌、温盐密度等进行测量记录JS的系统。包括海洋测量指挥管理系统、海洋测量设备及其收放贮运、资源供应、信息保障、维护保障等系统。" },
      { "code": "80", "name": "ZC系统", "level": 2,"description": "利用JC上配置的专用通信、雷达、光电、水声等ZC手段对外界目标环境等进行ZC，并对ZC得到的情报进行综合分析处理的系统。包括通信ZC系统、雷达ZC系统、光电ZC系统、水声ZC系统、情报综合处理系统和综合管理系统等。" },
      { "code": "90", "name": "专用项目", "level": 2,"description": "TZ保障系统备品备件和专用工具。" }
    ]
  },

  "08": {
    "code": "08",
    "name": "船舶装置",
    "level": 1,
    "description":"包括JC运动控制系统，机械式转运系统，门、窗、梯、盖等船体属具，舱室分隔和表面覆盖，防腐蚀与防污损和其他专用项目。",
    "children": [
      { "code": "00", "name": "总论", "level": 2,"description": "通用要求"  },
      { "code": "10", "name": "JC运动控制系统", "level": 2,"description": "为控制JC运动而设置的系统，包括操舵控制系统及操舵装置、舵、综合J桥设备、减摇系统、动力定位系统、主动转向装置、水翼收放控制装置和艉板可调装置等。" },
      { "code": "20", "name": "机械式转运系统", "level": 2,"description": "采用机械设施进行转运、操纵的系统。包括锚及其存放与操纵系统、系泊和拖曳系统、小艇及其收放系统、升降装置及其附属系统、货物转运系统等。" },
      { "code": "30", "name": "船体属具", "level": 2,"description": "JC上主要供人员通行又未列入其他各系统的门、窗、梯、盖、桅和桅樯信号，以及为保证人员安全、生活或JC运行所必需的索具和帆布制品、号型和号旗、彩旗、彩灯悬挂装置、栏杆、扶手和天幕装置等。" },
      { "code": "40", "name": "舱室分隔和表面覆盖", "level": 2,"description": "作为舱室分隔的非结构性舱壁，活动铺板和格栅，除涂料和金属镀层外的一切敷盖在船体和上层建筑舱室内用作隔热绝缘、防火、减振和隐身用的材料等。" },
      { "code": "50", "name": "防腐蚀与防污损", "level": 2,"description": "以防腐蚀为目的的涂料保护、金属涂层和电化保护，以及防止海洋生物附着于船体外表面造成污底的防污损。" },
      { "code": "60", "name": "专用项目", "level": 2,"description": "包括船体标识和标志、吃水标志、锁、钥匙和标签、防鼠和防害虫、救生设施、抗沉堵漏器材、拖曳体收放装置、浮筏及隔振装置、船舶装置工作液体、船舶装置备品备件和专用工具。" }
    ]
  },

  "09": {
    "code": "09",
    "name": "专用ZB系统",
    "level": 1,
    "description":"提供TZ任务能力的系统或设备。",
    "children": [
      { "code": "00", "name": "总论", "level": 2,"description": "通用要求"  },
      { "code": "10", "name": "TZ类型设备", "level": 2,"description": "为实现某个TZ任务能力配置的TZ设备" },
      { "code": "20", "name": "TZ修复设备", "level": 2,"description": "用来恢复设备性能的TZ修复设备(硬件/软件)，包括起重机和牵引支架设备等" },
      { "code": "30", "name": "TZ用途设备", "level": 2,"description": "系统中与JCZB相配合，以实现特殊任务目的的部分" }
    ]
  },

  "10": {
    "code": "10",
    "name": "训练系统",
    "level": 1,
    "description":"提供训练功能的系统或设备。",
    "children": [
      { "code": "00", "name": "总论", "level": 2,"description": "通用要求"  },
      { "code": "10", "name": "装置／附件／帮助", "level": 2,"description": "用来使培训人员获得足够的知识和技能，从而能够以最大的效率操作和维护系统的那些可交付使用的训练装置／附件／帮助。" },
      { "code": "20", "name": "设备", "level": 2,"description": "用来使培训人员获得足够的知识和技能，从而能够以最大的效率操作和维护系统的那些可交付使用的训练设备。" },
      { "code": "30", "name": "设施", "level": 2,"description": "用来使培训人员获得足够的知识和技能，从而能够以最大的效率操作和维护系统的那些可交付使用的训练设施。" }
    ]
  },

  "11": {
    "code": "11",
    "name": "维修、测试和保障系统",
    "level": 1,
    "description":"用于ZB监测、维护保养和维修的保障系统、设备或设施。",
    "children": [
      { "code": "00", "name": "总论", "level": 2,"description": "通用要求"  },
      { "code": "10", "name": "通用维修设备", "level": 2,"description": "用于使系统恢复到可使用状态的设施。" },
      { "code": "20", "name": "通用保障设备", "level": 2,"description": "用来保障和维护系统或子系统正常运行而不直接参与执行任务的设备。" },
      { "code": "30", "name": "测试和测量设备", "level": 2,"description": "实施特殊诊断、筛选或质量保证工作的过程中用来评估系统或设备的运行状态的通用测试和测量设备" },
      { "code": "40", "name": "保障和装卸设备", "level": 2,"description": "用于保障任务系统的可交付使用的工具和装卸设备" }
    ]
  }
}

_LEVEL2_NAME_MAP: Dict[str, Dict[str, str]] = {
    level1_code: {c["code"]: c["name"] for c in (level1.get("children") or [])}
    for level1_code, level1 in System_Name_Replace_Dict.items()
}


File_Dict={
  "A": {
    "name": "全船性完工文件",
    "files": {
      "01": "全船性完工文件目录",
      "02": "图样和图表",
      "03": "说明书",
      "04": "计算书",
      "05": "供应品清单",
      "06": "备品备件、工具等清单",
      "07": "履历簿",
      "08": "培训教材",
      "09": "多媒体",
      "10": "试验类文件",
      "11": "使用保养规程建议稿",
      "12": "质量证明类",
      "13": "其他文件"
    }
  },
  "B": {
    "name": "系统设备随机文件",
    "files": {
      "01": "随机文件目录",
      "02": "技术说明书",
      "03": "操作使用手册",
      "04": "BD级维修手册",
      "05": "零部件图解目录",
      "06": "图样及图表",
      "07": "备品备件、工具等清单",
      "08": "试验类文件",
      "09": "履历簿（书）",
      "10": "质量证明类",
      "11": "软件用户手册",
      "12": "成套设备汇总表",
      "13": "元器件明细表（包括自制及外购）",
      "14": "精度检查表",
      "15": "培训教材",
      "16": "多媒体",
      "17": "其他文件"
    }
  },
  "C": {
    "name": "JD级技术资料",
    "files": {
      "01": "预防性维修大纲",
      "02": "等级修理基准工程单",
      "03": "JD级维修手册",
      "04": "修理技术要求",
      "05": "修理原则工艺",
      "06": "关键件及寿命件检查方案及更换标准",
      "07": "计量校准保障方案",
      "08": "调试细则",
      "09": "大型设备出舱技术方案",
      "10": "修理结构方案",
      "11": "其他文件"
    }
  },
  "D": {
    "name": "非随装技术资料",
    "files": {
      "01": "ZB性能底数报告",
      "02": "ZB效能底数报告",
      "03": "ZB使用保养规程",
      "04": "ZB故障案例",
      "05": "ZBZZ使用手册"
    }
  }
}

def openai_chat(query: str, model="Qwen3.5-35B-A3B"):
    """调用OpenAI API"""
    try:
        client = OpenAI(
            api_key="none",
            base_url="http://192.168.0.46:59800/v1"
        )

        response = client.chat.completions.create(
            model=model,
            messages=[
                {"role": "user", "content": query},
            ],
            temperature=0.1,
            stream=False,
            response_format={"type": "json_object"},
            extra_body={"chat_template_kwargs": {"enable_thinking": False}}
        )
        return response.choices[0].message.content
    except Exception as e:
        print(f"调用OpenAI API时出错: {e}")
        return None
    

def safe_json_loads(s: str):
    try:
        return json.loads(s)
    except json.JSONDecodeError as e:
        # 尝试修复常见问题
        s = s.replace("\\n", "\\\n").replace("\r", "\\r").replace("\t", "\\t")
        # 或者直接清理非法字符
        s = re.sub(r'[\x00-\x1f\x7f]', '', s)  # 移除控制字符
        try:
            return json.loads(s)
        except:
            raise e



def extract_entity_rela(prompt= str) -> dict:
    content = openai_chat(prompt)
    try:
        cleaned = content.strip()
        if cleaned.startswith("```json"):
            cleaned = cleaned[7:].lstrip()
        if cleaned.endswith("```"):
            cleaned = cleaned[:-3].rstrip()
        
        json_result = safe_json_loads(cleaned)

        return json_result
    except Exception as e:
        return []


# def get_excel_node_relation(
#     excel_path: str,
#     sheet_name: Optional[str] = None,
#     batch_size: int = 3):
#     """从Excel提取实体和关系"""
#     all_entities = []
#     all_relationships = []
    
#     try:
#         # 1. 读取Excel数据
#         table_json = excel_to_jsondata(excel_path=excel_path, sheet_name=sheet_name)
#         if not table_json:
#             logger.warning("Excel文件为空")
#             return all_entities, all_relationships
            
#         # 2. 判断表格类型
#         data = json.dumps(table_json, ensure_ascii=False, indent=2)
#         prompt_type = prompt_type_excel.replace("{text}", data)
#         typeresult = openai_chat(prompt_type)
        
#         if not typeresult:
#             logger.error("类型判断失败")
#             return all_entities, all_relationships
        
#         # 3. 解析类型
#         try:
#             cleaned = typeresult.strip()
#             if cleaned.startswith("```json"):
#                 cleaned = cleaned[7:].lstrip()
#             if cleaned.endswith("```"):
#                 cleaned = cleaned[:-3].rstrip()
            
#             json_result = safe_json_loads(cleaned)
#             table_type = json_result.get("type", "")
            
#             if not table_type:
#                 logger.error("类型字段缺失")
#                 return all_entities, all_relationships
                
#         except Exception as e:
#             logger.error(f"解析类型失败: {e}")
#             return all_entities, all_relationships
        
#         # 4. 根据类型处理
#         if table_type == "备品备件":
#             logger.info("提取备品备件...")
#             print(data)
#             prompt = prompt_beipinbeijian.replace("text", data)
            
#             try:
#                 result = extract_entity_rela(prompt)
                
#                 if not result or not isinstance(result, dict):
#                     return all_entities, all_relationships
                
#                 entities = result.get("entities", [])
#                 relationships = result.get("relationships", [])
                
#                 for entity in entities:
#                     if "properties" not in entity:
#                         entity["properties"] = {}
#                     if isinstance(entity["properties"], dict):
#                         entity["properties"]["切片"] = data
                
#                 all_entities.extend(entities)
#                 all_relationships.extend(relationships)
#                 logger.info(f"完成: {len(entities)}实体, {len(relationships)}关系")
                
#             except Exception as e:
#                 logger.error(f"备品备件提取出错: {e}")
        
#         elif table_type == "故障汇总":
#             logger.info(f"提取故障汇总 (共{len(table_json)}条, 批量{batch_size})...")
            
#             for batch_idx in range(0, len(table_json), batch_size):
#                 batch = table_json[batch_idx:batch_idx + batch_size]
                
#                 try:
#                     batch_data = json.dumps(batch, ensure_ascii=False, indent=2)
#                     prompt = prompt_guzhanghuizong.replace("text", batch_data)
                    
#                     result = extract_entity_rela(prompt)
                    
#                     if not result or not isinstance(result, dict):
#                         continue
                    
#                     entities = result.get("entities", [])
#                     relationships = result.get("relationships", [])
                    
#                     for entity in entities:
#                         if "properties" not in entity:
#                             entity["properties"] = {}
#                         if isinstance(entity["properties"], dict):
#                             entity["properties"]["切片"] = batch_data
                    
#                     all_entities.extend(entities)
#                     all_relationships.extend(relationships)
                    
#                 except Exception as e:
#                     logger.error(f"批次{batch_idx//batch_size + 1}出错: {e}")
#                     continue
            
#             logger.info(f"完成: {len(all_entities)}实体, {len(all_relationships)}关系")
        
#         else:
#             logger.warning(f"未知类型: {table_type}")
    
#     except Exception as e:
#         logger.error(f"执行失败: {e}")
    
#     return all_entities, all_relationships


def get_excel_node_relation(
    excel_path: str,
    sheet_name: Optional[str] = None,
    batch_size: int = 3):
    """从Excel提取实体和关系"""
    all_entities = []
    all_relationships = []
    
    try:
        # 1. 读取Excel数据
        table_json = excel_to_jsondata(excel_path=excel_path, sheet_name=sheet_name)
        if not table_json:
            logger.warning("Excel文件为空")
            return all_entities, all_relationships
            
        # 2. 判断表格类型
        data = json.dumps(table_json, ensure_ascii=False, indent=2)
        prompt_type = prompt_type_excel.replace("{text}", data)
        typeresult = openai_chat(prompt_type)
        
        if not typeresult:
            logger.error("类型判断失败")
            return all_entities, all_relationships
        
        # 3. 解析类型
        try:
            cleaned = typeresult.strip()
            if cleaned.startswith("```json"):
                cleaned = cleaned[7:].lstrip()
            if cleaned.endswith("```"):
                cleaned = cleaned[:-3].rstrip()
            
            json_result = safe_json_loads(cleaned)
            table_type = json_result.get("type", "")
            
            if not table_type:
                logger.error("类型字段缺失")
                return all_entities, all_relationships
                
        except Exception as e:
            logger.error(f"解析类型失败: {e}")
            return all_entities, all_relationships
        
        # 4. 根据类型处理
        if table_type == "备品备件":
            logger.info("提取备品备件...")
           
            total_batches = (len(table_json) + batch_size - 1) // batch_size
        
            for batch_idx in range(0, len(table_json), batch_size):
                batch = table_json[batch_idx:batch_idx + batch_size]
                current_batch_num = batch_idx // batch_size + 1
                
                try:
                    # 将当前批次转为JSON字符串
                    batch_data = json.dumps(batch, ensure_ascii=False, indent=2)
                    
                    # 使用对应类型的prompt模板
                    prompt =  prompt = prompt_beipinbeijian.replace("text", data)
                    
                    # 调用实体关系提取
                    result = extract_entity_rela(prompt)
                    
                    if not result or not isinstance(result, dict):
                        logger.warning(f"批次{current_batch_num}/{total_batches}未返回有效结果")
                        continue
                    
                    entities = result.get("entities", [])
                    relationships = result.get("relationships", [])
                    
                    # 为每个实体添加切片属性
                    for entity in entities:
                        if "properties" not in entity:
                            entity["properties"] = {}
                        if isinstance(entity["properties"], dict):
                            entity["properties"]["切片"] = batch_data
                    
                    # 累加到总结果中
                    all_entities.extend(entities)
                    all_relationships.extend(relationships)
                    
                    logger.info(
                        f"批次{current_batch_num}/{total_batches}完成: "
                        f"{len(entities)}实体, {len(relationships)}关系"
                    )
              
                except Exception as e:
                    logger.error(f"批次{current_batch_num}/{total_batches}出错: {e}")
                    continue
        
        elif table_type == "故障汇总":
            logger.info(f"提取故障汇总 (共{len(table_json)}条, 批量{batch_size})...")
            
            for batch_idx in range(0, len(table_json), batch_size):
                batch = table_json[batch_idx:batch_idx + batch_size]
                
                try:
                    batch_data = json.dumps(batch, ensure_ascii=False, indent=2)
                    prompt = prompt_guzhanghuizong.replace("text", batch_data)
                    
                    result = extract_entity_rela(prompt)
                    
                    if not result or not isinstance(result, dict):
                        continue
                    
                    entities = result.get("entities", [])
                    relationships = result.get("relationships", [])
                    
                    for entity in entities:
                        if "properties" not in entity:
                            entity["properties"] = {}
                        if isinstance(entity["properties"], dict):
                            entity["properties"]["切片"] = batch_data
                    
                    all_entities.extend(entities)
                    all_relationships.extend(relationships)
                    
                except Exception as e:
                    logger.error(f"批次{batch_idx//batch_size + 1}出错: {e}")
                    continue
            
            logger.info(f"完成: {len(all_entities)}实体, {len(all_relationships)}关系")
        
        else:
            logger.warning(f"未知类型: {table_type}")
    
    except Exception as e:
        logger.error(f"执行失败: {e}")
    
    return all_entities, all_relationships


# if __name__ == "__main__":
#     strat_time = time.time()
#     excel_file = "F:\zklnlp\HJ\hj_kg_code\kgrag\extract_excel\螺旋桨-备品备件.xlsx"   # ← 你的 Excel
#     all_entities, all_relationships = get_excel_node_relation(excel_file)
#     end_time = time.time()
#     print(len(all_entities))
#     print(len(all_relationships))
#     print(end_time-strat_time)

