Upstage AI Lab 대회 회고: [IR] Scientific Knowledge Question Answering

0. 발표자료: Link

 

#5_IR_Competetion_과학 지식 질의 응답 시스템 구축_3조

Information Retrieval IR 3조

docs.google.com

 

1. 대회 개요 : Competition Overview


■ Goal of the Competition

질문과 대화 히스토리로 참고할 문서를 검색엔진에서 추출 후 이를 활용하여 질문에 적합한 대답을 생성하는 Task

■ Timeline

April 22th, 2024 - Start Date

May 2nd, 2024 - Final submission deadline

■ Environment

GPU 환경

  • VSCode와 SSH 원격 연결
  • NVIDIA RTX3060 | 24GB (실패)
  • NVIDIA-RTX-A5000 | 24GB (실제 사용)

협업툴: Github, Slack, Zoom

■ Dataset

- 대회 데이터셋 License

- 학습데이터(document.jsonl)

모델 학습을 위한 학습데이터가 아닌, 과학 상식 정보를 담고 있는 순수 색인 대상 문서 4272여 개

  • 'doc_id' : 문서별 id(uuid)
  • 'src' : 출처
  • 데이터를 Open Ko LLM Leaderboard에 들어가는 Ko-H4 데이터 중 MMLU, ARC 데이터를 기반으로 생성했기 때문에 출처도 두 가지 카테고리를 가짐
  • 'content' : 실제 RAG에서 참고하게 될 지식 문서 정보

파일 포맷: 각 line이 json인 jsonl 파일

{"docid": "42508ee0-c543-4338-878e-d98c6babee66", "src": "ko_mmlu__nutrition__test", "content": "건강한 사람이 에너지 균형을 평형 상태로 유지하는 것은 중요합니다. 에너지 균형은 에너지 섭취와 에너지 소비의 수학적 동등성을 의미합니다. 일반적으로 건강한 사람은 1-2주의 기간 동안 에너지 균형을 달성합니다. 이 기간 동안에는 올바른 식단과 적절한 운동을 통해 에너지 섭취와 에너지 소비를 조절해야 합니다. 식단은 영양가 있는 식품을 포함하고, 적절한 칼로리를 섭취해야 합니다. 또한, 운동은 에너지 소비를 촉진시키고 근육을 강화시킵니다. 이렇게 에너지 균형을 유지하면 건강을 유지하고 비만이나 영양 실조와 같은 문제를 예방할 수 있습니다. 따라서 건강한 사람은 에너지 균형을 평형 상태로 유지하는 것이 중요하며, 이를 위해 1-2주의 기간 동안 식단과 운동을 조절해야 합니다."}
{"docid": "7a3e9dc2-2572-4954-82b4-1786e9e48f1f", "src": "ko_ai2_arc__ARC_Challenge__test", "content": "산꼭대기에서는 중력이 아주 약간 변합니다. 이는 무게에 영향을 미칩니다. 산꼭대기에서는 무게가 감소할 가능성이 가장 높습니다. 중력은 지구의 질량에 의해 결정되며, 산꼭대기에서는 지구의 질량과의 거리가 더 멀어지기 때문에 중력이 약간 감소합니다. 따라서, 산꼭대기에서는 무게가 더 가볍게 느껴질 수 있습니다."}

 

- 평가데이터(eval.jsonl)

멀티턴 대화 시나리오를 가정하기 때문에 리스트 형태의 사용자와 시스템이 주고받은 메시지 형태

200개 : 과학상식 대화

{"eval_id": 0, "msg": [{"role": "user", "content": "나무의 분류에 대해 조사해 보기 위한 방법은?"}]}
{"eval_id": 1, "msg": [{"role": "user", "content": "각 나라에서의 공교육 지출 현황에 대해 알려줘."}]}
{"eval_id": 3, "msg": [{"role": "user", "content": "통학 버스의 가치에 대해 말해줘."}]}
{"eval_id": 4, "msg": [{"role": "user", "content": "Dmitri Ivanovsky가 누구야?"}]}

20개 : 멀티턴 대화

{"eval_id": 2, "msg": [{"role": "user", "content": "기억 상실증 걸리면 너무 무섭겠다."}, {"role": "assistant", "content": "네 맞습니다."}, {"role": "user", "content": "어떤 원인 때문에 발생하는지 궁금해."}]}

20개 : 일반적인 대화 메시지

{"eval_id": 36, "msg": [{"role": "user", "content": "니가 대답을 잘해줘서 너무 신나!"}]}
  • eval_id : 평가 항목 ID
  • msg : user와 assistant 간 대화 메시지 (리스트)

■ Evaluation_metric

  • RAG에 대한 End-to-End 평가 대신, 적합한 레퍼런스를 얼마나 잘 추출했는지에 대한 평가만 진행
  • Mean Average Precision(MAP)
    • 상위 N개의 관련된 문서에 대해 전부 점수를 반영할 수 있되, 관련된 문서의 위치에 따라 점수에 차등을 줄 수 있는 평가 모델
    • MAP 추가 로직: 과학 상식 질문이 아닌, 즉 검색이 필요 없는 ground truth 항목
      • 검색 결과 없는 경우 : 1점
      • 검색 결과 있는 경우 : 0점
    • 코드
def calc_map(gt, pred):
    sum_average_precision = 0
    for j in pred:
        if gt[j["eval_id"]]:
            hit_count = 0
            sum_precision = 0
            for i,docid in enumerate(j["topk"][:3]):
                if docid in gt[j["eval_id"]]:
                    hit_count += 1
                    sum_precision += hit_count/(i+1)
            average_precision = sum_precision / hit_count if hit_count > 0 else 0
        else:
            average_precision = 0 if j["topk"] else 1
        sum_average_precision += average_precision
    return sum_average_precision/len(pred)

 

2. 대회 목표 : Competition Detailed Goal


■ Learning Objective

  • 공동 학습 목표: Information Retrieval 강의 수강 및 대회 참여를 통한 역량 향상
  • 개인 학습 목표: IR Competitinon 나만의 첫 베이스라인 만들기
    • RAG는 익히 들었지만 정의만 알뿐, 어떻게 구현되고 가능한지는 몰랐다. 이번 강의 및 대회를 통해 RAG의 전신인 Information Retrieval을 이해한다.
    • 모델 학습이 중심이었던 여태 대회와 다르게 임베딩 생성 모델, 검색엔진, LLM 등을 활용하여 레퍼런스를 잘 추출하여 이를 토대로 답변을 잘 생성할 수 있도록 목표한다.

 

3. 모델 구조 요약 : Competition Model


■ Data

  • 일상대화 분류 Prompt Engineering

■ Modeling

  • Retrieval Model
    • Pretrained Language Model + colbert train
    • Hard Negative
  • Reranking: Pretrained Ko-Reranker

■ Result

  • MAP - Final Score :
    • Public LB : 0.8705 / Ranking 3rd
    • Private LB : 0.8462 / Ranking 3th (-)

 

4. 진행 과정 : Competition Process


■ Data

    • 일상대화 분류 Prompt Engineering

우선 본격적인 RAG를 펼치기 전에 LLM에 들어오는 질의가 과학상식을 묻는 건지, 아니면 그 외의 주제를 묻는 건지 판단할 필요가 있었다. 그래야 Reference를 가져올지 말지 정할 수 있으니까!

질의 분류는 LLM으로 진행하며, 어떻게 Prompt를 구성하느냐에 따라 분류 성능이 달라졌다. 강의 실습에서 나온 Prompt도 꽤 괜찮게 보였지만 실습 내에서도 가끔 이상하게 분류하기도 하기도 하여서 Prompt Engineering은 필수였다.

# 실습에서 사용한 Prompt
persona_qa = """
## Role: 과학 상식 전문가

## Instructions
- 사용자의 이전 메시지 정보 및 주어진 Reference 정보를 활용하여 간결하게 답변을 생성한다.
- 주어진 검색 결과 정보로 대답할 수 없는 경우는 정보가 부족해서 답을 할 수 없다고 대답한다.
- 한국어로 답변을 생성한다.
"""

 

공교롭게도 바꾼 Prompt가 정말 질의 분류를 잘하고 있는지 판단하기가 모호했던 게, 데이터는 content 외에 어떤 메타 정보도 없었기 때문이었다. 하지만 때마침 팀원분이 약 200개가량의 질의 데이터를 라벨링 하여서 해당 Prompt로 LLM이 정말 질의를 잘 분류할 수 있는지 판단할 수 있었다. 그리하여 여러시도를 통해 나온 Prompt의 핵심은 다음과 같다.

Tools를 강제하여 Function Calling 하고, 주어진 대화가 지식 추구 담화라면 검색에 사용할 질의를 생성 및 label 값을 1로 설정, 일상 담화라면 label 값이 0으로 설정하여 데이터 라벨링

 

좀 더 설명하자면 과학에도 다양한 분야가 있는데 고등학교 때 배운 물리, 화학, 생명과학, 지구과학 등을 예로 들 수 있다. 우리는 그냥 과학으로 일컬을 수 있지만 모델은 서로 다른 분야로 받아들일 수 있기에 ‘상세 분야’에 대한 정의를 추가함으로써 분류 성능을 높일 수 있었다.

 

하지만 위에서 ‘과학 상세 분야’가 아닌 ‘지식 추구 담화’라고 했는데 이유는 다음과 같다. 데이터셋을 살펴보면 이 대회에서 말하는 과학 지식은 사회과학, 컴퓨터공학, 수학 등등 좀 더 넓은 의미의 과학을 지칭했었기에 이 부분에 대한 상세 분야 정의를 더 추가해야 했다. 그리하여 과학에 한정한 게 아닌 ‘지식 추구 담화’라고 한 것이다.

과학 - 나무위키 (namu.wiki)
과학은 보편적인 진리나 법칙의 발견 목적으로 하는 체계적 지식을 의미한다. 좁은 의미로는 물리학, 생물학, 지구과학, 천문학, 화학을 포괄한 자연과학을 뜻하며, 넓은 의미로는 어떠한 법칙이나 이론 등을 학문과 실험과 같은 지적 탐구활동을 통해 수행하는 모든 학문을 뜻한다.

그리고 이 과정에서 예전에 흥미롭게 기억에 남았던 Prompt Engineering 방법도 적용해보려 했으나 이미 위 방법론만으로 약 99%의 성능이 나왔기도 하고, 적용하려는 방법이 어쨌든 한정된 크래딧에 토큰 사용량을 늘리기에 시도하진 않았다. (그렇다고 또 토큰 사용량이 엄청 늘어나진 않지만…)

 

  • Prompt ‘질문 재읽기' 전략
    • Read the question again이라는 단순한 문장을 추가함으로써 평균 3.81%의 성능 향상된다고 함
    • 관련 논문: https://arxiv.org/pdf/2309.06275
[Re-reading+CoT를 적용한 프롬프트 예시]
Q :
{question}
Read the question again: {question}

A : Let’s think step by step

■ Modeling

  • Retrieval Model (Pretrained Language Model + colbert train)

자연어 처리를 위해서 임베딩은 이제 필수이다. 이 대회의 기본 베이스라인에서는 sentence transformer를 사용하며, 그중에서도 한국어 사전학습 모델인 "snunlp/KR-SBERT-V40K-klueNLI-augSTS”을 썼다. 이 모델을 쭉 사용하다가 의문이 든 점이 외래어 및 외국어 키워드에 대해서는 성능이 다소 떨어진다는 것이었다.

 

이유에 대한 추측은 이렇다. 아까 과학의 넓은 의미를 살펴봤듯이 어떠한 법칙이나 이론 등 체계적 지식을 의미하는 과학은 일반적으로 대부분 영어로 기술되어 있다. 국내에서도 과학 분야에 대한 키워드 같은 경우는 영어 그대로 표기하거나, 발음 나는 대로 표기하거나, 외래어로 표기하거나 하는 방법으로 다뤄지고 있다. 하지만 한국어 사전학습 모델의 경우, 일상적인 한국어 담화로 학습되어 외국어 및 외래어는 잘 반영하지 못하는 것으로 결론 내렸다.

 

처음에는 이것을 어떻게 보완할지 막막하기도 하고 비슷한 단어를 같이 학습해야 하나 싶었는데 멘토링에서도 그렇고 소수를 위한 학습은 비효율적이라는 결론을 내렸다. 그리하여 찾은 방법이 sentence transformer에서 다국어 모델을 찾는 것! 실제로 이것은 효과가 있었는데 아래의 표를 통해 입증할 수 있다.

 

이제 와서 생각해 보면 한국어 사전학습 모델 중에서도 과학에 특화되어 Pre-train 된 모델이 있었을 텐데 이 부분을 찾아보지 못한 게 아쉽다.

  • Reranking: Pretrained Ko-Reranker

이 대회의 Evaluation Metric이 MAP인 것을 보면 알다시피, RAG의 성능 향상을 위해서는 질의와 관련된 문서가 추출된 Reference에 존재할 뿐만 아니라, Reference 내에서 그 순서 또한 상위권에 위치하고 있어야 한다. 이에 대한 해결책으로 쓸 수 있는 게 바로 ‘Rerank’이다.

Rerank는 질문과 문서 사이의 유사도 측정을 목표로 하며, Cross-Encoder의 Self-attention 기법을 통해 이것이 가능하다. 다만 질문 별로 모든 문서에 대한 유사도 측정이 필요하여 시간이 굉장히 굉장히 오래 걸린다는 단점이 있다.

하지만 그래서 시도한 전략이 바로 ‘Two-Stage 전략’, 이렇게 해도 역시 시간이 걸리는 편이긴 하지만 그냥 바로 Rerank를 적용할 때보다 훨씬 시간을 절약할 수 있었다.

  • Two-Stage 전략
    1. 기존의 벡터 검색 방식으로 대규모 문서 중 질문과 관련성이 높을 것 같은 후보군(Top k개) 검색 및 추출
    2. 검색된 문서들(후보군)에 대해 reranker 기반으로 질문-문서 유사도 재측정하여 순서 변경

위와 같은 Two-Stage 전략을 최대한으로 끌어올리기 위해 Top k별로 Rerank 성능 비교를 했고 다음과 같은 비교를 통해 Top 10~15를 가장 적당한 값으로 설정했다.

++ 대회 전 IR 강의에서는 Rerank에 대해 매우 가볍게 언급하고 지나가서 몰랐는데 나~중에 최종 발표 피드백 때 들어보니 실무에서는 효율성이 좀 떨어지지만 대회에서는 성능을 확실히 챙길 수 있는 치트키 같은 존재라 일부러 작게 이야기하고 넘어간 거라고 하셨다.

■ Result

  • MAP - Final Score :
    • Public LB : 0.8705 / Ranking 3rd
    • Private LB : 0.8462 / Ranking 3rd

대회 마감 하루 전만 해도 팀원 김*천 님의 열정 어린 제출물로 압도적인 리더보드 1위를 유지했었다. 그래서 최종 발표 PPT에도 1등을 기정 사실화 하고 자축하는 슬라이드를 준비했었지만 그 슬라이드는 안타깝게도 지워야 했다. 대회 마감 몇 시간 안 남기고 갑자기 뒤에서 치고 나오면 순식간에 3등으로 밀려난 것… 그 이후 shake up을 혹시나 기대했지만 Private LB에서도 3등을 그대로 유지했다.

■ Mentoring

멘토링에서 진행한 모든 질문 중(팀원 상관없이) 인상 깊은 것을 적어봤다.

  • Q1. 좋은 임베딩 방법
    • A1. cohere(임베딩 모델 선두 기업), upstage developers에서 RAG 관련 문서를 통해 방법론 연구 ⇒ research paper, API document parameter
    • 핵심 모델(논문)을 꿰차고 자신이 활용할 것에 대해 잘 알아두기
    • 왜 이 논문이 좋은지 잘 설명할 수 있는 사람이 되기
  • Q2. Validation-set 제작 시도 괜찮은지?
    • A2. 좋음, 이런 기조로 팀원들과 분업하여 다른 학습데이터 활용법을 시도해 볼 것
    • 예) Retrieval 모델을 학습하기 위해선 어떻게든 pair 데이터를 구성하는 것이 유리(Inverse Cloze Task, Question Generation)
  • Q3.. ipynb 파일로 대회 임하는 것에 대한 피드백
    • A3. .ipynb → .py modularize 권장 (모듈화)
  • Q4. 영어 데이터(ex. 목성 trojan) 함께 학습하는 것이 성능 개선에 도움이 될지?
    • A4. 소수의 질문만을 위해 굳이 할 필요가 있을까 하는 의문이 들고 학습 방법론을 찾아보는 것이 나을듯함
  • Q5. 모델링에 집중하려는 시도에 대한 피드백
    • A5. Retrieval 문제인데 왜 RAG 실습을 하게 했는지 고민해 볼 것
  • Q6. 유의미한 점수 및 점수 상승?
    • A6. MAP 스코어 0.85 이상 / 점수 상승 0.1 이상 상승 시 유의미하다고 볼 수 있음
  • Q7. 대회에 대해 효율적인 접근을 위한 피드백
    • A7. 시간을 들이는 거 말고 여기서만 찾을 수 있는 해법을 고민해 볼 것
  • Q8. 임베딩 모델 추천 피드백 (대회 막바지)
    • A8. FlagEmbedding 주시하고 있으며, re-ranking도 포함되어 있음
  • Q9. Llama Index 사용 시 Kernel 자체가 죽음. Indexing을 하는 코드를 돌리면 한 10초 정도 뒤에 바로 터짐
    • A9. 디버깅 breakpoint() 사용, MTEB (Massive Text Embedding Benchmark)에서 리소스 대비 가능한 모델 찾아볼 것

 

5. 자체 평가 의견 : Competition Review


■ Good point

  • 모든 회의 및 멘토링 참석하며 회의록 작성

어떤 팀 프로젝트든 항상 회의록을 도맡았었는데 이번 대회는 특히 이것만큼은 준수하고자 노력했다. 대회 기간 동안 학교 수업, 논문 스터디, 창업 동아리 등 다양한 활동과 병행하며 시간 분배를 하다 보니 대회에 많은 시간을 할애하지 못했기 때문이었다.

그러다 보니 팀원들과 Research 조사 및 실험 속도에서 차이가 발생했지만 꾸준히 회의에 참석하고 내용을 정리하며 흐름을 놓치지 않고자 하였고, 그런 과정을 통해 팀원이 조사하거나 실험한 것을 어렵지 않게 습득하면서 파생 아이디어를 제시하거나 실험을 보조하면서 팀에 기여했다.

비록 절대적인 기여는 충분하지 않을 수 있지만 이외에도 회의록을 정리하며 얻은 통찰을 활용하여 짜임 있는 회의로 업무 효율을 높이면서 팀 내에서 윤활유 같은 역할을 하지 않았나 싶다.

■ Fail point

  • 환경 설정 오류 장기화:

여태 대회를 진행해 오며 이런 일이 없었는데 이번 대회에서 할당한 Upstage 서버를 ssh로 연결하는 과정이 잘 안 되었다. 기존과 똑같은 방법으로 했는데 안되고, 검색을 통해 ssh와 관련된 여러 가지 설정을 고쳤는데도 안 됐다. 결국 포기하고 학교 LLM 프로젝트하며 받은 GPU에 원격 접속하여 GPU 문제는 일단락 됐다.

하지만 더 문제는 Elastic Search였으니,,, 이 모듈을 사용하기 온갖 시도를 벌였으나 결국 비밀번호를 얻지 못해서 사용하지 못했다.(elastic search를 사용하기 위해 mysql처럼 id/pw가 필요했음) 그래서 자포자기 후 실험보다 연구 및 아이디어에 좀 더 집중했었는데 어느 날 새로운 마음으로 모든 디렉토리를 초기화하고 elastic search 구동에 필요한 모든 명령을 한 땀 한 땀 권리자 권한으로 실행했더니 비밀번호도 뜨고 구동도 됐다.(다른 사람들은 관리자 권한 안 해도 그냥 되던데…)

■ Bummer point

  • 좀 더 다양한 기법을 적용해보지 못한 것

팀원들이 LLM 및 RAG에 대해 많은 참고 자료를 가져다주었지만 점수 올리기에 중요해 보이는 것을 우선하고 나머지는 보류해 두었다. 부족한 시간을 커버하는 관점에서는 충분한 시도였을지 몰라도 공부하는 관점에서는 아쉬운 선택이었다. 다음 리스트는 참고 자료 중에서도 좀 더 확인했으면 좋았을 참고 자료들이다.

■ Insights from the competition

  • 수동적인 LLM 활용에서 능동적인 LLM 활용으로:

LLM을 여태 콘솔 혹은 플레이그라운드 상에서 Prompt만 입력하며 활용했었는데, 이번 기회를 통해 좀 더 심화된 Prompt Engineering, Retrieval Modeling, Reranking 등등 여러 가지 접근법을 시도해 보면서 LLM을 보다 더 능동적으로 활용하게 됐다.

그동안 기획만 존재하고 어떻게 구현할지 난감한 아이디어가 있었는데 이것을 실제로 구체화할 수 있겠다는 자신감이 들어 실제로 플로우차트를 그려볼 수 있을 정도의 인사이트가 생겼다.

  • 배*경 강사님의 극찬 피드백

NLP를 원래 하다 오신 분들인지?라는 극찬을 들었다. 막판에 리더보드가 뒤집힌 아쉬움이 컸었는데, 수강생에게 갖는 일반적인 기대보다 많은 시도와 접근 방법을 체계적 해낸 것 같다는 칭찬을 해주셔서 감개무량할 따름이었다.(나중에 안 사실로, 상위 팀 중 하나가 손수 동의어 필터링을 추가작업하여 점수가 잘 나올 수밖에 없었다.)

그리고 reranking을 좀 더 활용할 수 있었는데 왜 제한적으로 사용했는지 물어보셨는데 이에 대해서는 대회에서 주어진 크레디트와 자원 이슈 때문에 Two-stage 전략을 사용했다고 말씀드렸다.