File size: 8,202 Bytes
294bfa9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# WikipediaデータからLlama 3.1用Q&Aデータセット生成ツールの解説( Google Colabノートブック付)

## はじめに

このツールは、Wikipediaの記事からLlama 3.1のファインチューニング用Q&Aデータセットを自動生成するためのものです。生成されたデータセットは、Llama 3.1の会話形式に準拠しており、高品質な学習データとして活用できます。

## システム構成

このツールは以下の4つの主要クラスで構成されています:

1. WikiTextProcessor - Wikipedia記事の取得と前処理
2. QAGenerator - Q&Aペアの生成とLlama形式への変換
3. QualityChecker - 生成されたQ&Aペアの品質管理
4. DatasetCreator - 全体のプロセス管理

## セットアップと環境構築

### 必要なライブラリのインストール

```python
!pip install litellm tqdm loguru wikipedia
```

### モデルの設定

```python
MODEL_NAME = "ollama/llama3.1:8b-instruct-fp16"
```

## 主要コンポーネントの解説

### WikiTextProcessor クラス

このクラスはWikipediaのテキストデータを取得し、適切な形式に加工します。

```python
class WikiTextProcessor:
    @staticmethod
    def get_wiki_text(topic: str, lang: str = "ja") -> str:
        """指定されたトピックのWikipedia記事を取得"""
        wikipedia.set_lang(lang)
        try:
            page = wikipedia.page(topic)
            return page.content
        except Exception as e:
            logger.error(f"Error fetching {topic}: {e}")
            return ""
            
    @staticmethod
    def clean_text(text: str) -> str:
        """テキストのクリーニング"""
        import re
        text = re.sub(r'\[\d+\]', '', text)
        text = re.sub(r'\n\s*\n', '\n', text)
        return text.strip()
        
    @staticmethod
    def split_into_chunks(text: str, max_chunk_size: int = 200) -> List[str]:
        """テキストを意味のある単位で分割"""
        sentences = text.split('。')
        chunks = []
        current_chunk = []
        current_size = 0
        
        for sentence in sentences:
            sentence_size = len(sentence) + 1
            if current_size + sentence_size > max_chunk_size and current_chunk:
                chunks.append('。'.join(current_chunk) + '。')
                current_chunk = [sentence]
                current_size = sentence_size
            else:
                current_chunk.append(sentence)
                current_size += sentence_size
                
        if current_chunk:
            chunks.append('。'.join(current_chunk) + '。')
            
        return chunks
```

このクラスの主な機能:
- Wikipedia記事の取得
- テキストのクリーニング(参照記号の除去など)
- 長い記事の適切なサイズへの分割

### QAGenerator クラス

Q&Aペアの生成とLlama形式への変換を担当します。

```python
class QAGenerator:
    @staticmethod
    def generate_qa_pairs_with_retry(
        chunk: str,
        num_pairs: int = 5,
        max_retries: int = 3,
        base_delay: int = 2
    ) -> List[Dict[str, str]]:
        prompt = f"""
        以下のテキストから質問と回答のペアを{num_pairs}つ生成してください。
        必ず以下の条件をすべて満たすJSONを出力してください:

        1. 厳密なJSON形式で出力(最後の要素にもカンマをつけない)
        2. すべての質問は日本語で記述
        3. すべての質問は「?」で終わる
        4. 回答は500文字以下
        5. 回答は必ずテキストの中に記載されている内容にして

        テキスト:
        {chunk}

        出力形式:
        {{
            "qa_pairs": [
                {{"question": "質問1?", "answer": "回答1"}},
                {{"question": "質問2?", "answer": "回答2"}},
                {{"question": "質問3?", "answer": "回答3"}}
            ]
        }}
        """
        # ... リトライロジックの実装 ...
```

主な機能:
- Q&Aペアの生成(リトライ機能付き)
- JSONからの応答抽出
- エラー処理と再試行メカニズム

### QualityChecker クラス

生成されたQ&Aペアの品質管理を行います。

```python
class QualityChecker:
    @staticmethod
    def validate_qa_pair(qa_pair: Dict[str, str]) -> bool:
        """Q&Aペアの品質チェック"""
        MIN_QUESTION_LENGTH = 10
        MIN_ANSWER_LENGTH = 20
        MAX_ANSWER_LENGTH = 500

        if not all(key in qa_pair for key in ['question', 'answer']):
            return False

        question = qa_pair['question']
        answer = qa_pair['answer']

        if not question or not answer:
            return False

        if len(question) < MIN_QUESTION_LENGTH:
            return False
        if len(answer) < MIN_ANSWER_LENGTH or len(answer) > MAX_ANSWER_LENGTH:
            return False
        if not question.endswith('?'):
            return False

        return True
```

主な機能:
- Q&Aペアの長さと形式の検証
- コンテンツの多様性チェック
- 重複検出

## データセット生成プロセス

### DatasetCreator クラス

全体のプロセスを管理し、データセットの生成を制御します。

```python
class DatasetCreator:
    def __init__(self):
        self.wiki_processor = WikiTextProcessor()
        self.qa_generator = QAGenerator()
        self.quality_checker = QualityChecker()
        
    def create_dataset(self, topics: List[str], output_file: str = "training_data.json") -> None:
        all_formatted_data = []
        
        for topic_idx, topic in enumerate(topics, 1):
            text = self.wiki_processor.get_wiki_text(topic)
            if not text:
                continue
                
            text = self.wiki_processor.clean_text(text)
            chunks = self.wiki_processor.split_into_chunks(text)
            
            for chunk in chunks:
                qa_pairs = self.qa_generator.generate_qa_pairs_with_retry(chunk)
                qa_pairs = [qa for qa in qa_pairs if self.quality_checker.validate_qa_pair(qa)]
                
                if self.quality_checker.check_diversity(qa_pairs):
                    formatted_data = self.qa_generator.format_for_llama(qa_pairs)
                    all_formatted_data.extend(formatted_data)
                    
        with open(output_file, 'w', encoding='utf-8') as f:
            json.dump(all_formatted_data, f, ensure_ascii=False, indent=2)
```

## Hugging Faceへのデータセットアップロード

生成したデータセットをHugging Faceにアップロードする機能も実装されています。

```python
def create_and_upload_dataset(data_dict, dataset_name, username):
    dataset = Dataset.from_dict(data_dict)
    dataset_dict = dataset.train_test_split(test_size=0.1, seed=42)
    repo_id = f"{username}/{dataset_name}"
    
    try:
        dataset_dict.push_to_hub(
            repo_id=repo_id,
        )
        logger.success(f"Dataset uploaded successfully to: https://huggingface.co/datasets/{repo_id}")
    except Exception as e:
        logger.error(f"Error uploading dataset: {e}")
        raise
```

## 使用方法

1. 環境のセットアップ
```python
!pip install datasets huggingface-hub
```

2. トピックリストの定義
```python
topics = ["霊烏路空"]
```

3. データセット生成の実行
```python
creator = DatasetCreator()
creator.create_dataset(topics, "llama_training_data.json")
```

## おわりに

このツールを使用することで、Wikipediaの記事から高品質なQ&Aデータセットを自動生成し、Llama 3.1のファインチューニングに使用することができます。生成されたデータセットは自動的にHugging Faceにアップロードされ、共有や再利用が容易になっています。

## Google Colabノートブック

https://colab.research.google.com/drive/1mmK5vxUzjk3lI6OnEPrQqyjSzqsEoXpk?usp=sharing

## リポジトリ

https://github.com/Sunwood-ai-labs/Llama-finetune-sandbox