본문 바로가기

Tech/Generative AI

Rag : 나만의 LLM을 만들자

무엇이든 잘 대답하는 LLM의 한계


 ChatGPT가 놀랍다는 건 이제 너무 지루한 말이 되어 버렸습니다. 이미 이 같은 대규모 언어 모델(Large Language Model, LLM)들을 많은 이들이 자신의 업무에 적용해 생산성을 크게 향상시키고 있죠. 무엇이든 잘 답변해 내는 걸 보면, 이제 AI가 아니라 마치 요술램프 지니 같기도 합니다.

 

 그러나, 이러한 LLM의 범용성에도 불구하고, 특정 도메인에 대한 세밀한 정보를 원하는 데는 한계가 있습니다. 예를 들어 특정 지역의 특정 은행 지점의 운영 시간과 같은 질문에 대해 LLM은 그 은행의 구체적인 정보를 알지 못하여, 가장 일반적인 응답을 제공할 가능성이 높은 것처럼 말이죠. 이는 LLM의 큰 한계점 중 하나인 할루시네이션 현상이기도 하죠.

 

 이는 많은 기업들이 LLM을 구축할 때 맞이하는 큰 벽입니다. 이러한 한계를 극복하기 위해선, 특정 도메인에 집중된 정보를 제공할 수 있는 맞춤형 LLM 개발이 필요합니다. 이번 포스팅에선 나만의 맞춤형 LLM을 만드는 방법, 그 중에서 Rag에 대해 소개를 드리고자 합니다.

나만의 LLM을 만드는 방법 - FineTuning & Rag


 맞춤형 LLM을 구축하기 위해선 다양한 방법론들이 있지만, 가장 대표적으로 FineTuningRag가 있습니다.

 

[FineTuning]

 FineTuning은 이미 똑똑한 LLM모델에서, 특정 도메인에 대한 정보들을 추가로 학습시키는 방법입니다. 이를 통해 범용적이었던 LLM이 해당 도메인에 대해 좀 더 전문가가 될 수가 있는 것이죠. 쉽게 이해하자면, 이제 막 의사 자격증을 취득한 똑똑한 일반의가 특정 전공(신경외과, 흉부외과 등)에 특화된 전공의가 되어가는 과정이라고 볼 수 있겠습니다.

 

[Rag]

 Rag(Retrieval-Augmented Generation)는 검색 기능을 통해 답변에 도움이 될 만한 정보들을 데이터베이스에서 찾아 LLM에게 전달하여, 해당 정보에 기반한 답변을 얻어내는 방법입니다. 이 덕분에 모델이 학습한 적이 없는 특정 도메인에 대한 질문도 답변을 잘 해낼 수 있게 되는 것이죠.

 

[FineTuning VS Rag]

 맞춤형 LLM을 위해 FineTuning이 더 나은지, Rag가 더 나은지 명확하게 정의를 내릴 수가 없습니다. 기업 혹은 조직이 다루고 있는 데이터와 상황에 따라 어떤 것이 더 적합한 방법인지 결정을 해야 합니다. 해당 포스팅에는 특정 상황에서 FineTuning과 Rag를 비교분석하기 유용한 내용이 담겨 있습니다.

 다만, 이번 포스팅에서는 FineTuning보다 비교적 구현하기 쉬우며, 매번 갱신되는 데이터를 반영하는데 용이한 Rag에 대해서 좀 더 자세히 살펴보고자 합니다.

Rag의 구조


 Rag의 가장 큰 컨셉은 질문과 관련된 문서를 검색하여, 이를 기반으로 답변을 생성해 내는 것입니다.

이러한 Rag의 구조를 크게 인덱싱과 검색 생성 단계로 구분 지어 볼 수 있습니다.

 

인덱싱

질문과 관련된 문서를 검색하기 위해선 우선 검색될 문서들을 사전에 정리하여 저장해 놓는 과정이 필요할 것입니다. 이를 인덱싱 과정이라 보겠습니다.

 

검색 및 생성

문서들이 인덱싱이 되어 DB에 저장되었다면, 질문에 필요한 문서를 해당 DB에서 검색하고 답변까지 생성해 내는 파이프라인이 필요할 것입니다. 이를 검색 및 생성과정이라고 보겠습니다.

1. 인덱싱 단계

 

[Load]

우선, LLM이 참고할 수 있는 모든 문서들을 텍스트형태로 Load 할 필요가 있습니다. 가령 A은행이 자사의 24시간 구동되는 챗봇 서비스를 만들기 위해 Rag를 도입한다면, 고객들이 물어볼 만한 A은행의 모든 정보들을 Load할 필요가 있겠습니다. 이때, 모든 문서가 굳이 txt파일일 필요는 없습니다. 우리가 많이들 사용하는 pdf나 docs 등 다양한 형태의 문서들을 로드할 수 있습니다.

[Split]

특정 정보가 담긴 문서들은 그 텍스트 길이가 꽤 길 수 있습니다. 우리는 이 긴 문서들을 특정 단위로 쪼갤 필요가 있습니다. 그렇게 함으로써 검색 효율성이 증가되며, 추후 임베딩에서 유용하게 작용될 수 있습니다.

[Embed]

텍스트를 분할한 후, 분할된 조각들을 임베딩 해줍니다. 여기서 임베딩의 역할은, 텍스트 데이터를 벡터라는 데이터로 수치화 함으로써, 텍스트가 가지는 의미적 유사성을 벡터 공간에서 거리로 표현할 수 있도록 해줍니다.

LLM 모델은 숫자만을 인식할 수 있으므로, 텍스트 데이터를 수치화할 필요가 있습니다. 또한, 텍스트의 의미론적 해석이 가능해야 합니다. 이러한 의미 관계를 표현하고자 벡터 공간 속에서 거리로 이를 표현해 주도록 합니다. (가령, 남자라는 벡터와 수컷이라는 벡터는 가까운 거리에 존재할 것)

[Store]

이렇게 Embed 과정을 거쳐 텍스트의 의미 관계가 벡터로 변환이 되었다면, 해당 벡터를 VectorDB에 저장을 해줍니다. VectorDB는 일반 DB와는 달리 의미적 유사성을 바탕으로 검색을 수행할 수 있도록 해줍니다. 이를 통해, 추후 사용자가 특정 질문을 하면, 해당 질문과 의미론적으로 가장 유사한 특정 텍스트들을 검색하여 찾아줄 수 있게 되는 것이죠.

 

2. 검색 및 생성 단계

 

[Question]

사용자가 질문을 하는 단계입니다. 가령 ‘A은행은 목요일에 몇 시에 문을 열며, 점심시간은 언제지?’라고 물어본다고 가정해 보겠습니다.

[Retrieve]

이제 위의 질문 ‘A은행은 목요일에 몇시에 문을 열며, 점심시간은 언제지?’와 의미론적으로 가장 유사한 벡터들을 사전에 구축한 VectorDB로부터 검색을 하게 됩니다. 이 과정에서 질문에 대해 Embed를 진행한 후, 그 결과와 가장 근거리에 있는 벡터 N개를 추출해 내게 되죠.

[Prompt]

그렇게 추출된 N개의 벡터를 기반으로 질문과 함께 새로운 프롬프트를 구성하여 LLM에게 던져주게 됩니다. 이는 질문과 더불어 질문과 관련되어 있는 문서들을 함께 LLM에게 전달하는 꼴이 되며, 이를 기반으로 답변을 생성해 달라는 의미를 가지게 됩니다.

[LLM]

LLM은 제공받은 프롬프트를 기반으로 답변을 생성해 내게 됩니다. 만약 A은행이 Rag를 구현할 때 vectorDB에 적합한 문서들을 잘 임베딩하여 넣었다면, A은행의 정확한 업무시간을 답해낼 수 있게 되겠죠.

 

 

 이러한 구조를 가진 Rag는 그 특성 덕분에, 답변에 대한 근거로 어떠한 문서를 참고했는지 알려줄 수 있습니다. 또한, 새로 추가된 데이터를 손쉽게 VectorDB에 추가할 수 있기 때문에, 변동성이 많은 데이터에 대해서도 답변을 생성해 낼 수 있게 되죠. 무엇보다, FineTuning과 달리 LLM모델을 추가로 학습시킬 비용과 시간이 들지 않는다는 큰 장점이 있습니다.

 

Reference

https://teddylee777.github.io/langchain/rag-tutorial/#인덱싱

https://python.langchain.com/docs/use_cases/question_answering/

https://www.skelterlabs.com/blog/rag-vs-finetuning

https://brunch.co.kr/@delight412/620