성공적인 RAG를 위한 리트리버 최적화 전략

LLM의 환각(Hallucination)을 줄이는 RAG에 대한 관심이 높아지면서, 어떤 RAG 솔루션을 사용해야 답의 후보군을 잘 찾고 답을 생성할 수 있을지에 대한 고민도 커지고 있습니다.

올거나이즈는 RAG 리더보드를 공개하고, 한국어 RAG 성능 평가를 돕고 있는데요.

RAG 리더보드 공개-금융, 공공, 의료, 법률, 커머스 한국어 RAG 성능 평가
올거나이즈가 RAG 리더보드를 공개했습니다. 금융, 공공, 의료, 법률, 커머스의 한국어 RAG 성능을 평가하실 수 있습니다. 테스트 데이터 셋까지 모두 공개해 누구나 사용 가능합니다. 기업을 위한 RAG는 복잡한 표와 이미지에서도 답을 잘 찾을 수 있어야 합니다. 업종별 특징과 실무 문서 스타일을 반영한 RAG들을 비교해 보실 수 있습니다.

RAG 리더보드는 올거나이즈의 RAG팀에서 제작했습니다. RAG팀은 고성능 RAG 솔루션을 고객에게 제공하기 위한 연구를 지속하는 조직입니다.
이정훈 RAG팀장이 RAG 성능을 좌우하는 리트리버 최적화 전략에 대해 공유합니다.


RAG(Retrieval Augmented Generation, 검색증강생성)에서 답변 성능에 가장 큰 영향을 미치는 부분은 Retrieval 입니다.

생성형 AI 환각 줄이는 기업용 RAG, 표+이미지까지 찾아야 게임체인저 (1)
생성AI의 환각을 줄이는 기술로 부각된 RAG(Retrieval Augmented Generation, 검색증강생성). RAG의 개념, 작동 원리 및 고성능 리트리버의 중요성과 RAG 성능을 높이기 위한 전략을 설명합니다.

Alli를 만들면서 느낀 점은 정확한 Context를 프롬프트에 입력하면 정확한 답변을 생성한다는 점입니다.

LLM을 학습시킬 때 In-Context learning도 하기 때문에, Context 기반 답변 생성은 이미 충분히 잘하고 있습니다.

AI 모델 학습시킬 때 자주 말하는 Garbage in, Garbage out이 RAG에도 동일하게 적용됩니다.

질문과 관련된 정확한 context를 입력하면 정확한 답변이 생성되고, 관련 없는 context를 넣으면 Hallucination이 포함된 답변을 생성합니다. 

그렇다면 수많은 context 사이에서 어떻게 질문과 관련된 context를 정확하게 가져올 수 있을까요?

예를 들어 10페이지로 구성된 문서 한 개에서 질문과 관련된 부분을 찾는 것은 쉬운 일입니다. 그러나 50~300페이지로 구성된 50개의 문서에서 질문과 관련된 부분을 찾기는 매우 어렵습니다. 심지어 같은 도메인의 문서라면 각 페이지의 내용이 비슷할 테니 질문과 관련 있는 context를 찾기는 더욱 어렵습니다.

올거나이즈 Alli는 어떻게 Retrieval을 구성했는지 차근차근 알려드리겠습니다.

텍스트를 적절한 크기로 나누는, Chunk

RAG의 Retrieval을 만들 때, 가장 먼저 마주하는 문제는 chunks를 어떤 단위로 할까입니다.

문서에 포함된 전체 텍스트를 한 번에 처리하기 어려울 수 있기 때문에, 텍스트를 더 작은 단위인 "chunks"로 나누어 처리합니다.

예를 들어, 300토큰 단위로 잘라서 context를 구성한다고 가정해 보겠습니다.

이렇게 잘게 쪼개는 경우에는 주변 정보가 소실되어 좋은 답변을 못 생성할 수 있습니다.

Retrieval 성능이 100%라서 주변 정보까지 모두 가져오면 정확한 답변을 생성하겠지만, 현실적으로 retrieval 성능이 100%가 되기 어렵습니다.

예를 들어, 아래 페이지를 200 토큰으로 자른 후, ‘장기시장금리에 대해 월별로 요약해서 설명해’ 라는 질문이 들어온다고 가정해 보겠습니다. 우측 문단의 전체 토큰은 800 토큰이며 월별로 요약하기 위해서는 우측 문단을 모두 참조해야 합니다.

출처 : 한국은행 금융안정보고서

위와 같은 경우가 존재하기 때문에, Alli는 chunks 기준을 문서의 페이지로 잡았습니다. 이렇게 하면, 넓은 범위의 질문들에 대해 답변을 제공할 수 있습니다. 물론 이렇게 하면, 프롬프트에 입력할 수 있는 context 개수의 한계가 있습니다. 

어떤 방식이든 정답이 있는 건 아니지만, 내부적으로 테스트했을 때, 페이지 단위로 접근하는 것이 성능이 더 좋았습니다.

그럼, 수많은 chunks 중 질문과 관련이 있는 chunks를 어떻게 찾아낼까요?

올거나이즈에서는 ChatGPT 등장 이전부터 Retrieval에 많은 관심과 테스트를 하고 있었습니다. Alli는 생성형 기반 모델들의 성능이 향상되기 전부터 추출형 방식으로 사용자의 질문에 대한 정답을 제공했습니다.

추출형은 BERT를 사용해 chunks에서 정답이 되는 부분의 시작 위치와 마지막 위치를 잡아 답변으로 제공합니다. 생성형같이 다양한 형태의 답변을 제공하지 못한다는 단점이 있었지만, 2023년 이전에는 추출형이 생성형보다 상대적으로 성능이 더 좋았습니다.

 Alli 추출형도 마찬가지로, Retrieval을 사용해 질문과 관련된 chunk를 찾아야 합니다. Alli 추출형 Retrieval 구현 방법으로 단어 중심으로 찾는 Keyword Search를 사용했습니다. 키워드 기반 검색으로 ElasticSearch를 사용했고 알고리즘은 BM25를 사용했습니다.

아래 예시처럼 문장의 길이 대비 정확히 일치하는 단어가 많을수록 순위가 높아집니다.

Keyword Search의 장점은 직관적이고 구현하기 쉽다는 점입니다. 직관적이라는 것은 성능에 대한 디버깅이 가능하다는 말입니다. 예를 들어, 특정 키워드에 대해서 가중치를 준다든지 이런 세부적인 접근이 가능합니다.

하지만, 단점은 유의어를 잡아내지 못한다는 점입니다.
예를 들어, apple computer가 아닌 apple에서 개발한 macintosh가 query로 입력되면 일치하는 keyword가 없습니다. 즉, Doc1, Doc2, Doc3가 모두 0점이 됩니다.

 그렇다면, Alli 추출형은 유의어에 대해서 전혀 대응할 수 없었을까요? Alli에서도 사용자 사전을 활용해 유의어에 대응했습니다. 하지만, 모든 유의어를 사용자 사전에 등록할 수 없기 때문에, 이러한 방식에는 한계가 있습니다.

위에서 말했듯이 Keyword Search는 유의어 대응에 한계가 있었습니다. Semantic Search는 이러한 문제를 해결할 수 있습니다. 의미 기반 검색의 작동 방법은 아래와 같습니다.

Alli 추출형도 Semantic Search를 도입하려 했지만, 임베딩 모델의 토큰 수 제한과 성능 한계로 인해 성능이 좋지 않아 도입하지 않았습니다.

Language Model로 Transformer Encoder 기반 모델을 사용해 Dense Vector로 변환했습니다.

모델의 max_token은 512 토큰으로 제한되어 있으며, Alli는 페이지 단위로 chunk하고 있기 때문에 최소 1K 이상의 텍스트를 입력받을 수 있어야 했습니다.

Longformer와 Bigbird 같은 sparse attention을 사용해 연산량을 줄인 long token 모델들도 검토하였지만, 성능이 좋지 않아 도입하지 않았습니다.

그럼 Alli는 현재 유의어에 제대로 대응하지 못하고 있을까요?

현재 Alli 생성형은 Keyword Search와 Semantic Search를 함께 적용하는 Hybrid Search를 사용하고 있습니다. Keyword Search는 위에서 설명한 BM25를 사용하고 있습니다. Semantic Search는 앞에서 말했듯이 모델 토큰 수의 한계가 있었지만, 최근에는 성능 좋은 4k~8k 모델들도 공개되고 있습니다.

Langchain RAG의 baseline으로 사용하는 OpenAI Embedding도 4k를 넘어가며, nomic-embed-text, bge-m3, gte-large-en 모델은 모두 max_token이 8192 토큰이며 성능 또한 우수합니다.

하지만, 내부적으로 성능을 비교했을 때, OpenAI Embedding model만 단독으로 사용했을 때 성능이 좋지는 못했습니다.

그래서 BM25 점수, 문서 제목을 Dense Vector로 변환하여 Query와 비교한 코사인 유사도 점수, 마찬가지로, 문서 페이지에 대한 코사인 유사도 점수를 함께 사용했습니다.

총 3가지의 점수를 정규화한 후, 더해서 최종 점수를 구하고 가장 점수가 높은 Top N개를 프롬프트에 입력했습니다.

아래의 예시로 과정을 간단하게 설명하겠습니다.

리트리버 최적화 전략, Retrieval Optimization

만약, 문서의 제목이 의미 없는 텍스트(ver1.pdf, ver1_1.pdf, 진짜 마지막.ppt)들로 구성되어 있는 프로젝트라면 성능이 좋게 나올까요?

예를 들어, 사용자가 한국어로 질문을 하고 업로드한 문서가 영어라면 어떻게 해야 할까요?

이런 방법에 대응하기 위해서 올거나이즈의 Alli는 간단하게 리트리버 최적화를 사용해 위와 같은 케이스에 대응합니다.

첫번째 케이스에서는 제목이 의미가 없으므로, Title Vector에 대한 가중치를 0으로 하여 점수 반영이 안되도록 제어할 수 있습니다.

두번째 케이스에서는 영어/한국어이므로 Keyword는 의미가 없게 됩니다. Page Vector의 가중치를 높이고 BM25 점수를 낮추면 성능이 향상될 것 입니다.

 

올거나이즈는 사용자 질문이 입력되면 앞에서 다루었던

  • 문서의 paragraph, table, chart에 대해서 파싱을 진행한 후,
  • 사용자에게 최적화된 Retrieval를 기반으로,
  • 올거나이즈 금융 sllm 모델인 Alfi 프롬프트에 입력해,

사용자에게 정확하게 제공합니다.

기업에서 LLM을 사용할 때 환각 걱정 없이 사용하기 위해서는 RAG 최적화 전략이 중요합니다.

빠르게 변화하는 RAG 솔루션을 제대로 적용하고 싶다면 올거나이즈가 도와드리겠습니다. RAG 솔루션에 대한 시연과 데모가 필요하시다면 아래 문의에 남겨주세요.

Contact Us