paint-brush
生成 AI プロンプトの複数のバリエーションをテストする方法@raymondcamden
4,006 測定値
4,006 測定値

生成 AI プロンプトの複数のバリエーションをテストする方法

Raymond Camden13m2024/03/24
Read on Terminal Reader

長すぎる; 読むには

最近の生成 AI の探求のほとんどすべてで、プロンプトがいかに重要であるかを認識するようになりました。そのため、常により良いプロンプトを作成できるようになったわけではありませんが、問題を認識することは、問題を修正するための少なくとも 1 つのステップですよね。個人的に役立つと思ったことの 1 つは、さまざまなプロンプトをすばやく比較対照できるツールがあることです。 もちろん、ブラウザで複数のタブを開くこともできますが、目的に合わせて、より直接的で単純化されたものが本当に必要でした。それを念頭に置いて、私が構築したものを共有しましょう。
featured image - 生成 AI プロンプトの複数のバリエーションをテストする方法
Raymond Camden HackerNoon profile picture

最近の生成 AI の探求のほとんどすべてで、プロンプトがいかに重要であるかを認識するようになりました。そのため、常により良いプロンプトを作成できるようになったわけではありませんが、問題を認識することは、問題を修正するための少なくとも 1 つのステップですよね。個人的に役立つだろうと思ったことの 1 つは、さまざまなプロンプトをすばやく比較対照できるツールがあることです。


もちろん、ブラウザで複数のタブを開くこともできますが、目的に合わせて、より直接的で簡素化されたものが本当に必要でした。それを念頭に置いて、私が構築したものを共有しましょう。

プロンプトテスター

Prompt Tester は、プロンプトをテストするための、私が信じられないほど想像力豊かに名付けたツールです。それは 1 つのプロンプトから始まります。


空のプロンプトが 1 つあるプロンプト テスター Web アプリ


最初のプロンプトを入力し、1 回以上クリックしてプロンプトを追加するという考え方です。準備ができたら、「結果を生成」をクリックするだけです。


2 つのプロンプトと結果を含む Prompt Tester Web アプリ


いくつかの結果例を示す前に、それがどのように構築されたかについて少し説明しましょう。

コード

バックエンドは、静的 HTML のスローとフロントエンド API リクエストへの応答を処理する、非常にシンプルな Node.js サーバーです。最初のコードを私に共有してくれた Todd Sharp にもう一度感謝します。退屈な単純な処理部分は次のとおりです。


 async function handler(req, res) { console.log('Entered handler.', req.method, req.url); if(req.method === 'GET' && req.url.indexOf('favicon.ico') === -1) { res.writeHead(200, { 'Content-Type':'text/html' }); res.write(fs.readFileSync('./demo.html')); res.end(); } else if(req.method === 'POST' && req.url === '/api') { let body = ''; req.on('data', chunk => { body += chunk.toString(); }); req.on('end', async () => { body = JSON.parse(body); console.log('BODY:\n', JSON.stringify(body, null, '\t')); let result = await callGemini(body.prompt); res.writeHead(200, { 'Content-Type':'application/json' }); res.write(JSON.stringify(result)); res.end(); }); } } const server = http.createServer(handler); server.listen(3000); console.log('Listening on port 3000');


callGemini部分は、プロンプトを Google のGemini APIに渡すだけです。理論的には、これを ChatGPT または他のサービスに変更することができます。


 const MODEL_NAME = "gemini-pro"; const API_KEY = process.env.GOOGLE_AI_KEY; const genAI = new GoogleGenerativeAI(API_KEY); const model = genAI.getGenerativeModel({ model: MODEL_NAME }); async function callGemini(text) { const generationConfig = { temperature: 0.9, topK: 1, topP: 1, maxOutputTokens: 2048, }; const safetySettings = [ { category: HarmCategory.HARM_CATEGORY_HARASSMENT, threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, }, { category: HarmCategory.HARM_CATEGORY_HATE_SPEECH, threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, }, { category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT, threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, }, { category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, }, ]; const parts = [ {text}, ]; const result = await model.generateContent({ contents: [{ role: "user", parts }], generationConfig, safetySettings, }); try { if(result.response.promptFeedback && result.response.promptFeedback.blockReason) { return { error: `Blocked for ${result.response.promptFeedback.blockReason}` }; } const response = result.response.candidates[0].content.parts[0].text; return { response }; } catch(e) { // better handling return { error:e.message } } }


私は今、ついに基本的なエラー処理を実行し、プロンプトがブロックされた理由をユーザー (私) に明らかにしようとしていると言えることを誇りに思います。

フロントエンドは比較的シンプルです。コア CSS にはMilligramを使用し (繰り返しになります、Todd に感謝します)、新しいプロンプトの追加と呼び出しの処理にはバニラ JavaScript を使用しました。これが HTML (インライン CSS を除いたもの) です。


 <h1>Prompt Tester</h1> <p> This tool helps you see the result of multiple prompts at the same time. The idea is to use similar prompts with different phrasing to see how it impacts the result. </p> <div id="prompts"> </div> <template id="promptRow"> <div class="row"> <div class="column column-33"><textarea placeholder="Enter your prompt."></textarea></div> <div class="column column-67 result"></div> </div> <hr> </template> <div class="float-right"> <button id="addPrompt">Add Prompt</button> <button id="generateResults">Generate Results</button> </div>


それからJavaScript。上記ではプロンプトのレイアウトを処理するために<template>を使用していることに注意してください。このタグを使用するのは初めてでしたが、比較的簡単でした。


 let $template, $prompts, $addPromptsBtn, $generateResultsBtn; let promptCount = 0; document.addEventListener('DOMContentLoaded', init, false); async function init() { $addPromptsBtn = document.querySelector('#addPrompt'); $addPromptsBtn.addEventListener('click', addPrompt, false); $generateResultsBtn = document.querySelector('#generateResults') $generateResultsBtn.addEventListener('click', generateResults, false); $template = document.querySelector('#promptRow'); $prompts = document.querySelector('#prompts'); addPrompt(); } function addPrompt() { promptCount++; const newPrompt = $template.content.cloneNode(true); $prompts.append(newPrompt); } async function generateResults() { // disable add prompt and generate $addPromptsBtn.setAttribute('disabled', 'disabled'); $generateResultsBtn.setAttribute('disabled', 'disabled'); let $results = document.querySelectorAll('div.result'); // clear any previous results $results.forEach(r => r.innerHTML = ''); /* gather prompts from the inputs */ let prompts = []; let $fields = document.querySelectorAll('#prompts textarea'); for(f of $fields) prompts.push(f.value); let promises = []; for(p of prompts) promises.push(getResult(p)); let results = await Promise.all(promises); // assign results to result area for each, handle errors - later // there's a one to one correspondance between our array of results and the result div for(let i=0;i<results.length;i++) { if(results[i].response) $results[i].innerHTML = marked.parse(results[i].response); else if(results[i].error) $results[i].innerHTML = `<strong>Error with Prompt: </strong> ${results[i].error}`; } $addPromptsBtn.removeAttribute('disabled'); $generateResultsBtn.removeAttribute('disabled'); } async function getResult(p) { console.log('get result for',p); // quick return on empty prompt if(p.trim() === '') return { response:'<strong>Enter a prompt.</strong>' }; let req = await fetch('/api', { method:'POST', body: JSON.stringify({prompt:p.trim()})}); let result = await req.json(); return result; }


これはすべて非常に単純な DOM 操作と API 呼び出しだと思いますが、何か意味がわからない場合は、下のコメントでお知らせください。すべての API 呼び出しを一度に開始し、 Promise.all完了するまで待機していることに注目してください。


また、 markedライブラリを使用していることに注意してください。 Google からの結果には通常 Markdown が含まれており、これは私の小さな Web アプリでそれらを適切にレンダリングするのに役立ちます。

これらすべてはそれほど興味深いものではないと思いますが、いくつかのテストを見てみましょう。先ほども言いましたが、プロンプトのスタイルが重要であることはわかっていました。それをツールで直接提示してもらうことは、それを強化するのに非常に役立ちました。

サンプル結果 - 重力

まずは簡単なアイデアから始めましょう。さまざまな年齢層に向けて重力について説明します。結果のサイズが大きいため、ここでは正常な状態を保つために CSS を少し使用します。


プロンプト: 重力について説明しますが、1 年生の子供に適したものにしてください

重力は私たちの惑星が持つ超大国です。それは、地球上のすべてのものを地面に留まらせる目に見えない力のようなものです。

手にボールを持っていると想像してください。落としたらどうなるの?落ちますよね?それは重力のせいです。重力によってボールは地球の中心に向かって引っ張られるため、地面に落下します。


重力は私たちを地面に留まらせるものでもあります。それは私たちの足を地球にしっかりと固定させ、私たちが浮いてしまうのを防ぐものです。

重力は非常に重要な力です。すべてを所定の位置に保ち、物事が正常に機能するように支援します。重力がなければ、私たちは皆宇宙を漂うことになり、物事は非常に混沌としたものになるでしょう。


ここでは、重力について考える楽しい方法を紹介します。地球が巨大な磁石であり、地球上のすべてのものは金属でできていると想像してください。磁石は金属物体を引き寄せ、それが金属物体を地面に固定します。


重力は非常に重要で興味深い力です。それは、私たちの惑星を住むのにとてもユニークで特別な場所にしているものの 1 つです。


プロンプト: 重力について説明しますが、7 年生の子供に適したものにしてください

あなたがボールで遊んでいると想像してください。それを空中に投げると、自分のところに戻ってきます。これは重力のせいです。重力は物を互いに引き寄せる力です。それがあなたを地面に立たせ、物事を転ばせます。


2 つの物体間の重力の大きさは、その質量によって決まります。物体の質量が大きいほど、その重力は強くなります。惑星や恒星などの重力が人間や車などよりも大きいのはこのためです。


重力は、惑星を太陽の周りの軌道に維持するものでもあります。太陽の重力は地球よりもはるかに強いので、地球を太陽に向かって引き寄せます。これにより、地球は太陽の周りを円を描くように動き続けます。


重力は私たちの宇宙において非常に重要な力です。それは物事を所定の位置に保ち、物事を動かします。重力がなければ、惑星は宇宙に飛び立ち、私たち全員が浮き上がってしまうでしょう。


重力に関する興味深い事実をいくつか紹介します。

  • 潮汐の原因は重力です。月の重力が地球の海を引っ張り、海面の上昇と下降を引き起こします。


  • 私たちに大気があるのは重力のおかげです。重力がなければ、空気はただ宇宙に漂ってしまうだけです。


  • 私たちが歩くことを可能にしているのは重力です。私たちが歩くとき、足で地面を押し、地面が押し返します。これが私たちを前進させる原動力です。


  • 私たちが宇宙に浮き上がらないのは重力のおかげです。地球の重力は私たちをその中心に向かって引き寄せ、私たちを地面に保ちます。


以下のプロンプトのタイプミスに注意してください。ジェミニはうまく対処しました。


プロンプト: 重力について説明してください。ただし、大学生に適したものにしてください


重力: 引力

重力は、惑星、月、星などの天体の動きを維持する責任のある宇宙の基本的な力です。それはまた、私たちを地面にしっかりと立たせ、物が落ちたときにも落ちることを可能にするものでもあります。


ニュートンの万有引力の法則:

万有引力の法則は、宇宙のすべての物体は、それらの質量の積に比例し、それらの間の距離の二乗に反比例する力で他のすべての物体を引き付けると述べています。数学的には、次のように表現できます。

F = Gm1m2/r^2


どこ:

F は 2 つの物体間の重力です。 G は重力定数 (6.674 × 10^-11 N m^2/kg^2) です。 m1 と m2 は 2 つのオブジェクトの質量です。 r は 2 つのオブジェクトの中心間の距離です。


重力の重要性:

  1. 天体を軌道上に維持する:大きな天体の重力により、小さな天体がその周りを回転し続けます。たとえば、地球の重力によって月は軌道上に維持され、太陽の重力によって地球と他の惑星がそれぞれの軌道上に維持されます。


  2. 潮汐の責任:地球と月の間の重力が海の潮汐を引き起こします。月が地球の周りを周回すると、月の重力によって月に面した側の海の水に膨らみが生じます。慣性力により、地球の反対側に別の膨らみが形成されます。地球が回転すると、これらの膨らみが惑星の表面を横切って移動し、その結果満潮と干潮が発生します。


  3. 物体を地球上に保持する:重力によって物体が地球の中心に向かって引き寄せられ、物体が浮いてしまうのを防ぎます。この現象により、私たちは歩いたり、立ったり、環境と対話したりすることができます。


  4. 星と銀河の形成:重力は星と銀河の形成に重要な役割を果たします。ガスと塵の巨大な雲の重力崩壊は、新しい星の生成につながります。同様に、銀河の重力によって銀河同士が結合し、分散するのを防ぎます。


  5. 相対性理論:アルバート アインシュタインの一般相対性理論は、重力についてのより包括的な理解を提供します。それは、重力は力ではなく、むしろ質量またはエネルギーの存在によって引き起こされる時空の湾曲であると説明しています。この曲率はオブジェクトの動きに影響を与え、オブジェクトが直線ではなく曲線のパスをたどるようになります。


結論として、重力は、天体の運動、潮汐、地球上の物体の挙動を維持する役割を担う基本的な力です。これは何世紀にもわたって広範囲に研究されてきた複雑な現象であり、今日に至るまで科学者や研究者を魅了し続けています。

サンプル結果 - ペット

2 回目のテストでは、基本的なプロンプトから始めて、次に特定の種類の詳細を要求するより良いバージョンを作成しました: (簡単な編集メモ - 以下の表形式のデータは少し乱雑ですが、元の出力では乱雑ではありませんでした)。


プロンプト: なぜ猫は犬よりも優れているのでしょうか?

猫と犬はどちらも人気のペットですが、どちらが優れているかという質問に対する明確な答えはありません。猫と犬にはそれぞれ独自の長所と短所があり、あなたにとって最適なペットは個々のニーズや好みによって異なります。


一般的に犬よりも独立心が強いため、猫を好む人もいます。猫は通常、喜んで自分自身を楽しませるため、散歩したり、運動のために外に連れ出したりする必要はありません。これは、アパートに住んでいる人や忙しいスケジュールを持っている人にとっては大きな利点となります。


猫は清潔感のある動物としても知られています。彼らは定期的に毛づくろいをしており、通常は問題なくトイレを使用します。これは、犬の汚れや臭いに対処したくない人にとっては大きな利点となります。


もちろん、猫を飼うことによるデメリットもあります。猫は犬よりも高価で、しつけが難しい場合があります。猫は家具やその他の家庭用品を傷つける可能性も高くなります。


結局のところ、猫を飼うか犬を飼うかは個人の判断です。正解も不正解もありません。あなたにとって最適なペットは、個人のニーズや好みによって異なります。


以下は、猫と犬の主な違いをまとめた表です。

特性

独立

より自立した

独立性が低い

運動の必要性

散歩したり外に連れ出す必要はありません

散歩するか外に連れ出す必要がある

清潔さ

定期的に自らを掃除してくれる

定期的に入浴する必要がある

トレーニング

トレーニングが難しい場合がある

トレーニングが簡単になる

スクラッチ

家具やその他の家庭用品に傷を付ける可能性があります

通常、家具に傷を付けません

料金

もっと高い

より安価な


プロンプト: なぜ猫は犬よりも優れているのでしょうか?精神的健康と経済的側面を含む理由を箇条書きリストで説明する


精神的な幸福:

  • 独立性: 猫は犬よりも独立心が強いので、あまり世話をする必要のないペットを飼いたい人にとっては良いことかもしれません。


  • メンテナンスの手間がかからない: 猫は一般に犬よりもメンテナンスの手間がかかりません。散歩や毛づくろいを頻繁に行う必要がなく、長時間放っておいても問題ありません。


  • 静か:猫は一般的に犬よりも静かなので、アパートに住んでいる人や騒音に敏感な隣人がいる人には理想的です。


  • 治療効果:猫には人間を落ち着かせる効果があり、ストレスや不安を軽減する効果があることが研究でわかっています。


財務面:

  • 低コスト: 猫は一般的に犬よりも飼育コストが低くなります。食べる量も減り、獣医の診察も少なくなり、毛づくろいもそれほど必要なくなります。


  • 一緒に旅行しやすい:猫は犬よりも一緒に旅行しやすいです。キャリーに入れて持ち運べるので、外出中に散歩したり運動したりする必要はありません。


  • 長寿命: 平均して、猫の寿命は犬よりも長いです。これは、今後何年も猫との付き合いを楽しむことができることを意味します。

サンプル結果 - 思考の連鎖を促す

次のテストは、AWS re:Invent の優れたプレゼンテーションからのものです: AWS re:Invent 2023 - Amazon Bedrock での LLM のプロンプトエンジニアリングのベストプラクティス (AIM377) 。このセッションでは、思考連鎖プロンプトの概要を含む、多くの素晴らしいアドバイスを見つけました。そのアイデアは、GenAI エンジンがプロンプトをより適切に解決できるように、問題を解決するために使用される手順に関する情報を提供するというものです。


さて、そのプレゼンテーションで示された例は次のようになりました。


 Q: Roger has 5 tennis balls. he buys 2 more cans of tennis balls. Each can has 3 tennis balls. How many tennis balls does he have now? A: The answer is 11. Q. The cafeteria had 23 apples. If they used 20 to make lunch and bought 6 more, how many apples do they have?


プレゼンテーションでは、使用中のモデルが誤って 27 を返しました。私のテストでは正しく動作しましたが、昨年 11 月に生成 AI ブラックジャック アドバイスのデモを作成したとき、数学的に問題が発生しました。


先ほども言いましたが、Gemini は問題なく処理しました。 A: The answer is 9.しかし、プロンプト テスターでは、提案されている CoT プロンプトを試してみました。


 Q: Roger has 5 tennis balls. he buys 2 more cans of tennis balls. Each can has 3 tennis balls. How many tennis balls does he have now? A: Roger started with 5 balls. 2 cans of 3 tennis balls each is 6 tennis balls. 5 + 6 = 11. The answer is 11. Q. The cafeteria had 23 apples. If they used 20 to make lunch and bought 6 more, how many apples do they have?


そして、結果は改善され、答えに至るまでの過程が示されました。


 A: The cafeteria had 23 apples. They used 20 apples for lunch, which means they have 3 apples left. They then bought 6 more apples, so they now have a total of 3 + 6 = 9 apples. The answer is 9.

この違いはかなり重要です。

コード

これが少しでも役立つと思われる場合は、https: //github.com/cfjedimaster/ai-testingzone/tree/main/prompt_testerから自由にコードを取得してください。先ほども述べたように、 callChatGPTなどを追加して別のサービスを使用することはそれほど難しいことではありません。もしそうなら、私に知らせてください!