어떤 한국어 임베딩 모델 성능이 가장 좋을까? 직접 벤치마크 해보자.

AutoRAG·2024년 8월 4일
14

Retrieval

목록 보기
5/7
post-thumbnail

AutoRAG는 RAG AutoML 툴로 최적의 RAG 조합을 찾기 위해서 만들어졌지만, 벤치마크를 진행하는 데에도 안성맞춤이다.
그래서 AutoRAG를 사용해서 빠르게 한국어 임베딩 벤치마크를 진행해보자. 정말 코드를 많이 적지 않아도 된다는 것에 놀랄 것이다!

=> 여기서 이 벤치마크의 전체 코드를 확인할 수 있다.

데이터 준비

벤치마크를 진행하기 위해서는 당연히 데이터가 가장 중요하다. 한국어 임베딩 모델 벤치마크이기 때문에 반드시 한국어 데이터를 준비해야 한다.

그래서 한국어 RAG 데이터 중 Allganize에서 제작한 RAG 벤치마크 데이터를 선정했다.
하지만 이 데이터를 곧바로 AutoRAG에 활용할 수는 없다. AutoRAG에 알맞은 형식으로 약간의 전처리를 진행해주어야 한다.

corpus 데이터 제작

먼저, Allganize의 데이터에는 따로 corpus가 공개되어 있지 않다. corpus라 하면, 원본 문서들을 파서를 이용해 모두 텍스트화 시킨 데이터를 의미한다. 따로 corpus가 공개되어 있지는 않지만 원본 문서들의 pdf 제목과 그 링크들은 공개되어 있었다.

그래서 일단 각 pdf들을 모두 다운로드 받았다. 그리고, 네이버 OCR 모델을 사용하여 파싱을 진행하였다. 왜 하필 네이버 OCR 모델을 골랐는지 궁금하다면, OCR 모델을 실험한 포스트를 참고하자!

QA 데이터 제작

이렇게 파싱을 모두 한 뒤에는, AutoRAG 데이터 제작에 중요한 과정 중에 하나인 retrieval gt를 매핑해주어야 한다.
retrieval gt란, 한 질문에 대하여 답변과 관련한 지식이나 정보가 들어있는 단락들을 의미한다. 다르게 말하자면, retrieval이 주어진 질문에 대해 찾아야 하는 정답 단락을들 의미한다.

Allganize 데이터셋에서는 이러한 retrieval gt가 어떤 pdf 문서에 어느 페이지에 정답이 있는지에 대한 라벨링이 되어 있었다. 이를 활용해 아래와 같은 과정을 거치면 retrieval gt를 매핑한 데이터를 완성할 수 있다.

  1. OCR로 pdf 문서를 텍스트화 한다.
  2. pdf 문서의 각 한 페이지씩이 한 chunk가 되며, 각 chunk에 고유한 id를 부여한다.
  3. 각 질문에 정답이 되는 chunk의 id를 retrieval gt로 적어준다.
  4. 각 질문에 고유한 id를 부여하여, qid - 질문 - retrieval gt - 모범 답변 (generation gt)로 이루어진 qa 데이터셋을 완성한다.

데이터 완성!

이렇게 720개의 chunk와 114개의 질의 응답으로 이루어진 데이터셋이 완성되었다.
데이터셋은 여기서 바로 확인해볼 수 있다.

설정 YAML 파일 만들기

우리는 오직 retrieval 성능만 평가할 것이다. (임베딩 모델 벤치마크니깐)
그래서 아래처럼 하나의 Retrieval Node와 vectordb 모듈 만이 필요하다. 대신, top-k와 embedding model 종류를 여러개 적어주자.
또한, 보다 정확한 측정을 위해 지원하는 모든 메트릭을 적어주었다.

node_lines:
- node_line_name: retrieve_node_line
  nodes:
    - node_type: retrieval
      strategy:
        metrics: [retrieval_f1, retrieval_recall, retrieval_precision,
                  retrieval_map, retrieval_mrr, retrieval_ndcg]
      top_k: [1, 3, 5, 10, 50]
      modules:
        - module_type: vectordb
          embedding_model:
          - openai
          - openai_embed_3_small
          - openai_embed_3_large
          - upstage_embed
          - cohere_embed
          - ko-sroberta-multitask # jhgan/ko-sroberta-multitask
          - KoSimCSE-roberta # BM-K/KoSimCSE-roberta
          - paraphrase-multilingual-mpnet-base-v2
          - paraphrase-multilingual-MiniLM-L12-v2
          - multilingual-e5-large-instruct

이렇게 되면 총 10개의 임베딩 모델에 대한 벤치마크를 바로 수행할 수 있다.

custom 임베딩 모델 추가하기

하지만, AutoRAG의 기본 지원 임베딩 모델은 얼마 되지 않는다. 그래서, 해당 YAML 파일을 통해 곧바로 AutoRAG를 실행하면 당연히 오류가 날 것이다.

그래서, main.py와 같은 python 실행 파일을 작성하며 새로운 임베딩 모델들을 추가해 주어야 한다. main.py는 아래와 같이 만들어 볼 수 있다.

import os

import autorag
import click
from autorag.evaluator import Evaluator
from dotenv import load_dotenv
from llama_index.embeddings.cohere import CohereEmbedding
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.embeddings.upstage import UpstageEmbedding

root_path = os.path.dirname(os.path.realpath(__file__))
data_path = os.path.join(root_path, 'data')


@click.command()
@click.option('--config', type=click.Path(exists=True), default=os.path.join(root_path, 'config',
                                                                             'embedding_benchmark.yaml'))
@click.option('--qa_data_path', type=click.Path(exists=True), default=os.path.join(data_path, 'qa_v4.parquet'))
@click.option('--corpus_data_path', type=click.Path(exists=True),
              default=os.path.join(data_path, 'ocr_corpus_v3.parquet'))
@click.option('--project_dir', type=click.Path(exists=False), default=os.path.join(root_path, 'benchmark'))
def main(config, qa_data_path, corpus_data_path, project_dir):
    load_dotenv()
    autorag.embedding_models['ko-sroberta-multitask'] = autorag.LazyInit(HuggingFaceEmbedding,
                                                                         model_name="jhgan/ko-sroberta-multitask")
    autorag.embedding_models['KoSimCSE-roberta'] = autorag.LazyInit(HuggingFaceEmbedding,
                                                                    model_name="BM-K/KoSimCSE-roberta")
    autorag.embedding_models['paraphrase-multilingual-mpnet-base-v2'] = autorag.LazyInit(
        HuggingFaceEmbedding, model_name="sentence-transformers/paraphrase-multilingual-mpnet-base-v2")
    autorag.embedding_models['paraphrase-multilingual-MiniLM-L12-v2'] = autorag.LazyInit(
        HuggingFaceEmbedding, model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2")
    autorag.embedding_models['multilingual-e5-large-instruct'] = autorag.LazyInit(
        HuggingFaceEmbedding, model_name="intfloat/multilingual-e5-large-instruct")
    autorag.embedding_models['upstage_embed'] = autorag.LazyInit(UpstageEmbedding)
    autorag.embedding_models['cohere_embed'] = autorag.LazyInit(CohereEmbedding, model_name="embed-multilingual-v3.0",
                                                                api_key=os.getenv('COHERE_API_KEY'))

    if not os.path.exists(project_dir):
        os.makedirs(project_dir)
    evaluator = Evaluator(qa_data_path, corpus_data_path, project_dir=project_dir)
    evaluator.start_trial(config)


if __name__ == '__main__':
    main()

여기서 주목할 부분은 두가지이다.

autorag.embedding_models['ko-sroberta-multitask'] = autorag.LazyInit(HuggingFaceEmbedding, model_name="jhgan/ko-sroberta-multitask")

먼저 위와 같이, autorag.embedding_models에 직접 새로운 임베딩 모델을 추가해주는 것으로 AutoRAG에서 여러 임베딩 모델을 바로 사용해 볼 수 있다.
꼭 주의할 점은, 그냥 python에서 한 번 실행하면 임베딩 모델이 영구 추가되지 않는다. 반드시 AutoRAG 평가 실행 전에 해당 코드를 실행해야 한다.
그렇기 때문에 위와 같이 Evaluator를 이용한 AutoRAG 실행을 한번에 진행하는 것이다.

evaluator = Evaluator(qa_data_path, corpus_data_path, project_dir=project_dir)
evaluator.start_trial(config)

위 코드는 AutoRAG를 실행시키는 코드이다. cli로 실행하는 것과 똑같은 기능을 한다.

실행하기

실행 환경

이 벤치마크를 실행하기 위해서는 반드시 CUDA gpu가 장착된 컴퓨터를 사용하는 것을 추천한다. 임베딩 모델을 여러 번 작동시켜야 하기 때문이다.
또한, 모델 용량이 클 수 있으므로 20기가 이상의 넉넉한 용량 확보도 필요하다.

환경 변수 설정

OpenAI 임베딩과 Upstage, Cohere 임베딩 모델을 사용하므로 각 업체의 사이트에 접속하여 api 키를 발급받자.
그 이후, 레포지토리의 .env 파일에 각 api 키를 추가하거나 환경변수로 설정해주자.
반드시 api 키를 설정해야 정상적으로 작동한다!!

결과

top-k는 몇 개의 passage를 retrieve 하는지를 의미한다. 만약 top-k가 3이면 3개의 passage 중에서 정답이 얼마나 있는지를 평가하는 것이다.

Top-k 1

Model nameF1RecallPrecisionmAPmRRNDCG
paraphrase-multilingual-mpnet-base-v20.35960.35960.35960.35960.35960.3596
KoSimCSE-roberta0.42980.42980.42980.42980.42980.4298
Cohere embed-multilingual-v3.00.35960.35960.35960.35960.35960.3596
openai ada 0020.47370.47370.47370.47370.47370.4737
multilingual-e5-large-instruct0.46490.46490.46490.46490.46490.4649
Upstage Embedding0.65790.65790.65790.65790.65790.6579
paraphrase-multilingual-MiniLM-L12-v20.29820.29820.29820.29820.29820.2982
openai_embed_3_small0.54390.54390.54390.54390.54390.5439
ko-sroberta-multitask0.42110.42110.42110.42110.42110.4211
openai_embed_3_large0.60530.60530.60530.60530.60530.6053

top-k가 1이기 때문에 모든 지표들의 점수가 각각 같다.
업스테이지 임베딩 모델이 가장 높은 성능을 보여주었다!

Top-k 3

Model nameF1RecallPrecisionmAPmRRNDCG
paraphrase-multilingual-mpnet-base-v20.23680.47370.15790.20320.20320.2712
KoSimCSE-roberta0.30260.60530.20180.26610.26610.3515
Cohere embed-multilingual-v3.00.28510.57020.19010.25150.25150.3321
openai ada 0020.35530.71050.23680.32020.32020.4186
multilingual-e5-large-instruct0.33330.66670.22220.29090.29090.3856
Upstage Embedding0.42110.84210.28070.35090.35090.4743
paraphrase-multilingual-MiniLM-L12-v20.20610.41230.13740.17400.17400.2340
openai_embed_3_small0.36400.72810.24270.30260.30260.4097
ko-sroberta-multitask0.29390.58770.19590.25000.25000.3351
openai_embed_3_large0.39470.78950.26320.33480.33480.4491

top-k가 3개일때에도 upstage 임베딩이 모든 지표에서 가장 높은 결과를 보여주었다.

Top-k 5

Model nameF1RecallPrecisionmAPmRRNDCG
paraphrase-multilingual-mpnet-base-v20.18130.54390.10880.15750.15750.2491
KoSimCSE-roberta0.21640.64910.12980.17510.17510.2873
Cohere embed-multilingual-v3.00.20760.62280.12460.16400.16400.2731
openai ada 0020.26020.78070.15610.21390.21390.3486
multilingual-e5-large-instruct0.25440.76320.15260.21940.21940.3487
Upstage Embedding0.29820.89470.17890.22370.22370.3822
paraphrase-multilingual-MiniLM-L12-v20.16370.49120.09820.14370.14370.2264
openai_embed_3_small0.26900.80700.16140.21480.21480.3553
ko-sroberta-multitask0.21640.64910.12980.16970.16970.2835
openai_embed_3_large0.28070.84210.16840.20880.20880.3586

top-k가 5개일때 역시 upstage 임베딩이 모든 지표에서 가장 높은 결과를 보여주었다.

Top-k 10

Model nameF1RecallPrecisionmAPmRRNDCG
paraphrase-multilingual-mpnet-base-v20.12120.66670.06670.11970.11970.2382
KoSimCSE-roberta0.13240.72810.07280.10800.10800.2411
Cohere embed-multilingual-v3.00.13240.72810.07280.11500.11500.2473
openai ada 0020.15630.85960.08600.10510.10510.2673
multilingual-e5-large-instruct0.14830.81580.08160.09800.09800.2520
Upstage Embedding0.17070.93860.09390.10780.10780.2848
paraphrase-multilingual-MiniLM-L12-v20.10530.57890.05790.09610.09610.2006
openai_embed_3_small0.15470.85090.08510.09840.09840.2593
ko-sroberta-multitask0.12760.70180.07020.09860.09860.2275
openai_embed_3_large0.16430.90350.09040.11800.11800.2855

top-k가 10개일때는 f1, recall, precision과 같이 랭킹과 관련없는 메트릭에서 Upstage 임베딩 모델이 가장 높은 성능을 보여주었다.
반면, mAP(mRR)에서는 mpnet-base-v2 모델이, NDCG 모델에서는 OpenAI의 embed 3 large 임베딩 모델이 가장 높은 성능을 보였다.

Upstage 임베딩의 경우 고순위(5순위 안)로 정답이 나오지 않은 경우, 다른 모델에 비해 좀 더 낮은 순위에서 정답 passage가 등장하는 모양이다.

Top-k 50

Model nameF1RecallPrecisionmAPmRRNDCG
paraphrase-multilingual-mpnet-base-v20.03200.81580.01630.02330.02330.1529
KoSimCSE-roberta0.03680.93860.01880.02700.02700.1758
Cohere embed-multilingual-v3.00.03820.97370.01950.02200.02200.1763
openai ada 0020.03750.95610.01910.02950.02950.1789
multilingual-e5-large-instruct0.03780.96490.01930.02950.02950.1804
Upstage Embedding0.03921.00000.02000.02060.02060.1776
paraphrase-multilingual-MiniLM-L12-v20.03130.79820.01600.02180.02180.1503
openai_embed_3_small0.03820.97370.01950.02020.02020.1731
ko-sroberta-multitask0.03540.90350.01810.02450.02450.1691
openai_embed_3_large0.03820.97370.01950.02100.02100.1741

top-k를 훨씬 큰 폭으로 넓힌 50개의 경우, 업스테이지 임베딩이 무려 Recall 1.0이라는 성능을 보여주었다. 모든 질문에 있어서 정답이 50개 안에 들어있는 것이다. 아주 대단하다.

다만, mAP와 NDCG는 다른 오픈소스 모델이 조금 더 높았다. 이는 역시 특정 단락의 경우 다른 모델에 비해 저순위에 배치되는 경우가 있는 것으로 보인다.

이 데이터셋에 대해서는, Upstage Embedding으로 50개 정도의 많은 양을 retrieve하고, 다른 임베딩 모델 혹은 리랭커 모델을 이용해 리랭킹을 진행하는 것도 좋은 전략으로 보여진다.

결론

Upstage 임베딩의 성능이 매우 괜찮았다! top-k가 1개일 때부터 50개일 때까지 모두 준수한 성능을 보여주며, 한국어에 있어서는 꽤나 좋은 임베딩 모델이라는 생각이 들었다.

또한, 이런 벤치마크를 할 때에 YAML 파일 작성과 데이터 전처리를 제외하면 코드를 거의 작성하지 않았다. (사소한 전처리, YAML 파일, main.py가 끝!)
AutoRAG를 내가 만들었지만 참 편하다^^

AutoRAG를 사용해보고 싶다면 이 벨로그 계정에 여러 포스트가 있다. 또한, 테디노트 유튜브에서 AutoRAG 관련 간단한 강의도 볼 수 있다. 그리고 꼭! 공식 docs를 참고하자.

마지막으로 도움이 되었다면 AutoRAG에 스타 한 번씩 꼭 부탁드린다^^

profile
RAG AutoML tool - AutoRAG

1개의 댓글

comment-user-thumbnail
어제

openai 이게 text-embedding-ada-002 를 말하는것인가요?

답글 달기