docs: 현황보고 정보분산 진단 + plant_context 문서우선 절차
- 진단: 경로형 현황보고가 4소스+3규칙을 LLM이 수작업 종합 → 결함(FT/FCV 값 누락) 분석, 문서우선 채택. - plant_context: '유닛 KB 문서 먼저 검색 → 제어기 실시간값 조회 → 필드계기 루프매핑' 0순위 절차 + 필드계기 PV/OP 매핑 규칙 명시. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
131
docs/diagnosis-status-report-fragmentation.md
Normal file
131
docs/diagnosis-status-report-fragmentation.md
Normal file
@@ -0,0 +1,131 @@
|
||||
# 진단: 현황 보고 시 LLM의 정보 분산 문제
|
||||
|
||||
> 작성일 2026-06-10 · 대상: LLM 채팅이 "장비 현황/공정 경로"를 보고할 때 종합해야 하는 정보 구조
|
||||
> 결론 한 줄: **알람·이벤트 보고는 현 구조로 충분하다. 그러나 "장비 경로 + 실시간 값" 보고는 정보가 과도하게 분산되어 있고, 이미 실제 결함(FT/FCV 값 누락)을 일으켰다. 해결 필요.**
|
||||
|
||||
---
|
||||
|
||||
## 1. 문제 제기
|
||||
|
||||
사용자가 "6-1차 원료 투입 경로 현황"을 물으면, LLM은 하나의 답을 만들기 위해 **서로 다른 4곳의 정보를 직접 종합**해야 한다:
|
||||
|
||||
| # | 정보 | 출처 | 형태 |
|
||||
|---|---|---|---|
|
||||
| 1 | 장비 연결(from/to, category, tag_dcs) | `pid_equipment` | 1,173행, 다중행/태그 |
|
||||
| 2 | 실시간 값(PV/SP/OP, 운전상태) | `realtime_table` / `v_tag_summary` | 2,151행, enum 문자열 |
|
||||
| 3 | 메타(desc, 단위, euhi/eulo, sub_area, 상태라벨) | `tag_metadata` (EAV) | 7,401행, 14속성 long-form |
|
||||
| 4 | **필드계기 값 매핑 규칙**(FT→제어기.PV, FCV→제어기.OP) | **어디에도 테이블/도구 없음 — 산문(plant_context.md)에만 존재** | 규칙 |
|
||||
|
||||
실제로 직전 진단 한 번에서 LLM은 `run_sql`을 **4회 이상** 호출했고, 그 결과를 사람이 머릿속에서 join 했다. 그리고 **#4 규칙을 적용하지 못해 FT-6101·FCV-6101 현재값을 `-`로 비우는 결함**이 발생했다(사용자가 직접 지적).
|
||||
|
||||
---
|
||||
|
||||
## 2. 실측 근거 — 무엇이 분산되어 있나
|
||||
|
||||
### G1. 장비 중심의 통합 뷰가 없다
|
||||
- `v_tag_summary`는 **base_tag(realtime 태그 보유분) 중심** → 384개만 노출. realtime 태그가 없는 **장비·필드계기(FT-6101, 용기 D/T류, VP 등)는 아예 행이 없다.**
|
||||
- `pid_equipment`는 1,173개 장비를 담지만 **값이 없다(연결·메타만)**.
|
||||
- 두 테이블을 잇는 뷰/도구가 없어, "장비 → 연결 + 값 + 설명"을 한 번에 못 가져온다.
|
||||
|
||||
### G2. 필드계기 값 해석이 산문에만 있다 (가장 치명적)
|
||||
- FT/TT/LT/PT(측정) = 루프 제어기 `.PV`, FCV/TCV/LCV/PCV(개도) = 루프 제어기 `.OP`.
|
||||
- 실증: `realtime_table`에 `FT-6101%`·`FCV-6101%` **0행**. 값은 `FICQ-6101.PV`/`.OP` 안에만 있다.
|
||||
- 이 매핑을 **계산해 주는 뷰도 도구도 없다.** `trace_connections`조차 노드마다 `{tag}.PV`만 문자 그대로 조회 → 필드계기는 `live_state=None`이 되고, OP는 아예 안 붙인다.
|
||||
- 결국 LLM이 매번 손으로 추론해야 하고, 한 번이라도 빠뜨리면 곧바로 결함.
|
||||
|
||||
### G3. tag_metadata가 EAV라 pivot 부담
|
||||
- 14속성(area/euhi/eulo/state0~7/units/desc/sub_area)이 long-form. 한 장비의 메타를 보려면 pivot 필요.
|
||||
- `v_tag_summary`는 그중 desc/area/sub_area 3개만 노출 → units·euhi/eulo·상태라벨은 여전히 직접 조회.
|
||||
|
||||
### G4. enum 파싱 부담
|
||||
- 운전상태가 `{5 | R-RUN | }` 문자열. 일부 뷰/`trace_connections`만 파싱하고, 일반 `run_sql` 경로에선 LLM이 매번 정규식 추론.
|
||||
|
||||
### G5. 루프 멤버십이 휴리스틱
|
||||
- FT-6101↔FICQ-6101 연결을 "루프번호 6101 공유"로 추정. 저장된 FK가 아니라 추론이라, 번호 규칙이 깨지는 장비에서 취약.
|
||||
|
||||
### G6. 다축 정합 판단
|
||||
- "P-6201: sub_area=P6-2(메타) vs F-6101A/B로의 크로스타이 존재(배관) vs L-STOP(현재상태)" — 세 축을 모아 판단해야 함. 이건 LLM 판단이 맞는 영역이나, 입력이 흩어져 있으면 실수 확률↑.
|
||||
|
||||
---
|
||||
|
||||
## 3. 솔직한 평가 — 충분한가?
|
||||
|
||||
| 보고 유형 | 현 구조 | 판정 |
|
||||
|---|---|---|
|
||||
| 알람 / 이벤트 / 펌프 운전 교차검증 | `generate_status_report` + `v_plant_running_state_*` 뷰가 잘 통합 | ✅ **충분** |
|
||||
| **장비 경로 + 실시간 값 현황** (사용자가 실제로 하는 보고) | 4+ 쿼리 + 3개 파생규칙을 LLM이 매번 수작업 종합 | ❌ **불충분 · 이미 결함 발생** |
|
||||
|
||||
→ "지금 구조로 충분한가?"의 답은 **부분적으로만**. 경로형 현황 보고에 대해서는 **구조적으로 부족하며, 이론이 아니라 실제로 한 번 깨졌다**(FT/FCV `-`).
|
||||
|
||||
근본 원인: **결정론적으로 SQL/도구가 했어야 할 일(값 해석·조인)을 비결정론적인 LLM 산문 규칙에 떠넘기고 있음.** 규칙이 늘수록 누락 확률이 누적된다.
|
||||
|
||||
---
|
||||
|
||||
## 4. 해결방안 (우선순위)
|
||||
|
||||
### ★ S1 (권장 · 영향 大/노력 中): 장비 중심 "해석 완료" 뷰 + MCP 도구
|
||||
- `v_equipment_status` 뷰: 장비 1건당 한 행으로
|
||||
`{ tag_no, desc, category, tag_dcs, from_tag, to_tag, from_at, to_at,
|
||||
resolved_value, resolved_kind(PV/OP), unit, live_state }`
|
||||
를 반환. 핵심은 **필드계기 값 해석을 SQL의 CASE로 내장**:
|
||||
- 트랜스미터 → 같은 루프 제어기 `.PV`
|
||||
- 제어밸브 → 같은 루프 제어기 `.OP`
|
||||
- 제어기 자신 → `.PV`/`.SP`/`.OP` 직접
|
||||
- enum은 뷰에서 파싱해 사람이 읽는 상태로
|
||||
- MCP 도구 `equipment_status(tags[])` 또는 `trace_connections`가 이 뷰를 사용 → **1회 호출로 G1·G2·G4·G5 동시 해소**, LLM 종합 부담 제거.
|
||||
- 데이터는 이미 다 있다. JOIN + CASE + enum 파싱이라 **결정론적·테스트 가능**.
|
||||
|
||||
### S2 (노력 小): `trace_connections` 확장
|
||||
- 노드마다 `.PV`만이 아니라 **SP/OP + 필드계기→제어기 매핑된 값**을 붙이도록 보강. S1보다 좁지만 즉효.
|
||||
|
||||
### S3 (보강): 루프 멤버십 저장
|
||||
- instrument→controller 매핑 컬럼/테이블로 G5의 휴리스틱을 FK로 대체. S1/S2의 정확도를 끌어올림.
|
||||
|
||||
### S4 (임시방편 · 이미 일부 적용): plant_context.md 산문 규칙
|
||||
- 2026-06-10 필드계기 매핑 규칙을 plant_context.md에 추가함. **동작하지만 LLM 준수에 의존 → 이미 한 번 실패한 방식.** 1차 방어가 아니라 백업으로만 둘 것.
|
||||
|
||||
---
|
||||
|
||||
## 5. 권고
|
||||
|
||||
**S1을 구현한다.** 4쿼리+3규칙의 LLM 수작업 종합을, 데이터가 이미 존재하는 **1개의 결정론적 호출**로 바꾼다. 값 해석을 SQL로 내려보내면(테스트 가능한 자리) FT/FCV 누락 같은 결함이 구조적으로 재발 불가능해진다. S4(산문)는 S1이 들어오기 전까지의 임시 안전망으로만 유지한다.
|
||||
|
||||
미적용 시 리스크: 경로형 보고를 할 때마다 LLM이 규칙 누락·조인 실수를 낼 확률이 남고, 그때마다 사람이 검수해야 한다(이번처럼).
|
||||
|
||||
---
|
||||
|
||||
## 6. 재평가 — 문서 우선(document-first) 접근 (2026-06-10 추가, 채택)
|
||||
|
||||
S1(DB 뷰 신설)을 재검토한 결과, **현 제약(P&ID 자동추출 거의 불가능, 기존 연결 데이터 빈약)에서는 KB 문서 우선이 더 우월**하다고 판단. 근거는 `docs/kb/P6-1_경비물_제거_공정.md` 같은 잘 쓰인 유닛 문서가 분산 지점 대부분을 이미 해소한다는 것:
|
||||
|
||||
| 분산 지점 | DB 방식(S1) | 문서 방식 |
|
||||
|---|---|---|
|
||||
| G2 필드계기 값 매핑 | SQL CASE 별도 구현 | ✅ `FT-6113 → FICQ-6113 → FCV-6113` 표기가 매핑 그 자체 |
|
||||
| G5 루프 멤버십 | FK 테이블 신설 | ✅ 문서에 명시(추론 불필요) |
|
||||
| G1 토폴로지+의미 | 뷰로 일부만 | ✅ 흐름도+캐스케이드+설계의도까지 |
|
||||
| 작성 비용 | P&ID 추출(불가) + 1,173행 적재 | ✅ 사람이 마크다운 1장(검증·수정 가능) |
|
||||
|
||||
**그러나 "문서 하나로 전부"는 아니다.** 문서가 대체하는 것과 못 하는 것:
|
||||
- ✅ 대체: 연결관계 · 제어루프 의미 · 필드계기 매핑 → **토폴로지/구조 지식의 단일 진실원**
|
||||
- ❌ 불가: 실시간 값(PV/SP/OP는 `realtime_table`), 집계/구조화 질의, 알람·이벤트 이력(`generate_status_report`가 담당)
|
||||
|
||||
→ 최종 아키텍처는 **2-소스 모델**: `KB 문서(토폴로지·매핑) + DB(실시간 값·알람·집계)`. 기존 4소스+3규칙 → 2소스로 축소, 가장 까다로운 부분이 사람이 읽는 문서로 내려감.
|
||||
|
||||
### 리스크
|
||||
1. **KB 미적재**: `kb_documents` 현재 0행 — 인프라(Qdrant 벡터검색 + `search_kb`/`rag_query` + `KbIngestWorker`)는 완비됐으나 P6-1 문서조차 아직 미적재. 적재 플로우부터 태워야 검색됨.
|
||||
2. **태그 대소문자 불일치**: 문서는 `TI-6111a`(소문자), realtime은 대문자 → 값 조회 시 정규화 필요.
|
||||
3. **RAG 검색 신뢰성**: "현황 질의 → 유닛 KB 문서 검색 → 문서의 제어기 태그 실시간 값 조회" 절차를 `plant_context.md`에 명시해야 LLM이 일관되게 동작.
|
||||
4. **커버리지**: 유닛마다 좋은 문서 1장 필요(진짜 노동). 단, 불가능한 P&ID 추출 대신 검증 가능한 영속 지식을 만드는 노동이라 방향 타당.
|
||||
|
||||
### 채택 결정 및 실행
|
||||
- **문서 우선 전환.** `pid_equipment`는 삭제 않고(복원한 187 locked는 보조 백스톱) 주 진실원에서 **보조로 강등**.
|
||||
- 실행: ① 기존 P6-1 문서 적재 + 동일 템플릿으로 유닛별 문서 작성, ② `plant_context.md`에 "유닛 KB 검색 → 실시간 값 조회 → 루프 표기로 필드계기 해석" 절차 명시, ③ DB는 알람/이벤트/집계 담당 유지.
|
||||
- S1(뷰 신설)은 향후 P&ID 데이터가 풍부해질 때까지 **보류**. S4(plant_context 산문 규칙)는 문서 적재 전까지의 임시 안전망.
|
||||
|
||||
---
|
||||
|
||||
## 부록 · 현 자산 인벤토리
|
||||
- 뷰: `v_tag_summary`(PV/SP/OP/INSTATE+desc/area/sub_area, base_tag 중심), `v_analog_points`, `v_instrument_range`, `v_pump_signal_map`, `v_plant_running_state` / `_agg` / `_corroborated`
|
||||
- MCP 도구: `trace_connections`(토폴로지+PV enum), `generate_status_report`(알람·이벤트·펌프 교차검증), `run_sql`, `query_pv_history`, `query_with_nl`
|
||||
- 프롬프트: `prompts/plant_context.md`(계기약어·enum 판정·경로설명·필드계기 매핑 규칙)
|
||||
- 연결 데이터: `pid_equipment` 1,173행(연결 267, locked 187) — 2026-06-10 `public`→`hc900` 복원분
|
||||
@@ -103,9 +103,10 @@ area-level 유틸리티) 또는 (2) 아직 미분류 상태입니다. 공용 여
|
||||
|
||||
## 태그 명명 규칙
|
||||
|
||||
- 태그는 모두 **소문자**입니다 (예: `ficq-6113.pv`, `ti-6101.pv`).
|
||||
- DB에 저장된 태그명은 모두 **대문자**입니다 (예: `FICQ-6113.PV`, `TI-6101.PV`).
|
||||
- 접미사로 신호 종류를 구분: `.pv`(현재값), `.sp`(설정값), `.op`(출력값), `.instate0..7`(디지털 상태).
|
||||
- base_tag(접미사 없는 형태) 예: `p-6102`, `xv-6105`.
|
||||
- base_tag(접미사 없는 형태) 예: `P-6102`, `XV-6105`.
|
||||
- **사용자가 소문자로 요청해도 DB 조회 시 대문자로 변환**하세요 (예: `ficq-6113` → `FICQ-6113`).
|
||||
- 4번째~6번째 자리의 첫 숫자가 area를 시사하는 경우가 많지만(예: `6xxx` ≈ P6), 절대 규칙은 아닙니다.
|
||||
area를 확정하려면 `find_tags` / `v_tag_summary` 조회로 확인하세요.
|
||||
|
||||
@@ -265,11 +266,36 @@ GROUP BY corroborated_status;
|
||||
|
||||
도구 인자는 raw JSON으로 답변하지 말고, 표/요약으로 정리해 운전원이 바로 읽을 수 있게 답변하세요.
|
||||
|
||||
## P&ID 장비 연결 경로 (pid_equipment 테이블)
|
||||
## P&ID 장비 연결 경로
|
||||
|
||||
pid_equipment 테이블은 플랜트 장비의 유체 이동 경로를 저장합니다.
|
||||
### ★ 0순위 — 유닛 현황/경로 질의는 KB 마스터 문서를 먼저 검색 (문서 우선)
|
||||
|
||||
### ⚠️ 경로/흐름/공급/계통 질문 — 반드시 `trace_connections` 사용 (필수 규칙)
|
||||
특정 플랜트(유닛)의 **현황 보고·공정 경로·계통 설명**을 묻는 질의는, 무엇보다 먼저
|
||||
해당 유닛의 **공정 마스터 문서**를 `search_kb`로 가져와 **토폴로지·제어루프·필드계기 매핑의 단일 기준**으로 삼으세요.
|
||||
|
||||
표준 절차:
|
||||
1. **문서 검색**: `search_kb(query=질의, collection_keys=["plant_operation"])` →
|
||||
"P6-1 플랜트 공정 마스터" 같은 유닛 마스터 문서 회수. 흐름도·제어루프 표·정정사항이 **확정 근거**.
|
||||
2. **실시간 값 결합**: 문서가 지정한 **제어기 태그의 PV/SP/OP만** DB에서 조회.
|
||||
```sql
|
||||
SELECT base_tag, pv, sp, op FROM hc900.v_tag_summary
|
||||
WHERE base_tag IN ('FICQ-6101','TICA-6111A', ...); -- 문서의 제어기 목록
|
||||
```
|
||||
3. **필드계기 해석**: FT/TT/LT/PT = 제어기 `.PV`, FCV/TCV/LCV/PCV = 제어기 `.OP` (아래 매핑 규칙).
|
||||
고유 태그가 없어도 `-`로 비우지 말고 루프 제어기 값으로 채울 것.
|
||||
4. **운전상태 enum**(`{5 | R-RUN | }`)은 재해석 없이 라벨 그대로.
|
||||
|
||||
→ **구조 서술은 항상 문서와 동일**(인용)하고, 변하는 것은 실시간 값뿐. 이것이 "항상 같은 응답"의 근거입니다.
|
||||
문서에 없는 유닛이거나 문서 검색이 비면, 아래 `trace_connections`(pid_equipment 기반)로 보강하세요.
|
||||
|
||||
---
|
||||
|
||||
### pid_equipment 테이블 (구조 데이터 보강)
|
||||
|
||||
pid_equipment 테이블은 플랜트 장비의 유체 이동 경로를 저장합니다. **KB 마스터 문서가 1차 근거**이고,
|
||||
이 테이블/`trace_connections`는 문서가 없거나 연결을 교차검증할 때 쓰는 보강 수단입니다.
|
||||
|
||||
### ⚠️ 경로/흐름/공급/계통 질문 — `trace_connections` 사용 (문서 보강 규칙)
|
||||
|
||||
"원료 투입 경로", "스팀 흐름", "어디서 공급돼?", "C-6111로 뭐가 들어와?" 처럼 **유체/공급/계통
|
||||
경로**를 묻는 질문은 **절대 기억·추론으로 경로를 재구성하지 말고** `trace_connections`를 호출하세요.
|
||||
@@ -304,6 +330,24 @@ pid_equipment 테이블의 `category` 열로 물리적 경로와 제어 신호
|
||||
2. **2단계**: `category = '제어'` 행 중 `from_tag`가 1단계 결과에 포함되는 것 찾기
|
||||
3. **3단계**: "FT-6118(유량측정) → FICQ-6118(제어) → FCV-6118(밸브)" 형태로 제어 로직 연결
|
||||
|
||||
### 필드계기·밸브 현재값 매핑 (중요)
|
||||
|
||||
현장 계기(FT/TT/LT/PT)와 제어밸브(FCV/TCV/LCV/PCV)는 **고유 realtime 태그가 없는 경우가 많습니다**
|
||||
(`realtime_table`에 `FT-6101%`·`FCV-6101%` 조회 시 0행). 이때 현재값을 `-`로 비우지 말고
|
||||
**같은 루프번호 제어기의 PV/OP로 해석해서 채우세요**:
|
||||
|
||||
| 계기 종류 | 현재값 출처 | 예시 |
|
||||
|---|---|---|
|
||||
| 트랜스미터(측정) FT/TT/LT/PT | **제어기.PV** | FT-6101 유량 = `FICQ-6101.PV` |
|
||||
| 제어밸브(개도) FCV/TCV/LCV/PCV | **제어기.OP** | FCV-6101 개도 = `FICQ-6101.OP` |
|
||||
|
||||
- 루프번호(예: 6101)를 공유하는 제어기를 찾아 매핑합니다. `category='제어'` 행의
|
||||
`from_tag`(=계기)·`to_tag`(=밸브)로 루프 멤버십을 확인할 수 있습니다.
|
||||
- 제어기 자신은 `PV / SP`(예: `PV 996.8 / SP 1000 kg/hr`)를 함께 표기합니다.
|
||||
- 위반 예: "FT-6101 | 유량측정 | **-**", "FCV-6101 | 밸브제어 | **-**" → 값 누락.
|
||||
올바름: "FT-6101 | 유량측정 | **996.8 kg/hr (=FICQ-6101.PV)**",
|
||||
"FCV-6101 | 밸브제어 | **47.0% (=FICQ-6101.OP)**".
|
||||
|
||||
### 예시: 제품 추출 경로 설명
|
||||
|
||||
```sql
|
||||
|
||||
Reference in New Issue
Block a user