개요

PDF에서 값을 뽑아 데이터베이스에 넣는 일은 늘 골치였습니다. 정규식으로 막아 보고, 멀티모달 LLM에 통째로 던져 보고, 결국 사람이 다시 한 번 확인하는 식이었습니다. Datalab이 6월 23일 공개한 lift는 이 흐름을 바꾸려는 시도입니다. 9B 파라미터짜리 오픈웨이트 비전 모델이고, JSON 스키마를 그대로 입력으로 받습니다. 출력은 그 스키마에 맞는 JSON입니다. 형식이 어긋날 수 없는 이유는 디코딩 단계에서 스키마를 깨는 토큰을 아예 못 고르도록 막아 두기 때문입니다.

핵심 요약

  • 스키마-제약 디코딩. JSON Schema가 그대로 vLLM의 response_format으로 들어가고, 문법이 컴파일되어 토큰을 막습니다. 결과 JSON은 구조와 타입이 항상 스키마와 일치합니다.
  • 다중 페이지를 한 번에 읽습니다. 페이지를 잘라서 따로 돌리지 않습니다. 6~64페이지짜리 문서에 흩어진 값도 한 패스에 잡습니다.
  • 없는 값은 null로 돌려주도록 학습. 환각으로 채우지 말고 비워 두라는 abstention 학습이 들어갔습니다.
  • 필드 정확도 90.2%, 중앙값 9.5초. 9B 모델 기준으로 자체 호스팅이 가능한 옵션 중 가장 정확하고 가장 빠른 축에 듭니다.
  • 라이선스는 두 갈래. 코드는 Apache 2.0, 가중치는 변형 OpenRAIL-M. 매출/펀딩 500만 달러 미만의 스타트업과 연구·개인 사용은 무료, Datalab API와 경쟁하는 용도는 금지.

스키마가 출력을 강제한다는 게 무슨 뜻일까

핵심 메커니즘은 한 줄로 요약됩니다. 모델이 스키마를 깨는 토큰은 샘플링조차 할 수 없습니다. 동작은 이렇습니다.

  1. 입력으로 받은 JSON Schema를 Pydantic 모델로 바꾸고, strict JSON Schema 형태로 정규화합니다.
  2. 정규화된 스키마를 vLLM에 response_format으로 넘깁니다.
  3. vLLM은 이 스키마를 토큰 문법으로 컴파일하고, 생성 단계에서 스키마와 충돌하는 토큰은 마스킹합니다.
  4. 모델은 남은 후보 중에서만 다음 토큰을 고릅니다. 결과는 항상 스키마 형식에 맞춰 끝납니다.

다만 한 가지 분명한 한계가 있습니다. 이 제약은 “모양"을 지키게 할 뿐, “내용"이 맞다는 보장은 아닙니다. "number" 타입 필드라면 숫자가 들어오는 건 보장되지만, 그 숫자가 진짜 송장 합계라는 보장은 따로 검증해야 합니다.

지원되는 스키마 기능은 문자열·숫자·정수·불리언, 스칼라/객체 배열, 중첩 객체, 필드 설명입니다. 반대로 enum, anyOf/oneOf, $ref, additionalProperties는 컴파일이 안 됩니다. 이런 스키마가 들어오면 lift는 경고만 남기고 제약 없이 생성하므로, 결과가 스키마 검증에서 떨어질 수 있습니다. 다운스트림에서 한 번 더 jsonschema 검증을 돌리라는 권고가 그래서 붙습니다.

벤치마크 — 9B인데 9.5초

평가는 225개 문서, 페이지 수 6~64장, 약 1만 1천 개 필드를 대상으로 했습니다. 까다로운 케이스 — 페이지를 가로지르는 값, 끝까지 나열해야 하는 리스트, 반드시 null이어야 하는 필드, 헷갈리게 비슷한 값 — 이 일부러 섞여 있습니다.

모델크기필드 정확도문서 전체 정확도중앙값 지연
Datalab API—95.9%44.4%30.8s
Gemini Flash 3.5—91.3%40.0%28.1s
lift9B90.2%20.9%9.5s
Azure Content Understanding—83.4%22.2%73.7s
NuExtract34B81.5%8.4%8.3s
Qwen3.5-9B9B76.32%24.0%16.8s

지연은 단일 GPU에 동시 요청 8개를 걸어 잰 값이고, 로컬 모델은 vLLM 위에서 돌렸습니다. 같은 9B인 Qwen3.5-9B보다 필드 정확도가 14%p 앞서면서, 지연은 절반에 가깝습니다. 문서 전체 정확도 20.9%가 낮아 보일 수 있는데, “1만 1천 필드 중 하나라도 틀리면 0점"인 평가라 길이가 긴 문서에서는 어느 모델이든 떨어집니다.

실제로 어떻게 쓰는가

설치는 Python 3.12 이상에서 한 줄입니다.

pip install lift-pdf
lift_vllm                                      # vLLM 서버 띄우기
lift_extract input.pdf ./output --schema schema.json

파이썬 API는 이렇게 부릅니다.

from lift import extract

schema = {"type": "object", "properties": {...}}
result = extract("document.pdf", "schema.json")
if result.extraction is not None:
    data = result.extraction

스키마를 빠르게 만들어 보고 싶다면 Streamlit 기반의 Schema Studio가 있습니다. pip install lift-pdf[app] 후 lift_app을 실행하면 브라우저에서 스키마를 짜고 바로 테스트할 수 있습니다.

운영 권장 GPU는 h100, a100-80, a100-40, l40s, a10, l4, 4090, 3090, t4까지로 폭이 넓습니다. 9B라 24GB급 카드 한 장으로도 돌릴 수 있다는 게 자체 호스팅 입장에선 큰 장점입니다.

직접 호스팅이냐, Datalab API냐

같은 회사가 둘을 같이 내놨다는 점이 흥미롭습니다. 정리하면 이렇게 갈립니다.

  • lift 직접 호스팅. 데이터가 회사 밖으로 나갈 수 없는 경우, 처리량이 일정하게 크고 비용을 깎아야 하는 경우, 오프라인 환경, GPU 지연을 직접 제어하고 싶을 때.
  • Datalab API. 필드별 검증·인용·신뢰도 점수가 필요한 경우, 가장 높은 정확도가 필요한 경우, 인프라를 들고 가고 싶지 않은 경우, 트래픽이 들쭉날쭉한 경우.

벤치마크에서도 Datalab API가 필드 정확도 95.9%, 문서 전체 44.4%로 lift를 앞섭니다. 정확도가 절대 기준이라면 API가, 데이터 거버넌스와 비용이 우선이라면 lift가 답이 됩니다.

실무자가 볼 핵심 포인트

  • 스키마는 “지시"가 아니라 “제약"입니다. 프롬프트로 형식을 부탁하는 것과 디코딩에서 막는 것은 안정성이 다릅니다. JSON 파싱 에러가 사라지는 것만으로도 파이프라인이 훨씬 단단해집니다.
  • abstention(null 반환)을 신뢰하세요. 송장에 tax_id가 없으면 lift는 빈 값을 채우는 대신 null을 돌려줍니다. “필드 누락"이 신호로 잡히면, 그다음 단계에서 검토 큐로 라우팅하는 로직이 깔끔해집니다.
  • 그래도 검증은 필요합니다. 형식은 지켜져도 값은 틀릴 수 있습니다. 후처리에서 jsonschema 검증과, 가능하면 OCR·룰 기반 교차 검증을 함께 거는 편이 안전합니다.
  • 스키마 설계가 곧 정확도입니다. 필드에 description을 잘 달고, 정말 필수인 필드만 required로 두세요. lift는 description을 힌트로 사용합니다.
  • 컴파일이 안 되는 키워드를 피하세요. enum, anyOf, $ref, additionalProperties가 들어가면 보장이 풀립니다. 가능하면 평탄한 스키마로 시작하고, 필요할 때 점진적으로 확장하는 편이 안전합니다.
  • 라이선스를 먼저 확인하세요. 매출/펀딩 500만 달러를 넘는 회사가 운영에 쓰려면 별도 협의가 필요하고, Datalab API와 경쟁하는 서비스에는 쓸 수 없습니다.

원문 출처

원문 보기