20일에 Anthropic에서 Introducing Contextual Retriever이라는 제목으로 새로운 Article을 개제했다. (링크)
기존의 RAG 방식의 문제점을 개선하기위해 나온 방법이라고해서 리뷰해보겠다.
기존의 문제점
기존 RAG에서는 문서를 효율적으로 검색하기 위해 작은 chunk로 나누지만 검색된 각각의 chunk는 문맥적인 정보가 부족하다는 단점이 있다. 그래서 사람이 직접 문장을 나누거나 embedding을 통해 문장의 유사도를 계산해 문서를 나누는 semantic chunk 를 수행하기도 하고 chunk에 문서를 요약한 내용을 넣어준다거나 가상의 문서를 만들어 임베딩하고 요약한 내용만을 인덱싱하는 등 다양한 방법들이 시도 되었다.
Contextual Retriever 소개
이번에 Anthropic에서 Contextual Retriever 이라는 한가지 방법을 소개했다.
각각의 chunk를 embedding 하기 전에 chunk와 관련된 설명을 추가해주고 BM25 index를 생성하는 것이다.
각각의 과정을 Contextual Embeddings 와 Contextual BM25 라고 부른다.
Contextual Retriever 적용방법
아래는 prompt의 예제이고 그 아래의 그림과 같이 chunk와 원본 문서를 함께넣어 context를 생성하는 과정을 거치게된다.
(Cook Book도 같이 제공하고 있다.)
Prompt Caching을 활용하여 비용 절약하기
하지만 이러한 과정은 비용을 크게 발생시킨다. 예를들어 몇 만장의 문서가 있고 문서하나당 50,000 token 의 크기를 가지고
500 token씩 잘라 context를 만들다면 50,500 token이 100번 사용되서 문서하나에만 5,050,000 token이 사용된다.
하지만 Anthropic에서 제공하는 prompt caching을 적용하면 문서를 한번만 불러들여 비용을 크게 절감할 수 있다.
Anthropic에서 예시를 들어주는데 8000 token의 문서에 800 token chunks,
50 token context instructions (context를 생성하기 위한 프롬프트) 그리고 chunk 당 추가할 context를 100 token으로 설정한다면 문서 하나당 $1.02 비용이 소비된다고 한다.
Experiments
또한 여러 분야별로 다양한 실험(embedding models, retrieval strategies, evaluation metrics)을 해보았을 때,
평가 지표로 사용한 1 minus recall@20 지표가 향상되었다고 한다.
1 minus recall@20 = 상위 20개 chunk 내에서 검색에 실패한 관련 문서의 비율을 측정
적용시 고려사항
Contextual Retrieval를 적용하면서 고려해야할 사항들을 몇 가지 적어놓았다.
- Chunk boundaries: chunk 분할 방법을 고려하라. (chunk_size, chunk_boundary, chunk_overlap)
- Embedding model: 모든 임베딩 모델에서 성능을 향상 시키지만 특히 효과적인 것들이 있다 (특히 Gemini, Voyage)
- Custom contextualizer prompts: 특정 도메인이나 사용사례에 맞게 프롬프트를 수정하라
- Number of chunks: 사용 사례에 따라 제공하는 chunk 수를 테스트하라 (5, 10, 20 테스트 결과 20개의 성능이 가장 좋았다)
- Always run evals: 항상 평가하라 (평가를 통해 context와 chunk를 구분하게하여 응답 생성은 개선할 수 있었다)
Reranking으로 성능을 더욱 향상
또한 Reranker를 적용하여 성능을 더욱 향상 시켰다.
주요한 과정은 아래와 같다:
- 초기 retrieval 를 통해 관련성 높은 상위 몇개의 chunk를 가져온다 (top 150 사용)
- 사용자의 query와 함께 top-N chunk를 reranking model 에 전달한다
- reranking model을 사용하여 rank를 매기고 top-K chunk를 선택한다 (top 20 사용)
- top-K chunk를 모델의 context로 전달하여 최종결과를 생성한다.
이 과정을 통해 성능향상을 확인할 수 있었다.
하지만 Reranking을 적용하면 Cost 와 Latency가 발생한다. 결국 성능 향상과 적은 latency와 cost 간의 trade-off다.
Anthropic에서도 주어진 상황에 맞게 여러 실험을 해서 균형을 찾으라고 조언한다.
결론
성능 향상을 최대화 하고싶다면 Contexrual Embeddings (Voyage or Gemini) 과 Contextual BM25를 수행하고
reranking 단계를 수행해서 top 20개의 chunk를 prompt에 전달하라.
아래는 top 20으로 실험한 분야별 결과이다 (top10, top5 도 보고싶다면 링크를 참고)