# RO-BEING OCR 스킬 구현 제안 (무료·로컬 → 자체 호스팅 → 상용)

- 작성일: 2025-09-09
- 목적: 비용/효율 최적화 관점에서 RO-BEING에 맞는 OCR 스킬을 단계적으로 설계·배포
- 원칙: 무료·로컬 우선 → 자체 호스팅 → 최고 성능 상용 API, HTTP API만 사용(직접 import 금지), 스킬은 독립 컨테이너(포트 8501–8599)

## 0) 목표와 기준
- 정확도: 문서 OCR CER/WER 낮춤, 표/키밸류 구조 복원 정확도↑
- 지연/처리량: A4 300–400DPI 기준 실사용 가능 지연(ms/페이지) 확보
- 비용: 로컬 무료 우선, 필요 시 온프레미스/상용 단계적 도입
- 보안/데이터경계: 업로드는 사내 스토리지(`/mnt/hdd/uploads/`), PII 외부 반출 금지
- 운영 표준: `/healthz` 헬스체크 일관화(main.py/Dockerfile/compose/workflows), 로그 30일 롤링(`/mnt/hdd/logs/`)

## 1) 아키텍처 개요
- 흐름: 업로드 → (PDF/이미지 분기) → skill-ocr HTTP 호출 → 텍스트/블록/메타 → RAG(ChromaDB) 저장 → 응답
- 컴포넌트
  - rb*: 클라이언트 요청 처리, 파일 유형 판별, skill-ocr 호출만 담당
  - skill-ocr(8506): OCR 파이프라인 수행(PDF: OCRmyPDF, 이미지: PaddleOCR 등)
  - Storage: `/mnt/hdd/uploads/{user_id}/`, 로그 `/mnt/hdd/logs/skill-ocr/`
  - Vector DB: ChromaDB(텍스트 조각) + PostgreSQL(메타)

## 2) 1단계 — MVP(즉시)
- PDF: OCRmyPDF + Tesseract 5(kor+eng)
  - 장점: 자동 전처리(회전/디스큐/노이즈), 검색가능 PDF 생성, 안정/단순
  - 권장 옵션: `--rotate-pages --deskew --optimize 3 --jobs N`
- 이미지/모바일: PaddleOCR(PP-OCR 계열, det+cls+rec_korean)
  - 장점: CPU에서도 빠름, 한글 정확도 우수, 다국어·경량 모델 제공
- API 스펙(초안)
  - POST `/ocr/pdf` → req: `{ path, langs:["kor","eng"], optimize:3, rotate:true, deskew:true }`
    - resp: `{ pdf_path_searchable, full_text, pages:[{text,conf}], conf_stats, meta{engine,version,latency_ms} }`
  - POST `/ocr/image` → req: `{ path, langs, det:"DB", rec:"PP-OCRv4", use_cls:true }`
    - resp: `{ blocks:[{bbox,text,conf}], full_text, meta{engine,version,latency_ms} }`
  - GET `/healthz` → `{ status:"ok", version, models }`
- rb 연동(rag.py)
  - 파일 확장자로 분기(PDF/이미지) → skill-ocr HTTP 호출 → 결과 텍스트/블록/메타를 RAG 파이프라인에 전달
  - 실패 시 재시도 및 폴백 규칙: PDF 파서 실패→OCR 모드, 저신뢰(conf<阈值) 경고 로그
- 운영
  - 로그 표준: DEBUG(사전처리/모델) / WARN(저신뢰) / ERROR(폴백) 예시 메시지 규격화
  - 저장: 생성된 검색가능 PDF는 원본과 함께 사용자 폴더에 보관

## 3) 2단계 — 고도화(1–2개월)
- Donut(문서 파싱, OCR-free)
  - 대상: 영수증/인보이스/계약서 등 정형 문서 → JSON 직접 추출
  - 데이터: 도메인별 1–2k 샘플 파인튜닝, 지표 CER/WER + 필드 정확도(F1)
  - API: POST `/parse/donut` → `{ path, schema }` → `{ fields... , meta }`
- TrOCR small(텍스트 라인 고정밀)
  - 대상: 서명란/단일행/중요 구획의 라인 인식 정밀도 향상
  - API: POST `/recognize/line` → `{ image_crops:[...], lang }` → `{ lines:[{text,conf}], meta }`
- 구조
  - skill-ocr 내 모듈 확장 혹은 `skill-ocr-parse`로 분리(부하/배포 단위 고려)

## 4) 3단계 — 선택적 확장
- 복잡 레이아웃/표: MMOCR 풀스택(table/layout) 또는 `table-transformers`/`pdfplumber` 병행
- 상용 API(정확도 최우선)
  - Google Document AI / Azure Document Intelligence / AWS Textract 비교 후 선택
  - 의사결정 기준: 표/키밸류 정밀도, 손글씨, 지연·비용, 보안요구
  - 가격은 최신 공식 가격표 기준으로 산정(시점에 따라 변동)

## 5) 평가·모니터링
- 데이터셋: 사내 샘플
  - 스캔 문서 200–500쪽(ko/en 혼합), 모바일 영수증 200장, 필기 메모 100장
- 지표
  - 문자: CER/WER
  - 필드: 필드 정확도/재현/정밀(F1)
  - 표: 셀 매핑/구조 F1
  - 운영: 페이지당 지연(ms), 처리량(pages/min), 실패율, 저신뢰 비율, 리소스(GPU/메모리)
- 관측/로그
  - `/healthz` 응답에 로드/모델 버전 포함
  - 로그는 `/mnt/hdd/logs/skill-ocr/` 30일 롤링, 샘플: `Fallback to OCR`, `OCR quality low: confidence=0.72`

## 6) 배포 가이드(요약)
- 컨테이너: `skill-ocr`(8506)
  - 볼륨: `-v /mnt/hdd/uploads:/mnt/hdd/uploads:ro`, `-v /mnt/hdd/logs/skill-ocr:/logs`
  - 환경: `LANGS=kor,eng`, `THREADS=N`, `USE_GPU=false|true`
  - 헬스체크: `GET /healthz` (main.py/Dockerfile/compose/workflows 동기화)
- rb 연동: rb10508_micro에서 선검증 → rb8001 반영, Nginx 프록시 규칙 준수(proxy_pass 끝에 `/`)

## 7) 리스크 & 폴백
- Tesseract 품질 한계: 저해상도/왜곡/필기체에서 오류↑ → PaddleOCR/TrOCR/Donut로 보완
- 긴 PDF 처리시간: 페이지 병렬화(`--jobs N`), 타임아웃/재시도 정책 설정
- 다국어 혼합: kor+eng 모델, 도메인 사전 기반 후처리(기업명/약어 교정)
- GPU 리소스: 배치 사이즈/혼잡 제어, CPU 폴백 경로 확보

## 8) 단계별 To-Do(요약)
- 1단계(MVP)
  - [ ] skill-ocr API `/ocr/pdf`, `/ocr/image`, `/healthz` 스펙 고정
  - [ ] rb10508_micro 연동(파일 분기, 폴백/에러 처리, 로그 규격)
  - [ ] 지표 수집(CER/WER, 지연) 대시보드 기초
- 2단계(고도화)
  - [ ] Donut 파인튜닝 데이터셋 구성/평가 루프
  - [ ] TrOCR 라인 인식기 통합(세그먼트 추출 포함)
- 3단계(확장)
  - [ ] MMOCR/표 복원 실험
  - [ ] 상용 API PoC 및 비용/정확도 비교

## 9) 참고(근거 자료)
- OCRmyPDF + Tesseract: ocrmypdf.readthedocs.io
- PaddleOCR 비교/리뷰: koncile.ai, modal.com 블로그
- 프레임워크 비교: Medium 리뷰(docTR/MMOCR/EasyOCR 등)
- TrOCR: Hugging Face 문서, AAAI 논문
- Donut: GitHub, arXiv, 산업 적용 리뷰
- Kraken/Calamari: GitHub, 공식 문서
