Spaces:
Sleeping
Sleeping
Merge feature/llm-evaluation-system
Browse files- README.md +5 -4
- docs/README.en.md +24 -21
- sandbox/llm-evaluator-notebook (1).md +469 -0
README.md
CHANGED
@@ -44,15 +44,14 @@ license: mit
|
|
44 |
|
45 |
## 🚀 プロジェクト概要
|
46 |
|
47 |
-
**Llama-finetune-sandbox**は、Llamaモデルのファインチューニングを実験的に学習・検証できる環境です。様々なファインチューニング手法を試し、モデルのカスタマイズや性能評価を行うことができます。初学者から研究者まで、幅広いユーザーのニーズに対応します。バージョン0.
|
|
|
48 |
|
49 |
## ✨ 主な機能
|
50 |
|
51 |
1. **多様なファインチューニング手法**:
|
52 |
- LoRA (Low-Rank Adaptation)
|
53 |
- QLoRA (Quantized LoRA)
|
54 |
-
- ⚠️~Full Fine-tuning~
|
55 |
-
- ⚠️~Parameter-Efficient Fine-tuning (PEFT)~
|
56 |
|
57 |
2. **柔軟なモデル設定**:
|
58 |
- カスタム可能な最大シーケンス長
|
@@ -79,6 +78,7 @@ license: mit
|
|
79 |
- → 詳細は [`efficient-ollama-colab-setup-with-litellm-guide.md`](sandbox/efficient-ollama-colab-setup-with-litellm-guide.md) をご参照ください。
|
80 |
- [📒ノートブックはこちら](https://colab.research.google.com/drive/1buTPds1Go1NbZOLlpG94VG22GyK-F4GW?usp=sharing)
|
81 |
|
|
|
82 |
## 🛠️ 環境構築
|
83 |
|
84 |
1. リポジトリのクローン:
|
@@ -107,6 +107,7 @@ cd Llama-finetune-sandbox
|
|
107 |
- [Llama モデルについて](https://github.com/facebookresearch/llama)
|
108 |
- [ファインチューニングのベストプラクティス](https://github.com/Sunwood-ai-labs/Llama-finetune-sandbox/wiki)
|
109 |
|
110 |
-
##
|
111 |
|
112 |
このプロジェクトはMITライセンスの下で公開されています。
|
|
|
|
44 |
|
45 |
## 🚀 プロジェクト概要
|
46 |
|
47 |
+
**Llama-finetune-sandbox**は、Llamaモデルのファインチューニングを実験的に学習・検証できる環境です。様々なファインチューニング手法を試し、モデルのカスタマイズや性能評価を行うことができます。初学者から研究者まで、幅広いユーザーのニーズに対応します。バージョン0.2.0では、ドキュメントの更新と改善が行われました。特に、OllamaとLiteLLMを使った効率的なモデル運用ガイドが追加され、README.mdと実装例ガイドも見やすくなりました。
|
48 |
+
|
49 |
|
50 |
## ✨ 主な機能
|
51 |
|
52 |
1. **多様なファインチューニング手法**:
|
53 |
- LoRA (Low-Rank Adaptation)
|
54 |
- QLoRA (Quantized LoRA)
|
|
|
|
|
55 |
|
56 |
2. **柔軟なモデル設定**:
|
57 |
- カスタム可能な最大シーケンス長
|
|
|
78 |
- → 詳細は [`efficient-ollama-colab-setup-with-litellm-guide.md`](sandbox/efficient-ollama-colab-setup-with-litellm-guide.md) をご参照ください。
|
79 |
- [📒ノートブックはこちら](https://colab.research.google.com/drive/1buTPds1Go1NbZOLlpG94VG22GyK-F4GW?usp=sharing)
|
80 |
|
81 |
+
|
82 |
## 🛠️ 環境構築
|
83 |
|
84 |
1. リポジトリのクローン:
|
|
|
107 |
- [Llama モデルについて](https://github.com/facebookresearch/llama)
|
108 |
- [ファインチューニングのベストプラクティス](https://github.com/Sunwood-ai-labs/Llama-finetune-sandbox/wiki)
|
109 |
|
110 |
+
## 📄 ライセンス
|
111 |
|
112 |
このプロジェクトはMITライセンスの下で公開されています。
|
113 |
+
```
|
docs/README.en.md
CHANGED
@@ -31,7 +31,7 @@ license: mit
|
|
31 |
</p>
|
32 |
|
33 |
<h2 align="center">
|
34 |
-
|
35 |
</h2>
|
36 |
|
37 |
<p align="center">
|
@@ -44,38 +44,40 @@ license: mit
|
|
44 |
|
45 |
## 🚀 Project Overview
|
46 |
|
47 |
-
**Llama-finetune-sandbox**
|
48 |
|
49 |
-
## ✨ Key Features
|
50 |
|
51 |
-
|
|
|
|
|
52 |
- LoRA (Low-Rank Adaptation)
|
53 |
- QLoRA (Quantized LoRA)
|
54 |
-
- ⚠️~Full Fine-tuning~
|
55 |
-
- ⚠️~Parameter-Efficient Fine-tuning (PEFT)~
|
56 |
|
57 |
-
2. **Flexible Model
|
58 |
- Customizable maximum sequence length
|
59 |
- Various quantization options
|
60 |
- Multiple attention mechanisms
|
61 |
|
62 |
-
3. **
|
63 |
- Performance evaluation tools
|
64 |
- Memory usage optimization
|
65 |
-
-
|
66 |
-
|
67 |
|
68 |
## 📚 Implementation Examples
|
69 |
|
70 |
This repository includes the following implementation examples:
|
71 |
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
|
|
|
|
|
|
|
|
|
|
77 |
|
78 |
-
2. Other implementation examples will be added periodically.
|
79 |
|
80 |
## 🛠️ Environment Setup
|
81 |
|
@@ -85,7 +87,7 @@ git clone https://github.com/Sunwood-ai-labs/Llama-finetune-sandbox.git
|
|
85 |
cd Llama-finetune-sandbox
|
86 |
```
|
87 |
|
88 |
-
## 📝 Adding
|
89 |
|
90 |
1. Add new implementations to the `examples/` directory.
|
91 |
2. Add necessary settings and utilities to `utils/`.
|
@@ -102,9 +104,10 @@ cd Llama-finetune-sandbox
|
|
102 |
## 📚 References
|
103 |
|
104 |
- [HuggingFace PEFT Documentation](https://huggingface.co/docs/peft)
|
105 |
-
- [About Llama
|
106 |
-
- [Fine-tuning
|
107 |
|
108 |
-
##
|
109 |
|
110 |
-
This project is licensed under the MIT License.
|
|
|
|
31 |
</p>
|
32 |
|
33 |
<h2 align="center">
|
34 |
+
Llama Model Fine-tuning Experiment Environment
|
35 |
</h2>
|
36 |
|
37 |
<p align="center">
|
|
|
44 |
|
45 |
## 🚀 Project Overview
|
46 |
|
47 |
+
**Llama-finetune-sandbox** provides an experimental environment for learning and verifying Llama model fine-tuning. You can try various fine-tuning methods, customize models, and evaluate performance. It caters to a wide range of users, from beginners to researchers. Version 0.2.0 includes updated and improved documentation. In particular, guides for efficient model operation using Ollama and LiteLLM have been added, and the README.md and implementation example guides have been made easier to understand.
|
48 |
|
|
|
49 |
|
50 |
+
## ✨ Main Features
|
51 |
+
|
52 |
+
1. **Diverse Fine-tuning Methods:**
|
53 |
- LoRA (Low-Rank Adaptation)
|
54 |
- QLoRA (Quantized LoRA)
|
|
|
|
|
55 |
|
56 |
+
2. **Flexible Model Configuration:**
|
57 |
- Customizable maximum sequence length
|
58 |
- Various quantization options
|
59 |
- Multiple attention mechanisms
|
60 |
|
61 |
+
3. **Well-equipped Experiment Environment:**
|
62 |
- Performance evaluation tools
|
63 |
- Memory usage optimization
|
64 |
+
- Experiment result visualization
|
|
|
65 |
|
66 |
## 📚 Implementation Examples
|
67 |
|
68 |
This repository includes the following implementation examples:
|
69 |
|
70 |
+
### High-Speed Fine-tuning using Unsloth
|
71 |
+
- High-speed fine-tuning implementation of Llama-3.2-1B/3B models
|
72 |
+
- → See [`Llama_3_2_1B+3B_Conversational_+_2x_faster_finetuning_JP.md`](sandbox/Llama_3_2_1B+3B_Conversational_+_2x_faster_finetuning_JP.md) for details.
|
73 |
+
- → [Use this to convert from markdown format to notebook format](https://huggingface.co/spaces/MakiAi/JupytextWebUI)
|
74 |
+
- [📒Notebook here](https://colab.research.google.com/drive/1AjtWF2vOEwzIoCMmlQfSTYCVgy4Y78Wi?usp=sharing)
|
75 |
+
|
76 |
+
### Efficient Model Operation using Ollama and LiteLLM
|
77 |
+
- Setup and operation guide on Google Colab
|
78 |
+
- → See [`efficient-ollama-colab-setup-with-litellm-guide.md`](sandbox/efficient-ollama-colab-setup-with-litellm-guide.md) for details.
|
79 |
+
- [📒Notebook here](https://colab.research.google.com/drive/1buTPds1Go1NbZOLlpG94VG22GyK-F4GW?usp=sharing)
|
80 |
|
|
|
81 |
|
82 |
## 🛠️ Environment Setup
|
83 |
|
|
|
87 |
cd Llama-finetune-sandbox
|
88 |
```
|
89 |
|
90 |
+
## 📝 Adding Implementation Examples
|
91 |
|
92 |
1. Add new implementations to the `examples/` directory.
|
93 |
2. Add necessary settings and utilities to `utils/`.
|
|
|
104 |
## 📚 References
|
105 |
|
106 |
- [HuggingFace PEFT Documentation](https://huggingface.co/docs/peft)
|
107 |
+
- [About Llama models](https://github.com/facebookresearch/llama)
|
108 |
+
- [Fine-tuning best practices](https://github.com/Sunwood-ai-labs/Llama-finetune-sandbox/wiki)
|
109 |
|
110 |
+
## 📄 License
|
111 |
|
112 |
+
This project is licensed under the MIT License.
|
113 |
+
```
|
sandbox/llm-evaluator-notebook (1).md
ADDED
@@ -0,0 +1,469 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# LLM評価システム実装ガイド
|
2 |
+
|
3 |
+
## はじめに
|
4 |
+
|
5 |
+
このノートブックでは、LLM(大規模言語モデル)の回答品質を自動的に評価するためのシステムを実装します。このシステムは、質問、模範解答、LLMの回答を比較し、4段階のスケールで評価を行います。
|
6 |
+
|
7 |
+
### 目的
|
8 |
+
- LLMの回答品質を定量的に評価する
|
9 |
+
- 評価プロセスを自動化し、大規模なデータセットの処理を可能にする
|
10 |
+
- 評価結果を分析可能な形式で出力する
|
11 |
+
|
12 |
+
|
13 |
+
### 評価基準
|
14 |
+
システムは以下の4段階スケールで評価を行います:
|
15 |
+
- **4点**: 優れた回答(完全で詳細な回答)
|
16 |
+
- **3点**: おおむね役立つ回答(改善の余地あり)
|
17 |
+
- **2点**: あまり役に立たない回答(重要な側面の欠落)
|
18 |
+
- **1点**: 全く役に立たない回答(無関係または不十分)
|
19 |
+
|
20 |
+
### 必要要件
|
21 |
+
- Python 3.7以上
|
22 |
+
- Google Colab環境
|
23 |
+
- Gemini API Key
|
24 |
+
- 評価対象のQAデータセット(JSON形式)
|
25 |
+
|
26 |
+
それでは、実装の詳細に進みましょう。
|
27 |
+
|
28 |
+
## 1. 環境セットアップ
|
29 |
+
|
30 |
+
必要なライブラリをインストールします。
|
31 |
+
|
32 |
+
```python
|
33 |
+
!pip install litellm tqdm loguru
|
34 |
+
```
|
35 |
+
|
36 |
+
必要なライブラリをインポートします。
|
37 |
+
|
38 |
+
```python
|
39 |
+
import json
|
40 |
+
import pandas as pd
|
41 |
+
from litellm import completion
|
42 |
+
import os
|
43 |
+
from tqdm import tqdm
|
44 |
+
import time
|
45 |
+
from google.colab import userdata
|
46 |
+
from loguru import logger
|
47 |
+
import sys
|
48 |
+
from functools import wraps
|
49 |
+
```
|
50 |
+
|
51 |
+
## 2. ユーティリティ関数の実装
|
52 |
+
|
53 |
+
### 2.1 リトライデコレータの実装
|
54 |
+
|
55 |
+
エラーハンドリングとリトライ機能を提供するデコレータクラスを実装します。
|
56 |
+
|
57 |
+
```python
|
58 |
+
def retry_on_error(max_retries=5, wait_time=30):
|
59 |
+
"""
|
60 |
+
関数実行時のエラーを処理し、指定回数リトライするデコレータ
|
61 |
+
|
62 |
+
Args:
|
63 |
+
max_retries (int): 最大リトライ回数
|
64 |
+
wait_time (int): リトライ間隔(秒)
|
65 |
+
|
66 |
+
Returns:
|
67 |
+
function: デコレートされた関数
|
68 |
+
"""
|
69 |
+
def decorator(func):
|
70 |
+
@wraps(func)
|
71 |
+
def wrapper(*args, **kwargs):
|
72 |
+
for attempt in range(max_retries):
|
73 |
+
try:
|
74 |
+
return func(*args, **kwargs)
|
75 |
+
except Exception as e:
|
76 |
+
if attempt == max_retries - 1:
|
77 |
+
logger.error(f"最大リトライ回数に達しました: {str(e)}")
|
78 |
+
raise
|
79 |
+
logger.warning(f"エラーが発生しました。{wait_time}秒後にリトライします。(試行 {attempt + 1}/{max_retries}): {str(e)}")
|
80 |
+
time.sleep(wait_time)
|
81 |
+
return None
|
82 |
+
return wrapper
|
83 |
+
return decorator
|
84 |
+
```
|
85 |
+
|
86 |
+
## 3. 評価システムのコアコンポーネント
|
87 |
+
|
88 |
+
### 3.1 プロンプト管理クラス
|
89 |
+
|
90 |
+
評価に使用するプロンプトを管理するクラスを実装します。
|
91 |
+
|
92 |
+
```python
|
93 |
+
class EvaluationPrompts:
|
94 |
+
"""評価プロンプトを管理するクラス"""
|
95 |
+
|
96 |
+
@staticmethod
|
97 |
+
def get_judge_prompt():
|
98 |
+
return """
|
99 |
+
あなたはLLMの回答を評価する審査員です。
|
100 |
+
質問と模範解答、そしてLLMの回答のセットを評価してください。
|
101 |
+
|
102 |
+
評価は1から4の整数スケールで行ってください:
|
103 |
+
1: 全く役に立たない回答:質問に対して無関係か、部分的すぎる
|
104 |
+
2: あまり役に立たない回答:質問の重要な側面を見落としている
|
105 |
+
3: おおむね役立つ回答:支援を提供しているが、改善の余地がある
|
106 |
+
4: 優れた回答:関連性があり、直接的で、詳細で、質問で提起されたすべての懸念に対応している
|
107 |
+
|
108 |
+
以下のフォーマットで評価を提供してください:
|
109 |
+
|
110 |
+
Feedback:::
|
111 |
+
評価理由: (評価の根拠を説明してください)
|
112 |
+
総合評価: (1から4の整数で評価してください)
|
113 |
+
|
114 |
+
これから質問、模範解答、LLMの回答を提示します:
|
115 |
+
|
116 |
+
質問: {question}
|
117 |
+
模範解答: {correct_answer}
|
118 |
+
LLMの回答: {llm_answer}
|
119 |
+
|
120 |
+
フィードバックをお願いします。
|
121 |
+
Feedback:::
|
122 |
+
評価理由: """
|
123 |
+
```
|
124 |
+
|
125 |
+
### 3.2 評価結果パーサークラス
|
126 |
+
|
127 |
+
```python
|
128 |
+
class EvaluationParser:
|
129 |
+
"""評価結果を解析するクラス"""
|
130 |
+
|
131 |
+
@staticmethod
|
132 |
+
def extract_score(response_text):
|
133 |
+
"""
|
134 |
+
評価テキストからスコアを抽出する
|
135 |
+
|
136 |
+
Args:
|
137 |
+
response_text (str): 評価テキスト
|
138 |
+
|
139 |
+
Returns:
|
140 |
+
int or None: 抽出されたスコア
|
141 |
+
"""
|
142 |
+
try:
|
143 |
+
score_text = response_text.split("総合評価:")[1].strip()
|
144 |
+
score = int(score_text.split()[0])
|
145 |
+
return score
|
146 |
+
except:
|
147 |
+
logger.error(f"スコア抽出に失敗しました: {response_text}")
|
148 |
+
return None
|
149 |
+
|
150 |
+
@staticmethod
|
151 |
+
def extract_reason(evaluation_text):
|
152 |
+
"""
|
153 |
+
評価テキストから評価理由を抽出する
|
154 |
+
|
155 |
+
Args:
|
156 |
+
evaluation_text (str): 評価テキスト
|
157 |
+
|
158 |
+
Returns:
|
159 |
+
str: 抽出された評価理由
|
160 |
+
"""
|
161 |
+
try:
|
162 |
+
reason = evaluation_text.split("評価理由:")[1].split("総合評価:")[0].strip()
|
163 |
+
return reason
|
164 |
+
except:
|
165 |
+
logger.warning("評価理由の抽出に失敗しました")
|
166 |
+
return ""
|
167 |
+
```
|
168 |
+
|
169 |
+
### 3.3 LLM評価クラス
|
170 |
+
|
171 |
+
```python
|
172 |
+
class LLMEvaluator:
|
173 |
+
"""LLMの回答を評価するメインクラス"""
|
174 |
+
|
175 |
+
def __init__(self, model_name="gemini/gemini-pro"):
|
176 |
+
"""
|
177 |
+
評価器を初期化する
|
178 |
+
|
179 |
+
Args:
|
180 |
+
model_name (str): 使用するLLMモデル名
|
181 |
+
"""
|
182 |
+
self.model_name = model_name
|
183 |
+
self.prompts = EvaluationPrompts()
|
184 |
+
self.parser = EvaluationParser()
|
185 |
+
logger.info(f"評価器を初期化しました。使用モデル: {model_name}")
|
186 |
+
|
187 |
+
@retry_on_error()
|
188 |
+
def evaluate_response(self, question, correct_answer, llm_answer):
|
189 |
+
"""
|
190 |
+
個々の回答を評価する
|
191 |
+
|
192 |
+
Args:
|
193 |
+
question (str): 質問
|
194 |
+
correct_answer (str): 模範解答
|
195 |
+
llm_answer (str): LLMの回答
|
196 |
+
|
197 |
+
Returns:
|
198 |
+
dict: 評価結果
|
199 |
+
"""
|
200 |
+
prompt = self.prompts.get_judge_prompt().format(
|
201 |
+
question=question,
|
202 |
+
correct_answer=correct_answer,
|
203 |
+
llm_answer=llm_answer
|
204 |
+
)
|
205 |
+
|
206 |
+
try:
|
207 |
+
response = completion(
|
208 |
+
model=self.model_name,
|
209 |
+
messages=[{"role": "user", "content": prompt}]
|
210 |
+
)
|
211 |
+
evaluation = response.choices[0].message.content
|
212 |
+
score = self.parser.extract_score(evaluation)
|
213 |
+
|
214 |
+
if score:
|
215 |
+
logger.debug(f"評価完了 - スコア: {score}")
|
216 |
+
|
217 |
+
return {
|
218 |
+
'score': score,
|
219 |
+
'evaluation': evaluation
|
220 |
+
}
|
221 |
+
except Exception as e:
|
222 |
+
logger.error(f"評価中にエラーが発生しました: {str(e)}")
|
223 |
+
raise
|
224 |
+
|
225 |
+
@retry_on_error()
|
226 |
+
def evaluate_dataset(self, json_file_path, output_file="evaluation_results.json"):
|
227 |
+
"""
|
228 |
+
データセット全体を評価する
|
229 |
+
|
230 |
+
Args:
|
231 |
+
json_file_path (str): 評価対象のJSONファイルパス
|
232 |
+
output_file (str): 評価結果の出力先ファイルパス
|
233 |
+
|
234 |
+
Returns:
|
235 |
+
dict: 評価結果と分析データを含む辞書
|
236 |
+
"""
|
237 |
+
logger.info(f"データセット評価を開始します: {json_file_path}")
|
238 |
+
|
239 |
+
with open(json_file_path, 'r', encoding='utf-8') as f:
|
240 |
+
data = json.load(f)
|
241 |
+
|
242 |
+
results = []
|
243 |
+
qa_pairs = data['qa_pairs_simple']
|
244 |
+
total_pairs = len(qa_pairs)
|
245 |
+
|
246 |
+
logger.info(f"合計 {total_pairs} 件のQAペアを評価します")
|
247 |
+
|
248 |
+
progress_bar = tqdm(qa_pairs, desc="評価進捗", unit="件")
|
249 |
+
for qa in progress_bar:
|
250 |
+
eval_result = self.evaluate_response(
|
251 |
+
qa['question'],
|
252 |
+
qa['correct_answer'],
|
253 |
+
qa['llm_answer']
|
254 |
+
)
|
255 |
+
|
256 |
+
if eval_result:
|
257 |
+
results.append({
|
258 |
+
'question': qa['question'],
|
259 |
+
'correct_answer': qa['correct_answer'],
|
260 |
+
'llm_answer': qa['llm_answer'],
|
261 |
+
'score': eval_result['score'],
|
262 |
+
'evaluation': eval_result['evaluation']
|
263 |
+
})
|
264 |
+
|
265 |
+
# 進捗状況を更新
|
266 |
+
progress_bar.set_postfix(
|
267 |
+
completed=f"{len(results)}/{total_pairs}",
|
268 |
+
last_score=eval_result['score']
|
269 |
+
)
|
270 |
+
|
271 |
+
time.sleep(1) # API制限考慮
|
272 |
+
|
273 |
+
# 結果を分析
|
274 |
+
scores = [r['score'] for r in results if r['score'] is not None]
|
275 |
+
analysis = {
|
276 |
+
'total_evaluations': len(results),
|
277 |
+
'average_score': sum(scores) / len(scores) if scores else 0,
|
278 |
+
'score_distribution': {
|
279 |
+
'1': scores.count(1),
|
280 |
+
'2': scores.count(2),
|
281 |
+
'3': scores.count(3),
|
282 |
+
'4': scores.count(4)
|
283 |
+
}
|
284 |
+
}
|
285 |
+
|
286 |
+
# 分析結果をログに出力
|
287 |
+
logger.success("評価が完了しました")
|
288 |
+
logger.info(f"総評価数: {analysis['total_evaluations']}")
|
289 |
+
logger.info(f"平均スコア: {analysis['average_score']:.2f}")
|
290 |
+
logger.info("スコア分布:")
|
291 |
+
for score, count in analysis['score_distribution'].items():
|
292 |
+
percentage = (count / len(scores) * 100) if scores else 0
|
293 |
+
logger.info(f"スコア {score}: {count}件 ({percentage:.1f}%)")
|
294 |
+
|
295 |
+
# 結果をJSONとして保存
|
296 |
+
output_data = {
|
297 |
+
'analysis': analysis,
|
298 |
+
'detailed_results': results
|
299 |
+
}
|
300 |
+
|
301 |
+
with open(output_file, 'w', encoding='utf-8') as f:
|
302 |
+
json.dump(output_data, f, ensure_ascii=False, indent=2)
|
303 |
+
|
304 |
+
logger.info(f"評価結果を保存しました: {output_file}")
|
305 |
+
return output_data
|
306 |
+
```
|
307 |
+
|
308 |
+
### 3.4 データエクスポートクラス
|
309 |
+
|
310 |
+
```python
|
311 |
+
class ResultExporter:
|
312 |
+
"""評価結果をエクスポートするクラス"""
|
313 |
+
|
314 |
+
@staticmethod
|
315 |
+
def export_to_csv(evaluation_results, output_file="evaluation_results.csv"):
|
316 |
+
"""
|
317 |
+
評価結果をCSVファイルに出力する
|
318 |
+
|
319 |
+
Args:
|
320 |
+
evaluation_results (dict): 評価結果
|
321 |
+
output_file (str): 出力ファイルパス
|
322 |
+
|
323 |
+
Returns:
|
324 |
+
pd.DataFrame: 出力したデータフレーム
|
325 |
+
"""
|
326 |
+
logger.info("CSV出力を開始します")
|
327 |
+
results = evaluation_results['detailed_results']
|
328 |
+
parser = EvaluationParser()
|
329 |
+
|
330 |
+
csv_data = []
|
331 |
+
for result in results:
|
332 |
+
csv_data.append({
|
333 |
+
'質問': result['question'],
|
334 |
+
'正解': result['correct_answer'],
|
335 |
+
'LLMの回答': result['llm_answer'],
|
336 |
+
'評価理由': parser.extract_reason(result['evaluation']),
|
337 |
+
'総合評価': result['score']
|
338 |
+
})
|
339 |
+
|
340 |
+
df = pd.DataFrame(csv_data)
|
341 |
+
df.to_csv(output_file, index=False, encoding='utf-8-sig')
|
342 |
+
|
343 |
+
logger.success(f"CSVファイルを出力しました: {output_file}")
|
344 |
+
return df
|
345 |
+
```
|
346 |
+
|
347 |
+
### 3.5 レポート生成クラス
|
348 |
+
|
349 |
+
```python
|
350 |
+
class ReportGenerator:
|
351 |
+
"""評価レポートを生成するクラス"""
|
352 |
+
|
353 |
+
@staticmethod
|
354 |
+
def generate_html_report(evaluation_results, model_name, output_file="evaluation_report.html"):
|
355 |
+
"""
|
356 |
+
HTML形式の評価レポートを生成する
|
357 |
+
|
358 |
+
Args:
|
359 |
+
evaluation_results (dict): 評価結果
|
360 |
+
model_name (str): 評価に使用したモデル名
|
361 |
+
output_file (str): 出力ファイルパス
|
362 |
+
"""
|
363 |
+
logger.info("HTMLレポート生成を開始します")
|
364 |
+
|
365 |
+
analysis = evaluation_results['analysis']
|
366 |
+
results = evaluation_results['detailed_results']
|
367 |
+
df = pd.DataFrame(results)
|
368 |
+
|
369 |
+
html_content = f"""
|
370 |
+
<html>
|
371 |
+
<head>
|
372 |
+
<title>LLM Evaluation Report</title>
|
373 |
+
<style>
|
374 |
+
body {{ font-family: Arial, sans-serif; margin: 20px; }}
|
375 |
+
.summary {{ background-color: #f0f0f0; padding: 20px; margin-bottom: 20px; }}
|
376 |
+
.distribution {{ margin-bottom: 20px; }}
|
377 |
+
table {{ border-collapse: collapse; width: 100%; }}
|
378 |
+
th, td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
|
379 |
+
th {{ background-color: #4CAF50; color: white; }}
|
380 |
+
tr:nth-child(even) {{ background-color: #f2f2f2; }}
|
381 |
+
</style>
|
382 |
+
</head>
|
383 |
+
<body>
|
384 |
+
<h1>LLM Evaluation Report</h1>
|
385 |
+
|
386 |
+
<div class="summary">
|
387 |
+
<h2>Summary</h2>
|
388 |
+
<p>Total Evaluations: {analysis['total_evaluations']}</p>
|
389 |
+
<p>Average Score: {analysis['average_score']:.2f}</p>
|
390 |
+
<p>Model: {model_name}</p>
|
391 |
+
</div>
|
392 |
+
|
393 |
+
<div class="distribution">
|
394 |
+
<h2>Score Distribution</h2>
|
395 |
+
<table>
|
396 |
+
<tr>
|
397 |
+
<th>Score</th>
|
398 |
+
<th>Count</th>
|
399 |
+
<th>Percentage</th>
|
400 |
+
</tr>
|
401 |
+
{''.join(f'<tr><td>{score}</td><td>{count}</td><td>{(count/analysis["total_evaluations"]*100):.1f}%</td></tr>'
|
402 |
+
for score, count in analysis['score_distribution'].items())}
|
403 |
+
</table>
|
404 |
+
</div>
|
405 |
+
|
406 |
+
<div class="details">
|
407 |
+
<h2>Detailed Results</h2>
|
408 |
+
{df.to_html()}
|
409 |
+
</div>
|
410 |
+
</body>
|
411 |
+
</html>
|
412 |
+
"""
|
413 |
+
|
414 |
+
with open(output_file, 'w', encoding='utf-8') as f:
|
415 |
+
f.write(html_content)
|
416 |
+
|
417 |
+
logger.success(f"HTMLレポートを生成しました: {output_file}")
|
418 |
+
```
|
419 |
+
|
420 |
+
## 4. メイン実行部分
|
421 |
+
|
422 |
+
```python
|
423 |
+
def main():
|
424 |
+
# APIキーの設定
|
425 |
+
os.environ['GEMINI_API_KEY'] = userdata.get('GEMINI_API_KEY')
|
426 |
+
|
427 |
+
# 評価器の初期化
|
428 |
+
evaluator = LLMEvaluator(model_name="gemini/gemini-1.5-flash-latest")
|
429 |
+
|
430 |
+
try:
|
431 |
+
# データセットを評価
|
432 |
+
logger.info("評価プロセスを開始します")
|
433 |
+
results = evaluator.evaluate_dataset("qa_with_llm.json")
|
434 |
+
|
435 |
+
# 結果のエクスポート
|
436 |
+
exporter = ResultExporter()
|
437 |
+
df = exporter.export_to_csv(results)
|
438 |
+
logger.info("最初の数行のデ���タ:")
|
439 |
+
logger.info("\n" + str(df.head()))
|
440 |
+
|
441 |
+
# レポート生成
|
442 |
+
report_generator = ReportGenerator()
|
443 |
+
report_generator.generate_html_report(results, evaluator.model_name)
|
444 |
+
logger.success("すべての処理が完了しました")
|
445 |
+
|
446 |
+
except Exception as e:
|
447 |
+
logger.error(f"処理中にエラーが発生しました: {str(e)}")
|
448 |
+
raise
|
449 |
+
|
450 |
+
if __name__ == "__main__":
|
451 |
+
main()
|
452 |
+
```
|
453 |
+
|
454 |
+
## 5. 使用方法
|
455 |
+
|
456 |
+
1. Google Colabで新しいノートブックを作成します。
|
457 |
+
2. 必要なライブラリをインストールします。
|
458 |
+
3. 上記のコードを順番にセルにコピーして実行します。
|
459 |
+
4. GEMINI_API_KEYを設定します。
|
460 |
+
5. 評価したいQAデータセットのJSONファイルを用意します。
|
461 |
+
6. メイン実行部分を実行します。
|
462 |
+
|
463 |
+
## 6. 注意点
|
464 |
+
|
465 |
+
- 評価には時間がかかる場合があります。
|
466 |
+
- API制限に注意してください。
|
467 |
+
- データセットは指定のJSON形式に従う必要があります。
|
468 |
+
- エラー発生時は自動的にリトライします。
|
469 |
+
|