Repository navigation
OCR Worker
donghoong2 edited this page Oct 28, 2026
·
1 revision
dev
a9974a0(2026-10-12) 기준
OCR 워커는 사용자가 올린 보험·의료 문서(진단서·보험증권·지급결과안내문·청구서·입퇴원확인서·진료비영수증)를 SQS로 받아, GPU OCR → 분류·추출 → PII 마스킹 → 저장 → 리포트 워커 발행까지 처리하는 단일 책임 워커다. 개인정보 보호를 위해 외부 OCR API를 쓰지 않고 모든 처리를 로컬 GPU에서 한다.
이 페이지는 코드의 현재 동작이 아니라 각 단계를 왜 이렇게 만들었는가를 모은 것이다. 동작 상세는 src/ocr_worker/README.md와 docs/architecture/ocr.md가 기준이다.
전체 흐름. 색은 실행 자원(SQS·외부 I/O·GPU·CPU)과 안전 게이트를 구분한다. 6(텍스트 마스킹)과 8(품질 판정)이 저장 전에 막는 게이트다
| 단계 | 결정 | 이유 | 관련 기록 |
|---|---|---|---|
| 소비 | 메시지 큐 워커로 분리, at-least-once + 애플리케이션 멱등 | OCR·VLM은 GPU를 오래 점유한다. 업로드와 같은 경로에 두면 API 지연과 GPU 경합이 함께 생긴다. SQS 표준 큐의 중복 전달은 브로커가 아니라 진입부 멱등 조회·결정적 ID·업서트로 흡수한다 | 결정 로그 D-009~D-011 |
| 재시도 | 인프로세스 재시도 없음, 브로커 재전달에 맡김. 결정적 실패(NonRetryableError)는 즉시 종결 |
재시도 규약을 한 곳에 둔다. 다시 해도 같은 결과인 실패는 재전달할 이유가 없다 | 청구 fan-in 기록 |
| OCR 엔진 | surya-ocr 0.17.x in-process, 결과를 라인 구조(텍스트·bbox·신뢰도)로 보존 | 분류·추출은 텍스트, 텍스트 마스킹은 문자열, 이미지 마스킹은 좌표가 필요하다. OCR은 한 번만 돌리고 세 트랙이 같은 결과를 쓴다. 0.18부터는 별도 추론 서버가 필요해 0.17에 고정 | — |
| 렌더 | PDF 200dpi, 큰 판형은 페이지별로 DPI 자동 하향 | A3 이상 스캔본이 PIL 압축폭탄 한도를 넘었다. 한도를 해제하지 않고 입력을 줄였다 (PR #40) | — |
| 분류·추출 | 가중 키워드 점수, 비-PII 도메인 값만 정규식 추출. 후보에 PII가 섞이면 부분 편집 없이 통째로 버림 | 추출이 마스킹보다 먼저 실행된다. OCR이 인접 셀을 한 줄로 합치면 "병명: … 성명: 홍길동"처럼 PII가 같이 잡힌다 | 초록불 기록 |
| 텍스트 마스킹 | 정규식 ∪ NER 스팬, 잔류 검사 실패 시 저장하지 않음(fail-closed) | 확신이 없으면 저장하지 않는다. PII에서는 가용성보다 안전이 우선 | NER 기록 |
| VLM 보완 | 표 문서 또는 신뢰도 < 0.90 페이지만, groundedness·재마스킹·잔류 검사 통과 시 채택 | 필요한 페이지에만 쓰고, VLM 환각을 원문 대조로 거른다 | VLM 하이브리드 기록 |
| 품질 판정 | 신뢰도 < 0.90 그리고 (이름 없음 또는 도메인 정보 없음) → needs_reupload
|
문서 전체 임계값은 재업로드를 너무 자주 만들고, 유형별 필수 필드는 유지 비용이 크다 | 같은 기록 |
| 이미지 마스킹 | PII 줄 검은 블록 사본, 검증 통과 시에만 원본 삭제 | 손해사정사가 원본과 비슷한 형태로 열람해야 한다. 삭제는 되돌릴 수 없다 | 원본 삭제 게이트 기록 |
| fan-in | 청구의 모든 문서가 종결된 뒤 청구당 ReportJob 1건 |
문서마다 리포트가 생기거나 미완성 청구가 조기 발행되지 않게 한다 | 청구 fan-in 기록 |
VLM은 고른 페이지에만 쓰고, surya 원문과 대조해 지어낸 내용이 없을 때만 병합한다
| 용도 | 모델 | 고른 이유 |
|---|---|---|
| 표 전사 | qwen3.6:35b-a3b | 같은 문서에서 qwen3-vl:8b보다 정확하고 빠름(약 11초 vs 약 15초) |
| PII 좌표(grounding) | qwen3-vl:8b-instruct | 0~1000 정규화 좌표로 이름 칸을 정확히 짚음. 35b-a3b는 박스가 헤더 영역으로 벗어남 |
| (제외) glm-ocr 0.9B | — | 표 정렬은 좋았지만 "급성 심근경색증"을 "급성 심근경쟁증"으로 읽는 의료 용어 오독, 무한 반복 출력 |
표 전사 대상의 예(시험용 가상 문서 촬영본). 지급 결정 표의 행마다 청구·지급 금액과 결과가 있어 surya의 라인 순서만으로는 행·열이 복원되지 않는다
| A. 텍스트 마스킹 (필수) | B. 이미지 검은블록 | |
|---|---|---|
| 입출력 | str → str |
image → image |
| OCR 좌표 | 불필요 | 필수 (surya bbox + 저신뢰도 문서는 VLM grounding 추가) |
| 결과 |
masked_text (LLM 입력), masked_lines
|
masked/ 사본 (SSE-KMS) |
| 보안 함정 | 모델 입력 상한 뒤 무음 누락 | PDF에 박스만 덧그리면 밑 텍스트가 복사됨 → 래스터화 |
| 일치 보장 | 페이지 스팬을 라인 로컬 오프셋으로 잘라 두 트랙이 같은 검출 결과를 씀 | 같음 |
이름·주민번호·주소·연락처·면허번호는 가리고, 진단명·KCD 코드·날짜·치료 기간은 남긴다. 판단에 필요한 값까지 지우면 리포트를 만들 수 없다
이미지 트랙과 원본 삭제. 검증 실패는 예외가 아니라 "원본 보존 + 경고"로 끝난다
- 진단서·청구서처럼 엔티티 필드가 1~2개인 유형은 그 필드가 원래 없는 양식이어도 재업로드로 오탐할 수 있다.
- groundedness 0.3, 저신뢰 0.90은 표본 3건 기준 시작값이다.
- 서명·인감·손글씨 PII는 OCR 라인이 없어 마스킹·검증 모두 못 잡는다.
- 검증 실패 페이지의 사본도 정상 서빙된다. 원본 삭제만 막는다.
- 팀 설계 문서 "OCR Worker 파이프라인 설계 문서", "마스킹 전략", "OCR 표 문서 — surya 한계와 VLM 검증"
-
src/ocr_worker/,docs/architecture/ocr.md
구성과 설계 근거
OCR 인식 · VLM 보완
개인정보 보호 · 마스킹
리포트 정확도
배포 · 데이터 파이프라인
레퍼런스