Late Chunking
레이트 청킹은 긴 컨텍스트 모델로 문서 전체를 임베딩한 다음 청크별로 토큰 벡터를 풀링하여 각 청크 임베딩에 문서의 맥락이 유지되도록 합니다.
지연 청킹은 긴 컨텍스트 임베딩 모델이 문서 전체를 먼저 인코딩한 뒤, 생성된 토큰 벡터를 청크 경계에 따라 분할하고 평균 풀링해 청크별 임베딩 하나를 생성하는 문서 청크 임베딩 방식입니다. 풀링 시점에 각 토큰은 이미 문서 전체를 참조했으므로 "교체해야 합니다"라는 청크에도 "그것"이 무엇을 가리키는지 정보가 남습니다. Jina AI 연구진은 2024년 논문 지연 청킹: 긴 컨텍스트 임베딩 모델을 사용한 문맥 기반 청크 임베딩에서 이 방법을 소개했으며, 추가 학습 없이 기존 임베딩 모델에 적용했습니다.
청크 임베딩에서 문맥이 사라지는 이유#
검색 증강 생성(RAG) 시스템은 각 벡터가 하나의 특정 구절을 나타내고 검색된 텍스트가 모델의 컨텍스트 윈도우에 들어가도록 문서를 청크로 나눕니다. 기존 청킹은 각 청크를 별도로 임베딩하므로 앞부분 텍스트와의 모든 연결이 끊깁니다. 매뉴얼의 연속된 두 문장을 예로 들어 보겠습니다. "XR-12 펌프는 프레스 라인에 냉각수를 순환시킵니다."와 "가동 시간 10,000시간이 지나면 교체해야 합니다." 두 번째 문장만 따로 임베딩하면 XR-12 펌프를 언급하지 않으므로, 답을 담고 있는데도 펌프 교체에 관한 질문이 벡터 검색에서 해당 문장과 잘 일치하지 않습니다.
Late Chunking 작동 방식#
문서 전체를 토큰화하고 각 청크의 토큰 범위를 기록합니다. 고정 크기 청킹이나 시맨틱 청킹을 비롯한 모든 분할기를 사용해 경계를 정할 수 있습니다. 그런 다음 전체 토큰 시퀀스를 트랜스포머 임베딩 모델에 통과시키면 셀프 어텐션이 모든 토큰의 정보를 서로 결합합니다. 마지막으로 각 범위에 속한 토큰 벡터를 평균해 해당 청크의 임베딩을 생성합니다. Jina jina-embeddings-v2 모델의 8,192개 토큰처럼 모델의 입력 한도를 초과하는 문서는 겹치는 큰 청크로 인코딩하며, 논문에서는 이를 긴 지연 청킹이라고 부릅니다.
아래 예제는 소형 Sentence Transformers 모델로 펌프 문장을 두 가지 방식으로 임베딩한 뒤 각 결과와 질문을 비교합니다.
import torch
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
chunks = [
"The XR-12 pump circulates coolant through the press line.",
"It must be replaced after 10,000 operating hours.",
]
query = model.encode("When should the XR-12 pump be replaced?", convert_to_tensor=True)
# 기존 청킹: 두 번째 청크를 따로 임베딩
naive = model.encode(chunks[1], convert_to_tensor=True)
# 지연 청킹: 문서 전체를 인코딩한 다음 두 번째 청크의 토큰만 평균 풀링
tokens = model.encode(" ".join(chunks), output_value="token_embeddings")
start = len(model.tokenizer(chunks[0])["input_ids"]) - 1 # [CLS] 토큰과 청크 1의 토큰
late = tokens[start:-1].mean(dim=0) # 마지막 [SEP] 제외
for name, emb in [("naive", naive), ("late", late)]:
print(name, round(torch.cosine_similarity(query, emb, dim=0).item(), 3))독립적으로 임베딩한 청크와 질문의 점수는 0.382인 반면, 같은 문장을 지연 청킹한 결과의 점수는 0.62입니다. 이는 토큰을 풀링하기 전에 "XR-12 펌프"에 어텐션을 적용했기 때문입니다.
객체 탐지에서도 2015년에 동일한 변화가 있었습니다. R-CNN은 각 잘라낸 영역 제안에 합성곱 네트워크를 별도로 실행했습니다. Fast R-CNN은 이미지 전체에 한 번만 네트워크를 실행하고 공유 특징 맵에서 각 영역을 풀링했습니다. VGG16 백본을 사용했을 때 테스트 시 탐지 속도가 213배 빨라졌습니다. Ultralytics YOLO26도 전체 이미지에 백본을 한 번 실행하고 공유 특징에서 모든 바운딩 박스를 예측하므로, 잘라낸 영역만 따로 처리해 탐지 결과를 계산하지 않습니다.
지연 청킹과 관련 방법 비교#
- 문맥 기반 검색: 인덱싱 전에 각 청크에 LLM이 작성한 메모를 앞에 추가합니다. 청크마다 LLM 호출 비용이 발생하고, 추가 문맥이 텍스트이므로 키워드 검색에도 도움이 됩니다.
- ColBERT 지연 상호작용: 토큰마다 벡터 하나를 유지하고 검색 시점에 쿼리와 비교합니다. 지연 청킹은 청크당 벡터 하나로 풀링하므로 일반적인 벡터 인덱스에 저장할 수 있습니다.
- 청크 중첩: 인접 청크에서 몇 개의 문장을 반복합니다. 가까운 문맥만 보존하며 인덱스 크기를 늘립니다.
- 재순위 지정 모델: 첫 번째 검색 후 더 강력한 모델로 검색 후보의 순서를 바꾸며 지연 청킹과 함께 사용할 수 있습니다.
지연 청킹이 효과적인 경우#
대명사, 한 번만 정의된 약어, 보고서와 매뉴얼 같은 서술형 콘텐츠처럼 청크가 앞선 텍스트에 의존할 때 효과가 가장 크며, 제품명처럼 짧고 독립적인 레코드에서는 효과가 가장 작습니다. 이 방법을 사용하려면 토큰을 평균해 풀링하고 토큰 수준 출력을 확인할 수 있는 임베딩 모델이 필요합니다. 또한 문서의 일부라도 변경되면 문서 전체를 다시 인코딩해야 합니다. 지연 청킹으로 만든 청크 벡터는 일반 벡터 데이터베이스에 그대로 저장할 수 있습니다. Jina의 임베딩 API는 연속된 청크 목록을 하나의 문서로 임베딩하는 late_chunking 매개변수로 이 방법을 제공합니다.










