【Evol-Instruct】機械的にプロンプトを進化させ、LLM の学習データを作成する方法

# Evol instruct とは？

Evol-Instruct は LLM 学習用のデータセットを自動で生成する手法です。
データの生成はベースとなる単純な指示からスタートし、**深さ進化**と**幅進化**の両方を組み合わせて、データの複雑さや多様性を向上させつつ、進化に失敗した指示を削除したりします。

なお、この手法を用いて作られたのが WizardLM のような Wizard 系のモデルですが、ベースの Llama 2 に比べて複雑な指示を遂行する能力が向上しています。



```plantuml
@startuml
<style>
root {
  Padding 0
  Margin 0
}
footer {
  FontColor black
  FontSize 17
}
</style>
footer  Evol-Insturct のイメージ図\n(出典：WizardLM: Empowering Large Language Models to Follow Complex Instructions)
title <img:https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/758571/35af4831-a706-6889-3239-4ee82674dfc9.png>
@enduml
```



## 具体的な方法

Evol-Insturct には、以下の二つの機能があります。
1. Insturction Evolver (指示データ進化機能)
2. Instruction Eliminator (指示データ排除機能)

これらを組み合わせ、3 つのステップでデータを生成します。
1. 指示進化
1. 応答生成
1. 失敗した進化の排除


### 指示進化
ChatGPT のような性能の高い LLM を利用して、ベースとなる指示を進化していきます。
先述の通り、進化は**深さ進化**と**幅進化**の二種類があります。

それぞれでプロンプトが異なります。

#### 深さ進化
深さ進化は以下のようなプロンプトで行います。
```
プロンプトの書き換えをしてください。
あなたの目的は、与えられたプロンプトをより複雑なバージョンに書き換えて、それら有名なAIシステム（例：ChatGPTやGPT4）を少し取り扱いにくくすることです。
しかし、書き換えられたプロンプトは合理的で、人間に理解され、対応されなければなりません。
書き換える際には、#Given Prompt#の非テキスト部分（例：表やコード）を省略しないでください。また、#Given Prompt#の入力も省略しないでください。
以下の方法を使用して与えられたプロンプトを複雑にするべきです：
#Given Prompt#にもう一つの制約/要件を加えてください。
#Rewritten Prompt#が冗長にならないように最善を尽くしてください。#Rewritten Prompt#は#Given Prompt#に10から20語を追加することができます。
‘#Given Prompt#’, ‘#Rewritten Prompt#’, ‘given prompt’, ‘rewritten prompt’は#Rewritten Prompt#には現れてはいけません。
#Given Prompt#：
<ここに指示があります。>
#Rewritten Prompt#：
```
このプロンプトの `#Given Prompt#に10から20語を追加することができます。` という制限は難易度の上昇をコントロールが目的です。各進化を「少しだけ難しく」するため、単語の追加を 10〜20 語と制限しています。

#### 幅進化
幅進化は以下のようなプロンプトで行います。
```
プロンプトクリエーターとして行動してください。
あなたの目標は、#Given Prompt#からインスピレーションを得て、まったく新しいプロンプトを作成することです。
この新しいプロンプトは#Given Prompt#と同じドメインに属している必要がありますが、さらに珍しいものでなければなりません。
#Created Prompt#の長さと難易度は#Given Prompt#と同様であるべきです。
#Created Prompt#は合理的であり、人間に理解され、応答される必要があります。
‘#Given Prompt#’, ‘#Created Prompt#’, ‘given prompt’, ‘created prompt’は#Created Prompt#には使用してはいけません。
#Given Prompt#：
<ここに指示があります。>
#Created Prompt#：
```
### 応答生成
先ほど紹介したプロンプトを用いて、指示を生成していきます。

#### 深さ進化の実例
実際に ChatGPT を使って進化させてみます。

ベースタスクは以下とします。
```
- 「彼女は青い空を見上げながら、木の下で本を読んでいました。」この文の主語は何ですか？
```
進化を 3 回繰り返すと以下のようなバリエーションが生まれました。
- 1回目：`「彼女は木陰で青い空を眺めながら、読書に耽っていました。」という情景において、文の主語は何でしょうか？`
- 2回目：`枝の間から漏れる陽光が彼女の肌を優しく撫で、彼女は木陰で心地よい風を感じながら、青い空を背景に本に没頭していました。この光景の中で、文の主語は何でしょうか？`
- 3回目：`枝の隙間から漏れる陽光が彼女の肌を柔らかく照らし、彼女は木陰に身を置きながら、微風に包まれながら、空に広がる青の無限を背景にして読書に耽っていました。この情景において、文の主語は何でしょうか？`

#### 幅進化の実例
実際に ChatGPT を使って進化させてみます。

ベースタスクは深さ進化と同様に以下とします。
```
- 「彼女は青い空を見上げながら、木の下で本を読んでいました。」この文の主語は何ですか？
```
進化を 3 回繰り返すと以下のようなバリエーションが生まれました。
- 1回目：`「島の海辺で、波の音を聞きながら、男性が砂浜に寝そべっていました。」この文の主語は何ですか？`
- 2回目：`「雨の音が背景に流れる中、街の路地裏で、黒い猫が影に隠れていました。」この文の主語は何ですか？`
- 3回目：`「森の奥深く、太陽が射す中、小さな川岸で、赤いキノコがひしめいていました。」この文の主語は何ですか？`

この例だと、幅進化は文章のバリエーションが出るのに対し、深さ進化は似たような意味の文章がどんどん修飾されている感じですね。

### 失敗した進化の排除

最後に、進化に失敗した指示を排除していきます。

進化の除去は以下の条件に従います。これらのどれかに当てはまる場合は除去していきます。
1. 進化した指示が元の指示と比べて情報利得を提供しない場合。
2. 進化した指示がLLMによる応答生成を困難にする場合。生成された応答が「申し訳ありません」と記載されており、かつ相対的に短い（つまり、80語未満）場合、LLMが進化した指示に対応することに苦労していることをしばしば示しています。したがって、このルールを使用して判断を下すことができます。
3. LLMによって生成された応答が句読点とストップワードのみを含む場合。
4. 進化した指示が「given prompt」、「rewritten prompt」、「#Rewritten Prompt#」など、進化プロンプトからいくつかの単語を明らかにコピーしている場合。

なお、1 は以下のようなプロンプトを使うことで判断できる。
```
以下はChatGPT AIへの2つの指示ですが、これらは以下の要件を満たしていると思いますか？
1. それらは同じ制約と要件を持っています。
2. それらは問いの深さと幅が同じです。
最初のプロンプト：<ここに最初の指示があります。>
二番目のプロンプト：<ここに二番目の指示があります。>
あなたの判断（答えるだけで良いです：等しい、または等しくない。理由を説明する必要はありません。）：
```

おわり。