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