141 lines
7.4 KiB
Python
141 lines
7.4 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
GUARDiA MES — 중앙 guardia-rag 색인 훅 (대표 도메인 메타 → mes 컬렉션).
|
||
|
||
불량 RCA·SPC 해석·예지보전/예측 해석의 근거 검색을 위해, MES 의 대표 도메인
|
||
**메타데이터(테이블/컬럼/판정규칙/방법 정의)** 만 중앙 RAG 의 `mes` 컬렉션에 적재한다.
|
||
실제 생산/검사 데이터 행·거래처/인사 PII·자격증명은 색인하지 않는다(보안 불변).
|
||
|
||
사용:
|
||
python scripts/rag_ingest_mes.py # 기본(http://127.0.0.1:8020)
|
||
RAG_URL=http://127.0.0.1:8020 python scripts/rag_ingest_mes.py
|
||
|
||
설계 메모:
|
||
- 외부 API 0. 중앙 guardia-rag(온프레미스)만 호출.
|
||
- 멱등: doc_id 안정 → 재실행 시 upsert(중앙이 처리). 실패해도 MES 동작에 영향 없음(보조 스크립트).
|
||
- PII/자격증명 미색인: 거래처 연락처·담당자명·SSH·비밀번호·IP 는 문서에 포함하지 않는다.
|
||
- 수치 결정론 불변: SPC 관리한계·Cp/Cpk·예측치는 MES Java 로직이 산출. 본 문서는 "방법·판정규칙 정의"만
|
||
제공해 AI 가 수치를 재계산하지 않고 해석만 하도록 grounding 한다.
|
||
"""
|
||
import json
|
||
import os
|
||
import sys
|
||
import urllib.request
|
||
import urllib.error
|
||
|
||
RAG_URL = os.environ.get("RAG_URL", "http://127.0.0.1:8020").rstrip("/")
|
||
SOLUTION = "mes"
|
||
|
||
# 대표 도메인 메타 문서 — 불량 RCA·SPC·예측 해석 근거용.
|
||
# (PII/자격증명 컬럼 제외. 판정규칙·방법론·논리지표↔물리컬럼 중심.)
|
||
DOCS = [
|
||
{
|
||
"doc_id": "mes_qms_ncr",
|
||
"source": "MES-SCHEMA-QMS",
|
||
"text": (
|
||
"부적합(NCR) 도메인: 검사/공정에서 발견된 부적합 기록. 핵심 필드 - ncr_no(부적합번호), "
|
||
"defect_code(불량코드), lot_no(LOT), item_code(품목), process_code(공정), "
|
||
"equipment_code(설비), qty_defect(불량수량), root_cause(추정원인), status. "
|
||
"불량코드 접두 규칙: DIM=치수, SCR/외관=표면손상, MAT=자재편차. "
|
||
"원인분석은 4M(Man/Machine/Material/Method)·5Why·파레토 관점으로 수행한다."
|
||
),
|
||
},
|
||
{
|
||
"doc_id": "mes_qms_capa",
|
||
"source": "MES-SCHEMA-QMS",
|
||
"text": (
|
||
"시정조치(CAPA) 도메인: 부적합에 대한 시정·예방 조치. 필드 - capa_no, ncr_no(연결 부적합), "
|
||
"action_type(CORRECTIVE/PREVENTIVE), action_desc(조치내용), owner_role, due_date, status, "
|
||
"effectiveness(유효성 검증결과). 유사 불량의 과거 CAPA 이력은 RCA 근거로 활용한다."
|
||
),
|
||
},
|
||
{
|
||
"doc_id": "mes_qms_inspection",
|
||
"source": "MES-SCHEMA-QMS",
|
||
"text": (
|
||
"검사(inspection) 도메인: 수입/공정/출하 검사 결과. 필드 - inspection_no, item_code, lot_no, "
|
||
"characteristic(검사항목), measured(실측값), lsl(하한규격), usl(상한규격), target(목표), "
|
||
"judgement(PASS/FAIL/REINSPECT), aql. 판정규칙: measured<lsl 또는 measured>usl 이면 FAIL. "
|
||
"deviation = measured - target. 최종 판정 권한은 사람에게 있으며 AI 는 초안만 제시한다."
|
||
),
|
||
},
|
||
{
|
||
"doc_id": "mes_method_spc",
|
||
"source": "MES-METHOD-SPC",
|
||
"text": (
|
||
"SPC(통계적공정관리) 방법 정의 — 관리도 X̄-R, p, np, c, u. 런 규칙(Western Electric/Nelson): "
|
||
"RULE1 관리한계 이탈(>UCL 또는 <LCL), RULE2 연속 9점이 중심선 한쪽, RULE3 연속 6점 증가/감소 추세. "
|
||
"공정능력: Cp=(USL-LSL)/(6σ), Cpk=min((USL-μ),(μ-LSL))/(3σ). "
|
||
"★수치(평균·UCL·LCL·Cp/Cpk·이탈점)는 MES 결정론 로직이 계산한다. AI 는 이탈 의미·원인·조치만 해석한다(재계산 금지)."
|
||
),
|
||
},
|
||
{
|
||
"doc_id": "mes_equipment_oee",
|
||
"source": "MES-SCHEMA-MES",
|
||
"text": (
|
||
"설비/OEE 도메인: 설비 가동·비가동·종합효율. 필드 - equipment_code, availability(가동률 0~1), "
|
||
"performance, quality, oee(=가용성*성능*품질), downtime_count(비가동 횟수), mtbf_hours(평균고장간격), "
|
||
"mttr_hours(평균수리시간). 예지보전 위험 규칙: 가동률 낮고(<0.7) 비가동 잦으며 MTBF 짧을수록(<100h) 고위험. "
|
||
"★위험점수·정비시점은 MES 결정론 로직이 산출하고 AI 는 추세 해석·우선순위만 제시한다."
|
||
),
|
||
},
|
||
{
|
||
"doc_id": "mes_production_forecast",
|
||
"source": "MES-METHOD-FORECAST",
|
||
"text": (
|
||
"수요/생산 예측 방법 정의 — 생산실적(job)·작업지시·출하 시계열 기반. 베이스라인: 가중 이동평균 + 선형추세 "
|
||
"(예측 = (마지막값 + 기울기*i)*0.6 + 평균*0.4, 음수 클램프). horizon 기본 7일, 최대 90일. "
|
||
"★예측 수치는 MES 결정론 로직이 산출(재현 가능). AI 는 추세 해석·이상신호 강조·생산계획 조정 권고만 한다."
|
||
),
|
||
},
|
||
{
|
||
"doc_id": "mes_inventory_optimize",
|
||
"source": "MES-METHOD-INVENTORY",
|
||
"text": (
|
||
"재고 최적화 방법 정의 — 안전재고 = Z * 수요표준편차 * sqrt(리드타임), 발주점(ROP) = 평균일수요*리드타임 + 안전재고. "
|
||
"기본 서비스수준 95%(Z=1.65). LOT 만료 위험은 lotserial 의 expiry_date 로 감지. "
|
||
"★수치는 MES 결정론 로직이 산출. AI 는 과부족·만료 위험 해석과 발주 권고만 제시한다."
|
||
),
|
||
},
|
||
{
|
||
"doc_id": "mes_rag_contract",
|
||
"source": "MES-RAG",
|
||
"text": (
|
||
"MES 최신 AI 기법 적용(중앙 guardia-rag): 대표 2기능 — (1) 불량 RCA+SPC 이상감지: SPC 수치는 결정론, "
|
||
"원인서술은 /rag/agent(tool-use)+/rag/structured(JSON 강제). (2) 예지보전/수요·생산 예측: 수치는 결정론 베이스라인, "
|
||
"해석은 /rag/agent. 기법 토글(rerank·graphrag·hybrid·tool_use·structured·stream)은 mes_setting 의 rag.* 키로 격리 저장. "
|
||
"무거운 기법은 서버 RAM 제약상 기본 off, 미가용 시 결정론 폴백(degraded:true). 외부 API 0(Ollama 온프레미스)."
|
||
),
|
||
},
|
||
]
|
||
|
||
|
||
def ingest():
|
||
payload = {"solution": SOLUTION, "documents": DOCS}
|
||
data = json.dumps(payload).encode("utf-8")
|
||
req = urllib.request.Request(
|
||
f"{RAG_URL}/rag/ingest",
|
||
data=data,
|
||
headers={"Content-Type": "application/json", "X-Solution-Key": SOLUTION},
|
||
method="POST",
|
||
)
|
||
try:
|
||
with urllib.request.urlopen(req, timeout=120) as resp:
|
||
body = resp.read().decode("utf-8")
|
||
print(f"[OK] ingested {len(DOCS)} docs into '{SOLUTION}' collection")
|
||
print(f" response: {body[:300]}")
|
||
return 0
|
||
except urllib.error.HTTPError as e:
|
||
print(f"[WARN] ingest HTTP {e.code} — 중앙 RAG 응답 이상(스크립트는 보조). 본 MES 동작 영향 없음.")
|
||
return 1
|
||
except urllib.error.URLError as e:
|
||
print(f"[WARN] 중앙 guardia-rag 미가용({RAG_URL}) — 색인 보류. 라이브 가동 후 재실행. (사유 요약: {str(e.reason)[:80]})")
|
||
return 1
|
||
except Exception:
|
||
print("[WARN] 색인 중 예기치 못한 오류 — 보류(MES 동작 영향 없음).")
|
||
return 1
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(ingest())
|