Contextual Retrieval
컨텍스트 기반 검색은 LLM이 작성한 문서 내 위치 설명을 각 청크 앞에 추가하여 임베딩과 BM25가 적절한 구절을 찾도록 합니다.
문맥 검색은 검색 증강 생성(RAG)을 위한 색인 기법입니다. 대규모 언어 모델(LLM)이 각 문서 전체를 읽고, 문서 내에서 특정 청크의 위치와 역할을 설명하는 짧은 메모(대개 50~100개 토큰)를 작성합니다. 청크를 임베딩하고 키워드 색인에 추가하기 전에 메모를 청크 앞에 붙이므로, 검색 시 청크 자체에는 명시되지 않은 정보도 일치시킬 수 있습니다. Anthropic은 2024년 9월 문맥 검색을 소개했습니다.
해결하려는 문제#
RAG 파이프라인은 정밀하게 임베딩할 수 있고 모델의 컨텍스트 윈도우에 여러 개를 넣을 수 있을 정도로 문서를 작은 청크로 분할합니다. 문서에서 분리된 청크에는 해당 청크를 검색할 수 있게 해 주는 사실이 빠져 있는 경우가 많습니다. Anthropic이 예로 든 재무 공시 청크에는 “회사의 매출은 전 분기보다 3% 증가했습니다.”라고 적혀 있습니다. 회사명이나 분기는 나오지 않으므로 ACME의 2023년 2분기 매출에 관한 질문과 일치시킬 정보가 없습니다. 이는 임베딩과 키워드 검색 모두에 해당합니다. 문맥 검색은 이를 다음과 같이 저장합니다. “이 청크는 2023년 2분기 ACME corp의 실적에 관한 SEC 공시에서 가져온 것입니다. 전 분기 매출은 3억 1,400만 달러였습니다. 회사의 매출은 전 분기보다 3% 증가했습니다.”
객체 크롭도 텍스트 청크와 같은 방식으로 문맥을 잃습니다. Ultralytics의 객체 크롭 솔루션은 이미지나 동영상에서 YOLO26을 실행하고 각 디텍션을 개별 파일로 저장합니다. 파일 이름은 crop_1.jpg, crop_2.jpg 등으로 지정되므로 크롭에 트럭이 보여도 어느 카메라, 장소, 장면에서 가져왔는지는 알 수 없습니다. 카메라 이름, 시간, 주변에서 디텍션된 다른 객체 등 원본 프레임을 설명하는 짧은 접두사를 각 크롭과 함께 색인하면 키워드 및 시맨틱 검색에 필요한 문맥을 복원할 수 있습니다.
컨텍스트 검색의 작동 방식#
각 청크마다 LLM은 전체 문서와 청크를 입력받고 “청크 검색 성능을 높일 수 있도록 전체 문서에서 이 청크의 위치를 설명하는 짧고 간결한 문맥을 제공하세요.”라는 요청을 받습니다. Anthropic은 프롬프트 캐싱을 사용해 Claude 3 Haiku로 각 문서를 한 번만 처리하고 모든 청크에 재사용했으며, 문서 토큰 100만 개당 일회성 비용을 1.02달러로 산정했습니다. 문맥이 추가된 청크는 임베딩 색인(“문맥 임베딩”)과 BM25 키워드 색인(“문맥 BM25”)에 저장됩니다. 쿼리 시 두 색인을 모두 검색하고 하이브리드 검색처럼 결과를 병합한 뒤 재순위화 모델이 상위 후보 150개에 점수를 매기고 가장 우수한 청크 20개를 프롬프트에 넣습니다.
예제 청크를 문맥 없이 임베딩한 경우와 문맥을 추가해 임베딩한 경우를 비교하면 벡터 검색의 효과를 확인할 수 있습니다:
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
# Anthropic's example chunk and the context an LLM wrote for it from the full filing
chunk = "The company's revenue grew by 3% over the previous quarter."
context = "This chunk is from an SEC filing on ACME corp's performance in Q2 2023; the previous quarter's revenue was $314 million."
other = "Globex Corporation reported that Q2 2023 revenue fell 2% on weaker demand."
query = "How did ACME's revenue change in Q2 2023?"
candidates = {"plain chunk": chunk, "contextual chunk": f"{context} {chunk}", "Globex chunk": other}
# Cosine similarity of the query to each indexed text
scores = model.similarity(model.encode(query), model.encode(list(candidates.values())))[0]
for name, score in zip(candidates, scores):
print(f"{name}: {score:.2f}")일반 청크는 질문과의 점수가 0.49로, 다른 회사에 관한 청크와 같은 점수를 얻습니다. 문맥을 앞에 추가하면 청크의 점수는 0.83으로 올라가며 큰 차이로 1위를 차지합니다.
컨텍스트 검색과 관련 기법 비교#
- 후행 청킹: 임베딩 모델의 어텐션을 통해 각 청크 임베딩에 문서 컨텍스트를 부여하며, 청크마다 LLM을 호출하지 않습니다. 저장된 청크 텍스트는 그대로 유지되므로 키워드 검색 성능은 향상되지 않습니다.
- 시맨틱 청킹: 청크가 시작되고 끝나는 위치를 정합니다. 각 청크가 생략하는 내용을 채워 주는 컨텍스트 검색과 함께 사용할 수 있습니다.
- 제목 및 헤딩 접두사: 모든 청크 앞에 동일한 문서 제목이나 섹션 헤딩을 붙이는, 비용이 더 저렴한 기존 방식입니다. 컨텍스트 검색은 각 청크마다 서로 다른 노트를 작성합니다.
- 컨텍스트 엔지니어링: 추론 시점에 모델의 컨텍스트 윈도우에 무엇을 넣을지 결정하는 더 폭넓은 방법입니다. 컨텍스트 검색은 한 단계 앞서 인덱싱할 내용을 다룹니다.
측정된 성능 향상#
Anthropic은 관련 청크가 상위 20개 결과에서 누락된 쿼리의 비율인 1에서 재현율@20을 뺀 값으로 검색 실패율을 측정했습니다. 기준 파이프라인은 쿼리의 5.7%에서 실패했습니다. 컨텍스트 임베딩은 이 비율을 3.7%로 낮춰 35% 감소시켰으며, 컨텍스트 BM25를 추가하면 2.9%로 낮아져 49% 감소했습니다. 결합된 결과를 재순위화하자 실패율은 1.9%가 되어 기준선보다 67% 감소했습니다.










