Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
**/.retrieval-augmented-generation
**/.env
**/__pycache__
**/res
**/res
myenv/
72 changes: 70 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,70 @@
# RAG-1stWeek
11월 7일 실습 및 과제를 위한 레포지토리입니다.
# RAGAS Metrics 분석 보고서


## 1. LLMContextRecall

- LLMContextRecall은 사용자 질문에 대해 모델이 검색한 정보가 얼마나 정확히 참조 답변에 포함된 주장(claim)을 포함하고 있는지 평가
- LLM을 사용하여 참조 답변(reference answer)의 각 주장이 검색된 컨텍스트(retrieved context)에 포함되어 있는지를 확인
- 이 metric은 0과 1 사이의 값을 가지며, 1에 가까울수록 검색된 정보가 참조 답변을 잘 포함하고 있음을 의미

### 예시 코드

```python
from ragas.dataset_schema import SingleTurnSample
from ragas.metrics import LLMContextRecall

# 평가할 샘플 생성
sample = SingleTurnSample(
user_input="Where is the Eiffel Tower located?", # 사용자 질문
response="The Eiffel Tower is located in Paris.", # 모델의 응답
reference="The Eiffel Tower is located in Paris.", # 참조 답변
retrieved_contexts=["Paris is the capital of France."], # 검색된 컨텍스트
)

# LLM 기반의 Context Recall 계산
context_recall = LLMContextRecall()
await context_recall.single_turn_ascore(sample)
```

- 예를 들어, "The Eiffel Tower is located in Paris."라는 참조 답변이 주어졌을 때, 모델이 "Paris is the capital of France."라는 검색 결과를 제시한 경우, 어느 정도 관련성이 있다고 평가

## 2. FactualCorrectness
- FactualCorrectness는 모델의 응답이 얼마나 사실에 부합하는지 평가
- 검색된 컨텍스트나 참조 정답과의 관련성을 확인해 모델이 부정확하거나 오해를 일으킬 수 있는 정보 제공 X

예시 코드
```python
from ragas.dataset_schema import SingleTurnSample
from ragas.metrics import FactualCorrectness

sample = SingleTurnSample(
user_input="What is the capital of France?",
response="The capital of France is Paris.",
reference="Paris is the capital of France."
)

factual_correctness = FactualCorrectness()
await factual_correctness.single_turn_ascore(sample)
```


## 3. NonLLMContextRecall
- NonLLMContextRecall은 LLMContextRecall과 유사한 방식으로 컨텍스트 회수 능력을 평가하지만, LLM 대신 문자열 비교와 같은 간단한 기준 사용

예시 코드
```python
from ragas.dataset_schema import SingleTurnSample
from ragas.metrics import NonLLMContextRecall

sample = SingleTurnSample(
retrieved_contexts=["Paris is the capital of France."],
reference_contexts=[
"Paris is the capital of France.",
"The Eiffel Tower is one of the most famous landmarks in Paris."
]
)

context_recall = NonLLMContextRecall()
await context_recall.single_turn_ascore(sample)
```
- 위 코드에서 NonLLMContextRecall은 검색된 컨텍스트가 참조 컨텍스트에 포함된 주장을 얼마나 잘 회수했는지 비교
57 changes: 37 additions & 20 deletions embeddings.ipynb

Large diffs are not rendered by default.

52 changes: 32 additions & 20 deletions intro.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,45 @@
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"# .env 파일에서 환경 변수를 불러와 OPENAI_API_KEY 값을 가져오는 코드\n",
"from dotenv import load_dotenv\n",
"import os\n",
"\n",
"load_dotenv()\n",
"\n",
"OPENAI_API_KEY=os.getenv(\"OPENAI_API_KEY\")\n"
"OPENAI_API_KEY = os.getenv(\"OPENAI_API_KEY\")\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"제가 실시간으로 날씨를 알려드릴 수는 없지만, 내일 서울의 예상 날씨는 대체로 맑은 날씨가 예상되며 최저 기온은 약 10도, 최고 기온은 약 19도 정도가 되겠습니다. 하지만 정확한 예보는 내일 아침에 다시 확인해보시는 것이 좋을 것 같습니다.\n"
"내일 서울의 날씨는 대체로 맑고 낮 기온은 26도, 밤에는 16도까지 내려갈 것으로 예상됩니다. 강수 확률은 매우 낮을 것으로 보입니다. 외출 시에는 가볍게 입을만한 옷을 준비하시면 좋을 것 같습니다.\n"
]
}
],
"source": [
"from openai import OpenAI\n",
"\n",
"client = OpenAI(api_key=OPENAI_API_KEY)\n",
"client = OpenAI(api_key=OPENAI_API_KEY) # API 클라이언트 초기화\n",
"\n",
"prompt=\"내일 서울 날씨는 어때?\"\n",
"prompt = \"내일 서울 날씨는 어때?\" # 사용자 질문 설정\n",
"\n",
"# GPT-3.5 모델로 질문에 대한 응답 생성\n",
"completion = client.chat.completions.create(\n",
" model=\"gpt-3.5-turbo-0125\",\n",
" messages=[\n",
" {\"role\": \"user\", \"content\": prompt},\n",
" ]\n",
" messages=[{\"role\": \"user\", \"content\": prompt}],\n",
")\n",
"\n",
"print(completion.choices[0].message.content)"
"print(completion.choices[0].message.content) # 모델의 응답 출력\n"
]
},
{
Expand All @@ -53,7 +52,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"저는 인공지능 챗봇으로 기상 정보를 제공하기 위해 프로그래밍되었습니다. 실시간으로 기상 정보를 업데이트하고 사용자의 질문에 대답하기 위해 미리 프로그래밍된 데이터베이스를 참조합니다. 그래서 사용자가 날씨에 관한 질문을 하면 제가 프로그래밍된 정보를 바탕으로 대답을 제공할 수 있습니다. 따라서 실시간 정보 업데이트가 되지 않는다고 걱정하지 않아도 됩니다.\n"
"저는 기상청 API와 같은 데이터 소스를 통해 실시간으로 날씨 정보를 가져와 사용자에게 제공합니다. 이를 통해 사용자가 원하는 시간대의 날씨를 정확하게 예측할 수 있습니다. 따라서 내일의 날씨 정보도 신뢰할 수 있게 제공해 드릴 수 있습니다.\n"
]
}
],
Expand All @@ -72,14 +71,14 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"내일은 전남해안과 제주도 중심으로 가끔 비가 오는 것으로 예상되며, 풍랑과 너울에 유의해야 합니다. 전국적으로는 대체로 흐린 날씨가 예상되니 우산을 챙기시고 외출하시는 것이 좋겠습니다.\n"
"내일은 전남해안과 제주도 중심으로 가끔 비가 오는 것으로 예상되며, 풍랑과 너울에 유의해야 합니다. 모레는 전국 대체로 맑겠지만, 경상권과 제주도는 가끔 구름이 많을 것으로 예상됩니다. 강수량은 각 지역마다 다르며, 서해5도와 강원산지, 강원동해안 등에서 5~10mm의 강수량이 예상됩니다.\n"
]
}
],
Expand Down Expand Up @@ -117,7 +116,7 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": null,
"metadata": {},
"outputs": [
{
Expand All @@ -127,28 +126,41 @@
"가장 유사한 텍스트 번호: 1\n",
"겹치는 단어 수 : 2\n"
]
},
{
"ename": "",
"evalue": "",
"output_type": "error",
"traceback": [
"\u001b[1;31mThe Kernel crashed while executing code in the current cell or a previous cell. \n",
"\u001b[1;31mPlease review the code in the cell(s) to identify a possible cause of the failure. \n",
"\u001b[1;31mClick <a href='https://aka.ms/vscodeJupyterKernelCrash'>here</a> for more info. \n",
"\u001b[1;31mView Jupyter <a href='command:jupyter.viewOutput'>log</a> for further details."
]
}
],
"source": [
"def count_common_words(text1, text2):\n",
" words1 = text1.split()\n",
" words2 = text2.split()\n",
" common_words = set(words1) & set(words2)\n",
" common_words = set(words1) & set(words2) # 두 텍스트에서 겹치는 단어 집합 구하기\n",
" return len(common_words)\n",
"\n",
"question = '한국의 전통 음식에 대해 무엇을 알고 계신가요?'\n",
"question = '한국의 전통 음식에 대해 무엇을 알고 계신가요?' # 사용자 질문\n",
"\n",
"ref_texts = [\n",
" '한국의 전통 음식은 다양한 재료와 조리법으로 유명합니다. 김치, 불고기, 비빔밥 등이 대표적인 예시입니다.',\n",
" '한국의 음식 문화는 건강에 좋은 재료를 사용하는 것으로 알려져 있습니다. 발효 식품인 김치가 대표적입니다.',\n",
" '한국의 역사와 문화는 매우 흥미롭습니다. 고궁과 한복, 그리고 태권도 등이 유명한 문화 요소입니다.'\n",
"]\n",
"\n",
"# 각 참조 텍스트와 질문에서 겹치는 단어 수 계산\n",
"common_word_counts = [count_common_words(question, ref_text) for ref_text in ref_texts]\n",
"\n",
"# 가장 많이 겹치는 단어 수를 가진 텍스트 찾기\n",
"most_similar_index = common_word_counts.index(max(common_word_counts))\n",
"print(f\"가장 유사한 텍스트 번호: {most_similar_index+1}\")\n",
"print(f\"겹치는 단어 수 : {common_word_counts[most_similar_index]}\")"
"print(f\"겹치는 단어 수 : {common_word_counts[most_similar_index]}\")\n"
]
},
{
Expand All @@ -161,7 +173,7 @@
],
"metadata": {
"kernelspec": {
"display_name": ".retrieval-augmented-generation",
"display_name": "myenv",
"language": "python",
"name": "python3"
},
Expand All @@ -175,7 +187,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.4"
"version": "3.12.0"
}
},
"nbformat": 4,
Expand Down
162 changes: 162 additions & 0 deletions korquad_new.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"c:\\Users\\Byung Mu Kang\\RAG-1stWeek\\myenv\\Lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
" from .autonotebook import tqdm as notebook_tqdm\n"
]
}
],
"source": [
"import pickle\n",
"from datasets import load_dataset\n",
"import random\n",
"\n",
"# KorQuAD 데이터셋 로드\n",
"dataset = load_dataset(\"KorQuAD/squad_kor_v1\")\n",
"\n",
"# 상위 10개 샘플만 선택\n",
"subset = dataset['train'].select(range(10))\n",
"\n",
"# 데이터 준비 (상위 10개만 선택)\n",
"questions = [sample['question'] for sample in subset]\n",
"contexts = [sample['context'] for sample in subset]\n",
"answers = [sample['answers']['text'][0] for sample in subset]\n",
"\n",
"# 각 질문에 대해 여러 개의 Context 생성 (정답 포함 + 무작위 Context 추가)\n",
"num_contexts = 3 # 각 질문에 대해 3개의 Context 설정\n",
"all_contexts = []\n",
"for i in range(len(questions)):\n",
" context_list = [contexts[i]] # 정답이 포함된 실제 Context\n",
" for _ in range(num_contexts - 1): # 나머지 Context는 무작위로 추가\n",
" random_context = random.choice(contexts)\n",
" context_list.append(random_context)\n",
" all_contexts.append(context_list)\n",
"\n",
"# RAG 데이터 구조 생성\n",
"rag_data = {\n",
" 'questions': questions,\n",
" 'contexts': all_contexts,\n",
" 'contexts_answer_idx': [0] * len(questions), # 실제 답변이 포함된 Context 인덱스를 첫 번째로 설정\n",
" 'answers': answers\n",
"}\n",
"\n",
"# pickle로 데이터 저장\n",
"with open('korquad_rag_data_10_new.pkl', 'wb') as f:\n",
" pickle.dump(rag_data, f)\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"10"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(questions)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"바그너는 괴테의 파우스트를 읽고 무엇을 쓰고자 했는가?\n",
"바그너는 교향곡 작곡을 어디까지 쓴 뒤에 중단했는가?\n",
"바그너가 파우스트 서곡을 쓸 때 어떤 곡의 영향을 받았는가?\n",
"1839년 바그너가 교향곡의 소재로 쓰려고 했던 책은?\n",
"파우스트 서곡의 라단조 조성이 영향을 받은 베토벤의 곡은?\n"
]
}
],
"source": [
"for question in questions[:5]:\n",
" print(question)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"from ragas.llms import LangchainLLMWrapper\n",
"from langchain_openai import ChatOpenAI\n",
"evaluator_llm = LangchainLLMWrapper(ChatOpenAI(model=\"gpt-4o\"))\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from tqdm import tqdm\n",
"from utils import call_openai, get_embeddings, cosine_similarity\n",
"\n",
"predictions = []\n",
"\n",
"# 각 질문에 대해 OpenAI 모델을 호출하여 예측 응답을 생성\n",
"for i in tqdm(range(len(questions))):\n",
" prompt = f\"\"\"You are an expert in reading comprehension and Korean general knowledge. Please answer the following question using only a single word. Use information given in Context appropriately.\n",
" \n",
"Question:\n",
"{questions[i]}\n",
"\"\"\"\n",
"\n",
" prediction = call_openai(prompt, model='gpt-4o-2024-05-13') # OpenAI 모델 호출하여 응답 생성\n",
" predictions.append(prediction) # 생성된 응답을 predictions 리스트에 추가\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "myenv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.0"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Binary file added korquad_rag_data.pkl
Binary file not shown.
Binary file added korquad_rag_data_10.pkl
Binary file not shown.
Binary file added korquad_rag_data_10_new.pkl
Binary file not shown.
Loading