프로젝트 내용
기간 : 24.10.02~24.10.24
구분 : 팀프로젝트(5명)
역할 : 조장 / EDA, Advanced RAG 적용한 Chabot 구현
내용 : Documnets들과 sigle turn과 multi turn 형태의 과학질의 데이터가 주어집니다. 해당 대화가 과학 질의라면 RAG를 활용하여 답변을 생성하고 과학 질의가 아니라면 답변을 회피합니다.
평가 방법 : 질의에 따라 문서 순위(Ground Truth)가 있습니다. 평가는 질의에 가장 유사 문서를 추출해야 합니다. 이를 MAP와 MRR 지표를 활용해서 평가합니다.
적용 기술 : Advanced RAG(Query Transfer, Fusion, LLM-Reranker), LangChain, Streamlit, google extention
EDA : Chunk가 잘 나누어 졌을까?
우리가 chunk를 나누는 이유는 하나의 document에 여러 내용이 담겨 있는 것(=정보의 혼재)을 방지하기 위해서 이다. 여러 내용이 담겨 있으면 질의에대한 필요한 내용 외의 부분까지 포함된 채로 prompt를 작성해야한다. 이러면 응답하는 인공지능이 다른 내용까지 읽고 응답을 생성하기에 응답 품질에 영향을 줄 수 있습니다.
따라서 좋은 RAG시스템을 구축하기 위해서는 질 좋은 Chunk 집합이 필요하다. 이를 해결하기 위해서 정량적 평가 3가지 측면에서 Chunk를 분석했습니다. 또한 정성적 평가 또한 함께 진행했습니다.
1. 토큰 수 분석
서로 비슷한 길의 Chunk로 나눠지는 것이 좋다. 특히, 길이가 긴 Chunk는 정보의 혼재가 있을 가능성을 높인다. 주어진 데이터를 분석 결과 아래와 같습니다.

평균적으로 짧은 텍스트로 이루어져 있다. 즉 주어진 데이터가 추가적인 Chunk로 나누지 않아도 충분히 적절한 Chunk로 나눠져 있다고 보여집니다.
2. 문장 유사도 분석
토큰 수 분석 만으로 chunk가 의미적으로 정보의 혼재가 없음을 판단하기 어렵습니다. 문장 유사도 분석은 문서를 문장 단위로 나눈 후 모든 문장 쌍의 유사도를 측정해서 평균을 나눈 값을 측정합니다. 해당 값이 1에 가까울 수록 의미적으로 유사한 문장들로 구성된 문서라고 판단할 수 있는 것입니다. 대회에서 주어진 데이터를 문장 유사도 분석을 하면 아래와 같습니다.

문장 유사도 검사 결과를 보면 평균이 0.6이상으로 대부분 높은 유사도를 가지고 있습니다. 이를 보았을 때도 Chunk가 이미 잘 나눠져 있다고 판단할 수 있습니다.
3. 토픽 일관성 검사
문서가 얼마나 일관적인 주제로 내용이 구성되어있는지를 판단하기위해서 LDA 토픽모델리을 사용했습니다. LDA 토픽 모델링을 사용하면 문서의 토픽의 혼재 비율을 알려주고 해당 비율값을 이용해서 토픽 엔트로피(=주제 무질서도)를 측정할 수 있습니다.

주어진 데이터의 토픽 일관성 검사 결과는 아래와 같습니다.

전체적으로 낮은 엔트로피를 구성하고 있는것을 확인 할 수 있습니다. 이를 통해 이미 적절한 Chunk로 나눠져 있음을 알 수 있습니다.
4. 정성평가
정성 평가는 단순하게 데이터를 직접 읽어보고 판단하는 과정입니다. 총 4200개의 데이터를 모두 직접 읽기에는 너무 피곤한 작업이기에 100개의 데이터를 무작위 샘플링하여 정성평가 하도록 진행 하였습니다. 작업 결과 문서는 하나의 공토된 주제에 대해서 서술된 깔끔한 데이터 였지만 두가지 문제점을 확인 할 수 있었습니다.
첫 번째, 번역체로 서술된 문서들. 원본 데이터가 영어였는데 해당 데이터를 기계번역을 통해 한국어 데이터를 만든 것이라 어색한 번역체가 남아있었습니다.
두 번째, 과학적 논리가 맞지 않은 문서들 존재. 말 그대로 논리에 맞지 않는 과학 문서가 존재하였습니다. 예시로 아래 글과 같은 데이터들이 존재했습니다.
이러한 점들에 유의해서 RAG시스템을 구축했습니다.
RAG시스템 구축
RAG 시스템 초기 구조
1. 입력으로 들어오는 query는 Single hop 형태일 수도 있고 Multi hop 형태일 수도 있습니다. Multi hop의 경우 적절한 Instruction과 함께 Prompt에 넣어 GPT-4o에게 전달합니다. 이후 GPT-4o가 단순한 query(standalone query)를 생성합니다.
2. 다시 GPT-4o에 해당 데이터를 Instruction과 함께 넣어 과학적 질문 유무를 판단합니다.
3-1. 과학적 질문일 경우, query를 검색에 용의한 query로 변경하여 RAG system에 전달하여 query와 연관된 5개의 관련 문서를 반환 받습니다.
3-2. 과학적 질문이 아닐 경우, GPT-4o를 사용하여 답변을 생성하고 과정을 끝냅니다.
4. 5개의 관련 문서를 다시 GPT-4o에 전달하여 논리적으로 오류가 없는지 검증하여 검증된 문서들만 GPT-4o에 전달하여 답변을 생성하고 과정을 끝냅니다.
1. 검색에 용이한 query를 Faiss란 임베딩 DB를 통해 임베딩 된 문서들 중 cosine 유사도가 가장 높은 200개 문서를 반환 받습니다.
- Faiss를 통해 KNN검색을 합니다(ANN보다 KNN이 검색의 질은 높지만 검색 속도가 느립니다. 그러나 해당 대회에서는 데이터 량이 적으므로 KNN이 유리할 것이라 생각했습니다.)
- Embedding은 한국어 검색에서 가장 성능이 높다고 평가되는 Solar Embedding을 사용하였습니다.
2. 200개의 문서는 cross-encoder기반이며 한국어로 fine tuning된 검색 모델인 'Dongjin-kr/ko-reranker'를 사용하여 5개의 관련 문서를 반환 받았습니다.
MAP와 MRR이 Base모델과 비교하면 MAP는 0.0834, MRR은 0.0803의 상승이 있었습니다.
정성적 평가 결과 대부분의 데이터들이 옳게 매칭되고 있었으나 과학적 질문을 하였음에도 불구하고 관련된 문서가 없다는 결과를 받거나 질문과 연관은 되어 있으나 대답을 생성하기에 정보가 부족한 문서들과 매칭되어 있는 query들이 있었습니다.
논리적 문서 판단 부분 제거 & Fusion적용
초기 RAG시스템의 모델 성능 결과 소폭의 성능 향상은 있었으나 기대한 성능향상에 미치지 못하는 아쉬운 결과 였습니다. 이러한 결과의 원인으로 논리적 오류 문서를 체크하는 부분을 꼬집었습니다. 리더보드의 Ground Trouth자체가 문서에 논리적 오류가 있던 말던 query에 관련만 있으면 연관된 문서라고 설정했을 가능성 높다고 생각했습니다. 이는 정성적 평가를 통해 과학 지식 질문임에도 관련 문서가 없다는 결과를 가진 데이터를 보며 확신을 가질 수 있었습니다. 따라서 논리적 오류 문서를 체크하는 부분을 제거하였습니다.
또한 너무 간단한 RAG 시스템 구조 또한 성능을 크게 올리지 못한 것에 기여하였다고 생각합니다. 특히, Faiss를 통한 dense 방식의 유사도 측정은 sementic한 정보의 유사도를 측저하는 것에는 좋으나 광범위한 일반 지식 영역이 아닌 특정 도메인에 대한 정보 검색 일수록 sparse한 방식이 효과적이라는 연구 결과도 있었습니다. 따라서 elastic search를 활용하여 BM25기반 역색인 방식의 검색 방식 또한 사용하였습니다. 각각의 방식으로 200개 씩의 문서를 검색해 오고 중복을 뺀 400개이하의 문서를 reranker에 전달하여 cross-encoder기반의 점수를 부여받습니다. dense방식의 cosine 유사도 점수기반 200개 문서, sparse방식의 BM25 점수 기반 200개 문서, reranker점수 기반 400개 이하문서들 각각을 z-정규화를 취한 후 아래 공식을 사용하여 최종 점수를 환산하여 3개의 문서를 도출 했습니다.
fusion score = (dense score * 0.7 + spares score * 0.3) * 0.525 + reranker score * 0.475
각 스코어에 곱해진 상수는 여러번의 실험을 통해 얻어진 하이퍼파라미터이다.
그 결과 MAP는 0.7879에서 0.9015로 약 0.1136 향상 하였고 MRR은 0.7894에서 0.9030으로 약 0.1136 향상된 결과를 얻을수 있었습니다.
LLM Re-Ranker
Fusion RAG의 ouput결과들을 살펴보면 대부분 상위 15개 문서 안에 정답 문서들이 존재했습니다. 하지만 가장 관련도 높은 문서가 1위에 위치한 것들이 적었습니다. 이를 해결하고자 LLM re-ranker 방식을 사용했습니다.
Fusion의 15개 문서 output 중에 1등 문서 유사도의 10%보다 유사도가 작은 문서가 존재한다면 그러한 문서는 Fusion에서 이미 query와 너무 연관 없다고 판별된 문서라 여기고 제외했습니다. 그러한 것들을 제외한 15개 이하의 문서를 GPT-4o에 instruction과 함께 전달합니다. 그 결과 query와 가장 유사한 문서라고 판단되는 문서 3개를 반환 받습니다.
그 결과 MAP 지표에서 0.9015에서 0.9288로 약 0.0273 상승하였고 MRR 지표에서 0.9030에서 0.9333으로 약 0.0303 상승하였습니다. 정성평가에서도 적절한 연관 문서를 찾고, 만족 할 만한 답변들을 생성하였습니다.
RAW Query
데이터를 분석해보면 주어진 query의 형태가 single hop인지 muti hop인지의 차이는 있지만 모든 query들이 단순하고 간단 명료한 형태로 질문을 하고 있었습니다. 따라서 검색에 용의하게 바꾸는 과정이 오히려 노이즈를 생성하는 과정일 수도 있겠다는 생각이 들었습니다.
따라서 과학적 질문 인지를 판별하는 GPT-4o의 프롬프트에서 검색에 용이한 tranformed query로 변환하는 Instruction부분을 제거하였습니다. 이로 인해 RAG system에 원본 데이터 형태를 유지한채 입력으로 들어가게 됩니다.
그 결과 MAP 지표에서 약 0.027 상승했고 MRR 지표에서 0.0258의 상승이 있었습니다.
Chat Bot 서비스
대회에서 구축한 RAG시스템을 활용하여 과학 질의에 응답하는 Chat bot을 구현해 보았습니다. Chatbot에는 이전 대화와 관련된 질의나 이전 대화에 이어서 하는 질의들을 사용자가 보낼 수 있습니다. 이러한 경우 이전 대화를 참고하여 답변을 생성하여야 합니다. 이를 해결하기 위한 간단한 방법으로 이전 대화의 내용을 프롬프트에 담아 현재 사용자의 입력과 함께 보내는 방법이 있습니다. 하지만 이러한 방법을 사용한다면 대화가 길어질 수록 프롬프트가 길어지고 이어서 성능 악화와 비용문제가 발생 할 것입니다. 이를 해결하고자 아래와 같은 시스템을 제안하였습니다.
history manger라는 시스템을 만들었습니다. 이 또한 RAG를 기반 시스템으로, query와 관련도가 높은 이전 대화를 검색하는 역할을 합니다. 자세한 history manager의 구조는 아래와 같습니다.
단기기억 공간(recent_data)과 장기기억 공간(summary_data)으로 나누어 이전의 대화를 저장합니다. 단기 기억공간에 5개의 대화가 찼을 경우 가장 오래된 대화를 요약하여 장기 기억 공간에 저장합니다. 검색 과정에서는 단기 기억 공간에서는 최근 대화 두개를 가져오고 장기기억 공간에서는 pinecone을 통해 dense기반 cosine 유사도 측정을 통하여 가장 유사한 요약 대화 2개를 가져와 반환합니다. 반환된 대화들은 프롬프트에 넣어 현재 사용자의 query와 함께 담겨 GPT-4o에 전달합니다.
이러한 과정을 쉽게 Lanchain을 통해 구현 할 수 있습니다. 그러나 Lanchain을 이용해 구현한 결과 정말 간단한 코드로 정말 빠르게는 구현이 되지만 우리가 원하는 기능들을 넣기에는 불편함이 있다는 것을 느꼈습니다. 기능면에서는 ReAct Agent의 기능이 대단하였다고 느꼈지만 그 또한 GPT API를 통해 해결 할 수 있겠다는 생각이 들었습니다.
Google Extention
두 번째로 개발한 것은 Tavily라는 실시간 웹브라우저 검색 API를 활용한 실시간 브라우저 질문 응답 AI를 구축했습니다. 브라우저 서칭 중 Chat GPT에게 물어보고 싶은 부분이 생기면 해당 부분을 복사-붙여넣기 해서 프롬프트를 만들어야 하는 번거로움이 있었습니다. 이러한 문제를 해결하고자 동영상과 같이 브라우저에서 드래그만하면 바로 GPT에게 물어볼 수 있는 서비스를 구현해 보았습니다.
해당 프로젝트에서 가장 큰 문제점이 서버 리소스의 한계 였습니다. 실제로 AI 모델을 서버에 올려 배포하는 것을 배워보고 싶었었습니다.
그러나 모델이 서버에서 작동하기 위해서는 최소한의 GPU 리소스가 있는 서버를 빌려야 했습니다. 그러나 그런 컴퓨팅 파워를 가진 것들은 너무 비싸다는 문제가 있었습니다. 이를 해결하기 위해서 최대한 API를 사용하여 모델을 서버에서 작동 될 필요 없게 구현을 해보았습니다.
대회 결과
최종 MAP 지표 0.9136점, MRR 지표 0.9167점을 기록하며 2위로 대회를 마무리 하였습니다.
public에 비해서 큰 폭으로 점수가 하락한 것을 확인 할 수 있습니다. 이러한 원인으로 세가지를 꼽았습니다.
첫 번째로, Fusion에서 상수값을 여러번의 실험에 의해 public 점수가 가장 잘 나오는 것을 fitting한 것이라 이 부분에서 오버피팅이 발생했을 것이라고 추측합니다.
두 번째로, LLM reranker의 과적합 입니다. LLM reranker를 적용하지 않은 모델이 MAP지표 0.9258과 MRR 지표 0.9288로 성능이 더 좋은 것을 확인했습니다. 이러한 결과를 보아 LLM reranker가 오히려 과적합을 일으키는데 영향을 미쳤다고 여겨집니다.
마지막 세번째로 테스터 데이터의 질 입니다. 번역체로 되어있고 논리적인지 않은 글로 구성된 문서들이 있었습니다. 이러한 데이터들이 노이즈를 일으켜 오버피팅이 일어났다고 추측합니다.
아쉽게 1등자리를 빼앗겨 버렸지만 실제 현장에서 많이 원하고 있는 RAG를 깊이 다루어 볼 수 있었던 좋은 대회였습니다.
'프로젝트 기록' 카테고리의 다른 글
| [RAG] Chunk 품질 평가 방법 (4) | 2024.12.23 |
|---|