import json import sys import os import asyncio import networkx as nx # 경로 설정을 위해 현재 파일의 디렉토리를 sys.path에 추가 current_dir = os.path.dirname(os.path.abspath(__file__)) sys.path.append(current_dir) from pid_geometric_extractor import PidGeometricExtractor from pid_topology_builder import PidTopologyBuilder from pid_intelligent_mapper import IntelligentMapper, validate_mapping async def run_full_pipeline(): # 1. 경로 설정 input_dxf = os.path.join(current_dir, "No-10_Plant_PID.dxf") geo_json_path = os.path.join(current_dir, "shared_geo_data.json") graph_json_path = os.path.join(current_dir, "pid_graph_topology.json") mapping_result_path = os.path.join(current_dir, "pid_final_mapping.json") # --- Phase 1: Geometric Extraction --- print("\n--- Phase 1: Geometric Extraction ---") try: extractor = PidGeometricExtractor(input_dxf) extractor.extract_and_save(geo_json_path) print(f"Geometric data saved to {geo_json_path}") except Exception as e: print(f"Phase 1 failed: {e}") return # --- Phase 2: Topology Modeling --- print("\n--- Phase 2: Topology Modeling ---") try: with open(geo_json_path, 'r', encoding='utf-8') as f: geometric_data = json.load(f) builder = PidTopologyBuilder( geometric_data=geometric_data, all_extracted_tags=[], config={'dist_threshold': 50.0, 'tag_threshold': 100.0} ) builder.build_graph() builder.save_graph(graph_json_path) print(f"Graph topology saved to {graph_json_path}") except Exception as e: print(f"Phase 2 failed: {e}") return # --- Phase 3: Intelligent Mapping --- print("\n--- Phase 3: Intelligent Mapping ---") try: # 1. 그래프 로드 with open(graph_json_path, 'r', encoding='utf-8') as f: graph_data = json.load(f) # NetworkX 그래프 복원 (node_link_data 형식 대응) from networkx.readwrite import json_graph G = json_graph.node_link_graph(graph_data) # 2. 시스템 태그 리스트 (실제로는 API나 DB에서 가져와야 함) # 테스트를 위한 가상 태그 리스트 system_tags = [ "PT-101.PV", "PT-102.PV", "FT-201.PV", "LT-301.PV", "P-101.STATUS", "P-101.SPEED", "V-101.OPEN", "V-101.CLOSE", "T-101.TEMP", "TK-101.LEVEL" ] # 3. 매퍼 초기화 (API Key는 환경변수나 설정파일에서 가져오는 것을 권장) api_key = os.getenv("OPENAI_API_KEY", "your-api-key-here") mapper = IntelligentMapper(G, system_tags, api_key=api_key) # 4. 노드 분류 및 매핑 실행 nodes = list(G.nodes()) transmitter_nodes = [n for n in nodes if "Transmitter" in G.nodes[n].get('type', '')] valve_nodes = [n for n in nodes if "Valve" in G.nodes[n].get('type', '')] equipment_nodes = [n for n in nodes if "Equipment" in G.nodes[n].get('type', '') or "Pump" in G.nodes[n].get('type', '')] print(f"Mapping {len(transmitter_nodes)} transmitters, {len(valve_nodes)} valves, {len(equipment_nodes)} equipment...") # 비동기 실행 results = await asyncio.gather( mapper.extract_transmitters(transmitter_nodes), mapper.extract_valves(valve_nodes), mapper.extract_equipment(equipment_nodes) ) # 결과 통합 final_mapping_raw = {} for res in results: final_mapping_raw.update(res) # 5. 검증 및 최종 결과 정리 # 가상 메타데이터 (실제로는 시스템에서 조회) mock_metadata = { "PT-101.PV": {"unit": "bar", "description": "Pressure Transmitter 101"}, "P-101.STATUS": {"unit": "", "description": "Pump 101 Status"}, } final_results = [] for node_id, mapping in final_mapping_raw.items(): symbol_type = G.nodes[node_id].get('type', 'Unknown') tag = mapping.resolved_tag meta = mock_metadata.get(tag, {"unit": "", "description": ""}) is_valid, val_msg = validate_mapping(tag, symbol_type, meta) final_results.append({ "node_id": node_id, "symbol_type": symbol_type, "original_text": G.nodes[node_id].get('value', ''), "resolved_tag": tag, "confidence": mapping.confidence, "reason": mapping.reason, "validation": { "is_valid": is_valid, "message": val_msg } }) # 6. 결과 저장 with open(mapping_result_path, 'w', encoding='utf-8') as f: json.dump(final_results, f, indent=4, ensure_ascii=False) print(f"Final mapping results saved to {mapping_result_path}") print(f"Successfully mapped {len(final_results)} nodes.") except Exception as e: print(f"Phase 3 failed: {e}") import traceback traceback.print_exc() if __name__ == "__main__": asyncio.run(run_full_pipeline())