일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- 괄호제거
- 상담원 인원
- 브루트포스
- 실버1
- 큐
- useHeaderHeight
- 2800
- LV3
- KeyboardAvoidingView
- 이분탐색
- 골드5
- 복잡도 측정
- 자료구조
- ReactNative
- 백준
- 수정렬하기4
- React #새파일생성
- 3079
- FlatList
- 그래프
- 프로그래머스
- 11831
- 17089
- 이진탐색
- 시간초과해결
- TouchableWithoutFeedback
- PYTHON
- 머신러닝
- 그리디
- 딥러닝
- Today
- Total
지니 코딩일기
[데보션영3기] 데보션오픈랩 LLMOps 스터디에 참여 후기 - 02 본문
저는 AutoRAG라는 소주제를 선택했는데요,
본격적인 첫 스터디의 주제는 [DATA CREATION]입니다!
오늘은 첫 시간이기 때문에 RAG와 AutoRAG에 대한 간단한 설명부터 시작하겠습니다 ~
RAG란?
RAG(Retrieval-Augmented Generation)는 정보 검색(IR)과 자연어 생성(NLG) 모델을 결합하여 AI가 더 정확하고 상세한 정보를 제공할 수 있도록 하는 기술입니다.
RAG는 두 가지 주요 구성 요소로 이루어집니다.
- 문서 검색기(Retriever): 대규모 데이터베이스나 문서 집합에서 사용자 질문과 관련된 정보를 검색합니다.
- 대규모 언어 모델(LLM): 검색된 정보를 활용하여 사용자 질문에 대한 답변을 생성합니다.
RAG의 작동 원리
검색
- RAG는 입력 query로 시작됩니다. 이는 사용자의 질문일 수도 있고 자세한 응답이 필요한 텍스트일 수도 있습니다.
- 검색 모델은 지식 기반, 데이터베이스, 외부 소스 또는 여러 소스에서 동시에 관련 정보를 가져옵니다.
- 검색된 정보는 고차원 공간의 벡터로 변환됩니다. 이러한 지식 벡터는 벡터DB에 저장됩니다.
- 검색 모델은 입력 query와의 관련성을 기준으로 검색된 정보의 순위를 매깁니다. 추가 처리를 위해 가장 높은 점수를 받은 문서나 구절이 선택됩니다.
생성
- 다음으로 LLM과 같은 생성 모델은 검색된 정보를 사용하여 텍스트 응답을 생성합니다.
- 생성된 텍스트는 문법적으로 정확하고 일관성이 있는지 확인하기 위해 추가적인 후처리 단계를 거칠 수 있습니다.
- 이러한 응답은 검색 모델이 제공한 추가 정보에 의해 다듬어졌기 때문에 전체적으로 더 정확하고 context에 더 부합합니다.
RAG의 장점
- 외부 데이터 활용을 통해 LLM의 사실 관계 오류와 맥락 이해 한계를 보완할 수 있습니다. (Hallucination 보완)
- RAG는 외부 참조를 정기적으로 업데이트할 수 있으므로 모델이 가장 최근의 정보에 액세스할 수 있습니다.
- 사용자 질문에 대해 정확하고 풍부한 답변을 제공할 수 있습니다.
- 교육, 의료 등 다양한 분야의 데이터를 활용한 혁신과 발전이 기대됩니다.
이처럼, RAG는 LLM의 한계를 극복하고 AI의 활용 범위를 크게 확장할 수 있는 유망한 기술로 평가받고 있습니다.
AutoRAG란?
AutoRAG는 RAG 파이프라인을 자동으로 최적화해주는 도구입니다.
RAG 파이프라인을 구축하고 최적화하는 것은 어려운 작업입니다.
AutoRAG는 이러한 어려움을 해결하기 위해 개발되었습니다.
사용자가 입력한 질문과 관련 문서를 제공하면, AutoRAG가 자동으로 최적의 RAG 파이프라인을 찾아줍니다.
AutoRAG의 작동 원리
- 사용자 질문과 관련 문서를 입력받습니다.
- 다양한 검색기와 LLM 조합으로 RAG 파이프라인을 구축합니다.
- 각 파이프라인의 성능을 평가하여 최적의 조합을 찾습니다.
- 최적화된 RAG 파이프라인을 출력합니다.
AutoRAG의 장점
- RAG 파이프라인 구축 및 최적화 작업을 자동화합니다.
- 시간과 노력을 절약할 수 있습니다.
- 최적의 RAG 파이프라인을 찾아 AI 답변의 정확성을 높일 수 있습니다.
AutoRAG는 RAG 기술의 활용을 더욱 쉽게 만들어주는 유용한 도구로, RAG 기반 AI 시스템의 성능 향상에 기여할 것으로 기대됩니다!
AutoRAG를 위해서는 RAG의 성능 평가가 필수적입니다.
RAG의 성능을 평가하려면 data가 필요한데, 대부분의 경우 만족스러운 data가 거의 또는 전혀 없습니다.
하지만, LLM 등장 이후 합성 데이터를 만드는 것이 좋은 대안으로 떠올랐습니다.
AutoRAG를 위해서는 사진과 같은 과정을 거쳐 raw data를 corpus data
, qa data
로 변환해야 합니다.
Dataset Format
AutoRAG에 사용되는 dataset은 corpus data
, qa data
2가지가 있습니다.
corpus dataset은 RAG 시스템의 정보 검색 단계에서, qa dataset은 답변 생성 및 평가 단계에서 주로 활용됩니다.
두 데이터셋의 질과 양이 RAG 시스템 전체의 성능을 좌우하게 됩니다.
1. QA dataset
qa data는 qid
, query
, retrieval_gt
, generation_gt
총 4가지 column을 가집니다.
qid : string
- 각 쿼리의 고유 식별자
query : string
- 사용자의 질문 내용
retrieval_gt : 2D list
- 검색된 정답 ID를 저장하는 문서 ID의 2차원 리스트 (1차원 string도 가능)
- 2차원 리스트인 이유는 질문에 대한 답변을 구성하기 위해 여러 문서의 정보를 조합해야 하기 때문
- 예를 들어 retrieval_gt = [['NewJeans1', 'Aespa1'], ['NewJeans2', 'Aespa2']]라면:
'NewJeans1'과 'Aespa1' 문서를 참고하거나
'NewJeans2'와 'Aespa2' 문서를 참고하면해당 질문에 대한 답변을 구성할 수 있다는 의미. - AutoRAG는 이 column을 사용하여 검색 성능을 평가하기 때문에 매우 중요합니다.
generation_gt : list
- LLM 모델이 생성할 것으로 기대하는 정답 목록입니다.
- RAG 시스템의 Generation 단계에서 목표로 하는 이상적인 답변 텍스트를 의미하며, 시스템 평가 및 학습을 위한 지표로 활용됩니다.
2. Corpus dataset
corpus dataset은 doc_id
, contents
, metadata
총 3가지 column을 가집니다.
doc_id : string
- chunk된 각 passage의 고유 식별자
contents : string
- 실제 콘텐츠 내용
- 다양한 chunk 전략을 통해 chunk된 결과물
metadata : dictionary
- chunk된 각 passage의 metadata 모음
evaluation data 생성
이제, corpus data와 qa data를 직접 생성해보겠습니다!
저는 네이버에서 적당한 길이의 뉴스기사 .txt 파일로 만들어서 데이터로 사용해보았습니다.
raw data에서 → corpus data 생성하기
- llama_index, LangChain 등의 loader를 이용해서 raw data를 texts로 load
- texts를 여러 문단으로 split
- corpus data로 만들기
- llama index는
llama_document_to_parquet
,llama_text_node_to_parquet
- Langchain은
langchain_document_to_parquet
사용
- llama index는
[Llama Index 코드]
from llama_index.core import SimpleDirectoryReader
from llama_index.core.node_parser import TokenTextSplitter
from autorag.data.corpus import llama_text_node_to_parquet
documents = SimpleDirectoryReader('your_dir_path').load_data()
nodes = TokenTextSplitter().get_nodes_from_documents(documents=documents, chunk_size=512, chunk_overlap=128)
corpus_df = llama_text_node_to_parquet(nodes, 'path/to/corpus.parquet')
[LangChain 코드]
from langchain_community.document_loaders import DirectoryLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from autorag.data.corpus import langchain_documents_to_parquet
documents = DirectoryLoader('your_dir_path', glob='**/*.md').load()
documents = RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=128).split_documents(documents)
corpus_df = langchain_documents_to_parquet(documents, 'path/to/corpus.parquet')
실행 결과
실행 결과는 간단히 print문으로 확인해봤습니다!
[ llama_index ]
[ langchain ]
실행 결과, corpus.parquet 파일이 생성되었고,
load후 split한 결과를 출력했을 때, 각각 이렇게 content, metadata를 포함한 형태로 출력되었습니다.
이때, llama와 langchain 결과에 담긴 데이터는 metadata의 값에서 차이가 있었습니다.
그리고 chunk_overlap을 하였기 때문에 이전 문단의 마지막 한 줄이 다음 문단의 첫 줄이 되는 것을 확인했습니다.
좀 더 구체적으로, langchain으로 생성한 corpus.parquet 파일을 살펴보면, 다음과 같습니다.
[.parquet 파일]
{
"doc_id":"5539088f-900d-4dbf-884a-987d9779813f",
"contents":"제21회 부산마라톤 대회가 졸속 운영으로 논란이 되면서 환불 요구가 빗발치고 있지만, 대회 측은 \"앞으로 의견을 수렴하겠다\"는 의미 없는 대응으로 일관하고 있다.\n\n지난 21일 부산시 강서구 대저생태공원 일원에서 부산광역시육상협회 주최, 부산마라톤협회 주관으로 제21회 부산마라톤이 개최됐다.\n\n이날 참가 인원은 5,000여 명에 달했으며 참가비는 5km 3만 원, 10km 3만 5,000원, 하프마라톤 4만 원이었다.\n\n그러나 대회 당일날인 21일부터 부산마라톤 홈페이지 게시판에는 대회 참가자들의 불만 섞인 후기글이 올라오고 있다.\n\n이들은 식수나 음식 공급, 코스 확보, 차량 통제 등 모든 게 엉망진창이었다며 분통을 터트렸다.\n\n한 참가자는 \"홈페이지상에는 국수, 두부김치, 막걸리 등 제공이라고 돼 있었는데 (현장에는) 전혀 없었다\"며 \"지불한 금액에 포함이라 생각했는데, 기념 티셔츠 하나만 주는 거였으면 4만 원 주고 신청 안 했다\"고 항의했다.",
"metadata":{"last_modified_datetime":1715261672606.668,"source":"뉴스기사.txt"}
}
생성된 data를 잘 살펴보면, corpus dataset의 column 요소인 doc_id
, contents
, metadata
가 모두 생성된 것을 확인할 수 있습니다.
corpus data에서 → qa data 생성하기
generate_qa_llama_index
는 콘텐츠별로 query 와 generation_gt 를 생성해줍니다.question_num_per_content
매개변수를 변경하여 콘텐츠 당 생성할 질문 개수를 설정할 수 있습니다 .make_single_content_qa
함수는 qa.parquet
파일을 생성합니다.
import pandas as pd
from llama_index.llms.openai import OpenAI
from autorag.data.qacreation import generate_qa_llama_index, make_single_content_qa
corpus_df = pd.read_parquet('path/to/corpus.parquet')
llm = OpenAI(model='gpt-3.5-turbo', temperature=1.0)
qa_df = make_single_content_qa(corpus_df, 50, generate_qa_llama_index, llm=llm, question_num_per_content=1,output_filepath='path/to/qa.parquet')
이때, make_single_content_qa
함수 2번째 인자로 들어가는 값은 corpus data의 크기와 같기 때문에, 자신의 corpus data에 맞게 수정해줘야 합니다.
그리고 OpenAI API를 사용하기 위해서,
openAI에서 API key를 발급받은 후 .env파일에 저장한 뒤, 다음 코드를 통해 세팅해줬습니다.
# API 키를 환경변수로 관리하기 위한 설정 파일
from dotenv import load_dotenv
# API 키 정보 로드
load_dotenv()
실행 결과
[qa.parquet]
{
"qid":"91cad8a2-e274-4cd4-b978-73f08d3e6e93",
"retrieval_gt":[["d1c83ed6-5899-4102-825c-764552d51115"]],
"query":"Where did the 21st Busan Marathon take place?",
"generation_gt":["The 21st Busan Marathon was held at the Daepar Ecological Park in Gangseo-gu, Busan."]
}
qa.parquet 결과를 보면, 질문이 영어로 생성된 것을 확인할 수 있습니다.
생성된 data를 잘 살펴보면, qa dataset의 column 요소인 qid
, query
, retrieval_gt
, generation_gt
가 모두 생성된 것을 확인할 수 있습니다.
좀더 보기 쉽게 print를 해보면, 다음처럼 4개의 질문이 생성된 걸 확인할 수 있습니다.
make_single_content_qa 함수에서 question_num_per_content=2로 설정하면, 문단 당 2개씩 질문이 생성되는 것을 확인할 수 있습니다.
결과도 나름 잘 나왔습니다!
llama_index의 경우, corpus data를 생성하는 과정에서 SimpleDirectoryReader ...등에 대한 내용이 첫 줄에 추가되어서 query 생성시에도 관련 없는 내용이 하나 포함되었습니다 😂
사용자 정의 프롬프트
사용자 정의 프롬프트를 사용하여 QA 데이터를 생성할 수 있습니다.
- {{text}}: 콘텐츠 문자열
- {{num_questions}}: 생성할 질문 수
import pandas as pd
from llama_index.llms.openai import OpenAI
from autorag.data.qacreation import generate_qa_llama_index, make_single_content_qa
prompt = """
Generate question and answer pairs for the given passage.
Passage:
{{text}}
Number of questions to generate: {{num_questions}}
Example:
[Q]: What is this?
[A]: This is a sample question.
Result:
"""
corpus_df = pd.read_parquet('path/to/corpus.parquet')
llm = OpenAI(model='gpt-3.5-turbo', temperature=1.0)
qa_df = make_single_content_qa(corpus_df, content_size=50, qa_creation_func=generate_qa_llama_index,
llm=llm, prompt=prompt, question_num_per_content=1)
프롬프트 수정 후
prompt = """
Generate natural and engaging question-answer pairs based on the given passage. The questions should be relevant, thought-provoking, and require understanding the key points and details in the passage to answer correctly. The answers should be clear, concise, and directly address the corresponding question.
Passage: {{text}}
Number of questions to generate: {{num_questions}}
Example:
[Q]: What are the main causes of global warming according to the passage?
[A]: The passage states that the primary causes of global warming are the burning of fossil fuels like coal and oil, as well as deforestation which reduces the Earth's capacity to absorb carbon dioxide.
Result:
"""
프롬프트를 수정하였더니 더 구체적인 질문과 답변을 받을 수 있었습니다!
여러 프롬프트 사용
다양한 유형의 질문 및 답변 쌍을 생성하려는 경우 여러 프롬프트를 사용할 수 있습니다.
각 프롬프트의 비율에 따라 무작위로 여러 프롬프트를 배포하는 기능을 지원하는데, 이는 구절당 비율에 따라 프롬프트가 선택된다는 의미입니다.
이를 위해서는 dictionary를 제공해야 합니다. dictionary에는 프롬프트 텍스트 파일 경로인 키와 프롬프트의 비율인 값이 있어야 합니다.
import pandas as pd
from llama_index.llms.openai import OpenAI
from autorag.data.qacreation import generate_qa_llama_index_by_ratio, make_single_content_qa
ratio_dict = {
'prompt1.txt': 1,
'prompt2.txt': 2,
'prompt3.txt': 3
}
corpus_df = pd.read_parquet('path/to/corpus.parquet')
llm = OpenAI(model='gpt-3.5-turbo', temperature=1.0)
qa_df = make_single_content_qa(corpus_df, content_size=50, qa_creation_func=generate_qa_llama_index_by_ratio,
llm=llm, prompts_ratio=ratio_dict, question_num_per_content=1, batch=6)
RAGAS evaluation data 생성
RAGAS(RAG Assessment)는 RAG(Retrieval-Augmented Generation) 파이프라인의 성능을 평가하고 모니터링하는 프레임워크입니다!
RAGAS는 평가용 evaluation data를 생성하는 기능도 가지고 있습니다.
RAGAS를 이용해서 Corpus data에서 → QA set 생성하기
QA set은 RAGAS를 이용해서도 생성할 수 있습니다.
import pandas as pd
from autorag.data.qacreation.ragas import generate_qa_ragas
corpus_df = pd.read_parquet('path/to/corpus-lang.parquet')
qa_df = generate_qa_ragas(corpus_df, test_size=50)
generate_qa_ragas 함수의 test_size 값을 조절해서 질문 개수를 정할 수 있습니다.
그런데 실행하자,
generate_qa_ragas함수 실행에서 429 error
, max retries exceeded for SimpleEvolution
이 발생했습니다.
원인을 찾다가, 해당 함수가 langchain을 기반으로 하는 것 같아 langchain으로 생성한 corpus-lang.parquet 파일을 사용했습니다.
(앞의 코드들은 모두 llama로 생성한 파일을 사용해야 했습니다)
그랬더니 오류는 없었지만
이렇게 3분이 넘는 오랜 시간 동안 돌려도 결과가 나오지 않았습니다..!
이유가 뭘까요 ….. 😦
generate_qa_ragas가 실행이 되지 않아서 뒤에 내용들도 직접 결과를 보지는 못했습니다 😭
스터디를 하면서 의논한 결과,
아무래도 autorag에서 자체적으로 생성한 라이브러리라서 안정성이 떨어지기 때문인 것 같습니다..!
그래서 다음에는 다른 방법으로 시도해보려고 합니다 !!
RAGAS 질문 유형
RAGAS는 원본 질문을 변형하여 추론, 조건, 다중 문맥, 대화형 등 다양한 특성을 가진 복잡한 질문을 생성합니다.
이를 통해 RAG 시스템의 전반적인 성능을 포괄적으로 평가할 수 있습니다.
- simple
- RAGAS는 난이도를 혼합하기 위해 단순한 직접적인 질문도 포함합니다.
- 예시
- "뉴턴의 제2법칙은 무엇인가?”
- reasoning (추론)
- 원본 질문을 효과적으로 답변하기 위해 추론이 필요하도록 재구성한 질문입니다. RAG 시스템의 multi-step 추론 능력을 평가합니다.
- 예시
- 원본 질문: "미국의 수도는 어디인가?"
- 추론 질문: "워싱턴 D.C.는 미국의 수도이다. 이 도시는 어떤 강 근처에 위치하는가?"
- multi_context
- 답변을 구성하기 위해 여러 관련 섹션이나 텍스트 조각의 정보가 필요하도록 재구성한 질문입니다. 검색 컴포넌트가 모든 관련 문맥을 찾아내는 능력을 평가합니다.
- 예시
- 원본 질문: "암은 무엇인가?"
- 다중 문맥 질문: "암의 원인, 증상 및 치료법에 대해 설명하시오."
- conditional
- 원본 질문에 조건을 추가하여 복잡성을 높인 질문입니다. RAG 시스템이 조건을 처리하는 능력을 평가합니다.
- 예시
- 원본 질문: "인간 면역 결핍 바이러스는 무엇인가?"
- 조건부 질문: "만약 HIV 바이러스에 감염되었다면, 어떤 증상이 나타날 수 있는가?"
from ragas.testset.evolutions import simple, reasoning, multi_context, conditional
from autorag.data.qacreation.ragas import generate_qa_ragas
distributions = { # uniform distribution
simple: 0.25,
reasoning: 0.25,
multi_context: 0.25,
conditional: 0.25
}
qa_df = generate_qa_ragas(corpus_df, test_size=50, distributions=distributions)
distributions에서 비율을 정할 수 있습니다
사용자 정의 모델 사용
RAGAS는 Langchain을 사용하여 사용자 정의 모델을 지원합니다.ChatModel
또한 Langchain의 클래스를 사용해야 할 수도 있습니다 .
from autorag.data.qacreation.ragas import generate_qa_ragas
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
generator_llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0.4)
critic_llm = ChatOpenAI(model="gpt-4", temperature=0.0)
embedding_model = OpenAIEmbeddings()
qa_df = generate_qa_ragas(corpus_df, test_size=50, distributions=distributions,
generator_llm=generator_llm, critic_llm=critic_llm, embedding_model=embedding_model)
이번 첫 스터디에서는 이렇게 RAG의 평가를 위해 필요한 Data를 생성하는 방법을 알아보고, 생성해보았습니다!
Reference
https://marker-inc-korea.github.io/AutoRAG/data_creation/tutorial.html
https://marker-inc-korea.github.io/AutoRAG/data_creation/data_format.html
https://marker-inc-korea.github.io/AutoRAG/data_creation/ragas.html