문서 사진 한 장을 구조화된 데이터로 변환하는 AI 파이프라인. Gemini Vision이 내용을 읽고, PaddleOCR이 위치를 찾고, 코드가 검증한다.
다양한 문서(영수증, 청구서, 계약서, 보험증권 등)의 사진이나 PDF를 업로드하면, AI가 자동으로 필드를 추출하고, 사람이 효율적으로 검수할 수 있는 워크플로우를 제공한다.
| 기능 | 설명 |
|---|---|
| 자동 문서 분류 | 영수증·청구서·계약서 등 유형을 자동 판별 |
| 필드 추출 | 상호명, 날짜, 금액, 품목 등 구조화된 데이터로 변환 |
| Bbox 하이라이트 | 추출된 값이 이미지의 어디에 있는지 위치 표시 |
| 신뢰도 기반 검수 | AI 확신도에 따라 자동승인/빠른확인/수동검토 분류 |
| 정규화 | 날짜(ISO), 금액(숫자), 전화번호 등 형식 자동 통일 |
| 피드백 학습 | 검수자 수정 패턴을 분석하여 다음 추출에 반영 |
LLM(Gemini)에게 모든 걸 시키지 않는다. 텍스트 인식과 필드 식별만 맡기고, 정규화·검증·필터링·좌표 매칭은 모두 결정론적 코드가 처리한다.
이미지를 보고 "이건 상호명, 저건 가격"을 판단한다. 맥락 이해, 다국어, OCR 오류 교정이 강점.
모든 글자의 정확한 픽셀 좌표를 감지한다. 결정론적이고 빠르며 좌표가 정밀하다.
왜 Gemini에게 좌표를 함께 요청하지 않나? 밀집 영수증에서 Gemini가 좌표 계산에 출력 토큰을 소진하면서 뒷부분 품목이 누락되었다(17→14개). 값은 Gemini, 위치는 PaddleOCR로 분리한 이유.
| 역할 | LLM (Gemini) | 코드 |
|---|---|---|
| 텍스트 인식·필드 식별 | ✓ | |
| confidence 초기값 | ✓ | |
| 정규화 (날짜/금액/전화) | ✓ normalizer.py | |
| 바코드 필터링·빈값 제거 | ✓ _clean_gemini_fields | |
| Bbox 스냅핑 (좌표 매칭) | ✓ bbox_snapper.py | |
| 신뢰도 다중시그널 보정 | ✓ confidence_scorer.py | |
| 합계 검증 | ✓ receipt_validator |
회전 보정, 기울기 교정, 샤프닝, 대비 향상 — 문제가 있는 경우에만 조건부 적용. 이미 깨끗한 이미지에는 아무것도 하지 않는다.
긴 변 2048px로 축소 → 배경이 많으면(80% 미만) OpenCV로 문서 영역만 잘라냄. 이후 모든 좌표는 이 crop 이미지 기준.
Gemini Vision이 첫 페이지를 보고 영수증/청구서/계약서 등 자동 분류. 재처리 시 기존 분류를 재사용하여 API 호출 절약.
이미지를 Gemini API에 전송 → 품목명, 가격, 합계 등 구조화된 필드 반환. 멀티페이지는 최대 4개 페이지를 병렬 호출.
바코드 필터링, 빈값 제거, 상호명 중복 병합, 날짜→ISO, 금액→숫자, 합계 산술 검증.
crop 이미지에서 모든 텍스트 좌표를 감지 → Gemini 추출값과 텍스트 유사도로 1:1 매칭 (3-pass 알고리즘).
OCR 매칭률, bbox 유무, 정규화 성공 등 다중 시그널로 confidence 보정. 3단계(초록/주황/빨강)로 분류 후 저장.
| FastAPI | REST API 서버 |
| Celery | 비동기 파이프라인 워커 |
| SQLAlchemy | PostgreSQL ORM |
| MinIO | 파일 스토리지 (S3 호환) |
| Redis | Celery 브로커 + 캐시 |
| React + Vite | SPA 프레임워크 |
| Tailwind CSS | 스타일링 |
| Zustand | 상태 관리 (인증, 테마, 토스트) |
| Axios | API 클라이언트 |
| 파일 | 역할 |
|---|---|
tasks.py | Celery 오케스트레이터 — 전체 파이프라인 흐름 제어 |
llm_structurer.py | Gemini API 호출, 프롬프트 관리, 필드 추출 |
bbox_snapper.py | PaddleOCR 좌표 → Gemini 필드 매칭 (3-pass) |
normalizer.py | 날짜/금액/전화번호 등 형식 정규화 |
confidence_scorer.py | 다중 시그널 기반 신뢰도 보정 |
image_utils.py | 전처리, 리사이즈, auto-crop, 페이지 추출 |
document_classifier.py | 문서 유형 자동 분류 |
| 페이지 | 설명 |
|---|---|
| Home | 문서 목록, 다중 업로드, 상태별 필터 |
| Review | 좌우 분할 — 왼쪽 문서 이미지(bbox 하이라이트) + 오른쪽 필드 검수 |
| Dashboard | 현황(KPI, 분포) + 파이프라인(처리시간, 스냅률, 트렌드) |
Gemini(값 추출)와 PaddleOCR(좌표 감지)를 분리하여 각각의 강점을 극대화. "Gemini에게 좌표를 요청하면 품목이 누락된다"는 실험적 근거에 기반한 설계.
AI 결과를 그대로 저장하지 않는다. 합계 산술 검증, 바코드 패턴 필터링, 상호명 중복 병합 등 규칙 기반 후처리가 AI의 오류를 잡는다.
Gemini가 주는 일률적 confidence를 5가지 시그널(OCR 매칭률, bbox 유무, 정규화 성공, 특수문자 비율, 값 길이)로 보정. 추가 API 호출 없이 코드만으로 정밀도 향상.
검수자의 수정 이력(AuditLog)을 분석하여 "이 유형에서 이 필드가 자주 틀린다"를 감지하고, 다음 추출 시 프롬프트에 주의사항을 자동 추가. 모델 재학습 없이 지속 개선.
모든 필드에 같은 95% 기준 대신, 필드별 실제 정확도를 계산하여 임계값을 조정. AI가 잘하는 필드(합계금액)는 쉽게 자동 승인, 못하는 필드(전화번호)는 엄격히 검토.
| 영역 | 개선 사항 | 기대 효과 |
|---|---|---|
| 성능 | OCR 엔진 캐싱, Gemini 배치 API 도입 | 처리시간 65초→30초 이하 |
| 정확도 | 테이블 구조 인식(PPStructure 경량화), 손글씨 필드 지원 | 표 형태 문서 정확도 향상 |
| UX | 문서 비교(before/after), 배치 검수 모드 | 검수 속도 2배 향상 |
| 안정성 | 파이프라인 단위 테스트, edge case 자동화 | 회귀 버그 방지 |
| 확장 | Gemini 대체 모델 지원(Claude, GPT-4o), 온프레미스 LLM | API 의존도 감소, 비용 절감 |
| 운영 | 처리량 대시보드, 비용 추적, 알림 시스템 | 운영 가시성 확보 |
우선순위 원칙: 정확도 > 검수 효율 > 처리 속도 > 확장성. 사용자가 AI 결과를 신뢰할 수 있어야 나머지가 의미 있다.