Files
ExperionCrawler/plans/PID-추출이후-이용방안플랜.md
windpacer 302183c97e feat: P&ID 연결 분석, LLM 에이전트 모드, KB 확장, MCP 서버 리팩토링
- P&ID: 연결 분석 API, Prefix 규칙 관리, 카테고리 분류, DXF 그래프 빌드
- LLM: 대화 요약, tool card 영구 보존, 시계열 차트(uPlot), 에이전트 모드
- KB: 청크 미리보기, Field Instrument Inference, 인증/Qdrant 클라이언트
- MCP: 서버 기능 확장, 파이프라인 수정, timeout 개선
- Frontend: P&ID UI, LLM UI, KB UI, OPC UA Write 탭 추가
- 설정: AGENTS.md, plant_context, README, opencode.json 업데이트
- 정리: 진단 체크리스트 문서 삭제
2026-05-21 23:36:57 +09:00

34 KiB
Raw Blame History

P&ID 추출 데이터 이용방안 플랜

작성일: 2026-05-14 배경: pid_equipment 테이블에 No-10_Plant_PID.dxf로부터 460건의 구조화 데이터(태그·라인번호·fluid·종류·area) 적재 완료. Experion realtime_table과의 자동 매핑(exact + prefix only, false positive 제거)도 동작 중. 다음 단계로 이 데이터를 무엇에 쓸지 결정.

현재 보유 데이터

컬럼 의미 예시
tag_no 추출된 원본 태그/라인번호 P-10138-600A-F2A-H100, PSV-10217, FCV-6113
instrument_type prefix 분류 FCV, PSV, P, T, BT, LIA
line_number LineNo 식별번호 (pipe만) 10138, 6203
confidence 추출 신뢰도 0.95~0.99
experion_tag_id realtime_table FK (매핑 시) NULL or int
is_active 활성 여부 true/false

서버 내부 사전(코드)으로 _PID_FLUID_DICT(P=PROCESS, CWS=COOLING WATER SUPPLY 등 19종), _PID_EQUIPMENT_PREFIX(P=Pump, T=Tank, F=Filter 등 14종), _PID_INSTRUMENT_FIRST/_PID_INSTRUMENT_MODIFIER(ISA letter 코드)도 함께 보유.


갈래 1 — 채팅 컨텍스트 보강 (최우선 추천)

가치: 운전원이 즉시 체감. 작업량 최소. 작업량: 0.5~1일.

구현

MCP 도구 2개 추가 (mcp-server/server.py):

@mcp.tool()
async def find_pid_equipment(query: str, kind: str | None = None,
                              area: str | None = None, limit: int = 20) -> str:
    """P&ID 장비/계기 검색. tag_no ILIKE 매칭 + kind/area 필터.

    kind: 'pipe'|'equipment'|'instrument' (없으면 전체)
    area: 6-1 → tag_no가 P-61XX/T-61XX 등 6+1로 시작
    """

@mcp.tool()
async def get_pid_equipment_info(tag_no: str) -> str:
    """단일 태그 상세. 매핑된 Experion 태그도 함께 반환.

    응답: {tag_no, type(fluid 또는 장비종류), instrument_type, line_number,
            experion_tag, latest_value (있으면)}
    """

ToolGuideKo(OllamaController.cs)에 새 도구 설명 추가 → LLM이 자동 활용.

효과 예시

  • "PSV-10217이 뭐야?" → "Pressure Safety Valve (mechanical, OPC 신호 없음). 10차 area"
  • "10차에 펌프 몇 대?" → find_pid_equipment(kind='equipment', area='10') → 카운트 + 리스트
  • "P-10138 어떤 fluid?" → "PROCESS FLUID, 600A, F2A spec, H100 단열"
  • "FCV-6113 지금 값은?" → 매핑된 experion 태그로 자동 join → 실시간값

갈래 2 — 알람·이벤트 컨텍스트 자동 주입

가치: 알람 보고서가 풍부해짐. 운전원이 태그 코드만 보고 의미 파악 가능. 작업량: 0.5일. 기존 summarize_events/generate_status_report에 join 추가.

구현

  • query_events 결과를 pid_equipment와 LEFT JOIN해서 각 이벤트에 PID 컨텍스트 첨부
  • 예: ALARM event tagname=fcv-6113.pv → 컨텍스트 "FCV-6113, Flow Control Valve, 6-1 area, P-10138 라인의 PROCESS 흐름 제어"
  • generate_status_report 마크다운 출력에 "## 영향 장비" 섹션 추가 (해당 area의 PID 인벤토리 요약)

효과

  • 알람 요약 LLM이 "단순 태그 나열" → "공정 맥락 포함된 운전 보고서"로 격상
  • KB 문서에서 같은 area의 절차서 자동 인용 (search_kb area 필터 + PID 데이터 연동)

갈래 3 — P&ID 다이어그램 시각화 (UI)

가치: 시각적 자산 파악. 도면 없이도 area별 장비 구조 한눈에 보기. 작업량: UI 작업 중심. 그래프 보기까지 가려면 from-to 추출 추가 필요.

Phase 3a (즉시 가능)

현재 데이터만으로 — area별·종류별 트리뷰/리스트뷰:

└─ 10차 area
   ├─ 펌프 (15)         P-10101, P-10116, …
   ├─ 탱크 (19)         T-10101, T-10102, …
   ├─ 필터 (4)          F-10101A, F-10101B, …
   ├─ 안전밸브 (18)     PSV-10101, PSV-10103, …
   └─ 라인 (172)        P-10138, CWS-10612, …

14번 P&ID 탭 또는 신규 탭에서 구현.

Phase 3b (확장, 작업 큼)

DXF에서 라인 끝점 좌표 + 장비 좌표 추출 후 KD-tree로 from-to 추정 → cytoscape/d3로 노드 그래프. 사용자 이미 결정한 "위치좌표 계산 없이" 방향과 상충 — 추후 필요해질 때만 착수.


갈래 4 — 자산 마스터 + KB 통합 (장기 그림)

가치: 단순 검색을 넘어 정비·운영 데이터 통합 플랫폼. 작업량: 큼. 다른 데이터 소스 통합 필요.

구성요소

  1. equipment_registry.yaml (이전 논의) — Experion htm에서 추출한 좌표·area + PID 추출 데이터 머지
  2. 정비/점검 일정 테이블 — 종류별 주기 정의 (PSV 1년, FCV 6개월, …) → 다음 점검일 자동 계산
  3. 누락 검출 리포트pid_equipment(P&ID 기준) vs realtime_table(Experion 기준) 양방향 차집합
    • P&ID에만 있는 것 → 측정 누락 (or mechanical/지표 없는 장비)
    • Experion에만 있는 것 → 도면 누락 (or 시스템 신호)
  4. KB 문서 자동 인용search_kb에 PID 태그 정보 자동 추가해서 검색 품질 향상

의존성

  • equipment_registry yaml 구축이 선결 (이전 결정: htm 파서 추가)
  • 정비 일정은 별도 사용자 입력 또는 기존 정비 시스템 연동 필요

갈래 5 — 기존 infer_field_instruments와의 통합 (보완 관계, 죽이지 않음)

배경: RAG 관리 → Field Instrument 탭의 기존 기능(infer_field_instruments → Excel 초안 다운로드)이 parse_pid_dxf 등장 후 의미를 잃었는지 의문 제기됨. 결론: 의미 없어지지 않음, 오히려 통합 가치가 생김.

두 기능의 본질적 차이

구분 infer_field_instruments (기존) parse_pid_dxf (신규)
입력 소스 Experion DB의 OPC 태그 (v_tag_summary) DXF 도면 파일
추론 방향 "실제 측정점이 있다 → 현장에 계기 있을 것" "도면에 그려져 있다 → 자산으로 존재"
ficq-6101 처리 base 보고 FT-6101 / FIC-6101 / FCV-6101 3개로 분해 도면에 그려진 그대로 (보통 FCV-6101, FIC-6101 등) 인식
PSV-10217 (mechanical, 신호 없음) 못 만듦 도면에 있으면 추출
추가된 임시 계기 (OPC 신호만 존재) 추론 가능 도면에 없으면 못 잡음
출력 Excel 초안 (운전원 수동 검수 후 KB 업로드) pid_equipment 테이블
동력기기 power_equipment role로 별도 분류 Pump prefix(P) 등으로 분류

잡는 누락이 정반대 — 단독으로는 불완전

  • OPC 신호 있지만 도면 미반영: infer_field_instruments만 잡음 (도면 업데이트 누락 케이스)
  • 도면엔 있지만 OPC 신호 없음: parse_pid_dxf만 잡음 (PSV/수동밸브/게이지/파이프 등 mechanical 자산)
  • 둘 다 존재: match_pid_tags가 자동 연결 (exact + prefix)

통합으로 새로 가능해지는 작업

  1. infer_field_instruments 출력 자동 검증

    • infer가 추론한 FT-6101이 실제 도면(pid_equipment)에 있는지 즉시 대조
    • 추론 정확도 자동 측정 → 추론 룰 개선 피드백 루프 가능
  2. Excel 초안 자동 라벨링 보강

    • 도면에는 PSV-10217이 있는데 infer는 못 만들었음 → "OPC 신호 없는 mechanical" 라벨로 Excel에 자동 행 추가
    • 도면 LineNo 정보(P-10138-600A-F2A-H100)로 fluid/size/material 컬럼 자동 채움
    • infer가 만든 row와 P&ID에서만 보이는 row를 한 Excel에 합쳐서 운전원이 한 번에 검수
  3. 양방향 차집합 리포트 (갈래 4의 핵심 산출물)

    차집합 의미 운영 액션
    pid_equipment realtime_table (도면 ⊖ 실제) 도면엔 있는데 측정 없는 자산 (a) mechanical → 정상, "OPC 신호 없음" 라벨로 마스터에 등록
    (b) 측정 누락 → 신호 추가 검토
    realtime_table pid_equipment (실제 ⊖ 도면) 측정은 있는데 도면 없는 신호 도면 업데이트 누락 → P&ID 도면 보완 요청
    양쪽 모두 정상 매핑 UI에서 표시 (현재 상태)

구현 (작업량 적음)

  • infer_field_instruments의 dedup 단계 뒤에 pid_equipment LEFT JOIN 한 번
    • infer 결과 row마다 in_pid_drawing: bool, pid_line_number, pid_drawing_no 컬럼 추가
    • infer가 만들지 못한 pid_equipment row를 별도 시트(Pid_Only_Mechanical)로 Excel에 추가
  • parse_pid_dxf는 손대지 않음. infer 쪽에만 join 추가
  • 운전원이 다운받는 Excel이 그대로 더 풍부해짐 — 추가 UI 변경 불필요

의존성

  • 갈래 1·2 없어도 가능. 단독 진행 가능
  • infer_field_instruments의 출력 Excel 포맷 일부 변경 (시트 추가) — 기존 운영 흐름에 영향 적음

갈래 6 — PID 추출 → 옵시디언 노트 부트스트랩 → 하이브리드 RAG

배경: plans/옵시디언-구조적용-플랜.md는 마크다운 노트 + [[wikilinks]] + frontmatter 기반 그래프 RAG를 제안하지만 아직 미구현 (notes/ 디렉토리·DB 테이블 없음, 위키링크가 들어있는 .md는 계획 문서 자체뿐). 옵시디언 노트 시스템을 0에서 시작하면 "초기 비어있음" 문제가 큰데, PID 추출 결과를 활용하면 첫날부터 460개 anchor 노트로 부트스트랩 가능.

역할 분담

영역 PID 추출 (pid_equipment) 옵시디언 노트 (planned)
채우는 것 뼈대 — 모든 태그/라인/장비 자동 인벤토리 — 절차, 루프 의미, 트러블슈팅, 벤더 정보, 운전 노하우
입력 도면 1번 + 자동 운전원/엔지니어 수기 + 채팅 저장
갱신 도면 바뀌면 재추출 사람이 알게 될 때마다
핵심 식별자 tag_no (FCV-6113, P-10101) 노트 ID tag/fcv-6113, loop/compression-a

공통 anchor가 tag ID — PID가 만든 모든 태그는 곧 노트 ID가 되고, 사람이 쓴 노트는 [[tag/fcv-6113]] 위키링크로 PID 인벤토리에 자동 연결.

구현 단계

Step 1 — PID stub 노트 자동 생성

pid_equipment 460건을 각각 frontmatter-only .md 파일로 발행:

---
id: tag/fcv-6113
kind: tag
prefix: FCV
type: Flow Control Valve
area: 6-1
line_number: 6113
experion_tag: fcv-6113.pv
source_drawing: No-10_Plant_PID.dxf
source: pid_equipment.id=42
generated_at: 2026-05-14
---
<!-- 본문은 비어둠 — 운전원이 채움 -->
  • 디렉토리: notes/tag/, notes/area/, notes/drawing/
  • 한 파일 = 한 노트 = pid_equipment 1행
  • 본문 비어있어도 anchor 역할 → 위키링크 타깃으로 즉시 사용 가능

Step 2 — 사람 노트는 위에 자라남

운전원/엔지니어가 만드는 손 노트는 별도 kind:

원칙: 사람은 신규 마크다운만 쓰고 PID stub은 안 건드림. 재추출 시 stub 안전하게 덮어쓰기 가능.

Step 3 — Stub 갱신 정책

PID 재추출 시:

  • frontmatter는 항상 최신 pid_equipment 값으로 덮어씀
  • 본문(<!-- comment --> 아래)에 운전원이 추가한 텍스트가 있으면 보존 (merge 로직)
  • 새로 등장한 tag → 신규 stub 생성
  • 사라진 tag → archived: true frontmatter 추가 (파일 삭제 안 함, 위키링크 깨짐 방지)

Step 4 — KB 인덱싱 + 그래프 엣지 추출

notes/ 디렉토리를 KbIngestWorker가 별도 컬렉션(예: kb_notes)으로 처리:

  • 노트 1개 = 1 청크 (헤딩으로 자르지 않음 — 작은 단위 유지)
  • frontmatter → Qdrant payload (area, kind, prefix 필터링 가능)
  • 본문에서 [[note-id]] 정규식 추출 → 신규 테이블 kb_note_edges (source_id, target_id, link_type)에 적재

Step 5 — 채팅 RAG에 그래프 1-hop 결합

search_kb가 top-k 청크 검색 → 각 청크가 노트면 kb_note_edges에서 1-hop 위키링크 타깃 조회 → 그 타깃 노트들의 frontmatter+첫 200자를 컨텍스트에 함께 주입.

# 의사 코드
chunks = search_kb(query, top_k=5)
extra_context = []
for chunk in chunks:
    if chunk.note_id:
        targets = db.fetch_edges(chunk.note_id, depth=1)
        extra_context.extend(targets)  # 5개 청크 + N개 1-hop 노트
return chunks + extra_context  # LLM에 함께 전달

LLM은 청크 5개만이 아니라 "이 청크와 명시적으로 연결된 절차/루프/이벤트 패턴"까지 함께 보고 답변.

트레이드오프

  • (+) 옵시디언 시스템의 "초기 비어있음" 문제 해결 — 첫날부터 460개 anchor 보유
  • (+) 운전원이 채팅에서 받은 답변을 loop/surge-recovery.md 한 줄로 영구화 가능 → 지식 자산이 자라남
  • (+) 마크다운이라 외부 옵시디언 앱으로 열어 편집해도 호환 (부수효과)
  • () stub 갱신 시 본문 보존 머지 로직 필요 (text diff 충돌 검출)
  • () 운전원이 위키링크 작성 습관 안 들이면 anchor만 잔뜩에 살이 없는 상태 → 저진입 UX 필수:
    • 채팅에서 "이 답변을 loop/compression-a에 저장" 같은 한 클릭 액션
    • 노트 작성 시 [[ 입력하면 자동완성 드롭다운으로 PID stub 추천

의존성

  • 갈래 1 권장 선결 — PID 데이터 조회 인프라가 있어야 stub 생성 스크립트 작성이 쉬움
  • 옵시디언-구조적용-플랜.md의 데이터 모델 결정사항 따름 (note ID 규칙, kind 9종, frontmatter 스키마)
  • KbIngestWorker에 notes 디렉토리 전용 처리 분기 추가

작업 분할

단계 산출물 작업량
Step 1 mcp-server/notes_sync.py — pid_equipment → notes/tag/*.md stub 생성기 0.5일
Step 3 머지 보존 로직 + archived 처리 0.5일
Step 4 KbIngestWorker notes 분기 + kb_note_edges 테이블 + 위키링크 파서 1일
Step 5 search_kb 그래프 1-hop 보강 + 채팅 통합 0.5일
사람 노트 저진입 UX "답변 → 노트 저장" 버튼, [[ 자동완성 1일 (UI)
합계 3.5일

갈래 7 — Excel 라운드트립으로 service/role 메타데이터 보강 (마지막 연결고리)

배경: DXF 파서는 tag·LineNo·fluid(파이프 한정)·prefix 분류는 자동 추출하지만, 장비의 실질 정보(service, role, contents, from-to)는 도면에 텍스트로 없음. 예: T-201이 원료탱크인지 폐액탱크인지, 무슨 fluid를 담는지, 어디로 보내는지 — LLM이 답할 컨텍스트가 없음. 운전원이 가장 익숙한 도구(Excel)로 한 번에 채우는 round-trip이 가장 실용적인 해결책.

갈래 5와의 차이: 갈래 5는 infer_field_instruments Excel(현장 계기 초안, 다운로드 전용)에 PID 정보를 합치는 것. 갈래 7은 PID 메타데이터를 사람이 채워 다시 시스템에 반영하는 round-trip — 편집 가능한 마스터 시트.

시트 구성 (장비 종류별 분리)

시트 자동 채워진 컬럼 사용자가 채울 컬럼
Tanks (T-XXX) tag_no, area, source_drawing service, role(feed/buffer/product/waste), contents(PGMEA/HBM/...), capacity, notes
Drums (D-XXX) 위와 동일 service, role, contents
Filters (F-XXX) tag_no, area service, medium, from_tag, to_tag
Heat Exchangers (E-XXX) tag_no, area service, hot_side, cold_side, duty
Columns (C-XXX) tag_no, area service, product, overhead, bottom
Pumps (P-XXX) tag_no, area, mapped_experion_tag service, driver(motor/turbine), from_tag, to_tag, power_kw
Compressors / Fans tag_no, area service, driver, power_kw
Cooling Towers tag_no, area service, capacity
Manual Valves (BV/GV/XV) tag_no, area service, normal_position(open/closed), purpose
Pipes (LineNo) service, fluid, size, spec, insul (이미 파싱됨) from_tag, to_tag (오직 이거만)
Legend dropdown 후보 (role 종류, fluid 코드, position 등)
Index 시트별 완성도 (채워진 비율)

Round-trip 흐름

[다운로드]
  pid_equipment → 장비 종류별 그룹핑 → 시트별 분리 → Excel 생성
  (자동 채운 컬럼 + 빈 컬럼 + dropdown legend)
                ↓
[운전원이 채움 (며칠~몇 주, 영역별 분할 가능)]
                ↓
[업로드]
  Excel 파싱 → 검증 (dropdown 값, 필수 필드, 참조 tag_no 존재 여부)
  → pid_equipment에 신규 컬럼들(service, role, contents, from_tag, to_tag, …) UPDATE
  → 변경 diff 리포트 (몇 건 채워졌는지, 무효 값 몇 건)
  → (갈래 6 도입 후) tag stub 노트 frontmatter 자동 갱신

데이터 모델 확장

pid_equipment 테이블에 컬럼 추가:

ALTER TABLE pid_equipment
  ADD COLUMN service        TEXT,     -- 운전원 입력 fluid/용도 (P=PROCESS와 별개로 자유 텍스트)
  ADD COLUMN role           TEXT,     -- feed_tank, buffer_tank, waste_tank, transfer_pump, ...
  ADD COLUMN contents       TEXT,     -- PGMEA, HBM, CITY_WATER, ...
  ADD COLUMN from_tag       TEXT,     -- 흐름 상류 tag (수동 입력)
  ADD COLUMN to_tag         TEXT,     -- 흐름 하류 tag
  ADD COLUMN driver         TEXT,     -- motor / turbine / electric / steam
  ADD COLUMN capacity       TEXT,     -- 자유 텍스트 (단위 포함)
  ADD COLUMN power_kw       NUMERIC,
  ADD COLUMN user_notes     TEXT,     -- 운전원 자유 메모
  ADD COLUMN metadata_filled_at TIMESTAMPTZ;  -- 마지막 사용자 갱신 시각

갈래 5/6과의 관계 — 같은 그림의 다른 단계

단계 역할 갈래
자동 추출 뼈대 (모든 태그 자동 인벤토리) PID 파서 (완료)
자동 검증 Excel mechanical/누락 자산 검출 (read-only) 갈래 5
수기 보강 round-trip 구조화 슬롯 일괄 채우기 (service/role/from-to) 갈래 7 (이 항목)
노트 자동 생성 tag stub frontmatter에 갈래 7 데이터 자동 반영 갈래 6 Step 1
채팅 RAG 강화 위 모두 통합 검색 갈래 1+2+6

갈래 7이 진짜 마지막 연결고리. 이게 없으면 갈래 6 stub의 frontmatter가 빈약하고, 채팅도 "T-201이 뭐 담는지" 답을 못 함.

트레이드오프

  • (+) Excel은 운전원이 가장 자연스럽게 다루는 도구 — 마크다운 학습 비용 0
  • (+) 한 번 다운로드받아 오프라인에서도 채울 수 있음
  • (+) 시트별 분리로 "오늘은 펌프만, 내일은 탱크만" 같은 분할 작업 가능
  • (+) dropdown legend로 데이터 일관성 자동 확보
  • () Excel은 discrete batch — 동시에 여러 사람이 채우면 머지 충돌 위험. 한 번에 한 사람 권장
  • () 다운로드 받은 파일이 오래되면 사이에 PID 재추출로 신규 tag 생긴 경우 머지 필요 — 업로드 시 "신규 tag는 이번 Excel에 없음" 경고
  • () 한 번에 460건 다 채우라 하면 부담 → 영역별/종류별 분할 가이드 필요 ("이번 주는 6-1 area Pump만")

구현 (작업량)

단계 산출물 작업량
DB 마이그레이션 pid_equipment 신규 컬럼 ALTER + InitializeAsync DDL 갱신 0.3일
다운로드 엔드포인트 GET /api/pid/metadata/excel — 시트별 분리 Excel 생성 (openpyxl) 0.5일
업로드 엔드포인트 POST /api/pid/metadata/excel — 파싱+검증+UPDATE+diff 리포트 1일
UI (RAG 관리 또는 P&ID 탭) 다운로드/업로드 버튼 + 진행률 + diff 표시 0.5일
Legend dropdown 사전 role/contents/driver 등 유효값 정의 + 운영 후 확장 가능하게 0.2일
합계 2.5일

의존성

  • 갈래 1·5와 독립적으로 진행 가능
  • 갈래 6보다 먼저 끝나야 stub frontmatter가 풍부해짐 → Phase B 또는 Phase C 초반에 진행 권장

갈래 8 — LineNo 파생 정보 컬럼 추가 (작지만 모든 갈래에 가치 전파)

배경: 현업 통찰 — 운영 부서는 LineNo(P-10138, 16456 등 시공·단관 제작용 번호)로 파이프를 부르지 않음. 가치 있는 건 거기서 파생되는 {service, fluid, size, material, flange_rating, insulation}. LineNo 자체는 시공·정비 참조용으로 보존하되, 파생 정보를 별도 컬럼으로 저장해야 운영 검색·통계·일관성 검증이 가능해짐.

현재 상태: _parse_pid_lineno가 MCP 응답에 7개 필드를 다 담고 있지만, C# 측이 line_number 하나만 DB에 저장하고 나머지는 버리고 있음. 추출은 되는데 활용이 안 됨.

구현

-- pid_equipment 컬럼 추가 (line_number는 그대로 유지)
ALTER TABLE pid_equipment
  ADD COLUMN service_code     TEXT,     -- 'P', 'CWS', 'ST', 'VG', ...
  ADD COLUMN fluid_name       TEXT,     -- 'PROCESS FLUID', 'STEAM' (legend 변환)
  ADD COLUMN pipe_size        TEXT,     -- '25A', '600A'
  ADD COLUMN material_spec    TEXT,     -- 'F', 'S'
  ADD COLUMN flange_rating    INT,      -- 1=150#, 2=300#
  ADD COLUMN insul_code       TEXT,     -- 'A', 'B'
  ADD COLUMN insul_thickness  TEXT;     -- 'H50', 'H100', 'E50', 'n'

장비/계기 행은 이 컬럼들이 NULL — 정상. 한 테이블 유지, 정규화 분리 안 함.

변경 파일

파일 변경
ExperionDbContext.InitializeAsync ALTER TABLE 7개 컬럼 추가 (또는 새 설치용 CREATE TABLE 갱신)
PidEquipment 엔티티 7개 속성 + [Column("snake_case")] 매핑
ExtractedItem DTO 7개 필드 추가 (PipeService/FluidName/PipeSize/...)
PidExtractorService.ParseJson MCP 응답의 pipe 필드를 ExtractedItem에 매핑
PidExtractorService.ExtractFromStreamAsync save 시 7개 컬럼 채움 (pipe 행만, instrument/equipment는 null)
MCP extract_pid_tags / parse_pid_dxf 이미 7개 필드 응답 중 — 변경 불필요

활용은 자동으로 따라옴

컬럼만 채워지면 기존 갈래들이 즉시 더 풍부해짐:

  • 갈래 1 채팅 검색: "CWS 25A 이상 라인", "스팀 H100 단열 라인" 같은 속성 조합 검색 즉시 가능
  • 갈래 6 stub frontmatter: pipe 노트에 service: P, fluid: PROCESS FLUID, pipe_size: 25A, insul_thickness: H50 자동 반영 → 노트가 빈약하지 않음
  • 갈래 7 Pipes 시트: 자동 채워진 컬럼이 7개로 늘어남, 사용자는 from_tag/to_tag/서비스별칭만 채우면 됨
  • (부수효과) 사양 분포 리포트, 일관성 검증 같은 분석이 가능해짐 — 필요할 때 별도 도구로 노출하면 됨 (지금은 컬럼만 추가)

작업량

단계 산출물 작업량
DB 컬럼 추가 ALTER TABLE + InitializeAsync DDL 갱신 0.2일
PidEquipment 엔티티 + [Column] 매핑 7개 속성 추가 0.1일
ExtractedItem 7개 필드 + ParseJson 매핑 DTO 확장 0.2일
PidExtractorService save 경로 7개 컬럼 INSERT 0.2일
기존 460건 재추출 (또는 in-place UPDATE 스크립트) truncate 후 재추출이 간단 0.1일
합계 0.8일

의존성

  • 없음. 단독 진행 가능
  • 갈래 1·6·7의 가치를 증폭시키므로 가장 먼저 배치 권장

갈래 9 — 추출 결과 저장·폐기 선택 UX (실수 방지)

배경: 현재 P&ID 추출 UI는 "추출 시작" 클릭 시 MCP 추출 → pid_equipment 즉시 INSERT가 자동으로 이뤄짐. 운전원이 실수로 다른 파일(다른 플랜트, 구버전 도면 등)을 추출해도 되돌릴 방법이 없음. TRUNCATE는 정상 데이터까지 날아가서 사용 불가. 추출 전/후에 사용자가 검토·취사선택할 수 있어야 함.

결정 보류: 아래 3개 옵션 중 어느 방향으로 갈지 사용자 결정 필요.

옵션 비교

옵션 A — Dry-run + 저장 버튼 (사전 검토)

[추출 시작] → MCP 추출만 (DB 저장 X) → "미리보기 460건" 표시
              ├── [✅ DB에 저장] → INSERT 수행
              └── [🗑️ 폐기] → 결과 버림
항목 내용
장점 가장 안전 — DB 들어가기 전 검토 가능. 운전원 의도 명확 ("이걸 저장할까?")
단점 UI 흐름 2단계로 늘어남. 결과를 서버 임시 캐시 또는 클라이언트 메모리에 보관 필요. 사용자가 검토 중 페이지 떠나면 데이터 잃음
작업량 약 1일
구현 PidExtractorService.ExtractWithoutSaveAsync 추가, IMemoryCache 결과 보관, UI에 미리보기 + 저장/폐기 버튼

옵션 B — 자동 저장 + 즉시 취소 버튼 (사후 롤백)

[추출 시작] → MCP 추출 → DB 저장 (extraction_batch_id 부여)
                       → "✅ 추출 완료: 460건" + [🗑️ 이번 추출 취소] 버튼
                                                        ↓
                                          batch_id WHERE 절로 일괄 삭제
항목 내용
장점 기존 UX 거의 그대로. 추출 이력 자체가 자동으로 남아 추후 분석 가능
단점 저장 후 후속 작업(confidence 수정 등)이 일어났으면 일괄 삭제가 그 작업까지 날림 → "최근 N분만 취소 가능" 같은 가드 필요. 다른 사용자가 잠깐 잘못된 데이터 볼 수 있음
작업량 약 0.5일
구현 pid_equipment.extraction_batch_id (UUID) 컬럼 추가, 추출 시 부여, UI에 "이번 추출 취소" 버튼 + 시간 가드

옵션 C — A + 영구 batch_id 보존 (절충)

[추출 시작] → MCP 추출 (DB 저장 X, staging 보관)
              ├── [저장] → batch_id와 함께 INSERT
              │           → 이후에도 "추출 이력" 페이지에서 batch_id로 일괄 삭제 가능
              └── [폐기] → staging만 버림
항목 내용
장점 A의 안전성 + B의 사후 롤백 모두 확보. "추출 이력" 페이지에서 과거 batch 단위 관리 가능
단점 작업량 가장 큼. UI도 가장 복잡 (미리보기 + 저장 + 이력 관리)
작업량 약 1.5~2일
구현 옵션 A + 옵션 B 합친 형태. staging 캐시 + batch_id 컬럼 + 이력 페이지

추천 (결정 보류 상태)

우선 고려 추천 옵션
안전성 우선 옵션 A
작업량 최소 옵션 B
장기 운영 (감사·이력) 옵션 C

운전원이 자주 추출하는 운영 환경이면 옵션 A의 사전 검토가 정신적 부담 적고 안전 — 기본 추천은 옵션 A. 단, "추출 이력 관리" 같은 요구가 미래에 나올 가능성이 크면 옵션 C가 미리 대응됨.

의존성

  • 옵션 A: IMemoryCache 또는 클라이언트 세션 — 표준 ASP.NET Core 기능
  • 옵션 B/C: pid_equipment.extraction_batch_id 컬럼 (UUID) — 갈래 8 컬럼 추가와 함께 ALTER 묶어 처리하면 효율적
  • 어느 옵션이든 갈래 8과 같은 시점에 진행하면 마이그레이션 1번으로 끝낼 수 있음

결정 시점

  • 갈래 1~5 진행 중 사용 패턴 보면서 결정 가능 (당장 결정 안 해도 됨)
  • 단, 옵션 B/C를 선택한다면 갈래 8 마이그레이션 시 extraction_batch_id 컬럼을 함께 추가하는 게 효율적 → 갈래 8 착수 전에 한 번 가볍게 결정 권장

추천 진행 순서

우선순위 항목 작업량 가치 의존성
0 갈래 8 (LineNo 파생 정보 컬럼 추가) 0.8일 모든 갈래에 가치 전파 없음
0+ 갈래 9 (추출 결과 저장/폐기 UX) 0.5~2일 (옵션별) 높음 (실수 방지) 갈래 8과 함께 마이그레이션 묶기 권장
1 갈래 1 (MCP 도구 2개) 0.5~1일 높음 갈래 8 권장
2 갈래 5 (infer ↔ pid_equipment 통합 Excel) 0.5일 높음 없음
3 갈래 2 (이벤트 컨텍스트) 0.5일 높음 갈래 1
4 갈래 7 (Excel round-trip으로 service/role 보강) 2.5일 매우 높음 갈래 8 권장
5 갈래 6 (옵시디언 노트 부트스트랩 + 하이브리드 RAG) 3.5일 매우 높음 (장기) 갈래 1·7·8 권장
6 갈래 3a (트리뷰 UI) 1~2일 없음
7 갈래 4 일부 (누락 검출 리포트 단독) 0.5일 갈래 5와 중복 — 갈래 5에 통합 권장
보류 갈래 3b (그래프 시각화) 사용 패턴 보고 결정 from-to 추출
보류 갈래 4 전체 (정비 일정·KB 통합) equipment_registry, 정비 시스템

추천 흐름

Phase 0 (반나절, 0.8일) — 모든 갈래의 가치 증폭 0. 갈래 8: pid_equipment에 service/fluid/size/material/flange/insul 7개 컬럼 추가 + 460건 재추출

  • 이후 모든 갈래가 더 풍부한 데이터로 동작

Phase A (이번 주, 1~2일) — 즉시 효과

  1. 갈래 1: find_pid_equipment / get_pid_equipment_info 추가 → 갈래 8로 채워진 7개 필드까지 검색·표시
  2. 갈래 5 병행: infer_field_instrumentspid_equipment join 추가 → Excel 초안에 mechanical/누락 자산 자동 포함

Phase B (Phase A 사용 패턴 본 뒤, 0.5일) — 정착 단계 3. 갈래 2: 알람·이벤트 컨텍스트에 PID 정보 자동 첨부 → 보고서 품질 향상

Phase C (2.5일 + 운전원 채움 기간) — 마지막 연결고리 4. 갈래 7: Excel round-trip 인프라 구축 → 운전원이 service/role/contents/from-to 채움

  • 자동 컬럼이 갈래 8 덕분에 7개 더 풍부 → 사용자 부담 줄어듦
  • 구축 자체는 2.5일이지만 운전원이 채우는 데 며칠~몇 주 걸림 (영역별 분할)
  • 일부라도 채워지면 즉시 갈래 1·2의 답변 품질이 올라감 (T-201 → "PGMEA 원료 탱크" 답변 가능)

Phase D (Phase C 진행 중 병행, 3.5일) — 지식 자산화로 진화 5. 갈래 6: PID stub 자동 생성 → 옵시디언 노트 시스템 부트스트랩 → 하이브리드 RAG

  • 갈래 8·7의 결과가 stub frontmatter로 자동 반영되어 빈약하지 않음
  • 운전원이 채팅에서 노트 작성 습관 들이면 시간이 갈수록 그래프가 자라남
  • 장기적으로는 이 갈래가 시스템의 핵심 자산 — PID/Experion은 자동 입력 소스, 노트는 사람의 운영 지식 저장소

Phase E (필요해질 때) — 확장 6. 갈래 3a: 시각적 인벤토리 필요해지면 트리뷰 UI 작업 7. 갈래 4 전체 또는 갈래 3b: 정비 시스템 연동/그래프 시각화 등은 실제 운영 요구가 명확해진 시점에 착수

우선순위 배치 근거

  • 갈래 8 최우선: 0.8일 작업으로 갈래 1·6·7 모두의 데이터 가치를 증폭. ROI 극단적으로 높음. 다른 모든 작업 전에 끝내는 게 합리적
  • 갈래 5 > 갈래 4: 갈래 4의 핵심 산출물(양방향 차집합 리포트)이 갈래 5의 Excel 시트로 자연스럽게 포함됨. 운전원이 이미 익숙한 UX 위에 얹는 거라 학습 비용 0
  • 갈래 7 > 갈래 6: 갈래 6 stub의 frontmatter는 갈래 7의 결과(service/role/contents)로 채워질 때 비로소 가치가 있음. 갈래 7 없이 갈래 6만 가면 빈 anchor만 잔뜩
  • 갈래 7 > 갈래 3a: service/role이 채워지지 않은 상태에서 시각화는 "이름만 있는 그림" — 우선 의미를 채워야 함
  • 갈래 6은 갈래 1·2·7·8 이후가 적기: 채팅에서 PID 데이터 활용 패턴이 나오고 메타데이터가 채워진 뒤라야 노트 시스템이 의미 있음

결정 필요 항목

  • 갈래 8 즉시 착수 여부 — pid_equipment 7개 컬럼 추가 + 460건 재추출 (0.8일, ROI 최고)
  • 갈래 9 옵션 선택 — A(dry-run, 1일) / B(자동저장+취소, 0.5일) / C(절충, 1.5~2일) 중 하나 선택. 갈래 8 착수 전 결정 권장 (B/C면 extraction_batch_id 컬럼을 갈래 8 마이그레이션에 함께 묶음)
  • 갈래 1 즉시 착수 여부 — find_pid_equipment / get_pid_equipment_info MCP 도구 추가
  • 갈래 5 즉시 착수 여부 — infer_field_instrumentspid_equipment LEFT JOIN + 별도 시트 추가
  • 갈래 2 진행 여부 — Phase A 정착 후
  • 갈래 7 데이터 모델 확정 — pid_equipment 컬럼 추가 항목(service/role/contents/from_tag/to_tag/driver/capacity/power_kw/user_notes) 확인
  • 갈래 7 legend dropdown 사전 시드값 — role/contents/driver 유효값 누가 정의
  • 갈래 7 운전원 채우기 가이드 — 영역별 분할 방식(어떤 area부터?)
  • 갈래 6 Step 1·2 일정 — PID stub 생성기 + 머지 보존 로직 (갈래 8·7 컬럼이 stub frontmatter로 흐르도록 같이 설계)
  • 갈래 6 Step 5 (그래프 1-hop RAG) — search_kb 수정 시점 확정 필요
  • 갈래 6 저진입 UX (채팅 답변 → 노트 저장 버튼) — UI 작업 일정
  • 갈래 3a 트리뷰 UI 작업 일정 — 갈래 7 보강 데이터가 채워진 뒤가 효과적
  • 갈래 4 단독 누락 검출 리포트 — 갈래 5에 흡수할지, 별도 페이지로 만들지

잔여 데이터 정합성 이슈

  • 중복 추출: 현재 460건 중 동일 tag_no가 2번씩 들어간 행 다수 발견 (예: PSV-10101이 2회). DXF에서 같은 텍스트가 여러 위치에 그려져서 발생. unique index 또는 (tag_no, pid_drawing_no) 복합키로 해결 필요.
  • pid_drawing_no NULL: 현재 모든 행 NULL. 도면 파일명을 자동 채우거나 사용자 입력 받도록 보강 필요 — 갈래 4 누락 검출에 도면 단위 추적 필요할 때.
  • prefix 오분류: PFD, SP, SC, TR 등 도면 라벨/약어가 instrument로 잘못 분류되는 케이스 — _PID_TAG_RE 또는 _classify_pid_tag에 예외 사전 추가 필요.