에이치에너지
경력근거: LLM 에이전트·RAG·워크플로 자동화로 해결책을 빠르게 설계·구현·배포 (프로세스·문서 자동화, 발전소 진단 알람·조치 자동화 등).
에이치에너지는 모햇·솔라온케어·솔라쉐어로 전국의 옥상·지붕 태양광을 짓고 운영하며, 시공사·안전관리자·발전사업자를 플랫폼 생태계로 끌어들이는 회사입니다. 이 자리는 자사 코드베이스만 보는 개발이 아니라 계약 고객사인 발전사업자 현장에 들어가 개발·인허가·O&M·전력거래의 병목을 찾아 AX 과제로 바꾸는 일이고, 현장에서 실제로 받는 자료는 정돈된 API 응답이 아니라 ERP 에서 내려받은 엑셀과 정산 명세서 PDF 입니다. 이 도구는 그 파일을 그대로 받아 자동화가 되는지 검증하는 첫 단계를 만들어 둔 것입니다. 다만 이 포트폴리오가 보여주는 것은 비개발 직군 문서 파싱과 명칭 정규화, 규칙 기반 금액 대조 같은 기술이며, 전력거래·정산 회계 도메인 전문성은 주장하지 않습니다. 모르는 깊이는 면접에서 모른다고 말하는 편이 낫습니다.
사업 현장에 직접 들어가 문제를 정의하고 AI 로 풀어 제품까지 끌고 가는 팀입니다. 고객사 정산 담당자가 매달 손으로 맞춰보던 대사 작업을 받아 자동화가 되는지 검증하고 돌아가는 도구로 만드는 것이 이 역할의 핵심입니다.
프로토타이핑에서 멈추지 않고 배포·모니터링·운영까지 끌고 가는 능력을 봅니다. 1주차 CLI 완결품을 2주차에 GCP Cloud Run Jobs 월 배치로 올려 실행 로그를 남기는 흐름으로 이 요구를 그대로 보여줍니다.
우대사항이 에너지·제조 같은 물리세계 도메인 데이터와 비IT 현업 협업, 그리고 RAG·워크플로 자동화 경험입니다. 비개발 정산 담당자가 실제로 쓰는 엑셀·PDF 를 입력으로 받고 계약서 조항을 근거로 인용하는 구성으로 이 우대 역량에 그대로 닿습니다.
에이치에너지 AX 엔지니어가 계약 고객사에 나가서 쓰는 CLI입니다. 고객사 정산 담당자가 매달 받는 전력판매 정산 명세서 PDF 와 사내 ERP 에서 내려받은 발전소·계약 마스터 엑셀을 인자로 받아, 표 안의 소계행과 페이지마다 반복되는 머리글을 규칙으로 걸러내고 발전소명 표기 흔들림을 계약 코드에 붙입니다. 계약 단가와 계량 전력량으로 기대 금액을 계산해 명세서 금액과의 차액을 발전소별로 산출하고, 계약이 없거나 단가 칸이 비어 판정할 수 없는 행은 금액을 추측하지 않고 담당자에게 보낼 확인 질문으로 넘깁니다. 결과는 화면이 아니라 발전소별 판정표 csv 와 사람이 읽는 리포트 md 파일로 떨어집니다.
제3자 소유 태양광 발전소 마흔 곳 남짓을 보유한 발전사업자의 정산 담당자입니다. 매달 전력판매 정산 명세서 PDF 와 사내 ERP 에서 내려받은 계약 엑셀을 나란히 띄워 놓고 발전소마다 금액을 손으로 맞춰보다가, 어느 발전소가 얼마나 비는지와 누구에게 무엇을 물어야 하는지를 한 번에 받아보고 싶은 사람입니다. 엑셀은 능숙하지만 개발자는 아니어서, 파일을 넣으면 결과 파일이 나오는 방식이라야 매달 혼자 돌릴 수 있습니다.
고객사가 매달 받는 정산 명세서와 ERP 계약 마스터를 한 스키마로 정규화하면, (a) 소계행·머리글 반복 같은 집계 행을 규칙으로 걸러내고, (b) 계약 단가와 계량 전력량으로 기대 금액을 계산해 명세서 금액과의 차액을 발전소별로 정확히 짚으며, (c) 계약이 없거나 단가가 비어 판정할 수 없는 행은 추측 없이 확인 질문 목록으로 넘길 수 있습니다.
명세서 PDF 와 계약 엑셀 경로를 인자로 주면 집계 행을 걸러내고 발전소명을 계약 코드에 붙인 뒤, 계약 단가로 기대 금액과 차액을 계산해 판정표 csv 와 리포트 md, 확인 질문 목록을 파일로 내놓는 동작하는 CLI입니다. 텍스트 레이어가 있는 PDF 를 가정해 시작하고, 스캔본 이미지 판독은 2주차 이후 과제로 미룹니다. 명세서와 계약 마스터는 작성자가 만든 더미로 시작합니다.
CLI를 GCP Cloud Run Jobs 배치로 올려 실행 로그와 실패 기록을 남기고, 계약서 PDF 조항을 Vertex AI 임베딩으로 색인해 단가 근거 문장에 인용을 달아 리포트에 붙이는 단계입니다. 파싱·대조·질문작성 단계를 에이전트로 나눠 단계별 로그를 남기고, 질문 문구가 사람 검수와 얼마나 맞는지도 측정합니다.
n8n 워크플로로 월 명세서가 올라오면 배치를 자동 실행해 리포트를 지정 폴더에 적재하고, BigQuery 로 발전소별 차액 추이와 자주 나오는 오류 유형을 집계하며, 서식이 다른 두 번째 고객사 명세서를 파서 규칙만 바꿔 붙여 재사용성을 확인하는 단계입니다.
고객사에서 받은 6월 명세서 PDF 와 계약 엑셀을 CLI에 넣으면 판정표 csv 와 리포트 md, 확인 질문 목록이 몇 초 안에 파일로 떨어지는 것을 시연합니다. 판정 한 줄마다 어느 파일 몇 번째 행에서 왔는지 출처가 붙습니다
기대 금액과 차액이 계약 단가와 계량 전력량으로 그대로 재현되는지 자동 채점에서 전부 통과하고, 소계행과 머리글 반복 행이 판정 대상에서 빠진 건수가 정답과 일치함을 보여줍니다
별칭 표기·단가 칸 결측·계약 미등록·계약기간 이탈·계량값 파싱 실패를 섞은 하드 케이스 40행을 넣어도 출력 형식이 한 번도 안 깨지고, 계약을 못 찾은 행은 금액을 추측하지 않고 계약미등록으로 표시합니다. 다만 데이터와 정답을 모두 작성자가 만든 합성 기준이라 '성능 검증'이 아니라 '데모 조건에서의 동작'임을 명시합니다
진짜 성능 검증은 여기서 멈춥니다. 위 결과는 전부 작성자가 만든 더미 명세서·계약 마스터의 자가채점이며, 실제 대조 정확도는 고객사의 실 명세서 서식과 정산 담당자 검수가 있어야 측정 가능합니다. 이 도구는 그 검증을 바로 돌릴 수 있는 상태로 만듭니다
이건 고객·실데이터 없이 혼자 만든 포트폴리오입니다. 모든 결과는 합성 데이터 자가채점이라 '성능 증명'이 아닙니다. 면접에서는 '데모 조건 동작 + 실검증 준비 상태'로 솔직히 설명합니다
정답을 작성자가 만들었으니 잘 맞는 것이 당연합니다. 별칭 표기 흔들림·소계행·머리글 반복·단가 칸 결측·계약 만료 후 등장·계량값 파싱 실패 같은 하드 케이스를 더미 명세서에 일부러 섞어, 쉬운 문제만 푸는 게 아님을 보여줘야 합니다
이 포트폴리오가 보여주는 것은 비개발 직군 문서 파싱과 명칭 정규화, 규칙 기반 금액 대조 같은 기술이며, 전력거래·정산 회계 도메인 전문성은 주장하지 않습니다. 모르는 깊이는 면접에서 모른다고 말하는 편이 낫습니다. 정답은 계약 단가와 계량 전력량으로 결정되는 규칙으로 객관 채점하고, LLM 은 질문 문구 작성 같은 보조만 맡깁니다
실제 도입 시 달라지는 것을 명시합니다. 대조 범위를 전력판매 대금 한 종류로 좁혔으므로 공급인증서 정산이나 세금계산서 대사는 범위 밖이고, 고객사마다 명세서 서식이 달라 파서 규칙을 서식별로 붙이는 작업이 남습니다. 스캔본 명세서는 판독 단계가 별도로 필요합니다
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
고객사가 받은 월 전력판매 정산 명세서 PDF 에서 뽑아낸 원시 행입니다. 대조 판정의 입력이자 정답(gold)을 함께 담습니다. 소계행·머리글 반복·금액 서식 흔들림·별칭 표기·단가 칸 결측·계약 미등록 발전소를 일부러 섞어, 쉬운 데이터만 푸는 게 아님을 보여줍니다.
| row_id | source_file | period | row_kind | plant_name_raw | meter_kwh_raw | unit_price_raw | amount_raw | gold_plant_code | gold_expected_amount_krw | gold_flag |
|---|---|---|---|---|---|---|---|---|---|---|
| r001 | 2026-06_전력판매_정산명세서.pdf p2 | 2026-06 | 명세행 | 성남 상대원 지붕1호 | 12,480 | 121.5 | 1,516,320원 | PL-1021 | 1,516,320 | 일치 |
| r002 | 2026-06_전력판매_정산명세서.pdf p2 | 2026-06 | 명세행 | 두정2호 | 9,750 | 118.0 | 1,150,500원 | PL-1035 | 1,150,500 | 일치 |
| r003 | 2026-06_전력판매_정산명세서.pdf p2 | 2026-06 | 명세행 | 반여1호 | 11,200 | — | 1,388,800원 | PL-1042 | 1,388,800 | 일치 |
| r004 | 2026-06_전력판매_정산명세서.pdf p2 | 2026-06 | 소계행 | 소계 | 33,430 | — | 4,055,620원 | — | — | 집계행제외 |
| r005 | 2026-06_전력판매_정산명세서.pdf p3 | 2026-06 | 머리글반복 | 발전소명 | 계량전력량 | 단가 | 정산금액 | — | — | 집계행제외 |
아래 JSON Schema 에 맞는 태양광 전력판매 정산 명세서 원시 행 40건을 JSON 배열로 생성하세요. plant_name_raw 는 plant_contracts 의 official_name 또는 aliases 와 이어지게 하고, gold_expected_amount_krw 는 계량 전력량과 계약 단가의 곱으로 결정되게(정답이 규칙으로 재현되게) 만드세요.
{"type":"object","properties":{"row_id":{"type":"string"},"source_file":{"type":"string"},"period":{"type":"string"},"row_kind":{"type":"string","enum":["명세행","소계행","머리글반복"]},"plant_name_raw":{"type":"string"},"meter_kwh_raw":{"type":"string"},"unit_price_raw":{"type":["string","null"]},"amount_raw":{"type":"string"},"gold_plant_code":{"type":["string","null"]},"gold_expected_amount_krw":{"type":["number","null"]},"gold_flag":{"type":"string","enum":["일치","차액발생","계약미등록","계약기간외","단가미등록","서식오류","집계행제외"]}},"required":["row_id","source_file","period","row_kind","plant_name_raw","amount_raw","gold_flag"]}
쉬운 데이터만 만들지 말 것. 다음 하드 케이스를 의도적으로 섞으세요: (1) 페이지마다 반복되는 머리글 행과 소계행을 3~5건(gold_flag=집계행제외), (2) 금액 서식 흔들림(쉼표 있음·없음, '원' 붙음·떨어짐, 숫자 사이 공백), (3) 같은 발전소를 정식명과 별칭으로 번갈아 표기, (4) unit_price_raw 가 null 인 행(계약 단가로 계산해야 함), (5) 계약 마스터에 없는 발전소 1~2건(gold_flag=계약미등록, 기대 금액 null), (6) 계약 종료일이 지난 뒤 등장한 행 1건(gold_flag=계약기간외), (7) meter_kwh_raw 가 '-' 나 빈 문자열인 행 1~2건(gold_flag=서식오류). JSON 배열만 출력하세요.{"type":"object","properties":{"row_id":{"type":"string"},"source_file":{"type":"string"},"period":{"type":"string"},"row_kind":{"type":"string","enum":["명세행","소계행","머리글반복"]},"plant_name_raw":{"type":"string"},"meter_kwh_raw":{"type":"string"},"unit_price_raw":{"type":["string","null"]},"amount_raw":{"type":"string"},"gold_plant_code":{"type":["string","null"]},"gold_expected_amount_krw":{"type":["number","null"]},"gold_flag":{"type":"string","enum":["일치","차액발생","계약미등록","계약기간외","단가미등록","서식오류","집계행제외"]}},"required":["row_id","source_file","period","row_kind","plant_name_raw","amount_raw","gold_flag"]}고객사 ERP 에서 내려받은 발전소·계약 마스터 엑셀입니다. 발전소명 별칭과 계약 단가, 계약 기간의 진실원이며 기대 금액 계산의 기준이 됩니다. 단가가 계약서 별첨으로 빠져 비어 있는 행과 계약이 끝난 행을 섞어, 판정할 수 없는 경우가 실제로 존재함을 보여줍니다.
| plant_code | official_name | aliases | capacity_kw | unit_price_krw_per_kwh | contract_start | contract_end | note |
|---|---|---|---|---|---|---|---|
| PL-1021 | 성남 상대원 지붕1호 | ["상대원1호","성남상대원 1호"] | 98.4 | 121.5 | 2024-03-01 | 2029-02-28 | — |
| PL-1035 | 천안 두정 옥상2호 | ["두정2호","천안두정 2호"] | 76.2 | 118 | 2024-07-01 | 2029-06-30 | — |
| PL-1042 | 해운대 반여 지붕1호 | ["반여1호"] | 88 | 124 | 2023-11-01 | 2028-10-31 | 명세서에 단가 칸이 자주 비어 옵니다 |
| PL-1058 | 미추홀 학익 옥상1호 | ["학익1호"] | 70.5 | 119.5 | 2025-01-01 | 2029-12-31 | 2025년 단가 조정 후 계약서 부속합의서 존재 |
| PL-1063 | 원주 태장 유휴부지1호 | ["태장1호"] | 145 | 116 | 2024-05-01 | 2029-04-30 | — |
아래 JSON Schema 에 맞는 발전사업자 ERP 발전소·계약 마스터 40행을 JSON 배열로 생성하세요. official_name 은 '지역 동이름 설치형태N호' 형태로 짓고, aliases 에는 명세서에서 실제로 쓰일 법한 축약 표기를 1~2개 넣으세요.
{"type":"object","properties":{"plant_code":{"type":"string"},"official_name":{"type":"string"},"aliases":{"type":"array","items":{"type":"string"}},"capacity_kw":{"type":"number"},"unit_price_krw_per_kwh":{"type":["number","null"]},"contract_start":{"type":"string"},"contract_end":{"type":"string"},"note":{"type":["string","null"]}},"required":["plant_code","official_name","aliases","contract_start","contract_end"]}
쉬운 데이터만 만들지 말 것. 다음 하드 케이스를 의도적으로 섞으세요: (1) unit_price_krw_per_kwh 가 null 인 행 2~3건(단가가 계약서 별첨에만 있는 경우), (2) contract_end 가 대조 대상 기간보다 이른 행 1~2건(계약 종료 후 명세서에 등장하는 경우), (3) aliases 에 띄어쓰기만 다른 표기를 포함해 정규화가 필요하게, (4) 명세서에는 한 번도 나오지 않을 발전소 2~3건(누락 확인 질문 대상). JSON 배열만 출력하세요.{"type":"object","properties":{"plant_code":{"type":"string"},"official_name":{"type":"string"},"aliases":{"type":"array","items":{"type":"string"}},"capacity_kw":{"type":"number"},"unit_price_krw_per_kwh":{"type":["number","null"]},"contract_start":{"type":"string"},"contract_end":{"type":"string"},"note":{"type":["string","null"]}},"required":["plant_code","official_name","aliases","contract_start","contract_end"]}| Python | 명세서·계약 파일 파싱, 표기 정규화, 기대 금액·차액 계산 규칙, 정답 대비 자동 채점 스크립트 |
| CLI(Typer) | 파일 경로와 정산 기간을 인자로 받아 판정표 csv·리포트 md 를 생성하는 실행 진입점 |
| pdfplumber · openpyxl | 정산 명세서 PDF 표와 고객사 ERP 내보내기 엑셀에서 행을 읽어내는 파서 |
| LLM(Claude Sonnet) | 차액 원인별 확인 질문 문구 작성과 항목명 정규화 후보 제안 등 변환 보조(금액 판정은 규칙이 담당) |
| RAG | 고객사 계약서 PDF 조항을 검색해 단가 근거 문장을 clause_id 로 인용 |
| Multi-Agent | 파싱·대조·질문작성 단계를 나눠 각 단계 입출력과 로그를 분리 |
| GCP Cloud Run Jobs | 2주차부터 월 정산 배치를 클라우드에서 실행하고 실행 로그를 수집 |
| Vertex AI | 계약서 조항 임베딩과 검색 서빙 |
| BigQuery | 월별 발전소 차액 추이와 오류 유형 집계 |
| n8n | 명세서 파일이 올라오면 배치 실행과 리포트 적재를 잇는 워크플로 자동화 |
| SQLite | 정규화된 명세서 행·계약 마스터·판정 결과를 담는 로컬 단일 진실원 |
✓ pass → 그대로 멈춰도 완결입니다. 더 키우고 싶으면 2주차(배치 배포·계약서 조항 인용·단계 분리)로 진행합니다.
✓ pass → 여기서 멈춰도 완결입니다. 더 키우면 3주차(자동 실행·월별 집계·두 번째 서식 확장)로 진행합니다.
CLI 실행 한 번의 결과입니다. 1) 명세서 행마다 계약을 붙여 기대 금액과 차액을 판정하고, 2) 소계·머리글 같은 집계 행을 제외 사유와 함께 남기며, 3) 명세서에 나오지 않은 계약 발전소를 짚고, 4) 판정할 수 없는 행을 담당자에게 보낼 확인 질문으로 묶습니다. 금액 판정은 규칙이 결정하고 LLM 은 질문 문구만 맡습니다. 이 객체가 판정표 csv 와 리포트 md 의 원본이 됩니다.
{"type":"object","properties":{"period":{"type":"string"},"source_files":{"type":"array","items":{"type":"string"}},"reconciled":{"type":"array","items":{"type":"object","properties":{"row_id":{"type":"string"},"plant_code":{"type":["string","null"]},"plant_name_normalized":{"type":["string","null"]},"meter_kwh":{"type":["number","null"]},"contract_unit_price":{"type":["number","null"]},"expected_amount_krw":{"type":["number","null"]},"statement_amount_krw":{"type":["number","null"]},"diff_krw":{"type":["number","null"]},"flag":{"type":"string","enum":["일치","차액발생","계약미등록","계약기간외","단가미등록","서식오류","집계행제외"]},"evidence":{"type":"string"}},"required":["row_id","flag","evidence"]}},"unmatched_contracts":{"type":"array","items":{"type":"object","properties":{"plant_code":{"type":"string"},"reason":{"type":"string"}},"required":["plant_code","reason"]}},"questions":{"type":"array","items":{"type":"object","properties":{"to":{"type":"string"},"text":{"type":"string"},"related_row_ids":{"type":"array","items":{"type":"string"}}},"required":["to","text"]}},"totals":{"type":"object","properties":{"rows_total":{"type":"integer"},"rows_reconciled":{"type":"integer"},"diff_sum_krw":{"type":"number"}},"required":["rows_total","rows_reconciled","diff_sum_krw"]},"hedge":{"type":["string","null"]}},"required":["period","source_files","reconciled","questions","totals"]}[
{
"input_ref": "recon run 2026-06 · 정상 대조 구간(r001~r004): 정식명·별칭·단가 칸 결측·소계행이 섞인 행",
"output": {
"period": "2026-06",
"source_files": [
"2026-06_전력판매_정산명세서.pdf",
"발전소_계약마스터_ERP내보내기.xlsx"
],
"reconciled": [
{
"row_id": "r001",
"plant_code": "PL-1021",
"plant_name_normalized": "성남 상대원 지붕1호",
"meter_kwh": 12480,
"contract_unit_price": 121.5,
"expected_amount_krw": 1516320,
"statement_amount_krw": 1516320,
"diff_krw": 0,
"flag": "일치",
"evidence": "2026-06_전력판매_정산명세서.pdf p2 3행 · 계약 PL-1021 단가 121.5"
},
{
"row_id": "r003",
"plant_code": "PL-1042",
"plant_name_normalized": "해운대 반여 지붕1호",
"meter_kwh": 11200,
"contract_unit_price": 124,
"expected_amount_krw": 1388800,
"statement_amount_krw": 1388800,
"diff_krw": 0,
"flag": "일치",
"evidence": "2026-06_전력판매_정산명세서.pdf p2 5행 · 명세서 단가 칸이 비어 계약 단가 124.0 을 적용"
},
{
"row_id": "r004",
"plant_code": null,
"plant_name_normalized": null,
"meter_kwh": null,
"contract_unit_price": null,
"expected_amount_krw": null,
"statement_amount_krw": null,
"diff_krw": null,
"flag": "집계행제외",
"evidence": "2026-06_전력판매_정산명세서.pdf p2 6행 · 소계 행이라 판정 대상에서 제외"
}
],
"unmatched_contracts": [],
"questions": [],
"totals": {
"rows_total": 4,
"rows_reconciled": 3,
"diff_sum_krw": 0
},
"hedge": "단가는 고객사 ERP 계약 마스터 기준이며, 계약서 부속합의서로 조정된 단가는 반영되지 않았을 수 있습니다."
}
},
{
"input_ref": "recon run 2026-06 · 차액이 난 행(r006)과 명세서에 나오지 않은 계약 발전소",
"output": {
"period": "2026-06",
"source_files": [
"2026-06_전력판매_정산명세서.pdf",
"발전소_계약마스터_ERP내보내기.xlsx"
],
"reconciled": [
{
"row_id": "r006",
"plant_code": "PL-1058",
"plant_name_normalized": "미추홀 학익 옥상1호",
"meter_kwh": 8940,
"contract_unit_price": 119.5,
"expected_amount_krw": 1068330,
"statement_amount_krw": 1028100,
"diff_krw": -40230,
"flag": "차액발생",
"evidence": "2026-06_전력판매_정산명세서.pdf p3 4행 · 명세서 단가 115.0 이 계약 단가 119.5 와 다름"
}
],
"unmatched_contracts": [
{
"plant_code": "PL-1102",
"reason": "계약 기간 중인데 6월 명세서에 해당 발전소 행이 없습니다"
},
{
"plant_code": "PL-1121",
"reason": "계약 기간 중인데 6월 명세서에 해당 발전소 행이 없습니다"
}
],
"questions": [
{
"to": "정산 담당자",
"text": "미추홀 학익 옥상1호(PL-1058)의 6월 명세서 단가가 115.0 원으로 찍혀 계약 마스터의 119.5 원과 다릅니다. 2025년 단가 조정 부속합의서가 반영된 값인지 확인 부탁드립니다.",
"related_row_ids": [
"r006"
]
},
{
"to": "정산 담당자",
"text": "부산 재송 지붕3호(PL-1102)와 광주 첨단 지붕1호(PL-1121)는 계약 기간 중인데 6월 명세서에 행이 없습니다. 계량 누락인지 별도 명세로 분리된 것인지 확인 부탁드립니다.",
"related_row_ids": []
}
],
"totals": {
"rows_total": 1,
"rows_reconciled": 1,
"diff_sum_krw": -40230
},
"hedge": "차액 원인은 단가 차이로 좁혀 표시했을 뿐이며, 계량값 자체가 맞는지는 이 도구가 판단하지 않습니다."
}
},
{
"input_ref": "recon run 2026-06 · 판정할 수 없는 행(r009 계약 종료, r010 단가 미등록, r011 계약 미등록, r012 계량값 파싱 실패)",
"output": {
"period": "2026-06",
"source_files": [
"2026-06_전력판매_정산명세서.pdf",
"발전소_계약마스터_ERP내보내기.xlsx"
],
"reconciled": [
{
"row_id": "r009",
"plant_code": "PL-1090",
"plant_name_normalized": "천안 백석 옥상1호",
"meter_kwh": 7860,
"contract_unit_price": 118,
"expected_amount_krw": null,
"statement_amount_krw": 927480,
"diff_krw": null,
"flag": "계약기간외",
"evidence": "계약 종료일 2026-05-31 이후 기간의 명세 행이라 금액을 판정하지 않음"
},
{
"row_id": "r010",
"plant_code": "PL-1115",
"plant_name_normalized": "인천 주안 옥상2호",
"meter_kwh": 9330,
"contract_unit_price": null,
"expected_amount_krw": null,
"statement_amount_krw": 1115000,
"diff_krw": null,
"flag": "단가미등록",
"evidence": "ERP 계약 마스터에 단가가 비어 있어 기대 금액을 계산하지 않음"
},
{
"row_id": "r011",
"plant_code": null,
"plant_name_normalized": null,
"meter_kwh": 6540,
"contract_unit_price": null,
"expected_amount_krw": null,
"statement_amount_krw": 784800,
"diff_krw": null,
"flag": "계약미등록",
"evidence": "'김포 걸포 옥상1호'가 계약 마스터의 이름·별칭 어디에도 없어 추측 없이 미등록으로 표시"
},
{
"row_id": "r012",
"plant_code": "PL-1063",
"plant_name_normalized": "원주 태장 유휴부지1호",
"meter_kwh": null,
"contract_unit_price": 116,
"expected_amount_krw": null,
"statement_amount_krw": 0,
"diff_krw": null,
"flag": "서식오류",
"evidence": "계량전력량 칸이 '-' 로 찍혀 숫자로 읽히지 않음"
}
],
"unmatched_contracts": [],
"questions": [
{
"to": "정산 담당자",
"text": "천안 백석 옥상1호(PL-1090)는 계약 종료일이 2026-05-31 인데 6월 명세에 정산금액이 잡혀 있습니다. 재계약이 체결됐다면 계약 마스터 갱신을 부탁드립니다.",
"related_row_ids": [
"r009"
]
},
{
"to": "계약 담당자",
"text": "인천 주안 옥상2호(PL-1115)는 계약 마스터에 단가가 비어 있어 기대 금액을 계산하지 못했습니다. 계약서 별첨의 단가를 알려주시면 대조에 반영하겠습니다.",
"related_row_ids": [
"r010"
]
},
{
"to": "정산 담당자",
"text": "명세서의 '김포 걸포 옥상1호'는 계약 마스터에 없는 이름입니다. 신규 발전소인지 기존 발전소의 다른 표기인지 확인 부탁드립니다.",
"related_row_ids": [
"r011"
]
},
{
"to": "정산 담당자",
"text": "원주 태장 유휴부지1호(PL-1063)는 계량전력량 칸이 '-' 로 비어 있습니다. 6월 계량이 실제로 없었는지, 서식이 깨진 것인지 원본 확인을 부탁드립니다.",
"related_row_ids": [
"r012"
]
}
],
"totals": {
"rows_total": 4,
"rows_reconciled": 0,
"diff_sum_krw": 0
},
"hedge": "이 네 행은 금액을 판정하지 않았습니다. 판정 불가 사유만 남기고 추측 금액은 넣지 않습니다."
}
}
][자동 검증] 1. JSON Schema 형식 통과: 출력이 스키마를 만족하는지(필드·enum·타입) 검사해 형식 깨짐을 거릅니다. 2. 기대 금액 재현: expected_amount_krw 가 meter_kwh 와 contract_unit_price 의 곱과 일치하고, diff_krw 가 명세서 금액과의 차와 맞는지 규칙으로 채점합니다. 3. 판정 플래그 일치: flag 가 statement_rows 의 gold_flag 와 행 단위로 일치하는지 대조합니다(계약미등록·계약기간외·단가미등록·서식오류 포함). 4. 집계 행 제외: row_kind 가 소계행·머리글반복인 행이 모두 집계행제외로 빠졌는지, 반대로 명세행이 잘못 제외되지 않았는지 검사합니다. 5. 근거 필드 존재: reconciled 의 evidence 가 실제 source_file 과 행 번호를 가리키는지, 계약 인용이 계약 마스터에 존재하는 plant_code 인지 확인합니다. [수동 검증] 1. 확인 질문 검수: 외부 검수자 두 명이 questions 의 문구가 판정 사유와 맞고 단정·과장이 없는지 라벨링하고, 판정이 얼마나 일치하는지 측정합니다(Cohen's κ: 두 사람 판정이 우연 이상으로 일치하는 정도, 0~1). 2. 판정 불가 처리 점검: 계약을 못 찾거나 단가가 빈 행에서 금액을 추측하지 않고 사유만 남기는지 표본 점검합니다.