NEXTSCAPE blog

株式会社ネクストスケープの社員による会社公式ブログです。ネスケラボでは、社員が日頃どのようなことに興味をもっているのか、仕事を通してどのような面白いことに取り組んでいるのかなど、会社や技術に関する情報をマイペースに紹介しています。

MENU

退屈なプロンプトエンジニアリングはLLMにやらせよう

こんにちは。Azureビジネス部の金重です。
 今年に入って、LLMが大流行し、個人や企業でも活用する例には枚挙にいとまがありません。また、MicrosoftではOpenAIと手を組んでAzure OpenAI Serviceというサービスが提供され、開発に言語生成AIを含む生成AIの機能を組み込むことができるようになりました。そういった背景でサービスの開発やプロンプトエンジニアリングが盛り上がってきていますが、このプロンプトエンジニアリングを自動化したい!という試みです。

★この記事は…

NEXTSCAPE Advent Calendar 2023 8日目 です。

qiita.com

背景

LLM(Azure OpenAI Service)の会話の仕組み

 Azure OpenAI Serviceを例に紹介します。LLMを用いてチャットを含めた何かしらの応答を受け取りたい場合、一般には以下の仕組みで会話を行います。

この会話文は本家ChatGPTをはじめとしたサービスでAPIが用意されており、Azure OpenAI Serviceにおいては以下の様なJson形式で会話文を送信します。

 roleは誰が話しているか?を指します。最初のsystemと記載があるアイテムはLLMに与える強い制約として、会話セッションにおけるエージェントの性格や会話の目的、語尾、文章執筆といった特定の目的の会話エージェントであること等を明示してあげることで後の会話の仕方を制限します。
 そして、userがユーザーの入力、assistantがLLMの返答として、ユーザーが会話をするとLLMが過去の会話履歴を基に返答を生成します。複数ターンの会話であれば、その会話履歴を含めることができ、例えば一度エージェントに質問をして回答が得られたときに、その回答を要約してと頼むことでより簡潔な回答を得るといったこともできます。特に、一度で大量の指示を出すとLLMは一度に解釈することが難しいらしいので、順番に指示を出してあげることが有効になりそうです。

プロンプトエンジニアリング

 そこで、ChatGPTに良い応答をしてもらうために、プロンプトエンジニアリングという技術があります。例えば、few-shot promptingという方法ではいきなり質問をするのではなく、具体例を示してその例を基に質問に答えさせます。具体的には、「太郎は飴を買って嬉しかったです。という文章はポジティブ」「花子は雨が降っていて外に出られないので悲しかったです。という文章はネガティブ」と例示した後に、「XXという文章の感情を判定してください」と質問を投げます。そうすることで、いきなりXXという文章の感情を判定してくださいと質問するよりも、判断材料が明確になったような答えを得やすくなります。

 プロンプトエンジニアリングの手法については、現段階では各々が試して得られた知見が体系化されきっておらずアップデートも激しいのでうまく語ることはできないのですが、特定のユースケースに特化したプロンプト集をまとめている方がいる他、汎用的な知見についてはMicrosoftのセミナー資料などがよくまとまっています。

プロンプトをLLM自身に考えさせてみる

 プロンプトエンジニアリング、難しい…!ということで、ユーザーが入力するプロンプト自体をLLMに考えさせてみましょう。とはいっても、一から考えさせることは非常に難しいので、本投稿では最初に簡単な指示を用意して、そこに付随する細かい制約を考えさせて、追加していきます。うまく回答を生成できるようになってくれると嬉しいですね。
 ここでの想定としては、一般の機械学習のように大量のデータを与えるよりは、レビューを2,3回繰り返すようなイメージです。というのも、評価結果を自然言語で出力するので、それに応じて具体例を直してもらう感じになりますし、一発で良い修正案を出してくれれば十分良い結果を出せるようになるはずです。
 また、自然言語の評価には従来はクラウドソーシングで人手で評価をすることが多かったのですが、最近はArXiv上でLLMの生成結果をLLM自体に評価させる手法が登場しており、進歩を感じます(機械学習関係のここ最近で一番の驚きです)。勿論Domain-spesificな課題に対してはプロが見るべきですが、一般レベルの読解力を求めるのであればLLMの方が良いのかもしれません。

実装

というわけで、全体のアーキテクチャを以下に示します。

アーキテクチャはユーザーが会話するチャットモデルとチャットモデルの出力を評価及び提案するレビューモデルから構成されます。学習段階では質問を固定してチャットモデルに質問を行います。チャットモデルがLLMを用いて返答を返すと、その結果がレビューモデルの入力になります。レビューモデルはまず、その解答とレビュー観点を基に、LLMを用いてチャットモデルの返答の良しあしを判断してレビュー結果を出力します。一度出力されたレビュー結果はそのままチャットモデルに制約として加えるのではなく、制約を提案する為にレビュー結果をLLMに投げて、その結果制約を出力してもらいます。例えば、文章が短すぎれば"文章を長くしてください"のようなものになります。最後に、この提案された制約をチャットモデルに追加するのですが、学習を回すごとに制約文がどんどん追加されるとプロンプトが無限に長くなってしまうため、指摘事項が無い場合は追加しない分岐処理を挟んだうえで、制約の要約を行います。端的にいうと、重複する内容の制約を削除してあげます。

 アーキテクチャとしては以上ですが、実際には各モデルに与えられるプロンプトの機微に影響する部分も大きいため、見ていきます。プロンプトはそれぞれ以下の通りです。今回は旅行プランを提案するエージェントとしました。こういったケースではRAGを構築して実際の旅行先データ等から最新の正しい情報を提供することが望ましいですが、自動化を試すだけなのでLLMの学習した内部の知識に頼ります。

 長いのでサマリを示すと、チャットモデルの要約・チャット及びレビューモデルのレビュー・提案のそれぞれのリクエストに対するシステムプロンプト及びユーザープロンプトを順番に列挙しています。{}で囲まれた部分にはユーザーの入力や生成結果が代入されるイメージです。

### チャットモデル 制約要約用システムプロンプト
 """あなたは文章要約AIです。与えられた文章を、指示に従って要約してください。"""
### チャットモデル 制約要約用ユーザープロンプト
"""
以下の文章を、重複する項目を削除してください。また、指摘事項がない旨を示すメッセージは削除してください。\n
文章:\"{}\"
"""

### チャットモデル チャット用システムプロンプト
"""あなたは旅行プランを提案するAIエージェントです。ユーザーの質問に対して、おすすめの旅行プランを一つ教えてください。"""
### チャットモデル チャット用ユーザープロンプト
"""
ユーザーに指定された場所の旅行プランを教えて下さい。その際、以下の制約にしたがってプランを考えてください。\n
場所:\"{}\"\n
制約:\"{}\"
"""

### レビューモデル レビュー用システムプロンプト
"""あなたはチャットAIサービスのプロンプトを改善するためのエージェントです。チャットAIサービスの回答をレビューして、各観点ごとに課題を挙げてください。課題は問題を具体的に記載してください。"""
### レビューモデル レビュー観点
"""
魅力:旅行プランが魅力的なものであるか。\n
情報量:実際に旅行プランを遂行するにあたって十分な情報が記載されているか。\n
文章構成:文章のフォーマットが整った読みやすいものとなっているか。\n
冗長性:内容が簡潔で冗長な部分がないか。\n
"""
### レビューモデル レビュー用ユーザープロンプト
"""
ユーザーの質問へのチャットAIの回答に対して、各観点ごとに一文ずつレビューして下さい。また、レビューの結果のみ出力して、他の情報は出力しないでください。ユーザーの質問、チャットAIの回答、レビューの観点は以下の通りです。\n
ユーザーの質問:\"{}\"\n
チャットAIの回答:\"{}\"\n
レビューの観点:\"{}\"\n
"""

### レビューモデル 提案用システムプロンプト
"""あなたはチャットAIサービスのプロンプトを改善するためのエージェントです。チャットAIサービスの回答に対するレビューを基に、改善したプロンプトを提案してください。また、提案としてプロンプトに追加する指示文章のみを出力してください。プロンプトは具体的な指示を与えるものにしてください。"""
### レビューモデル 提案用ユーザープロンプト
"""
チャットAIのプロンプトをより良いプロンプトにするために追加する指示文章を生成してください。指示文章は一文で生成してください。指摘事項が無いレビュー項目は無視してください。提案する指示文章は以下のjson形式で出力してください。また、指示文章は以下のレビュー文章に基づいて作成してください。\n
レビュー文章:\"{}\"
"""

実験

実験条件

 今回はチャットモデル及びレビューモデルの双方にGPT4モデルを使用します(理由は後述)。三回ループを回してみた結果を以下に示します。東京の旅行プランについて質問し、出力は各ループ毎のチャットモデル出力、制約事項一覧、レビュー結果、提案された制約事項の四つとなります。また、回ごとのランダム性に影響する温度パラメータは0としました。一度のループで大量のレビュー結果を見たいようなケースだと役に立ちそうですが、今回は一度に一つの出力に対してレビューを回すのと、温度パラメータが高いと各回のチャット出力で制約を守ってくれない懸念があった為です。

結果・考察

 長くなるのでサマリを先に記載します。まず、一度目のチャット時点でかなり良い旅行プランを提案しています。日ごとに朝昼夜と分けたプランを提供してくれています。それに対して、読みやすい構成となっているが移動手段や所要時間が足りない為追加してほしいとレビューされ、二度目のチャットではその内容を踏まえた旅行プランを提案してくれます。この時点で三回目は指摘事項が追加されない為、少しフォーマットは異なりますがほぼ同じ結果が出力されます。

 また、回ごとにめぐる場所が異なりますが、それに関してはコンテキストにプランを渡していない為です。先述のRAGなどでプラン自体は渡してあげることで、そのプランをより魅力的にかつ分かりやすく、その他レビュー観点に則った形で出力できると思います。

条件: 
場所:東京
loop 1 # チャット chat:東京は日本の首都で、多くの観光地や美味しい食事が楽しめる場所です。以下に3日間の旅行プランを提案します。 【1日目】 • 朝:浅草の「雷門」で写真を撮り、仲見世通りでお土産を見つつ「浅草寺」へ。その後、スカイツリーへ移動し、東京のパノ ラマを楽しむ。 • 昼:スカイツリータウン内のレストランでランチを楽しむ。 • 午後:上野公園へ移動し、上野動物園や東京国立博物館を訪れる。 • 夜:上野のアメ横でショッピングを楽しんだ後、地元の居酒屋で夕食。 【2日目】 • 朝:新宿御苑で自然を楽しむ。 • 昼:新宿のラーメン店でランチを楽しむ。 • 午後:新宿から電車で原宿へ移動し、竹下通りや表参道でショッピング。その後、明治神宮を訪れる。 • 夜:渋谷の「渋谷スクランブル交差点」を見てから、地元のレストランで夕食。 【3日目】 • 朝:築地市場で新鮮な寿司を楽しむ。 • 昼:銀座でショッピングを楽しむ。 • 午後:東京駅周辺を散策し、皇居を訪れる。 • 夜:東京駅近くのレストランで最後の夕食。 このプランはあくまで一例で、東京には他にも多くの観光地があります。また、季節によっては花見や夏祭りなど、さまざまなイベントも楽しめま す。 # 制約(初回は無し) limitations: # レビュー結果 review:魅力:旅行プランは東京の主要な観光地を網羅しており、魅力的な内容となっています。 情報量:具体的な観光地や食事の場所が記載されていますが、移動手段や所要時間、予算などの詳細情報が不足しています。 文章構成:日程ごとに朝・昼・午後・夜と時間帯を分けてプランを提示しているため、非常に読みやすい文章構成となっています。 冗長性:内容は簡潔で、冗長な部分は見受けられません。 # 提案された制約事項 suggest:{"instruction": "旅行プランに移動手段、所要時間、予算などの詳細情報を追加してください。"}
loop 2 # チャット chat:旅行プラン:東京2日間の観光 【1日目】 • 9:00 東京駅集合、スカイツリーへの移動(電車で約30分、500円) • 10:00 スカイツリー観光(入場料3100円) • 12:00 昼食(予算2000円) • 13:00 浅草への移動(電車で約20分、200円) • 13:30 浅草寺、仲見世通り散策(無料) • 15:00 上野への移動(電車で約15分、200円) • 15:30 上野動物園観光(入場料600円) • 17:00 ホテルへの移動(電車で約20分、200円) • 18:00 ホテルチェックイン、休憩 • 19:00 夕食(予算3000円) 【2日目】 • 9:00 ホテル出発、原宿への移動(電車で約30分、200円) • 10:00 明治神宮参拝(無料) • 11:00 原宿散策、昼食(予算2000円) • 13:00 六本木への移動(電車で約20分、200円) • 13:30 六本木ヒルズ観光(展望台入場料2300円) • 15:30 銀座への移動(電車で約20分、200円) • 16:00 銀座散策、ショッピング • 18:00 夕食(予算3000円) • 20:00 東京駅への移動(電車で約15分、200円) ホテル代(1泊8000円)を含むと、大体の予算は約25000円となります。移動は主に電車を利用し、観光地へのアクセスも良好です。また、食事は地 元の美味しい料理を楽しむことができます。このプランでは東京の主要な観光地を効率良く巡ることができます。 # 制約事項 limitations:文章:"旅行プランに移動手段、所要時間、予算などの詳細情報を追加してください。" # レビュー結果 review:魅力:東京の主要な観光地を効率良く巡るプランが提案されており、地元の美味しい料理を楽しむことができる点が魅力的である。 情報量:移動手段、所要時間、予算などの詳細情報が具体的に記載されており、実際に旅行プランを遂行するにあたって十分な情報が提供されてい る。 文章構成:日程ごとに活動内容とその詳細が整理されており、読みやすいフォーマットとなっている。 冗長性:内容が簡潔で、冗長な部分は見受けられない。 # 提案された制約事項(ここで収束) suggest:{ "指示": "特に改善点は見受けられません。現状のプロンプトを維持してください。" }
loop 3 # チャット chat:【1日目】 • 8:00: ホテル出発 • 9:00: 上野公園(上野動物園、東京国立博物館など)訪問。移動手段は地下鉄で、所要時間は約1時間、入場料は600円。 • 12:00: 上野アメ横でランチ。予算は約1,000円。 • 13:00: 秋葉原へ移動。移動手段はJR山手線で、所要時間は約10分。 • 15:00: 浅草へ移動。移動手段は地下鉄銀座線で、所要時間は約15分。浅草寺や雷門を訪問。入場料は無料。 • 18:00: 浅草で夕食。予算は約2,000円。 • 20:00: ホテルへ戻る。移動手段は地下鉄銀座線で、所要時間は約30分。 【2日目】 • 8:00: ホテル出発 • 9:00: 東京ディズニーランド訪問。移動手段はJR京葉線で、所要時間は約1時間。入場料は8,200円。 • 19:00: ディズニーランド内で夕食。予算は約2,000円。 • 21:00: ホテルへ戻る。移動手段はJR京葉線で、所要時間は約1時間。 【3日目】 • 8:00: ホテル出発 • 9:00: 渋谷でショッピング。移動手段はJR山手線で、所要時間は約30分。 • 12:00: 渋谷でランチ。予算は約1,000円。 • 13:00: 原宿へ移動。移動手段は徒歩で、所要時間は約15分。原宿竹下通りや明治神宮を訪問。入場料は無料。 • 16:00: 新宿へ移動。移動手段はJR山手線で、所要時間は約10分。新宿御苑や歌舞伎町を訪問。新宿御苑の入場料は500円。 • 19:00: 新宿で夕食。予算は約2,000円。 • 21:00: ホテルへ戻る。移動手段は地下鉄で、所要時間は約30分。 このプランの予算は、交通費、食事、観光地の入場料を含めて約30,000円です。 # 制約事項 limitations:"旅行プランに移動手段、所要時間、予算などの詳細情報を追加してください。" # レビュー結果 review:魅力:東京の主要な観光地を網羅しており、魅力的な旅行プランとなっています。 情報量:移動手段、所要時間、予算など具体的な情報が詳細に記載されており、十分な情報量となっています。 文章構成:時間と行動を一つずつ列挙する形で整理されており、非常に読みやすい文章構成となっています。 冗長性:各行動について必要な情報のみを簡潔に記載しており、冗長な部分は見受けられません。 # 提案された制約事項 suggest:{ "指示": "特に改善点は見受けられません。現状のプロンプトを維持してください。" }

 GPT4モデルを使用した理由について、GPT3.5モデルだと制約事項を追加してもあまりよろしくない結果になった事情があります。試行錯誤する段階ではGPT4モデルを、実運用では安価なGPT3.5モデルを使用するような方法もあるのですが、今回はベースのプロンプトエンジニアリング力が足りず、といった事情です。レビューの観点なども少し変えるだけで結構出力が変わってしまい、人間の感覚的な少し違うとLLMの解釈の少し違うの間のズレがあるのを感じます。そういったプロンプトの機微の調整が大切である点は否めないです(結局プロンプトエンジニアリング力は必要なんですね)。

 正直なところ、レビュー観点が出ていればそれに合わせた制約事項は思いつきそうなのですが、そこを思いつけない時に頭出ししてもらうような感じになりそうです。方針が大まかに決まったらあとは人力プロンプトエンジニアリング力の出番なので、ループを回し続けるよりもまず最初の一回を見て人間が考えてあげる方が良さそうでした。

終わりに

ここ最近LLMに関するブログはたくさんあるのですが、折角だから面白いことができないかな~と思ってやってみました。実用性の面では毎回この学習を回すよりも人間が実際のユースケースに即した知見を与える方が良いと思うのですが、AIが自己学習したら嬉しいなと思ったのでやってみました。

 

※タイトルはこの書籍のオマージュです。プロンプトエンジニアリング、奥深いですね。

O'Reilly Japan - 退屈なことはPythonにやらせよう (oreilly.co.jp)