Few-shot promptingを使った出力フォーマットの操り方
はじめに
はじめまして、WingArc1stのmatskenと申します。
みなさん、生成AI使ってますか?ChatGPTをはじめとした生成AIは、今や多くのエンジニアにとって、欠かせないものになっているかと思います。一方で、ガートナーのハイプ・サイクルによると、2024年8月6日時点で生成AIは「過度な期待」から「幻滅期」に差し掛かろうとしているフェーズに来ており、多くの期待を背負っている反面、実務上では短所や限界が見えてきているのではないでしょうか。
生成AIの出力フォーマットは、そんな悩みのタネの一つだと思います。いくら生成AIに出力フォーマットに関するプロンプトを与えても、それに沿わない出力が生成されたり、不要な一文が先頭に入ったり、という経験、皆さんもありませんか?
OpenAIが2024年8月6日に発表したstructured outputを利用すると、JSON出力に関してはかなり厳密に出力フォーマットをコントロールできるようになりましたが、JSON以外の出力は、依然としてゆらぎが多いのが現状です。
https://openai.com/index/introducing-structured-outputs-in-the-api/
生成AIの出力フォーマット問題
まずはOpenAIの gpt-4o-mini-2024-07-18 モデルを使って、以下のプロンプトを与えてみます:
{
role: "user",
content: `あなたは有能な料理レシピのアシスタントです。与えられた食材を主に利用するレシピを3つ教えて下さい。出力にはマークダウン記法を利用してください。
食材:トマト`
}
このような結果になりました:
もちろんです!トマトを主に利用した料理レシピを3つご紹介します。
### 1. トマトのカプレーゼサラダ
#### 材料
- フレッシュモッツァレラチーズ:150g
- トマト:2個
- バジルの葉:適量
- オリーブオイル:大さじ2
- 塩:少々
- 黒胡椒:少々
#### 作り方
1. トマトをスライスし、モッツァレラチーズも同様にスライスします。
2. お皿にトマトとモッツァレラを交互に重ねて並べます。
3. バジルの葉を散らします。
4. オリーブオイルを全体にかけ、塩と黒胡椒で味を調えたら完成です。
---
### 2. トマトのリゾット
#### 材料
- アルボリオ米:200g
- トマト(中サイズ):3個
- 玉ねぎ:1個
- ニンニク:1片
- チキンブイヨン:500ml
- パルメザンチーズ:30g
- オリーブオイル:大さじ2
- 塩:適量
- 黒胡椒:適量
#### 作り方
1. トマトは湯むきして、角切りにします。
2. 玉ねぎとニンニクをみじん切りにします。
3. 中火にした鍋にオリーブオイルを熱し、玉ねぎとニンニクを炒めます。
4. 玉ねぎが透明になったら、アルボリオ米を加え、全体を軽く炒めます。
5. トマトを加え、全体がしんなりするまでさらに炒めます。
6. チキンブイヨンを少しずつ加えながら、米がアルデンテになるまで約18分煮ます。
7. 火を止めてパルメザンチーズを加え、塩と黒胡椒で味を調えたら完成です。
---
### 3. トマトソースパスタ
#### 材料
- パスタ:200g
- トマト(中サイズ):4個
- 玉ねぎ:1個
- ニンニク:2片
- オリーブオイル:大さじ2
- バジル(乾燥または生):適量
- 塩:適量
- 黒胡椒:適量
#### 作り方
1. トマトはざく切りにし、玉ねぎとニンニクはみじん切りにします。
2. 鍋にオリーブオイルを熱し、玉ねぎとニンニクを炒め、香りが立ったらトマトを加えます。
3. 中火でトマトが崩れるまで煮込み、バジル、塩、黒胡椒で味を調えます。
4. パスタを表示通りに茹で、茹で上がったらソースと和えます。
5. お皿に盛り付けて、お好みでバジルをトッピングしたら完成です。
---
これらのレシピを参考にして、美味しいトマト料理を楽しんでください!
今回はマークダウン記法を指定したので、ある程度のフォーマットの差異は吸収できてしまいますが、最初の一行と最後の一行は、明らかに本文とは別の文が入っているのがわかります。「もちろんです!」など、明らかに生成AIらしい一文ですね。
Few-shot promptingを使うと、このような不要な文を出力させないようにしたり、より開発者の意図に沿った出力にすることができるようになります。
Few-shot prompting
Few-shot promptingとは、生成AIが普及し始めた初期の頃から存在する、比較的古典的なプロンプト・エンジニアリングの手法です。手法としては至って簡単で、ユーザーとアシスタント(生成AI)の対話の例を、最初からプロンプトに埋め込んでしまう、というものです。原理としては非常に単純なのですが、複数のメッセージを一つのプロンプトに埋め込むという性質上、APIからの利用に限定されるため、あまり馴染みのない方も多いかもしれません。詳しくはこちらのページなどを御覧ください:
対して、先程の例のプロンプトは、すべての情報を一つのメッセージとして生成AIに問い合わせるもので、zero-shot promptingとも呼ばれます。
Few-shot promptの実例
先程の例を、few-shot promptingの手法を使うとこのようなプロンプトになります:
messages: [
{
role: "system",
content: "あなたは有能な料理レシピのアシスタントです。与えられた食材を主に利用するレシピを3つ教えて下さい。出力にはマークダウン記法を利用してください。"
},
{ role: "user", content: "トマト" },
{
role: "assistant",
content: `
### トマトを使うレシピ
1. トマトのカプレーゼ
2. トマトのリゾット
3. トマトソースパスタ
`
},
{ role: "user", content: "玉ねぎ" }
]
まずは、このプロンプトの中身を詳しく見ていきたいと思います。
このプロンプトは、4つのメッセージで構成されています。
1つ目はシステムプロンプトで、アシスタントの役割や振る舞いを指示するものです:
{
role: "system",
content: "あなたは有能な料理レシピのアシスタントです。与えられた食材を主に利用するレシピを3つ教えて下さい。出力にはマークダウン記法を利用してください。"
}
2つ目は、few-shot promptingの肝となる、「やりとりの例」のうち、ユーザープロンプトを模したものです:
{ role: "user", content: "トマト" }
3つ目は、「やり取りの例」のうち、アシスタントからの返答を模したものです。自分でアシスタントの返答例を作ってしまうことで、これ以降のアシスタントの出力が、これに似たものとなります:
{
role: "assistant",
content: `
### トマトを使うレシピ
1. トマトのカプレーゼ
2. トマトのリゾット
3. トマトソースパスタ
`
}
そして最後の4つ目は、実際のユーザープロンプトです。現実的ユースケースだと、ここにユーザーからの入力が入ることになります:
{ role: "user", content: "玉ねぎ" }
今回は、やり取りの例を1ペアだけ使いましたが、その名のとおり few shot ということで、やり取りの例のペアを複数指定することもでき、そうすることで精度の向上が見込める場合もあります。
そして出力はこのようになりました:
### 玉ねぎを使ったレシピ
1. **玉ねぎのオニオンスープ**
- **材料**: 玉ねぎ、バター、ブイヨン、塩、胡椒、パン、チーズ
- **作り方**:
1. 玉ねぎを薄切りにし、バターを溶かした鍋でじっくり炒める。
2. 玉ねぎが caramelizationされるまで炒めたら、ブイヨンと水を加える。
3. 中火で煮込み、塩と胡椒で味を調える。
4. 耐熱皿にスープとパンを入れ、上にチーズを乗せてオーブンで焼く。
2. **玉ねぎのマリネ**
- **材料**: 玉ねぎ、酢、オリーブオイル、塩、胡椒、ハーブ(お好みで)
- **作り方**:
1. 玉ねぎを薄切りにする。
2. ボウルに酢、オリーブオイル、塩、胡椒を混ぜる。
3. 玉ねぎを加え、全体をよく混ぜる。
4. 冷蔵庫で30分以上マリネしてから提供する。
3. **玉ねぎとひき肉の炒め物**
- **材料**: 玉ねぎ、ひき肉(豚肉または牛肉)、醤油、砂糖、豆板醤(お好みで)
- **作り方**:
1. 玉ねぎを薄切りにし、フライパンで炒める。
2. 玉ねぎが透明になったらひき肉を加え、火が通るまで炒める。
3. 醤油と砂糖、豆板醤を加えてさらに炒める。
4. ご飯にかけてボリューム満点の一品に。
これらのレシピは、人気の食材である玉ねぎを活かした美味しい料理です。お楽しみください!
まず、最初の不要な一文が省かれているのがわかります。最後の一文はまだありますが、ここはプロンプトを工夫するなどして対応できるかもしれません。
また、返答例をかなり簡潔にしたこともあり、今回の出力は、最初の出力の半分程度の長さになっています。このように、few-shot promptingを使うと、フォーマットだけではなく、長さや内容に関しても、ある程度操作することが可能になります。
そろそろおなかがすいてきましたね!
まとめ
今回は、few-shot promptingというプロンプト・エンジニアリングの手法を使って、生成AIの出力フォーマットを操作する方法をご紹介しました。Few-shot promptingは、出力フォーマットの操作だけではなく、出力そのものの精度向上にも使えますので、みなさんも是非試してみてください。
この記事が気に入ったらサポートをしてみませんか?