LLM과 검색 파이프라인을 위한 PDF 준비

최종 확인

PDF를 언어 모델에 넣는 일 — 검색 증강 생성을 위해, 요약을 위해, 아니면 그저 긴 문맥 창에 붙여 넣기 위해 — 은 이제 문서를 변환하는 가장 흔한 이유 가운데 하나입니다.

동시에 변환 품질이 가장 크게 작용하면서 가장 눈에 덜 띄는 용도이기도 합니다. 검색 파이프라인은 조용히 실패하기 때문입니다. 잘못 변환된 문서는 오류를 내지 않습니다. 그저 엉뚱한 대목을, 혹은 표가 망가진 대목을 돌려주고, 모델은 그것을 근거로 자신 있게 답합니다.

읽는 데 7분

원본 텍스트만 뽑으면 왜 부족한가

어떤 PDF 라이브러리든 몇 줄이면 문서의 글자를 돌려줍니다. 단일 단 업무 메모라면 그것으로 충분합니다. 그 밖의 경우에는 충분하지 않으며, 이유가 셋 있고 모두 검색 품질을 갉아먹습니다.

첫째, 읽는 순서. 날것의 추출은 글자꼴이 그려진 순서대로 텍스트를 돌려주므로, 2단 지면에서는 두 단이 서로 엇갈립니다. chunk의 절반이 무관한 문단 사이를 오가는 문장 조각이 되고, 그것들은 벡터 공간의 아무것에도 대응하지 않는 지점에 embedding 됩니다.

둘째, 경계. 제목이 없으면 글자 수 말고는 쪼갤 근거가 없어 chunk가 문장 한가운데와 표 한가운데에서 끊깁니다. 설명 도중에 시작하는 chunk는 그것만으로 이해되지 않는데, 검색되어 나온 chunk에 요구되는 것이 바로 그 단독 이해 가능성입니다.

셋째, 표. 날것의 텍스트로 뽑힌 표는 어느 열에서 왔는지 아무 표시도 없는 숫자의 흐름이 됩니다. 그것을 읽은 모델은 그래도 질문에 답합니다. 답이 틀릴 뿐입니다.

Markdown이 파이프라인에 주는 것

여기서 Markdown이 좋은 중간 형식인 이유는 보기 좋다는 것과는 아무 상관이 없습니다.

  • 제목이 의미 단위의 chunk 경계를 주므로, chunk가 천 글자짜리 창이 아니라 하나의 절이 됩니다.
  • 제목 경로가 각 chunk에 문맥을 줍니다. embedding 전에 “3장 › 요청 한도 › 버스트 동작”을 앞에 붙일 수 있고, 같은 낱말이 절마다 다른 뜻을 갖는 문서에서 검색 성능이 측정 가능하게 좋아집니다.
  • 파이프 표는 행과 열의 대응을 유지하므로, 검색되어 나온 표를 읽는 모델이 어떤 수치가 어떤 머리글에 속하는지 알 수 있습니다.
  • 간결합니다. Markdown은 요소당 몇 글자의 값으로 구조를 나르지만, HTML이나 JSON 배치 형식은 모델에게 아무것도 알려 주지 않는 마크업에 token을 씁니다.
  • 현재의 모든 모델이 학습 과정에서 엄청난 양을 본 형식이라, 프롬프트에서 따로 설명할 필요가 없습니다.

청킹, 구체적으로

변환된 문서에서 통하는 방식은 제목에서 먼저 나누고, 지나치게 큰 절 안에서만 크기 상한으로 되돌아가는 것입니다.

대부분의 문서 종류에서 버티는 대략의 값입니다.

1차 분할H2 기준, 긴 절에서는 H3으로
목표 chunk 크기500–1,000 tokens
상한문맥에 chunk 여럿이 들어갈 만큼
겹침1–2문장, 제목으로 경계가 잡히면 없어도 됨
chunk 접두문서 제목과 제목 경로 전체
절대 나누지 않음 — 크기를 넘겨도 통째로

표는 절대 나누지 마십시오

대부분의 파이프라인이 어기는 규칙입니다. 단순한 분할기는 자기가 표 안에 있다는 사실을 모르기 때문입니다.

GFM 표를 한가운데서 자르면 chunk 두 개가 생기는데 둘 다 유효한 표가 아닙니다. 앞쪽은 머리글과 몇 줄을 갖고, 뒤쪽은 머리글이 전혀 없는 줄만 갖습니다. 뒤쪽은 쓸모없는 정도가 아니라 해롭습니다. 숫자에 이름표가 없고, 모델이 추측으로 이름표를 붙일 것이기 때문입니다.

쪼개기 전에 표 덩어리를 찾아내고 각각을 온전히 유지하십시오. 그 때문에 목표 크기를 넘는 chunk가 생겨도 그렇게 하십시오. 표가 정말로 한 chunk에 담기지 않을 만큼 크다면, 조각마다 머리글 줄을 되풀이하십시오.

스캔 문서가 놓이는 자리

스캔에는 글자가 없으므로 쪼갤 것이 없습니다. 문자 인식이 먼저 와야 하고, 그 결과에는 파이프라인이 셈에 넣어야 할 성질이 있습니다. 인식은 옮겨 적기가 아니라 추정이기 때문입니다.

특히 두 가지입니다. 신뢰도는 쪽마다 달라서, 마흔 쪽은 거의 완벽하고 세 쪽만 미덥지 못한 문서가 나올 수 있습니다. 인식 단계가 쪽별 신뢰도를 알려 준다면 그것을 chunk 메타데이터로 옮겨, 신뢰도가 낮은 답에 표시를 달 수 있게 하십시오. 또 하나, 읽지 못한 낱말은 표시되지 않고 그냥 빠집니다. 즉 글은 매끄럽고 온전해 보이는데, 엔진이 가장 어려워한 것 — 대개 이름, 관리번호, 수치 — 이 빠져 있습니다.

오류에 대가가 따르는 곳이라면, 인식된 글은 원본과 대조해야 할 실마리로 다루고 기록의 출처로 삼지 마십시오.

말뭉치를 색인하기 전에 확인할 것

색인은 비싸고 느리고 되돌리기 어려운 단계이니, 먼저 표본에 스무 분을 쓸 값어치가 있습니다. 서로 성격이 다르도록 고른 문서 다섯 개를 변환해 Markdown을 읽어 보십시오.

  • 제목이 말이 되는 층위를 이룹니까? 평평하다면 분할기가 나눌 근거가 없어 말뭉치 전체에서 고정 크기 창으로 되돌아갑니다.
  • 표가 살아남았습니까? 두세 개에서 열 수를 원본과 맞춰 보십시오.
  • 여러 단으로 짜인 쪽에서 읽는 순서가 맞습니까? 엇갈린 단은 보면 바로 드러나고, 색인한 뒤에는 보이지 않습니다.
  • 비었거나 거의 빈 변환 결과가 있습니까? 그것들은 스캔이며 다른 경로가 필요합니다.
  • 같은 상투 문구가 모든 문서에 되풀이됩니까? 되풀이되는 머리말과 꼬리말은 거의 같은 chunk가 되어 검색 결과에서 실제 내용을 밀어냅니다.

곁가지가 아닌 개인정보 문제

RAG 말뭉치는 조직이 제3자에게 가장 넘기기 꺼리는 문서로 세워집니다. 계약서, 내부 보고서, 고객 기록, 아직 발표하지 않은 연구 같은 것들입니다.

파이프라인의 어느 단계가 그 문서를 어디로 보내는지 의식적으로 정할 값어치가 있습니다. 변환이 그중 하나일 필요는 없습니다. 브라우저에서 도는 변환기는 파일이 이미 있는 기기에서 처리하므로, 변환 단계가 사슬에 새로운 당사자를 더하지 않습니다. 뒤이은 단계가 어떤지는 별개의 판단이지만, 따로 내릴 수 있는 판단입니다.