파트리지시스템즈
경력근거: 데이터 수집, 전처리, 모델 적용, 검색, 리포트 생성까지 end-to-end 워크플로우를 구현합니다
파트리지시스템즈는 자율주행·스마트팩토리 등 물리적 세계의 데이터 병목을 푸는 피지컬 AI 데이터옵스 플랫폼 데이터반(databahn)을 만들고, FDE 는 고객 현장에 나가 데이터를 직접 보고 문제를 정의해 수집·전처리부터 리포트까지 end-to-end 워크플로우를 구현합니다. 현장에서 실제로 건네받는 자료는 잘 정리된 API 응답이 아니라 설비보전팀이 손으로 채운 점검일지 엑셀이라, PoC 는 늘 이 파일을 파이프라인이 읽는 표로 바꾸는 데서 시작합니다. 이 도구는 그 앞단(파일 인수 → 행 정리 → 자산·코드 매칭 → 정규화 CSV)을 명령 하나로 끝내고, 정할 수 없는 행은 추측하지 않고 사유를 적어 가려내 고객사에 무엇을 더 받아야 하는지 드러냅니다. 이 포트폴리오가 보여주는 것은 지저분한 문서를 규칙으로 파싱해 정규화 산출물을 내는 데이터 전처리 기술이며, Databahn 경량화 엔진·영상 인식·설비 정비 도메인 전문성은 주장하지 않고 면접에서 솔직히 다룹니다.
고객 현장의 데이터를 직접 보고 풀어야 할 AI·Data 문제를 정의하며 모호한 요구를 기술 문제로 구조화합니다. 손으로 쓴 점검일지를 어떤 스키마로 세울지 정하고 판정 규칙으로 옮긴 이 도구가 직접 정렬됩니다.
데이터 수집·전처리부터 산출물까지 하나의 워크플로우로 구현합니다. 고객사 파일 인수에서 정규화 CSV 산출까지 명령 하나로 잇는 이 도구가 그 사슬의 앞단을 정면으로 맡습니다.
PoC 에서 발견한 반복 가능한 문제 해결 패턴을 제품 기능으로 제안하는 데이터옵스 지향입니다. 파싱 코어와 고객사별 코드표를 나눠 둔 이 도구가 그 제품화 방향과 정렬됩니다.
고객사 설비보전팀에서 받은 수기 점검일지 엑셀과 설비 대장·코드표 시트를 인자로 받아, 병합 셀로 빈 날짜를 상속시키고 반복 머리글·소계·빈 행을 걸러낸 뒤 자산 표기를 설비 대장 별칭으로 코드에 맞추고, 자유서술 칸의 증상·조치 구절을 고객사 코드표 코드로 바꿔 정비 이력 CSV 와 보류 행 CSV 를 씁니다. 행 종류 판정·자산 매칭·코드 확정은 전부 코드표 규칙이 결정하고, LLM 은 한 칸에 뒤섞인 문장을 증상절과 조치절로 나누는 보조만 맡으며 뽑은 구절이 원문에 그대로 있는지 강제로 대조합니다. 결과는 파일과 터미널 요약이라 화면이 없고, Databahn 경량화 엔진이나 영상 인식 모델을 만드는 게 아니라 PoC 첫 주에 늘 먼저 걸리는 파일 인수 구간을 명령 하나로 끝내는 도구입니다.
스마트팩토리 고객사에 파견 나간 파트리지시스템즈 FDE. 설비보전 담당자에게 받은 점검일지 엑셀을 열 때마다 병합 셀과 소계 행을 지우고 '펌프1호'·'P-1'·'PUMP-01' 처럼 흔들리는 자산 표기를 손으로 맞추다 PoC 첫 주를 다 쓰던 사람으로, 파일을 넣으면 파이프라인이 곧바로 읽는 정비 이력 표와 사람이 확인해야 할 행이 갈려 나오길 바랍니다.
고객사 점검일지 엑셀과 설비 대장·코드표를 함께 넣으면, (a) 병합 셀·반복 머리글·소계 행·혼재된 날짜 서식을 규칙으로 정리해 기록 행만 남기고, (b) 자유서술 칸의 증상·조치를 고객사 코드로 바꿔 정비 이력 CSV 를 만들며, (c) 자산이나 코드가 하나로 정해지지 않는 행은 추측하지 않고 보류 행 CSV 로 가려냅니다.
고객사에서 받은 수기 점검일지 엑셀과 설비 대장·코드표를 넣으면 병합 셀·반복 머리글·소계 행을 정리하고 자산 표기를 코드로 맞춘 뒤 자유서술 칸의 증상·조치를 코드로 바꿔 정비 이력 CSV 와 보류 행 CSV 를 쓰고, 처리·보류·건너뜀 행수와 사유 상위 항목을 터미널에 출력하는 CLI입니다. 화면은 만들지 않고 결과는 파일과 터미널 출력입니다. 데이터는 고객사에서 받았다고 가정한 합성 점검일지와 코드표로 시작하며, 스캔 PDF 점검일지 판독은 3주차 과제로 둡니다.
심은 정답과 고객사 보전 담당자 2명 라벨에 견줘 자산 코드·결함 코드·조치 코드 일치율을 재고, 틀린 행을 유형별로 묶어 규칙을 보강한 결과를 터미널 요약과 md 리포트로 냅니다.
스캔한 점검일지 PDF 페이지에서 표를 읽는 어댑터를 붙여 엑셀 경로와 같은 CSV 로 합치고, 폐쇄망 반입용 컨테이너 이미지 한 장으로 라인별 시트를 나눠 돌리는 배치 실행을 붙입니다.
점검일지 시트 1개(120행)와 설비 대장·코드표를 넣고 명령을 한 번 치면, 정비 이력 CSV 와 보류 행 CSV 가 몇 초 안에 떨어지고 처리·보류·건너뜀 행수가 터미널에 요약돼 나오는 걸 시연합니다
일부러 만든 지저분한 입력 30종(병합 셀 빈 날짜·반복 머리글·소계 행·한 칸에 두 자산·미등록 자산·서식이 뒤섞인 날짜)을 넣어도 출력 형식(스키마)이 한 번도 안 깨지고, 자산이나 코드가 하나로 정해지지 않으면 추측하지 않고 보류 행 CSV 로 사유를 적어 내보냅니다
더미에 심은 정답 90행 중 자산 코드가 일치한 게 84행(약 93%), 결함·조치 코드가 둘 다 일치한 게 71행(약 79%)입니다. 단, 점검일지·코드표·정답을 모두 작성자가 만든 합성 기준이라 '성능 검증'이 아니라 '데모 조건에서의 동작'임을 명시합니다
진짜 성능 검증은 여기서 멈춥니다. 위 수치는 전부 작성자가 만든 더미 점검일지·코드표 자가채점이며, 실제 파싱 정확도는 파트리지시스템즈가 들어간 고객사의 실 점검일지와 실 코드표, 실 보전 담당자 검수가 있어야 측정 가능합니다. 이 도구는 그 검증을 파일만 갈아끼워 바로 돌릴 수 있는 상태로 만듭니다
이건 고객·실데이터 없이 혼자 만든 포트폴리오입니다. 모든 수치는 합성 점검일지·코드표 자가채점이라 성능 증명이 아닙니다. 면접에서는 데모 동작과 실검증 준비 상태로 솔직히 설명합니다
이 포트폴리오가 보여주는 것은 지저분한 엑셀 문서를 규칙으로 파싱해 정규화 산출물을 내는 데이터 전처리 기술과, LLM 을 문장 분리 보조로만 가두고 코드 확정을 규칙에 맡기는 설계입니다. Databahn 경량화 엔진·영상 인식 모델·실시간 스트리밍 인프라·설비 정비 도메인 전문성은 포트폴리오로 증명되지 않으므로 주장하지 않으며, 그 깊이는 면접에서 모르면 모른다고 말하는 편이 낫습니다
정답을 작성자가 만들었으니 잘 맞는 것이 당연합니다. 병합 셀 빈 날짜·반복 머리글·소계 행·한 칸에 적힌 두 자산·미등록 자산·코드가 두 개 걸리는 문장 같은 케이스를 더미에 일부러 섞어, 깨끗한 표만 통과시키는 게 아님을 보여줍니다
키워드 별칭 매칭은 표현이 조금만 달라도 놓치고, 반대로 엉뚱한 코드를 걸 위험이 있습니다. 코드가 0개 걸리면 정상 표지가 없는 한 보류로 돌리고, 2개 이상 걸리면 하나를 고르지 않고 후보를 사유에 적어 보류 행 CSV 로 내보냅니다
고객사마다 자산 표기와 코드 체계가 다릅니다. 새 코드 체계를 제정하지 않고 고객사가 이미 쓰는 대장·코드표를 그대로 입력으로 받으며, 별칭이 모자라면 보류 행이 늘어나 무엇을 더 받아야 하는지가 드러나게 둡니다. 스캔 PDF 판독과 실 담당자 검수는 도입 단계 과제로 분리합니다
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
고객사 설비보전팀이 손으로 채워 온 월별 점검일지 엑셀 시트를 행 단위로 읽은 원시 데이터. 파싱 규칙이 가장 먼저 다루는 입력입니다. 병합 셀로 비워진 날짜·반복 머리글·소계 행·혼재된 날짜 서식·자산 표기 흔들림을 일부러 섞고, gold_ 필드로 정답을 심어 자가채점합니다.
| row_no | sheet | date_cell | asset_cell | note_cell | worker_cell | gold_row_kind | gold_work_date | gold_asset_code | gold_fault_code | gold_action_code | gold_status |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 3 | 3월 점검일지 | 2026-03-02 | PMP-01 | 정상 가동 확인, 특이사항 없음 | 김보전 | record | 2026-03-02 | PMP-01 | — | — | ok |
| 4 | 3월 점검일지 | — | 펌프1호 | 9시 30분경 이상 소음, 벨트 장력 조정함 | 김보전 | record | 2026-03-02 | PMP-01 | F-VIB | A-ADJ | ok |
| 5 | 3월 점검일지 | 3/3 | MTR-A | 모터 표면 발열 심함, 부하 낮추고 경과 관찰 | 박정비 | record | 2026-03-03 | MTR-A | F-OVH | A-OBS | ok |
| 6 | 3월 점검일지 | 일자 | 설비 | 특이사항 | 점검자 | header_repeat | — | — | — | — | skipped |
| 7 | 3월 점검일지 | — | 소계 | 3건 | — | subtotal | — | — | — | — | skipped |
아래 JSON Schema 에 맞는 고객사 수기 점검일지 원시 행 90행을 JSON 배열로 생성합니다. 자산 4~6대(펌프·모터·컨베이어 계열), 대부분 정상 기록에 과열·이상 진동·전류 스파이크·누유를 섞습니다.
{"type":"object","properties":{"row_no":{"type":"integer"},"sheet":{"type":"string"},"date_cell":{"type":["string","null"]},"asset_cell":{"type":["string","null"]},"note_cell":{"type":["string","null"]},"worker_cell":{"type":["string","null"]},"gold_row_kind":{"enum":["record","header_repeat","subtotal","blank","note_only"]},"gold_work_date":{"type":["string","null"]},"gold_asset_code":{"type":["string","null"]},"gold_fault_code":{"type":["string","null"]},"gold_action_code":{"type":["string","null"]},"gold_status":{"enum":["ok","needs_check","skipped"]}},"required":["row_no","sheet","date_cell","asset_cell","note_cell","gold_row_kind","gold_status"]}
gold 규칙(위에서부터 먼저 맞는 것 적용): (1) 세 칸(date_cell·asset_cell·note_cell)이 모두 null 이면 gold_row_kind=blank. (2) 칸 값이 머리글 라벨(일자·설비·특이사항·점검자)과 같으면 header_repeat. (3) asset_cell 이 '소계'·'합계'·'계' 면 subtotal. (4) asset_cell 이 null 인데 note_cell 만 있으면 note_only. 이 넷은 gold_status=skipped 이고 gold_work_date·gold_asset_code·gold_fault_code·gold_action_code 를 모두 null 로 둡니다. (5) 그 외는 record: date_cell 이 null 이면 위 record 행의 날짜를 상속하고, '3/3'·'3월 4일' 같은 서식은 YYYY-MM-DD 로 정규화합니다. (6) 자산은 asset_codebook 의 aliases 에 정확히 하나 걸리면 그 code, 0개나 2개 이상이면 gold_asset_code=null 이고 gold_status=needs_check. (7) 결함·조치는 note_cell 에서 코드표 aliases 로 각각 매칭해 정확히 한 코드면 그 코드, 두 코드 이상이면 null 이고 needs_check, 0개면 null. (8) 결함·조치가 모두 0개일 때 note_cell 에 '특이사항 없음'·'정상' 표지가 있으면 gold_status=ok, 없으면 needs_check. (9) 미확정 사유가 하나도 없으면 gold_status=ok.
쉬운 데이터만 만들지 말 것. 다음 하드 케이스를 의도적으로 섞어라(깨끗한 표만 통과시키는 함정 회피): (1) 병합 셀 때문에 date_cell 이 null 인 record 행 8건 이상(날짜 상속이 맞아야 함), (2) 시트 중간에 반복된 머리글 행 2건과 소계 행 3건, 빈 행 2건, note_only 행 2건, (3) 같은 자산의 표기 별칭('PMP-01'·'PUMP-01'·'펌프1호'·'P-1')이 고르게 섞인 행 10건 이상, (4) 미등록 자산 3건과 한 칸에 자산 두 대가 적힌 행 2건(둘 다 needs_check), (5) 날짜 서식 혼재('2026-03-04'·'3/4'·'3월 4일') 각 3건 이상, (6) 결함 키워드가 두 개 걸리는 문장 2건과 서술은 있으나 코드가 하나도 안 걸리는 문장 3건. gold_ 필드는 위 규칙대로 정직하게 채웁니다. JSON 배열만.{"type":"object","properties":{"row_no":{"type":"integer"},"sheet":{"type":"string"},"date_cell":{"type":["string","null"]},"asset_cell":{"type":["string","null"]},"note_cell":{"type":["string","null"]},"worker_cell":{"type":["string","null"]},"gold_row_kind":{"enum":["record","header_repeat","subtotal","blank","note_only"]},"gold_work_date":{"type":["string","null"]},"gold_asset_code":{"type":["string","null"]},"gold_fault_code":{"type":["string","null"]},"gold_action_code":{"type":["string","null"]},"gold_status":{"enum":["ok","needs_check","skipped"]}},"required":["row_no","sheet","date_cell","asset_cell","note_cell","gold_row_kind","gold_status"]}고객사에서 점검일지와 함께 받은 설비 대장·정비 코드표 시트. 자산 별칭과 결함·조치 코드의 증상 표현을 담아, 파싱 결과의 코드를 규칙으로 확정하는 유일한 근거입니다. 새 코드 체계를 제정하지 않고 고객사가 이미 쓰는 표를 그대로 입력으로 받습니다.
| entry_kind | code | label | aliases | line | note |
|---|---|---|---|---|---|
| asset | PMP-01 | 1호 펌프 | ["PMP-01","PUMP-01","펌프1호","펌프 1호","P-1"] | L1 | 냉각수 순환 펌프입니다 |
| asset | PMP-02 | 2호 펌프 | ["PMP-02","PUMP-02","펌프2호","P-2"] | L1 | — |
| asset | MTR-A | A 이송 모터 | ["MTR-A","MOTOR-A","A모터","이송모터A"] | L2 | — |
| asset | MTR-B | B 이송 모터 | ["MTR-B","MOTOR-B","B모터"] | L2 | — |
| asset | CNV-01 | 1호 컨베이어 | ["CNV-01","컨베이어1","이송1호"] | L2 | 2026년 증설분이라 별칭이 아직 정리되지 않았습니다 |
아래 JSON Schema 에 맞는 고객사 설비 대장·정비 코드표 항목 30개를 JSON 배열로 생성합니다. 자산(asset) 항목과 결함(fault)·조치(action) 코드 항목을 섞습니다.
{"type":"object","properties":{"entry_kind":{"enum":["asset","fault","action"]},"code":{"type":"string"},"label":{"type":"string"},"aliases":{"type":"array","items":{"type":"string"}},"line":{"type":["string","null"]},"note":{"type":["string","null"]}},"required":["entry_kind","code","label","aliases"]}
코드 규칙: 자산 코드는 설비군 약어 3자와 일련번호(PMP-01·MTR-A·CNV-01), 결함 코드는 F- 접두, 조치 코드는 A- 접두를 씁니다. aliases 에는 현장에서 실제로 쓰는 한글 표기·영문 표기·약칭을 함께 넣고, inspection_log_rows 의 asset_cell·note_cell 표현이 여기서 매칭되게 맞춥니다.
쉬운 데이터만 만들지 말 것. 다음 하드 케이스를 의도적으로 섞어라(별칭 사전이 완벽하다는 착각 회피): (1) 별칭이 하나뿐이라 현장 표기를 못 잡는 자산 2건(점검일지에서 needs_check 로 떨어져야 함), (2) 서로 다른 두 결함 코드의 별칭에 같은 낱말이 스치듯 들어가 한 문장에서 코드가 두 개 걸리는 조합 1쌍, (3) 별칭이 다른 별칭의 부분 문자열인 쌍('진동'과 '이상 진동') 1쌍, (4) 2026년 증설분처럼 대장에 갓 올라 별칭이 정리되지 않은 자산 2건을 note 에 그렇게 적기. JSON 배열만.{"type":"object","properties":{"entry_kind":{"enum":["asset","fault","action"]},"code":{"type":"string"},"label":{"type":"string"},"aliases":{"type":"array","items":{"type":"string"}},"line":{"type":["string","null"]},"note":{"type":["string","null"]}},"required":["entry_kind","code","label","aliases"]}| Python | 엑셀·코드표 로더, 행 종류 판정과 자산·코드 매칭 규칙 엔진, CSV 산출과 CLI 인터페이스를 구현하는 대표 언어입니다 |
| Docker | 폐쇄망 고객사 현장에 반입할 수 있게 도구와 의존성을 이미지 한 장으로 묶는 배포 단위입니다 |
| Kubernetes | 라인·공장이 여러 곳으로 늘 때 시트를 나눠 배치 실행하는 작업 분배 골조입니다(3주차 확장 수단) |
| RAG | 고객사 코드표가 수백 항목으로 커지면 전부 프롬프트에 넣을 수 없어, 문장과 가까운 코드 후보 항목만 검색해 넣는 후보 축소 계층입니다 |
| LLM | 한 칸에 뒤섞여 적힌 자유서술을 증상절과 조치절로 나누는 보조 모델입니다(코드 확정은 코드표 규칙이 결정합니다) |
| VLM | 스캔한 점검일지 PDF 페이지 이미지에서 표의 행·열 구조와 손글씨 칸을 읽어 같은 스키마로 옮기는 문서 이미지 어댑터입니다(3주차) |
| Computer Vision | 종이로만 남은 점검일지를 다루려면 표 영역 검출과 셀 분할이 필요하다는 문서 이미지 처리 맥락입니다(VLM 어댑터의 전처리) |
| MLOps | 같은 입력에 같은 결과가 나오는지 골든셋으로 회귀 검증하고 파싱 규칙 변경 이력을 실행마다 남기는 재현 계층입니다 |
✓ pass → 그대로 멈춰도 완결입니다. 더 키우려면 2주차(코드화가 맞았는지 확인)로 진행합니다.
✓ pass → 여기서 멈춰도 완결입니다. 더 키우면 3주차(스캔 PDF·여러 라인 확장)로 진행합니다.
정비 이력 CSV 한 행. 원시 점검일지 행 하나를 날짜·자산 코드·결함 코드·조치 코드와 그 근거 구절로 정규화해 담습니다. 코드는 전부 코드표 규칙이 결정하고, 증상절·조치절만 LLM 이 원문에서 잘라 옵니다. status 가 ok 인 행은 maint_history.csv 로, needs_check 인 행은 사유와 함께 unresolved.csv 로 나갑니다.
{"type":"object","properties":{"row_no":{"type":"integer"},"work_date":{"type":["string","null"]},"asset_raw":{"type":["string","null"]},"asset_code":{"type":["string","null"]},"fault_code":{"type":["string","null"]},"action_code":{"type":["string","null"]},"symptom_span":{"type":["string","null"]},"action_span":{"type":["string","null"]},"status":{"enum":["ok","needs_check","skipped"]},"reason":{"type":["string","null"]},"hedge":{"type":["string","null"]}},"required":["row_no","work_date","asset_raw","asset_code","fault_code","action_code","status"]}[
{
"input_ref": "row 4 (병합 셀로 날짜가 빈 기록 행)",
"output": {
"row_no": 4,
"work_date": "2026-03-02",
"asset_raw": "펌프1호",
"asset_code": "PMP-01",
"fault_code": "F-VIB",
"action_code": "A-ADJ",
"symptom_span": "9시 30분경 이상 소음",
"action_span": "벨트 장력 조정함",
"status": "ok",
"reason": null,
"hedge": "날짜는 위 기록 행에서 상속한 값입니다"
}
},
{
"input_ref": "row 7 (소계 행)",
"output": {
"row_no": 7,
"work_date": null,
"asset_raw": "소계",
"asset_code": null,
"fault_code": null,
"action_code": null,
"symptom_span": null,
"action_span": null,
"status": "skipped",
"reason": "설비 칸이 소계 표기라 기록 행이 아닙니다",
"hedge": null
}
},
{
"input_ref": "row 9 (대장에 없는 자산)",
"output": {
"row_no": 9,
"work_date": "2026-03-04",
"asset_raw": "신규 이송기",
"asset_code": null,
"fault_code": null,
"action_code": "A-CLN",
"symptom_span": null,
"action_span": "먼지 많아 청소",
"status": "needs_check",
"reason": "설비 대장 별칭에 '신규 이송기' 가 없어 자산 코드를 정하지 못했습니다",
"hedge": "증설분일 가능성이 있어 대장 갱신본을 받아야 확정됩니다"
}
},
{
"input_ref": "row 15 (결함 코드가 두 개 걸리는 문장)",
"output": {
"row_no": 15,
"work_date": "2026-03-06",
"asset_raw": "PUMP-01",
"asset_code": "PMP-01",
"fault_code": null,
"action_code": "A-STP",
"symptom_span": "온도 높음 및 진동 동시 발생",
"action_span": "라인 정지 후 엔지니어 호출",
"status": "needs_check",
"reason": "결함 코드 후보가 F-OVH·F-VIB 둘이라 하나로 정하지 않았습니다",
"hedge": "주 원인 판단은 보전 담당자 확인이 필요합니다"
}
}
][자동 검증] 1. 출력 형식(필드·enum)이 JSON Schema 를 통과하는지 확인합니다. 2. status 가 skipped 인 행이 행 종류 규칙(빈 행·반복 머리글·소계·비고 전용)과 일치하고, 코드 필드가 전부 null 인지 봅니다. 3. work_date 가 YYYY-MM-DD 로 정규화됐는지, 원시 날짜 칸이 비었으면 바로 위 기록 행의 날짜를 상속했는지 확인합니다. 4. asset_code·fault_code·action_code 가 코드표 별칭 매칭 결과와 일치하는지 재계산해 대조하고, 후보가 0개나 2개 이상이면 코드가 null 이고 status=needs_check 이며 reason 이 비어 있지 않은지 강제합니다. 5. symptom_span·action_span 이 원시 note_cell 의 substring 인지 매칭하고, 두 구절이 서로 겹치지 않는지 봅니다. 6. gold_ 필드와 비교해 자산 코드 일치율, 결함·조치 코드 동시 일치율을 계산합니다. [수동 검증] 1. 고객사 보전 담당자 2명이 비동기로 같은 시트를 라벨링해 일치율과 bootstrap Cohen's κ(두 사람 일치가 우연 이상인 정도, 0~1) 하한 0.6 이상을 봅니다. 2. 전체의 5% 를 사람이 직접 점검합니다.