import json import fitz # PyMuPDF import os from collections import Counter from kg_build.Prompt import prompt_extract_beipinbeijian_node_rela from openai import OpenAI from extract_util import safe_json_loads, highlight_pdf_file, get_content_bbox from modelsAPI.model_api import OpenaiAPI # 指定 JSON 文件路径 # file_path = '/storage01/home/hdf/project/wxkgrag/kgextract/output/122-06A0014-B01001_发动机-维修手册_content_list.json' # try: # with open(file_path, 'r', encoding='utf-8') as file: # data = json.load(file) # except Exception as e: # print(f"读取 JSON 文件时出错:{e}") # data = [] # 为每条记录添加 id(从1开始) def get_beipinbeijian_chunk_bbox_and_removed_data(data): # 定义三种可能的表头格式 labels = [ '', '
名称型专规格
', '<
序号名称型号规格
', '
序号名称型号规格
', '
序号名称型号规格
', '
名称型专规格
', '
备品备件、附件和工具清单
设备备品备件清单设备型号设备装舰台套数
', '
序号名 称型号规格图号或标准号
' ] record_map = {item["id"]: item for item in data} results = [] ids_to_remove = set() for ins in data: if ins.get("type") == "table": table_body = ins.get("table_body", "") if any(label in table_body for label in labels): current_id = ins["id"] # 获取当前及前4个记录的 id(确保 >=1) group_ids = [current_id - i for i in range(4, -1, -1) if current_id - i >= 1] ids_to_remove.update(group_ids) # 按顺序构建 group(从最早到当前) group = [record_map[pid] for pid in group_ids if pid in record_map] results.append(group) filtered_data = [item for item in data if item["id"] not in ids_to_remove] return results, filtered_data async def extract_beipinbeijian_table_entity(chunk): print("提取备品备件类实体和关系") final_prompt = prompt_extract_beipinbeijian_node_rela.format(text=chunk) raw_response = await OpenaiAPI.openai_chat_aysnc(final_prompt,timeout=600) if raw_response is None: print("API 调用失败,跳过当前 chunk") return [] try: cleaned = raw_response.strip() if cleaned.startswith("```json"): cleaned = cleaned[7:].lstrip() if cleaned.endswith("```"): cleaned = cleaned[:-3].rstrip() json_result = safe_json_loads(cleaned) if json_result is None: print("JSON 解析失败: 返回 None") return [] return json_result except Exception as e: print(f"⚠️ JSON 解析异常: {e}") print(f"原始响应片段: {repr(raw_response[:500])}") return [] async def get_beipinbeijian_node_relation(input_pdf_path,data,prefix_url = "http://192.168.0.46:59085"): for idx, item in enumerate(data, start=1): item["id"] = idx # 主流程 guzhang_groups, cleaned_data = get_beipinbeijian_chunk_bbox_and_removed_data(data) if not guzhang_groups: print("未找到符合条件的备品备件表格,跳过处理。") all_entity_results,all_relation_results = [],[] else: all_entity_results,all_relation_results = [],[] # 用于收集所有成功提取的结果 for i, compose in enumerate(guzhang_groups): try: print(f"开始处理第{i+1}个备品备件表") # 获取内容和高亮信息 content, highlight_list = get_content_bbox(compose) print("备品备件表切片内容为:",content) # 提取实体 result =await extract_beipinbeijian_table_entity(content) if result is []: print(f"第 {i+1} 组:实体提取失败,跳过") continue # 安全访问 entities 字段 entities = result.get("entities", []) if not isinstance(entities, list): print(f"第 {i+1} 组:entities 字段格式异常,跳过") continue relationships = result.get("relationships", []) # 为每个 entity 添加 knowledge_source highlight_filename, most_common_page,filename = highlight_pdf_file(input_pdf_path,highlight_list) url = f"{prefix_url}/upload/{highlight_filename}#page={most_common_page}" # for entity in entities: # knowledge_source = [{ # "filename": filename, # "info": content, # "url": url # }] # # 确保 properties 存在 # if "properties" not in entity or not isinstance(entity["properties"], dict): # entity["properties"] = {} # entity["properties"]["knowledge_source"] = knowledge_source for entity in entities: # 构造原始数据对象 (List of Dict) source_data_list = [{ "filename": filename, "info": content, "url": url }] # 2. 【关键修改】将列表序列化为 JSON 字符串 # ensure_ascii=False 确保中文内容不会被转义成 \uXXXX knowledge_source_str = json.dumps(source_data_list, ensure_ascii=False) # 确保 properties 存在且是字典 if "properties" not in entity or not isinstance(entity["properties"], dict): entity["properties"] = {} # 3. 赋值字符串而不是对象列表 entity["properties"]["knowledge_source"] = knowledge_source_str # 更新 result 中的 entities all_entity_results.extend(entities) all_relation_results.extend(relationships) except Exception as e: print(f"处理第 {i+1} 组时发生未预期错误: {e}") continue # 跳过当前组,继续下一轮 return all_entity_results,all_relation_results # if __name__ == "__main__": # file_path = '/app/files/122-06A0014-B01001_发动机-维修手册_content_list.json' # input_pdf_path = "/app/files/122-06A0014-B01001_发动机-维修手册.pdf" # try: # with open(file_path, 'r', encoding='utf-8') as file: # data = json.load(file) # except Exception as e: # print(f"读取 JSON 文件时出错:{e}") # data = [] # all_entity_results,all_relation_results = get_guzhang_node_relation(input_pdf_path,data=data) # length_entity = len(all_entity_results) # length_relation = len(all_relation_results) # print(f"抽取{length_entity}个实体,抽取{length_relation}个关系")
序号名称型专规格