/augment/text-parser로 PDF에서 텍스트 뽑아내기- 원하는 레코드를 JSON 스키마로 기술하기
- 스키마를 요청이 아니라 강제로 적용해 추출하기
- 텍스트가 전혀 없는 파일 다루기
- 같은 페이지에서 두 경로가 만들어내는 결과 비교하기
준비
Python 3.9 이상,requests 패키지, 그리고 Venice API 키가 필요합니다. 키가 없다면 API 키 생성을 참조하세요.
extract.py를 만듭니다:
AUTH와 JSON_HEADERS가 분리되어 있음에 유의하세요. 파서는 멀티파트 업로드를 받는데, 멀티파트 요청에서 Content-Type을 직접 설정하면 requests가 바운더리를 추가하지 못해 진단하기 짜증나는 방식으로 실패합니다.
1. 텍스트 뽑아내기
/augment/text-parser는 25MB 이하의 PDF, DOCX, XLSX, 또는 일반 텍스트 파일을 받아 텍스트와 토큰 수를 반환합니다. 문서는 메모리에서 처리되며 내용은 보관되지 않습니다.
tokens 수입니다. 다음 요청을 만들기 전에 문서가 얼마의 비용을 초래할지 알려주는데, 긴 PDF는 여러분이 의도한 예산을 쉽게 넘어설 수 있으므로 이는 중요합니다.
2. 원하는 레코드 기술하기
모델에게 JSON을 요청하면 대략 여러분이 요청한 형태의 JSON을 얻게 됩니다. 스키마를 전달하면 스키마와 일치하는 JSON을 얻습니다. 스키마는 생성을 권고하는 것이 아니라 제약하기 때문입니다.additionalProperties: False는 모든 레벨에서 설정할 가치가 있습니다. 이것이 없으면 흥미로운 것을 발견한 모델이 여러분이 전혀 계획하지 않은 키를 추가할 수 있고, 결과를 읽는 코드는 그것을 예상하지 못합니다.
3. 추출하기
한 번의 호출로,response_format이 스키마를 담고 strict가 켜져 있습니다:
200으로 도착하기 때문입니다:
affiliation을 필수로 지정하므로, 모델은 필드를 생략하는 대신 빈 문자열을 반환했습니다. 이는 스키마가 여러분이 지시한 대로 정확히 작동한 것입니다.
빈 문자열과 누락된 값은 서로 다른 사실이며,
required는 이 둘을 하나로 뭉갭니다. “문서가 언급하지 않는다”와 “문서가 여기서 아무것도 말하지 않는다”를 구분해야 한다면, 필드를 {"type": ["string", "null"]}로 타입 지정하고 시스템 프롬프트에서 null을 요청하세요. 스트릭트 모드는 유니온을 받아들이고, "" 대신 null을 얻게 됩니다.사고를 끄기
disable_thinking은 그 요청에서 논쟁의 여지가 있는 줄이므로, 그 논거를 여기 적습니다. 기본 텍스트 모델은 답변하기 전에 추론하며, 추론은 JSON과 동일한 완성 예산에서 끌어옵니다. 같은 추출을 네 번 실행하고 모델이 얼마를 쓰는지 지켜보세요:
예산을 늘리는 것은 첫 번째 문제를 해결하지 못하며, 단지 모델이 도달할 수 있는 상한을 올릴 뿐입니다. 4003 토큰을 쓴 실행은
finish_reason이 length인 채로, 빈 문자열을 반환했습니다.
사고를 끄자 이 추출은 다섯 배 저렴해졌고, 더 유용하게는 매번 동일해졌습니다. 스키마가 이미 추론이 하려던 일을 대신 하고 있으며, 그것은 답이 어떤 형태를 취할지 결정하는 일입니다.
4. 뽑아낼 텍스트가 없을 때
스캐너로 만든 PDF는 텍스트가 아니라 페이지의 이미지들을 담고 있습니다. 파일 이름이 그것을 알려주지도 않고, 파일 크기도 그것을 드러내지 않습니다. 여러분이 감지할 필요는 없습니다. 파서가 대신 해주기 때문입니다:400으로 도착하며, 실패가 아니라 라우팅 신호입니다. 이 파일에는 텍스트 경로를 사용할 수 없으므로 다른 경로를 택합니다: 페이지를 렌더링해 모델이 그것을 보게 하는 것입니다.
5. 두 경로가 의견을 달리하는 지점
같은 첫 페이지에 두 경로를 실행하면 레코드는 거의 동일하게 돌아옵니다. 흥미로운 부분은 그 “거의”입니다:
텍스트 경로는 Ł를 보존했습니다. 비전 경로는 ASCII L을 반환했는데, 문자 코드가 아니라 자형을 읽고 있으며, 발음 구별 부호는 잘 보존되지 않는 작은 시각적 세부 사항이기 때문입니다. 추출된 이름을 데이터베이스와 대조한다면, 이 차이가 그 행을 찾을 수 있을지 없을지를 결정합니다.
여덟 번째 저자는 더 중요합니다. 페이지에는 Illia Polosukhin의 소속이 명시되어 있지 않고, 텍스트 경로는 이를 매번 충실하게 빈 문자열로 보고합니다. 비전 경로는 일부 실행에서 같은 페이지의 그럴듯한 이웃 값으로 필드를 채워 넣었습니다. 픽셀을 읽는 것은 문자를 읽는 것보다 추론의 여지가 더 많고, 필수 필드는 채우라는 초대입니다. 출력을 손으로 확인할 수 없다면, 문서가 텍스트를 제공하는 어디에서든 파싱된 텍스트를 선호할 이유가 됩니다.
비용은 보이는 것보다 가깝습니다. 양쪽 모두에서 사고를 끈 상태로, 이 페이지에서 두 경로는 거의 같은 프롬프트 크기로 실행되었습니다:
이미지는 923,732자의 base64였지만, 그중 어느 것도 여러분이 비용을 지불하는 대상이 아닙니다. 이미지는 인코딩 길이가 아니라 크기로 토큰화되므로, 큰 PNG는 그렇게 보이는 만큼의 비용이 들지 않습니다.
문서에 텍스트가 있을 때는 파싱된 텍스트를 선호하세요. 정확한 문자를 유지하고, 1페이지 너머에 도달하는 데 추가 비용이 들지 않으며, 페이지가 어떻게 배치되었는지 신경 쓰지 않습니다. 파서가 읽을 것이 없다고 말하거나, 차트, 도장, 서명처럼 의미가 레이아웃에 있는 경우에만 비전을 사용하세요.
다른 것을 추출하기
위의 어떤 것도 논문에 특화되어 있지 않습니다. 스키마와 시스템 프롬프트를 바꾸면 파이프라인은 청구서를 추출합니다:description 필드가 실제 일을 하고 있습니다. 날짜는 어떤 형식을 원하는지 말한 뒤에야 모호하지 않게 되며, 03/04/2026은 누가 썼는지에 따라 서로 다른 두 날짜를 의미합니다.
다음 단계
pydantic이나jsonschema로 결과를 스키마에 대해 검증하면, 잘못된 레코드가 세 함수 뒤가 아니라 경계에서 실패합니다.- 추출된 텍스트를 임베딩으로 저장해 문서를 다시 추출하는 대신 문서 전반에 걸쳐 검색하세요.
- 레코드가 아니라 답변을 원할 때는 파일 입력으로 문서를 채팅 완성에 직접 첨부하세요.
- 함수 호출로 도구를 활용하는 에이전트 만들기를 통해 추출기를 에이전트에 도구로 제공하세요.
문서 처리
text-parser 엔드포인트 레퍼런스.
구조화된 응답
json_schema가 완성을 어떻게 제약하는지.
비전
채팅 모델에 이미지 보내기.
파일 입력
직접 파싱하지 않고 문서를 첨부하세요.