少し難しいタスクについて ChatGPT とオープンソース モデルを比較する
VicunaやMPT-7B-Chatなどのオープンソース LLM があちこちで登場しており、これらのモデルを商用 LLM (ChatGPT や Bard など) とどのように比較するかについて多くの議論が行われています。
比較のほとんどは、簡単な 1 ターンの質問/指示に対する回答です。たとえば、LMSYSOrgの人々は、さまざまな短い質問について Vicuna-13B と ChatGPT を比較する興味深い分析 (自動化され再現可能であることに +1) を行いました。これは、単純なチャットボットとしてのモデルの比較としては優れています。ただし、LLM を使用する多くの興味深い方法には、通常、複雑な指示や複数回にわたる会話、および迅速なエンジニアリングが必要です。「現実の世界」では、ほとんどの人が、さまざまなプロンプトを使用して、問題に関してさまざまな LLM サービスを比較したいと考えると思います。
このブログ投稿 ( Scott Lundbergguidance
と共同で執筆)は、ユーザーによる LLM の制御を支援するオープンソース プロジェクトである を使用したそのような探索がどのようなものになるかを示す一例です。さまざまな複雑さのタスクについて、2 つのオープン ソース モデル (Vicuna-13B、MPT-7b-Chat) と ChatGPT (3.5) を比較します。
ウォームアップ: 方程式を解く
ウォームアップとして、単純な多項方程式を解くというおもちゃのタスクから始めましょう。出力が正しいかどうかをチェックでき、迅速なエンジニアリングはそれほど必要ありません。これは、ここ の数学カテゴリに似ていますが、GPT-4 を使用して出力を評価するのではなく、グラウンド トゥルースに基づいてモデルを正しいか間違っているかを評価する点が異なります。
チャット構文について少し脱線します。これらのモデルにはそれぞれ独自のチャット構文があり、発話を区切る特殊なトークンが使用されます。同じ会話が Vicuna と MPT でどのように表示されるかを次に示します ([generated response]
モデルが出力を生成する場所はどこです)。
ビクーニャ:
A chat between a curious user and an artificial intelligence assistant. The assistant gives helpful, detailed, and polite answers to the user's questions.
USER: Can you please solve the following equation? x^2 + 2x + 1 = 0
ASSISTANT: [generated response] </s>
<|im_start|>system
- You are a helpful assistant chatbot trained by MosaicML.
- You answer questions.
- You are excited to be able to help the user, but will refuse to do anything that could be considered harmful to the user.
- You are more than just an information source, you are also able to write poetry, short stories, and make jokes.
<|im_end|>
<|im_start|>user Can you please solve the following equation? x^2 + 2x + 1 = 0<|im_end|>
<|im_start|>assistant [generated response]<|im_end|>
find_roots = guidance('''
{{#system~}}
{{llm.default_system_prompt}}
{{~/system}}
{{#user~}}
Please find the roots of the following equation: {{equation}}
Think step by step, find the roots, and then say:
ROOTS = [root1, root2...]
For example, if the roots are 1.3 and 2.2, say ROOTS = [1.3, 2.2].
Make sure to use real numbers, not fractions.
{{~/user}}
{{#assistant~}}
{{gen 'answer'}}
{{~/assistant~}}''')
import guidance
mpt = guidance.llms.transformers.MPTChat('mosaicml/mpt-7b-chat', device=1)
vicuna = guidance.llms.transformers.Vicuna('yourpath/vicuna-13b', device_map='auto')
chatgpt = guidance.llms.OpenAI("gpt-3.5-turbo")
equation = 'x^2 + 3.0x = 0'
roots = [0, -3]
answer_gpt = find_roots(llm=chatgpt, equation=equation)
answer_vicuna = find_roots(llm=vicuna, equation=equation)
answer_mpt = find_roots(llm=mpt, equation=equation)
この投稿に付属のノートブックでは、-20 から 20 までの整数根を持つランダムな 2 次方程式を生成する関数を作成し、各モデルでプロンプトを 20 回実行します。結果は次のとおりでした。
╔═══════════╦══════════╦
║ Model ║ Accuracy ║
╠═══════════╬══════════╬
║ ChatGPT ║ 80% ║
║ Vicuna ║ 0% ║
║ MPT ║ 0% ║
╚═══════════╩══════════╩
ChatGPT は最後のステップで計算エラーを起こします。ここで、ではなく(13 +- 25) /2
yield が必要です。ここで、Vicuna と MPT は 2 次方程式で失敗したため、次のようなさらに単純な方程式を見ていきます。これらの方程式では、次の数値が得られます。[19, -6]
[19.5, -6.5]
x - 10 = 0
╔═══════════╦══════════╦
║ Model ║ Accuracy ║
╠═══════════╬══════════╬
║ ChatGPT ║ 100% ║
║ Vicuna ║ 85% ║
║ MPT ║ 30% ║
╚═══════════╩══════════╩
議論
これは非常に難しいタスクでしたが、同じプロンプトを使用して異なるチャット構文を持つモデルを比較する方法の例として役立ちました。この特定のタスクとプロンプトの組み合わせでは、ChatGPT は精度 (グラウンド トゥルースで測定) の点で Vicuna や MPT をはるかに上回っています。
タスク: スニペットの抽出 + 会議に関する質問に答える
次に、精度の評価がそれほど単純ではない、より現実的なタスクに移ります。LLM に、会議の記録に関する質問に (根拠となる関連する会話セグメントを使用して) 答えてもらいたいとします。
これは、プライバシー上の理由から、一部のユーザーが商用 LLM ではなくオープンソース LLM を使用することを好む可能性があるアプリケーションです (たとえば、一部の企業は会議データを OpenAI に送信したくない可能性があります)。
まずはおもちゃ会議の記録です。
会議の記録:
John : わかりました。それでは、Microsoft から当社のスタートアップを買収するというオファーについて話し合うために全員がここに来ました。これについてはどう思いますか?
ルーシー: そうですね、私たちにとっては素晴らしい機会だと思います。Microsoft は多くのリソースを備えた巨大企業であり、当社の製品を次のレベルに引き上げるのに大いに役立つでしょう。
スティーブン: 私もルーシーの意見に同意します。Microsoft はテクノロジー業界で豊富な経験を持っており、ビジネスの成長に必要なサポートを提供してくれるでしょう。
John : あなたの言いたいことはわかりますが、私たちのスタートアップを売却することについては少し躊躇しています。私たちはこの会社を築くために多くの時間と努力を費やしてきましたが、まだ手放す準備ができているかどうかはわかりません。
ルーシー: ジョン、あなたがどこから来たのかは理解していますが、私たちは会社の将来について考えなければなりません。Microsoft に売却すれば、Microsoft のリソースと専門知識にアクセスできるようになり、ビジネスのさらなる成長に役立つ可能性があります。
Steven : そうですね、経済的なメリットも忘れてはなりません。Microsoft は私たちのスタートアップに多額の資金を提供しており、新しいプロジェクトへの投資やチームの拡大に役立つ可能性があります。
ジョン: あなたの言いたいことはわかりますが、まだ若干の留保があります。Microsoft が製品や企業文化を変えたらどうなるでしょうか? 自分自身のビジネスをコントロールできなくなったらどうなるでしょうか?
Steven : そうですね、私はこれまで考えたこともありませんでしたが、おそらくジョンは正しいでしょう。私たちの文化が変わってしまったら残念です。
ルーシー:それらは正当な懸念ですが、当社に対するある程度のコントロールを確実に維持するために、取引条件を交渉することはできます。また、製品と文化に関しては、Microsoft と協力して、当社のビジョンが損なわれていないことを確認できます。
ジョン:でも、大企業に吸収されただけでは、私たちは変わらないのですか?つまり、私たちは非常に特殊な文化を持つ小さなスタートアップです。Microsoft は非常に異なる文化を持つ巨大企業です。この 2 つが共存できるかどうかはわかりません。
Steven : でも、ジョン、私たちは常に買収されることを計画していたんじゃないの? これはいつでも問題になりませんか?
ルーシー: そうでしょう
ジョン: 私たちがここで築いてきたものを失いたくないんです。
スティーブン: 私もこの懸念を共有します
まず、ChatGPT にタスクを解決してもらうことから始めましょう。「スティーブンは販売についてどう感じていますか?」という質問についてテストしてみます。プロンプトでの最初の試みは次のとおりです
qa_attempt1 = guidance('''{{#system~}}
{{llm.default_system_prompt}}
{{~/system}}
{{#user~}}
You will read a meeting transcript, then extract the relevant segments to answer the following question:
Question: {{query}}
Here is a meeting transcript:
----
{{transcript}}
----
Please answer the following question:
Question: {{query}}
Extract from the transcript the most relevant segments for the answer, and then answer the question.
{{/user}}
{{#assistant~}}
{{gen 'answer'}}
{{~/assistant~}}''')
qa_attempt3 = guidance('''{{#system~}}
{{llm.default_system_prompt}}
{{~/system}}
{{#user~}}
You will read a meeting transcript, then extract the relevant segments to answer the following question:
Question: {{query}}
Here is a meeting transcript:
----
{{transcript}}
----
Based on the above, please answer the following question:
Question: {{query}}
Please extract from the transcript whichever conversation segments are most relevant for the answer, and then answer the question.
Note that conversation segments can be of any length, e.g. including multiple conversation turns.
Please extract at most 3 segments. If you need less than three segments, you can leave the rest blank.
As an example of output format, here is a fictitious answer to a question about another meeting transcript.
CONVERSATION SEGMENTS:
Segment 1: Peter and John discuss the weather.
Peter: John, how is the weather today?
John: It's raining.
Segment 2: Peter insults John
Peter: John, you are a bad person.
Segment 3: Blank
ANSWER: Peter and John discussed the weather and Peter insulted John.
{{/user}}
{{#assistant~}}
{{gen 'answer'}}
{{~/assistant~}}''')
qa_attempt5 = guidance('''{{#system~}}
{{llm.default_system_prompt}}
{{~/system}}
{{#user~}}
You will read a meeting transcript, then extract the relevant segments to answer the following question:
Question: What were the main things that happened in the meeting?
Here is a meeting transcript:
----
Peter: Hey
John: Hey
Peter: John, how is the weather today?
John: It's raining.
Peter: That's too bad. I was hoping to go for a walk later.
John: Yeah, it's a shame.
Peter: John, you are a bad person.
----
Based on the above, please answer the following question:
Question: {{query}}
Please extract from the transcript whichever conversation segments are most relevant for the answer, and then answer the question.
Note that conversation segments can be of any length, e.g. including multiple conversation turns.
Please extract at most 3 segments. If you need less than three segments, you can leave the rest blank.
{{/user}}
{{#assistant~}}
CONVERSATION SEGMENTS:
Segment 1: Peter and John discuss the weather.
Peter: John, how is the weather today?
John: It's raining.
Segment 2: Peter insults John
Peter: John, you are a bad person.
Segment 3: Blank
ANSWER: Peter and John discussed the weather and Peter insulted John.
{{~/assistant~}}
{{#user~}}
You will read a meeting transcript, then extract the relevant segments to answer the following question:
Question: {{query}}
Here is a meeting transcript:
----
{{transcript}}
----
Based on the above, please answer the following question:
Question: {{query}}
Please extract from the transcript whichever conversation segments are most relevant for the answer, and then answer the question.
Note that conversation segments can be of any length, e.g. including multiple conversation turns.
Please extract at most 3 segments. If you need less than three segments, you can leave the rest blank.
{{~/user}}
{{#assistant~}}
{{gen 'answer'}}
{{~/assistant~}}''')
qa_attempt5(llm=chatgpt, transcript=meeting_transcript, query=query1)
qa_guided = guidance('''{{#system~}}
{{llm.default_system_prompt}}
{{~/system}}
{{#user~}}
You will read a meeting transcript, then extract the relevant segments to answer the following question:
Question: {{query}}
----
{{transcript}}
----
Based on the above, please answer the following question:
Question: {{query}}
Please extract the three segment from the transcript that are the most relevant for the answer, and then answer the question.
Note that conversation segments can be of any length, e.g. including multiple conversation turns. If you need less than three segments, you can leave the rest blank.
As an example of output format, here is a fictitious answer to a question about another meeting transcript:
CONVERSATION SEGMENTS:
Segment 1: Peter and John discuss the weather.
Peter: John, how is the weather today?
John: It's raining.
Segment 2: Peter insults John
Peter: John, you are a bad person.
Segment 3: Blank
ANSWER: Peter and John discussed the weather and Peter insulted John.
{{/user}}
{{#assistant~}}
CONVERSATION SEGMENTS:
Segment 1: {{gen 'segment1'}}
Segment 2: {{gen 'segment2'}}
Segment 3: {{gen 'segment3'}}
ANSWER: {{gen 'answer'}}
{{~/assistant~}}''')
もちろん、同じプロンプトを MPT で実行することもできます。
MPT は形式に従いますが、質問は無視し、実際のトランスクリプトからではなく形式の例から断片を取得します。
ここからは、ChatGPT と Vicuna を比較していきます。
別の質問をしてみましょう。「会社を売りたいのは誰ですか?」
ChatGPT は次のとおりです。
ビクーニャ:
どちらも本当にうまく機能しているようです。会議の記録をイーロン・マスク氏のインタビューの最初の数分間に切り替えてみましょう。これから尋ねる質問に関連する部分は次のとおりです。
イーロン・マスク:それでは、先生、あなたは自分が何を言っているのか分からないと言います。
インタビュアー: 本当ですか?
イーロン・マスク:はい。憎しみに満ちたコンテンツの例を 1 つも挙げることはできないからです。ツイートも一つもありません。それなのに、あなたはヘイトコンテンツが多いと主張しました。それは間違いです。
インタビュアー: いいえ、私が主張したこと -
イーロン・マスク: あなたはただ嘘をついただけです。
次に、次の質問をします。
「イーロン・マスクはインタビュアーを侮辱しましたか?」
チャットGPT:
ビクーニャ:
Vicuna には正しいフォーマットと正しいセグメントさえありますが、驚くべきことに、「イーロン・マスクは嘘をついていると非難したり、いかなる形でも彼を侮辱したりしていません」と完全に間違った答えを生成します。
私たちは他のさまざまな質問や会話を試しましたが、全体的なパターンとしては、Vicuna はほとんどの質問で ChatGPT と同等でしたが、ChatGPT よりも間違った答えをすることが多かったです。
タスク: bash を使用して作業を行う
ここで、これらの LLM に bash シェルを繰り返し使用させて、個々の問題を解決しようとします。彼らがコマンドを発行するたびに、タスクが解決されるまで、それを実行して出力をプロンプトに挿入し直します。
ChatGPT プロンプトは次のとおりです (引数shell this.command
としてユーザー定義関数を呼び出していることに注意してくださいthis.command
)。
terminal = guidance('''{{#system~}}
{{llm.default_system_prompt}}
{{~/system}}
{{#user~}}
Please complete the following task:
Task: list the files in the current directory
You can give me one bash command to run at a time, using the syntax:
COMMAND: command
I will run the commands on my terminal, and paste the output back to you. Once you are done with the task, please type DONE.
{{/user}}
{{#assistant~}}
COMMAND: ls
{{~/assistant~}}
{{#user~}}
Output: guidance project
{{/user}}
{{#assistant~}}
The files or folders in the current directory are:
- guidance
- project
DONE
{{~/assistant~}}
{{#user~}}
Please complete the following task:
Task: {{task}}
You can give me one bash command to run at a time, using the syntax:
COMMAND: command
I will run the commands on my terminal, and paste the output back to you. Once you are done with the task, please type DONE.
{{/user}}
{{#geneach 'commands' stop=False}}
{{#assistant~}}
{{gen 'this.command'}}
{{~/assistant~}}
{{~#user~}}
Output: {{shell this.command)}}
{{~/user~}}
{{/geneach}}''')
実際、ChatGPT は非常に自然なシーケンスに従い、タスクを解決します。DONE と言う指示には従いませんが、COMMAND は発行されないため、反復を自動的に停止できます。
オープンソース モデルの場合は、一連のコマンド出力がある、より単純な (ガイド付き) プロンプトを作成します。
guided_terminal = guidance('''{{#system~}}
{{llm.default_system_prompt}}
{{~/system}}
{{#user~}}
Please complete the following task:
Task: list the files in the current directory
You can run bash commands using the syntax:
COMMAND: command
OUTPUT: output
Once you are done with the task, use the COMMAND: DONE.
{{/user}}
{{#assistant~}}
COMMAND: ls
OUTPUT: guidance project
COMMAND: DONE
{{~/assistant~}}
{{#user~}}
Please complete the following task:
Task: {{task}}
You can run bash commands using the syntax:
COMMAND: command
OUTPUT: output
Once you are done with the task, use the COMMAND: DONE.
{{~/user}}
{{#assistant~}}
{{#geneach 'commands' stop=False ~}}
COMMAND: {{gen 'this.command' stop='\\n'}}
OUTPUT: {{shell this.command)}}{{~/geneach}}
{{~/assistant~}}''')
MPTは次のとおりです。
興味深い展開として、ビクーニャは課題を解決できませんでしたが、MPT は成功しました。オープンソース モデルには、プライバシー (セッション トランスクリプトを OpenAI に送信しません) に加えて、ここで大きな利点があります。プロンプト全体が 1 回の LLM 実行です (さらに、 のような出力構造トークンを生成させないことで高速化しています)COMMAND:
。 。対照的に、コマンドごとに ChatGPT を新たに呼び出す
必要があるため、時間がかかり、コストも高くなります。
次に、別のコマンドを試します。「現在 git によって追跡されていない ~/work/guidance 内のすべての jupyter ノートブック ファイルを検索します」。
ChatGPT は次のとおりです。
ここでも、ChatGPT が指定された出力構造に従っていないという問題に遭遇しました (そのため、人間がループに参加しないとプログラム内で使用することができなくなりました)。私たちのプログラムはコマンドを実行しただけなので、上記の最後の ChatGPT メッセージの後に停止しました。
私たちは空の出力によって ChatGPT がオフになったのではないかと考え、出力がない場合のメッセージを変更することでこの問題を修正しました。ただし、指定した出力構造に ChatGPT を強制できないという一般的な問題は解決できません。
ChatGPT は、この小さな修正により問題を解決することができました。Vicuna がどのように動作するかを見てみましょう:
Vicuna は出力構造に従いますが、残念ながらタスクを実行するために間違ったコマンドを実行します。MPT (図示せず) は git status を繰り返し呼び出すため、これも失敗します。
これらのプログラムを他のさまざまな命令に対して実行したところ、ChatGPT はほぼ常に正しいコマンド シーケンスを生成しますが、指定された形式に従っていない場合がある (したがって人間の介入が必要である) ことがわかりました。オープンソース モデルはあまりうまく機能しませんでした (おそらく、より迅速なエンジニアリングで改善できるでしょうが、最も難しい指示では失敗しました)。
テイクアウト
上記の例に加えて、両方のタスク (質問応答と bash) に対してさまざまな入力を試しました。また、要約、質問応答、「創造的な」生成、正確さを自動的に評価できるおもちゃの文字列操作タスクなど、他のさまざまなタスクも試しました。
調査結果の要約は次のとおりです。
- タスクの品質:私たちが試したすべてのタスクにおいて、ChatGPT (3.5) は依然としてタスク自体の点で Vicuna よりも強力です。MPT はほぼすべてのタスクでパフォーマンスが悪く (おそらく使い方が間違っているのでしょうか?)、Vicuna は ChatGPT に近いことがよくありました (上記の最後のタスク例のように、非常に近い場合もあれば、はるかに悪い場合もありました)。
- 使いやすさ: ChatGPT を指定された出力形式に従わせるのははるかに困難であるため、プログラム内で (ループに人間が関与しないで) ChatGPT を使用するのはさらに難しくなります。さらに、出力用の正規表現パーサーを常に作成する必要があります (Vicuna とは対照的に、明確な構文でプロンプトを解析するのは簡単です)。
通常、数ショットのサンプルを追加することで構造の問題を解決できますが、サンプルを作成するのは面倒で、とにかく ChatGPT がスクリプトから外れることもあります。また、プロンプトは長く、不格好で、醜いものになり、満足のいくものではありません。
出力構造を指定できることは、オープンソース モデルの大きな利点です, たとえタスク自体が少し劣っていても、ChatGPT よりも Vicuna を好む場合があるほどです。 - 効率: モデルをローカルに持つということは、1 回の LLM 実行でタスクを解決できる (
guidance
プログラムの実行中に LLM 状態を維持できる) ことを意味し、より速く、より安価になります。これは、サブステップに他の API または関数 (検索、ターミナルなど) の呼び出しが含まれる場合に特に当てはまり、常に OpenAI API への新しい呼び出しが必要になります。guidance
また、モデルに出力構造トークンを生成させないことで生成を高速化します。これにより、大きな違いが生じる場合があります。
過去数年間に OpenAI モデルを頻繁に使用したこと、GPT-3 に依存するさまざまな論文 (例:ここ、ここ)、および基本的に「GPT-4 は素晴らしい」と言っている論文を書いたことによって偏見があることを認識する必要があります。 、ここに素晴らしい例がたくさんあります。」
そういえば、Vicuna は ChatGPT (3.5) にある程度匹敵しますが、私たちは GPT-4 の方がはるかに強力なモデルであると信じており、オープンソース モデルがそれに近づくことができるかどうかを確認することに興奮しています。OpenAI モデルは非常にうまく機能しますがguidance
、出力構造を指定して生成を高速化できる場合に真価を発揮します。
繰り返しになりますが、私たちは明らかに偏見を持っていますが、guidance
API (OpenAI、Azure) またはローカル (huggingface) を使用するかどうかに関係なく、これがこれらのモデルを使用する優れた方法であると考えています。ここに、上記のすべての例 (およびその他) のコードを含む jupyter ノートブックへのリンクがあります。
免責事項: この投稿は Marco Tulio Ribeiro と Scott Lundberg が共同で執筆したものです。これは厳密に私たちの個人的な意見を表すものであり、雇用主 (Microsoft) の意見ではありません。
謝辞:この投稿に関して洞察力に富んだコメントをくださった Harsha Ori 氏に心より感謝いたします。