Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】Stop shipping untested prompts: test your LLM prompts like code with promptfoo — hands-on

2026年10月01日に「Dev.to」が公開したITニュース「Stop shipping untested prompts: test your LLM prompts like code with promptfoo — hands-on」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

LLMのプロンプトもコード同様、テストしないと問題が起きる可能性がある。promptfooは、プロンプトをテストするためのオープンソースツールだ。YAMLでテストケースと期待する結果を定義し、プロンプトの動作を検証できる。プロンプトの品質を高め、バグを早期発見し、CI/CDに組み込んで信頼性の高いLLMアプリケーション開発を支援する。

ITニュース解説

大規模言語モデル(LLM)の活用が広まる中で、LLMへの指示となる「プロンプト」は、アプリケーションの動作に非常に重要な役割を果たす。しかし、多くの開発現場では、プロンプトはチャットツール上で試行錯誤され、目視で軽く確認されただけで本番環境にデプロイされることが少なくない。これは、まるで決済機能のコードをテストせずにリリースするようなもので、極めて危険な行為である。例えば、顧客への返金処理を決定する重要なプロンプトが、開発者が良かれと思って行った「ちょっとした表現の変更」によって、予期せず「フランス語で謝罪を始める」といった奇妙な振る舞いをしてしまう可能性がある。LLMのモデル自体がアップデートされたり、チーム内でプロンプトの表現が「改善」されたりするたびに、このような潜在的な問題が発生するリスクは常に存在するのだ。プロンプトはもはや単なる指示文ではなく、アプリケーションの重要なコードの一部として、厳格なテストが不可欠である。

このようなプロンプトの品質管理に関する課題を解決するために開発されたのが、オープンソースツール「promptfoo」である。これは、テスト駆動型のLLM開発を実現するためのコマンドラインインターフェース(CLI)とライブラリを提供する。promptfooの主な目的は、プロンプトが期待通りに機能するかを自動的に検証し、その品質を保証することにある。具体的には、プロンプトの内容、利用するLLMサービス(プロバイダー)、そしてテストケースをYAML形式の設定ファイルに記述する。そして、それぞれのプロンプトからの出力に対して、期待される動作を検証するための「アサーション」(検証条件)を設定する。これにより、複数のプロンプトのバージョンを横並びで比較したり、各プロンプトの出力結果を評価してスコアを付けたり、機械が読み取れる形式でテスト結果をエクスポートしたりすることが可能になる。最終的には、このテスト結果を基に、本番環境へのデプロイを自動的に制御する「デプロイゲート」として組み込むこともできる。

promptfooを使ったテストの基本的なプロセスは、一般的なソフトウェア開発における単体テストのサイクルに非常によく似ている。まず、テスト環境の準備が必要だが、このニュース記事の紹介ではNode.jsとPythonがあれば十分である。特筆すべきは、LLMのAPIキーや高性能なGPUが不要である点だ。これは、promptfooが提供する「モックプロバイダー」機能のおかげである。モックプロバイダーとは、実際のLLMサービスと通信する代わりに、定義された入力に対して事前に決められた出力を返す仮想的なLLMのことである。これにより、テストにかかる費用をゼロに抑え、ネットワーク環境に依存せず、常に同じ結果を得られるため、初心者でも安心して学習や開発を進めることができる。

次に、テスト対象となるプロンプトを具体的に定義する。例えば、サポートチケットを自動分類するボットを作成するケースを考える。ここでは、初期の「素朴なプロンプト」(v1)と、より詳細な指示を含む「改善されたプロンプト」(v2)の2種類を用意する。v2プロンプトでは、JSON形式での出力、特定の部門名のみを回答させる、緊急度を明確に判断させる、といったように、テストしやすい明確な「契約」(出力形式や内容のルール)を明示的に記述する。

そして、テストの中心となる設定ファイル(promptfooconfig.yaml)を作成する。このファイルには、使用するプロンプトファイル、モックプロバイダー、そして具体的なテストケースを記述する。テストケースでは、実際のサポートチケットの例文(例:「二重に請求された」)と、その出力に期待されるアサーションを複数定義する。アサーションには、出力に特定の文字列が含まれるか(icontains)、正規表現に一致するか(regex)、出力がJSON形式であるか(is-json)、出力の長さなどのプロパティが条件を満たすか(pythonスクリプトによるチェック)など、多様な種類がある。

ニュース記事のチュートリアルでは、このサポートチケット分類ボットの例を通じて、promptfooの利用方法を具体的に解説している。v1プロンプトは単に「件名と部門で応答せよ」と指示するのみだが、v2プロンプトはJSON形式での出力、部門の候補リスト、緊急度判定のロジックまで明確に指示している点が異なる。

テストを実行すると、promptfooは各プロンプトとテストケースの組み合わせに対して、定義されたアサーションを適用し、その結果を合格・不合格のグリッド形式で表示する。この結果は、ウェブブラウザ上で詳細なレポートとして確認できるだけでなく、ターミナル上でも表形式で概要を把握できる。

このチュートリアルでは、v1プロンプトがJSON形式の出力要件を満たせず(is-jsonアサーションが失敗)、また「緊急度」に関する情報も出力しないため、緊急度をチェックする正規表現アサーションも失敗することが具体的に示されている。一方、v2プロンプトは全てのアサーションに合格する。この結果は、プロンプトのわずかな表現の違いが、出力形式や情報内容に大きく影響を与え、本番環境での潜在的なトラブルに直結する可能性を明確に示している。つまり、このテストスイートは、LLMモデル自体ではなく、プロンプト自体に潜む潜在的なバグを効果的に洗い出したのだ。もしテストがなければ、v1プロンプトはデプロイされ、顧客への返金処理の緊急度が黙って低下したり、後続のシステムがJSONを解析できずにエラーになったりといった問題が、システムの利用者に発見されることになるだろう。

promptfooは、大規模なテストケースにも対応できるよう設計されている。テストケースをYAMLファイルに直接記述する代わりに、CSVファイルとして外部化し、そのCSVファイルをpromptfooconfig.yamlから参照することも可能だ。これにより、大量の過去のサポートチケットデータなどをCSV形式で用意するだけで、瞬時に数十、数百ものテストケースをスイートに追加できる。これは、実際の運用データに基づいた「回帰テストスイート」(過去に発見されたバグが再発しないことを確認するテスト)を簡単に構築できることを意味する。

また、開発サイクルを高速化するために、promptfooは特定のプロンプトのみをテストするフィルタリング機能や、テスト結果をJSON形式で出力し、前回の結果と比較できる機能も提供する。これにより、プロンプトの変更、テストの実行、結果の比較という「赤・緑ループ」を、コードの単体テストと同じように回すことができる。

さらに、promptfoo evalコマンドは、アサーションが失敗すると非ゼロの終了コードを返すため、継続的インテグレーション(CI)パイプラインに簡単に組み込むことができる。GitHub ActionsのようなCIツールでpromptfooのテストステップを追加すれば、プロンプトの変更を含むプルリクエストが作成された際に、自動的にテストが実行される。もしプロンプトの変更が既存の契約を破ったり、期待される振る舞いを損なったりした場合、CIが失敗し、その変更が本番環境にデプロイされるのを未然に防ぐことができる。これにより、プロンプトの品質管理を自動化し、開発プロセスの初期段階で問題を検出・修正する「シフトレフト」を実現する。

promptfooは、プロンプトの反復的な改善を行ったり、異なるLLMモデルやプロンプトのバージョンを比較したりするすべてのプロジェクトで導入を検討する価値がある。特に、「小さな表現の変更」が予期せぬ動作を引き起こした経験があるならば、その有効性は高い。モックプロバイダーを利用すれば、費用をかけることなく、ツールの有効性を試すことができる。導入の際は、まずis-json、icontains、regex、JavaScript/Pythonスクリプトによるチェックといった、決定的で安定したアサーションから始めることを推奨する。これらのアサーションは高速かつ無料で実行できるため、CIパイプラインでの頻繁な実行に適している。人間による判断が必要な、より複雑な評価(別のLLMを使って出力を評価するアサーションなど)は、必要に応じて追加し、ナイトリービルドやリリースブランチなど、実行頻度を抑えた環境で利用を検討すると良いだろう。これは、モデル評価アサーションは費用が発生する場合があるためである。

いくつかの注意点もある。promptfooの終了コードはCIの合否を決定する重要な要素だが、その設定は自分で確実に行う必要がある。モックプロバイダーはテストハーネス(テスト環境)の有効性を検証するには最適だが、実際のLLMモデルの振る舞いを完全に保証するものではない。そのため、デプロイ前に実際のLLMプロバイダーに対して(温度パラメーターを0に設定し、複数回実行するなどで)最終的なテストを行うことが重要だ。さらに、非決定論的なLLMの出力に対しては、一度のテストパスだけでは十分な証明とならず、統計的な思考に基づいた複数回実行や評価が必要になる場合もある。

このニュース記事が示唆する不都合な真実とは、プロンプトの品質保証がいかに簡単な設定で実現可能かということだ。たった1つのYAML設定ファイル、2つのプロンプトファイル、そして60行程度のモックプロバイダー、そして数個のアサーションを用意するだけで、「新しいプロンプトはまだ期待通りに機能するか?」という疑問は、希望的観測ではなく、機械がチェックできる明確な答えとなる。v1プロンプトが失敗したのは、そのプロンプトが「不十分」だったからではなく、その「機能する」という定義がどこにも明文化されていなかったからである。promptfooは、この「機能する」という定義を機械が理解できる形で記述し、すべてのコミットで自動的にチェックするための規律を提供するツールと言える。今日のあなたの仕事の中で、特に重要だと感じるプロンプトを一つ選び、その出力の「契約」に対して3つ程度のテストケースとアサーションを記述し、promptfoo evalを実行してみることを推奨する。もしテストが全て合格すれば、あなたは貴重な回帰テストスイートを手に入れたことになる。もし失敗した場合は、ユーザーが発見する前に、システムに潜むバグを自ら見つけ出したことになるだろう。プロンプトが単なる一時的な指示ではなく、サポートボットや分類器、RAGパイプラインのような「インフラストラクチャ」の一部となる瞬間、それはコードとなり、テストのないコードはシステムにとっての負債となる。

関連コンテンツ

関連IT用語

関連ITニュース