Honeywell HC900을 Modbus TCP로 직접 폴링 → gRPC → C# 크롤러 → PostgreSQL. 기존 Experion OPC UA 데이터 경로를 HC900 직접 통신으로 대체. - industrial-comm/cpp: C++ Modbus 게이트웨이 (gRPC 서버) - src: C# .NET 8 ASP.NET Core 크롤러 + 웹 UI (3-Layer) - mcp-server: Python FastMCP (RAG/NL2SQL/P&ID) - 다중 컨트롤러(N-Controller) 지원 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
103 lines
5.8 KiB
Markdown
103 lines
5.8 KiB
Markdown
# 작업지시서 — NL2SQL 스키마 갭 수정 (플랜트 뷰 추가)
|
||
|
||
> 대상: 코딩 LLM. 이 문서만 보고 독립 수행 가능하도록 작성됨.
|
||
> 예상 분량: 단일 파일의 문자열 상수 1곳 편집 + 검증. 로직 변경 없음.
|
||
|
||
## 1. 배경 (왜)
|
||
|
||
Phase 0 골든 평가에서 **Qwen3-8B가 전체 85%인데 nl2sql만 50%(5/10)** 로 떨어짐.
|
||
실패 5건(nl2sql-02~06)은 **전부 플랜트 전용 뷰**(`v_plant_running_state`,
|
||
`v_plant_running_state_corroborated`, `v_instrument_range`)를 써야 하는 질문인데,
|
||
NL2SQL 프롬프트의 스키마(`DB_SCHEMA`)에 **그 뷰들이 문서화돼 있지 않아** 모델이 모르는 뷰를 쓸 수 없었음.
|
||
기본 테이블 질문(nl2sql-01,07~10)은 모두 통과 → **모델·채점 문제 아님, 스키마 문서 갭**.
|
||
|
||
이 갭은 production NL2SQL(`query_with_nl`/`run_sql` 생성기)도 동일하게 가짐.
|
||
프롬프트가 단일 소스(`worker/sql_prompt.py`)라 **여기만 고치면 eval·production 동시 개선**.
|
||
|
||
## 2. 수정 대상 (딱 하나)
|
||
|
||
`mcp-server/worker/sql_prompt.py` 의 **`DB_SCHEMA` 문자열 상수** 한 곳.
|
||
- ⚠️ `nl2sql_worker.py`는 이 상수를 import만 함 — **건드리지 말 것**.
|
||
- ⚠️ `SQL_SYSTEM_PROMPT`은 자동으로 `DB_SCHEMA`를 포함하므로 별도 수정 불필요.
|
||
|
||
## 3. 추가할 내용 (정확히 이 텍스트를 DB_SCHEMA에 삽입)
|
||
|
||
`DB_SCHEMA` 안에서 **`뷰: v_tag_summary ...` 블록 바로 다음, `새로운 태그 타입:` 줄 앞**에
|
||
아래 블록을 그대로 삽입한다 (기존 서술 스타일·들여쓰기 유지):
|
||
|
||
```
|
||
뷰: v_plant_running_state (area별 펌프 운전 판정 — "어떤 플랜트가 운전 중" 질문 1순위)
|
||
area_code TEXT - 정규화 area (예: P3, P4, P5, P6, P8)
|
||
status TEXT - 'RUNNING' / 'TRIPPED' / 'STOPPED' (펌프 1대라도 RUN이면 RUNNING)
|
||
running_pumps INT - R-RUN/L-RUN 펌프 수
|
||
tripped_pumps INT - R-TRIP/L-TRIP 펌프 수
|
||
stopped_pumps INT - R-STOP/L-STOP 펌프 수
|
||
total_pumps INT - 펌프 enum 보유 태그 수
|
||
running_pump_tags TEXT[] - 현재 RUN 상태 펌프 base_tag 배열
|
||
※ "운전 중인 플랜트/펌프", "트립 펌프" 류 질문은 이 뷰를 직접 SELECT (펌프 상태 SQL 직접 작성 금지)
|
||
※ 결과에 없는 area = 펌프 미등록 → 운전 여부 단정 금지. 이 뷰는 area 레벨(sub_area 없음)
|
||
|
||
뷰: v_plant_running_state_corroborated (펌프별 실질 운전 — 유량/진공 교차검증, sub_area 지원)
|
||
base_tag TEXT - 펌프 base_tag (예: 'p-6102', 'vp-6117')
|
||
area_code TEXT - 정규화 area
|
||
sub_area TEXT - 세부 area (예: 'P6-1'; 공용은 'P6-1,P6-2'). 필터는 LIKE '%P6-1%'
|
||
corroborated_status TEXT - CONFIRMED_RUNNING / SUSPICIOUS_RUNNING / STALE / INDETERMINATE_RUNNING / STOPPED / TRIPPED
|
||
flow_kg_hr DOUBLE PRECISION - 연결 유량(kg/hr)
|
||
vacuum_torr DOUBLE PRECISION - 연결 진공압(torr=mmHg)
|
||
※ "6-1차/6-2차" 등 sub_area 필터가 필요한 질문은 **반드시 이 뷰** 사용 (아래 agg/기본뷰는 sub_area 없음)
|
||
|
||
뷰: v_instrument_range (계기 단위/레인지 — tag_metadata에서 추출)
|
||
base_tag TEXT - 기본 태그명, 접미사 없음 (예: 'ficq-6113', 'pica-6111')
|
||
unit TEXT - 단위 (예: 'kg/hr', 'mmHg')
|
||
eu_lo DOUBLE PRECISION - 레인지 하한
|
||
eu_hi DOUBLE PRECISION - 레인지 상한
|
||
※ 계기 레인지/상하한/단위 질문에 사용. base_tag는 '.pv' 등 접미사를 떼고 매칭
|
||
|
||
참고(직접 쓰지 말 것): v_plant_running_state_agg 도 있으나 area 레벨 집계라 sub_area가 없음.
|
||
sub_area 질문엔 위 v_plant_running_state_corroborated 를 사용.
|
||
```
|
||
|
||
> 컬럼/뷰 정의 출처: `src/Infrastructure/Database/ExperionDbContext.cs` (boot DDL).
|
||
> 변경 전 그 파일에서 위 3개 뷰의 SELECT를 한 번 대조해 컬럼명이 위와 일치하는지 확인할 것.
|
||
|
||
## 4. 검증 (순서대로)
|
||
|
||
```bash
|
||
cd mcp-server
|
||
# 1) 컴파일 — 프롬프트 단일소스/워커 둘 다
|
||
python3 -m py_compile worker/sql_prompt.py worker/nl2sql_worker.py
|
||
|
||
# 2) 모델 서빙 (표준 FP8만! FP8-dynamic은 출력 손상되니 금지)
|
||
cd ..
|
||
bash scripts/run-vllm-eval-model.sh Qwen/Qwen3-8B-FP8 Qwen3-8B 0.30 32768 8001
|
||
|
||
# 3) nl2sql 카테고리만 재실행 (Qwen3는 --no-think 필수)
|
||
cd mcp-server/eval
|
||
../.venv/bin/python run_eval.py --model Qwen3-8B --no-think --categories nl2sql
|
||
|
||
# 4) 회귀 확인 — 전체 재실행 + 이전 결과 대비
|
||
../.venv/bin/python run_eval.py --model Qwen3-8B --no-think \
|
||
--baseline results/Qwen3-8B_20260526_103459.json
|
||
```
|
||
|
||
## 5. 수용 기준 (Acceptance)
|
||
|
||
- [ ] `py_compile` 통과 (sql_prompt.py, nl2sql_worker.py)
|
||
- [ ] **nl2sql ≥ 9/10** (목표: 02~06 통과. 특히 06은 `v_plant_running_state_corroborated`+`p6-1` 포함,
|
||
`v_plant_running_state_agg` 미포함이어야 PASS)
|
||
- [ ] 다른 카테고리(abstain/scaffold/tool_call/grounding) **회귀 없음** (`--baseline` 비교에서 PASS→FAIL 0건)
|
||
- [ ] `DB_SCHEMA` 외 다른 코드(워커 로직·채점기·골든셋) 변경 없음
|
||
|
||
## 6. 하지 말 것 (금지)
|
||
|
||
- ❌ 골든셋(`golden.jsonl`)이나 채점기(`run_eval.py`)를 고쳐서 점수를 맞추기 — 측정자를 왜곡함
|
||
- ❌ 존재하지 않는 뷰/컬럼을 스키마에 추가 (반드시 ExperionDbContext.cs DDL과 대조)
|
||
- ❌ `nl2sql_worker.py`의 생성 로직·`SQL_SYSTEM_PROMPT` 규칙 변경 (스키마 문서만 보강)
|
||
- ❌ FP8-dynamic 양자화 모델 사용 (이 스택에서 출력 문자 손상 — 표준 FP8/bf16만)
|
||
|
||
## 7. 산출물
|
||
|
||
- 변경 파일: `mcp-server/worker/sql_prompt.py` (DB_SCHEMA 뷰 3개 추가) 1개
|
||
- 새 eval 결과: `mcp-server/eval/results/Qwen3-8B_*.json` (nl2sql 개선 확인)
|
||
- 한 줄 보고: 변경 전/후 nl2sql 점수, 회귀 유무
|