From 87ab8adfe09f31bb7ebb9b1e58a93a8d9f91afa0 Mon Sep 17 00:00:00 2001 From: windpacer Date: Sun, 24 May 2026 06:31:58 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20=EC=B8=A1=EB=A5=98=EC=B6=94=EC=B6=9C=20?= =?UTF-8?q?=EC=9E=90=EB=8F=99=EC=9A=B4=EC=A0=84=20=ED=94=8C=EB=9E=9C=20?= =?UTF-8?q?=EB=AC=B8=EC=84=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit C-6111 측류추출탑 자동운전 관련 플랜·관계식·운전 주의점 문서. - 측류추출-자동운전-플랜-byOpus.md / -컨셉회의.md(.docx) - 측류추출-관계식.md, PGMEA_측류추출운전방식_주의점.md - 측류추출-시간지연-적용방식.md(박스 정렬 수정) Co-Authored-By: Claude Opus 4.7 --- PGMEA_측류추출운전방식_주의점.md | 75 + 측류추출-관계식.md | 100 + 측류추출-시간지연-적용방식.md | 4 +- 측류추출-자동운전-플랜-byOpus.md | 251 +++ 측류추출-자동운전-플랜-컨셉회의.docx | Bin 0 -> 115820 bytes 측류추출-자동운전-플랜-컨셉회의.md | 2774 ++++++++++++++++++++++++++ 6 files changed, 3202 insertions(+), 2 deletions(-) create mode 100644 PGMEA_측류추출운전방식_주의점.md create mode 100644 측류추출-관계식.md create mode 100644 측류추출-자동운전-플랜-byOpus.md create mode 100644 측류추출-자동운전-플랜-컨셉회의.docx create mode 100644 측류추출-자동운전-플랜-컨셉회의.md diff --git a/PGMEA_측류추출운전방식_주의점.md b/PGMEA_측류추출운전방식_주의점.md new file mode 100644 index 0000000..81a11f8 --- /dev/null +++ b/PGMEA_측류추출운전방식_주의점.md @@ -0,0 +1,75 @@ +# 반도체 신너(PGMEA) 증류탑 측류 추출(Side-stream) 운전 방식 및 주의점 + +본 문서는 반도체 공정용 초고순도 PGMEA 정제 과정에서 사용되는 '측류 추출 방식(Side-stream Draw)'의 원리, 2기 직렬 탑 대비 단점, 그리고 정밀 운전을 위한 최우선 관리 항목에 대해 정리한 엔지니어링 가이드입니다. + +--- + +## 1. 측류 추출 운전 방식의 개요 및 목적 + +단일 증류탑에서 탑 상부(Top) 환류 라인 일부와 탑 하부(Bottom) 리보일러 유량 일부를 제거(Purge/Blowdown)하고, 탑 중간(Middle)에서 제품을 추출하는 이유는 **하나의 증류탑 내에서 PGMEA보다 끓는점이 낮은 물질(경비물)과 높은 물질(중비물)을 동시에 완벽히 분리**하기 위함입니다. + +``` + [ 탑 상부 (Top) ] + ---> 경비물 제거 (수분, 메탄올, PGME 등) + | (리플럭스 라인 일부 Purge) + | + |===| + | | + Feed | | ---> [ 탑 중간 (Middle) ] + ------> | | 초고순도 PGMEA 제품 측류 추출 (Side-stream Draw) + | | + |===| + | + |---> [ 탑 하부 (Bottom) ] + 중비물 제거 (DPGMEA, 금속 불순물, 중합물 등) + (열교환 유량 일부 Blowdown) +``` + +* **탑 상부(Top) 리플럭스일부 제거:** 수분, 메탄올, PGME 등 끓는점이 낮은 가벼운 불순물을 계 외로 배출하여 탑 내 농축 및 제품단으로의 하강을 차단합니다. +* **탑 하부(Bottom) 유량 일부 제거:** DPGMEA, 고분자 중합물, 금속 성분 등 끓는점이 높은 무거운 불순물을 배출하여 리보일러 파울링(Fouling)을 방지하고 기류를 통한 제품단 오염을 방지합니다. +* **탑 중간(Middle) 제품 추출:** 가벼운 물질과 무거운 물질이 모두 최소화된 탑 중간의 '최고 순도 구간(Sweet Spot)'에서 측류로 제품을 뽑아내어 반도체급 스펙을 만족시킵니다. +* **경제적 이점:** 2개의 증류탑을 직렬로 연결하는 대신 1개의 증류탑만 사용하여 설비 투자비(CAPEX) 및 에너지 비용(OPEX)을 극적으로 절감할 수 있습니다. + +--- + +## 2. 2개 탑 직렬 연결 방식 대비 단점 + +측류 추출 방식은 경제성이 우수한 반면, 기술적·운전 측면에서 다음과 같은 명확한 단점과 한계를 가집니다. + +### ① 운전 및 제어의 극악한 난이도 (Process Coupling) +* **직렬 방식:** 1번 탑(경비물 제거)과 2번 탑(중비물 제거)의 제어 루프가 독립적입니다. +* **측류 추출 방식:** 모든 운전 변수가 하나로 복잡하게 얽혀 있습니다. 예를 들어, 상부 환류량을 미세하게 조정하더라도 탑 전체의 온도 및 조성 프로파일이 흔들려 중간 제품의 순도가 동시에 출렁이게 되므로 고도의 고급 공정 제어(APC)가 요구됩니다. + +### ② 원료 조성 및 공급 조건 변화에 대한 취약성 +* 증류탑 내부에서 순도가 가장 높은 '최적의 추출 지점'은 고정되어 있지 않고, 유입되는 원료의 불순물 농도 및 유량에 따라 위아래로 계속 이동합니다. +* 실제 운전 중에는 물리적인 추출단 배관 위치를 바꿀 수 없으므로, 피드(Feed) 조건이 조금만 흔들려도 경비물이나 중비물이 제품단으로 쉽게 유입됩니다. + +### ③ 초고순도(Electronic Grade) 달성의 구조적 한계 +* 탑 내부의 격렬한 기-액 접촉 과정에서 발생하는 미세한 액적 비산(Entrainment)이나 급격한 증기 흐름으로 인해, 경비물이나 중비물이 제품 측류에 미량 혼입될 위험이 늘 존재합니다. +* ppb(parts per billion) 단위의 극단적인 불순물 제어가 필요한 반도체 최고 등급 품질 관리에서는 안정성 면에서 직렬 방식보다 불리할 수 있습니다. + +### ④ 운전 유연성(Turndown Ratio) 저하 +* 시장 수요 감소 등으로 인해 공장 생산량을 낮추어 저부하(Low Load) 운전을 할 때, 탑 내부의 유체역학적 균형(기-액 밸런스)이 쉽게 깨집니다. +* 기류 유속이 떨어지면 상부 불순물이 하강하고, 액체 흐름이 약해지면 하부 불순물이 축적되어 생산량을 줄였을 때 오히려 순도가 저하되는 역설적인 상황이 발생할 수 있습니다. + +--- + +## 3. 측류 추출 운전 시 최우선 제어 관리 항목 (우선순위) + +단일 측류 추출탑의 운전 성패는 **"탑 내부의 온도 및 조성 프로파일을 설정된 제어 위치에 완벽하게 고정하는 것"**에 달려 있습니다. + +### 1순위 | 감도 트레이(Sensitive Tray) 온도의 정밀 제어 +* **개념:** 외부 외란에 의해 탑 내부 조성 분포가 흔들리는 것을 막기 위해, 온도가 가장 민감하게 변하는 특정 트레이(Tray)를 지정합니다. +* **조치:** 감도 트레이의 온도를 소수점 단위로 실시간 감시하고, 이 온도와 상부 환류량(Reflux) 또는 리보일러 열량을 연동(Cascaded Control)시켜 탑 전체의 온도 경계선이 위아래로 출렁이지 않도록 묶어두어야 합니다. + +### 2순위 | 측류 추출량(Draw Rate)과 내부 물질 수지의 밸런스 +* **개념:** 중간에서 제품을 지나치게 많이 뽑아내면(Over-draw), 제품단 아래쪽으로 내려가야 할 액체 환류량이 부족해져 상부의 경비물이 제품단으로 빨려 내려오게 됩니다. +* **조치:** 측류 추출량은 독립 제어하기보다 피드(Feed) 유량 및 상부 환류량과 일정 비율을 유지하도록 비율 제어(Ratio Control)를 적용해야 합니다. + +### 3순위 | 피드(Feed) 조건의 외란 원천 차단 +* **개념:** 유입되는 원료의 온도, 유량, 조성(수분 등)이 흔들리면 탑 내부 밸런스가 즉시 붕괴됩니다. +* **조치:** 증류탑 전단에 피드 예열기(Preheater)를 설치하여 입조 온도를 항시 일정하게 유지하고, 원료 탱크 내 조성을 균일화하는 완충(Buffering) 시스템을 철저히 관리해야 합니다. + +### 4순위 | 물리적 비산(Entrainment) 및 플러딩(Flooding) 방지 +* **개념:** 탑 내부의 증기 유속이 임계치를 넘으면 하부의 무거운 불순물(금속, 고분자 중합물)이 기류를 타고 튀어 올라와 제품을 오염시킵니다. +* **조치:** 제품 추출단 하부에 데미스터(Demister) 등 물리적 차단 장치를 점검하고, 탑 내부 차압(Delta P)을 모니터링하여 상한선을 엄격히 통제해야 합니다. diff --git a/측류추출-관계식.md b/측류추출-관계식.md new file mode 100644 index 0000000..63f7575 --- /dev/null +++ b/측류추출-관계식.md @@ -0,0 +1,100 @@ +# 반도체 신너(PGMEA) 측류 추출 운전 - 전방먹임 비례 제어(Feedforward Ratio Control) 관계식 + +본 문서는 실제 석유화학 및 반도체 소재 공장의 DCS(분산제어시스템)나 APC(고급공정제어)에서 사용하는 '전방먹임 비례 제어(Feedforward Ratio Control)' 모델의 핵심 공식을 물질수지(Material Balance)와 열수지(Energy Balance) 관점에서 정리한 자료입니다. + +--- + +## 0. 기호 정의 (Variables) + +관계식의 명확성을 위해 다음과 같이 변수를 정의합니다. (단위: kg/h 또는 ton/h) + +* F : 원료 투입량 (Feed) +* D : 탑 상부 제거량 (Distillate / Light Purge) +* B : 탑 하부 제거량 (Bottom / Heavy Blowdown) +* P : 탑 중간 제품 추출량 (Side Product) +* R : 탑 상부 환류량 (Reflux) +* S : 리보일러 스팀 공급량 (Steam) + +--- + +## 1. 총 물질수지 관계식 (Total Material Balance) + +증류탑으로 유입되는 총 질량과 유출되는 총 질량은 같아야 한다는 기본 법칙입니다. + +F = D + P + B + +이를 원료 투입량(F) 기준으로 제어하기 위해 각각의 **추출 비율 계수(K)**를 도입하여 DCS 제어식을 도출합니다. + +* K_D : 원료 대비 상부 제거 비율 (D/F) +* K_P : 원료 대비 제품 수율 (P/F) +* K_B : 원료 대비 하부 제거 비율 (B/F) + +### [DCS 제어 설정식] + +D = K_D × F +P = K_P × F +B = K_B × F + +> 💡 **추출 비율 계수(K) 산정 팁:** +> 원료(Feed) 내의 불순물 분석 데이터에 따라 결정됩니다. 예를 들어 원료 내 경비물(수분 등)이 1%, 중비물이 1%이고 목표 PGMEA 회수율이 98%라면, K_D = 0.01, K_B = 0.01, K_P = 0.98로 초기 세팅 후 품질을 보며 미세 조정합니다. (단, K_D + K_P + K_B = 1을 만족해야 합니다.) + +--- + +## 2. 환류량(Reflux) 관계식 + +환류량(R)은 상부 제거량(D)과 연동하며, 기-액 평형 조건을 유지하기 위한 **설계 환류비(R_f = R/D)**를 이용합니다. + +R = R_f × D + +위의 물질수지 제어식(D = K_D × F)을 대입하여, 최종적으로 원료 투입량(F)에 대한 관계식으로 풀면 다음과 같습니다. + +### [DCS 제어 설정식] + +R = R_f × K_D × F + +* 원료 투입량이 변하면 상부로 나가는 가스/액체 유량도 변하므로, 이에 비례하여 환류량(R)도 자동으로 조절되도록 로직을 구성합니다. + +--- + +## 3. 스팀량(Steam) 관계식 + +스팀량(S)은 탑 내부에서 끓어 올라가야 하는 **총 증기량(V, Vapor Load)**과 직결됩니다. +PGMEA를 액체(Liquid) 상태로 측류 추출한다고 가정할 때, 탑 상부로 올라가는 대략적인 필요 증기량은 다음과 같습니다. + +V ≈ R + D + +리보일러 스팀 공급량(S)은 이 증기량(V)을 만드는 데 필요한 잠열을 공급해야 하므로, 스팀-증기 비례 상수(α)를 적용합니다. + +S = α × V = α × (R + D) + +이 식에 앞서 구한 R과 D의 제어식을 대입하면, 최종적으로 **원료 투입량(F) 기준의 스팀량 공식**이 완성됩니다. + +S = α × (R_f × K_D × F + K_D × F) = α × K_D × (R_f + 1) × F + +상수들을 하나로 묶어 **K_S (스팀/피드 비례 계수)**로 단순화하면 DCS 식은 매우 간결해집니다. + +### [DCS 제어 설정식] + +S = K_S × F + +--- + +## 4. DCS 실제 적용을 위한 최종 로직 요약 + +실제 공장 제어실(DCS)에 알고리즘을 구현할 때는 원료 유량 계측기(FT)의 값을 실시간으로 받아 각 제어 밸브의 유량 설정치(SV)를 아래와 같이 자동 계산(Feedforward Ratio)하도록 연동합니다. + +1. **상부 Purge 밸브 설정치 (Distillate SV):** D_SV = K_D × F +2. **중간 제품 밸브 설정치 (Side Product SV):** P_SV = K_P × F +3. **하부 Blowdown 밸브 설정치 (Bottom SV):** B_SV = K_B × F +4. **상부 환류 밸브 설정치 (Reflux SV):** R_SV = R_f × D +5. **리보일러 스팀 밸브 설정치 (Steam SV):** S_SV = K_S × F + f(ΔP) + Bias + +--- + +## ⚠️ 현업 운전 시 필독 주의점 (Bias의 필요성) + +이론적인 비례 관계식은 위와 같으나, 실제 현장에서는 **탑 자체의 열손실(Heat Loss), 외기 온도 변화, 계측기 오차, 원료 공급 온도의 미세한 흔들림**이 발생합니다. + +따라서 DCS 로직을 설계할 때는 완전 비례식만 적용하기보다, 운전원이 공정 상태를 보며 미세 조정할 수 있도록 **보정값(Bias)** 튜닝 탭을 반드시 확보해야 합니다. + +특히 스팀 제어의 경우, 앞서 언급한 **탑 내부 차압[f(ΔP)]에 따른 감쇄(Override) 제어 알고리즘**을 상기 스팀 설정식에 더하여(Cascade/Override 구조) 안전성을 이중으로 확보해야 합니다. diff --git a/측류추출-시간지연-적용방식.md b/측류추출-시간지연-적용방식.md index 4b596c6..b633139 100644 --- a/측류추출-시간지연-적용방식.md +++ b/측류추출-시간지연-적용방식.md @@ -153,7 +153,7 @@ DCS 로직을 수정하실 수 있다면 **[1번 대책: 5분짜리 시상수를 │ ▼ ┌─────────────────────┐ -│ Filter Block (300초) │ +│ Filter Block (300초)│ └─────────┬───────────┘ │ ▼ @@ -161,7 +161,7 @@ DCS 로직을 수정하실 수 있다면 **[1번 대책: 5분짜리 시상수를 │ ▼ ┌─────────────────────┐ -│ 각종 밸브 연동 공식 │ +│ 각종 밸브 연동 공식 │ └─────────────────────┘ ``` diff --git a/측류추출-자동운전-플랜-byOpus.md b/측류추출-자동운전-플랜-byOpus.md new file mode 100644 index 0000000..6a1c046 --- /dev/null +++ b/측류추출-자동운전-플랜-byOpus.md @@ -0,0 +1,251 @@ +# 측류 추출 증류탑(C-6111) — 로컬 LLM 기반 자동운전 플랜 + +> **목적**: `측류추출-시간지연-적용방식.md`의 시간지연/시차 보상 제어를 ExperionCrawler 시스템 위에서 +> 구현하되, **운전원이 단계적으로 신뢰를 쌓아 권한을 넘기는** 감독제어(Supervisory Control) 형태의 +> 자동운전을 설계한다. 결정론 엔진이 제어하고, 로컬 LLM(vLLM Qwen)은 그 위에서 진단·예외·인터페이스를 맡는다. +> +> 문서 성격: **설계/의사결정 기록**. 구현 착수 전 합의 완료본. 코드 미작성 상태. + +*작성일: 2026-05-22 / 갱신: 2026-05-22 (논의 합의 반영) / 대상: C-6111 PGMEA 진공 측류추출 증류탑 (P6 영역)* + +--- + +## 0. 핵심 원칙 + +**LLM을 빠른 제어 루프에 넣지 않는다.** 빠른 보상은 결정론 엔진(코드)이, LLM은 분/이벤트 단위 진단·튜닝·인터페이스만. + +| 문제 | 영향 | +|------|------| +| 비결정성 | 같은 입력에 다른 출력 → 밸브 제어에 치명적 | +| 지연(latency) | 토큰 생성 수 초 → Flooding 즉시 대응 불가 | +| 환각 | 잘못된 값 한 줄이 바로 밸브로 → 측류 순도 영역 파괴 | + +따름정리: **헌팅 검출·MAN 전환·OP 산출 등 안전·실시간 판단은 모두 결정론.** LLM은 그 트립을 *설명*하고 +*원인을 진단*할 뿐, 직접 트립시키거나 OP를 쓰지 않는다. + +--- + +## 1. 물리 결정론 vs LLM — 역할 경계 (이 플랜의 출발점) + +운영자가 **밸브 사이즈·배관 종류·컨트롤밸브 Cv 값/Cv 커브·플로우미터 유량범위** 등 물리 데이터를 +보유하면, 제어 수학의 상당 부분이 *데이터 피팅 없이 계산*된다. + +### 1.1 물리 데이터로 결정론화되는 것 (LLM 불필요) +| 물리 데이터 | 계산되는 모델 | +|------------|--------------| +| Cv 커브(설치특성) | OP(%) → 유량 관계, 밸브 게인 dQ/dOP | +| 배관 종류·구경·길이 | ΔP·마찰, 이송 데드타임 θ = 관내체적/유량 | +| 드럼/트레이 홀드업 체적 | 체류시간 τ = 체적/유량 (D-6113 환류드럼 등) | +| 플로우미터 레인지 | 스케일링·분해능·노이즈 플로어 | + +→ 자동운전의 **B(하부)·D/R(상부) 타이밍은 하이드롤릭 홀드업(=체적/유량)으로 직접 계산**된다. +밸브 게인도 Cv 커브 미분으로 나온다. **이 부분은 그냥 프로그램한다.** + +### 1.2 물리 데이터가 못 주는 것 +- **(가) 분리/조성 동특성** — P(측류)의 "15~20분" 지연은 배관 이송이 아니라 트레이 홀드업+기액평형(VLE)으로 + 새 조성이 자리잡는 시간. 상대휘발도·트레이 효율·VLE는 Cv 커브에 없음. → **B·D는 물리로 계산되지만 P는 별도 모델 필요.** +- **(나) 모델-플랜트 불일치(드리프트)** — Cv 커브는 신품 설계값. 밸브 stiction·마모, E-6103 파울링, 트레이 효율 저하로 시간에 따라 어긋남. +- **(다) 목적·맥락·예외** — 회수율 최대 vs 에너지 최소 vs 순도 사수, 등급변경, 기동/정지, 계기고장, 상류 외란. + +### 1.3 따라서 LLM이 실제로 하는 일 +> **LLM의 가치는 물리모델 품질에 반비례.** 물리를 잘 잡을수록 LLM은 제어 산수에서 빠지고 가장자리로 이동. + +| LLM 역할 | 구체 | 가치 | +|---------|------|------| +| ① 커미셔닝 보조 | 밸브 데이터시트·Cv 커브·배관 스펙 파싱 → 엔진 config/코드로 조립, 정합성 점검 | ★★ | +| ② 드리프트 진단((나)) | 물리예측 vs 실측 잔차는 수학, *"이 OP·ΔP에서 8% 미달 → 밸브 파울링/마모 의심"* 해석·재교정 트리거는 LLM | ★★ | +| ③ 소프트센서 보조((가)) | 측정 안 되는 조성을 온도(TI-6111B/C)로 추론, 분석기 결측 보간 | ★ | +| ④ 감독형 예외 처리((다)) | 엔진이 프로그램 안 된 상황(기동·등급변경·상류 업셋·계기고장) 판단·완화 | ★★★ | +| ⑤ 운전원 인터페이스 | 의도/경제목표 → SV·제약 번역, "왜 이렇게 도는지" 설명 | ★★★ | +| ⑥ 교차 데이터 융합 | 알람+이벤트+랩분석+정비이력+물리잔차 엮어 진단 (기존 MCP 도구) | ★★★ | +| ⑦ 헌팅 원인 진단 | 튜닝 vs stiction vs 외란 판별 → 4단계(OP 개입) 적용 여부 게이트 (§4.3) | ★★★ | + +--- + +## 2. 감독제어 아키텍처 — 운전원이 권한을 쥔다 + +핵심 설계 사상: **엔진은 PID 루프의 SP/OP 레지스터를 직접 덮어쓰지 않는다.** 별도 감독변수에 쓰고, +**운전원이 스위치로 채택**한다. 권한 손잡이는 항상 운전원에게 있다. SP 경로와 OP 경로가 대칭이다. + +| | SP 경로 (평상시) | OP 경로 (헌팅 시) | +|---|------------------|-------------------| +| 엔진이 쓰는 곳 | RSP 소스 포인트 (별도 변수) | `.op` (PID MAN 상태에서) | +| 운전원 스위치 | **LSP ↔ RSP** (Local ↔ Remote SP = AUTO↔CAS) | **PID MODE: AUTO ↔ MAN** | +| 빠른 규제 담당 | DCS PID (그대로 둠) | 엔진(소프트웨어 컨트롤러) | +| 폴백(엔진 사망) | 운전원이 LSP로 토글 | 데드맨 → MAN→AUTO (bumpless) | +| 적용 | 1~3단계 (신뢰 이양) | 4단계 (튜닝발 헌팅 한정) | + +### 2.1 SP 경로 — RSP(Remote Setpoint) +- 엔진은 **루프 SP를 절대 안 건드림.** 자기 감독소스 포인트에만 OPC write → 그 포인트가 PID의 RSP/X 입력에 control connection. +- 운전원의 **LSP/RSP 토글이 유일한 권한 손잡이.** RSP면 엔진 SP 추종, LSP면 운전원 수동 — 언제든 가역. +- **bumpless 요건(중요)**: OPC 외부 감독은 DCS의 back-calculation 핸드셰이크를 못 받음. + → 루프가 LSP(미선택)일 때 엔진이 **현재 실작동 SP를 읽어 자기 출력=현재 SP로 추종**시켜야 함. + 그래야 운전원이 RSP로 토글하는 순간 충격 없음. +- **공짜 안전망**: DCS RSP 한계(SPHILM/SPLOLM, RSP rate)가 엔진과 독립으로 한 겹 더. +- **장점**: 1~2단계(제안 표시)는 페이스플레이트가 RSP 후보값을 네이티브로 보여줌 → **별도 화면 개발 불필요.** + +### 2.2 OP 경로 — MAN + OP 쓰기 (튜닝발 헌팅 전용) +- 평상시 RSP로는 **튜닝발 헌팅이 안 잡힘**(PID가 루프에 그대로). 그래서 헌팅 루프에 한해 OP를 직접 잡는다. +- 방식: PID를 **MAN**으로 → 엔진이 `.op`에 직접 write. **MAN이라 적분이 멈춰 windup 없음, OP 쓰기는 본질적 bumpless.** + 기존 `ControlOp`(MD→MAN→OP쓰기) / `WriteTagAsync(.op)` 그대로 사용 → **신규 DCS 구성 불필요, 저MoC.** +- **운전원 회수**: MAN의 OP는 엔진이 쓴 마지막 값 → 운전원이 그 값에서 이어 조정, 또는 AUTO로 올림. +- **폴백(엔진 사망)**: 엔진 워치독 + **DCS 컨트롤러 로직이 stale(N초 갱신 없음) 감지 → MAN→AUTO 강제 복귀.** + PID가 bumpless output 설정이라 **현재 OP(=마지막 LLM_OP)에서 적분 임펄스 없이 규제 재개.** + - *정직한 단서*: 폴백은 "헌팅하던 그 PID"로 돌아감 → 안전(규제됨, SIS가 극단 차단)하나 **엔진 복구 전까지 헌팅 재개.** 위험 아님, 차선. + - 설정 확인: MAN 중 SP 추종/홀드 → 폴백 후 어떤 LSP로 규제할지 결정. +- **상위 옵션(임계 루프 한정)**: *순간 규제 공백도 불가*한 빠른 루프는 선택+back-calc(PID는 AUTO 추종 유지, 무충격 즉시 폴백)을 쓰되, 밸브 출력경로를 변형하므로 MoC가 더 엄격. 기본값은 위 MAN 방식. + +--- + +## 3. LLM-OP 모드의 제어법 — FF + 느린 PI (rate 제한) + +OP 경로로 개입한 동안 엔진이 매 순간 OP에 무엇을 쓰는가. **크루즈컨트롤과 동일 구조**: 미리 예측(FF) + 잔차 청소(PI). + +``` +F(헌팅) ─Lag필터→ F_clean ─물질수지→ 목표유량 ─Cv커브→ OP_ff ┐ + ├→ OP → rate제한 → 절대/변동폭 클램프 → 밸브 +설정값 − 실측PV ───────────────── 느린 PI ───────→ OP_pi ┘ +``` + +- **FF (피드포워드)**: 물리로 *미리* 정답 개도 계산. `개도% = Cv⁻¹( Q / √(ΔP/SG) )`. + 필터링된 F_clean로 목표유량(B/D/P)을 물질수지로 구하고 → Cv 커브로 OP 계산 → §5 시간상수로 부드럽게 이동. + **외란발 헌팅을 잡는 주역**(반응이 아니라 예측이라 밸브가 안 채인다). +- **PI (느린 피드백)**: Cv 커브는 신품값이라 마모·파울링·ΔP 부정확으로 살짝 빗나감. 잔차(SP−PV)를 + **느리게/약하게** 보정. 약한 이유: ①헌팅 재유발 방지 ②큰 일은 FF가 이미 함. +- **rate 제한**: OP 변화율 제한으로 밸브 부드럽게. +- **비채택: "고정+간헐 보정"** — 보정 사이 능동 규제 0 → 외란 시 PV 드리프트(피드백 상실). 사용 안 함. +- **연결**: FF = §5 결정론 보상 엔진 그대로 + 그 위에 작은 PI 트림 하나. + +--- + +## 4. 헌팅 검출 & 원인 진단 — 4단계의 게이트 + +### 4.1 검출 (결정론) +- 오실레이션 인덱스: 진폭·주기·지속성. 임계 초과(예: 진폭 > 범위의 X%, 주기 안정, N분 지속) 시 트립. +- **MAN 전환 트립은 결정론**(LLM 지연 불가). LLM은 트립을 설명만. + +### 4.2 원인 분류 (LLM + 데이터 융합) — §1.3-⑦ +| 원인 | 4단계(MAN+OP)로 잡히나 | 조치 | +|------|----------------------|------| +| 튜닝 과민 | ✅ 즉시 | MAN 전환 → FF+PI로 OP 핸드홀딩 | +| 상류 외란 | ✅ 잘 잡힘 | 동일(FF가 주역) | +| 루프 간섭 | ⚠️ 부분 | 시차 조절로 완화 | +| **밸브 stiction** | ❌ 악화 | **정비 플래그.** OP 핸드홀딩 금지(마모만 늘어남) | + +→ LLM이 OP-PV 위상·한계주기 파형·상류 신호·정비이력을 엮어 *"이건 stiction → 4단계 말고 정비"* vs +*"외란 → 4단계 유효"* 판정. **초기엔 LLM 진단 → 운전원 확인 권장.** + +--- + +## 5. 보상 제어 수식 (결정론, FF의 본체) + +원본 문서 §2·§4 기준. +- **1차 지연(Lag) 필터** (이산): `y[k] = y[k-1] + (Δt/τ) · (x[k] − y[k-1])` +- **데드타임**: 링버퍼로 N틱 지연 +- **헌팅 제거**: 원료 FT 신호 직후 Lag 필터 τ=**300초(3~5분)** (원본 §4.1) + +| MV | 제어 대상 | τ / 데드타임 | 근거 | 목적 | +|----|----------|-------------|------|------| +| B | 하부 제거량 | 1~2분 | 하이드롤릭 홀드업(물리 계산) | 탑 넘침(Flooding) 즉시 방지 | +| D/R | 상부 제거량/환류 | 5분 | D-6113 드럼 체류시간(물리 계산) | 압력/조성 안정화 | +| P | 측류 제품 추출 | 15~20분 | **분리/조성 동특성(§1.2-가, 별도 모델)** | 초고순도 PGMEA 품질 보호 | +| S | 리보일러 스팀 | 가장 빠름 | 압력 즉시 전달 | 하부 온도 직결 | + +추가(원본 §4.2/§4.3): PID 블록 **dead band 0.5~1.0%**, 원료탱크 **Surge Control**(P-Gain↓ I-Time↑). + +--- + +## 6. 안전 봉투 (Safety Envelope) + +엔진의 모든 쓰기는 아래를 강제 통과한다(다층 독립 방어): + +1. **엔진 가드**: rate 제한 · 절대 min/max · **현재 유량범위 대비 밸브 변동폭 제한** · 태그 화이트리스트 · 전 쓰기 감사로그 +2. **DCS 측 한계**: RSP 한계(SPHILM/SPLOLM), 출력 한계(OPHILM/OPLOLM) — 엔진과 독립 +3. **운전원 스위치**: LSP/RSP, AUTO/MAN — 언제든 즉시 회수 (최우선) +4. **데드맨/워치독**: 엔진 stale → SP경로는 운전원 LSP 회수, OP경로는 DCS 로직이 MAN→AUTO(bumpless) 폴백 +5. **ESD/IL/SIS 독립**: BPCS 루프의 MAN/AUTO·LSP/RSP와 무관하게 최종요소에 독립 동작 → 실험을 봉인된 안전 범위에 묶음 +6. **한 번에 한 루프**: 간섭 루프 동시 MAN 금지 +7. **양방향 bumpless**: 모든 전환에서 충격 없음(PID bumpless output + 엔진 추종) + +> ⚠️ **MoC/문화**: 자동 시스템이 SP/OP를 조작하는 것은 현장에서 APC로 간주 → 변경관리·운전원 수용 절차 필요(기술 외 항목). + +--- + +## 7. 단계별 신뢰 이양 로드맵 (운전원 비전) + +| 단계 | 내용 | 경로 | 권한 | +|------|------|------|------| +| **1. 제안 표시** | 엔진이 RSP 소스 포인트에 계산값 write → 운전원이 페이스플레이트에서 "제안 SP"를 봄(LSP 유지) | SP/RSP | 운전원 100% | +| **2. 관찰·신뢰 형성** | 제안값이 합리적인지 운전원이 일정 기간 관찰 | SP/RSP | 운전원 100% | +| **3. SP 주도권 이양** | 신뢰 시 운전원이 **RSP로 토글** → 엔진 SP 추종. 언제든 LSP 회수 | SP/RSP | 엔진(가역) | +| **4. 헌팅 자동 안정화** | 헌팅 임계 초과 + 원인=튜닝/외란 확인 시 PID MAN 전환 → FF+PI로 OP 핸드홀딩 → 안정 후 복귀 | OP/MAN | 엔진(데드맨 폴백) | + +**구현 선행조건(Phase 0)**: §6-1 엔진 가드 레이어 + 데드맨. *(현재 쓰기 경로에 가드 0건 — §10 참조.)* + +--- + +## 8. 태그/노드 매핑 (실측 — `find_tags`·`trace_connections`) + +원료 경로(trace_connections): +``` +P-6101(원료펌프) → FT-6101 → FICQ-6101 → FCV-6101 → E-6103(예열) → C-6111 원료 스프레이 분배기 +``` + +| # | 경로 | MV/제어 | 유량 | 온도 | 수위/압력 | τ | +|---|------|---------|------|------|----------|---| +| **F** | 원료 투입 | **FICQ-6101**→FCV-6101 | FT-6101 | (E-6103 예열) | — | 입력(Lag 300s) | +| **S** | 리보일러 스팀 | 스팀밸브 | **FI-6115** | TI-6111A(BOT), TICA-6111A | PI-6700(스팀압) | 가장 빠름 | +| **B** | 하부 제거 | 하부 발출 밸브 *(밸브태그 미확인)* | (미확인) | TI-6111A(BOT) | **LI-6111**(하부수위) | 1~2분 | +| **D/R** | 상부/환류 | **FICQ-6113**(PV29.9/SP36.4) | FI-6113 | TI-6111D(TOP) | **LI-6113**(D-6113 환류드럼), LICA-6113, PI-6111(진공), PICA-6111 | 5분 | +| **P** | 측류 제품 | **🔲 사용자 매핑 예정** | FI-6120(PGMEA) | TI-6111B/C(MID) | LI-6121/6122/6123(제품탱크) | 15~20분 | + +- OPC Node 형식: `ns=1;s=sinamserver:ficq-6101.sp` / `.op` / `.md`(MAN=0/AUTO=1). + ※ SP 경로 구현 시 write 타깃은 **루프 SP가 아니라 RSP 소스 포인트**로 바뀜(노드 ID만 교체, 쓰기 코드 동일). +- 현재 운전 흔적: FICQ-6113 PV 29.9 / SP 36.4 추종, 진공압 PICA-6111 30.4 → 가동 중 추정. + +### 8.1 미완료 매핑 (담당 구분) +- **P(측류 제품 추출) 경로 매핑 — 사용자 직접 진행 예정** (본 플랜 보류) +- B(하부) 발출 유량계·밸브 태그 — `find_tags`(6112/6114/6116번대) 또는 C-6111 `trace_connections downstream`로 보강 + +--- + +## 9. 현 시스템 재사용 자산 + +| 구분 | 자산 | +|------|------| +| 쓰기 | `ExperionOpcWriteClient.WriteTagAsync(.sp/.op)`, `SetModeAsync(MAN/AUTO)`, `ControlOp`(MD→MAN→OP→AUTO) / `POST /api/experion/{write,mode,control}` / UI "OPC UA Write" 탭 | +| 읽기 | `ExperionRealtimeService`(실시간 PV 구독, IHostedService), `query_pv_history`(MCP)/`ExperionHistoryController` | +| 백그라운드 | `IHostedService`/`AddHostedService` 패턴 기존 사용 → 신규 `AutoRunService : BackgroundService` 그대로 적용 | +| LLM 감독 | `query_pv_history`, `find_tags`, `trace_connections`, `active_alarms`, `query_events`, `summarize_events`, `generate_status_report`, ReAct 에이전트 모드 | + +--- + +## 10. 미해결/확인 필요 항목 + +- [ ] **P(측류 제품 추출) 경로 매핑** — *사용자 직접 진행* +- [ ] B(하부) 발출 유량계·밸브 태그 확정 +- [ ] **쓰기 경로 안전 가드(§6-1) 신규 구현** — 현재 `WriteTagAsync`에 클램프/rate/변동폭 0건 (Phase 0 선행) +- [ ] **DCS 구성**: RSP 소스 포인트 생성·연결, OP 데드맨(stale→MAN→AUTO) 로직, RSP 추종/홀드 설정 +- [ ] 헌팅 임계 정의(진폭/주기/지속) 및 stiction 자동판별 신뢰 수준 +- [ ] 각 MV의 hard min/max·변화율·밸브 변동폭 한계(공정 안전 범위) + Cv 커브·배관 물리 데이터 수집 형태 +- [ ] P(측류) 분리/조성 모델(§1.2-가) 깊이 결정: 고정 τ vs 간이 트레이모델 vs 경험모델 +- [ ] `ask_iiot_llm`(vLLM) 빈 응답 — vLLM 엔드포인트 상태 점검 +- [ ] Step Test 수행 가능 시점/조건 (가동 중 5~10% 스텝) +- [ ] APC 블록 내장 여부 vs 일반 PID 환경 / MoC 절차 + +--- + +## 부록 A. 참조 +- 원본 개념 문서: `측류추출-시간지연-적용방식.md` +- 쓰기 구현: `src/Infrastructure/OpcUa/ExperionOpcWriteClient.cs`, `src/Web/Controllers/ExperionControllers.cs`(ExperionWriteController) +- 실시간 읽기: `src/Infrastructure/OpcUa/ExperionRealtimeService.cs` +- UI: `src/Web/wwwroot/index.html` (#pane-write) +- MCP 도구: `mcp-server/server.py` (find_tags, trace_connections, query_pv_history, ask_iiot_llm 등) + +## 부록 B. 합의된 핵심 결정 (요약) +1. 감독제어 — 엔진은 별도 변수에만 쓰고 운전원이 스위치로 채택(권한은 운전원). +2. SP는 **RSP** 경로(LSP/RSP 토글), 외부 추종으로 bumpless. +3. OP는 **MAN+`.op` 쓰기** 경로(기존 ControlOp), 엔진 워치독 + **DCS 데드맨→MAN→AUTO bumpless** 폴백. +4. OP 제어법은 **물리 FF(Cv·배관) + 느린 PI + rate제한** (고정+간헐 보정 비채택). +5. PID 파라미터 재튜닝은 **필수 아님** — MAN에서 OP 대체로 헌팅 안정화 가능(stiction 제외). +6. LLM은 물리 결정론 위에서 ①커미셔닝 ②드리프트진단 ③소프트센서 ④예외처리 ⑤인터페이스 ⑥교차융합 ⑦헌팅원인진단. diff --git a/측류추출-자동운전-플랜-컨셉회의.docx b/측류추출-자동운전-플랜-컨셉회의.docx new file mode 100644 index 0000000000000000000000000000000000000000..39dacb5f5bee0e981f6b3ff8f1e790411ea922c7 GIT binary patch literal 115820 zcmY(KLy#!pvaQ>;ZQHiJ+qP}nwryLxZQHhOyYD_{@Zz0GRYcV+SN>U*E5DSN1_nU^ z004jh$dPZ+u2C#WNC5-@m;eI+K>qhsOW4lV*~HdaPuauX#7T$F-NyQFitL|F0ff-o zZ`4$JJ_0Xcc+|=RdkTA+1T2xdtY;35HTr8Ap!e4)t_YQR`7kiLgzSu0AH2;*-X8B3 zGA&_|YaN|zwIU+mGVh}8Lb@AM_G8fmLdjK$L)@idu==)aZ_HUXK!(HmK`uR{kXxaA z&A=4(cYs*(nmAP?{E-j{McxU}@VcUT_JS^Adu7FoG4exd^WzD5*Y7DmH==i8f6?6U zH99iY9IGs-jsTAI2>m-1u~7Zy#382!*J7?N#?Af`IQJ1~JA{QJn?5?XNj2sR zu*Qn$Cne1tB+HPaYdfo8viij{;9Rv|TkibJO;u|1E=`SCWgm-+APFqbS7Es9%f3KL z@+Lx^WUx%8uDBZS;Mc*|SIUw&62AAfaNXCXMOm9E75_2#P*xTG2E|UnxYTiGPWE4i z3t=Lk=lo!;bxsjEpDqzSUWx#LA+NW4xX%*<&<%_?n1I?>iLdU`W0%dqLL(WPR7$Py z6x?FO-UNeBuMg<5Dohc+{;$=t?PLClSE9mC6j@yW`TtSTgG^fB?Vox(KmY*H|L%H@ zCe}{$bpN^5Bu+~KGa~rk@`;X-mf5zbh!n5uik!(7^Yx`q-IUt;N|bK&bSsGHsH64c zo!%ZAnXY6NVXsk_S_i2aYAgp9toEz#QrTN-!LUsiZx+@<9YglJSJrlzTn2^1) znW_@-QSTrRYf(1c%nQ~EiRe+;NWhf`S0o`mK|52Zx%kj7+JV`L$+WOWmesT$S-VBP z@wYfj==%#?#M>h(Wyl#bqH`3(Nje}u2}_>N##Y9+XQOp|bjq7+Ro&B_1quIA(sd_! z0-Nqa8sac(<|&(RI}|^mB_W; zhG<)#xuR5@H7UUZw|yUr4`gOsMiYHe3Ro~u^|`>3S&TX|E8$$kLyfE~OQAD_Ic35ATVOYx>pMP-9vJ<6aW!Fsuf&J-6;HBFDC)tOaIRh7L1Ewl znFSOw6y4fXnf4;Dog5u@XI+7Hs$g2fVBk_Q3+AuOs|5lJAhxtzckG5r8b+6v4z_5W zNd5VpjoX;(k-u9eImpute6zO;;6~ke&B7pal3$rMFxPOX-`MX#FfPpCbSW3zgnzyU9vlBJTV6>3V8EW#i z6JA73hEw-=;Py^`sAruw-~@J>y-GXf?7io{Oaw%)TpQko?o#CcuI;2NF#L(E0{*Tu zukt9L=YUD7c>q=ijC?ryJjtm?P8P7hS?@q3@tK+D6K$BRuaY{Tt0v^F9U&)4 z#r-tI$EG%-yiq$n6<*cUk<*Gn&11zvbS2#n@ofh@wj&2kw&KN*7kAY>z<)Kz`bMC; zw_!Zpdw1c5zHkHM@NH{?#7nz|wEiBCp2Q1iv))Zh;hR?5CE*UsMpyB&{*#b4v?-`b?clr4W|9=ys-cQWkk{uABPYCkA2iDEb(U|_%@w9`P9t(o_?~Vz&eK>F}!Q56?l^(I7w{9j{a)yga!MU zN~4{g4%>eXsCS8*CXR#w9lSdkmT+c32-7P{+ryrxr-x_l=M4k84}b{6!xZ}oU@Q*mI4gW|Vj|DqhcJ*9^Ybw9G}E$V$Izk=8q z_!#+vDfG=eov;>hdl5z(rckA=|p*!)F<>f<98+--@O7{vbss{4YzHspD^=(u0Hq7Cd zGrG6NIX%at`0QtpszE3RuM-==c1zgMV<^{1jTSgYF^_oh)vlM?bn zVAiFLLjEV0sdOa9SPrA<@FU0K(06={T$D8lU5pAEUFqYj*q{4+60<{^5ByK1sgxLD z=cTJRIo#9|u7Ye?Oa`kqt&i{Y7Kmb@RoUr3)Kr zN2h0qL#sL^y3ZKlO-eA|hr}#@A$A77>*DxWG{LKXll(NTmtf%#__wUi84-LYnP$vp3Ttun8S(N>^U67CPjynmG5Vt`&C0evDq?pgw zAh)xuHu~58pODMnho269cZIe+O_&w{x^JqJL#vHmkj$Tj^(Q|zc3jTaI`FL>z0aSr z-B;=_eG)A6RaD#!cjd1OzfeEYz24n${atj#AGNkvJYK3FZ%&MESKG6Rc6uKTl4(itv-TiW;&n-`dL^Q zk%LpA0zrrU2Z8duoo*CZ7#{~)3Iy0-q5k+YXwW|0F8Av#0gl+(%00Dv3hyjFEO_n6 z02tUoYSGSc;5HN(@S*_sJ8c@gaJ|?Z;6#yu4wUFafLU0u!+;+F9s;ld^q_esbnrli z`2c$wJknKJnPC06S;;U785pnwAH5}0@Jj^f+@x48m0~LKfS|;~X1(`|!t2(8pQuF7 zAT@K>EQt(yZQO7_2Ra-i1$Dv>qQbPnQ$s&E%1q*HdWSwg3^rn%EwlC8s>B4SdrQUM ztVKa-02S+I0nH)x{w4gI^_0JsC+&&Dc>C;;kAbj8>b)d18Q?0KJ}w($ zN6*J3GFr)W~7*@pxC}c2R$*VH58G5kURm&o13z-!%XU_oLIrMU5u#^sk{_ugo zL2EOckWAjOirY+#YEYv6saI#Xbl@4a&(`t%7F}44{e9c)wY3OEFV$YiONq`J6qxLT zk)}lWeH5dM=t1ukVRE!OifvC4vokc69s5k2EU>O^9p~%rV?moY0mRm~o!Y8T$dex; zPJqw{@)8xFS4--06LXA!6EESA-Gu&3@)IcoV&Pb0I~0YZOLr8)!!v>kKD0z50lMns zBAi*O2mAAvHo%{V3tfMJ6aoC_A5|e9%_(2R%tA#>~cL zE6q*BX342dmYPYV#UF3$e5P$A*yG1V%OX@IeU{!(Wzu7bQUct~U^z*&UDJVg!prwZ zC3w5LXUhQbi zRu$nHS%N6XX0j#ousU9M;<<9K)ss1dk?)=kkZcvh)8|;rKq;q|&{?)F^<-8vT8b?! z(y1$Y>n<#*AV+}!zw~~*KwocFs$|Ae!p+(i$4WQ;ix9{0?S)#4iAA_Bh|9_?Va}@u zVkqb^1tS`FOij(1%4RKA_|2TOLLT|hwOp>>;Zx510^ z)@}9saNHYN^j0+fTX*0;_rr+!`kn4%D%B=xPS(E1QSCl9sf*X+;7QBczyO zUHaxR-qw9~`4Q4*|4xAs_(zvesayJ9+~}&J^8Py-(=1AD$pIqK#3{tmG%%&OU8E$N zDJMlgtnH~mg#}b_=CUX*-jr&RT_<)UDNZEMr7D=bdBzXa_(K>7ZH!pOGqNM;ID`v8 z)5I92@dvm=ActG{@~W2!0oe80)j=ZH+KlZ&gjJ@TU%_Hm3D2IC)2$_l9HFa#vj!ppDE@ ztAj8*Y06)_Vyk?E{8})UOk&a2y>HO-pLh$*E4FRaBD3exOi8wvka56Inh$q7 zDvwu+U9O(nk>@arX5FXT-h?UGE0#!V|HOJ7>8`(mw#s&Y{Ty^~&OV(M1$%p!xt)if z>td2cK@XGnF`Cis@;5H~zH7TA)N+sKU;B%KyL0IF_|=2`s)}NmFja23u#^OfQw})J?k=gt8uR%v9Y%;&#O*|V za9CYE>=_Vn-=yVr9Y*5k#RDjtBpu}yr-mcEOBXSt$X!^CC^cl` z0MveI*4EL{pQS&H@wUf}#ZnkO-e6<#QMK$iXLl}#nr8mYZUN%&$zcUGQ^fTmUNu`1 zj<;$LWRp$Cq@dP%)(nu2vD&_p$(#G@_*TuK5Nn~v==jmk;-UTAh#G~4rl|V{#vjm zxh*yNHJ6LawkKIes8X6feGvzs8cuS??l|fOs^?jisN;klo03OYAl8}O5C#FKoOF_u zpm#~6YpzZ2Z_qEFSN~8%`S#te7JHHzmE>gC;G{s2Wh;uB*%z@%W+2y*Maw9zbU_{x zni5060IB8D8{XrPA#X54{3?j4z8Ec3XSJ&>*lEhS)zE3kUo0+{n@*zQ@Cpy7DQEUx<9o2j}hk^hh;Z7MTSe!T4Tu#4yKt>b`zA$u@_|p`RKGWkbIE- zElWn96sL9Zhd&SD^%jN}i!F^*YuBb0vw>8-(+k1Qb|GIb=`{pf1DE!K+3p_5T0%@< zL((}&YSOAqD^O3w%9HiP1l3W&?`^h{0djM?#&9CyVzR%)vsuK%19gX_&84_nOh)4c z?`>kc=V5t$z3-d>7QkQOU^Y+REg9jNVu{-Wh^nQTH>m7^Uiyo7l+L7*=k;@LGIc#- zP<49Kn5+6UP5?1SGp7+tG<_iFi^q5VQ( zP7P7Z_@Sg;;V zy?(<#h*%gn;dOOS#PNe60&Vzz`6@5+Mb0Lem7k+d*uWG*TjPFLukZK zrZ@dm(`YZ095ZslNQ-k=)yX>zYy)ZRfiQSA zYX>@oPb&+ojyPX-(B~7Ru`@2#Xy~gl-`Vw(T8{?_czjr+O-fF|n9z`jh8)0kN|`Dj z%_!Cbu>4)FR!zDF!C^WqP-0^ybOGp$jr4pAD%`BjXSGd!8m-GtH~CI@3iKkChoGvm zaP*lWt$OXLFnvhIfU;uN5E+Z-L|*!^sL@n#tmYFFty6iepG~7zvsJTG%rj=-=;XpTrzSO5!+%7oaPY=5e1zygtLAxTcku0nk$QzEsB5d`Y1%@nnc2 zNJX&TSlYhcBU^gQ4^cpKFnlI9I~lS>+{hqnEz7pg)WtWYlHbGa0F2x8Ho1E{Yjlw! z8vmVdOKAVrDn5PUS@0j3=-Uh-nbi}^`wW^=w0w3!=r&OG;g2Hg=M#_$c^plE?=CK0 zNrl3BAVbIe8d;o(rJ}-MkG^QP>$5BsM))k);=p#n&ni=il+q4Py+PU9)Z6+IOdl$crxVm*3UP9*IEref_gN_9 z^8G@(2OFUZzW(I?#HkajlpY-@?tj(zS^P!&H%1+mnRKaw=C(-n)^_kYD~G^1Ayii~ zp3)q?(PH>U93y}V5S)49^y>Jqi-#-_92bl;=u5=JB&G(s=>>SwV%{#CrPfw@zBhKb zqPV`kcdqi#B!6kc!OSEL`e>h2)h?6V*;JO^Gyrhzls!YlZl5MQ)!D^80R!l?vaesB z*Jja7(o28dhB%INs-}9E&J(Kxf}KOu$L@|!$|eS1Dn6dwjB41x7}Cf?^fG^7sRJCX z6s5M+U^t*`n^<3ZNevGzBJt^p109H5Hk0K*Y?QnC zD=wv0NMK6aEN$>-R~*yZ&d@lQ8E`a2)#hM{Sgw!NVR=M3ax=t~l=wFYD}E_yQodo&(6l#AS~-9I&g1J;_P|WMBwoT3Wzca(slX)Yh)2NT=!KIw#oa$=Jz;P zhoT@tvvK;VbQkz17Twe!OZ7UlmEJUOyJ0&l>pNCfq4`TVjXoIc10%+3@eU>C{8#l! zdmz%*Vs|vsS5Ht}Mh9b2^4q{OD0vcjqPQWO)pX%($YI%oLg%VbBqnA{N19XtSNiOo zDNXg5*~Pp9*4Wfl*A!`Gd{T!-gRgJZNG)SLXRvCBRxX*oj}L6pOZP=*dsKftG(qvn zk3D)Rec%WX+U#>$_(ex0WODA1d)sJ|-j7;tOzxjkg!~8oIYFtOngu|+U%GAv!++>ubsaQkVeQW!Vm%JNlq(FWH9Ac>r|KRmW|=PX{i)gdL|}5Tge8kA8QP68G}= z$4YB`t}W$-kZRz`a@2VHw^}aNO%~qRW;wya*#{ve2r&Ct)Ax;B_Clj0H!;f=mrL$NFeCP zN*1q*iuyCosP>+Z9K`7*@ac##PEUh{GNOGzW4>?lgMPt81)j%sF1z7FJD$JJ6MWM}6|l0rPDZz!R#ihtp-872%Ij*hzl}#mFk!s;B zRE;l>oSbN8kSl#mj~H$DSQ2NXMr=3a)0if^@bWh>qwztDf*L+0m+4U+?C;P*^EB8>i6cYe7s+KOnt}5YNf2aG%+idcv+fjavx)HKp1gCUXilC+A%~i zr}A`26mA0=e!*h#t?;>s@_f^S%4i4_&|8vzx=Y zNR0cXJuPQ$smwj*EC@;^0P@##n+_2u8lQXniIC{=9vVsO=E-k5E9S%bJ2Zxph5_DpNl|56w;6wXZ6Jee8 z6c#L2l{qxFu8si;?~CM&TjXs$Sf>loLPMqCPZG~LZmCU3Pr)o**m0Lg7zf(f=Yt}P zBd0Z1HB8N5r;^>KR8(uJennQYHK8$FlS6hOBK+tH@5vFnqc{>-YC_;MH7BZmf|?Zs zvNDzFbkz#2o0WPyKl_eBOMmG~QDZNT(orbi^h>JCQ#)*lCsq?adv*SDRqaZIEwFna zu7QP;6?(l2Mu>cjf%E_^^MnSjV%F>mA+H5Uc(@OaW4>5G#Zm2`??9oL`tZbq?8An2 zpKm2#x_r`hNnt}rm^1weTXa&y8)k8%R!#&Zxo6DN@`3R&|LMFtmb8a4Xfut^sV3t^ zpmbs|K}W9KExE-CyzMLiwLGAl4-w)qqtlD6PN*6#Zbmw^2edUHEg;Je=5aEr8oPGw zq*Mz@u0~gxBu+h8I&@_lIx+83vOP{#2tk2LB&WwZP|})wEk#+W)MB6xYgOg7DGgB_ zsshb8ljRa7G-Tu2l{xKl1qxx>>dW7rKU5Evo4Lyd$4sae*qp4saHtR^9Eplv2A;b< zmE&;7Znm{#KJ4aV&vhmd@h##G^wC6Q4T?p)%#f*;Rodtf>4TYL0O_wa)Y+#&YBe)2nVKocvWSOV<3~m0EsqU!zBFVv(G}C>ZVS}%^jkP5QYN|@?>2g)}b2K zZ)0HFyV11dq_~x5(WlCx=!tp^_bz!;hW!n}F%^ilW3evMd)^uq={7kYgvM{E*8S%U z2=f$LEmH)p!JC-BZ-kLZk!l@!Z69->oNh|aJ`NmNXr#-&g9^XL_;$b# zd{~a+qBV!{3>6vW)r4gZu)Gh4+8Bok2-JiM`knlGuwYv8x(JM&;7s$Emx#iR(cZ|a zP+p>*;%}o!D$rN&6iOTrC_253_;h9Ug1QZF13)M3L%31r@#@nw=xEIITUCqz0FaWUnLHpZNRawgQKR4rP><>geEq5u=P@P@u*60o92rl##6VvL|h zREl%m!ja%C(bCh6j0-Q^7CJHDwEHuxk<)=1^vZu1XHC&x@?Hl$G?sex7Cqshh@n-F zl;SwvmeuqUAb;HF-LnVWo6g=(mGWFyG-{&-tpb<|ZYj)=oMlHCEV673JdvK6yi*03 z5pZ+g3J(0PqVjzlcL^Qs&V1(kifeeh;Oe%vphF$m(nTm!f2MMC#%eR3QEh2EdWb$F zCMtR0z7x_jr3=zG!Zch#FMgtpzOG{;NChG>k7 zwx+9jQ&>;PDB!)S<;$XNl-p!PqnYwfMZHSWt0X~GYDarx?6BdP!sjmR!jYY~|e$m&}qr5OGu)(n9u zZ%iBP)8Ob&>Insa^%(HxLx}n?*=KoaH;(I2*RL{r8os4h4!W#{iBlgV6(mc`2xo1f zVu=nIz{&(@7QRwmjnS6Os__Z3-!>N9(P!xgAaV49t21;#)XRm`}8~c zB-nGTiF;@^2XBuK0g74?7LB8Tj7R1E*PuEPX|)azZ5Kt!nL-HVS&L~xUiMNBjH1DJ za_lFw&3_z|SITjiRya7tU}uxY1ME%TmRmj$cCUqqr@uHL2De73`!e(^o2Yy++Emd$K_-QB)te)lMeb=`+j*zCVY47CU6MwXMS8Z0yLD*VNtqGf)~_4ex*pVC~Q`}YsxFnc(= zEa4>@S2Iq3LG2ogvF(kFMP4`!{Mw4WM5tEr?Bv?;71~z3t=#>;+)Cm%39g{4#+>@p z|AO>;#!KexwUo!@%~y8BZ9yZn0?sk6A!^uGqA|z>W)>|mabVO#cfAB@1`}bOiPj7M zW6|%Y$r}9i$)?iXeiRM(@t;|bYpKXdisJ~A3zq<4->Dn7G0yV7D0sB-@BFhFir<$v zcWmy>IT8rD#?#1d~qhQ~hfu)B3 z+*#3a^N6gR_Fk<`=_}pF!E7~R=}NzZ&vxb{N^zyC);Cdwt#T1T#u)wDmr0PxY?^E} z;;fM;`&OA`wf0gxs5)Y{a-tv#je4B}qrJfJXMvW3Hi7zk<~bxVpgxfG&?B3R`b&uW z1d*Q%RJ_<8jfVnDzvzv;1JW3jNOY;~dYt;&odW56RN-P6)JRU_5+GA0YOcd4Z@z1T zeRjgpdT^ZGY>_H}v|3UYHQ-KVra;Au$Mi_%I_HQcs2{1tbLTP`-*8rHY2ce?TDp@d1Di_ z@E>AJo*NXhz$0cPXHWX2kI!y2fcCv;&{mX|6tnSXRMSv0EFdKJ?y-X&ptj028!ajJ zpPss#PBN?r#?O2%?wYRs8qhl3+2?CyRvlW!Xa8AXleTtY0K;?Q%*Y4=!IXY)=m9AP z=E#>J#4N&c(<}1eC4Imef?E(NLHOui*k8_a`ZD=d(YEHzKFZ!KeHpB{A%pnuLiWL? zC-K@)qkD4(28mtKt|?KVNWDNMsqJ7?L?omE-2wT8X-i9aCe6NSuMD}v6~s2`yA`xz z&>`p|*n=H~mKhA8&b?aU_djeGKs3?DfbQ{oT&8(E8TN}VM_QRRed{ki73Y;&7TFUHCKvg6r3*~y*|wQ9o6MWk;dQBQn)FItE#2;Tfi?}~=E ztuT=*gP&`k;oY-gv7QPly|Nk$H=;mO1c@e!f|WT#=OhCcW{qntgJaQHcTj|H6`Qh< z*rNHtgQ@n?qBobEO(WCRHtABbFOOS8I$Hl252WUG3_%%V6&~)4x}9uBTYyb>DRcEd zCz75ig4B5dMP?|<63C}{3?kXZKFKf{Z=YAe3ECSFZc=<%W+v~PLnU=6WhTPNMyyqY zmKWw3FiO@TVl2jGay6qi^G1POnLBy_o=6`UFI|Xca&CEICwe)3FJqtTRs1%$<-g4@ z$TMfQOrA$Tfg_NsLj6$=Z4JGD`zzTF{p|46p4>@r;`V)ve1L()b#(Gw#DoGc_%5Pm z?5zh&^a;>zqhUd;)qJwp%2Ix;H?mt~vzRm1emjBvP$RPF7_<%q>m!8(Re)}{&3v`Q zT9Bh@l6L<4R-sbw%P@$(Cv;^|^&f(DHe=se zU>*}>DPhs8&i(Gz#Sbv&32OnO3eS2s?~KpiF@G9`-wTJ5-EA5&#huTAV=|v z&M?Bt1}t;N6STa-w>JnzIqb3iyXo8*uV8KqMvncbWB>%xNR+dM>1ouiHf^KLzZS5_Njpp^2#_baVavjp#IwJ6ask4l5$KSX$pvM?*}N;t(LSzeiO#D8Mu&9Vi^Zd>3L&t zZlpxL(ukR> zR45j(B0Y+Vftgo))#p9p1Fj10cbqN&M78c$32il#3f8Dg*{9L30!sp4?UZGbBz7u= zRoXaC;2R>Nfu7yIdflTvAd{N$Xi!rF6b+5(i$7v}*5z6YXj`gW!xcDKe&WYw{bqNjc^5freYIi%qbV3P9X>5*g6i=Gwi?jXjFE)8|Ia z`qTUrSg#Ww+MZfvfM!xAOlyKrHuSqg%PgSJ>VV8V0hq+6K8&g)u3U*Y@>eQ2U{@4n+j#O0>%yT=Hj<={5ti3jN zYGY3u*!^PHV?pqQi&pn5;zktE-qvE~QxMcu?~SV3}N4DkhgL_!YB3NS98u zm(-U|HfM3{P>?DU1O2At8o=P+g%(ztRrtce3nx67ZN{pgwpF2(gsa^O&Tiq4t3St+ zeyHN0U*-?LRU8D(eljCI{AAk{+Rb%$)2kJB$D6jIUH7ok+l|X5D|YA&{a4e$j9E(^ zK>@xFV8xf<8!YCI)3BG5;}-$W^Ea^1F~gcOPpy}#*0Z3Wl$1%B}h49V~DaCpXM70xNP?iD*> zo_7e<^Nh}$>(cA>wwE2%qa&}jg^#@dcoi+u72C;2iISCzl~;!7y3JQiMc{z671KQ< zb58fNoU(pe2%ocPK{u)oLZ;<&Nf#sWI$wA=87}@yDcD*qmDRThq?el19R;|MLGhUO zWSWu|q1~0fBJeR!Hsy#u@J!) zeP;Ky-e>o8@0J|qX#!D)r&9%2SKHr&7u{H0sK{Cg4!oFPK6#Tl&&(fA1_WQ9%UX{4 zV9$+9Eo56056(zO2w$&q*@6aN2^IaHIYE{ct?odi)~PEA4ZTUxP>k6HaeM;?1!hz9 z_6e}XpSc+YR%;dCE8#GMZu|bP1ypggydPl=vflH<$B7k?5NgxA7`_4Y>?k+fBB^rR z9gQK+`T0hsaYuJ0gzZ}7N-PwxrHZ7w3`at@=MIkDwZV&$RWqP8E~C`}AI;riX*|T( zC-6T{ULZV2j&nYEy<1KluhDm)pqWm zDAB$B&f0ettG``01N3b>95sS(%>x<=06!~_mZtqIvCT@`b#^|`MrCLB=XmW!Z_qO$ zelJ~(i2}oyT_{;)VJvI2|IhHYEfn`g6RGn$#;|WAmFvSDH34oZtjfS}PHuL+fkZ=c>75SDa;4*%%0}j4+5#OB@(^NJ+`&h%-EGnlxa>*(Qty{pjgJiP47B zN)oBUI24ALa#XrtBzo=yMF>qfXse{GXgrKDC3xbN+_Mxq3{fhn zz_+j)tMkv(jF)(uBy%V3!thU13p@oX5O9vCyR!*Y6JQV7Rhd2`K)8EfJMQlnaNeUA zwBk7UD$(b_fE@}tHM|%2a=g-J;XsKPnJo%j{>PlS1DVx3!^k45O0gcNE+ML{93!S^ zD2gwsJjiD%XQ_4dL55@w#)SxVD=eFv8Q*v4cr zn7Rc>n~sobQlR-wQz(w?h&bCMm%Q+Z3zUn{er&-szO@JQrR^B*G=L1|HdMw=t57N~ z*hJExe=1q93dZC}`|5|RWSu)tR-8}cEZ-ntE4{c1lCEdD_ToPFv@}y8IiOFj&U*$S z3usM7hcB~7g3E4iyx<;(?H&H0bODsjzIHO3d4h!Gps90{%L`9=yWLZQMwSvwhEN6D zTquqN!7cO`Wm;+yWCY|kxxYM6*IRYFJbx(fj!9lZByuVx<`LaZk&xB}VVP=@>ErKz zLl`oc8PYNR)D)V}XN}znG)OhC(OlFWO;bnYZ9OX+?R8jbLlZcf-|Vcpn4jKjQlzWE&zIe^Un(4h%#j+ z->k5b-PqM~a`$(LTHw%5>~zemdc7m*wOEO>m`bI-WFZd>*hn#H^=sHI+|}92(4#I6 z0DON5OD=1wOS2;<`~vzN3f*90`6&X80kvRQIIfp8TK|k7)MeQi*JgQWtdd4|$2nba zyeg_tOwv;?V2doUlW5p}^trgqzp$HIDKGVqnq0rNSZc3M3v0>JVl@$K;bo7r@ma_B zE>rOK!}1Ipa<0<$IO~{Cc?FMq)g~!-*&YDOgK?;GL)Zo%)z{dqUtGM{KCZCO>>Z(N z_tq`@i1cQa$D(d)kt3m?UvKhYHjT%*UOi#5w@@-^ee0vqb-9(dYaCVpDk-J$X{F&` zvOw8vU##G5p2*fnYt?=0uF}bTX&$0Cq6RLT41HS}WB%1+M;ccpr`GE6rl>k>ug@QD zC~xF9#`JHZXt1fuTD<WWk_$~kf=GOc{zW0e$h{&E3PECuiF%U$LDz2wcO^R(3QN2JXJ-V;-x$msR}Cwp-C8_2)2!@iObM1KByL6=vnr; zTE8JyR6B1R?*I1N{X@68iBr!FqSEVanl)-;hreTyguK<=iCx!K;_-t00e=hfyipaN zoMBdJdHYS9e%M-peEaU!e83wg>9`aA#kuC!(}Q2vIIgdow;q@P{G)0lqL7op@-S$3 zJ#KC_cIF{XFLu@L=@d9%?^X&aq!fy}zllAwEGMU%vDlu147l0tD|A^x$Dews(xTeG zH5XITTbbc^nTiNBrR(<`5@EZjN3!aVWFku@)4;~ekX*gmBj%Gb4YSBu{Oj5TzP(~}$AdWBq*#(p zc*7Wps)+RENkh&ZT)9c0a(wZln$pJpqiQnHni6jZ=P8Pt+N}!S0QaOrNnMro*h=Np z(~3t};fO$eI^sBT1tREvG#WwL_B5Qx_bHTTCJS}Ar<|?$W;-1*0mkwwm4$Nipja5 z_O)O`qjI5k5fRv;#QI4x^$@SVJuEVHlkrpxHIMNb9@k0Dev*c|Da^cPH}lNdw(^;( zUbO?B3{q`2(BOgbUg9j=EKpkPdxsA%1VXfm7<;6>C{i29MH7_#^vIoQPio=t9vj}0 zwZOJ-{%zAFHHHdWwI=K)*dv@ohJ#M}cmd>;yfEIj7uw^ad&Yj7;y>tyc5*gXM0)i5 zUdbT3*6?uqa*5N@R(*k({2EF`p|J(8qJygjYFKGoH9xFoQ<~DkPtUkC`f^qV6IZ;< zt7CReGx;p3p0-|8zb`s9Mtg##b`;8bPQFonM<#m2Ukq*Pi)o#!O2dJVjp6Lkv-=dZ z1zdC~pn}L=>-$smklTfT=ZDQi%5;;kLj3R8M=1_i1*55=L_M8onn~hGH&Qi!OHQtI z`C>5~w^9;UBQ{IL%Ly$t!f^2F!08W1+t#WTX>1khVh5BMOUR5RusH!pB z)Fc__FN!5XmhPs$ zY)afnhPLo6M|QlTAYa_M%is#KALFT1Tx`3i0QTRaGlNoBZD4^Z)>uv8pLqGB5!61z!*01ym`nHPLfphLEOy$n28j3;4DJ=PdYSWet z$=m$Z-6aj-9Wv1|TDbgh+X0;wOP4W$vQ6l;@k*3-r8|gC6crz9JeA!qhIc|Ud`fC0 zbF~%c%I|zBe&fzcDnmc+K;;NwT}j}NCXxk6(|^@Rjg3rnznZ;1C}>(M7S#ta98{FK zX=^065`Kw?>mo;i^-nVVrKC?P^hE1A@Nv}+<@qpa-ZuO(YUVcJVRicUibA&sK9>hR z)*CpVJMx7#pE9;t2P#b-(7|0G?pL&c;#xm|H~#v!m=8va5+*QT_!-f*PIrtpekyS+ z3twG@v_9Z%O>23mcrBpo=4H!b*Gn z-<^czb8gi#v4-!WtE!fEMo@PtED0X*n|5 zbWkgj$qAtj@SGA2T+1D%t1+?th!#{-9Rt3Z2e#G`;uj+zsaDVF0eYZ;6godChx=tx zZl}oFSsC;~tcK^58G8cfYx;f)3JCaUNrCUqp5fqc^u1p3d$wIqeXOD1L zQ_z%#rV4#K^1HZ)4=6_kf_r7vFNraLktu5DpDmez9(6#bT*gP0^Mg7b{C`_2Q_?9p zvBFFIQPzj3@ukCd_cB?$;a7!eP)4JtIix1=e{FH)2XCH|Y8h9OT7NMRe~_~A@-a1D zCvw2=nt60VP@@8Q^GTYlkmif=;A~=QB1+RLd|=z_;hUEBa2J; z0Zn#bpC*p2dk6bT#J`+3M!u;$TT>*2?dgyNIm9?N=!KM1E`!FR8{jK%nMu7F)53-4)-q@mTYz7P2j2WuMus+~JW41V7-1(98fHi4rn-0I(t1DQEQ01R(r)_W&VH{+_kk$pL3YF!p<~K0Xqpz-v zg_r#UPq5eQPGlBKQHt>bKH&a>7fmz@qyA84Wk+HOD(gt5=(&f*uX+BU?RSWl=9Ys^ z&FxJsE!gps`hRwqMQYq0kqcbwM6oRmSL-<_jO?&6_0;`qMH5noFRn0>@jCHX9B657 zmb#MG7mtPxL{Mi6el-*bZ ze4ASOQ69Dm%*UOcbCXz~Yc^|Gu-s#HnpA!Y@FfX%>QUKhtxTx^WGE*en*NxXv?A_- zL-&i8CJtEG)gVq{u);60FbN&I`q(_dCmpc$KhekyX}$5r%DS-vze05V+4)^W8GkC(0QXFT@8dnFs2s&plCayc2Io?+SK<&Abcqpqb>9wIV25-K!1O*-y=*r zA{rcwTnVajsxrH}a7|$I*N`gQ@cmKjySew>-1~0sckRNyn|t5Qz3=9J*J$_M-1~0s zeK+^V%?$HhMrCnZmSTspJ%r`8=pP7#BA4JtY;YhJQ(}5Jf5rCW7C+;-#eOVdcf}IS zNw-*LP%4Yr?zCTlOENLO4xh~-kcG2!Pn5I)h(Q1?F3Q^OYbiC$6HxI|Tj z3(l~WN+~F7lXCfQ6nRUj%e`4mj%DOCYqTe20xR6mvT=RoSfKCAOVP;XaKEf%71i{7 zHCb9;sr9;4ILkJZ)?`O;%Db19@=Sf$joL$`x&dy58fAKfy{V_IW2eG7wF}wH(CpMw zgP1<<>-8P;b+4~{W?rpMV0k$e7P#Kl3cw|8O-6{8S-T1+d9WT37bmv~23G6*y4&rk z!I}|%8Dgq@4U7cdr~_;f`jZj0Q#w>b)S&rDGzecOY+0AWaUG`BYac`~91sCcK>O`jV#CKF~i`HgAub=dFq+3|IN?{eAT zNPGS05Q1eV$#2KYNB59EF>XxRlsD01s|3;KQpRc)OVSsV;eBSPIq1VR9tCla8DJtA znuoDkrizuNq;bEvUj^_kdm#5x^ad`+|7$^3N%;qb-@p3;ydT3B?m5vdLXpT25f_!E zB4Np*dsNtv)8}oi)j{kp=*t;6f}hCJs4`IHG*F;CdNw>!D!8QMH#du=cXg0(SV*;+ z{$!W$!pAdU|29T!ZZ3u1)!7k~PhrWHEMk)q;zm|a<WHI&E3PTt!*hr9`3!Q zUh;BR5w*@Ev=%qkWWRYEZTrW_epq{Sqo59TkSHmeBw%J3PZ^OlcO4bI|Fr!Q3nOdW zSh<(1gEJlmwly9r5tcHU$9rI98pKXM(JCjMV>w-$!52 zTw1?dFdYQ8qP~2lI-Q{i(TyS+uUOYdW;(gcaiKvBPvQsoU}{)dc^gaYXTXZ}G{V!_ z!PD~WIa=F{mE|T}?wX4smBlkpQ^-;|qFfZh%{L>FV1AD4WAk9CQdRo;ioTozVuRna z1!FD2kZ024Fp@=HW396Ka~Z!7l0W2vTnP2XuZ4o4b_Z}e4qY;#+uxg_=};RNvICHM)q=P|doHOpbY&t+fT4deWT zKK@reudlX5{a*!K8*ghDkKIQ;Z8_d*-dEm$HYVzOr^3>{`Jhi2QzH#%%2yksGe*kx z#%>rXp4wdg%_H?$MDX6E@b2NgZD7YP4-WZkAY$Yrk{pTA?U~JLzxRkAfy@4*?3NsN zyOw=x<7eioF@_&D=6beN2hY>UrdKdba?_DqBjx@@g2f$h`PC##3J21LX-KealNig0 zF7*38B!(0CPq&nL&RAwi4ZSB$b@@&P1~2pn5E9%WG{Cx%1NWJXmV#wBuH-_Hf7k85S!XyHlqT3(s z$hpEsJSJysJ`rjfsgxzZ{%is`$8aBF|OZxPQ$x3nD7mE*2cSzsWfpGujA%}2R z$LuF-6z!`(EF=D_gpviuC%{M59(j%J+VD(d6HZ8f-cr7@-a0eU;U1GXZ}lJCAaF z8NDzvAw<}-XWzNW_=CM9Lq2N&KO5&D2F?m_7QRbYhZoT~_#kK8FH$!U!WEuNRC7w& zH}CX9yq?ITd#^)KWQTMrviPXw>nEUBWm6sEjM|ujjbvlT381XW_=+cnh47hUd8%91S z#|C=_=mI-8wBLJvOnS(vVfP@g??BmH{>CIEf!modOq_Pj_1XHee&g?yhS z1zvTabc|#$LaCMWr!P+u%g>L)J~ZwiW_2%6HiJi-GZW25tL(hdB*Y>nM`EfXrGe}P zwk$dEvm^yw?VOGH^jJZERMu}7Io7_MHe-O;3}r4yxsR*rVLSJuEbn>Qch$L37U^%% zC@yGb0c@Ks{ZV5XbZ&OTNUg3G+=}KMJ}PC_*zprxe*|@~*)RJsIK$lGOmB~nesp7Y z0vMx5^c*;WjeE3iQ7MC7l5mLo$I^s^KKED9jaWqIhbt?q*cPx`=tWRq8z~p6cmL!G zuK4o_e$^`2>FSJi?Yt6<1}=eA^YvbiUJ42g3=?B?o?wyF4%z!UJZQ|F_qLJ-N2U~K z?Mx?)7Yh#De48c6cA!I6bS?qs1(;?PRNLf|r)K7X&F73E+RbHdd18fKjQd64^$y(a z9&@*4VXre*5<}3>$8m3&g>BT+2vfD zR~Kc`usjb_YwBzB$eU0WzdzUQ`~A6N@PCin>>k)C4Rd1~F`|*;BvpBE`uH2Oc7ASj zBC{*ugrH$>OT=CP`@XhL(ig~aI{pF|98Znlf&zQ4-g+)DCp`bCmKpA-^&2|YPd_h2 z;_=9!`Ry1yJ`}`<#{P2Db&y^#qzKvGlq-MKb&UR)qoEs_!`jg!;(Av;yi2w)^FaksCFAK0O#^bD6bBD%WKB>P@0eiUP;z6#6nFK7jrw$rtF3^Rl)01^8Yr%$a z>M*|JqRi~Ef_>5PNN`_V%1x_P0GKC0Gj3+#3j*J~KX2sb#Q{;hId0tiMjXW|31gVr zzgAO=@D){kTz|_>TTB+OEZ+orKt^k1){L=5qqvCIz{tv(D|2HJ9e|G)DbFd-U0=)u zcIAY$hn;>c?d^@cdmnb$clE=3fwkLyL|Q`_7(W)uoWFu5n1!qXw z?#3up?iG^y+_2DW4TJT&OO^6B)PEY4>v1z8jSaZLT&)xv0_-T5i2iT^%wcIRIAcgP z{sa~Xntj;}`Nd`?1l5XeZ-8%`=(5!rYbU*8vcQ~iyR^?v_EPKt;gZUP1(MH@r0flb zE;gOH90u#gA>_Dmn9dlLDK05LOCO)t{%a%_kN($-LAQr8=Ah{IzTnMlwOg%wR$+=Lp{7ZceUVhr|QM1;aE8J^$~#w6MZ?SRfbb zoD6t?aW)grheBjIdqu#5qOqD42V^k;;T};*9T`@XyOD+W7L4LNzQ+$&6)SUDMycV%iI8ijC zHH0g#cD7BT>txRPKAcq)jzw{;KN~^3L-c>q#B>W^%e6(nJ11BC?pxV zBvJA*x@4ZyTMF-YVosEhy1@&qoosPi(6ae)p)XG%^2&|*PiQ(Df><~S?WA9A1t|In zOh|}^E*kA*o15SyXAAv)`X z8l2Kpt~$LZN||AQ5D^4MiOfqXdr3LdiNZPhK+I z=VLD==OMiRMn;3<06OZ&n01Z!R82W0Gv69N0W`Gm-_c z5Tb-#n(QdvD;s;0+* zl_72yPM>Tw!j-hFJ1ZW6B`~XGUmF=LsRz~8c$}qF>lix?qz5p}mD5qk|C7fA=0 zheBF_VRCah+ICy{jClen<5PxIk6I01>H!|8R=SX6S-?vH1P|mgS^zHRKX9_;01Hu0 zx&&pv4L@X8C6Ig^B`$V-8ntnM63({;wrqza&r0kSFxO0IVc1v`U08aR(B#WMVtUtV zMBWI(m@yjM9yOMMO`DRVjUDt)@~RU`}mk)CcUUt##NX z8S|_Tkk5eovD7=>p5^OM(gmWYIK-;DW~VEiUM5fSKXJ3c4D!lG$(YVwvk$QEZj>lEK&lM49jPqeB%O&InIt@JEOJ@B z2Mg#cr33;D{cS{ll=WaIXLRp9DAYdQbrzWaw`f$uE3D2br&&@E92gh8(QOImKw|3X zcbD**zPN_^6tPi7@}lOLMK?c(Pk=;lZ9wZ;D0ylk(Pa1BBZOSMC0sqTj0u5exEUZS zjvIjgIbJ~86ybt#Ne+ow`7GFqr6MR<`%Lalja$IFc(`Wo8bO`aXeWwk{ZYvnnYVYB zxHW0{Do{pKIbew^%dit2(Vlqs{>!8}sSmMdO!^^d12H=d_BUIo!guloMRZ&p=Fkl2 z>Gw+d-KXX%UXT&fu`mNl0@R5geMS%^*su-$Vm}FGfkk`o8{5u?Uof>CvOj78{htewt zlO;Fj)GeDoh;?SJ&62?gd)F{GWk6zRgUke(`pR}GgO;za{Fpoe_f@na`n`ELwZ`0p zwE#F+>5Qb#qWaB8^=?QYi)7ijKZ&hYVbhnhh>}`s_UEc&yR415B*Yxs>EyTtiW^(C zo`lfZtHxNK)0tlZD^#@}rUwSS3)ZSAcNu*AiMNnfPyfCM`ranj6(!w1c`1yC1QXcG zF3ml#D$EXW`kaAd>+Ici1+z#|rC(pMhao6Sp`LYW#yyaoXr7Ad%((uj1h3qJ*h=BH z&8I3?--fVdA;+WtHD55kOVFuYD)OjQu~7_%Pw$nkvEe1_%mF=@jVRDw_U zP~d5*s4h!!Q@lbJmEO2pAfIPrEi)snM7F~XqaYF0zB_IMFg zLhLi)tB?gRkTu)-Dwd~79*EoM1ql~Gn+anl7N$AfKaN<2E zwLrN0s45}hK|TdnDDQmsktza2G4lxMg`0Cxb}$SNk=8dbZH$RvMqze?p}Gf1r`2mu zrI)3FR)UO~WDF-%t2|pHKsqXZ-V>qrIu=yoObyJc*B{JSxkQ|i0!IKnd9qe(H7`?F zSV3f^Nn(Mc23!;JW?~H1IW53#_rvV_VfO9qzy#;@X*Kf}NFnEpw(@*Y+6~)+B()mL_#R#bFX`iHfS`4`pLyvX=F|U8}pb!AVuNCWuLsU0<=(W7AuNwO!S}PE)ET z=(S@@n2c_#kdU|$TSofYrZs1zFXQnyRKJO!^|>ivyQ@#;Zwk zz~!*qLVpa39c%>{B9!WxS)l$t)P&O+3vE$=%j%SC_SIBBKqqZ4cIe&qY^yDvea<)s zBc=SnOqoGD1C&p^Fgs}!=gqW4)U+t+*F(TC;&jjY%0DK1q{4OhmlT}h&b#U-=cIk- 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 literal 0 HcmV?d00001 diff --git a/측류추출-자동운전-플랜-컨셉회의.md b/측류추출-자동운전-플랜-컨셉회의.md new file mode 100644 index 0000000..06eb3dd --- /dev/null +++ b/측류추출-자동운전-플랜-컨셉회의.md @@ -0,0 +1,2774 @@ + + + ▐▛███▜▌ Claude Code v2.1.143 +▝▜█████▛▘ Opus 4.7 · Claude Pro + ▘▘ ▝▝ ~/projects/ExperionCrawler + + +❯ 측류추출-시간지연-적용방식.md 을 읽고, 이걸 로컬 LLM에서 자동운전 할 수 있는 방법을 제시해줘 + +● 파일을 먼저 찾아서 읽어보겠습니다. + + Searched for 1 pattern, read 1 file (ctrl+o to expand) + +● 문서를 읽었습니다. 이제 이 시스템이 실제로 무엇을 할 수 있는지(특히 DCS 쓰기/제어 능력이 있는지) 파악해서 현실적인 + 자동운전 방안을 제시하겠습니다. 기존 MCP 도구와 아키텍처를 빠르게 확인하겠습니다. + + Searched for 2 patterns (ctrl+o to expand) + +● Bash(grep -nA2 "@mcp.tool" mcp-server/server.py | grep -E "^.*def " | sed -E 's/.*def ([a-zA-Z0-9_]+).*/\1/' | sort | + tr '\n' ' '; echo; echo "=== query_pv_history s…) + ⎿  active_alarms analyze_pid_impact ask_iiot_llm build_pid_graph_parallel classify_intent extract_pid_tags find_t + ags generate_status_report get_tag_metadata infer_field_instruments list_drawings match_pid_tags parse_documen + t parse_pid_drawing parse_pid_dxf parse_pid_pdf query_events query_pv_history query_with_nl rag_query run_sql + … +18 lines (ctrl+o to expand) + +● 문서와 코드베이스를 다 확인했습니다. 핵심 사실부터 정리하면: + + - 이 문서의 방법 A/B(데드타임 블록, 1차 지연 필터, 무빙애버리지)는 결정론적 제어 수학입니다 — 매 스캔(약 1초)마다 도는 + PID/필터 로직. + - 현재 ExperionCrawler MCP 도구는 전부 읽기 전용입니다 (query_pv_history, get_tag_metadata, active_alarms, + query_events, run_sql …). 밸브/SV 쓰기, OPC write, 셋포인트 명령 도구는 하나도 없습니다. + + 이 두 사실이 "로컬 LLM 자동운전"의 설계를 결정합니다. + + --- + 0. 가장 중요한 원칙 — LLM을 제어 루프에 넣지 마세요 + + 문서가 말하는 "1분/5분/15~20분 지연 보상"은 초 단위로 결정론적으로 돌아야 하는 빠른 루프입니다. 여기에 LLM을 직접 + 넣으면: + + - 비결정성 — 같은 입력에 다른 출력. 밸브 제어엔 치명적. + - 지연(latency) — 토큰 생성 수 초. 탑 넘침(Flooding) 방지 같은 즉시 대응 불가. + - 환각 — 잘못된 SV 한 번이 측류 순도 영역을 파괴. + + → 결론: 빠른 보상 로직은 코드(결정론 엔진)가, LLM은 그 위의 감독·조언·튜닝(분 단위/이벤트 단위) 만 맡습니다. 이게 + 업계에서 LLM을 공정에 붙이는 유일하게 안전한 형태입니다. + + --- + 1. 2-Plane 아키텍처 + + ┌─────────────────────────────────────────────────────────────┐ + │ Plane 2: 인지/감독 (LLM, 분~이벤트 단위, 느림) │ + │ - Step Test 곡선 분석 → θ(데드타임)·τ 자동 추출 │ + │ - 파라미터(K, τ) 튜닝 제안 │ + │ - 헌팅/Flooding/순도드리프트 이상 감지 + 운전원 설명 │ + │ - "왜 제품밸브가 천천히 열려요?" 운전원 Q&A │ + │ │ (파라미터/권고만 전달, 직접 밸브 X) │ + │ ▼ │ + │ ┌──────────────────── 안전 게이트 ─────────────────────┐ │ + │ │ Hard min/max clamp · rate limit · dead band · 감사로그│ │ + │ └──────────────────────────┬───────────────────────────┘ │ + ├─────────────────────────────┼───────────────────────────────┤ + │ Plane 1: 결정론 보상 엔진 (코드, 초 단위, 빠름) │ + │ F_raw → [Lag τ=300s 필터] → F_clean │ + │ ├─ B_sv = K_B × deadtime(F_clean, 1~2분) │ + │ ├─ D_sv = K_D × lag(F_clean, 5분) │ + │ └─ P_sv = K_P × lag(F_clean, 15~20분) │ + └─────────────────────────────────────────────────────────────┘ + │ + 읽기: query_pv_history (현 시스템 OK) + 쓰기: OPC write (Phase B에서 신규 — 현재 없음) + + Plane 1은 LLM이 아니라 순수 수학입니다. 1차 지연은 y[k] = y[k-1] + (Δt/τ)(x[k]-y[k-1]), 데드타임은 링버퍼 한 줄. + 파이썬/C# 어느 쪽이든 수십 줄. + + --- + 2. 현 시스템에 매핑 — 지금 코드로 "당장 가능한 것" + + 현 시스템이 읽기 전용이므로, 밸브를 직접 안 여는 "조언형 자동운전(Advisory)" 이 즉시 구현 가능합니다: + + ┌───────────────────────┬───────────────────────────────────────────────┬──────────────────────┐ + │ 기능 │ 사용하는 기존 도구 │ 신규 필요 │ + ├───────────────────────┼───────────────────────────────────────────────┼──────────────────────┤ + │ 원료 유량 읽기·필터링 │ query_pv_history(["ficq-6113.pv"]) │ 필터 계산기 │ + ├───────────────────────┼───────────────────────────────────────────────┼──────────────────────┤ + │ 권고 SV 계산·표시 │ (위 + 메타데이터) │ 보상 엔진(읽기 전용) │ + ├───────────────────────┼───────────────────────────────────────────────┼──────────────────────┤ + │ Step Test 곡선 분석 │ query_pv_history(온도/수위/분석기) │ LLM 분석 프롬프트 │ + ├───────────────────────┼───────────────────────────────────────────────┼──────────────────────┤ + │ 이상 감지·설명 │ active_alarms, query_events, summarize_events │ 에이전트 루프 │ + ├───────────────────────┼───────────────────────────────────────────────┼──────────────────────┤ + │ 운전원 Q&A │ 기존 채팅 + ReAct 에이전트 모드(이미 있음) │ 시스템 프롬프트 │ + └───────────────────────┴───────────────────────────────────────────────┴──────────────────────┘ + + 즉 Plane 2 전체와 Plane 1의 "계산·표시" 는 지금 코드 위에서 만들 수 있고, 운전원이 권고값을 보고 손으로 적용합니다. + DCS 쓰기 없이 안전. + + --- + 3. LLM이 진짜 잘하는 4가지 역할 + + 1. Step Test 분석 (강력 추천) — 문서 §3의 그 작업. 유량 스텝 후 하부온도/상부온도/환류드럼수위/측류 Analyzer 곡선을 + query_pv_history로 뽑아 LLM에 주면 각 구간의 데드타임 θ와 τ를 읽어냅니다. (결정론적 곡선 피팅으로 교차검증) → 그 값이 + Plane 1 파라미터가 됩니다. + 2. 파라미터 튜닝 조언 — 처리량·원료 조성이 드리프트할 때 K·τ 재조정 제안. + 3. 이상 상황 서술 — "FT 헌팅이 5분째 ±5% 지속, 필터 τ를 300→420초 권장" 같은 자연어 진단. + 4. 운전원 코칭 — 신입 운전원에게 "왜 P는 15분 늦게 여는가"를 문서 근거로 설명. + + --- + 4. 단계별 로드맵 + + - Phase A — 조언형 (현 코드로 가능, 위험 0): 보상 엔진(읽기 전용) + 권고 SV 대시보드 + LLM Step Test 분석기. DCS 쓰기 + 없음, 운전원 수동 적용. + - Phase B — 감독형 폐루프: OPC 쓰기 채널 신규 추가(가장 큰 작업·안전심사 필요). Plane 1이 SV를 직접 쓰되 하드 클램프 + 안에서만. LLM은 여전히 밸브 직접 X — 파라미터만 제안하고 변경은 운전원 승인. + - Phase C — 자가 튜닝: LLM이 Step Test 시점을 제안 → 자동 피팅 → 시뮬레이터에서 A/B 검증 후 반영. (현 브랜치가 sim/... + 이므로 디지털 트윈으로 실플랜트 전에 검증 권장) + + --- + 5. 안전 가드 (Phase B 이상 필수) + + - Plane 1의 하드 min/max·rate limit·dead band는 LLM 출력과 무관하게 항상 강제. + - LLM 권고는 기본 "표시", 자동 적용 경로는 별도 게이트 + 전 변경 감사 로그. + - 통신 두절/이상 시 마지막 안전 SV로 폴백. + + --- + 핵심은 "LLM이 운전하는" 게 아니라 "결정론 엔진이 운전하고 LLM이 감독·튜닝한다" 입니다. 그래야 안전하면서도 LLM의 + 가치(Step Test 해석, 적응 튜닝, 운전원 보조)를 다 살립니다. + + 어디까지 진행할지에 따라 다음 작업이 달라져서 한 가지만 확인하겠습니다. + +● User declined to answer questions + ⎿  · 어느 범위부터 실제로 구현해 드릴까요? (Phase A 조언형부터 / Step Test 분석기만 먼저 / 결정론 보상 엔진 코드만 / + 설계 문서만 작성) + +● 무엇을 명확히 하고 싶으신가요? 위 제안 중 궁금하거나 다르게 가져가고 싶은 부분을 말씀해 주세요. + + 몇 가지 짚어볼 만한 지점을 미리 적어두면: + + - "자동운전"의 의미 — (a) 증류탑이 원료 변화에 스스로 보상하며 도는 것(=결정론 엔진이 운전, LLM 감독)인지, 아니면 (b) + LLM이 운전원처럼 자율 판단·조치하는 것(=ReAct 에이전트)을 원하시는지. 제 제안은 (a)를 중심에 뒀습니다. + - 실제 DCS 쓰기 가능 여부 — 현 시스템은 읽기 전용이라 폐루프(밸브 직접 조작)는 OPC 쓰기 채널 신설 + 안전 심사가 + 전제입니다. 실제 Experion에 쓰기 접근이 가능한 환경인지. + - 대상 범위 — 이 측류추출 증류탑 한 기에 한정인지, 일반화 가능한 프레임워크로 만들 것인지. + - 검증 환경 — 현 브랜치가 sim/... 인데, 실플랜트 전에 시뮬레이터/디지털 트윈으로 먼저 검증할 생각이신지. + + 어떤 점을 더 풀어서 다룰지, 또는 위 범위 질문 자체를 어떻게 바꾸면 좋을지 알려주세요. + +✻ Worked for 2m 21s + +❯ 이미 쓰기 기능은 추가되어 있어, UI OPC UA Write 탭을 살펴봐 + +● 쓰기 기능이 이미 있군요. 확인하겠습니다. + + Searched for 2 patterns, read 2 files (ctrl+o to expand) + +● 쓰기 채널이 실제로 있군요. 컨트롤러와 통합 제어 시퀀스, 그리고 안전 가드 유무를 확인하겠습니다. + + Searched for 2 patterns (ctrl+o to expand) + +● 핵심을 파악했습니다. 쓰기 채널이 실제로 다 갖춰져 있네요. 마지막으로 백그라운드 서비스 패턴과 안전 가드 유무만 + 확인하겠습니다. + +● Bash(cd /home/windpacer/projects/ExperionCrawler; echo "=== ControlOpRequest fields ==="; sed -n '1385,1410p' + src/Web/Controllers/ExperionControllers.cs; echo "=== B…) + ⎿  === ControlOpRequest fields === + public class ControlOpRequest + { + … +25 lines (ctrl+o to expand) + +● 확인 완료했습니다. 제가 처음에 "읽기 전용"이라고 한 건 틀렸고, 정정합니다. 쓰기 채널이 온전히 갖춰져 있습니다. + + 실제로 있는 쓰기 능력 + + ┌────────────────────────────────┬─────────────────────────────────────────────────────┬──────────────────────────┐ + │ 기능 │ 구현 │ 엔드포인트 │ + ├────────────────────────────────┼─────────────────────────────────────────────────────┼──────────────────────────┤ + │ SP/OP 직접 쓰기 │ ExperionOpcWriteClient.WriteTagAsync(cfg, nodeId, │ POST /api/experion/write │ + │ │ value) │ │ + ├────────────────────────────────┼─────────────────────────────────────────────────────┼──────────────────────────┤ + │ MAN/AUTO 모드 변경 │ SetModeAsync(cfg, nodeId, "MAN"|"AUTO") │ POST /api/experion/mode │ + ├────────────────────────────────┼─────────────────────────────────────────────────────┼──────────────────────────┤ + │ 통합 제어 (MD→MAN → OP 쓰기 → │ ControlOp(TagName, OpValue, RestoreAuto) │ POST │ + │ AUTO 복귀) │ │ /api/experion/control │ + └────────────────────────────────┴─────────────────────────────────────────────────────┴──────────────────────────┘ + + 게다가 백그라운드 서비스 패턴(IHostedService/AddHostedService)도 이미 Realtime·History·OpcServer·Mcp에서 쓰고 있고, + 실시간 PV 구독(ExperionRealtimeService.AddMonitoredItemAsync)도 있습니다. 즉, 폐루프 자동운전이 신규 인프라 없이 기존 + 코드 위에서 실제로 구현 가능합니다. + + ⚠️ 그런데 자동운전 전에 반드시 알아야 할 2가지 + + 코드를 읽다가 발견한 위험 지점입니다: + + 1. 쓰기 경로에 안전 가드가 0건입니다. WriteTagAsync는 들어온 double 값을 그대로 씁니다 — min/max 클램프, rate limit, + 범위 검증, 변화율 제한이 전혀 없습니다. 사람이 UI에서 손으로 쓸 땐 운전원이 최종 안전망이지만, 엔진이 자동으로 쓰는 + 순간 이 안전망이 사라집니다. 잘못된 SV 한 줄이 바로 밸브로 갑니다. + 2. 현재 LLM(MCP)에는 쓰기 도구가 없습니다. 쓰기는 Web UI/HTTP 전용 → 지금은 "사람만 쓸 수 있는" 상태가 유일한 안전 + 경계입니다. 자동운전을 붙이면 이 경계를 넘게 됩니다. + + → 따라서 0순위 작업은 쓰기 가드 레이어입니다. 자동운전 엔진보다 먼저. + + 업데이트된 아키텍처 (폐루프 가능 버전) + + ┌─ Plane 2: LLM 감독 (MCP, 분/이벤트 단위) ──────────────────┐ + │ Step Test 곡선 분석 → θ·τ 추출 │ 파라미터(K,τ) 튜닝 제안 │ + │ 헌팅/Flooding/순도 이상 감지·설명 │ 운전원 Q&A │ + │ │ ※ 밸브 직접 쓰기 X. "엔진 파라미터 저장소"에만 │ + │ │ 제안→운전원 승인 후 반영 │ + ├─────────┼──────────────────────────────────────────────────┤ + │ 🔒 안전 가드 레이어 (신규 0순위) ─ 모든 쓰기 강제 통과 │ + │ hard min/max · 변화율 제한 · dead band · 화이트리스트 │ + │ · 자동 폴백(통신두절→안전SV) · 전 쓰기 감사로그 │ + ├─────────┼──────────────────────────────────────────────────┤ + │ Plane 1: 결정론 보상 엔진 (신규 BackgroundService, 초단위) │ + │ Realtime 구독으로 F 읽기 → Lag(300s) 필터 │ + │ → B_sv(데드타임 1~2분)/D_sv(5분)/P_sv(15~20분) 계산 │ + │ → WriteTagAsync / ControlOp 로 쓰기 (가드 통과 후) │ + └─────────────────────────────────────────────────────────────┘ + + 기존 코드 매핑: + - 읽기: ExperionRealtimeService(실시간 F·온도·수위) + query_pv_history(Step Test 곡선) + - 엔진: 신규 AutoRunService : BackgroundService — 기존 IHostedService 패턴 그대로 + - 쓰기: 기존 IExperionOpcWriteClient — 단, 신규 가드 레이어를 반드시 경유 + - LLM 감독: 기존 MCP 도구 + ReAct 에이전트 모드(이미 있음) + + 핵심 원칙은 그대로입니다 — 빠른 보상은 결정론 엔진(코드)이, LLM은 분 단위 감독·튜닝만. LLM은 밸브를 직접 건드리지 + 않고, 엔진의 파라미터(K·τ·한계값)만 제안하며 그것도 운전원 승인 게이트를 거칩니다. + + 쓰기가 된다는 사실이 그림을 바꿨으니, 무엇부터 만들지 다시 여쭙겠습니다. + +● User declined to answer questions + ⎿  · 추가 쓰기 능력을 확인했습니다. 무엇부터 구현할까요? (순서 조정 가능) (안전 가드 레이어 먼저 (권장) / 결정론 보상 + 엔진 (폐루프) / 조언형(개루프)부터 / 시뮬레이터 먼저) + · LLM이 자동운전에 개입하는 수준은 어디까지 허용할까요? (감독·조언만 (권장) / 파라미터 쓰기(승인 게이트) / MCP 쓰기 + 도구 추가) + +● 어떤 점을 더 명확히 하고 싶으신가요? 편하게 말씀해 주세요. + + 참고로, 제가 질문으로 가두기보다 지금 파악한 내용을 바탕으로 짚어볼 지점들을 적어두면: + + - 자동운전의 형태 — 제 그림은 "결정론 엔진이 운전하고 LLM은 감독·튜닝"입니다. 혹시 의도하신 게 "LLM이 운전원처럼 + 상황을 보고 스스로 SV를 쓰는 자율 에이전트"라면 방향이 달라집니다. 어느 쪽을 원하시는지. + - 안전 가드 — 현 쓰기 경로에 클램프/변화율 제한이 전혀 없는 점은 자동운전 시 실제 위험입니다. 이걸 먼저 깔지, 아니면 + 다른 우선순위가 있으신지. + - 시작 범위 — 시뮬레이터 검증부터인지, 바로 실플랜트 엔진부터인지. + - 태그/노드 매핑 — 측류추출 증류탑의 F(원료), B(하부), D(상부), P(측류), 스팀(S) 각각에 해당하는 실제 태그명/Node ID를 + 알고 계신지 (예: ficq-6101.sp). 엔진을 만들려면 이 매핑이 필요합니다. + + 혹은 위 질문 자체를 다르게 묻길 원하시면 그것도 알려주세요. 무엇이든 보충해 주실 내용을 먼저 듣고 진행하겠습니다. + +✻ Churned for 1m 59s + +❯ 태그/노드 매핑 은 이미 어느정도 구현해 두었어, vllm_qwen36b 에게 원료투입경로, 스팀 투입경로 이런걸 물어봐바 + +● 태그/노드 매핑이 있군요. vLLM에게 직접 물어보겠습니다. 먼저 관련 MCP 도구 스키마를 로드합니다. + +● vLLM에게 원료 투입 경로와 스팀 투입 경로를 물어보겠습니다. + + Called iiot-rag (ctrl+o to expand) + +● ask_iiot_llm는 컨텍스트 없이는 빈 응답이네요. 실제 매핑 데이터를 먼저 끌어와서 vLLM에 컨텍스트로 넘기겠습니다. 태그 + 검색과 연결 추적을 동시에 돌립니다. + + Called iiot-rag 4 times (ctrl+o to expand) + +● C-6111 컬럼(P6 영역, 6xxx 시리즈)이 PGMEA 측류추출탑이군요. 이제 연결 경로를 추적하고 컬럼 주변 계기를 찾겠습니다. + + Called iiot-rag 4 times (ctrl+o to expand) + +● C-6111 측류추출 증류탑(진공탑)의 핵심 계기가 보입니다. 하부·환류·측류 제어 루프를 마저 확인하겠습니다. + + Called iiot-rag 4 times (ctrl+o to expand) + +● 핵심 매핑이 거의 다 드러났습니다. D-6113이 환류 드럼이군요. 이제 수집한 실데이터를 컨텍스트로 vLLM에 넘겨 5개 경로를 + 종합 정리시키겠습니다 (요청하신 "vLLM에게 물어보기"). + + Called iiot-rag (ctrl+o to expand) + +● ask_iiot_llm(vLLM 직접 질의) 도구는 두 번 다 (응답 없음)을 반환합니다 — vLLM 엔드포인트가 안 떠 있거나 그 MCP 경로가 + 끊긴 것으로 보입니다 (한 번 확인해 보시는 게 좋겠습니다). 대신 데이터 기반 도구(find_tags, trace_connections — DB + + LLM이 만든 P&ID 그래프)는 정상 동작했고, 거기서 C-6111 측류추출탑의 실제 매핑을 복원했습니다. + + C-6111 PGMEA 측류추출 증류탑 — 실측 태그 매핑 (P6 영역) + + trace_connections가 돌려준 원료 경로: + P-6101 → FT-6101 → FICQ-6101 → FCV-6101 → E-6103(예열) → C-6111 원료 스프레이 분배기 + + ┌─────┬──────────┬───────────────────────┬──────────────┬───────────────┬──────────────────────────┬────────────┐ + │ # │ 경로 │ 조작변수(MV)/제어 │ 유량 │ 온도 │ 수위/압력 │ 문서상 τ │ + ├─────┼──────────┼───────────────────────┼──────────────┼───────────────┼──────────────────────────┼────────────┤ + │ │ 원료 │ FICQ-6101(SP/OP) → │ │ TI-6111? │ │ 입력신호(L │ + │ F │ 투입 │ FCV-6101 │ FT-6101 │ (예열 E-6103) │ — │ ag 300s │ + │ │ │ │ │ │ │ 필터) │ + ├─────┼──────────┼───────────────────────┼──────────────┼───────────────┼──────────────────────────┼────────────┤ + │ S │ 리보일러 │ 스팀밸브(리보일러 │ FI-6115 │ TI-6111A(BOT) │ PI-6700(스팀압) │ 가장 빠름 │ + │ │ 스팀 │ 듀티) │ │ , TICA-6111A │ │ │ + ├─────┼──────────┼───────────────────────┼──────────────┼───────────────┼──────────────────────────┼────────────┤ + │ B │ 하부 │ 하부 발출 밸브 │ (미확인) │ TI-6111A(BOT) │ LI-6111(하부수위) │ 1~2분 │ + │ │ 제거 │ │ │ │ │ │ + ├─────┼──────────┼───────────────────────┼──────────────┼───────────────┼──────────────────────────┼────────────┤ + │ │ 상부/환 │ FICQ-6113(PV29.9/SP36 │ │ │ LI-6113(D-6113 │ │ + │ D/R │ 류 │ .4) │ FI-6113 │ TI-6111D(TOP) │ 환류드럼), LICA-6113, │ 5분 │ + │ │ │ │ │ │ PI-6111(진공) │ │ + ├─────┼──────────┼───────────────────────┼──────────────┼───────────────┼──────────────────────────┼────────────┤ + │ P │ 측류 │ 측류 추출 밸브 │ FI-6120(PGME │ TI-6111B/C(MI │ LI-6121/6122/6123(제품탱 │ 15~20분 │ + │ │ 제품 │ │ A) │ D) │ 크) │ │ + └─────┴──────────┴───────────────────────┴──────────────┴───────────────┴──────────────────────────┴────────────┘ + + OPC Node 형식: ns=1;s=sinamserver:ficq-6101.sp / .op / .md(MAN=0/AUTO=1) — UI 기본값과 일치. + + 자동운전 엔진에 그대로 꽂히는 그림 + + - 입력(외란/피드): FICQ-6101 원료 유량 → Lag(300s) 필터 → F_clean + - MV 1 (B, τ 1~2분): F_clean → 하부 발출 밸브, LI-6111 수위 제약(Flooding 방지) + - MV 2 (D/R, τ 5분): F_clean → FICQ-6113.sp, LI-6113 드럼 수위 연동 + - MV 3 (P, τ 15~20분): F_clean → 측류 추출 밸브, TI-6111B/C 중간단 온도/순도 보호 + - S: 하부 온도(TI-6111A/TICA-6111A)에 직결 — 가장 빠른 응답 + + 흥미로운 현재 상태: FICQ-6113 PV 29.9 / SP 36.4로 추종 중이고 진공압 PICA-6111 30.4 — 탑이 실제 운전 중인 데이터로 + 보입니다. + + 아직 비어 있는 2칸 (엔진 만들기 전 확정 필요) + + 1. B(하부 제거) 유량계·밸브 태그 — LI-6111 수위는 있는데 발출 유량/밸브 태그가 안 잡힙니다. + 2. P(측류) 추출 밸브 태그 — FI-6120(유량 측정)은 있으나 추출 제어밸브가 미확인. + + 이 두 개는 find_tags로 6112/6114/6116번대를 더 훑거나, C-6111에서 trace_connections downstream를 돌리면 채울 수 + 있습니다. + + 지금 매핑을 (a) 더 파서 빈 칸 2개를 채울까요, 아니면 (b) 이 매핑을 자동운전 엔진 설계 문서/태그 설정으로 정리해 + 드릴까요? 그리고 ask_iiot_llm이 빈 응답인 건 vLLM 서버 상태를 확인해 보시는 걸 권합니다. + +✻ Cooked for 2m 38s + +❯ 아니, 제품 추출 부분은 아직 매핑을 완료하지 않았어, 이건 내가 할거고, 일단, 측류추출-자동운전-플랜.md에 컨셉과 + 선택사항을 모두 기록해줘 + +● 플랜 문서를 작성하겠습니다. 원본 문서와 같은 위치(루트)에 두고, 제품 추출(P) 매핑은 사용자 담당 TODO로 표시하겠습니다. + +● Write(측류추출-자동운전-플랜.md) + +──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Create file + 측류추출-자동운전-플랜.md +╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ + 1 # 측류 추출 증류탑(C-6111) — 로컬 LLM 기반 자동운전 플랜 + 2 + 3 > **목적**: `측류추출-시간지연-적용방식.md`의 시간지연/시차 보상 제어를 ExperionCrawler 시스템 위에서 + 4 > **로컬 LLM(vLLM Qwen)** 과 결합해 자동운전(Autopilot)으로 구현하기 위한 컨셉·아키텍처·선택사항 기록. + 5 > + 6 > 문서 성격: **설계/의사결정 기록**. 구현 착수 전 합의용. 코드 미작성 상태. + 7 + 8 *작성일: 2026-05-22 / 대상: C-6111 PGMEA 진공 측류추출 증류탑 (P6 영역)* + 9 + 10 --- + 11 + 12 ## 0. 핵심 원칙 (가장 중요) + 13 + 14 **LLM을 빠른 제어 루프에 넣지 않는다.** + 15 + 16 `측류추출-시간지연-적용방식.md`가 말하는 "1분/5분/15~20분 지연 보상"은 초 단위로 결정론적으로 돌아야 + 17 하는 빠른 루프다. 여기에 LLM을 직접 넣으면: + 18 + 19 | 문제 | 영향 | + 20 |------|------| + 21 | 비결정성 | 같은 입력에 다른 출력 → 밸브 제어에 치명적 | + 22 | 지연(latency) | 토큰 생성 수 초 → Flooding 즉시 대응 불가 | + 23 | 환각 | 잘못된 SV 한 줄이 바로 밸브로 → 측류 순도 영역 파괴 | + 24 + 25 → **결론**: 빠른 보상은 **결정론 엔진(코드)** 이 담당하고, **LLM은 분 단위 감독·튜닝·조언만** 한다. + 26 이것이 LLM을 실공정에 붙이는 유일하게 안전한 형태다. + 27 + 28 --- + 29 + 30 ## 1. 2-Plane 아키텍처 + 31 + 32 ``` + 33 ┌─ Plane 2: LLM 감독 (MCP, 분/이벤트 단위, 느림) ───────────────┐ + 34 │ · Step Test 곡선 분석 → θ(데드타임)·τ(시상수) 자동 추출 │ + 35 │ · 파라미터(K, τ, 한계값) 튜닝 제안 │ + 36 │ · 헌팅 / Flooding / 순도 드리프트 이상 감지·자연어 설명 │ + 37 │ · 운전원 Q&A ("왜 제품밸브가 천천히 열려요?") │ + 38 │ │ ※ 밸브 직접 쓰기 금지. "엔진 파라미터 저장소"에만 │ + 39 │ │ 제안 → 운전원 승인 후 반영 │ + 40 ├─────────┼──────────────────────────────────────────────────────┤ + 41 │ 🔒 안전 가드 레이어 (신규, 0순위) ─ 모든 쓰기가 강제 통과 │ + 42 │ hard min/max · 변화율(rate) 제한 · dead band · 태그 화이트 │ + 43 │ 리스트 · 통신두절→안전SV 폴백 · 전 쓰기 감사로그 │ + 44 ├─────────┼──────────────────────────────────────────────────────┤ + 45 │ Plane 1: 결정론 보상 엔진 (신규 BackgroundService, 초 단위) │ + 46 │ Realtime 구독으로 F(원료유량) 읽기 │ + 47 │ → Lag(τ=300s) 필터로 헌팅 제거 → F_clean │ + 48 │ → B_sv(데드타임 1~2분) / D_sv(5분) / P_sv(15~20분) 계산 │ + 49 │ → 가드 통과 후 WriteTagAsync / ControlOp 로 쓰기 │ + 50 └────────────────────────────────────────────────────────────────┘ + 51 읽기: ExperionRealtimeService · query_pv_history + 52 쓰기: IExperionOpcWriteClient (가드 레이어 경유 필수) + 53 ``` + 54 + 55 --- + 56 + 57 ## 2. 보상 제어 수식 (Plane 1 — 결정론, LLM 아님) + 58 + 59 원본 문서 §2·§4 기준. + 60 + 61 - **1차 지연(Lag) 필터** (이산): `y[k] = y[k-1] + (Δt/τ) · (x[k] − y[k-1])` + 62 - **데드타임(Dead Time)**: 링버퍼로 N틱 지연 + 63 - **헌팅 제거**: 원료 FT 신호 직후 Lag 필터 τ=**300초(3~5분)** 1개 (원본 §4.1 "1순위 대책") + 64 + 65 | MV | 제어 대상 | τ / 데드타임 | 목적 | + 66 |----|----------|-------------|------| + 67 | B | 하부 제거량 | 1~2분 | 탑 넘침(Flooding) 즉시 방지 | + 68 | D/R | 상부 제거량/환류 | 5분 | 압력/조성 안정화 | + 69 | P | 측류 제품 추출 | 15~20분 | 초고순도 PGMEA 품질 보호 (가장 보수적) | + 70 | S | 리보일러 스팀 | 가장 빠름(수초~수분) | 하부 온도 직결 | + 71 + 72 추가 안전요소(원본 §4.2/§4.3): 각 PID 블록 **dead band 0.5~1.0%**, 원료탱크 **Surge Control**(P-Gain↓ I-Time↑). + 73 + 74 --- + 75 + 76 ## 3. 현 시스템에서 확인된 능력 (재사용 자산) + 77 + 78 ### 3.1 쓰기 (이미 구현됨) + 79 | 기능 | 구현 | 엔드포인트 | + 80 |------|------|-----------| + 81 | SP/OP 직접 쓰기 | `ExperionOpcWriteClient.WriteTagAsync(cfg, nodeId, value)` | `POST /api/experion/write` | + 82 | MAN/AUTO 모드 | `SetModeAsync(cfg, nodeId, "MAN"\|"AUTO")` | `POST /api/experion/mode` | + 83 | 통합 제어 (MD→MAN → OP쓰기 → AUTO복귀) | `ControlOp(TagName, OpValue, RestoreAuto)` | `POST /api/experion/con + trol` | + 84 | UI | "OPC UA Write" 탭 (#15) | `index.html #pane-write` | + 85 + 86 ### 3.2 읽기 + 87 - `ExperionRealtimeService` — 실시간 PV 구독 (`AddMonitoredItemAsync`), `IHostedService` + 88 - `query_pv_history` (MCP) / `ExperionHistoryController` — Step Test용 시계열 + 89 + 90 ### 3.3 백그라운드 서비스 패턴 + 91 - `IHostedService`/`AddHostedService` 이미 Realtime·History·OpcServer·Mcp에서 사용 중 + 92 → 신규 `AutoRunService : BackgroundService`가 기존 패턴에 그대로 들어감 + 93 + 94 ### 3.4 LLM 감독용 MCP 도구 (기존) + 95 - `query_pv_history`, `find_tags`, `trace_connections`, `active_alarms`, `query_events`, + 96 `summarize_events`, `generate_status_report`, ReAct 에이전트 모드(구현됨) + 97 + 98 --- + 99 + 100 ## 4. ⚠️ 안전 관련 발견 사항 (자동운전 전 반드시 처리) + 101 + 102 1. **쓰기 경로에 안전 가드가 0건.** `WriteTagAsync`는 들어온 double을 그대로 쓴다 — + 103 min/max 클램프·rate limit·범위 검증·변화율 제한 전무. 사람이 UI에서 손으로 쓸 땐 운전원이 + 104 최종 안전망이지만, **엔진이 자동으로 쓰는 순간 안전망이 사라진다.** → **0순위: 가드 레이어.** + 105 2. **현재 LLM(MCP)에는 쓰기 도구가 없다.** 쓰기는 Web UI/HTTP 전용 → 지금은 "사람만 쓸 수 있는" + 106 상태가 유일한 안전 경계. 자동운전을 붙이면 이 경계를 넘게 됨 → 신중한 권한 설계 필요. + 107 3. **`ask_iiot_llm`(vLLM 직접 질의) MCP 도구가 빈 응답.** 2회 시도 모두 `(응답 없음)`. + 108 vLLM 엔드포인트 상태/연결 점검 필요. (단 `find_tags`/`trace_connections`는 정상 동작.) + 109 + 110 --- + 111 + 112 ## 5. 태그/노드 매핑 (실측 — `find_tags`·`trace_connections` 기반) + 113 + 114 `trace_connections`가 돌려준 원료 경로: + 115 ``` + 116 P-6101(원료펌프) → FT-6101 → FICQ-6101 → FCV-6101 → E-6103(예열) → C-6111 원료 스프레이 분배기 + 117 ``` + 118 + 119 | # | 경로 | 조작변수(MV)/제어 | 유량 | 온도 | 수위/압력 | τ | + 120 |---|------|------------------|------|------|----------|---| + 121 | **F** | 원료 투입 | **FICQ-6101**(SP/OP)→FCV-6101 | FT-6101 | (E-6103 예열) | — | 입력신호(Lag 300s) | + 122 | **S** | 리보일러 스팀 | 스팀밸브(리보일러 듀티) | **FI-6115** | TI-6111A(BOT), TICA-6111A | PI-6700(스팀압) | + 가장 빠름 | + 123 | **B** | 하부 제거 | 하부 발출 밸브 *(밸브태그 미확인)* | (미확인) | TI-6111A(BOT) | **LI-6111**(하부수위) | 1 + ~2분 | + 124 | **D/R** | 상부/환류 | **FICQ-6113**(PV29.9/SP36.4) | FI-6113 | TI-6111D(TOP) | **LI-6113**(D-6113 환류드럼), + LICA-6113, PI-6111(진공), PICA-6111 | 5분 | + 125 | **P** | 측류 제품 | **🔲 사용자 매핑 예정** | FI-6120(PGMEA) | TI-6111B/C(MID) | LI-6121/6122/6123(제품탱크) + | 15~20분 | + 126 + 127 - OPC Node 형식: `ns=1;s=sinamserver:ficq-6101.sp` / `.op` / `.md`(MAN=0/AUTO=1) + 128 - 현재 운전 데이터 흔적: FICQ-6113 PV 29.9 / SP 36.4 추종 중, 진공압 PICA-6111 30.4 → 탑 가동 중으로 추정 + 129 + 130 ### 5.1 미완료 매핑 (담당 구분) + 131 - **P(측류 제품 추출) 경로 매핑 — 사용자가 직접 진행 예정** (본 플랜에서는 보류) + 132 - B(하부 제거) 발출 유량계·밸브 태그 — `find_tags`(6112/6114/6116번대) 또는 + 133 C-6111 `trace_connections downstream`로 보강 가능 (착수 시 확정) + 134 + 135 --- + 136 + 137 ## 6. 선택사항 (의사결정 대기) + 138 + 139 ### 6.1 시작 지점 — "무엇부터 구현하나" + 140 | 옵션 | 내용 | 비고 | + 141 |------|------|------| + 142 | **A. 안전 가드 레이어 먼저** | 쓰기 경로에 클램프·변화율·dead band·화이트리스트·감사로그 추가 | **권장**. 자 + 동운전 전제조건이며 수동 쓰기도 즉시 안전해짐 | + 143 | B. 결정론 보상 엔진(폐루프) | `AutoRunService`: F구독→Lag/데드타임→B/D/P SV 계산→가드 경유 쓰기 | 실제 자동운 + 전 핵심 | + 144 | C. 조언형(개루프)부터 | 엔진은 권고 SV만 계산·표시, 쓰기는 운전원이 클릭 승인 | 로직 안전검증 후 폐루프 전환 + | + 145 | D. 시뮬레이터 먼저 | FOPDT 증류탑 디지털 트윈으로 실플랜트 전 검증 | 현 브랜치 `sim/...` 와 자연스러움 | + 146 + 147 ### 6.2 LLM 개입 수준 — "LLM 권한 어디까지" + 148 | 옵션 | 내용 | 비고 | + 149 |------|------|------| + 150 | **가. 감독·조언만** | Step Test 분석·이상 설명·파라미터 제안만. 밸브/쓰기 절대 안 함 | **권장**. 가장 안전 | + 151 | 나. 파라미터 쓰기(승인 게이트) | LLM이 K·τ 등 엔진 파라미터 변경 제안 → 운전원 승인 후 반영. 밸브 직접 제어는 + 여전히 엔진만 | 적응 튜닝 가능 | + 152 | 다. MCP 쓰기 도구 추가 | LLM이 MCP로 직접 SV/모드 쓰기(가드 경유) | 유연하나 위험 큼 — 신중 적용 | + 153 + 154 > 현재 권장 조합: **6.1-A (가드 먼저) + 6.2-가 (LLM 감독만)** 로 시작 → 검증 후 단계적 확장. + 155 + 156 --- + 157 + 158 ## 7. 단계별 로드맵 + 159 + 160 - **Phase 0 — 안전 가드 레이어**: 쓰기 경로 클램프/rate/dead band/화이트리스트/폴백/감사로그. (전제조건) + 161 - **Phase A — 조언형(개루프)**: 보상 엔진이 권고 SV 계산·대시보드 표시 + LLM Step Test 분석기. + 162 DCS 쓰기는 운전원 수동 승인. 위험 최소. + 163 - **Phase B — 감독형 폐루프**: `AutoRunService`가 가드 안에서 SV 자동 쓰기. LLM은 파라미터만 제안(승인 게이트). + 164 - **Phase C — 자가 튜닝**: LLM이 Step Test 시점 제안 → 자동 피팅 → 시뮬레이터 A/B 검증 후 반영. + 165 + 166 --- + 167 + 168 ## 8. LLM이 잘하는 4가지 역할 (Plane 2 상세) + 169 + 170 1. **Step Test 분석 (강력 추천)** — 원본 §3. 유량 스텝 후 하부/상부/환류드럼/측류 온도·Analyzer 곡선을 + 171 `query_pv_history`로 뽑아 LLM에 주면 구간별 데드타임 θ·시상수 τ를 읽어냄 (결정론 곡선피팅으로 교차검증) + 172 → 그 값이 Plane 1 파라미터가 됨. + 173 2. **파라미터 튜닝 조언** — 처리량·원료 조성 드리프트 시 K·τ 재조정 제안. + 174 3. **이상 상황 서술** — "FT 헌팅 5분째 ±5% 지속, 필터 τ 300→420초 권장" 식 자연어 진단. + 175 4. **운전원 코칭** — 신입에게 "왜 P는 15분 늦게 여는가"를 문서 근거로 설명. +✻ Cooked for 2m 38s + +❯ 아니, 제품 추출 부분은 아직 매핑을 완료하지 않았어, 이건 내가 할거고, 일단, 측류추출-자동운전-플랜.md에 컨셉과 + 선택사항을 모두 기록해줘 + +● 플랜 문서를 작성하겠습니다. 원본 문서와 같은 위치(루트)에 두고, 제품 추출(P) 매핑은 사용자 담당 TODO로 표시하겠습니다. + +● Write(측류추출-자동운전-플랜.md) + ⎿  Wrote 196 lines to 측류추출-자동운전-플랜.md + 1 # 측류 추출 증류탑(C-6111) — 로컬 LLM 기반 자동운전 플랜 + 2 + 3 > **목적**: `측류추출-시간지연-적용방식.md`의 시간지연/시차 보상 제어를 ExperionCrawler 시스템 위에서 + 4 > **로컬 LLM(vLLM Qwen)** 과 결합해 자동운전(Autopilot)으로 구현하기 위한 컨셉·아키텍처·선택사항 기록. + 5 > + 6 > 문서 성격: **설계/의사결정 기록**. 구현 착수 전 합의용. 코드 미작성 상태. + 7 + 8 *작성일: 2026-05-22 / 대상: C-6111 PGMEA 진공 측류추출 증류탑 (P6 영역)* + 9 + 10 --- + … +200 lines (ctrl+o to expand) + +● 측류추출-자동운전-플랜.md를 루트(측류추출-시간지연-적용방식.md 옆)에 작성했습니다. + + 기록된 내용: + + - §0 핵심 원칙 — LLM을 빠른 제어 루프에 넣지 않음 + - §1 2-Plane 아키텍처 — 결정론 엔진(초 단위) + LLM 감독(분 단위) + 안전 가드 레이어 다이어그램 + +──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Settings Status Config Usage Stats + + Session + + + Total cost: $2.01 + Total duration (API): 7m 3s + Total duration (wall): 21m 49s + Total code changes: 197 lines added, 0 lines removed + Usage by model: + Usage by model: + Usage by model: + 1 # 측류 추출 증류탑(C-6111) — 로컬 LLM 기반 자동운전 플랜 + 2 + 3 > **목적**: `측류추출-시간지연-적용방식.md`의 시간지연/시차 보상 제어를 ExperionCrawler 시스템 위에서 + 4 > **로컬 LLM(vLLM Qwen)** 과 결합해 자동운전(Autopilot)으로 구현하기 위한 컨셉·아키텍처·선택사항 기록. + 5 > + 6 > 문서 성격: **설계/의사결정 기록**. 구현 착수 전 합의용. 코드 미작성 상태. + 7 + 8 *작성일: 2026-05-22 / 대상: C-6111 PGMEA 진공 측류추출 증류탑 (P6 영역)* + 9 + 10 --- + … +200 lines (ctrl+o to expand) + +❯ /usage + ⎿ Settings dialog dismissed + +● 측류추출-자동운전-플랜.md를 루트(측류추출-시간지연-적용방식.md 옆)에 작성했습니다. + + 기록된 내용: + - §0 핵심 원칙 — LLM을 빠른 제어 루프에 넣지 않음 + - §1 2-Plane 아키텍처 — 결정론 엔진(초 단위) + LLM 감독(분 단위) + 안전 가드 레이어 다이어그램 + - §2 보상 수식 — Lag 필터/데드타임, MV별 τ(B 1~2분 / D 5분 / P 15~20분 / S 가장 빠름) + - §3 재사용 자산 — 기존 쓰기 클라이언트·엔드포인트·BackgroundService 패턴·MCP 도구 + - §4 안전 발견 — 쓰기 가드 0건, LLM 쓰기 도구 없음, ask_iiot_llm 빈 응답 + - §5 실측 태그 매핑 — F/S/B/D·R 매핑 표 + P는 "🔲 사용자 매핑 예정"으로 보류 표시 + - §6 선택사항 — 6.1 시작 지점(A~D), 6.2 LLM 권한(가~다), 권장 조합 명시 + - §7 로드맵 — Phase 0/A/B/C + - §8 LLM 4대 역할, §9 미해결 항목(P 매핑 = 사용자 담당으로 명기) + + 말씀대로 제품 추출(P) 경로 매핑은 사용자 진행 예정으로 §5.1과 §9에 담당 구분해 두었습니다. P 매핑을 마치시면 + 알려주시면 표의 해당 칸을 채우겠습니다. + +✻ Sautéed for 1m 11s + +❯ PID loop의 튜닝을 LLM이 보조할 수 있는 방법은?, 이걸 학습으로 플랜트 상황에 맞게 튜닝 가능할까? + +● 좋은 질문입니다. 두 부분으로 나눠서 — (1) LLM이 PID 튜닝을 어떻게 보조하나, (2) 그걸 학습으로 플랜트에 맞게 적응시키는 + 게 현실적인가. + + 1. LLM의 PID 튜닝 보조 — 역할 분담이 핵심 + + 자동운전 플랜의 §0 원칙과 동일합니다: LLM은 숫자를 만들지 않습니다. 정확한 산수와 결정성이 필요한 부분(모델 식별, 튜닝 + 공식 계산)은 결정론 수학이 하고, LLM은 그 위에서 판단·진단·번역·오케스트레이션을 합니다. + + ┌──────────────────────────────────────────────────┬─────────────────────────┬────────────────────────────────────┐ + │ 작업 │ 담당 │ 이유 │ + ├──────────────────────────────────────────────────┼─────────────────────────┼────────────────────────────────────┤ + │ Bump/Step Test 응답에서 FOPDT 모델(K, τ, θ) 식별 │ 수학(최소제곱 곡선피팅) │ LLM 산수는 부정확·비결정 │ + ├──────────────────────────────────────────────────┼─────────────────────────┼────────────────────────────────────┤ + │ 튜닝 공식 적용 → Kc, τI, τD 계산 │ 수학(SIMC/Lambda 등) │ 동일 │ + ├──────────────────────────────────────────────────┼─────────────────────────┼────────────────────────────────────┤ + │ 어떤 튜닝 규칙·목표(λ)를 쓸지 결정 │ LLM │ 루프 용도·강건성 트레이드오프 판단 │ + ├──────────────────────────────────────────────────┼─────────────────────────┼────────────────────────────────────┤ + │ 루프 분류 (유량/수위/온도/압력) → 튜닝 철학 선택 │ LLM │ 도메인 지식 매칭 │ + ├──────────────────────────────────────────────────┼─────────────────────────┼────────────────────────────────────┤ + │ 트렌드에서 병증 진단 (발진/둔감/stiction/windup) │ LLM │ 패턴 해석·서술 │ + ├──────────────────────────────────────────────────┼─────────────────────────┼────────────────────────────────────┤ + │ 운전원 언어 ↔ 파라미터 번역 │ LLM │ "오버슈트가 심해" → "Kc↓ 또는 τI↑" │ + ├──────────────────────────────────────────────────┼─────────────────────────┼────────────────────────────────────┤ + │ 재튜닝 시점 판단·근거 로깅 │ LLM │ 이벤트 단위 의사결정 │ + └──────────────────────────────────────────────────┴─────────────────────────┴────────────────────────────────────┘ + + 표준 워크플로우 (LLM이 지휘) + + ① LLM: 이 루프는 무엇? (예: TICA-6111A = 온도, 품질직결, 느림) + → 튜닝 철학 결정 (Lambda/SIMC, λ 보수적으로) + ② 수학: Bump Test 수행 → 응답곡선 → FOPDT (K,τ,θ) 최소제곱 피팅 + ③ LLM: 피팅 품질 검증 ("R²낮음, 노이즈/외란 의심 → 재시험 권고") + ④ 수학: SIMC 공식으로 Kc,τI,τD 산출 + ⑤ LLM: 결과 설명 + 안전범위 점검 → 운전원 승인 게이트 + ⑥ 가드 레이어 경유 적용 (플랜 §1 그대로) + + 루프별로 튜닝 철학이 다른데, 이게 LLM의 진짜 가치 + + ┌────────────────────────┬───────────────────────────────────┬──────────────────────────────┐ + │ 루프 (이 플랜트) │ 철학 │ LLM이 자동 선택 │ + ├────────────────────────┼───────────────────────────────────┼──────────────────────────────┤ + │ FICQ-6101 유량 │ 빠름, Lambda 작게, P+I만 (D 금지) │ 노이즈 많음 → 적극적 D 배제 │ + ├────────────────────────┼───────────────────────────────────┼──────────────────────────────┤ + │ LI-6111 / LI-6113 수위 │ Averaging/Surge (느슨하게) │ 원본 문서 §4.3과 직결 — 완충 │ + ├────────────────────────┼───────────────────────────────────┼──────────────────────────────┤ + │ TICA-6111A 온도 │ 지배동특성, 보수적 λ │ 품질직결 → 강건성 우선 │ + ├────────────────────────┼───────────────────────────────────┼──────────────────────────────┤ + │ PICA-6111 진공 │ 비교적 빠름 │ — │ + └────────────────────────┴───────────────────────────────────┴──────────────────────────────┘ + + 그리고 "튜닝 대상"이 둘이라는 점 + + 1. 기저 PID 루프 (Kc, τI, τD) — 위 고전 튜닝 + 2. 피드포워드 보상 파라미터 (Lag τ, 데드타임, 게인 K_D/K_B/K_P) — 자동운전 플랜의 Step Test 분석이 바로 이걸 식별 + + LLM은 둘 다 보조하며, Step Test 곡선 해석은 두 작업의 공통 입력입니다. + + --- + 2. "학습으로 플랜트에 맞게" — 가능하다, 단 메커니즘 선택이 전부 + + 가능합니다. 하지만 "강화학습으로 증류탑을 학습"은 실플랜트에선 위험·비현실적입니다(샘플 비효율 + 탐색 = 나쁜 SV 투입). + 안전한 것부터 야심찬 것 순으로 사다리를 제시합니다: + + ┌──────┬──────────────────────────────────────────────────────────┬──────────────┬────────────────────────────────┐ + │ 레벨 │ 방법 │ "학습" 성격 │ 현실성 │ + ├──────┼──────────────────────────────────────────────────────────┼──────────────┼────────────────────────────────┤ + │ L1 │ 주기적 재식별 (Bump Test 재실행 → FOPDT 재피팅 → 재튜닝) │ ML 아님, │ ★★★ 가장 실용·안전 │ + │ │ │ 적응 │ │ + ├──────┼──────────────────────────────────────────────────────────┼──────────────┼────────────────────────────────┤ + │ L2 │ 게인 스케줄링 (처리량·등급별 다점 튜닝 후 보간) │ 룩업 학습 │ ★★★ 비선형 대응 정석 │ + ├──────┼──────────────────────────────────────────────────────────┼──────────────┼────────────────────────────────┤ + │ L3 │ 고전 적응제어 (RLS 온라인 추정 → Self-Tuning) │ 온라인 추정 │ ★★ 검증됨(Åström), 진동주의 │ + ├──────┼──────────────────────────────────────────────────────────┼──────────────┼────────────────────────────────┤ + │ L4 │ 베이지안 최적화 (성능비용 IAE/오버슈트를 소수 실험으로 │ 데이터기반 │ ★★ 트윈 우선, 샘플효율 최고 │ + │ │ 최소화) │ ML │ │ + ├──────┼──────────────────────────────────────────────────────────┼──────────────┼────────────────────────────────┤ + │ L5 │ 강화학습(RL) │ 정책학습 │ ★ 시뮬레이터 전용, 실플랜트 │ + │ │ │ │ 금지 │ + └──────┴──────────────────────────────────────────────────────────┴──────────────┴────────────────────────────────┘ + + 추가로 탐색 없이 안전하게 학습하는 두 가지가 이 시스템에 특히 잘 맞습니다: + + - 섀도/추천 모드 학습: 엔진이 "이렇게 하겠다"를 계산만 하고, 실제 운전원 조치 + 결과를 로깅 → 둘의 격차를 학습. + "운전원은 항상 P밸브를 우리 모델보다 느리게 연다" → 모델 보정. 탐색 위험 0, 지도학습. + - CLPM (폐루프 성능 모니터링): Harris 지수(최소분산 대비)·발진 감지·밸브 stiction 진단을 일상 운전 데이터만으로 수행 → + 루프 건강도 점수화 → 튜닝 열화 시 자동 플래그. 이게 재튜닝의 트리거가 되고, LLM이 우선순위를 서술. + + 추천 적응 루프 (이 플랜트 기준) + + 일상 데이터 → CLPM(Harris·stiction·발진) → LLM이 "열화 루프" 식별·서술 + → 게인 스케줄(L2) 해당 점 벗어남? → Bump Test 재식별(L1) + → 트윈에서 베이지안 최적화(L4)로 미세조정 → 운전원 승인 → 가드 경유 반영 + → 결과 로깅 → 섀도 학습으로 모델 보정 (순환) + + 반드시 지켜야 할 제약 (정직하게) + + - 디지털 트윈 우선 — 현 브랜치 sim/... 활용. L4/L5는 실플랜트 전 트윈 검증 필수. + - 식별성(Identifiability) — 충분한 가진(excitation) 없으면 모델 못 만듦. 고순도 탑은 비선형·느림 → 작은 선형모델은 + 국소적으로만 유효 → 그래서 L2 게인 스케줄링이 핵심. + - 안전 제약 — 모든 적응은 플랜 §0 가드 레이어 하드 한계 안에서만. 탐색형(L4/L5)엔 trust-region 필수. + - LLM은 비용함수·실험설계·수렴판정·가드를 담당하고, 최적화 수치는 알고리즘이 낸다 — 여기서도 §0 원칙 유지. + - 이 C-6111은 품질직결·느림·비선형 = 가장 보수적으로 다뤄야 하는 케이스. L1+L2+섀도부터, L4는 트윈에서만. + + --- + 요약: LLM은 PID 튜닝의 지휘자·진단가·번역가로 강력하고(수치는 결정론 수학이 산출), 플랜트 적응 학습도 가능하되 RL이 + 아니라 재식별+게인스케줄링+베이지안최적화+섀도학습+CLPM 조합이 안전하고 현실적인 답입니다. + + 이 내용을 자동운전 플랜 문서에 "§10. PID 튜닝 보조 & 적응 학습" 섹션으로 추가해 둘까요? + +✻ Brewed for 1m 10s + +❯ 좀더 얘기를 하고 문서를 작성하자, + + 내가 알고있는것은 밸브의 사이즈, 배관의종류, 컨트롤밸브의 CV 값과 CV 커브, 플로우미터의 유량범위 등의 물리적인 + 데이터를 가지고 있다면, 결정론적인 부분을 이것으로 프로그램화 하고, LLM은 실제로 무엇을 할 수있다는거야? + +● 아주 정확한 지점을 찌르셨습니다. 솔직하게 답하면 — 그 물리 데이터를 가지고 있다면, 제어 수학에서 LLM이 할 일은 오히려 + 크게 줄어듭니다. 그게 맞고, 그게 좋은 겁니다. 하나씩 정리하죠. + + 1. 물리 데이터로 결정론화되는 부분 (LLM 불필요) + + 말씀하신 데이터는 사실 "데이터 피팅으로 추정"해야 했던 것들을 계산으로 바꿔버립니다: + + ┌───────────────────────────────────┬─────────────────────────────────────────────┬────────────────────┐ + │ 물리 데이터 │ 계산되는 결정론 모델 │ 이전엔 뭐로 구했나 │ + ├───────────────────────────────────┼─────────────────────────────────────────────┼────────────────────┤ + │ 컨트롤밸브 Cv + Cv 커브(설치특성) │ OP(%) → 유량 관계, 밸브 게인 dQ/dOP │ Step Test 식별 │ + ├───────────────────────────────────┼─────────────────────────────────────────────┼────────────────────┤ + │ 배관 종류·구경·길이 │ ΔP·마찰, 이송 데드타임 θ = 관내체적/유량 │ Step Test로 θ 측정 │ + ├───────────────────────────────────┼─────────────────────────────────────────────┼────────────────────┤ + │ 드럼/트레이 홀드업 체적 │ 체류시간 τ = 체적/유량 (D-6113 환류드럼 등) │ Step Test로 τ 측정 │ + ├───────────────────────────────────┼─────────────────────────────────────────────┼────────────────────┤ + │ 플로우미터 레인지 │ 스케일링·분해능·노이즈 플로어 │ — │ + └───────────────────────────────────┴─────────────────────────────────────────────┴────────────────────┘ + + → 즉 자동운전 플랜의 B(하부)·D/R(상부) 타이밍은 하이드롤릭 홀드업 = 체적/유량 으로 직접 계산됩니다. 밸브 게인도 Cv + 커브 미분으로 나옵니다. 여기에 LLM을 넣을 이유가 없습니다. 모델기반 튜닝(SIMC/Lambda)도 이 물리모델로 바로 Kc·τI가 + 떨어집니다. 이 부분은 그냥 프로그램하세요. 제 처음 답에서 "Step Test로 식별"이라던 것의 상당 부분이 당신의 경우 + 불필요해집니다. + + 2. 그런데 물리 데이터가 못 주는 3가지 + + 여기가 핵심입니다. Cv·배관·유량범위는 하이드롤릭(얼마나 흐르나) 을 줍니다. 그런데 증류탑의 진짜 어려움은 거기가 + 아닙니다. + + (가) 분리/조성 동특성 — 당신 데이터에 없음. + 원본 문서의 "P(측류)는 15~20분으로 가장 느리다" 는 배관 이송이 아니라 트레이별 물질·열 홀드업 + 기액평형(VLE)으로 새 + 조성이 자리잡는 시간입니다. 홀드업 체적은 당신이 알지만, 상대휘발도·트레이 효율·VLE는 Cv 커브에 없습니다. 이 P 지연은 + 물리 데이터만으론 안 나오고, 단별(stage) 분리 모델이 필요합니다. → B·D는 물리로 계산되지만, P는 안 됩니다. 이게 + 경계선입니다. + + (나) 모델-플랜트 불일치(드리프트). Cv 커브는 깨끗한 신품 설계값입니다. 실제론 밸브 stiction·시트 마모, E-6103 파울링, + 트레이 효율 저하로 시간에 따라 어긋납니다. 물리모델은 "어제의 진실"이고 플랜트는 오늘 다릅니다. + + (다) 목적·맥락·예외. 무엇이 "잘 도는" 건지(회수율 최대 vs 에너지 최소 vs 순도 사수), 등급 변경, 기동/정지, 계기 고장, + 상류 외란 — 정적 물리 데이터엔 전혀 없습니다. + + 3. 그래서 LLM이 실제로 하는 일 (과장 없이) + + 물리모델이 좋을수록 LLM은 제어 경로에서 빠지고 가장자리로 이동합니다. 솔직한 목록: + + ┌────────────────────┬───────────────────────────────────────────────────────────────────┬───────────────────────┐ + │ LLM 역할 │ 구체적으로 │ 정직한 가치 │ + ├────────────────────┼───────────────────────────────────────────────────────────────────┼───────────────────────┤ + │ ① 커미셔닝 보조 │ 밸브 데이터시트·Cv 커브·배관 스펙을 파싱해 결정론 엔진의 │ ★★ 즉시 유용. "물리는 │ + │ │ config/코드로 조립, Cv 값 정합성 점검 │ 결정론" 철학 그대로 │ + ├────────────────────┼───────────────────────────────────────────────────────────────────┼───────────────────────┤ + │ ② 데이터 │ 물리예측 유량 vs 실측 잔차 계산은 수학, "이 OP·ΔP에서 8% 미달 → │ │ + │ 정합(드리프트 │ 밸브 파울링/마모 의심" 해석·재교정 트리거는 LLM │ ★★ (나) 해결 │ + │ 진단) │ │ │ + ├────────────────────┼───────────────────────────────────────────────────────────────────┼───────────────────────┤ + │ ③ 소프트센서 보조 │ 측정 안 되는 조성을 온도(TI-6111B/C)로 추론, 분석기 결측 보간 │ ★ (가) 보완(완전 해결 │ + │ │ │ 아님) │ + ├────────────────────┼───────────────────────────────────────────────────────────────────┼───────────────────────┤ + │ ④ 감독형 예외 처리 │ 엔진이 프로그램 안 된 상황(기동·등급변경·상류 업셋·계기고장)에서 │ ★★★ 물리 침묵 영역 │ + │ │ 판단·완화 │ │ + ├────────────────────┼───────────────────────────────────────────────────────────────────┼───────────────────────┤ + │ ⑤ 운전원 │ 의도/경제목표 → SV·제약으로 번역, "왜 이렇게 도는지" 설명 │ ★★★ 물리 침묵 영역 │ + │ 인터페이스 │ │ │ + ├────────────────────┼───────────────────────────────────────────────────────────────────┼───────────────────────┤ + │ ⑥ 교차 데이터 융합 │ 알람+이벤트+랩분석+정비이력+물리잔차를 엮어 진단 │ ★★★ 기존 MCP 도구 │ + │ │ │ 활용 │ + └────────────────────┴───────────────────────────────────────────────────────────────────┴───────────────────────┘ + + 4. 핵심 원리 (한 줄) + + ▎ LLM의 가치는 물리모델 품질에 반비례합니다. 당신처럼 물리를 잘 잡을수록 LLM은 제어 산수에서 사라지고 — ③ 못 측정하는 + ▎ 조성, ④ 프로그램 안 된 예외, ⑤ 사람 인터페이스, ⑥ 교차 진단, ①커미셔닝으로 옮겨갑니다. 이게 정상이고 안전한 + ▎ 모습입니다. + + --- + 문서로 넘어가기 전에 같이 정리하고 싶은 게 몇 가지 있습니다: + ▎ 모습입니다. + + --- + 문서로 넘어가기 전에 같이 정리하고 싶은 게 몇 가지 있습니다: + + 1. 분리/조성(가) 모델을 어디까지 갈 건가? — P 지연을 (a) 그냥 보수적 고정 τ(15~20분)로 두고 안 건드릴지, (b) 간이 + 트레이/홀드업 모델을 세울지, (c) 운전데이터 기반 경험모델로 둘지. 이게 LLM 역할 ③의 깊이를 결정합니다. + 2. 물리 데이터의 형태 — Cv 커브가 표/수식/데이터시트 PDF 중 무엇인가요? 역할 ①(LLM이 config로 조립)의 실현성이 여기 + 달려 있습니다. + 3. LLM을 "제어 보조"로 보시는지 "운전 보조(예외·인터페이스)"로 보시는지 — 위 ②④⑤⑥ 중 어디에 무게를 두실지에 따라 문서 + 구조가 달라집니다. + + 이 세 가지에 대한 생각을 들려주시면, 그걸 반영해서 플랜 문서에 섹션을 작성하겠습니다. + +✻ Baked for 1m 17s + +❯ 내가 생각하는 방향은 이거야 + 1. 결정론이든, llm이든 목표 설정값을 연산---> Experion 서버에 전달 + 2. Experion 서버에서 프로그램을 해서, 전달된 값을 화면상(Operator Station 모니터링 HMI)에 PID Loop 표시에 제안한 + SP값을 표시 + 3. 운전원이 여기에 익숙해지고, 신뢰가 생긴다면, mode 변경, -> Set Point 변경 주도권 가져옴 + 4. PID LOOP의 Hunting이 심하다고 판단되는 기준을 넘으면, 매뉴얼 모드로 변경, 제어출력(OP)를 가지고 변경하면서 안정권 + 유지 + + 꼭 DCS 컨트롤러의 PID 제어기의 파라미터를 교정하는것이 아니어도 매뉴얼 모드에서, op 변경만 가지고도 가능할까? 하는 + 의문에서 시작된 것이 이 세션의 시작 목적이기도 함---> 당연히 안전장치(rate제한, 절대값 제한, 현재 유량 범위 감안 밸브 + 변동폭 제한, 기본 컨트롤러에 설정된 ESD, IL 동작 이 보증된 상태에서 임 + +● 이제 핵심이 명확해졌습니다. 그리고 시작 질문 — "PID 파라미터를 안 건드리고, MANUAL에서 OP만으로 안정화 가능한가?" — 에 + 정직하게 답하면: 경우에 따라 Yes, 그리고 그게 오히려 브라운필드에서 더 현실적입니다. 다만 결정적인 단서가 있습니다. + + 1. 시작 질문에 대한 직답 + + 핵심은 헌팅의 원인입니다. MANUAL+OP로 잡히는 헌팅과 안 잡히는 헌팅이 갈립니다. + + ┌──────────────────────┬────────────────────┬─────────────────────────────────────────────────────────────────────┐ + │ 헌팅 원인 │ MANUAL+OP로 │ 설명 │ + │ │ 잡히나? │ │ + ├──────────────────────┼────────────────────┼─────────────────────────────────────────────────────────────────────┤ + │ 튜닝 과민(Kc 과대/I │ ✅ 즉시 잡힘 │ MAN 전환 순간 컨트롤러 피드백이 빠지므로 제어기발 발진이 사라짐. │ + │ 과속) │ │ OP를 천천히·rate제한으로 움직이면 됨 │ + ├──────────────────────┼────────────────────┼─────────────────────────────────────────────────────────────────────┤ + │ 상류 외란(원료 헌팅 │ ✅ 잘 잡힘 │ 원본 문서의 "필터 + 부드럽게" 가 곧 MAN 느낌의 피드포워드. 가장 │ + │ 등) │ │ 강력한 케이스 │ + ├──────────────────────┼────────────────────┼─────────────────────────────────────────────────────────────────────┤ + │ 루프 간 간섭 │ ⚠️ 부분적 │ 이동/시차 조절로 완화 │ + ├──────────────────────┼────────────────────┼─────────────────────────────────────────────────────────────────────┤ + │ 밸브 stiction(고착) │ ❌ 안 잡힘, 오히려 │ 물리적 결함. MAN에서 작게 보정하면 또 고착·점프. 액추에이터 마모만 │ + │ │ 악화 │ 늘어남 → 정비 대상 │ + └──────────────────────┴────────────────────┴─────────────────────────────────────────────────────────────────────┘ + + → 결론: 튜닝·외란발 헌팅은 PID 파라미터를 안 건드리고 MAN+OP로 충분히 안정화됩니다. 단, 한 가지 본질적 사실: + + ▎ MAN으로 가는 순간 DCS PID가 하던 자동 피드백 규제가 사라집니다. OP를 누가 계속 움직여줘야 합니다. 즉 당신은 "튜닝을 + ▎ 안 한" 게 아니라 컨트롤러를 DCS 밖(당신 소프트웨어)으로 옮긴 것입니다. 외부 프로그램이 느린 PI/피드포워드로 OP를 + ▎ 써주는, 사실상 외부 컨트롤러가 됩니다. + + 이건 정당한 방식이고, 실제 APC가 하는 일과 같습니다. 그리고 브라운필드에서 매력적인 이유: DCS 로직 변경·변경관리(MoC) + 없이 OPC 쓰기만으로 됩니다(당신은 이미 OPC Write가 있음). + + 2. 그래서 두 가지 모드를 구분하세요 — 당신의 1~4단계가 정확히 여기 매핑됩니다 + + ┌─────────────────────────┬───────────────────────┬──────────────────────────────────────────┬───────────┐ + │ 방식 │ 누가 빠른 규제를 하나 │ 언제 │ 당신 계획 │ + ├─────────────────────────┼───────────────────────┼──────────────────────────────────────────┼───────────┤ + │ (A) SP 쓰기 + AUTO 유지 │ DCS PID (그대로 둠) │ 평상시 감독·최적화. 기저 PID가 쓸만할 때 │ 1~3단계 │ + ├─────────────────────────┼───────────────────────┼──────────────────────────────────────────┼───────────┤ + │ (B) OP 쓰기 + MANUAL │ 당신 소프트웨어 │ 기저 PID가 헌팅인데 재튜닝 못/안 할 때 │ 4단계 │ + └─────────────────────────┴───────────────────────┴──────────────────────────────────────────┴───────────┘ + + (A)는 SP를 AUTO 루프에 쓰는 거라 본질적으로 bumpless하고 가장 안전합니다. (B)는 더 강력하지만 규제·bumpless·폴백을 + 전부 당신이 책임집니다. + + → 당신 직관이 정확합니다: 평상시엔 (A)로 신뢰를 쌓고, 헌팅 루프에 한해 (B)로 개입. PID 파라미터 교정은 필수가 + 아닙니다. + + 3. 4단계의 전제 — "헌팅 원인 진단"이 게이트 (여기가 LLM의 진짜 자리) + + 4단계가 성공하려면 MAN 전환 전에 원인을 판별해야 합니다. stiction인데 OP 핸드홀딩하면 헛수고+마모입니다. + + - 헌팅 검출/심각도 판정 = 결정론(진폭·주기·지속성, 오실레이션 인덱스). MAN 전환 트립도 결정론이어야 함(LLM 지연 불가). + - 원인 분류(튜닝 vs stiction vs 외란) = LLM + 데이터 융합의 고가치 역할. OP-PV 위상, 한계주기 파형, 상류 신호, + 정비이력을 엮어 "이건 stiction → 4단계 말고 정비 플래그" vs "외란 → 4단계 OP 핸드홀딩 유효" 판단. + + 즉 LLM은 OP를 직접 흔드는 게 아니라, "이 루프에 4단계를 적용해도 되는가"를 판정합니다. 이게 당신 비전에 LLM이 깔끔하게 + 들어가는 지점입니다. + + 4. 안전 봉투 — 당신이 든 것 + 빠진 것 + + 당신이 명시한 것(✅ 다 맞음): rate 제한 · 절대값 제한 · 현재 유량 대비 밸브 변동폭 제한 · ESD/IL 독립 보증. 특히 + ESD/SIS가 BPCS 루프의 MAN/AUTO와 무관하게 독립 동작한다는 점이 이 실험을 봉인된 안전 범위 안에 묶어줍니다 — 정확한 + 인식입니다. + + 추가로 반드시 넣어야 할 것: + + 1. 양방향 Bumpless — AUTO→MAN 시 현재 OP에서 시작, MAN→AUTO 복귀 시 PID가 현재 PV/OP에서 초기화(Experion 기본 지원). + 2. 컴스 워치독 → AUTO로 폴백 (중요한 미묘점): MAN에서 OP 잡고 있다가 외부 프로그램이 죽으면 루프가 마지막 OP에 규제 + 없이 방치됨 → 위험. 그래서 "통신 두절 시 MAN 고수가 아니라 AUTO 복귀" 가 안전. 결국 DCS PID는 적당히 튜닝된 채로 두는 + 게 폴백 안전망입니다(바이패스해도 AUTO가 늘 안전귀항지여야 함). + 3. PV/품질 가드 — PV가 밴드 이탈하면 4단계 중단→AUTO 또는 안전 OP. + 4. 한 번에 한 루프 — 간섭 루프를 동시에 MAN 두지 않기. + 5. 운전원 최우선 오버라이드 — 항상 즉시 회수 가능. + 6. MoC/문화 — 자동 시스템이 루프를 MAN으로 돌리고 OP를 흔드는 건 현장에서 APC로 간주되어 변경관리·운전원 수용 이슈가 + 있음(기술 외 항목). + + 5. 기존 인프라와의 매핑 (이미 다 있음) + + - 1~2단계(제안 SP 표시): 루프별 advisory 섀도 포인트(예: FICQ-6101_ADV)를 WriteTagAsync로 쓰고 HMI 그룹/트렌드에 실제 + SP 옆에 표시 → 페이스플레이트 해킹 없이 "제안 vs 실제" 비교. (Experion 디스플레이에 제안값을 어떻게 띄울지가 1~2단계의 + 실질 통합 과제) + - 3단계(SP 주도권): WriteTagAsync(.sp) + AUTO 유지. + - 4단계(MAN+OP): 바로 그 ControlOp(MD→MAN→OP쓰기→AUTO복귀) 가 4단계의 기본 프리미티브입니다. RestoreAuto=false로 MAN + 유지하며 OP 스트리밍 → 안정되면 AUTO 복귀, 워치독이 비상 복귀. + + --- + 문서로 가기 전에 같이 못 박을 것 세 가지: + + 1. 4단계 OP 제어법 — MAN에서 (i) OP 고정 후 가끔 보정인지, (ii) 외부 느린 PI/피드포워드로 OP를 상시 써주는지. 후자면 + "외부 컨트롤러"를 명시적으로 설계해야 합니다(이게 사실상 미니 APC). + 2. 헌팅 임계 정의 — 진폭 몇 %/주기/지속 몇 분에서 4단계 트립? 그리고 stiction 자동 판별을 어디까지 신뢰할지(초기엔 LLM + 진단 → 운전원 확인 권장). + 3. 1~2단계 HMI 표시 방식 — advisory 섀도 포인트로 갈지, Experion 커스텀 디스플레이를 손댈지. 이게 신뢰 구축 단계의 + 실현성을 좌우합니다. + + 이 세 개에 대한 생각을 주시면, 지금까지의 컨셉·4단계 로드맵·안전봉투·LLM 역할(특히 헌팅 원인 진단)을 플랜 문서에 정식 + 섹션으로 정리하겠습니다. + +✻ Cooked for 1m 47s + +❯ sp는 PID 루프의 RSP 입력을 사용하면, 운전원이 언제든 LOCAL SP로 변경할 수 있으므로, 문제 없슴, 즉, PID LOOP의 SP를 + 직접 WRITE하는게 아니고, 별도의 변수에 쓰고, 그게 RSP로 연결, 운전원은 선택권이 있슴 + +● 맞습니다. RSP(Remote SP)를 쓰는 게 정석이고, 이걸로 권한·bumpless·가역성이 한 번에 깔끔하게 풀립니다. 제가 직전에 + 제안한 "advisory 섀도 포인트 + 커스텀 디스플레이"는 이제 필요 없습니다 — 더 나은 길입니다. + + 왜 이게 정답인가 + + 엔진은 루프 SP 레지스터를 절대 건드리지 않고, 자기 변수에만 씁니다. 그 변수가 RSP로 연결되고, 운전원의 LSP↔RSP(= + Experion 기준 AUTO↔CAS) 전환 스위치가 유일한 권한 손잡이가 됩니다. + + 이게 당신의 1~3단계를 하나의 운전원 소유 스위치로 압축합니다: + - 1~2단계(제안 표시): 루프는 LSP(AUTO)에 둠. 운전원은 페이스플레이트에서 "원격이 제안하는 SP 후보값"을 그냥 봄. 별도 + 화면 개발 불필요 — 네이티브 페이스플레이트가 RSP 후보를 보여줌. + - 3단계(주도권 이양): 운전원이 신뢰가 생기면 CAS로 한 번 토글 → 그 순간부터 엔진 SP 추종. 코드 추가 0. 되돌리려면 다시 + LSP로 토글하면 끝. + + 다만 한 가지 구현 요건 — 외부 추종(tracking) + + 여기가 OPC 외부 감독의 미묘점입니다. 정식 Experion 캐스케이드라면 back-calculation 핸드셰이크로 primary가 자동 + 추종합니다. 그런데 OPC로 RSP 소스에 쓰는 외부 엔진은 그 핸드셰이크를 못 받습니다. 그래서: + + ▎ 루프가 LSP(미선택) 상태일 때, 엔진은 현재 실작동 SP를 읽어 자기 출력값 = 현재 SP로 추종시켜야 합니다. 그래야 + ▎ 운전원이 CAS로 토글하는 순간 bumpless가 보장됩니다. (선택 안 됐을 때 출력을 현재값에 물려두는 표준 캐스케이드 매너를 + ▎ 엔진이 직접 구현) + + 이거 하나만 지키면 운전원이 언제 토글해도 충격 없습니다. + + 방어 심층 (independent layers) + + 1. 엔진 자체 가드 (rate·절대값·변동폭) + 2. DCS의 RSP 한계 (SPHILM/SPLOLM, RSP rate) — 엔진과 무관한 독립 클램프. 공짜 안전망 한 겹 추가. + 3. 운전원 LSP/RSP 토글 (언제든 회수) + 4. ESD/IL/SIS 독립 동작 + + 구체 작업 항목 + + - DCS 구성: 루프별 감독 소스 포인트 생성 → 각 PID의 RSP/X 입력에 control connection. (엔진은 이 포인트에만 OPC write) + - OPC 타깃 변경: WriteTagAsync 대상이 ...:ficq-6101.sp → 감독 소스 포인트로만 바뀜. 쓰기 인프라는 그대로, 노드 ID만 + 교체. + - 모드 전환은 엔진이 안 함: AUTO↔CAS는 운전원 전유. 엔진은 SP 경로에서 모드를 절대 안 바꿈 → 더 안전. + + 한 가지 비대칭 — OP 경로(4단계)는 이만큼 깔끔하지 않음 + + RSP 트릭은 SP 경로(방식 A) 를 완벽히 커버합니다. 그런데 4단계(튜닝발 헌팅 → MAN+OP)는 다릅니다: + - CAS/RSP로 SP를 줘봐야 PID가 루프에 그대로 있으니 튜닝발 헌팅은 안 잡힘. + - 그래서 4단계는 여전히 MAN으로 내려 OP를 직접 쓰는 "무거운 개입"이고, 이전 단서(엔진이 컨트롤러가 됨 / 워치독→AUTO + 폴백)가 그대로 유효. + - 확인 필요: 당신 DCS가 RSP처럼 외부 OP 입력 + 운전원 선택 스위치(output connection/external OP)를 지원하나요? + 지원하면 OP 경로도 RSP만큼 가역적으로 만들 수 있습니다. 없으면 4단계는 MAN+OP쓰기+워치독으로 남습니다. + + --- + 이제 SP 경로 설계는 깔끔하게 잠겼습니다(RSP + 외부 추종 + 운전원 토글). 직전에 띄운 세 가지 정렬 항목 중 HMI 표시 건은 + RSP로 해결됐고, 남은 건 둘입니다: + + 1. 4단계 OP 제어법 — MAN에서 OP 고정+간헐 보정인지, 외부 느린 PI/FF로 상시 OP 작성(=미니 APC)인지. 그리고 위의 "외부 + OP 입력" 지원 여부. + 2. 헌팅 임계 정의 — 진폭/주기/지속 기준, stiction 자동판별 신뢰 수준. + + 이 둘에 대한 방향을 주시면 — 컨셉, RSP 기반 SP 경로, 4단계 OP 경로, 안전봉투, LLM 역할(헌팅 원인 진단 중심), 단계별 + 신뢰 이양 로드맵 — 전부 플랜 문서로 정리하겠습니다. + +✻ Worked for 1m 14s + +❯ 확인 필요: 당신 DCS가 RSP처럼 외부 OP 입력 + 운전원 선택 스위치(output connection/external OP)를 지원하나요? + 지원하면 OP 경로도 RSP만큼 가역적으로 만들 수 있습니다. 없으면 4단계는 MAN+OP쓰기+워치독으로 남습니다.---> 이것도 + DCS 컨트롤러에 별도의 변수를 만들고, 그걸 우리가 WRITE 하고, SWITCH 기능을 만들어서, PID LOOP OP, LLM OP 를 선택하게 + 하면 해결됨 + +● 정확합니다. 그 셀렉터 방식으로 OP 경로가 RSP와 완전 대칭이 됩니다. 그리고 한 가지 짚으면 — 제대로 하면 이게 기존 + MAN+OP+워치독보다 더 안전해집니다. + + 대칭 구조 완성 + + ┌──────────────────┬──────────────────────┬────────────────────────┐ + │ │ SP 경로 │ OP 경로 │ + ├──────────────────┼──────────────────────┼────────────────────────┤ + │ 감독 변수 │ RSP 소스 포인트 │ "LLM OP" 변수 │ + ├──────────────────┼──────────────────────┼────────────────────────┤ + │ 우리가 OPC write │ 그 포인트에만 │ 그 변수에만 │ + ├──────────────────┼──────────────────────┼────────────────────────┤ + │ 운전원 스위치 │ LSP ↔ RSP (AUTO↔CAS) │ PID-OP ↔ LLM-OP 셀렉터 │ + ├──────────────────┼──────────────────────┼────────────────────────┤ + │ 권한 │ 운전원 전유 │ 운전원 전유 │ + └──────────────────┴──────────────────────┴────────────────────────┘ + + 쓰기 인프라(WriteTagAsync)는 그대로, 노드 ID만 바뀝니다. 양쪽 다 "엔진은 자기 변수에만 쓰고, 운전원이 스위치로 + 채택"하는 동일 패턴. + + 단 하나의 결정적 요건 — 비선택 PID의 back-calculation 추종 + + 이게 OP 경로의 핵심이자 RSP 추종의 쌍입니다. 셀렉터가 LLM-OP에 있을 때, 네이티브 PID를 그냥 두면: + + ▎ PID가 AUTO에서 계속 적분 → 자기 OP는 밸브에 안 가는데 적분만 쌓임(windup) → PID-OP로 되돌리는 순간 누적출력이 + ▎ 튀어나옴(bump). + + 방지책: 셀렉터가 선택된 출력(LLM-OP)을 비선택 PID로 되먹임(back-calc/initialization) 해서, PID 내부 OP가 항상 현재 + 밸브 위치를 추종하게 만듭니다. 그러면 windup 없음 + 양방향 bumpless. (Honeywell 계열의 BACKCALC/INIT 경로) + + 보너스 — 이게 4단계의 위험을 없앱니다 + + 이 설계는 기존 "MAN으로 내려 OP 쓰고 워치독으로 AUTO 복귀"를 대체하고 더 낫습니다: + + - MAN이 필요 없음. PID는 AUTO에 둔 채 추종만 시키고, 셀렉터로 밸브 주도권만 가져옴 → 튜닝발 헌팅은 PID가 밸브에서 + 빠졌으니 사라짐. + - 장애 시 무충격 자동 폴백. 엔진 죽거나 운전원이 회수하면 셀렉터가 PID-OP로 → PID가 이미 현재 밸브 위치를 추종 + 중이므로 그 자리에서 즉시·bumpless로 규제 재개. 기존 MAN 방식의 "규제 없이 마지막 OP에 방치" 위험이 사라짐. + + → 즉 4단계 = "MAN+OP+워치독" 이 아니라 "셀렉터를 LLM-OP로 + PID는 AUTO 추종 + 컴스두절/회수 시 PID-OP로 fail-over" 로 + 다시 씁니다. + + 정직한 단서 — MoC 강도가 다름 + + - RSP(SP) 경로: PID에 입력 하나만 추가. 출력경로 손 안 댐 → 저위험. + - 셀렉터(OP) 경로: PID와 최종요소(밸브) 사이에 셀렉터를 삽입 → 밸브로 가는 경로를 변경. 오설정 시 밸브에 직접 영향 → + 변경관리·테스트가 더 엄격해야 함. (라이브 루프면 더더욱) + + 방어 심층은 그대로: 엔진 가드 + DCS 출력한계(OPHILM/OPLOLM) + 운전원 셀렉터 + ESD/IL/SIS 독립. + + --- + 이제 SP·OP 양 경로가 대칭으로 잠겼습니다. 남은 진짜 설계 결정은 하나뿐: + + LLM-OP 모드에서 엔진이 OP에 무엇을 쓰나? 제 권장은 — "OP 고정+간헐 보정"(규제 상실)이 아니라, 물리모델(Cv 커브·배관) + 피드포워드 + 느린 외부 PI를 rate제한해서 OP에 작성 = 사실상 "DCS PID가 이랬으면 했던, 잘 튜닝된 컨트롤러를 우리 + 소프트웨어에서 구동". 헌팅 원인이 외란이면 FF만으로도 충분하고, 약한 PI가 잔차를 잡습니다. + + 여기에 + 헌팅 임계 정의(진폭/주기/지속). + + 이 두 개 방향만 확정하면 — 컨셉, RSP/셀렉터 대칭 구조, back-calc 추종 요건, fail-over, 안전봉투, LLM 헌팅원인 진단 + 역할, 신뢰 이양 로드맵 — 전부 플랜 문서로 정리하겠습니다. 권장안(외부 FF+느린 PI)으로 진행할지, "고정+간헐 보정"으로 + 보수적으로 갈지 알려주세요. + +✻ Cooked for 58s + +❯ PID가 AUTO에서 계속 적분 → 자기 OP는 밸브에 안 가는데 적분만 쌓임(windup) → PID-OP로 되돌리는 순간 누적출력이 + ▎ 튀어나옴(bump).---> LLM OP 전환시 PID MODE를 MANUAL 전환하고, LLM OP 값이 PID OP를 겹쳐쓰게함(Bumpless output + 가능) , 운전원의 PID_OP 선택시 같은 값에서 시작하게 하므로, 운전원 판단에 다라 값을 변경하면됨 + +● 맞습니다. 그게 더 단순하고, 게다가 기존 인프라로 즉시 됩니다. PID를 MAN으로 내리면 적분이 멈추니 windup 자체가 없고, + MAN에서 .op에 쓰는 건 본질적으로 bumpless입니다. 이건 지금 있는 ControlOp(MD→MAN→OP쓰기) / WriteTagAsync(.op) 그대로 — + 셀렉터 블록도, back-calc 배선도 불필요. MoC도 낮습니다(밸브로 가는 출력경로를 변형하지 않고, 네이티브 MAN OP 쓰기만 + 씀). 제 셀렉터 제안보다 이게 더 나은 기본값입니다. + + 운전원 회수도 말씀대로 깔끔합니다: MAN에서 OP는 LLM이 쓴 마지막 값 → 운전원이 그 값에서 이어서 조정, 또는 AUTO로 + 올리면 PID가 현재 PV/OP에서 bumpless 재개. + + 정직하게, 이 방식이 치르는 단 하나의 비용 — 장애 모드 + + 선택+back-calc과 다른 점은 엔진이 죽었을 때입니다: + + - 선택+back-calc(PID는 AUTO 추종 유지): 폴백 시 PID가 즉시 규제 재개. + - MAN+OP쓰기(이 방식): 엔진이 죽으면 루프가 MAN에 OP 동결 + 규제 없음 상태로 방치. 죽은 엔진은 스스로 AUTO로 못 올림. + + → 그래서 이 방식엔 DCS 측 데드맨(comms watchdog) 한 조각이 필요합니다: + + ▎ 엔진이 heartbeat/카운터를 같이 write → DCS 로직이 "N초간 갱신 없음" 감지 시 루프를 강제로 MAN→AUTO 복귀 (안전귀항 = + ▎ DCS PID 규제로 fail-safe). + + 이게 유일하게 추가되는 DCS 측 안전 로직입니다. 작지만 필수 — 없으면 엔진 사망 시 무기한 동결입니다. (대부분의 + 유량/수위 루프는 동결이 한동안 양성이고 SIS/IL이 극단을 잡으므로, 데드맨→AUTO면 충분히 안전합니다.) + + 그래서 결론 — 기본값과 예외 + + ┌───────────────────────────────────────┬──────────────────────────────────┬──────────────────────────────────────┐ + │ 루프 성격 │ 방식 │ 이유 │ + ├───────────────────────────────────────┼──────────────────────────────────┼──────────────────────────────────────┤ + │ 대부분 (유량·수위 등) │ MAN+OP쓰기 + DCS 데드맨→AUTO ← │ 단순·기존인프라·저MoC. 동결이 양성 │ + │ │ 당신 안 │ │ + ├───────────────────────────────────────┼──────────────────────────────────┼──────────────────────────────────────┤ + │ 빠르고 위험해 순간 규제 공백도 불가한 │ 선택+back-calc (PID AUTO 추종) │ 무충격 즉시 폴백 가치가 추가 MoC를 │ + │ 소수 루프 │ │ 정당화 │ + └───────────────────────────────────────┴──────────────────────────────────┴──────────────────────────────────────┘ + + 즉 당신 방식을 기본으로, 임계 루프만 선택적으로 업그레이드. + + --- + + - 섀도/추천 모드 학습: 엔진이 "이렇게 하겠다"를 계산만 하고, 실제 운전원 조치 + 결과를 로깅 → 둘의 격차를 학습. + "운전원은 항상 P밸브를 우리 모델보다 느리게 연다" → 모델 보정. 탐색 위험 0, 지도학습. + - CLPM (폐루프 성능 모니터링): Harris 지수(최소분산 대비)·발진 감지·밸브 stiction 진단을 일상 운전 데이터만으로 수행 → + 루프 건강도 점수화 → 튜닝 열화 시 자동 플래그. 이게 재튜닝의 트리거가 되고, LLM이 우선순위를 서술. + + 추천 적응 루프 (이 플랜트 기준) + + 일상 데이터 → CLPM(Harris·stiction·발진) → LLM이 "열화 루프" 식별·서술 + → 게인 스케줄(L2) 해당 점 벗어남? → Bump Test 재식별(L1) + → 트윈에서 베이지안 최적화(L4)로 미세조정 → 운전원 승인 → 가드 경유 반영 + → 결과 로깅 → 섀도 학습으로 모델 보정 (순환) + + 반드시 지켜야 할 제약 (정직하게) + + - 디지털 트윈 우선 — 현 브랜치 sim/... 활용. L4/L5는 실플랜트 전 트윈 검증 필수. + - 식별성(Identifiability) — 충분한 가진(excitation) 없으면 모델 못 만듦. 고순도 탑은 비선형·느림 → 작은 선형모델은 + 국소적으로만 유효 → 그래서 L2 게인 스케줄링이 핵심. + - 안전 제약 — 모든 적응은 플랜 §0 가드 레이어 하드 한계 안에서만. 탐색형(L4/L5)엔 trust-region 필수. + - LLM은 비용함수·실험설계·수렴판정·가드를 담당하고, 최적화 수치는 알고리즘이 낸다 — 여기서도 §0 원칙 유지. + - 이 C-6111은 품질직결·느림·비선형 = 가장 보수적으로 다뤄야 하는 케이스. L1+L2+섀도부터, L4는 트윈에서만. + + --- + 요약: LLM은 PID 튜닝의 지휘자·진단가·번역가로 강력하고(수치는 결정론 수학이 산출), 플랜트 적응 학습도 가능하되 RL이 + 아니라 재식별+게인스케줄링+베이지안최적화+섀도학습+CLPM 조합이 안전하고 현실적인 답입니다. + + 이 내용을 자동운전 플랜 문서에 "§10. PID 튜닝 보조 & 적응 학습" 섹션으로 추가해 둘까요? + +✻ Crunched for 1m 10s + +❯ 좀더 얘기를 하고 문서를 작성하자, + + 내가 알고있는것은 밸브의 사이즈, 배관의종류, 컨트롤밸브의 CV 값과 CV 커브, 플로우미터의 유량범위 등의 물리적인 + 데이터를 가지고 있다면, 결정론적인 부분을 이것으로 프로그램화 하고, LLM은 실제로 무엇을 할 수있다는거야? + +● 아주 정확한 지점을 찌르셨습니다. 솔직하게 답하면 — 그 물리 데이터를 가지고 있다면, 제어 수학에서 LLM이 할 일은 오히려 크게 + 줄어듭니다. 그게 맞고, 그게 좋은 겁니다. 하나씩 정리하죠. + + 1. 물리 데이터로 결정론화되는 부분 (LLM 불필요) + + 말씀하신 데이터는 사실 "데이터 피팅으로 추정"해야 했던 것들을 계산으로 바꿔버립니다: + + ┌───────────────────────────────────┬─────────────────────────────────────────────┬────────────────────┐ + │ 물리 데이터 │ 계산되는 결정론 모델 │ 이전엔 뭐로 구했나 │ + ├───────────────────────────────────┼─────────────────────────────────────────────┼────────────────────┤ + │ 컨트롤밸브 Cv + Cv 커브(설치특성) │ OP(%) → 유량 관계, 밸브 게인 dQ/dOP │ Step Test 식별 │ + ├───────────────────────────────────┼─────────────────────────────────────────────┼────────────────────┤ + │ 배관 종류·구경·길이 │ ΔP·마찰, 이송 데드타임 θ = 관내체적/유량 │ Step Test로 θ 측정 │ + ├───────────────────────────────────┼─────────────────────────────────────────────┼────────────────────┤ + │ 드럼/트레이 홀드업 체적 │ 체류시간 τ = 체적/유량 (D-6113 환류드럼 등) │ Step Test로 τ 측정 │ + ├───────────────────────────────────┼─────────────────────────────────────────────┼────────────────────┤ + │ 플로우미터 레인지 │ 스케일링·분해능·노이즈 플로어 │ — │ + └───────────────────────────────────┴─────────────────────────────────────────────┴────────────────────┘ + + → 즉 자동운전 플랜의 B(하부)·D/R(상부) 타이밍은 하이드롤릭 홀드업 = 체적/유량 으로 직접 계산됩니다. 밸브 게인도 Cv 커브 + 미분으로 나옵니다. 여기에 LLM을 넣을 이유가 없습니다. 모델기반 튜닝(SIMC/Lambda)도 이 물리모델로 바로 Kc·τI가 떨어집니다. 이 + 부분은 그냥 프로그램하세요. 제 처음 답에서 "Step Test로 식별"이라던 것의 상당 부분이 당신의 경우 불필요해집니다. + + 2. 그런데 물리 데이터가 못 주는 3가지 + + 여기가 핵심입니다. Cv·배관·유량범위는 하이드롤릭(얼마나 흐르나) 을 줍니다. 그런데 증류탑의 진짜 어려움은 거기가 아닙니다. + + (가) 분리/조성 동특성 — 당신 데이터에 없음. + 원본 문서의 "P(측류)는 15~20분으로 가장 느리다" 는 배관 이송이 아니라 트레이별 물질·열 홀드업 + 기액평형(VLE)으로 새 조성이 + 자리잡는 시간입니다. 홀드업 체적은 당신이 알지만, 상대휘발도·트레이 효율·VLE는 Cv 커브에 없습니다. 이 P 지연은 물리 + 데이터만으론 안 나오고, 단별(stage) 분리 모델이 필요합니다. → B·D는 물리로 계산되지만, P는 안 됩니다. 이게 경계선입니다. + + (나) 모델-플랜트 불일치(드리프트). Cv 커브는 깨끗한 신품 설계값입니다. 실제론 밸브 stiction·시트 마모, E-6103 파울링, 트레이 + 효율 저하로 시간에 따라 어긋납니다. 물리모델은 "어제의 진실"이고 플랜트는 오늘 다릅니다. + + (다) 목적·맥락·예외. 무엇이 "잘 도는" 건지(회수율 최대 vs 에너지 최소 vs 순도 사수), 등급 변경, 기동/정지, 계기 고장, 상류 외란 + — 정적 물리 데이터엔 전혀 없습니다. + + 3. 그래서 LLM이 실제로 하는 일 (과장 없이) + + 물리모델이 좋을수록 LLM은 제어 경로에서 빠지고 가장자리로 이동합니다. 솔직한 목록: + + ┌──────────────────────────────┬─────────────────────────────────────────────────────────────────────────────────────────────── + ──────────────────┬───────────────────────────────────────────┐ + │ LLM 역할 │ 구체적으로 + │ 정직한 가치 │ + ├──────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────── + ──────────────────┼───────────────────────────────────────────┤ + │ ① 커미셔닝 보조 │ 밸브 데이터시트·Cv 커브·배관 스펙을 파싱해 결정론 엔진의 config/코드로 조립, Cv 값 정합성 점검 + │ ★★ 즉시 유용. "물리는 결정론" 철학 그대로 │ + ├──────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────── + ──────────────────┼───────────────────────────────────────────┤ + │ ② 데이터 정합(드리프트 진단) │ 물리예측 유량 vs 실측 잔차 계산은 수학, "이 OP·ΔP에서 8% 미달 → 밸브 파울링/마모 의심" + 해석·재교정 트리거는 LLM │ ★★ (나) 해결 │ + ├──────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────── + ──────────────────┼───────────────────────────────────────────┤ + │ ③ 소프트센서 보조 │ 측정 안 되는 조성을 온도(TI-6111B/C)로 추론, 분석기 결측 보간 + │ ★ (가) 보완(완전 해결 아님) │ + ├──────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────── + ──────────────────┼───────────────────────────────────────────┤ + │ ④ 감독형 예외 처리 │ 엔진이 프로그램 안 된 상황(기동·등급변경·상류 업셋·계기고장)에서 판단·완화 + │ ★★★ 물리 침묵 영역 │ + ├──────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────── + ──────────────────┼───────────────────────────────────────────┤ + │ ⑤ 운전원 인터페이스 │ 의도/경제목표 → SV·제약으로 번역, "왜 이렇게 도는지" 설명 + │ ★★★ 물리 침묵 영역 │ + ├──────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────── + ──────────────────┼───────────────────────────────────────────┤ + │ ⑥ 교차 데이터 융합 │ 알람+이벤트+랩분석+정비이력+물리잔차를 엮어 진단 + │ ★★★ 기존 MCP 도구 활용 │ + └──────────────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────────── + ──────────────────┴───────────────────────────────────────────┘ + + 4. 핵심 원리 (한 줄) + + ▎ LLM의 가치는 물리모델 품질에 반비례합니다. 당신처럼 물리를 잘 잡을수록 LLM은 제어 산수에서 사라지고 — ③ 못 측정하는 조성, ④ + ▎ 프로그램 안 된 예외, ⑤ 사람 인터페이스, ⑥ 교차 진단, ①커미셔닝으로 옮겨갑니다. 이게 정상이고 안전한 모습입니다. + + --- + 문서로 넘어가기 전에 같이 정리하고 싶은 게 몇 가지 있습니다: + + 1. 분리/조성(가) 모델을 어디까지 갈 건가? — P 지연을 (a) 그냥 보수적 고정 τ(15~20분)로 두고 안 건드릴지, (b) 간이 트레이/홀드업 + 모델을 세울지, (c) 운전데이터 기반 경험모델로 둘지. 이게 LLM 역할 ③의 깊이를 결정합니다. + 2. 물리 데이터의 형태 — Cv 커브가 표/수식/데이터시트 PDF 중 무엇인가요? 역할 ①(LLM이 config로 조립)의 실현성이 여기 달려 + 있습니다. + 3. LLM을 "제어 보조"로 보시는지 "운전 보조(예외·인터페이스)"로 보시는지 — 위 ②④⑤⑥ 중 어디에 무게를 두실지에 따라 문서 구조가 + 달라집니다. + + 이 세 가지에 대한 생각을 들려주시면, 그걸 반영해서 플랜 문서에 섹션을 작성하겠습니다. + +✻ Baked for 1m 17s + +❯ 내가 생각하는 방향은 이거야 + 1. 결정론이든, llm이든 목표 설정값을 연산---> Experion 서버에 전달 + 2. Experion 서버에서 프로그램을 해서, 전달된 값을 화면상(Operator Station 모니터링 HMI)에 PID Loop 표시에 제안한 SP값을 표시 + 3. 운전원이 여기에 익숙해지고, 신뢰가 생긴다면, mode 변경, -> Set Point 변경 주도권 가져옴 + 4. PID LOOP의 Hunting이 심하다고 판단되는 기준을 넘으면, 매뉴얼 모드로 변경, 제어출력(OP)를 가지고 변경하면서 안정권 유지 + + 꼭 DCS 컨트롤러의 PID 제어기의 파라미터를 교정하는것이 아니어도 매뉴얼 모드에서, op 변경만 가지고도 가능할까? 하는 의문에서 + 시작된 것이 이 세션의 시작 목적이기도 함---> 당연히 안전장치(rate제한, 절대값 제한, 현재 유량 범위 감안 밸브 변동폭 제한, 기본 + 컨트롤러에 설정된 ESD, IL 동작 이 보증된 상태에서 임 + +● 이제 핵심이 명확해졌습니다. 그리고 시작 질문 — "PID 파라미터를 안 건드리고, MANUAL에서 OP만으로 안정화 가능한가?" — 에 정직하게 + 답하면: 경우에 따라 Yes, 그리고 그게 오히려 브라운필드에서 더 현실적입니다. 다만 결정적인 단서가 있습니다. + + 1. 시작 질문에 대한 직답 + + 핵심은 헌팅의 원인입니다. MANUAL+OP로 잡히는 헌팅과 안 잡히는 헌팅이 갈립니다. + + ┌───────────────────────────┬─────────────────────────┬──────────────────────────────────────────────────────────────────────── + ───────────────────────────────┐ + │ 헌팅 원인 │ MANUAL+OP로 잡히나? │ 설명 + │ + ├───────────────────────────┼─────────────────────────┼──────────────────────────────────────────────────────────────────────── + ───────────────────────────────┤ + │ 튜닝 과민(Kc 과대/I 과속) │ ✅ 즉시 잡힘 │ MAN 전환 순간 컨트롤러 피드백이 빠지므로 제어기발 발진이 사라짐. OP를 + 천천히·rate제한으로 움직이면 됨 │ + ├───────────────────────────┼─────────────────────────┼──────────────────────────────────────────────────────────────────────── + ───────────────────────────────┤ + │ 상류 외란(원료 헌팅 등) │ ✅ 잘 잡힘 │ 원본 문서의 "필터 + 부드럽게" 가 곧 MAN 느낌의 피드포워드. 가장 강력한 + 케이스 │ + ├───────────────────────────┼─────────────────────────┼──────────────────────────────────────────────────────────────────────── + ───────────────────────────────┤ + │ 루프 간 간섭 │ ⚠️ 부분적 │ 이동/시차 조절로 완화 + │ + ├───────────────────────────┼─────────────────────────┼──────────────────────────────────────────────────────────────────────── + ───────────────────────────────┤ + │ 밸브 stiction(고착) │ ❌ 안 잡힘, 오히려 악화 │ 물리적 결함. MAN에서 작게 보정하면 또 고착·점프. 액추에이터 마모만 + 늘어남 → 정비 대상 │ + └───────────────────────────┴─────────────────────────┴──────────────────────────────────────────────────────────────────────── + ───────────────────────────────┘ + + → 결론: 튜닝·외란발 헌팅은 PID 파라미터를 안 건드리고 MAN+OP로 충분히 안정화됩니다. 단, 한 가지 본질적 사실: + + ▎ MAN으로 가는 순간 DCS PID가 하던 자동 피드백 규제가 사라집니다. OP를 누가 계속 움직여줘야 합니다. 즉 당신은 "튜닝을 안 한" 게 + ▎ 아니라 컨트롤러를 DCS 밖(당신 소프트웨어)으로 옮긴 것입니다. 외부 프로그램이 느린 PI/피드포워드로 OP를 써주는, 사실상 외부 + ▎ 컨트롤러가 됩니다. + + 이건 정당한 방식이고, 실제 APC가 하는 일과 같습니다. 그리고 브라운필드에서 매력적인 이유: DCS 로직 변경·변경관리(MoC) 없이 OPC + 쓰기만으로 됩니다(당신은 이미 OPC Write가 있음). + + 2. 그래서 두 가지 모드를 구분하세요 — 당신의 1~4단계가 정확히 여기 매핑됩니다 + + ┌─────────────────────────┬───────────────────────┬──────────────────────────────────────────┬───────────┐ + │ 방식 │ 누가 빠른 규제를 하나 │ 언제 │ 당신 계획 │ + ├─────────────────────────┼───────────────────────┼──────────────────────────────────────────┼───────────┤ + │ (A) SP 쓰기 + AUTO 유지 │ DCS PID (그대로 둠) │ 평상시 감독·최적화. 기저 PID가 쓸만할 때 │ 1~3단계 │ + ├─────────────────────────┼───────────────────────┼──────────────────────────────────────────┼───────────┤ + │ (B) OP 쓰기 + MANUAL │ 당신 소프트웨어 │ 기저 PID가 헌팅인데 재튜닝 못/안 할 때 │ 4단계 │ + └─────────────────────────┴───────────────────────┴──────────────────────────────────────────┴───────────┘ + + (A)는 SP를 AUTO 루프에 쓰는 거라 본질적으로 bumpless하고 가장 안전합니다. (B)는 더 강력하지만 규제·bumpless·폴백을 전부 당신이 + 책임집니다. + + → 당신 직관이 정확합니다: 평상시엔 (A)로 신뢰를 쌓고, 헌팅 루프에 한해 (B)로 개입. PID 파라미터 교정은 필수가 아닙니다. + + 3. 4단계의 전제 — "헌팅 원인 진단"이 게이트 (여기가 LLM의 진짜 자리) + + 4단계가 성공하려면 MAN 전환 전에 원인을 판별해야 합니다. stiction인데 OP 핸드홀딩하면 헛수고+마모입니다. + + - 헌팅 검출/심각도 판정 = 결정론(진폭·주기·지속성, 오실레이션 인덱스). MAN 전환 트립도 결정론이어야 함(LLM 지연 불가). + - 원인 분류(튜닝 vs stiction vs 외란) = LLM + 데이터 융합의 고가치 역할. OP-PV 위상, 한계주기 파형, 상류 신호, 정비이력을 엮어 + "이건 stiction → 4단계 말고 정비 플래그" vs "외란 → 4단계 OP 핸드홀딩 유효" 판단. + + 즉 LLM은 OP를 직접 흔드는 게 아니라, "이 루프에 4단계를 적용해도 되는가"를 판정합니다. 이게 당신 비전에 LLM이 깔끔하게 들어가는 + 지점입니다. + + 4. 안전 봉투 — 당신이 든 것 + 빠진 것 + + 당신이 명시한 것(✅ 다 맞음): rate 제한 · 절대값 제한 · 현재 유량 대비 밸브 변동폭 제한 · ESD/IL 독립 보증. 특히 ESD/SIS가 BPCS + 루프의 MAN/AUTO와 무관하게 독립 동작한다는 점이 이 실험을 봉인된 안전 범위 안에 묶어줍니다 — 정확한 인식입니다. + + 추가로 반드시 넣어야 할 것: + + 1. 양방향 Bumpless — AUTO→MAN 시 현재 OP에서 시작, MAN→AUTO 복귀 시 PID가 현재 PV/OP에서 초기화(Experion 기본 지원). + 2. 컴스 워치독 → AUTO로 폴백 (중요한 미묘점): MAN에서 OP 잡고 있다가 외부 프로그램이 죽으면 루프가 마지막 OP에 규제 없이 방치됨 + → 위험. 그래서 "통신 두절 시 MAN 고수가 아니라 AUTO 복귀" 가 안전. 결국 DCS PID는 적당히 튜닝된 채로 두는 게 폴백 + 안전망입니다(바이패스해도 AUTO가 늘 안전귀항지여야 함). + 3. PV/품질 가드 — PV가 밴드 이탈하면 4단계 중단→AUTO 또는 안전 OP. + 4. 한 번에 한 루프 — 간섭 루프를 동시에 MAN 두지 않기. + 5. 운전원 최우선 오버라이드 — 항상 즉시 회수 가능. + 6. MoC/문화 — 자동 시스템이 루프를 MAN으로 돌리고 OP를 흔드는 건 현장에서 APC로 간주되어 변경관리·운전원 수용 이슈가 있음(기술 + 외 항목). + + 5. 기존 인프라와의 매핑 (이미 다 있음) + + - 1~2단계(제안 SP 표시): 루프별 advisory 섀도 포인트(예: FICQ-6101_ADV)를 WriteTagAsync로 쓰고 HMI 그룹/트렌드에 실제 SP 옆에 + 표시 → 페이스플레이트 해킹 없이 "제안 vs 실제" 비교. (Experion 디스플레이에 제안값을 어떻게 띄울지가 1~2단계의 실질 통합 과제) + - 3단계(SP 주도권): WriteTagAsync(.sp) + AUTO 유지. + - 4단계(MAN+OP): 바로 그 ControlOp(MD→MAN→OP쓰기→AUTO복귀) 가 4단계의 기본 프리미티브입니다. RestoreAuto=false로 MAN 유지하며 + OP 스트리밍 → 안정되면 AUTO 복귀, 워치독이 비상 복귀. + + --- + 문서로 가기 전에 같이 못 박을 것 세 가지: + + 1. 4단계 OP 제어법 — MAN에서 (i) OP 고정 후 가끔 보정인지, (ii) 외부 느린 PI/피드포워드로 OP를 상시 써주는지. 후자면 "외부 + 컨트롤러"를 명시적으로 설계해야 합니다(이게 사실상 미니 APC). + 2. 헌팅 임계 정의 — 진폭 몇 %/주기/지속 몇 분에서 4단계 트립? 그리고 stiction 자동 판별을 어디까지 신뢰할지(초기엔 LLM 진단 → + 운전원 확인 권장). + 3. 1~2단계 HMI 표시 방식 — advisory 섀도 포인트로 갈지, Experion 커스텀 디스플레이를 손댈지. 이게 신뢰 구축 단계의 실현성을 + 좌우합니다. + + 이 세 개에 대한 생각을 주시면, 지금까지의 컨셉·4단계 로드맵·안전봉투·LLM 역할(특히 헌팅 원인 진단)을 플랜 문서에 정식 섹션으로 + 정리하겠습니다. + +✻ Cooked for 1m 47s + +❯ sp는 PID 루프의 RSP 입력을 사용하면, 운전원이 언제든 LOCAL SP로 변경할 수 있으므로, 문제 없슴, 즉, PID LOOP의 SP를 직접 + WRITE하는게 아니고, 별도의 변수에 쓰고, 그게 RSP로 연결, 운전원은 선택권이 있슴 + +● 맞습니다. RSP(Remote SP)를 쓰는 게 정석이고, 이걸로 권한·bumpless·가역성이 한 번에 깔끔하게 풀립니다. 제가 직전에 제안한 + "advisory 섀도 포인트 + 커스텀 디스플레이"는 이제 필요 없습니다 — 더 나은 길입니다. + + 왜 이게 정답인가 + + 엔진은 루프 SP 레지스터를 절대 건드리지 않고, 자기 변수에만 씁니다. 그 변수가 RSP로 연결되고, 운전원의 LSP↔RSP(= Experion 기준 + AUTO↔CAS) 전환 스위치가 유일한 권한 손잡이가 됩니다. + + 이게 당신의 1~3단계를 하나의 운전원 소유 스위치로 압축합니다: + - 1~2단계(제안 표시): 루프는 LSP(AUTO)에 둠. 운전원은 페이스플레이트에서 "원격이 제안하는 SP 후보값"을 그냥 봄. 별도 화면 개발 + 불필요 — 네이티브 페이스플레이트가 RSP 후보를 보여줌. + - 3단계(주도권 이양): 운전원이 신뢰가 생기면 CAS로 한 번 토글 → 그 순간부터 엔진 SP 추종. 코드 추가 0. 되돌리려면 다시 LSP로 + 토글하면 끝. + + 다만 한 가지 구현 요건 — 외부 추종(tracking) + + 여기가 OPC 외부 감독의 미묘점입니다. 정식 Experion 캐스케이드라면 back-calculation 핸드셰이크로 primary가 자동 추종합니다. + 그런데 OPC로 RSP 소스에 쓰는 외부 엔진은 그 핸드셰이크를 못 받습니다. 그래서: + + ▎ 루프가 LSP(미선택) 상태일 때, 엔진은 현재 실작동 SP를 읽어 자기 출력값 = 현재 SP로 추종시켜야 합니다. 그래야 운전원이 CAS로 + ▎ 토글하는 순간 bumpless가 보장됩니다. (선택 안 됐을 때 출력을 현재값에 물려두는 표준 캐스케이드 매너를 엔진이 직접 구현) + + 이거 하나만 지키면 운전원이 언제 토글해도 충격 없습니다. + + 방어 심층 (independent layers) + + 1. 엔진 자체 가드 (rate·절대값·변동폭) + 2. DCS의 RSP 한계 (SPHILM/SPLOLM, RSP rate) — 엔진과 무관한 독립 클램프. 공짜 안전망 한 겹 추가. + 3. 운전원 LSP/RSP 토글 (언제든 회수) + 4. ESD/IL/SIS 독립 동작 + + 구체 작업 항목 + + - DCS 구성: 루프별 감독 소스 포인트 생성 → 각 PID의 RSP/X 입력에 control connection. (엔진은 이 포인트에만 OPC write) + - OPC 타깃 변경: WriteTagAsync 대상이 ...:ficq-6101.sp → 감독 소스 포인트로만 바뀜. 쓰기 인프라는 그대로, 노드 ID만 교체. + - 모드 전환은 엔진이 안 함: AUTO↔CAS는 운전원 전유. 엔진은 SP 경로에서 모드를 절대 안 바꿈 → 더 안전. + + 한 가지 비대칭 — OP 경로(4단계)는 이만큼 깔끔하지 않음 + + RSP 트릭은 SP 경로(방식 A) 를 완벽히 커버합니다. 그런데 4단계(튜닝발 헌팅 → MAN+OP)는 다릅니다: + - CAS/RSP로 SP를 줘봐야 PID가 루프에 그대로 있으니 튜닝발 헌팅은 안 잡힘. + - 그래서 4단계는 여전히 MAN으로 내려 OP를 직접 쓰는 "무거운 개입"이고, 이전 단서(엔진이 컨트롤러가 됨 / 워치독→AUTO 폴백)가 + 그대로 유효. + - 확인 필요: 당신 DCS가 RSP처럼 외부 OP 입력 + 운전원 선택 스위치(output connection/external OP)를 지원하나요? 지원하면 OP + 경로도 RSP만큼 가역적으로 만들 수 있습니다. 없으면 4단계는 MAN+OP쓰기+워치독으로 남습니다. + + --- + 이제 SP 경로 설계는 깔끔하게 잠겼습니다(RSP + 외부 추종 + 운전원 토글). 직전에 띄운 세 가지 정렬 항목 중 HMI 표시 건은 RSP로 + 해결됐고, 남은 건 둘입니다: + + 1. 4단계 OP 제어법 — MAN에서 OP 고정+간헐 보정인지, 외부 느린 PI/FF로 상시 OP 작성(=미니 APC)인지. 그리고 위의 "외부 OP 입력" + 지원 여부. + 2. 헌팅 임계 정의 — 진폭/주기/지속 기준, stiction 자동판별 신뢰 수준. + + 이 둘에 대한 방향을 주시면 — 컨셉, RSP 기반 SP 경로, 4단계 OP 경로, 안전봉투, LLM 역할(헌팅 원인 진단 중심), 단계별 신뢰 이양 + 로드맵 — 전부 플랜 문서로 정리하겠습니다. + +✻ Worked for 1m 14s + +❯ 확인 필요: 당신 DCS가 RSP처럼 외부 OP 입력 + 운전원 선택 스위치(output connection/external OP)를 지원하나요? + 지원하면 OP 경로도 RSP만큼 가역적으로 만들 수 있습니다. 없으면 4단계는 MAN+OP쓰기+워치독으로 남습니다.---> 이것도 DCS + 컨트롤러에 별도의 변수를 만들고, 그걸 우리가 WRITE 하고, SWITCH 기능을 만들어서, PID LOOP OP, LLM OP 를 선택하게 하면 해결됨 + +● 정확합니다. 그 셀렉터 방식으로 OP 경로가 RSP와 완전 대칭이 됩니다. 그리고 한 가지 짚으면 — 제대로 하면 이게 기존 MAN+OP+워치독보다 더 안전해집니다. + + 대칭 구조 완성 + + ┌──────────────────┬──────────────────────┬────────────────────────┐ + │ │ SP 경로 │ OP 경로 │ + ├──────────────────┼──────────────────────┼────────────────────────┤ + │ 감독 변수 │ RSP 소스 포인트 │ "LLM OP" 변수 │ + ├──────────────────┼──────────────────────┼────────────────────────┤ + │ 우리가 OPC write │ 그 포인트에만 │ 그 변수에만 │ + ├──────────────────┼──────────────────────┼────────────────────────┤ + │ 운전원 스위치 │ LSP ↔ RSP (AUTO↔CAS) │ PID-OP ↔ LLM-OP 셀렉터 │ + ├──────────────────┼──────────────────────┼────────────────────────┤ + │ 권한 │ 운전원 전유 │ 운전원 전유 │ + └──────────────────┴──────────────────────┴────────────────────────┘ + + 쓰기 인프라(WriteTagAsync)는 그대로, 노드 ID만 바뀝니다. 양쪽 다 "엔진은 자기 변수에만 쓰고, 운전원이 스위치로 채택"하는 동일 패턴. + + 단 하나의 결정적 요건 — 비선택 PID의 back-calculation 추종 + + 이게 OP 경로의 핵심이자 RSP 추종의 쌍입니다. 셀렉터가 LLM-OP에 있을 때, 네이티브 PID를 그냥 두면: + + ▎ PID가 AUTO에서 계속 적분 → 자기 OP는 밸브에 안 가는데 적분만 쌓임(windup) → PID-OP로 되돌리는 순간 누적출력이 튀어나옴(bump). + + 방지책: 셀렉터가 선택된 출력(LLM-OP)을 비선택 PID로 되먹임(back-calc/initialization) 해서, PID 내부 OP가 항상 현재 밸브 위치를 추종하게 만듭니다. 그러면 windup 없음 + 양방향 bumpless. (Honeywell 계열의 BACKCALC/INIT 경로) + + 보너스 — 이게 4단계의 위험을 없앱니다 + + 이 설계는 기존 "MAN으로 내려 OP 쓰고 워치독으로 AUTO 복귀"를 대체하고 더 낫습니다: + + - MAN이 필요 없음. PID는 AUTO에 둔 채 추종만 시키고, 셀렉터로 밸브 주도권만 가져옴 → 튜닝발 헌팅은 PID가 밸브에서 빠졌으니 사라짐. + - 장애 시 무충격 자동 폴백. 엔진 죽거나 운전원이 회수하면 셀렉터가 PID-OP로 → PID가 이미 현재 밸브 위치를 추종 중이므로 그 자리에서 즉시·bumpless로 규제 재개. 기존 MAN 방식의 "규제 없이 마지막 OP에 방치" 위험이 사라짐. + + → 즉 4단계 = "MAN+OP+워치독" 이 아니라 "셀렉터를 LLM-OP로 + PID는 AUTO 추종 + 컴스두절/회수 시 PID-OP로 fail-over" 로 다시 씁니다. + + 정직한 단서 — MoC 강도가 다름 + + - RSP(SP) 경로: PID에 입력 하나만 추가. 출력경로 손 안 댐 → 저위험. + - 셀렉터(OP) 경로: PID와 최종요소(밸브) 사이에 셀렉터를 삽입 → 밸브로 가는 경로를 변경. 오설정 시 밸브에 직접 영향 → 변경관리·테스트가 더 엄격해야 함. (라이브 루프면 더더욱) + + 방어 심층은 그대로: 엔진 가드 + DCS 출력한계(OPHILM/OPLOLM) + 운전원 셀렉터 + ESD/IL/SIS 독립. + + --- + 이제 SP·OP 양 경로가 대칭으로 잠겼습니다. 남은 진짜 설계 결정은 하나뿐: + + LLM-OP 모드에서 엔진이 OP에 무엇을 쓰나? 제 권장은 — "OP 고정+간헐 보정"(규제 상실)이 아니라, 물리모델(Cv 커브·배관) 피드포워드 + 느린 외부 PI를 rate제한해서 OP에 작성 = 사실상 "DCS PID가 이랬으면 했던, 잘 튜닝된 컨트롤러를 우리 소프트웨어에서 구동". 헌팅 원인이 외란이면 FF만으로도 충분하고, 약한 PI가 잔차를 잡습니다. + + 여기에 + 헌팅 임계 정의(진폭/주기/지속). + + 이 두 개 방향만 확정하면 — 컨셉, RSP/셀렉터 대칭 구조, back-calc 추종 요건, fail-over, 안전봉투, LLM 헌팅원인 진단 역할, 신뢰 이양 로드맵 — 전부 플랜 문서로 정리하겠습니다. 권장안(외부 FF+느린 PI)으로 진행할지, "고정+간헐 보정"으로 보수적으로 갈지 알려주세요. + +✻ Cooked for 58s + +❯ PID가 AUTO에서 계속 적분 → 자기 OP는 밸브에 안 가는데 적분만 쌓임(windup) → PID-OP로 되돌리는 순간 누적출력이 + +✻ Cooked for 1m 47s + +❯ sp는 PID 루프의 RSP 입력을 사용하면, 운전원이 언제든 LOCAL SP로 변경할 수 있으므로, 문제 없슴, 즉, PID LOOP의 SP를 직접 WRITE하는게 아니고, 별도의 변수에 쓰고, 그게 RSP로 연결, 운전원은 선택권이 있슴 + +● 맞습니다. RSP(Remote SP)를 쓰는 게 정석이고, 이걸로 권한·bumpless·가역성이 한 번에 깔끔하게 풀립니다. 제가 직전에 제안한 "advisory 섀도 포인트 + 커스텀 디스플레이"는 이제 필요 없습니다 — 더 나은 길입니다. + + 왜 이게 정답인가 + + 엔진은 루프 SP 레지스터를 절대 건드리지 않고, 자기 변수에만 씁니다. 그 변수가 RSP로 연결되고, 운전원의 LSP↔RSP(= Experion 기준 AUTO↔CAS) 전환 스위치가 유일한 권한 손잡이가 됩니다. + + 이게 당신의 1~3단계를 하나의 운전원 소유 스위치로 압축합니다: + - 1~2단계(제안 표시): 루프는 LSP(AUTO)에 둠. 운전원은 페이스플레이트에서 "원격이 제안하는 SP 후보값"을 그냥 봄. 별도 화면 개발 불필요 — 네이티브 페이스플레이트가 RSP 후보를 보여줌. + - 3단계(주도권 이양): 운전원이 신뢰가 생기면 CAS로 한 번 토글 → 그 순간부터 엔진 SP 추종. 코드 추가 0. 되돌리려면 다시 LSP로 토글하면 끝. + + 다만 한 가지 구현 요건 — 외부 추종(tracking) + + 여기가 OPC 외부 감독의 미묘점입니다. 정식 Experion 캐스케이드라면 back-calculation 핸드셰이크로 primary가 자동 추종합니다. 그런데 OPC로 RSP 소스에 쓰는 외부 엔진은 그 핸드셰이크를 못 받습니다. 그래서: + + ▎ 루프가 LSP(미선택) 상태일 때, 엔진은 현재 실작동 SP를 읽어 자기 출력값 = 현재 SP로 추종시켜야 합니다. 그래야 운전원이 CAS로 토글하는 순간 bumpless가 보장됩니다. (선택 안 됐을 때 출력을 현재값에 물려두는 표준 캐스케이드 매너를 엔진이 직접 구현) + + 이거 하나만 지키면 운전원이 언제 토글해도 충격 없습니다. + + 방어 심층 (independent layers) + + 1. 엔진 자체 가드 (rate·절대값·변동폭) + 2. DCS의 RSP 한계 (SPHILM/SPLOLM, RSP rate) — 엔진과 무관한 독립 클램프. 공짜 안전망 한 겹 추가. + 3. 운전원 LSP/RSP 토글 (언제든 회수) + 4. ESD/IL/SIS 독립 동작 + + 구체 작업 항목 + + - DCS 구성: 루프별 감독 소스 포인트 생성 → 각 PID의 RSP/X 입력에 control connection. (엔진은 이 포인트에만 OPC write) + - OPC 타깃 변경: WriteTagAsync 대상이 ...:ficq-6101.sp → 감독 소스 포인트로만 바뀜. 쓰기 인프라는 그대로, 노드 ID만 교체. + - 모드 전환은 엔진이 안 함: AUTO↔CAS는 운전원 전유. 엔진은 SP 경로에서 모드를 절대 안 바꿈 → 더 안전. + + 한 가지 비대칭 — OP 경로(4단계)는 이만큼 깔끔하지 않음 + + RSP 트릭은 SP 경로(방식 A) 를 완벽히 커버합니다. 그런데 4단계(튜닝발 헌팅 → MAN+OP)는 다릅니다: + - CAS/RSP로 SP를 줘봐야 PID가 루프에 그대로 있으니 튜닝발 헌팅은 안 잡힘. + - 그래서 4단계는 여전히 MAN으로 내려 OP를 직접 쓰는 "무거운 개입"이고, 이전 단서(엔진이 컨트롤러가 됨 / 워치독→AUTO 폴백)가 그대로 유효. + - 확인 필요: 당신 DCS가 RSP처럼 외부 OP 입력 + 운전원 선택 스위치(output connection/external OP)를 지원하나요? 지원하면 OP 경로도 RSP만큼 가역적으로 만들 수 있습니다. 없으면 4단계는 MAN+OP쓰기+워치독으로 남습니다. + + --- + 이제 SP 경로 설계는 깔끔하게 잠겼습니다(RSP + 외부 추종 + 운전원 토글). 직전에 띄운 세 가지 정렬 항목 중 HMI 표시 건은 RSP로 해결됐고, 남은 건 둘입니다: + + 1. 4단계 OP 제어법 — MAN에서 OP 고정+간헐 보정인지, 외부 느린 PI/FF로 상시 OP 작성(=미니 APC)인지. 그리고 위의 "외부 OP 입력" 지원 여부. + 2. 헌팅 임계 정의 — 진폭/주기/지속 기준, stiction 자동판별 신뢰 수준. + + 이 둘에 대한 방향을 주시면 — 컨셉, RSP 기반 SP 경로, 4단계 OP 경로, 안전봉투, LLM 역할(헌팅 원인 진단 중심), 단계별 신뢰 이양 로드맵 — 전부 플랜 문서로 정리하겠습니다. + +✻ Worked for 1m 14s + +❯ 확인 필요: 당신 DCS가 RSP처럼 외부 OP 입력 + 운전원 선택 스위치(output connection/external OP)를 지원하나요? + 지원하면 OP 경로도 RSP만큼 가역적으로 만들 수 있습니다. 없으면 4단계는 MAN+OP쓰기+워치독으로 남습니다.---> 이것도 DCS 컨트롤러에 별도의 변수를 만들고, 그걸 우리가 WRITE 하고, SWITCH 기능을 만들어서, PID LOOP OP, LLM OP 를 선택하게 하면 해결됨 + +● 정확합니다. 그 셀렉터 방식으로 OP 경로가 RSP와 완전 대칭이 됩니다. 그리고 한 가지 짚으면 — 제대로 하면 이게 기존 MAN+OP+워치독보다 더 안전해집니다. + + 대칭 구조 완성 + + ┌──────────────────┬──────────────────────┬────────────────────────┐ + │ │ SP 경로 │ OP 경로 │ + ├──────────────────┼──────────────────────┼────────────────────────┤ + │ 감독 변수 │ RSP 소스 포인트 │ "LLM OP" 변수 │ + ├──────────────────┼──────────────────────┼────────────────────────┤ + │ 우리가 OPC write │ 그 포인트에만 │ 그 변수에만 │ + ├──────────────────┼──────────────────────┼────────────────────────┤ + │ 운전원 스위치 │ LSP ↔ RSP (AUTO↔CAS) │ PID-OP ↔ LLM-OP 셀렉터 │ + ├──────────────────┼──────────────────────┼────────────────────────┤ + │ 권한 │ 운전원 전유 │ 운전원 전유 │ + └──────────────────┴──────────────────────┴────────────────────────┘ + + 쓰기 인프라(WriteTagAsync)는 그대로, 노드 ID만 바뀝니다. 양쪽 다 "엔진은 자기 변수에만 쓰고, 운전원이 스위치로 채택"하는 동일 패턴. + + 단 하나의 결정적 요건 — 비선택 PID의 back-calculation 추종 + + 이게 OP 경로의 핵심이자 RSP 추종의 쌍입니다. 셀렉터가 LLM-OP에 있을 때, 네이티브 PID를 그냥 두면: + + ▎ PID가 AUTO에서 계속 적분 → 자기 OP는 밸브에 안 가는데 적분만 쌓임(windup) → PID-OP로 되돌리는 순간 누적출력이 튀어나옴(bump). + + 방지책: 셀렉터가 선택된 출력(LLM-OP)을 비선택 PID로 되먹임(back-calc/initialization) 해서, PID 내부 OP가 항상 현재 밸브 위치를 추종하게 만듭니다. 그러면 windup 없음 + 양방향 bumpless. (Honeywell 계열의 BACKCALC/INIT 경로) + + 보너스 — 이게 4단계의 위험을 없앱니다 + + 이 설계는 기존 "MAN으로 내려 OP 쓰고 워치독으로 AUTO 복귀"를 대체하고 더 낫습니다: + + - MAN이 필요 없음. PID는 AUTO에 둔 채 추종만 시키고, 셀렉터로 밸브 주도권만 가져옴 → 튜닝발 헌팅은 PID가 밸브에서 빠졌으니 사라짐. + - 장애 시 무충격 자동 폴백. 엔진 죽거나 운전원이 회수하면 셀렉터가 PID-OP로 → PID가 이미 현재 밸브 위치를 추종 중이므로 그 자리에서 즉시·bumpless로 규제 재개. 기존 MAN 방식의 "규제 없이 마지막 OP에 방치" 위험이 사라짐. + + → 즉 4단계 = "MAN+OP+워치독" 이 아니라 "셀렉터를 LLM-OP로 + PID는 AUTO 추종 + 컴스두절/회수 시 PID-OP로 fail-over" 로 다시 씁니다. + + 정직한 단서 — MoC 강도가 다름 + + - RSP(SP) 경로: PID에 입력 하나만 추가. 출력경로 손 안 댐 → 저위험. + - 셀렉터(OP) 경로: PID와 최종요소(밸브) 사이에 셀렉터를 삽입 → 밸브로 가는 경로를 변경. 오설정 시 밸브에 직접 영향 → 변경관리·테스트가 더 엄격해야 함. (라이브 루프면 더더욱) + + 방어 심층은 그대로: 엔진 가드 + DCS 출력한계(OPHILM/OPLOLM) + 운전원 셀렉터 + ESD/IL/SIS 독립. + + --- + 이제 SP·OP 양 경로가 대칭으로 잠겼습니다. 남은 진짜 설계 결정은 하나뿐: + + LLM-OP 모드에서 엔진이 OP에 무엇을 쓰나? 제 권장은 — "OP 고정+간헐 보정"(규제 상실)이 아니라, 물리모델(Cv 커브·배관) 피드포워드 + 느린 외부 PI를 rate제한해서 OP에 작성 = 사실상 "DCS PID가 이랬으면 했던, 잘 튜닝된 컨트롤러를 우리 소프트웨어에서 구동". 헌팅 원인이 외란이면 FF만으로도 충분하고, 약한 PI가 잔차를 잡습니다. + + 여기에 + 헌팅 임계 정의(진폭/주기/지속). + + 이 두 개 방향만 확정하면 — 컨셉, RSP/셀렉터 대칭 구조, back-calc 추종 요건, fail-over, 안전봉투, LLM 헌팅원인 진단 역할, 신뢰 이양 로드맵 — 전부 플랜 문서로 정리하겠습니다. 권장안(외부 FF+느린 PI)으로 진행할지, "고정+간헐 보정"으로 보수적으로 갈지 알려주세요. + +✻ Cooked for 58s + +❯ PID가 AUTO에서 계속 적분 → 자기 OP는 밸브에 안 가는데 적분만 쌓임(windup) → PID-OP로 되돌리는 순간 누적출력이 + ▎ 튀어나옴(bump).---> LLM OP 전환시 PID MODE를 MANUAL 전환하고, LLM OP 값이 PID OP를 겹쳐쓰게함(Bumpless output 가능) , 운전원의 PID_OP 선택시 같은 값에서 시작하게 하므로, 운전원 판단에 다라 값을 변경하면됨 + +● 맞습니다. 그게 더 단순하고, 게다가 기존 인프라로 즉시 됩니다. PID를 MAN으로 내리면 적분이 멈추니 windup 자체가 없고, MAN에서 .op에 쓰는 건 본질적으로 bumpless입니다. 이건 지금 있는 ControlOp(MD→MAN→OP쓰기) / WriteTagAsync(.op) 그대로 — 셀렉터 블록도, back-calc 배선도 불필요. MoC도 낮습니다(밸브로 가는 출력경로를 변형하지 않고, 네이티브 MAN OP 쓰기만 씀). 제 셀렉터 제안보다 이게 더 나은 기본값입니다. + + 단 하나의 결정적 요건 — 비선택 PID의 back-calculation 추종 + + 이게 OP 경로의 핵심이자 RSP 추종의 쌍입니다. 셀렉터가 LLM-OP에 있을 때, 네이티브 PID를 그냥 두면: + + ▎ PID가 AUTO에서 계속 적분 → 자기 OP는 밸브에 안 가는데 적분만 쌓임(windup) → PID-OP로 되돌리는 순간 누적출력이 튀어나옴(bump). + + 방지책: 셀렉터가 선택된 출력(LLM-OP)을 비선택 PID로 되먹임(back-calc/initialization) 해서, PID 내부 OP가 항상 현재 밸브 위치를 추종하게 만듭니다. 그러면 windup 없음 + 양방향 bumpless. (Honeywell 계열의 BACKCALC/INIT 경로) + + 보너스 — 이게 4단계의 위험을 없앱니다 + + 이 설계는 기존 "MAN으로 내려 OP 쓰고 워치독으로 AUTO 복귀"를 대체하고 더 낫습니다: + + - MAN이 필요 없음. PID는 AUTO에 둔 채 추종만 시키고, 셀렉터로 밸브 주도권만 가져옴 → 튜닝발 헌팅은 PID가 밸브에서 빠졌으니 사라짐. + - 장애 시 무충격 자동 폴백. 엔진 죽거나 운전원이 회수하면 셀렉터가 PID-OP로 → PID가 이미 현재 밸브 위치를 추종 중이므로 그 자리에서 즉시·bumpless로 규제 재개. 기존 MAN 방식의 "규제 없이 마지막 OP에 방치" 위험이 사라짐. + + → 즉 4단계 = "MAN+OP+워치독" 이 아니라 "셀렉터를 LLM-OP로 + PID는 AUTO 추종 + 컴스두절/회수 시 PID-OP로 fail-over" 로 다시 씁니다. + + 정직한 단서 — MoC 강도가 다름 + + - RSP(SP) 경로: PID에 입력 하나만 추가. 출력경로 손 안 댐 → 저위험. + - 셀렉터(OP) 경로: PID와 최종요소(밸브) 사이에 셀렉터를 삽입 → 밸브로 가는 경로를 변경. 오설정 시 밸브에 직접 영향 → 변경관리·테스트가 더 엄격해야 함. (라이브 루프면 더더욱) + + 방어 심층은 그대로: 엔진 가드 + DCS 출력한계(OPHILM/OPLOLM) + 운전원 셀렉터 + ESD/IL/SIS 독립. + + --- + 이제 SP·OP 양 경로가 대칭으로 잠겼습니다. 남은 진짜 설계 결정은 하나뿐: + + LLM-OP 모드에서 엔진이 OP에 무엇을 쓰나? 제 권장은 — "OP 고정+간헐 보정"(규제 상실)이 아니라, 물리모델(Cv 커브·배관) 피드포워드 + 느린 외부 PI를 rate제한해서 OP에 작성 = 사실상 "DCS PID가 이랬으면 했던, 잘 튜닝된 컨트롤러를 우리 소프트웨어에서 구동". 헌팅 원인이 외란이면 FF만으로도 충분하고, 약한 PI가 잔차를 잡습니다. + + 여기에 + 헌팅 임계 정의(진폭/주기/지속). + + 이 두 개 방향만 확정하면 — 컨셉, RSP/셀렉터 대칭 구조, back-calc 추종 요건, fail-over, 안전봉투, LLM 헌팅원인 진단 역할, 신뢰 이양 로드맵 — 전부 플랜 문서로 정리하겠습니다. 권장안(외부 FF+느린 PI)으로 진행할지, "고정+간헐 보정"으로 보수적으로 갈지 알려주세요. + +✻ Cooked for 58s + +❯ PID가 AUTO에서 계속 적분 → 자기 OP는 밸브에 안 가는데 적분만 쌓임(windup) → PID-OP로 되돌리는 순간 누적출력이 + ▎ 튀어나옴(bump).---> LLM OP 전환시 PID MODE를 MANUAL 전환하고, LLM OP 값이 PID OP를 겹쳐쓰게함(Bumpless output 가능) , 운전원의 PID_OP 선택시 같은 값에서 시작하게 하므로, 운전원 판단에 다라 값을 변경하면됨 + +● 맞습니다. 그게 더 단순하고, 게다가 기존 인프라로 즉시 됩니다. PID를 MAN으로 내리면 적분이 멈추니 windup 자체가 없고, MAN에서 .op에 쓰는 건 본질적으로 bumpless입니다. 이건 지금 있는 ControlOp(MD→MAN→OP쓰기) / WriteTagAsync(.op) 그대로 — 셀렉터 블록도, back-calc 배선도 불필요. MoC도 낮습니다(밸브로 가는 출력경로를 변형하지 않고, + 네이티브 MAN OP 쓰기만 씀). 제 셀렉터 제안보다 이게 더 나은 기본값입니다. + + 운전원 회수도 말씀대로 깔끔합니다: MAN에서 OP는 LLM이 쓴 마지막 값 → 운전원이 그 값에서 이어서 조정, 또는 AUTO로 올리면 PID가 현재 PV/OP에서 bumpless 재개. + + 정직하게, 이 방식이 치르는 단 하나의 비용 — 장애 모드 + + 선택+back-calc과 다른 점은 엔진이 죽었을 때입니다: + 소프트웨어에서 구동". 헌팅 원인이 외란이면 FF만으로도 충분하고, 약한 PI가 잔차를 잡습니다. + + 여기에 + 헌팅 임계 정의(진폭/주기/지속). + + 이 두 개 방향만 확정하면 — 컨셉, RSP/셀렉터 대칭 구조, back-calc 추종 요건, fail-over, 안전봉투, LLM 헌팅원인 진단 역할, 신뢰 이양 로드맵 — 전부 플랜 문서로 정리하겠습니다. 권장안(외부 FF+느린 PI)으로 진행할지, "고정+간헐 보정"으로 + 보수적으로 갈지 알려주세요. + +✻ Cooked for 58s + +❯ PID가 AUTO에서 계속 적분 → 자기 OP는 밸브에 안 가는데 적분만 쌓임(windup) → PID-OP로 되돌리는 순간 누적출력이 + ▎ 튀어나옴(bump).---> LLM OP 전환시 PID MODE를 MANUAL 전환하고, LLM OP 값이 PID OP를 겹쳐쓰게함(Bumpless output 가능) , 운전원의 PID_OP 선택시 같은 값에서 시작하게 하므로, 운전원 판단에 다라 값을 변경하면됨 + +● 맞습니다. 그게 더 단순하고, 게다가 기존 인프라로 즉시 됩니다. PID를 MAN으로 내리면 적분이 멈추니 windup 자체가 없고, MAN에서 .op에 쓰는 건 본질적으로 bumpless입니다. 이건 지금 있는 ControlOp(MD→MAN→OP쓰기) /WriteTagAsync(.op) 그대로 — + 셀렉터 블록도, back-calc 배선도 불필요. MoC도 낮습니다(밸브로 가는 출력경로를 변형하지 않고, 네이티브 MAN OP 쓰기만 씀). 제 셀렉터 제안보다 이게 더 나은 기본값입니다. + + 운전원 회수도 말씀대로 깔끔합니다: MAN에서 OP는 LLM이 쓴 마지막 값 → 운전원이 그 값에서 이어서 조정, 또는 AUTO로 올리면 PID가 현재 PV/OP에서 bumpless 재개. + + 정직하게, 이 방식이 치르는 단 하나의 비용 — 장애 모드 + + 선택+back-calc과 다른 점은 엔진이 죽었을 때입니다: + + +❯ PID가 AUTO에서 계속 적분 → 자기 OP는 밸브에 안 가는데 적분만 쌓임(windup) → PID-OP로 되돌리는 순간 누적출력이 + ▎ 튀어나옴(bump).---> LLM OP 전환시 PID MODE를 MANUAL 전환하고, LLM OP 값이 PID OP를 겹쳐쓰게함(Bumpless output 가능) , 운전원의 PID_OP 선택시 같은 값에서 시작하게 하므로, 운전원 판단에 다라 값을 + 변경하면됨 + +● 맞습니다. 그게 더 단순하고, 게다가 기존 인프라로 즉시 됩니다. PID를 MAN으로 내리면 적분이 멈추니 windup 자체가 없고, MAN에서 .op에 쓰는 건 본질적으로 bumpless입니다. 이건 지금 있는 ControlOp(MD→MAN→OP쓰기) / + WriteTagAsync(.op) 그대로 — 셀렉터 블록도, back-calc 배선도 불필요. MoC도 낮습니다(밸브로 가는 출력경로를 변형하지 않고, 네이티브 MAN OP 쓰기만 씀). 제 셀렉터 제안보다 이게 더 나은 기본값입니다. + + 운전원 회수도 말씀대로 깔끔합니다: MAN에서 OP는 LLM이 쓴 마지막 값 → 운전원이 그 값에서 이어서 조정, 또는 AUTO로 올리면 PID가 현재 PV/OP에서 bumpless 재개. + + 정직하게, 이 방식이 치르는 단 하나의 비용 — 장애 모드 + + 선택+back-calc과 다른 점은 엔진이 죽었을 때입니다: + + - 선택+back-calc(PID는 AUTO 추종 유지): 폴백 시 PID가 즉시 규제 재개. + - MAN+OP쓰기(이 방식): 엔진이 죽으면 루프가 MAN에 OP 동결 + 규제 없음 상태로 방치. 죽은 엔진은 스스로 AUTO로 못 올림. + + → 그래서 이 방식엔 DCS 측 데드맨(comms watchdog) 한 조각이 필요합니다: + + ▎ 엔진이 heartbeat/카운터를 같이 write → DCS 로직이 "N초간 갱신 없음" 감지 시 루프를 강제로 MAN→AUTO 복귀 (안전귀항 = DCS PID 규제로 fail-safe). + + 이게 유일하게 추가되는 DCS 측 안전 로직입니다. 작지만 필수 — 없으면 엔진 사망 시 무기한 동결입니다. (대부분의 유량/수위 루프는 동결이 한동안 양성이고 SIS/IL이 극단을 잡으므로, 데드맨→AUTO면 충분히 + 안전합니다.) + + 그래서 결론 — 기본값과 예외 + + ┌─────────────────────────────────────────────────┬────────────────────────────────────────┬───────────────────────────────────────────┐ + │ 루프 성격 │ 방식 │ 이유 │ + ├─────────────────────────────────────────────────┼────────────────────────────────────────┼───────────────────────────────────────────┤ + │ 대부분 (유량·수위 등) │ MAN+OP쓰기 + DCS 데드맨→AUTO ← 당신 안 │ 단순·기존인프라·저MoC. 동결이 양성 │ + + 정직하게, 이 방식이 치르는 단 하나의 비용 — 장애 모드 + + 선택+back-calc과 다른 점은 엔진이 죽었을 때입니다: + + - 선택+back-calc(PID는 AUTO 추종 유지): 폴백 시 PID가 즉시 규제 재개. + - MAN+OP쓰기(이 방식): 엔진이 죽으면 루프가 MAN에 OP 동결 + 규제 없음 상태로 방치. 죽은 엔진은 스스로 AUTO로 못 올림. + + → 그래서 이 방식엔 DCS 측 데드맨(comms watchdog) 한 조각이 필요합니다: + + ▎ 엔진이 heartbeat/카운터를 같이 write → DCS 로직이 "N초간 갱신 없음" 감지 시 루프를 강제로 MAN→AUTO 복귀 (안전귀항 = DCS PID 규제로 fail-safe). + + 이게 유일하게 추가되는 DCS 측 안전 로직입니다. 작지만 필수 — 없으면 엔진 사망 시 무기한 동결입니다. (대부분의 유량/수위 루프는 동결이 한동안 양성이고 SIS/IL이 극단을 잡으므로, + 데드맨→AUTO면 충분히 안전합니다.) + + 그래서 결론 — 기본값과 예외 + + ┌─────────────────────────────────────────────────┬────────────────────────────────────────┬───────────────────────────────────────────┐ + │ 루프 성격 │ 방식 │ 이유 │ + ├─────────────────────────────────────────────────┼────────────────────────────────────────┼───────────────────────────────────────────┤ + │ 대부분 (유량·수위 등) │ MAN+OP쓰기 + DCS 데드맨→AUTO ← 당신 안 │ 단순·기존인프라·저MoC. 동결이 양성 │ + ├─────────────────────────────────────────────────┼────────────────────────────────────────┼───────────────────────────────────────────┤ + │ 빠르고 위험해 순간 규제 공백도 불가한 소수 루프 │ 선택+back-calc (PID AUTO 추종) │ 무충격 즉시 폴백 가치가 추가 MoC를 정당화 │ + └─────────────────────────────────────────────────┴────────────────────────────────────────┴───────────────────────────────────────────┘ + + 즉 당신 방식을 기본으로, 임계 루프만 선택적으로 업그레이드. + ▎ 튀어나옴(bump).---> LLM OP 전환시 PID MODE를 MANUAL 전환하고, LLM OP 값이 PID OP를 겹쳐쓰게함(Bumpless output 가능) , 운전원의 PID_OP 선택시 같은 + 값에서 시작하게 하므로, 운전원 판단에 다라 값을 변경하면됨 + +● 맞습니다. 그게 더 단순하고, 게다가 기존 인프라로 즉시 됩니다. PID를 MAN으로 내리면 적분이 멈추니 windup 자체가 없고, MAN에서 .op에 쓰는 건 본질적으로 + bumpless입니다. 이건 지금 있는 ControlOp(MD→MAN→OP쓰기) / WriteTagAsync(.op) 그대로 — 셀렉터 블록도, back-calc 배선도 불필요. MoC도 낮습니다(밸브로 + 가는 출력경로를 변형하지 않고, 네이티브 MAN OP 쓰기만 씀). 제 셀렉터 제안보다 이게 더 나은 기본값입니다. + + 운전원 회수도 말씀대로 깔끔합니다: MAN에서 OP는 LLM이 쓴 마지막 값 → 운전원이 그 값에서 이어서 조정, 또는 AUTO로 올리면 PID가 현재 PV/OP에서 bumpless + 재개. + + 정직하게, 이 방식이 치르는 단 하나의 비용 — 장애 모드 + + 선택+back-calc과 다른 점은 엔진이 죽었을 때입니다: + + - 선택+back-calc(PID는 AUTO 추종 유지): 폴백 시 PID가 즉시 규제 재개. + - MAN+OP쓰기(이 방식): 엔진이 죽으면 루프가 MAN에 OP 동결 + 규제 없음 상태로 방치. 죽은 엔진은 스스로 AUTO로 못 올림. + + → 그래서 이 방식엔 DCS 측 데드맨(comms watchdog) 한 조각이 필요합니다: + + ▎ 엔진이 heartbeat/카운터를 같이 write → DCS 로직이 "N초간 갱신 없음" 감지 시 루프를 강제로 MAN→AUTO 복귀 (안전귀항 = DCS PID 규제로 fail-safe). + + 이게 유일하게 추가되는 DCS 측 안전 로직입니다. 작지만 필수 — 없으면 엔진 사망 시 무기한 동결입니다. (대부분의 유량/수위 루프는동결이 한동안 양성이고 + SIS/IL이 극단을 잡으므로, 데드맨→AUTO면 충분히 안전합니다.) + + 그래서 결론 — 기본값과 예외 + + ┌─────────────────────────────────────────────────┬────────────────────────────────────────┬───────────────────────────────────────────┐ + │ 루프 성격 │ 방식 │ 이유 │ + ├─────────────────────────────────────────────────┼────────────────────────────────────────┼───────────────────────────────────────────┤ + │ 대부분 (유량·수위 등) │ MAN+OP쓰기 + DCS 데드맨→AUTO ← 당신 안 │ 단순·기존인프라·저MoC. 동결이 양 │ + ├─────────────────────────────────────────────────┼────────────────────────────────────────┼───────────────────────────────────────────┤ + │ 빠르고 위험해 순간 규제 공백도 불가한 소수 루프 │ 선택+back-calc (PID AUTO 추종) │ 무충격 즉시 폴백 가치가 추가 MoC 정당화 │ + └─────────────────────────────────────────────────┴────────────────────────────────────────┴───────────────────────────────────────────┘ + + 즉 당신 방식을 기본으로, 임계 루프만 선택적으로 업그레이드. + + ▎ 튀어나옴(bump).---> LLM OP 전환시 PID MODE를 MANUAL 전환하고, LLM OP 값이 PID OP를 겹쳐쓰게함(Bumpless output 가능) , + 운전원의 PID_OP 선택시 같은 값에서 시작하게 하므로, 운전원 판단에 다라 값을 변경하면됨 + +● 맞습니다. 그게 더 단순하고, 게다가 기존 인프라로 즉시 됩니다. PID를 MAN으로 내리면 적분이 멈추니 windup 자체가 없고, MAN에서 + .op에 쓰는 건 본질적으로 bumpless입니다. 이건 지금 있는 ControlOp(MD→MAN→OP쓰기) / WriteTagAsync(.op) 그대로 — 셀렉터 블록도, + back-calc 배선도 불필요. MoC도 낮습니다(밸브로 가는 출력경로를 변형하지 않고, 네이티브 MAN OP 쓰기만 씀). 제 셀렉터 제안보다 + 이게 더 나은 기본값입니다. + + 운전원 회수도 말씀대로 깔끔합니다: MAN에서 OP는 LLM이 쓴 마지막 값 → 운전원이 그 값에서 이어서 조정, 또는 AUTO로 올리면 PID가 + 현재 PV/OP에서 bumpless 재개. + + 정직하게, 이 방식이 치르는 단 하나의 비용 — 장애 모드 + + 선택+back-calc과 다른 점은 엔진이 죽었을 때입니다: + + - 선택+back-calc(PID는 AUTO 추종 유지): 폴백 시 PID가 즉시 규제 재개. + - MAN+OP쓰기(이 방식): 엔진이 죽으면 루프가 MAN에 OP 동결 + 규제 없음 상태로 방치. 죽은 엔진은 스스로 AUTO로 못 올림. + + → 그래서 이 방식엔 DCS 측 데드맨(comms watchdog) 한 조각이 필요합니다: + + ▎ 엔진이 heartbeat/카운터를 같이 write → DCS 로직이 "N초간 갱신 없음" 감지 시 루프를 강제로 MAN→AUTO 복귀 (안전귀항 = DCS PID + ▎ 규제로 fail-safe). + + 이게 유일하게 추가되는 DCS 측 안전 로직입니다. 작지만 필수 — 없으면 엔진 사망 시 무기한 동결입니다. (대부분의 유량/수위 루프는 + 동결이 한동안 양성이고 SIS/IL이 극단을 잡으므로, 데드맨→AUTO면 충분히 안전합니다.) + + 그래서 결론 — 기본값과 예외 + + ┌───────────────────────────────────────────┬────────────────────────────────────┬────────────────────────────────────────┐ + │ 루프 성격 │ 방식 │ 이유 │ + ├───────────────────────────────────────────┼────────────────────────────────────┼────────────────────────────────────────┤ + │ 대부분 (유량·수위 등) │ MAN+OP쓰기 + DCS 데드맨→AUTO ← │ 단순·기존인프라·저MoC. 동결이 양성 │ + │ │ 당신 안 │ │ + ├───────────────────────────────────────────┼────────────────────────────────────┼────────────────────────────────────────┤ + │ 빠르고 위험해 순간 규제 공백도 불가한 │ 선택+back-calc (PID AUTO 추종) │ 무충격 즉시 폴백 가치가 추가 MoC를 │ + │ 소수 루프 │ │ 정당화 │ + └───────────────────────────────────────────┴────────────────────────────────────┴────────────────────────────────────────┘ + + 즉 당신 방식을 기본으로, 임계 루프만 선택적으로 업그레이드. + + --- + 이제 SP(RSP)·OP(MAN+OP쓰기+데드맨) 양 경로가 다 잠겼습니다. 남은 마지막 한 가지 — LLM-OP 모드의 제어법 — 에 대한 제 권장은: + │ 빠르고 위험해 순간 규제 공백도 불가한 │ 선택+back-calc (PID AUTO 추종) │ 무충격 즉시 폴백 가치가 추가 MoC를 │ + │ 소수 루프 │ │ 정당화 │ + └───────────────────────────────────────────┴────────────────────────────────────┴────────────────────────────────────────┘ + + 즉 당신 방식을 기본으로, 임계 루프만 선택적으로 업그레이드. + + --- + 이제 SP(RSP)·OP(MAN+OP쓰기+데드맨) 양 경로가 다 잠겼습니다. 남은 마지막 한 가지 — LLM-OP 모드의 제어법 — 에 대한 제 권장은: + + ▎ 물리모델(Cv 커브·배관) 피드포워드 + 느린 외부 PI, rate제한. 외란발 헌팅은 FF만으로 잡히고, 약한 PI가 잔차 보정. = "DCS PID가 + ▎ 이랬으면 했던 잘 튜닝된 컨트롤러를 우리 소프트웨어에서 느리게 구동". "고정+간헐 보정"은 규제를 잃어 비권장. + + 이 권장안으로 확정하면, 지금까지 합의된 전체를 플랜 문서로 정리하겠습니다: + + - 컨셉 & §0 원칙 + - RSP 기반 SP 경로 (감독소스 포인트 + 외부추종 + 운전원 LSP/RSP) + - MAN+OP 기반 OP 경로 (ControlOp + DCS 데드맨→AUTO, 선택+back-calc은 임계루프 옵션) + - 헌팅 검출(결정론) + 원인진단(LLM: 튜닝 vs stiction vs 외란) + - 안전봉투(rate·절대·변동폭·데드맨·ESD/IL/SIS 독립) + - 신뢰 이양 로드맵(1~4단계) + - LLM 역할(물리 결정론 위의 진단·예외·인터페이스·커미셔닝) + + 권장 제어법(FF+느린 PI)으로 갈지 알려주시면 바로 문서로 정리하겠습니다. (보수적으로 "고정+간헐 보정"을 원하시면 그걸로 + 반영합니다.) + +✻ Crunched for 58s + +❯ MAN+OP쓰기(이 방식): 엔진이 죽으면 루프가 MAN에 OP 동결 + 규제 없음 상태로 방치. 죽은 엔진은 스스로 AUTO로 못 올림.----> 엔진 + WATCHDOG은 당연히 만들어야 할 것이고, WATCHDOG 발생시 , CONTROLLER LOGIC -> PID AUTO MODE 로 하면 해결됨--> OP가 LLM_OP에서 + 시작하므로, PID 적산 IMPULSE 출력도 없을 것임, PID LOOP 는 BUMPLESS OUTPUT 설정 되어 있슴 + +● 정확합니다. 그러면 완전히 닫힙니다. DCS PID가 bumpless output으로 설정돼 있으니, 워치독→AUTO 전환 시 적분항이 현재 + OP(=LLM_OP)에서 back-calc 초기화 → 적분 임펄스 없이 그 자리에서 규제 재개. 셀렉터+back-calc 없이도 동일한 "무충격 즉시 폴백"을 + 얻습니다 — 그래서 기본값으로 셀렉터는 아예 불필요합니다. + + 확인용 두 가지만 (반론 아님, 설정 체크): + + 1. MAN 중 SP 추종/홀드 설정 — 폴백 후 AUTO가 어떤 LSP로 규제할지가 여기서 정해집니다. SP가 PV 추종이면 전환 시점 PV에 머물고, + SP 홀드면 운전원 목표값으로 복귀(출력은 여전히 bumpless, PI가 천천히 끌고 감). 어느 쪽이 의도인지만 맞춰두면 됩니다. + 2. 이 시나리오 특유의 정직한 단서 — 우리가 OP를 가져온 이유가 그 PID가 헌팅이라서입니다. 따라서 폴백은 헌팅하던 그 PID로 + 되돌아갑니다 → 안전(규제됨, SIS가 극단 차단)하지만 엔진 복구/운전원 개입 전까지 헌팅이 재개됩니다. 위험은 아니고 단지 차선 — + 문서에 명시만 해두면 됩니다. + + --- + 이로써 양 경로가 완전히 잠겼습니다: + - SP: 감독소스 → RSP, 외부추종, 운전원 LSP/RSP 토글 + - OP: MAN + .op write, 엔진 워치독 + DCS 컨트롤러 로직이 stale 감지 → MAN→AUTO(bumpless) 폴백 + + 남은 마지막 결정은 LLM-OP 모드의 제어법 하나뿐입니다. 제 권장(재확인): + + ▎ 물리 FF(Cv 커브·배관) + 느린 외부 PI, rate제한 — 외란발 헌팅은 FF로, 잔차는 약한 PI로. "고정+간헐 보정"은 규제 상실이라 + ▎ 비권장. + + 이걸로 확정해도 될까요? 확정 주시면 — 컨셉/§0 원칙, RSP SP경로, MAN+OP OP경로(+데드맨 폴백), 헌팅 검출(결정론)+원인진단(LLM), + 안전봉투, 1~4단계 신뢰이양, LLM 역할 — 전부 측류추출-자동운전-플랜.md에 정식 섹션으로 추가하겠습니다. + +✻ Crunched for 44s + +❯ 물리 FF(Cv 커브·배관) + 느린 외부 PI, rate제한 — 외란발 헌팅은 FF로, 잔차는 약한 PI로. "고정+간헐 보정"은 규제 상실이라 + ▎ 비권장. --> 나의 이해가 부족함 좀 더 명확하게 설명해주세요 + +● 좋습니다, 천천히 직관부터 쌓아가겠습니다. 핵심 상황은 이겁니다: MAN으로 내린 순간부터 밸브 개도(OP%)를 매 순간 "우리"가 정해야 + 합니다. DCS PID가 더 이상 규제 안 하니까요. 그럼 OP를 무슨 근거로 정하나? 두 가지 정보원을 씁니다. + + 1. 먼저 운전 비유 (정속주행 = cruise control) + + 차로 100km/h를 유지한다고 합시다. + + ┌────────────────┬────────────────────────────────────────────────────────────────────────┬────────────────────────────────┐ + │ 방법 │ 하는 일 │ 결과 │ + ├────────────────┼────────────────────────────────────────────────────────────────────────┼────────────────────────────────┤ + │ 피드포워드(FF) │ 언덕이 보이면 차가 느려지기 전에 미리 가속페달을 더 밟음 (이 언덕엔 │ 속도가 거의 안 떨어짐 │ + │ │ 대략 이만큼 필요하다는 걸 앎) │ │ + ├────────────────┼────────────────────────────────────────────────────────────────────────┼────────────────────────────────┤ + │ 피드백(PI) │ 계기판이 "98km/h, 2 부족"을 보여주면 그만큼만 살짝 더 밟아 보정 │ 잔차 제거 │ + ├────────────────┼────────────────────────────────────────────────────────────────────────┼────────────────────────────────┤ + │ 고정+간헐 보정 │ 페달을 한 위치에 고정, 30초마다 한 번씩만 조정 │ 언덕에서 푹 꺼졌다가 뒤늦게 │ + │ │ │ 복구 → 출렁임 │ + ├────────────────┼────────────────────────────────────────────────────────────────────────┼────────────────────────────────┤ + │ rate 제한 │ 페달을 확 밟지 않고 부드럽게 밟음 │ 차가 안 울컥거림 │ + └────────────────┴────────────────────────────────────────────────────────────────────────┴────────────────────────────────┘ + + FF + PI = 사실상 크루즈컨트롤. 언덕을 미리 보고(FF) + 계기판 잔차를 다듬는다(PI). 이게 우리가 OP에 쓰려는 제어법입니다. + + 2. 이 플랜트로 매핑 + + - "언덕"(외란) = 원료 F의 헌팅(±5%). 원본 문서의 그 문제. + - "이 속도엔 가스 이만큼"(물리 지식) = 밸브 Cv 커브. 원하는 유량 Q와 현재 차압 ΔP를 알면 필요한 개도를 직접 계산: 개도% = Cv⁻¹( + Q / √(ΔP/SG) ). 측정 오차가 쌓이길 기다릴 필요 없이 바로 정답 개도를 압니다. + + FF가 하는 일 (외란발 헌팅을 잡는 핵심) + + 1. 원료 F를 필터링(Lag 300s, 플랜의 그것) → F_clean (헌팅 제거된 부드러운 신호) + 2. 물질수지로 목표 발출유량 계산 (B/D/P) + 3. Cv 커브로 각 목표유량 → 정확한 OP% 계산 + 4. 플랜의 시간상수(B 1~2분 / D 5분 / P 15~20분)로 부드럽게 그 OP로 이동 + + → F가 출렁여도 우리는 필터링된 F로 미리 정답 OP를 계산해 부드럽게 가니까, 밸브가 홱홱 안 움직임 → 헌팅 소멸. (옛 PID는 F + 출렁임을 그대로 받아 밸브를 잡아채서 헌팅했던 것) + + PI가 하는 일 (FF의 오차 청소) + + Cv 커브는 신품 설계값입니다. 밸브 마모·파울링·ΔP 부정확 때문에 FF만으론 살짝 빗나갑니다. 예: 목표 50인데 실제 48. + + → 느린 PI가 잔차(+2)를 보고 OP를 천천히 조금 더 열어 50으로 맞춤. + "느리게/약하게" 인 이유: ①헌팅을 다시 일으킬 만큼 세게 잡아채면 안 됨 ②큰 일은 FF가 이미 했으니 PI는 자투리만 다듬으면 됨. + + 3. 한 줄 공식 + + OP = FF(Cv·배관 물리로 계산한 예측 개도) ← 큰 움직임, 미리, 부드럽게 + + PI(설정값 − 실측 PV, 느린 게인) ← 작은 잔차만 청소 + → rate 제한 + 절대 min/max + 변동폭 제한 ← 안전 봉투 + + 4. 왜 "고정+간헐 보정"은 비권장인가 + + OP를 고정해두고 가끔만 건드리면, 건드리는 사이사이엔 능동 규제가 0입니다. F가 변하거나 ΔP가 드리프트하면 PV가 흘러가는데 다음 + 보정 때까지 아무도 안 잡습니다 → PV 드리프트. 즉 피드백 규제를 통째로 버리는 것. 느린 PI라도 연속적으로 잡아주는 것과 + 근본적으로 다릅니다. (= 크루즈컨트롤 vs 페달 고정) + + 5. 이미 만든 플랜과의 연결 + + 새 개념이 아닙니다: + - FF = 우리가 설계한 결정론 보상 엔진 (필터 → 물질수지 → Cv → OP, 시간상수 적용) 그대로 + - PI = 그 위에 얹는 작은 피드백 트림 하나 추가 + + F(헌팅) ─filter→ F_clean ─물질수지→ 목표유량 ─Cv커브→ OP_ff ┐ + ├→ OP → rate제한 → 밸브 + 설정값 − 실측PV ───────────── 느린 PI ──────────→ OP_pi ┘ + + --- + 정리하면: FF는 "물리로 미리 계산한 부드러운 큰 움직임"(헌팅 차단), PI는 "모델 오차만 천천히 청소하는 작은 피드백"(정확도 확보). + 둘이 상호보완이고, 고정+간헐은 피드백을 버려서 PV가 드리프트하므로 안 씁니다. + + 이 설명으로 명확해지셨나요? 막히는 부분 있으면 더 풀어드리고, 괜찮으시면 이 제어법을 확정으로 플랜 문서에 반영하겠습니다. + +✻ Cooked for 57s + +❯ 이해됐어, 이제 플랜 문서에 반영해줘 + +● 전체 논의를 통합해 플랜 문서를 개정하겠습니다. 먼저 현재 내용을 확인합니다. + + Read 1 file (ctrl+o to expand) + +● 전체 논의를 통합해 문서를 전면 개정하겠습니다. + +● Write(측류추출-자동운전-플랜.md) + +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Overwrite file + 측류추출-자동운전-플랜.md +╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ + 1 # 측류 추출 증류탑(C-6111) — 로컬 LLM 기반 자동운전 플랜 + 2 + 3 > **목적**: `측류추출-시간지연-적용방식.md`의 시간지연/시차 보상 제어를 ExperionCrawler 시스템 위에서 + 4 -> **로컬 LLM(vLLM Qwen)** 과 결합해 자동운전(Autopilot)으로 구현하기 위한 컨셉·아키텍처·선택사항 기록. + 4 +> 구현하되, **운전원이 단계적으로 신뢰를 쌓아 권한을 넘기는** 감독제어(Supervisory Control) 형태의 + 5 +> 자동운전을 설계한다. 결정론 엔진이 제어하고, 로컬 LLM(vLLM Qwen)은 그 위에서 진단·예외·인터페이스를 맡는다. + 6 > + 6 -> 문서 성격: **설계/의사결정 기록**. 구현 착수 전 합의용. 코드 미작성 상태. + 7 +> 문서 성격: **설계/의사결정 기록**. 구현 착수 전 합의 완료본. 코드 미작성 상태. + 8 + 8 -*작성일: 2026-05-22 / 대상: C-6111 PGMEA 진공 측류추출 증류탑 (P6 영역)* + 9 +*작성일: 2026-05-22 / 갱신: 2026-05-22 (논의 합의 반영) / 대상: C-6111 PGMEA 진공 측류추출 증류탑 (P6 영역)* + 10 + 11 --- + 12 + 12 -## 0. 핵심 원칙 (가장 중요) + 13 +## 0. 핵심 원칙 + 14 + 14 -**LLM을 빠른 제어 루프에 넣지 않는다.** + 15 +**LLM을 빠른 제어 루프에 넣지 않는다.** 빠른 보상은 결정론 엔진(코드)이, LLM은 분/이벤트 단위 진단·튜닝·인터페이스만. + 16 + 16 -`측류추출-시간지연-적용방식.md`가 말하는 "1분/5분/15~20분 지연 보상"은 초 단위로 결정론적으로 돌아야 + 17 -하는 빠른 루프다. 여기에 LLM을 직접 넣으면: + 18 - + 17 | 문제 | 영향 | + 18 |------|------| + 19 | 비결정성 | 같은 입력에 다른 출력 → 밸브 제어에 치명적 | + 20 | 지연(latency) | 토큰 생성 수 초 → Flooding 즉시 대응 불가 | + 23 -| 환각 | 잘못된 SV 한 줄이 바로 밸브로 → 측류 순도 영역 파괴 | + 21 +| 환각 | 잘못된 값 한 줄이 바로 밸브로 → 측류 순도 영역 파괴 | + 22 + 25 -→ **결론**: 빠른 보상은 **결정론 엔진(코드)** 이 담당하고, **LLM은 분 단위 감독·튜닝·조언만** 한다. + 26 -이것이 LLM을 실공정에 붙이는 유일하게 안전한 형태다. + 23 +따름정리: **헌팅 검출·MAN 전환·OP 산출 등 안전·실시간 판단은 모두 결정론.** LLM은 그 트립을 *설명*하고 + 24 +*원인을 진단*할 뿐, 직접 트립시키거나 OP를 쓰지 않는다. + 25 + 26 --- + 27 + 30 -## 1. 2-Plane 아키텍처 + 28 +## 1. 물리 결정론 vs LLM — 역할 경계 (이 플랜의 출발점) + 29 + 32 -``` + 33 -┌─ Plane 2: LLM 감독 (MCP, 분/이벤트 단위, 느림) ───────────────┐ + 34 -│ · Step Test 곡선 분석 → θ(데드타임)·τ(시상수) 자동 추출 │ + 35 -│ · 파라미터(K, τ, 한계값) 튜닝 제안 │ + 36 -│ · 헌팅 / Flooding / 순도 드리프트 이상 감지·자연어 설명 │ + 37 -│ · 운전원 Q&A ("왜 제품밸브가 천천히 열려요?") │ + 38 -│ │ ※ 밸브 직접 쓰기 금지. "엔진 파라미터 저장소"에만 │ + 39 -│ │ 제안 → 운전원 승인 후 반영 │ + 40 -├─────────┼──────────────────────────────────────────────────────┤ + 41 -│ 🔒 안전 가드 레이어 (신규, 0순위) ─ 모든 쓰기가 강제 통과 │ + 42 -│ hard min/max · 변화율(rate) 제한 · dead band · 태그 화이트 │ + 43 -│ 리스트 · 통신두절→안전SV 폴백 · 전 쓰기 감사로그 │ + 44 -├─────────┼──────────────────────────────────────────────────────┤ + 45 -│ Plane 1: 결정론 보상 엔진 (신규 BackgroundService, 초 단위) │ + 46 -│ Realtime 구독으로 F(원료유량) 읽기 │ + 47 -│ → Lag(τ=300s) 필터로 헌팅 제거 → F_clean │ + 48 -│ → B_sv(데드타임 1~2분) / D_sv(5분) / P_sv(15~20분) 계산 │ + 49 -│ → 가드 통과 후 WriteTagAsync / ControlOp 로 쓰기 │ + 50 -└────────────────────────────────────────────────────────────────┘ + 51 - 읽기: ExperionRealtimeService · query_pv_history + 52 - 쓰기: IExperionOpcWriteClient (가드 레이어 경유 필수) + 53 -``` + 30 +운영자가 **밸브 사이즈·배관 종류·컨트롤밸브 Cv 값/Cv 커브·플로우미터 유량범위** 등 물리 데이터를 + 31 +보유하면, 제어 수학의 상당 부분이 *데이터 피팅 없이 계산*된다. + 32 + 55 ---- + 33 +### 1.1 물리 데이터로 결정론화되는 것 (LLM 불필요) + 34 +| 물리 데이터 | 계산되는 모델 | + 35 +|------------|--------------| + 36 +| Cv 커브(설치특성) | OP(%) → 유량 관계, 밸브 게인 dQ/dOP | + 37 +| 배관 종류·구경·길이 | ΔP·마찰, 이송 데드타임 θ = 관내체적/유량 | + 38 +| 드럼/트레이 홀드업 체적 | 체류시간 τ = 체적/유량 (D-6113 환류드럼 등) | + 39 +| 플로우미터 레인지 | 스케일링·분해능·노이즈 플로어 | + 40 + 57 -## 2. 보상 제어 수식 (Plane 1 — 결정론, LLM 아님) + 41 +→ 자동운전의 **B(하부)·D/R(상부) 타이밍은 하이드롤릭 홀드업(=체적/유량)으로 직접 계산**된다. + 42 +밸브 게인도 Cv 커브 미분으로 나온다. **이 부분은 그냥 프로그램한다.** + 43 + 59 -원본 문서 §2·§4 기준. + 44 +### 1.2 물리 데이터가 못 주는 것 + 45 +- **(가) 분리/조성 동특성** — P(측류)의 "15~20분" 지연은 배관 이송이 아니라 트레이 홀드업+기액평형(VLE)으로 + 46 + 새 조성이 자리잡는 시간. 상대휘발도·트레이 효율·VLE는 Cv 커브에 없음. → **B·D는 물리로 계산되지만 P는 별도 모델 필요.** + 47 +- **(나) 모델-플랜트 불일치(드리프트)** — Cv 커브는 신품 설계값. 밸브 stiction·마모, E-6103 파울링, 트레이 효율 저하로 시 + +간에 따라 어긋남. + 48 +- **(다) 목적·맥락·예외** — 회수율 최대 vs 에너지 최소 vs 순도 사수, 등급변경, 기동/정지, 계기고장, 상류 외란. + 49 + 61 -- **1차 지연(Lag) 필터** (이산): `y[k] = y[k-1] + (Δt/τ) · (x[k] − y[k-1])` + 62 -- **데드타임(Dead Time)**: 링버퍼로 N틱 지연 + 63 -- **헌팅 제거**: 원료 FT 신호 직후 Lag 필터 τ=**300초(3~5분)** 1개 (원본 §4.1 "1순위 대책") + 50 +### 1.3 따라서 LLM이 실제로 하는 일 + 51 +> **LLM의 가치는 물리모델 품질에 반비례.** 물리를 잘 잡을수록 LLM은 제어 산수에서 빠지고 가장자리로 이동. + 52 + 65 -| MV | 제어 대상 | τ / 데드타임 | 목적 | + 66 -|----|----------|-------------|------| + 67 -| B | 하부 제거량 | 1~2분 | 탑 넘침(Flooding) 즉시 방지 | + 68 -| D/R | 상부 제거량/환류 | 5분 | 압력/조성 안정화 | + 69 -| P | 측류 제품 추출 | 15~20분 | 초고순도 PGMEA 품질 보호 (가장 보수적) | + 70 -| S | 리보일러 스팀 | 가장 빠름(수초~수분) | 하부 온도 직결 | + 53 +| LLM 역할 | 구체 | 가치 | + 54 +|---------|------|------| + 55 +| ① 커미셔닝 보조 | 밸브 데이터시트·Cv 커브·배관 스펙 파싱 → 엔진 config/코드로 조립, 정합성 점검 | ★★ | + 56 +| ② 드리프트 진단((나)) | 물리예측 vs 실측 잔차는 수학, *"이 OP·ΔP에서 8% 미달 → 밸브 파울링/마모 의심"* 해석·재교정 트리 + +거는 LLM | ★★ | + 57 +| ③ 소프트센서 보조((가)) | 측정 안 되는 조성을 온도(TI-6111B/C)로 추론, 분석기 결측 보간 | ★ | + 58 +| ④ 감독형 예외 처리((다)) | 엔진이 프로그램 안 된 상황(기동·등급변경·상류 업셋·계기고장) 판단·완화 | ★★★ | + 59 +| ⑤ 운전원 인터페이스 | 의도/경제목표 → SV·제약 번역, "왜 이렇게 도는지" 설명 | ★★★ | + 60 +| ⑥ 교차 데이터 융합 | 알람+이벤트+랩분석+정비이력+물리잔차 엮어 진단 (기존 MCP 도구) | ★★★ | + 61 +| ⑦ 헌팅 원인 진단 | 튜닝 vs stiction vs 외란 판별 → 4단계(OP 개입) 적용 여부 게이트 (§4.3) | ★★★ | + 62 + 72 -추가 안전요소(원본 §4.2/§4.3): 각 PID 블록 **dead band 0.5~1.0%**, 원료탱크 **Surge Control**(P-Gain↓ I-Time↑). + 73 - + 63 --- + 64 + 76 -## 3. 현 시스템에서 확인된 능력 (재사용 자산) + 65 +## 2. 감독제어 아키텍처 — 운전원이 권한을 쥔다 + 66 + 78 -### 3.1 쓰기 (이미 구현됨) + 79 -| 기능 | 구현 | 엔드포인트 | + 80 -|------|------|-----------| + 81 -| SP/OP 직접 쓰기 | `ExperionOpcWriteClient.WriteTagAsync(cfg, nodeId, value)` | `POST /api/experion/write` | + 82 -| MAN/AUTO 모드 | `SetModeAsync(cfg, nodeId, "MAN"\|"AUTO")` | `POST /api/experion/mode` | + 83 -| 통합 제어 (MD→MAN → OP쓰기 → AUTO복귀) | `ControlOp(TagName, OpValue, RestoreAuto)` | `POST /api/experion/control` | + 84 -| UI | "OPC UA Write" 탭 (#15) | `index.html #pane-write` | + 67 +핵심 설계 사상: **엔진은 PID 루프의 SP/OP 레지스터를 직접 덮어쓰지 않는다.** 별도 감독변수에 쓰고, + 68 +**운전원이 스위치로 채택**한다. 권한 손잡이는 항상 운전원에게 있다. SP 경로와 OP 경로가 대칭이다. + 69 + 86 -### 3.2 읽기 + 87 -- `ExperionRealtimeService` — 실시간 PV 구독 (`AddMonitoredItemAsync`), `IHostedService` + 88 -- `query_pv_history` (MCP) / `ExperionHistoryController` — Step Test용 시계열 + 70 +| | SP 경로 (평상시) | OP 경로 (헌팅 시) | + 71 +|---|------------------|-------------------| + 72 +| 엔진이 쓰는 곳 | RSP 소스 포인트 (별도 변수) | `.op` (PID MAN 상태에서) | + 73 +| 운전원 스위치 | **LSP ↔ RSP** (Local ↔ Remote SP = AUTO↔CAS) | **PID MODE: AUTO ↔ MAN** | + 74 +| 빠른 규제 담당 | DCS PID (그대로 둠) | 엔진(소프트웨어 컨트롤러) | + 75 +| 폴백(엔진 사망) | 운전원이 LSP로 토글 | 데드맨 → MAN→AUTO (bumpless) | + 76 +| 적용 | 1~3단계 (신뢰 이양) | 4단계 (튜닝발 헌팅 한정) | + 77 + 90 -### 3.3 백그라운드 서비스 패턴 + 91 -- `IHostedService`/`AddHostedService` 이미 Realtime·History·OpcServer·Mcp에서 사용 중 + 92 - → 신규 `AutoRunService : BackgroundService`가 기존 패턴에 그대로 들어감 + 78 +### 2.1 SP 경로 — RSP(Remote Setpoint) + 79 +- 엔진은 **루프 SP를 절대 안 건드림.** 자기 감독소스 포인트에만 OPC write → 그 포인트가 PID의 RSP/X 입력에 control connec + +tion. + 80 +- 운전원의 **LSP/RSP 토글이 유일한 권한 손잡이.** RSP면 엔진 SP 추종, LSP면 운전원 수동 — 언제든 가역. + 81 +- **bumpless 요건(중요)**: OPC 외부 감독은 DCS의 back-calculation 핸드셰이크를 못 받음. + 82 + → 루프가 LSP(미선택)일 때 엔진이 **현재 실작동 SP를 읽어 자기 출력=현재 SP로 추종**시켜야 함. + 83 + 그래야 운전원이 RSP로 토글하는 순간 충격 없음. + 84 +- **공짜 안전망**: DCS RSP 한계(SPHILM/SPLOLM, RSP rate)가 엔진과 독립으로 한 겹 더. + 85 +- **장점**: 1~2단계(제안 표시)는 페이스플레이트가 RSP 후보값을 네이티브로 보여줌 → **별도 화면 개발 불필요.** + 86 + 94 -### 3.4 LLM 감독용 MCP 도구 (기존) + 95 -- `query_pv_history`, `find_tags`, `trace_connections`, `active_alarms`, `query_events`, + 96 - `summarize_events`, `generate_status_report`, ReAct 에이전트 모드(구현됨) + 87 +### 2.2 OP 경로 — MAN + OP 쓰기 (튜닝발 헌팅 전용) + 88 +- 평상시 RSP로는 **튜닝발 헌팅이 안 잡힘**(PID가 루프에 그대로). 그래서 헌팅 루프에 한해 OP를 직접 잡는다. + 89 +- 방식: PID를 **MAN**으로 → 엔진이 `.op`에 직접 write. **MAN이라 적분이 멈춰 windup 없음, OP 쓰기는 본질적 bumpless.** + 90 + 기존 `ControlOp`(MD→MAN→OP쓰기) / `WriteTagAsync(.op)` 그대로 사용 → **신규 DCS 구성 불필요, 저MoC.** + 91 +- **운전원 회수**: MAN의 OP는 엔진이 쓴 마지막 값 → 운전원이 그 값에서 이어 조정, 또는 AUTO로 올림. + 92 +- **폴백(엔진 사망)**: 엔진 워치독 + **DCS 컨트롤러 로직이 stale(N초 갱신 없음) 감지 → MAN→AUTO 강제 복귀.** + 93 + PID가 bumpless output 설정이라 **현재 OP(=마지막 LLM_OP)에서 적분 임펄스 없이 규제 재개.** + 94 + - *정직한 단서*: 폴백은 "헌팅하던 그 PID"로 돌아감 → 안전(규제됨, SIS가 극단 차단)하나 **엔진 복구 전까지 헌팅 재개.** + +위험 아님, 차선. + 95 + - 설정 확인: MAN 중 SP 추종/홀드 → 폴백 후 어떤 LSP로 규제할지 결정. + 96 +- **상위 옵션(임계 루프 한정)**: *순간 규제 공백도 불가*한 빠른 루프는 선택+back-calc(PID는 AUTO 추종 유지, 무충격 즉시 + +폴백)을 쓰되, 밸브 출력경로를 변형하므로 MoC가 더 엄격. 기본값은 위 MAN 방식. + 97 + 98 --- + 99 + 100 -## 4. ⚠️ 안전 관련 발견 사항 (자동운전 전 반드시 처리) + 100 +## 3. LLM-OP 모드의 제어법 — FF + 느린 PI (rate 제한) + 101 + 102 -1. **쓰기 경로에 안전 가드가 0건.** `WriteTagAsync`는 들어온 double을 그대로 쓴다 — + 103 - min/max 클램프·rate limit·범위 검증·변화율 제한 전무. 사람이 UI에서 손으로 쓸 땐 운전원이 + 104 - 최종 안전망이지만, **엔진이 자동으로 쓰는 순간 안전망이 사라진다.** → **0순위: 가드 레이어.** + 105 -2. **현재 LLM(MCP)에는 쓰기 도구가 없다.** 쓰기는 Web UI/HTTP 전용 → 지금은 "사람만 쓸 수 있는" + 106 - 상태가 유일한 안전 경계. 자동운전을 붙이면 이 경계를 넘게 됨 → 신중한 권한 설계 필요. + 107 -3. **`ask_iiot_llm`(vLLM 직접 질의) MCP 도구가 빈 응답.** 2회 시도 모두 `(응답 없음)`. + 108 - vLLM 엔드포인트 상태/연결 점검 필요. (단 `find_tags`/`trace_connections`는 정상 동작.) + 102 +OP 경로로 개입한 동안 엔진이 매 순간 OP에 무엇을 쓰는가. **크루즈컨트롤과 동일 구조**: 미리 예측(FF) + 잔차 청소(PI). + 103 + 104 +``` + 105 +F(헌팅) ─Lag필터→ F_clean ─물질수지→ 목표유량 ─Cv커브→ OP_ff ┐ + 106 + ├→ OP → rate제한 → 절대/변동폭 클램프 → 밸브 + 107 +설정값 − 실측PV ───────────────── 느린 PI ───────→ OP_pi ┘ + 108 +``` + 109 + + 110 +- **FF (피드포워드)**: 물리로 *미리* 정답 개도 계산. `개도% = Cv⁻¹( Q / √(ΔP/SG) )`. + 111 + 필터링된 F_clean로 목표유량(B/D/P)을 물질수지로 구하고 → Cv 커브로 OP 계산 → §5 시간상수로 부드럽게 이동. + 112 + **외란발 헌팅을 잡는 주역**(반응이 아니라 예측이라 밸브가 안 채인다). + 113 +- **PI (느린 피드백)**: Cv 커브는 신품값이라 마모·파울링·ΔP 부정확으로 살짝 빗나감. 잔차(SP−PV)를 + 114 + **느리게/약하게** 보정. 약한 이유: ①헌팅 재유발 방지 ②큰 일은 FF가 이미 함. + 115 +- **rate 제한**: OP 변화율 제한으로 밸브 부드럽게. + 116 +- **비채택: "고정+간헐 보정"** — 보정 사이 능동 규제 0 → 외란 시 PV 드리프트(피드백 상실). 사용 안 함. + 117 +- **연결**: FF = §5 결정론 보상 엔진 그대로 + 그 위에 작은 PI 트림 하나. + 118 + + 119 --- + 120 + 112 -## 5. 태그/노드 매핑 (실측 — `find_tags`·`trace_connections` 기반) + 121 +## 4. 헌팅 검출 & 원인 진단 — 4단계의 게이트 + 122 + 114 -`trace_connections`가 돌려준 원료 경로: + 115 -``` + 116 -P-6101(원료펌프) → FT-6101 → FICQ-6101 → FCV-6101 → E-6103(예열) → C-6111 원료 스프레이 분배기 + 117 -``` + 123 +### 4.1 검출 (결정론) + 124 +- 오실레이션 인덱스: 진폭·주기·지속성. 임계 초과(예: 진폭 > 범위의 X%, 주기 안정, N분 지속) 시 트립. + 125 +- **MAN 전환 트립은 결정론**(LLM 지연 불가). LLM은 트립을 설명만. + 126 + 119 -| # | 경로 | 조작변수(MV)/제어 | 유량 | 온도 | 수위/압력 | τ | + 120 -|---|------|------------------|------|------|----------|---| + 121 -| **F** | 원료 투입 | **FICQ-6101**(SP/OP)→FCV-6101 | FT-6101 | (E-6103 예열) | — | 입력신호(Lag 300s) | + 122 -| **S** | 리보일러 스팀 | 스팀밸브(리보일러 듀티) | **FI-6115** | TI-6111A(BOT), TICA-6111A | PI-6700(스팀압) | 가장 빠름 + - | + 123 -| **B** | 하부 제거 | 하부 발출 밸브 *(밸브태그 미확인)* | (미확인) | TI-6111A(BOT) | **LI-6111**(하부수위) | 1~2분 | + 124 -| **D/R** | 상부/환류 | **FICQ-6113**(PV29.9/SP36.4) | FI-6113 | TI-6111D(TOP) | **LI-6113**(D-6113 환류드럼), LICA-6113, + - PI-6111(진공), PICA-6111 | 5분 | + 125 -| **P** | 측류 제품 | **🔲 사용자 매핑 예정** | FI-6120(PGMEA) | TI-6111B/C(MID) | LI-6121/6122/6123(제품탱크) | 15~20분 + -| + 127 +### 4.2 원인 분류 (LLM + 데이터 융합) — §1.3-⑦ + 128 +| 원인 | 4단계(MAN+OP)로 잡히나 | 조치 | + 129 +|------|----------------------|------| + 130 +| 튜닝 과민 | ✅ 즉시 | MAN 전환 → FF+PI로 OP 핸드홀딩 | + 131 +| 상류 외란 | ✅ 잘 잡힘 | 동일(FF가 주역) | + 132 +| 루프 간섭 | ⚠️ 부분 | 시차 조절로 완화 | + 133 +| **밸브 stiction** | ❌ 악화 | **정비 플래그.** OP 핸드홀딩 금지(마모만 늘어남) | + 134 + 127 -- OPC Node 형식: `ns=1;s=sinamserver:ficq-6101.sp` / `.op` / `.md`(MAN=0/AUTO=1) + 128 -- 현재 운전 데이터 흔적: FICQ-6113 PV 29.9 / SP 36.4 추종 중, 진공압 PICA-6111 30.4 → 탑 가동 중으로 추정 + 135 +→ LLM이 OP-PV 위상·한계주기 파형·상류 신호·정비이력을 엮어 *"이건 stiction → 4단계 말고 정비"* vs + 136 +*"외란 → 4단계 유효"* 판정. **초기엔 LLM 진단 → 운전원 확인 권장.** + 137 + 130 -### 5.1 미완료 매핑 (담당 구분) + 131 -- **P(측류 제품 추출) 경로 매핑 — 사용자가 직접 진행 예정** (본 플랜에서는 보류) + 132 -- B(하부 제거) 발출 유량계·밸브 태그 — `find_tags`(6112/6114/6116번대) 또는 + 133 - C-6111 `trace_connections downstream`로 보강 가능 (착수 시 확정) + 138 +--- + 139 + 140 +## 5. 보상 제어 수식 (결정론, FF의 본체) + 141 + + 142 +원본 문서 §2·§4 기준. + 143 +- **1차 지연(Lag) 필터** (이산): `y[k] = y[k-1] + (Δt/τ) · (x[k] − y[k-1])` + 144 +- **데드타임**: 링버퍼로 N틱 지연 + 145 +- **헌팅 제거**: 원료 FT 신호 직후 Lag 필터 τ=**300초(3~5분)** (원본 §4.1) + 146 + + 147 +| MV | 제어 대상 | τ / 데드타임 | 근거 | 목적 | + 148 +|----|----------|-------------|------|------| + 149 +| B | 하부 제거량 | 1~2분 | 하이드롤릭 홀드업(물리 계산) | 탑 넘침(Flooding) 즉시 방지 | + 150 +| D/R | 상부 제거량/환류 | 5분 | D-6113 드럼 체류시간(물리 계산) | 압력/조성 안정화 | + 151 +| P | 측류 제품 추출 | 15~20분 | **분리/조성 동특성(§1.2-가, 별도 모델)** | 초고순도 PGMEA 품질 보호 | + 152 +| S | 리보일러 스팀 | 가장 빠름 | 압력 즉시 전달 | 하부 온도 직결 | + 153 + + 154 +추가(원본 §4.2/§4.3): PID 블록 **dead band 0.5~1.0%**, 원료탱크 **Surge Control**(P-Gain↓ I-Time↑). + 155 + + 156 --- + 157 + 137 -## 6. 선택사항 (의사결정 대기) + 158 +## 6. 안전 봉투 (Safety Envelope) + 159 + 139 -### 6.1 시작 지점 — "무엇부터 구현하나" + 140 -| 옵션 | 내용 | 비고 | + 141 -|------|------|------| + 142 -| **A. 안전 가드 레이어 먼저** | 쓰기 경로에 클램프·변화율·dead band·화이트리스트·감사로그 추가 | **권장**. 자동운전 전제 + -조건이며 수동 쓰기도 즉시 안전해짐 | + 143 -| B. 결정론 보상 엔진(폐루프) | `AutoRunService`: F구독→Lag/데드타임→B/D/P SV 계산→가드 경유 쓰기 | 실제 자동운전 핵심 | + 144 -| C. 조언형(개루프)부터 | 엔진은 권고 SV만 계산·표시, 쓰기는 운전원이 클릭 승인 | 로직 안전검증 후 폐루프 전환 | + 145 -| D. 시뮬레이터 먼저 | FOPDT 증류탑 디지털 트윈으로 실플랜트 전 검증 | 현 브랜치 `sim/...` 와 자연스러움 | + 160 +엔진의 모든 쓰기는 아래를 강제 통과한다(다층 독립 방어): + 161 + 147 -### 6.2 LLM 개입 수준 — "LLM 권한 어디까지" + 148 -| 옵션 | 내용 | 비고 | + 149 -|------|------|------| + 150 -| **가. 감독·조언만** | Step Test 분석·이상 설명·파라미터 제안만. 밸브/쓰기 절대 안 함 | **권장**. 가장 안전 | + 151 -| 나. 파라미터 쓰기(승인 게이트) | LLM이 K·τ 등 엔진 파라미터 변경 제안 → 운전원 승인 후 반영. 밸브 직접 제어는 여전히 엔 + -진만 | 적응 튜닝 가능 | + 152 -| 다. MCP 쓰기 도구 추가 | LLM이 MCP로 직접 SV/모드 쓰기(가드 경유) | 유연하나 위험 큼 — 신중 적용 | + 162 +1. **엔진 가드**: rate 제한 · 절대 min/max · **현재 유량범위 대비 밸브 변동폭 제한** · 태그 화이트리스트 · 전 쓰기 감사로 + +그 + 163 +2. **DCS 측 한계**: RSP 한계(SPHILM/SPLOLM), 출력 한계(OPHILM/OPLOLM) — 엔진과 독립 + 164 +3. **운전원 스위치**: LSP/RSP, AUTO/MAN — 언제든 즉시 회수 (최우선) + 165 +4. **데드맨/워치독**: 엔진 stale → SP경로는 운전원 LSP 회수, OP경로는 DCS 로직이 MAN→AUTO(bumpless) 폴백 + 166 +5. **ESD/IL/SIS 독립**: BPCS 루프의 MAN/AUTO·LSP/RSP와 무관하게 최종요소에 독립 동작 → 실험을 봉인된 안전 범위에 묶음 + 167 +6. **한 번에 한 루프**: 간섭 루프 동시 MAN 금지 + 168 +7. **양방향 bumpless**: 모든 전환에서 충격 없음(PID bumpless output + 엔진 추종) + 169 + 154 -> 현재 권장 조합: **6.1-A (가드 먼저) + 6.2-가 (LLM 감독만)** 로 시작 → 검증 후 단계적 확장. + 170 +> ⚠️ **MoC/문화**: 자동 시스템이 SP/OP를 조작하는 것은 현장에서 APC로 간주 → 변경관리·운전원 수용 절차 필요(기술 외 항목) + +. + 171 + 172 --- + 173 + 158 -## 7. 단계별 로드맵 + 174 +## 7. 단계별 신뢰 이양 로드맵 (운전원 비전) + 175 + 160 -- **Phase 0 — 안전 가드 레이어**: 쓰기 경로 클램프/rate/dead band/화이트리스트/폴백/감사로그. (전제조건) + 161 -- **Phase A — 조언형(개루프)**: 보상 엔진이 권고 SV 계산·대시보드 표시 + LLM Step Test 분석기. + 162 - DCS 쓰기는 운전원 수동 승인. 위험 최소. + 163 -- **Phase B — 감독형 폐루프**: `AutoRunService`가 가드 안에서 SV 자동 쓰기. LLM은 파라미터만 제안(승인 게이트). + 164 -- **Phase C — 자가 튜닝**: LLM이 Step Test 시점 제안 → 자동 피팅 → 시뮬레이터 A/B 검증 후 반영. + 176 +| 단계 | 내용 | 경로 | 권한 | + 177 +|------|------|------|------| + 178 +| **1. 제안 표시** | 엔진이 RSP 소스 포인트에 계산값 write → 운전원이 페이스플레이트에서 "제안 SP"를 봄(LSP 유지) | SP/RS + +P | 운전원 100% | + 179 +| **2. 관찰·신뢰 형성** | 제안값이 합리적인지 운전원이 일정 기간 관찰 | SP/RSP | 운전원 100% | + 180 +| **3. SP 주도권 이양** | 신뢰 시 운전원이 **RSP로 토글** → 엔진 SP 추종. 언제든 LSP 회수 | SP/RSP | 엔진(가역) | + 181 +| **4. 헌팅 자동 안정화** | 헌팅 임계 초과 + 원인=튜닝/외란 확인 시 PID MAN 전환 → FF+PI로 OP 핸드홀딩 → 안정 후 복귀 | O + +P/MAN | 엔진(데드맨 폴백) | + 182 + 183 +**구현 선행조건(Phase 0)**: §6-1 엔진 가드 레이어 + 데드맨. *(현재 쓰기 경로에 가드 0건 — §10 참조.)* + 184 + + 185 --- + 186 + 168 -## 8. LLM이 잘하는 4가지 역할 (Plane 2 상세) + 187 +## 8. 태그/노드 매핑 (실측 — `find_tags`·`trace_connections`) + 188 + 170 -1. **Step Test 분석 (강력 추천)** — 원본 §3. 유량 스텝 후 하부/상부/환류드럼/측류 온도·Analyzer 곡선을 + 171 - `query_pv_history`로 뽑아 LLM에 주면 구간별 데드타임 θ·시상수 τ를 읽어냄 (결정론 곡선피팅으로 교차검증) + 172 - → 그 값이 Plane 1 파라미터가 됨. + 173 -2. **파라미터 튜닝 조언** — 처리량·원료 조성 드리프트 시 K·τ 재조정 제안. + 174 -3. **이상 상황 서술** — "FT 헌팅 5분째 ±5% 지속, 필터 τ 300→420초 권장" 식 자연어 진단. + 175 -4. **운전원 코칭** — 신입에게 "왜 P는 15분 늦게 여는가"를 문서 근거로 설명. + 189 +원료 경로(trace_connections): + 190 +``` + 191 +P-6101(원료펌프) → FT-6101 → FICQ-6101 → FCV-6101 → E-6103(예열) → C-6111 원료 스프레이 분배기 + 192 +``` + 193 + 194 +| # | 경로 | MV/제어 | 유량 | 온도 | 수위/압력 | τ | + 195 +|---|------|---------|------|------|----------|---| + 196 +| **F** | 원료 투입 | **FICQ-6101**→FCV-6101 | FT-6101 | (E-6103 예열) | — | 입력(Lag 300s) | + 197 +| **S** | 리보일러 스팀 | 스팀밸브 | **FI-6115** | TI-6111A(BOT), TICA-6111A | PI-6700(스팀압) | 가장 빠름 | + 198 +| **B** | 하부 제거 | 하부 발출 밸브 *(밸브태그 미확인)* | (미확인) | TI-6111A(BOT) | **LI-6111**(하부수위) | 1~2분 | + 199 +| **D/R** | 상부/환류 | **FICQ-6113**(PV29.9/SP36.4) | FI-6113 | TI-6111D(TOP) | **LI-6113**(D-6113 환류드럼), LICA-6113, + + PI-6111(진공), PICA-6111 | 5분 | + 200 +| **P** | 측류 제품 | **🔲 사용자 매핑 예정** | FI-6120(PGMEA) | TI-6111B/C(MID) | LI-6121/6122/6123(제품탱크) | 15~20분 + +| + 201 + + 202 +- OPC Node 형식: `ns=1;s=sinamserver:ficq-6101.sp` / `.op` / `.md`(MAN=0/AUTO=1). + 203 + ※ SP 경로 구현 시 write 타깃은 **루프 SP가 아니라 RSP 소스 포인트**로 바뀜(노드 ID만 교체, 쓰기 코드 동일). + 204 +- 현재 운전 흔적: FICQ-6113 PV 29.9 / SP 36.4 추종, 진공압 PICA-6111 30.4 → 가동 중 추정. + 205 + + 206 +### 8.1 미완료 매핑 (담당 구분) + 207 +- **P(측류 제품 추출) 경로 매핑 — 사용자 직접 진행 예정** (본 플랜 보류) + 208 +- B(하부) 발출 유량계·밸브 태그 — `find_tags`(6112/6114/6116번대) 또는 C-6111 `trace_connections downstream`로 보강 + 209 + + 210 --- + 211 + 179 -## 9. 미해결/확인 필요 항목 + 212 +## 9. 현 시스템 재사용 자산 + 213 + 214 +| 구분 | 자산 | + 215 +|------|------| + 216 +| 쓰기 | `ExperionOpcWriteClient.WriteTagAsync(.sp/.op)`, `SetModeAsync(MAN/AUTO)`, `ControlOp`(MD→MAN→OP→AUTO) / `POST / + +api/experion/{write,mode,control}` / UI "OPC UA Write" 탭 | + 217 +| 읽기 | `ExperionRealtimeService`(실시간 PV 구독, IHostedService), `query_pv_history`(MCP)/`ExperionHistoryController` | + 218 +| 백그라운드 | `IHostedService`/`AddHostedService` 패턴 기존 사용 → 신규 `AutoRunService : BackgroundService` 그대로 적용 + + | + 219 +| LLM 감독 | `query_pv_history`, `find_tags`, `trace_connections`, `active_alarms`, `query_events`, `summarize_events`, ` + +generate_status_report`, ReAct 에이전트 모드 | + 220 + + 221 +--- + 222 + + 223 +## 10. 미해결/확인 필요 항목 + 224 + + 225 - [ ] **P(측류 제품 추출) 경로 매핑** — *사용자 직접 진행* + 226 - [ ] B(하부) 발출 유량계·밸브 태그 확정 + 183 -- [ ] 6.1 / 6.2 선택 확정 (시작 지점 / LLM 권한) + 227 +- [ ] **쓰기 경로 안전 가드(§6-1) 신규 구현** — 현재 `WriteTagAsync`에 클램프/rate/변동폭 0건 (Phase 0 선행) + F(헌팅) ─filter→ F_clean ─물질수지→ 목표유량 ─Cv커브→ OP_ff ┐ + ├→ OP → rate제한 → 밸브 + 설정값 − 실측PV ───────────── 느린 PI ──────────→ OP_pi ┘ + + --- + 정리하면: FF는 "물리로 미리 계산한 부드러운 큰 움직임"(헌팅 차단), PI는 "모델 오차만 천천히 청소하는 작은 피드백"(정확도 확보). + 둘이 상호보완이고, 고정+간헐은 피드백을 버려서 PV가 드리프트하므로 안 씁니다. + + 이 설명으로 명확해지셨나요? 막히는 부분 있으면 더 풀어드리고, 괜찮으시면 이 제어법을 확정으로 플랜 문서에 반영하겠습니다. + +✻ Cooked for 57s + +❯ 이해됐어, 이제 플랜 문서에 반영해줘 + +● 전체 논의를 통합해 플랜 문서를 개정하겠습니다. 먼저 현재 내용을 확인합니다. + + Read 1 file (ctrl+o to expand) + +● 전체 논의를 통합해 문서를 전면 개정하겠습니다. + +● Write(측류추출-자동운전-플랜.md) + ⎿  Added 178 lines, removed 123 lines + 1 # 측류 추출 증류탑(C-6111) — 로컬 LLM 기반 자동운전 플랜 + 2 + 3 > **목적**: `측류추출-시간지연-적용방식.md`의 시간지연/시차 보상 제어를 ExperionCrawler 시스템 위에서 + 4 -> **로컬 LLM(vLLM Qwen)** 과 결합해 자동운전(Autopilot)으로 구현하기 위한 컨셉·아키텍처·선택사항 기록. + 4 +> 구현하되, **운전원이 단계적으로 신뢰를 쌓아 권한을 넘기는** 감독제어(Supervisory Control) 형태의 + 5 +> 자동운전을 설계한다. 결정론 엔진이 제어하고, 로컬 LLM(vLLM Qwen)은 그 위에서 진단·예외·인터페이스를 맡는다. + 6 > + 6 -> 문서 성격: **설계/의사결정 기록**. 구현 착수 전 합의용. 코드 미작성 상태. + 7 +> 문서 성격: **설계/의사결정 기록**. 구현 착수 전 합의 완료본. 코드 미작성 상태. + 8 + 8 -*작성일: 2026-05-22 / 대상: C-6111 PGMEA 진공 측류추출 증류탑 (P6 영역)* + 9 +*작성일: 2026-05-22 / 갱신: 2026-05-22 (논의 합의 반영) / 대상: C-6111 PGMEA 진공 측류추출 증류탑 (P6 영역)* + 10 + 11 --- + 12 + 12 -## 0. 핵심 원칙 (가장 중요) + 13 +## 0. 핵심 원칙 + 14 + 14 -**LLM을 빠른 제어 루프에 넣지 않는다.** + 15 +**LLM을 빠른 제어 루프에 넣지 않는다.** 빠른 보상은 결정론 엔진(코드)이, LLM은 분/이벤트 단위 진단·튜닝·인터페 + +이스만. + 16 + 16 -`측류추출-시간지연-적용방식.md`가 말하는 "1분/5분/15~20분 지연 보상"은 초 단위로 결정론적으로 돌아야 + 17 -하는 빠른 루프다. 여기에 LLM을 직접 넣으면: + 18 - + 17 | 문제 | 영향 | + 18 |------|------| + 19 | 비결정성 | 같은 입력에 다른 출력 → 밸브 제어에 치명적 | + 20 | 지연(latency) | 토큰 생성 수 초 → Flooding 즉시 대응 불가 | + 23 -| 환각 | 잘못된 SV 한 줄이 바로 밸브로 → 측류 순도 영역 파괴 | + 21 +| 환각 | 잘못된 값 한 줄이 바로 밸브로 → 측류 순도 영역 파괴 | + 22 + 25 -→ **결론**: 빠른 보상은 **결정론 엔진(코드)** 이 담당하고, **LLM은 분 단위 감독·튜닝·조언만** 한다. + 26 -이것이 LLM을 실공정에 붙이는 유일하게 안전한 형태다. + 23 +따름정리: **헌팅 검출·MAN 전환·OP 산출 등 안전·실시간 판단은 모두 결정론.** LLM은 그 트립을 *설명*하고 + 24 +*원인을 진단*할 뿐, 직접 트립시키거나 OP를 쓰지 않는다. + 25 + 26 --- + 27 + 30 -## 1. 2-Plane 아키텍처 + 28 +## 1. 물리 결정론 vs LLM — 역할 경계 (이 플랜의 출발점) + 29 + 32 -``` + 33 -┌─ Plane 2: LLM 감독 (MCP, 분/이벤트 단위, 느림) ───────────────┐ + 34 -│ · Step Test 곡선 분석 → θ(데드타임)·τ(시상수) 자동 추출 │ + 35 -│ · 파라미터(K, τ, 한계값) 튜닝 제안 │ + 36 -│ · 헌팅 / Flooding / 순도 드리프트 이상 감지·자연어 설명 │ + 37 -│ · 운전원 Q&A ("왜 제품밸브가 천천히 열려요?") │ + 38 -│ │ ※ 밸브 직접 쓰기 금지. "엔진 파라미터 저장소"에만 │ + 39 -│ │ 제안 → 운전원 승인 후 반영 │ + 40 -├─────────┼──────────────────────────────────────────────────────┤ + 41 -│ 🔒 안전 가드 레이어 (신규, 0순위) ─ 모든 쓰기가 강제 통과 │ + 42 -│ hard min/max · 변화율(rate) 제한 · dead band · 태그 화이트 │ + 43 -│ 리스트 · 통신두절→안전SV 폴백 · 전 쓰기 감사로그 │ + 44 -├─────────┼──────────────────────────────────────────────────────┤ + 45 -│ Plane 1: 결정론 보상 엔진 (신규 BackgroundService, 초 단위) │ + 46 -│ Realtime 구독으로 F(원료유량) 읽기 │ + 47 -│ → Lag(τ=300s) 필터로 헌팅 제거 → F_clean │ + 48 -│ → B_sv(데드타임 1~2분) / D_sv(5분) / P_sv(15~20분) 계산 │ + 49 -│ → 가드 통과 후 WriteTagAsync / ControlOp 로 쓰기 │ + 50 -└────────────────────────────────────────────────────────────────┘ + 51 - 읽기: ExperionRealtimeService · query_pv_history + 52 - 쓰기: IExperionOpcWriteClient (가드 레이어 경유 필수) + 53 -``` + 30 +운영자가 **밸브 사이즈·배관 종류·컨트롤밸브 Cv 값/Cv 커브·플로우미터 유량범위** 등 물리 데이터를 + 31 +보유하면, 제어 수학의 상당 부분이 *데이터 피팅 없이 계산*된다. + 32 + 55 ---- + 33 +### 1.1 물리 데이터로 결정론화되는 것 (LLM 불필요) + 34 +| 물리 데이터 | 계산되는 모델 | + 35 +|------------|--------------| + 36 +| Cv 커브(설치특성) | OP(%) → 유량 관계, 밸브 게인 dQ/dOP | + 37 +| 배관 종류·구경·길이 | ΔP·마찰, 이송 데드타임 θ = 관내체적/유량 | + 38 +| 드럼/트레이 홀드업 체적 | 체류시간 τ = 체적/유량 (D-6113 환류드럼 등) | + 39 +| 플로우미터 레인지 | 스케일링·분해능·노이즈 플로어 | + 40 + 57 -## 2. 보상 제어 수식 (Plane 1 — 결정론, LLM 아님) + 41 +→ 자동운전의 **B(하부)·D/R(상부) 타이밍은 하이드롤릭 홀드업(=체적/유량)으로 직접 계산**된다. + 42 +밸브 게인도 Cv 커브 미분으로 나온다. **이 부분은 그냥 프로그램한다.** + 43 + 59 -원본 문서 §2·§4 기준. + 44 +### 1.2 물리 데이터가 못 주는 것 + 45 +- **(가) 분리/조성 동특성** — P(측류)의 "15~20분" 지연은 배관 이송이 아니라 트레이 홀드업+기액평형(VLE)으로 + 46 + 새 조성이 자리잡는 시간. 상대휘발도·트레이 효율·VLE는 Cv 커브에 없음. → **B·D는 물리로 계산되지만 P는 별도 모 + +델 필요.** + 47 +- **(나) 모델-플랜트 불일치(드리프트)** — Cv 커브는 신품 설계값. 밸브 stiction·마모, E-6103 파울링, 트레이 효율 + + 저하로 시간에 따라 어긋남. + 48 +- **(다) 목적·맥락·예외** — 회수율 최대 vs 에너지 최소 vs 순도 사수, 등급변경, 기동/정지, 계기고장, 상류 외란. + 49 + 61 -- **1차 지연(Lag) 필터** (이산): `y[k] = y[k-1] + (Δt/τ) · (x[k] − y[k-1])` + 62 -- **데드타임(Dead Time)**: 링버퍼로 N틱 지연 + 63 -- **헌팅 제거**: 원료 FT 신호 직후 Lag 필터 τ=**300초(3~5분)** 1개 (원본 §4.1 "1순위 대책") + 50 +### 1.3 따라서 LLM이 실제로 하는 일 + 51 +> **LLM의 가치는 물리모델 품질에 반비례.** 물리를 잘 잡을수록 LLM은 제어 산수에서 빠지고 가장자리로 이동. + 52 + 65 -| MV | 제어 대상 | τ / 데드타임 | 목적 | + 66 -|----|----------|-------------|------| + 67 -| B | 하부 제거량 | 1~2분 | 탑 넘침(Flooding) 즉시 방지 | + 68 -| D/R | 상부 제거량/환류 | 5분 | 압력/조성 안정화 | + 69 -| P | 측류 제품 추출 | 15~20분 | 초고순도 PGMEA 품질 보호 (가장 보수적) | + 70 -| S | 리보일러 스팀 | 가장 빠름(수초~수분) | 하부 온도 직결 | + 53 +| LLM 역할 | 구체 | 가치 | + 54 +|---------|------|------| + 55 +| ① 커미셔닝 보조 | 밸브 데이터시트·Cv 커브·배관 스펙 파싱 → 엔진 config/코드로 조립, 정합성 점검 | ★★ | + 56 +| ② 드리프트 진단((나)) | 물리예측 vs 실측 잔차는 수학, *"이 OP·ΔP에서 8% 미달 → 밸브 파울링/마모 의심"* 해석· + +재교정 트리거는 LLM | ★★ | + 57 +| ③ 소프트센서 보조((가)) | 측정 안 되는 조성을 온도(TI-6111B/C)로 추론, 분석기 결측 보간 | ★ | + 58 +| ④ 감독형 예외 처리((다)) | 엔진이 프로그램 안 된 상황(기동·등급변경·상류 업셋·계기고장) 판단·완화 | ★★★ | + 59 +| ⑤ 운전원 인터페이스 | 의도/경제목표 → SV·제약 번역, "왜 이렇게 도는지" 설명 | ★★★ | + 60 +| ⑥ 교차 데이터 융합 | 알람+이벤트+랩분석+정비이력+물리잔차 엮어 진단 (기존 MCP 도구) | ★★★ | + 61 +| ⑦ 헌팅 원인 진단 | 튜닝 vs stiction vs 외란 판별 → 4단계(OP 개입) 적용 여부 게이트 (§4.3) | ★★★ | + 62 + 72 -추가 안전요소(원본 §4.2/§4.3): 각 PID 블록 **dead band 0.5~1.0%**, 원료탱크 **Surge Control**(P-Gain↓ I-Time↑). + 73 - + 63 --- + 64 + 76 -## 3. 현 시스템에서 확인된 능력 (재사용 자산) + 65 +## 2. 감독제어 아키텍처 — 운전원이 권한을 쥔다 + 66 + 78 -### 3.1 쓰기 (이미 구현됨) + 79 -| 기능 | 구현 | 엔드포인트 | + 80 -|------|------|-----------| + 81 -| SP/OP 직접 쓰기 | `ExperionOpcWriteClient.WriteTagAsync(cfg, nodeId, value)` | `POST /api/experion/write` | + 82 -| MAN/AUTO 모드 | `SetModeAsync(cfg, nodeId, "MAN"\|"AUTO")` | `POST /api/experion/mode` | + 83 -| 통합 제어 (MD→MAN → OP쓰기 → AUTO복귀) | `ControlOp(TagName, OpValue, RestoreAuto)` | `POST /api/experion/con + -trol` | + 84 -| UI | "OPC UA Write" 탭 (#15) | `index.html #pane-write` | + 67 +핵심 설계 사상: **엔진은 PID 루프의 SP/OP 레지스터를 직접 덮어쓰지 않는다.** 별도 감독변수에 쓰고, + 68 +**운전원이 스위치로 채택**한다. 권한 손잡이는 항상 운전원에게 있다. SP 경로와 OP 경로가 대칭이다. + 69 + 86 -### 3.2 읽기 + 87 -- `ExperionRealtimeService` — 실시간 PV 구독 (`AddMonitoredItemAsync`), `IHostedService` + 88 -- `query_pv_history` (MCP) / `ExperionHistoryController` — Step Test용 시계열 + 70 +| | SP 경로 (평상시) | OP 경로 (헌팅 시) | + 71 +|---|------------------|-------------------| + 72 +| 엔진이 쓰는 곳 | RSP 소스 포인트 (별도 변수) | `.op` (PID MAN 상태에서) | + 73 +| 운전원 스위치 | **LSP ↔ RSP** (Local ↔ Remote SP = AUTO↔CAS) | **PID MODE: AUTO ↔ MAN** | + 74 +| 빠른 규제 담당 | DCS PID (그대로 둠) | 엔진(소프트웨어 컨트롤러) | + 75 +| 폴백(엔진 사망) | 운전원이 LSP로 토글 | 데드맨 → MAN→AUTO (bumpless) | + 76 +| 적용 | 1~3단계 (신뢰 이양) | 4단계 (튜닝발 헌팅 한정) | + 77 + 90 -### 3.3 백그라운드 서비스 패턴 + 91 -- `IHostedService`/`AddHostedService` 이미 Realtime·History·OpcServer·Mcp에서 사용 중 + 92 - → 신규 `AutoRunService : BackgroundService`가 기존 패턴에 그대로 들어감 + 78 +### 2.1 SP 경로 — RSP(Remote Setpoint) + 79 +- 엔진은 **루프 SP를 절대 안 건드림.** 자기 감독소스 포인트에만 OPC write → 그 포인트가 PID의 RSP/X 입력에 cont + +rol connection. + 80 +- 운전원의 **LSP/RSP 토글이 유일한 권한 손잡이.** RSP면 엔진 SP 추종, LSP면 운전원 수동 — 언제든 가역. + 81 +- **bumpless 요건(중요)**: OPC 외부 감독은 DCS의 back-calculation 핸드셰이크를 못 받음. + 82 + → 루프가 LSP(미선택)일 때 엔진이 **현재 실작동 SP를 읽어 자기 출력=현재 SP로 추종**시켜야 함. + 83 + 그래야 운전원이 RSP로 토글하는 순간 충격 없음. + 84 +- **공짜 안전망**: DCS RSP 한계(SPHILM/SPLOLM, RSP rate)가 엔진과 독립으로 한 겹 더. + 85 +- **장점**: 1~2단계(제안 표시)는 페이스플레이트가 RSP 후보값을 네이티브로 보여줌 → **별도 화면 개발 불필요.** + 86 + 94 -### 3.4 LLM 감독용 MCP 도구 (기존) + 95 -- `query_pv_history`, `find_tags`, `trace_connections`, `active_alarms`, `query_events`, + 96 - `summarize_events`, `generate_status_report`, ReAct 에이전트 모드(구현됨) + 87 +### 2.2 OP 경로 — MAN + OP 쓰기 (튜닝발 헌팅 전용) + 88 +- 평상시 RSP로는 **튜닝발 헌팅이 안 잡힘**(PID가 루프에 그대로). 그래서 헌팅 루프에 한해 OP를 직접 잡는다. + 89 +- 방식: PID를 **MAN**으로 → 엔진이 `.op`에 직접 write. **MAN이라 적분이 멈춰 windup 없음, OP 쓰기는 본질적 bump + +less.** + 90 + 기존 `ControlOp`(MD→MAN→OP쓰기) / `WriteTagAsync(.op)` 그대로 사용 → **신규 DCS 구성 불필요, 저MoC.** + 91 +- **운전원 회수**: MAN의 OP는 엔진이 쓴 마지막 값 → 운전원이 그 값에서 이어 조정, 또는 AUTO로 올림. + 92 +- **폴백(엔진 사망)**: 엔진 워치독 + **DCS 컨트롤러 로직이 stale(N초 갱신 없음) 감지 → MAN→AUTO 강제 복귀.** + 93 + PID가 bumpless output 설정이라 **현재 OP(=마지막 LLM_OP)에서 적분 임펄스 없이 규제 재개.** + 94 + - *정직한 단서*: 폴백은 "헌팅하던 그 PID"로 돌아감 → 안전(규제됨, SIS가 극단 차단)하나 **엔진 복구 전까지 헌 + +팅 재개.** 위험 아님, 차선. + 95 + - 설정 확인: MAN 중 SP 추종/홀드 → 폴백 후 어떤 LSP로 규제할지 결정. + 96 +- **상위 옵션(임계 루프 한정)**: *순간 규제 공백도 불가*한 빠른 루프는 선택+back-calc(PID는 AUTO 추종 유지, 무 + +충격 즉시 폴백)을 쓰되, 밸브 출력경로를 변형하므로 MoC가 더 엄격. 기본값은 위 MAN 방식. + 97 + 98 --- + 99 + 100 -## 4. ⚠️ 안전 관련 발견 사항 (자동운전 전 반드시 처리) + 100 +## 3. LLM-OP 모드의 제어법 — FF + 느린 PI (rate 제한) + 101 + 102 -1. **쓰기 경로에 안전 가드가 0건.** `WriteTagAsync`는 들어온 double을 그대로 쓴다 — + 103 - min/max 클램프·rate limit·범위 검증·변화율 제한 전무. 사람이 UI에서 손으로 쓸 땐 운전원이 + 104 - 최종 안전망이지만, **엔진이 자동으로 쓰는 순간 안전망이 사라진다.** → **0순위: 가드 레이어.** + 105 -2. **현재 LLM(MCP)에는 쓰기 도구가 없다.** 쓰기는 Web UI/HTTP 전용 → 지금은 "사람만 쓸 수 있는" + 106 - 상태가 유일한 안전 경계. 자동운전을 붙이면 이 경계를 넘게 됨 → 신중한 권한 설계 필요. + 107 -3. **`ask_iiot_llm`(vLLM 직접 질의) MCP 도구가 빈 응답.** 2회 시도 모두 `(응답 없음)`. + 108 - vLLM 엔드포인트 상태/연결 점검 필요. (단 `find_tags`/`trace_connections`는 정상 동작.) + 102 +OP 경로로 개입한 동안 엔진이 매 순간 OP에 무엇을 쓰는가. **크루즈컨트롤과 동일 구조**: 미리 예측(FF) + 잔차 청 + +소(PI). + 103 + 104 +``` + 105 +F(헌팅) ─Lag필터→ F_clean ─물질수지→ 목표유량 ─Cv커브→ OP_ff ┐ + 106 + ├→ OP → rate제한 → 절대/변동폭 클램프 → 밸브 + 107 +설정값 − 실측PV ───────────────── 느린 PI ───────→ OP_pi ┘ + 108 +``` + 109 + + 110 +- **FF (피드포워드)**: 물리로 *미리* 정답 개도 계산. `개도% = Cv⁻¹( Q / √(ΔP/SG) )`. + 111 + 필터링된 F_clean로 목표유량(B/D/P)을 물질수지로 구하고 → Cv 커브로 OP 계산 → §5 시간상수로 부드럽게 이동. + 112 + **외란발 헌팅을 잡는 주역**(반응이 아니라 예측이라 밸브가 안 채인다). + 113 +- **PI (느린 피드백)**: Cv 커브는 신품값이라 마모·파울링·ΔP 부정확으로 살짝 빗나감. 잔차(SP−PV)를 + 114 + **느리게/약하게** 보정. 약한 이유: ①헌팅 재유발 방지 ②큰 일은 FF가 이미 함. + 115 +- **rate 제한**: OP 변화율 제한으로 밸브 부드럽게. + 116 +- **비채택: "고정+간헐 보정"** — 보정 사이 능동 규제 0 → 외란 시 PV 드리프트(피드백 상실). 사용 안 함. + 117 +- **연결**: FF = §5 결정론 보상 엔진 그대로 + 그 위에 작은 PI 트림 하나. + 118 + + 119 --- + 120 + 112 -## 5. 태그/노드 매핑 (실측 — `find_tags`·`trace_connections` 기반) + 121 +## 4. 헌팅 검출 & 원인 진단 — 4단계의 게이트 + 122 + 114 -`trace_connections`가 돌려준 원료 경로: + 115 -``` + 116 -P-6101(원료펌프) → FT-6101 → FICQ-6101 → FCV-6101 → E-6103(예열) → C-6111 원료 스프레이 분배기 + 117 -``` + 123 +### 4.1 검출 (결정론) + 124 +- 오실레이션 인덱스: 진폭·주기·지속성. 임계 초과(예: 진폭 > 범위의 X%, 주기 안정, N분 지속) 시 트립. + 125 +- **MAN 전환 트립은 결정론**(LLM 지연 불가). LLM은 트립을 설명만. + 126 + 119 -| # | 경로 | 조작변수(MV)/제어 | 유량 | 온도 | 수위/압력 | τ | + 120 -|---|------|------------------|------|------|----------|---| + 121 -| **F** | 원료 투입 | **FICQ-6101**(SP/OP)→FCV-6101 | FT-6101 | (E-6103 예열) | — | 입력신호(Lag 300s) | + 122 -| **S** | 리보일러 스팀 | 스팀밸브(리보일러 듀티) | **FI-6115** | TI-6111A(BOT), TICA-6111A | PI-6700(스팀압) | + - 가장 빠름 | + 123 -| **B** | 하부 제거 | 하부 발출 밸브 *(밸브태그 미확인)* | (미확인) | TI-6111A(BOT) | **LI-6111**(하부수위) | 1 + -~2분 | + 124 -| **D/R** | 상부/환류 | **FICQ-6113**(PV29.9/SP36.4) | FI-6113 | TI-6111D(TOP) | **LI-6113**(D-6113 환류드럼), + -LICA-6113, PI-6111(진공), PICA-6111 | 5분 | + 125 -| **P** | 측류 제품 | **🔲 사용자 매핑 예정** | FI-6120(PGMEA) | TI-6111B/C(MID) | LI-6121/6122/6123(제품탱크) + -| 15~20분 | + 127 +### 4.2 원인 분류 (LLM + 데이터 융합) — §1.3-⑦ + 128 +| 원인 | 4단계(MAN+OP)로 잡히나 | 조치 | + 129 +|------|----------------------|------| + 130 +| 튜닝 과민 | ✅ 즉시 | MAN 전환 → FF+PI로 OP 핸드홀딩 | + 131 +| 상류 외란 | ✅ 잘 잡힘 | 동일(FF가 주역) | + 132 +| 루프 간섭 | ⚠️ 부분 | 시차 조절로 완화 | + 133 +| **밸브 stiction** | ❌ 악화 | **정비 플래그.** OP 핸드홀딩 금지(마모만 늘어남) | + 134 + 127 -- OPC Node 형식: `ns=1;s=sinamserver:ficq-6101.sp` / `.op` / `.md`(MAN=0/AUTO=1) + 128 -- 현재 운전 데이터 흔적: FICQ-6113 PV 29.9 / SP 36.4 추종 중, 진공압 PICA-6111 30.4 → 탑 가동 중으로 추정 + 135 +→ LLM이 OP-PV 위상·한계주기 파형·상류 신호·정비이력을 엮어 *"이건 stiction → 4단계 말고 정비"* vs + 136 +*"외란 → 4단계 유효"* 판정. **초기엔 LLM 진단 → 운전원 확인 권장.** + 137 + 130 -### 5.1 미완료 매핑 (담당 구분) + 131 -- **P(측류 제품 추출) 경로 매핑 — 사용자가 직접 진행 예정** (본 플랜에서는 보류) + 132 -- B(하부 제거) 발출 유량계·밸브 태그 — `find_tags`(6112/6114/6116번대) 또는 + 133 - C-6111 `trace_connections downstream`로 보강 가능 (착수 시 확정) + 138 +--- + 139 + 140 +## 5. 보상 제어 수식 (결정론, FF의 본체) + 141 + + 142 +원본 문서 §2·§4 기준. + 143 +- **1차 지연(Lag) 필터** (이산): `y[k] = y[k-1] + (Δt/τ) · (x[k] − y[k-1])` + 144 +- **데드타임**: 링버퍼로 N틱 지연 + 145 +- **헌팅 제거**: 원료 FT 신호 직후 Lag 필터 τ=**300초(3~5분)** (원본 §4.1) + 146 + + 147 +| MV | 제어 대상 | τ / 데드타임 | 근거 | 목적 | + 148 +|----|----------|-------------|------|------| + 149 +| B | 하부 제거량 | 1~2분 | 하이드롤릭 홀드업(물리 계산) | 탑 넘침(Flooding) 즉시 방지 | + 150 +| D/R | 상부 제거량/환류 | 5분 | D-6113 드럼 체류시간(물리 계산) | 압력/조성 안정화 | + 151 +| P | 측류 제품 추출 | 15~20분 | **분리/조성 동특성(§1.2-가, 별도 모델)** | 초고순도 PGMEA 품질 보호 | + 152 +| S | 리보일러 스팀 | 가장 빠름 | 압력 즉시 전달 | 하부 온도 직결 | + 153 + + 154 +추가(원본 §4.2/§4.3): PID 블록 **dead band 0.5~1.0%**, 원료탱크 **Surge Control**(P-Gain↓ I-Time↑). + 155 + + 156 --- + 157 + 137 -## 6. 선택사항 (의사결정 대기) + 158 +## 6. 안전 봉투 (Safety Envelope) + 159 + 139 -### 6.1 시작 지점 — "무엇부터 구현하나" + 140 -| 옵션 | 내용 | 비고 | + 141 -|------|------|------| + 142 -| **A. 안전 가드 레이어 먼저** | 쓰기 경로에 클램프·변화율·dead band·화이트리스트·감사로그 추가 | **권장**. 자 + -동운전 전제조건이며 수동 쓰기도 즉시 안전해짐 | + 143 -| B. 결정론 보상 엔진(폐루프) | `AutoRunService`: F구독→Lag/데드타임→B/D/P SV 계산→가드 경유 쓰기 | 실제 자동운 + -전 핵심 | + 144 -| C. 조언형(개루프)부터 | 엔진은 권고 SV만 계산·표시, 쓰기는 운전원이 클릭 승인 | 로직 안전검증 후 폐루프 전환 + -| + 145 -| D. 시뮬레이터 먼저 | FOPDT 증류탑 디지털 트윈으로 실플랜트 전 검증 | 현 브랜치 `sim/...` 와 자연스러움 | + 160 +엔진의 모든 쓰기는 아래를 강제 통과한다(다층 독립 방어): + 161 + 147 -### 6.2 LLM 개입 수준 — "LLM 권한 어디까지" + 148 -| 옵션 | 내용 | 비고 | + 149 -|------|------|------| + 150 -| **가. 감독·조언만** | Step Test 분석·이상 설명·파라미터 제안만. 밸브/쓰기 절대 안 함 | **권장**. 가장 안전 | + 151 -| 나. 파라미터 쓰기(승인 게이트) | LLM이 K·τ 등 엔진 파라미터 변경 제안 → 운전원 승인 후 반영. 밸브 직접 제어는 + - 여전히 엔진만 | 적응 튜닝 가능 | + 152 -| 다. MCP 쓰기 도구 추가 | LLM이 MCP로 직접 SV/모드 쓰기(가드 경유) | 유연하나 위험 큼 — 신중 적용 | + 162 +1. **엔진 가드**: rate 제한 · 절대 min/max · **현재 유량범위 대비 밸브 변동폭 제한** · 태그 화이트리스트 · 전 + +쓰기 감사로그 + 163 +2. **DCS 측 한계**: RSP 한계(SPHILM/SPLOLM), 출력 한계(OPHILM/OPLOLM) — 엔진과 독립 + 164 +3. **운전원 스위치**: LSP/RSP, AUTO/MAN — 언제든 즉시 회수 (최우선) + 165 +4. **데드맨/워치독**: 엔진 stale → SP경로는 운전원 LSP 회수, OP경로는 DCS 로직이 MAN→AUTO(bumpless) 폴백 + 166 +5. **ESD/IL/SIS 독립**: BPCS 루프의 MAN/AUTO·LSP/RSP와 무관하게 최종요소에 독립 동작 → 실험을 봉인된 안전 범위 + +에 묶음 + 167 +6. **한 번에 한 루프**: 간섭 루프 동시 MAN 금지 + 168 +7. **양방향 bumpless**: 모든 전환에서 충격 없음(PID bumpless output + 엔진 추종) + 169 + 154 -> 현재 권장 조합: **6.1-A (가드 먼저) + 6.2-가 (LLM 감독만)** 로 시작 → 검증 후 단계적 확장. + 170 +> ⚠️ **MoC/문화**: 자동 시스템이 SP/OP를 조작하는 것은 현장에서 APC로 간주 → 변경관리·운전원 수용 절차 필요(기 + +술 외 항목). + 171 + 172 --- + 173 + 158 -## 7. 단계별 로드맵 + 174 +## 7. 단계별 신뢰 이양 로드맵 (운전원 비전) + 175 + 160 -- **Phase 0 — 안전 가드 레이어**: 쓰기 경로 클램프/rate/dead band/화이트리스트/폴백/감사로그. (전제조건) + 161 -- **Phase A — 조언형(개루프)**: 보상 엔진이 권고 SV 계산·대시보드 표시 + LLM Step Test 분석기. + 162 - DCS 쓰기는 운전원 수동 승인. 위험 최소. + 163 -- **Phase B — 감독형 폐루프**: `AutoRunService`가 가드 안에서 SV 자동 쓰기. LLM은 파라미터만 제안(승인 게이트). + 164 -- **Phase C — 자가 튜닝**: LLM이 Step Test 시점 제안 → 자동 피팅 → 시뮬레이터 A/B 검증 후 반영. + 176 +| 단계 | 내용 | 경로 | 권한 | + 177 +|------|------|------|------| + 178 +| **1. 제안 표시** | 엔진이 RSP 소스 포인트에 계산값 write → 운전원이 페이스플레이트에서 "제안 SP"를 봄(LSP 유 + +지) | SP/RSP | 운전원 100% | + 179 +| **2. 관찰·신뢰 형성** | 제안값이 합리적인지 운전원이 일정 기간 관찰 | SP/RSP | 운전원 100% | + 180 +| **3. SP 주도권 이양** | 신뢰 시 운전원이 **RSP로 토글** → 엔진 SP 추종. 언제든 LSP 회수 | SP/RSP | 엔진(가역) + + | + 181 +| **4. 헌팅 자동 안정화** | 헌팅 임계 초과 + 원인=튜닝/외란 확인 시 PID MAN 전환 → FF+PI로 OP 핸드홀딩 → 안정 + +후 복귀 | OP/MAN | 엔진(데드맨 폴백) | + 182 + 183 +**구현 선행조건(Phase 0)**: §6-1 엔진 가드 레이어 + 데드맨. *(현재 쓰기 경로에 가드 0건 — §10 참조.)* + 184 + + 185 --- + 186 + 168 -## 8. LLM이 잘하는 4가지 역할 (Plane 2 상세) + 187 +## 8. 태그/노드 매핑 (실측 — `find_tags`·`trace_connections`) + 188 + 170 -1. **Step Test 분석 (강력 추천)** — 원본 §3. 유량 스텝 후 하부/상부/환류드럼/측류 온도·Analyzer 곡선을 + 171 - `query_pv_history`로 뽑아 LLM에 주면 구간별 데드타임 θ·시상수 τ를 읽어냄 (결정론 곡선피팅으로 교차검증) + 172 - → 그 값이 Plane 1 파라미터가 됨. + 173 -2. **파라미터 튜닝 조언** — 처리량·원료 조성 드리프트 시 K·τ 재조정 제안. + 174 -3. **이상 상황 서술** — "FT 헌팅 5분째 ±5% 지속, 필터 τ 300→420초 권장" 식 자연어 진단. + 175 -4. **운전원 코칭** — 신입에게 "왜 P는 15분 늦게 여는가"를 문서 근거로 설명. + 189 +원료 경로(trace_connections): + 190 +``` + 191 +P-6101(원료펌프) → FT-6101 → FICQ-6101 → FCV-6101 → E-6103(예열) → C-6111 원료 스프레이 분배기 + 192 +``` + 193 + 194 +| # | 경로 | MV/제어 | 유량 | 온도 | 수위/압력 | τ | + 195 +|---|------|---------|------|------|----------|---| + 196 +| **F** | 원료 투입 | **FICQ-6101**→FCV-6101 | FT-6101 | (E-6103 예열) | — | 입력(Lag 300s) | + 197 +| **S** | 리보일러 스팀 | 스팀밸브 | **FI-6115** | TI-6111A(BOT), TICA-6111A | PI-6700(스팀압) | 가장 빠름 | + 198 +| **B** | 하부 제거 | 하부 발출 밸브 *(밸브태그 미확인)* | (미확인) | TI-6111A(BOT) | **LI-6111**(하부수위) | 1 + +~2분 | + 199 +| **D/R** | 상부/환류 | **FICQ-6113**(PV29.9/SP36.4) | FI-6113 | TI-6111D(TOP) | **LI-6113**(D-6113 환류드럼), + +LICA-6113, PI-6111(진공), PICA-6111 | 5분 | + 200 +| **P** | 측류 제품 | **🔲 사용자 매핑 예정** | FI-6120(PGMEA) | TI-6111B/C(MID) | LI-6121/6122/6123(제품탱크) + +| 15~20분 | + 201 + + 202 +- OPC Node 형식: `ns=1;s=sinamserver:ficq-6101.sp` / `.op` / `.md`(MAN=0/AUTO=1). + 203 + ※ SP 경로 구현 시 write 타깃은 **루프 SP가 아니라 RSP 소스 포인트**로 바뀜(노드 ID만 교체, 쓰기 코드 동일). + 204 +- 현재 운전 흔적: FICQ-6113 PV 29.9 / SP 36.4 추종, 진공압 PICA-6111 30.4 → 가동 중 추정. + 205 + + 206 +### 8.1 미완료 매핑 (담당 구분) + 207 +- **P(측류 제품 추출) 경로 매핑 — 사용자 직접 진행 예정** (본 플랜 보류) + 208 +- B(하부) 발출 유량계·밸브 태그 — `find_tags`(6112/6114/6116번대) 또는 C-6111 `trace_connections downstream`로 + +보강 + 209 + + 210 --- + 211 + 179 -## 9. 미해결/확인 필요 항목 + 212 +## 9. 현 시스템 재사용 자산 + 213 + 214 +| 구분 | 자산 | + 215 +|------|------| + 216 +| 쓰기 | `ExperionOpcWriteClient.WriteTagAsync(.sp/.op)`, `SetModeAsync(MAN/AUTO)`, `ControlOp`(MD→MAN→OP→AUTO) + + / `POST /api/experion/{write,mode,control}` / UI "OPC UA Write" 탭 | + 217 +| 읽기 | `ExperionRealtimeService`(실시간 PV 구독, IHostedService), `query_pv_history`(MCP)/`ExperionHistoryCon + +troller` | + 218 +| 백그라운드 | `IHostedService`/`AddHostedService` 패턴 기존 사용 → 신규 `AutoRunService : BackgroundService` + +그대로 적용 | + 219 +| LLM 감독 | `query_pv_history`, `find_tags`, `trace_connections`, `active_alarms`, `query_events`, `summarize_ + +events`, `generate_status_report`, ReAct 에이전트 모드 | + 220 + + 221 +--- + 222 + + 223 +## 10. 미해결/확인 필요 항목 + 224 + + 225 - [ ] **P(측류 제품 추출) 경로 매핑** — *사용자 직접 진행* + 226 - [ ] B(하부) 발출 유량계·밸브 태그 확정 + 183 -- [ ] 6.1 / 6.2 선택 확정 (시작 지점 / LLM 권한) + 227 +- [ ] **쓰기 경로 안전 가드(§6-1) 신규 구현** — 현재 `WriteTagAsync`에 클램프/rate/변동폭 0건 (Phase 0 선행) + 228 +- [ ] **DCS 구성**: RSP 소스 포인트 생성·연결, OP 데드맨(stale→MAN→AUTO) 로직, RSP 추종/홀드 설정 + 229 +- [ ] 헌팅 임계 정의(진폭/주기/지속) 및 stiction 자동판별 신뢰 수준 + 230 +- [ ] 각 MV의 hard min/max·변화율·밸브 변동폭 한계(공정 안전 범위) + Cv 커브·배관 물리 데이터 수집 형태 + 231 +- [ ] P(측류) 분리/조성 모델(§1.2-가) 깊이 결정: 고정 τ vs 간이 트레이모델 vs 경험모델 + 232 - [ ] `ask_iiot_llm`(vLLM) 빈 응답 — vLLM 엔드포인트 상태 점검 + 185 -- [ ] 각 MV의 hard min/max·변화율 한계값(공정 안전 범위) 수집 + 233 - [ ] Step Test 수행 가능 시점/조건 (가동 중 5~10% 스텝) + 187 -- [ ] APC 블록 내장 여부 vs 일반 PID 환경 (원본 §"현재 시스템 확인 사항") + 234 +- [ ] APC 블록 내장 여부 vs 일반 PID 환경 / MoC 절차 + 235 + 236 --- + 237 + ... + 241 - 실시간 읽기: `src/Infrastructure/OpcUa/ExperionRealtimeService.cs` + 242 - UI: `src/Web/wwwroot/index.html` (#pane-write) + 243 - MCP 도구: `mcp-server/server.py` (find_tags, trace_connections, query_pv_history, ask_iiot_llm 등) + 244 + + 245 +## 부록 B. 합의된 핵심 결정 (요약) + 246 +1. 감독제어 — 엔진은 별도 변수에만 쓰고 운전원이 스위치로 채택(권한은 운전원). + 247 +2. SP는 **RSP** 경로(LSP/RSP 토글), 외부 추종으로 bumpless. + 248 +3. OP는 **MAN+`.op` 쓰기** 경로(기존 ControlOp), 엔진 워치독 + **DCS 데드맨→MAN→AUTO bumpless** 폴백. + 249 +4. OP 제어법은 **물리 FF(Cv·배관) + 느린 PI + rate제한** (고정+간헐 보정 비채택). + 250 +5. PID 파라미터 재튜닝은 **필수 아님** — MAN에서 OP 대체로 헌팅 안정화 가능(stiction 제외). + 251 +6. LLM은 물리 결정론 위에서 ①커미셔닝 ②드리프트진단 ③소프트센서 ④예외처리 ⑤인터페이스 ⑥교차융합 ⑦헌팅원인진단. + +● 플랜 문서를 전면 개정했습니다. 이번 세션에서 합의한 내용을 모두 반영했습니다. 향후 세션을 위해 핵심 발견을 메모리에 + 남겨두겠습니다. + + Read 1 file, recalled 1 memory, wrote 2 memories (ctrl+o to expand) + +● 플랜 문서 개정과 메모리 기록을 완료했습니다. + + 측류추출-자동운전-플랜.md 개정 내역 + + 처음 작성본(2-Plane 일반론)에서 → 이번 세션에서 합의한 감독제어 구체 설계로 전면 개편했습니다. + + 새로 추가/확정된 핵심 섹션: + + ┌────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ § │ 내용 │ + ├────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ + │ §1 │ 물리 결정론 vs LLM 역할 경계 — Cv·배관으로 B·D는 계산되나 P(측류)는 분리/조성 모델 필요, LLM은 ①~⑦ 가장자리 역할 │ + ├────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ + │ §2 │ 감독제어 아키텍처 — SP=RSP / OP=MAN+OP쓰기 대칭 표, 운전원이 권한 쥠, bumpless 요건, 데드맨 폴백 │ + ├────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ + │ §3 │ LLM-OP 제어법 — FF(Cv) + 느린 PI + rate제한, 크루즈컨트롤 다이어그램, "고정+간헐" 비채택 │ + ├────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ + │ §4 │ 헌팅 검출(결정론) + 원인진단(LLM: 튜닝/외란/stiction) — 4단계 게이트 │ + ├────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ + │ §6 │ 안전 봉투 — 엔진가드·DCS한계·운전원스위치·데드맨·ESD/IL/SIS 독립·한루프·bumpless 7층 │ + ├────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ + │ §7 │ 1~4단계 신뢰 이양 로드맵 (운전원 비전) │ + ├────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ + │ 부록 B │ 합의된 6대 핵심 결정 요약 │ + └────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + + §8 태그 매핑은 P 경로 = 사용자 직접 진행으로 유지했습니다. + + 메모리 + + project_autopilot_plan.md를 추가하고 인덱스에 등록했습니다. 향후 세션이 자동운전 작업에 들어가기 전 알아야 할 두 가지 — 쓰기 + 경로 가드 0건(Phase 0 선행), ask_iiot_llm 빈 응답(vLLM 점검) — 을 명시해 두었습니다. + + 플랜 §10에 미해결 항목(가드 구현, DCS 구성, 헌팅 임계 정의, P 분리모델 깊이 등)을 체크리스트로 정리해 두었으니, 다음에 어느 + 항목부터 착수할지 정하시면 됩니다. + +✻ Churned for 2m 28s + +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── +❯ 쓰기 경로 안전 가드부터 구현해줘 +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + ⏵⏵ accept edits on (shift+tab to cycle) + + +