RAG(Retrieval Augmented Generation)

RAG팀을 이끌고 있는 패트릭 루이스(Patrick Lewis)는 2020년 한 논문 ‘지식 집약적 NLP 작업을 위한 검색 증강 생성(Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks-다운)’에서 RAG라는 용어를 처음 만듦

  • 정리 잘되어있음

Retrieval-Augmented Generation for Large Language Models: A Survey

  • RAG란?

RAG는 외부 소스에서 가져온 정보로 생성 AI 모델의 정확성과 신뢰성을 향상시키는 기술이다.

-> LLM의 작동 방식에서 부족한 부분을 채워주는 기술 (할루시네이션 감소등의 역할을 함)

즉, 검색 모델과 생성 모델의 장점을 결합한 기술

RAG의 실패 문제 원인

RAG 검색을 통힌 LLM 생성 시 생길 수 있는 문제

RAG는 이 중 1번 전부, 2번의 4번

  1. Retrieval problems

    1. 의미적 모호성
    2. Magnitude vs. Direction(크기 방향)
    코사인 유사도를 사용함으로 크기를 고려하지 않아 유사한 데이터로 추출될 수 있음
    3. Granularity Mismatch (세분성 불일치)
    쿼리 벡터는 특정 개념을 나타낼 수 있지만 
    데이터 세트에서 넓은 주제만 있는 경우, 
    4. Vector Space Density
    고차원에서의 벡터공간의 밀도가 높아 겉보기에 관련이 없어 보이는 결과가 관련성 있는 것으로 나올 수 있음 
    -> 이부분은 벡터 스케일에 따른 적용이 필요할듯
    5. Global vs. Local Similarities
    대부분 벡터 검색 메커니즘은 전역 유사성을 식별함 
    6. Sparse Retrieval Challenges
    필요한 정보가 여러 문서에 분산되어있는 경우 
    
  2. Augmentation Problems (증강문제)

    1. Integration of Context(맥락 통합)
    이전 검색 히스토리에 너무 의존하는 경우 문제가 생길 수 있음 
    예시) python의 역사 -(검색 후)> python의 응용프로그램
    이전 검색인 python의 역사를 기반으로 검색
    2. Redundancy and Repetition
    검색 구절에 유사한 정보가 포함되어 있는 경우 생성 단계에서 반복적인 컨텐츠가 생성될 수 있음
    3. Ranking and Priority (순위 및 우선순위)
    4. Mismatched Styles or Tones(일치하지 않는 스타일 어조)
    검색 대상에서는 여러가지 어조나 스타일을 가지고 있어 스타일 사이를 오가며 응집력이 떨어질 수 있음
    5. Over-reliance on Retrieved Content (검색 컨텐츠의 과한 의존)
    생성 모델이 증강된 정보에 너무 많이 의존하여 가치를 추가하거나 종합을 제공하는 대신 검색된 콘텐츠를 앵무새처럼 표현하는 출력
    
  3. Generation problems

    1. Coherence and Consistency(일관성)
    생성된 출력이 논리적으로 일관되고 일관된 설명을 유지하는지 확인
    2. Verbose or Redundant Outputs (장황하거나 중복된 설명)
    3. Over-generalization(과도한 일반화)
    4. Lack of Depth or Insight(깊이 또는 통찰력 부족)
    5. Stylistic Inconsistencies(문제 불일치)
    6. Failure to Address Contradictions(모순해결 실패)
    7. 
    

RAG의 작동 방식

run

RAG 모델 정확도 향상 방법

Data

1. Text Clearning
특수문자 제거 등 관련 없는 정보를 제거 
2. Entity Resolution
용어를 일반적으로 변경
ex) NER, 개체명인식, 객체인식
3. Data Deduplication
중복 문서나 중복 정보를 제거하여 검색자의 집중력과 효율성을 향상
4. Document Segmentation
긴 문서를 관리 가능한 덩어리로 나누거나 반대로 작은 조각을 일관된 문서로 결합하여 검색기 성능을 최적화
5. Domain-Specific Annotations
도메인별 태그 또는 메타데이터로 문서에 주석을 답니다. 예를 들어, 클라우드 기술에 초점을 맞추면 "AWS", "Azure" 등과 같은 클라우드 관련 기술에 태그를 지정
6. Data Augmentation
동의어, 의역, 심지어 다른 언어와의 번역을 사용하여 말뭉치의 다양성을 높임
7. Hierarchy & Relationships (계층, 관계)
문서 간의 부모-자식 또는 형제 관계를 식별하여 상황에 따른 이해를 향상
8. User Feedback Loop
실제 상호 작용을 기반으로 한 새로운 Q&A 쌍으로 데이터베이스를 지속적으로 업데이트
-> 결국 수동작업 필요
9. Time-Sensitive Data
자주 업데이트되는 주제의 경우 오래된 문서를 무효화하거나 업데이트하는 메커니즘을 구현

Embeddings

	- fine-tuning embeddings (with fine-tunable/trainable embeddings)
fine-tuning을 통한 임베딩 진행 
ex) LlamaIndex를 통해 훈련 세트를 생성할 수 있다고 함 -> 찾아보기

일반적으로 지표가 5~10% 향상될 수 있다고 함 
(https://www.mattambrogi.com/posts/chunk-size-matters/ )
(https://betterprogramming.pub/fine-tuning-your-embedding-model-to-maximize-relevance-retrieval-in-rag-pipeline-2ea3fa231149)
	
	- Dynamic embeddings (with fine-tunable/trainable embeddings)
단일 벡터로 각 단어를 나타내는 정적 임베딩과 달리 동적 임베딩은 단어가 나타나는 컨텍스트에 따라 조정
ex) 임베딩 중 토큰길이가 5개 이하의 경우 다른 토큰들이 높은 유사도를 보이는 경우가 있음 
단어가 나타내는 컨텍스트에 따라 조정하는 방법

	- Refresh embeddings (with fine-tunable/trainable embeddings)
코퍼스에서 진화하는 의미를 포착하기 위해 임베딩을 주기적으로 새로 고쳐야함

Retrieval

	 - Tune your chunking
검색 정확도를 높이기 위해 더 작은 청크를 사용하며 요약 임베딩 및 가상 질문을 사용하는 Langchain의 다중 벡터 검색 방법을 적용해야함 
LlamaIndex Response Evaluation 같은 평가 프레임워크를 이용해서 최적의 청크 사이즈를 결정해야함
(날짜와 같은 메타데이터를 청크에 포함해야 함)

일반적으로는 청크 크기가 작을수록 정확도가 향상됨  -> but 문맥을 이해 못함 
일반적인 청크 사이즈 찾을때
작은 사이즈(짧은 메시지, 문자)는 128 or 256에서 최적화 
큰 사이즈는 512 or 1025에서 찾기 시작

query routing over multiple indexes -> 서로 다른 인덱스를 갖고 동시에 쿼리 -> 특정 키워드 날짜 같은 메타데이터를 기반으로 함 
  • 문서당 여러 벡터를 만들어 다중 벡터 검색을 하는 방법
1. 작은 chunk size : 문서를 더 작은 청크로 분할하고 이를 더 긴청크와 함께 사용
2. summary embeddings 추가 : 문서에 요약을 생성하고 이를 문서와 함께(혹은 대신) 사용
3. Hypothetical questions: 각 문서에 답변하기에 가장 적합한 가상 질문을 만들고 이를 문서와 함께(혹은 대신) 삽입.
4. Explore hybrid search : 키워드 기반 검색, 의미 체계 검색, 벡터 검색과 같은 기술을 지능적으로 혼합
5. Recursive retrieval & query engine : AG 시스템에서 검색을 최적화하는 또 다른 강력한 접근 방식 중 하나. 핵심 의미를 포착하기 위해 더 작은 문서 청크를 가져오는 작업이 포함됨 
  • 재귀 검색과 스마트 쿼리 엔진 결합
1. HyDE(Precise Zero-Shot Dense Retrieval without Relevance Labels)
쿼리를 받아 가상의 응답을 생성한 다음 임베딩 조회에 두 가지를 모두 사용
-> 성능이 많이 향상된다고 함
2. Read Retrieve Read
누락된 정보에 대한 질문을 반복적으로 평가하고 모든 정보가 사용 가능해지면 응답
3. Parent Document Retriever
의미론적 의미를 더 잘 포착하기 위해 검색 중에 작은 청크를 가져오고, LLM에 더 많은 컨텍스트가 포함된 더 큰 청크를 제공
4. Vector Search
색할 이웃 수, 사용된 거리 측정법과 같은 요소

4. Synthesis

1. Query transformation
복잡한 질문을 여러 질문으로 분할 (복잡한 질문을 나눠서 하는경우 성능이 향상상된다고 함)
 쿼리가 여러 질문으로 분해되도록 RAG 시스템에 이를 구축
2. Engineer your base prompt
프롬프트 엔지니어링은 두 가지 접근 방식이 있음

Prompt Templating: 특정 사용 사례를 염두에 두고 쿼리와 컨텍스트의 본질을 포착하는 템플릿을 정의
ex) “Help the user resolve issue: {issue_description}. Consider these documents: {document_snippets}.”

Prompt Conditioning: 컨텍스트를 설정하거나 모델이 특정 방식으로 응답하도록 지시하는 접두사를 추가하여 모델을 조건화

"Using your understanding of machine learning and cloud technologies, answer the following:”
5. ETC
  • LLM을 finetuning하여 RAG로 사용

  • 해당 도메인 지식으로 파인튜닝한 LLM 사용하여 질문에 대한 답변 생성

그 답변을 RAG 질문으로 통과

-> 두개를 동시에 썻더니 정확도가 대폭 상승했으나 서버 비용과 속도가 대폭 증가했다고함(https://arca.live/b/alpaca/88242924?p=1)

fine-tuning - rag 비교

  • Parameter Efficient Fine-Tuning (PEFT)

PEFT는 LLM모델을 효과적으로 학습하기 위해 나온 테스크

  • fine tuning 특징

    사용자 정의시 및 상황에 적합한 모델 생성

    데이터 보안 용의

    학습 리소스 필요

    LLM에 비해 더욱 높은 수준에 제어를 할 수 있음

  • RAG 특징

    사용자 정의시 지식을 종적으로 향상시킴

    리소스가 많이 들지 않음

    Fine-tuning 보다는 복잡해 전문 지식 필요

RAG 성능 최적화 해보기

성능 평가를 위해 인터넷 (랜덤)회사 사이트에서 QnA 데이터셋을 가지고 시작

학습 평가셋을 나눠야하나 우선 같은셋으로 진행

(잘 되는 케이스를 모아 테스트 형태를 정교하게 변경 예정)

QnA 846개의 질의응답 셋을 가지고 Answer데이터셋을 전부 백터화 한 후 해당 데이터셋을 잘 가져오는지를 확인

대상 모델 : jhgan/ko-sroberta-multitask

기본 테스트 - 846개중 RAG 결과 상위 1개 2개 3개를 뽑았을때 정답이 포함된 점수

[0.3806146572104019, 0.5011820330969267, 0.5591016548463357]

-> 대상이 많아서인지 38~55%가 나오며 질문 답변 키워드가 겹치는게 많아서 그런것으로 보임 (생각보다 잘나옴)

학습 및 테스트

1. losses.DenoisingAutoEncoderLoss

학습 셋을 그대로 losses.DenoisingAutoEncoderLoss 학습 후 테스트

-> 질문 ,답변 데이터셋을 그대로 넣어 846 * 2 개의 데이터셋 생성

lr = 1e-5 , batch = 8

epoch = 3 [0.15130023640661938, 0.2293144208037825, 0.2695035460992908]
epoch = 10 [0.29314420803782504, 0.4066193853427896, 0.4787234042553192]

성능이 너무 내려가는 것을 확인.. 이방법은 아닌것 같음

2. triplet_loss

1번과 같은 조건으로 triplet loss 테스트 (batch 16)

데이터셋은 부정은 랜덤으로 가져왔으며 2배수로 만들어냄

dataset*1 epoch = 1  [0.3947990543735225, 0.5189125295508275, 0.5673758865248227]
dataset*1 epoch = 3  [0.36879432624113473, 0.48108747044917255, 0.5472813238770685]
dataset*1 epoch = 10  [0.3900709219858156, 0.5047281323877069, 0.5602836879432624]
dataset*2 epoch = 1  [0.32742316784869974, 0.43498817966903075, 0.4988179669030733]
dataset*2 epoch = 3  [0.3959810874704492, 0.5141843971631206, 0.5626477541371159]
dataset*2 epoch = 10 [0.3061465721040189, 0.408983451536643, 0.4787234042553192]

학습 epoch을 많이 늘리면 오를거같은데 학습데이터와 평가데이터가 같아서 오버피팅도 의심됨 …

-> 평가 데이터셋을 따로 구축 필요해보임

3. MultipleNegativesRankingLoss

https://blog.llamaindex.ai/fine-tuning-embeddings-for-rag-with-synthetic-data-e534409a3971

-> 여기에서 미세조정 후 검색 평가 지표 성능이 5~10% 향상되었다고 함 따라해보기

MultipleNegativesRankingLoss

  • 네거티브 샘플링을 positive와 유사하게 만들어 학습하는 방법

  • 중간에 평가가 불가능

  • 긍정쌍만 넣어 모든 부정쌍을 만든 후 softmax 에서 로그 유사도를 최소화 시팀 (triplet이랑 비슷)

    -> batch 마다 많은 수의 negative를 학습시켜 아닌건 확실히 아니라고 나오도록 학습

사용할때 편한점은 positive pair만 넣어주면 negative sampling은 내부에서 알아서 해줌

batch 8

epoch = 1  [0.3900709219858156, 0.5059101654846335, 0.5685579196217494]
epoch = 3  [0.44799054373522457, 0.566193853427896, 0.6323877068557919]
epoch = 10 [0.6146572104018913, 0.735224586288416, 0.7955082742316785]
batch 16 epoch = 10 [0.5531914893617021, 0.6855791962174941, 0.7364066193853428]
batch 8 10, 16 10 -> 20 epoch 시 80까지 올라감 [0.6513002364066194, 0.7683215130023641, 0.817966903073286]
epoch = 30  [0.7600472813238771, 0.8392434988179669, 0.8498817966903073]
epoch = 30 두번 째 시도  [0.7789598108747045, 0.8439716312056738, 0.8569739952718676]

스코어가 상당히 올라가는것을 확인 -> 해당 loss function을 기준으로 여러가지 더 테스트 해보자

16 batch 기준 20GB 사용, 10epoch 기준 약 2~3분 소요

-> 데이터 셋이 확실히 부족해서 스코어가 더 안올라 가는것으로 보임

4. Flag Embedding

코드 : https://github.com/FlagOpen/FlagEmbedding

  • 참조

    https://medium.com/@scholarly360/state-of-the-art-bge-embeddings-for-retrieval-augmented-generation-2c882afb9e37

더 보기

  • RAG로 SQL검색 활용 팁

https://medium.com/madhukarkumar/secrets-to-optimizing-rag-llm-apps-for-better-accuracy-performance-and-lower-cost-da1014127c0a

참고

  • 인공지능신문

https://www.aitimes.kr

https://cloudatlas.me/why-do-rag-pipelines-fail-advanced-rag-patterns-part1-841faad8b3c2

  • RAG 정확도 향상 방법

https://towardsdatascience.com/10-ways-to-improve-the-performance-of-retrieval-augmented-generation-systems-5fa2cee7cd5c

  • fine-tuning - rag 비교

https://www.linkedin.com/pulse/fine-tuning-vs-retrieval-augmented-generation-rag-tailoring-liz-liu/

  • MultipleNegativesRankingLoss 설명

https://acdongpgm.tistory.com/339#What%–is%–MultipleNegativesRankingLoss%-F

  • 코드참조

https://github.com/run-llama/finetune-embedding/blob/main/evaluate.ipynb