スプレッドシートでのプロンプト管理は確実に破綻する
生成AIを組み込んだシステムの開発において、プロンプトの管理方法をどう設計するかは、プロジェクトの成否を分ける重要な分岐点です。初期のPoC段階では、プランナーやドメインエキスパートが手軽に編集できるよう、スプレッドシートやWiki等でプロンプトを共有するケースがよくあります。
PoCの段階では便利だった共有シートが、本番運用に近づくにつれて「誰がいつ、なぜその文言に変更したのか分からない魔境」と化すのを何度も目の当たりにしてきました。
このようなスプレッドシート管理が破綻する理由は、アプリケーションコードのバージョンとプロンプトのバージョンとの紐付けが完全に失われるからです。
たとえば、LLMのモデルバージョンが更新されたタイミングで、出力を安定させるためにプロンプトの指示文を微修正したとします。その後、何らかの不具合でアプリケーションのコードを前のバージョンにロールバックする必要が生じた際、スプレッドシート上のプロンプトはすでに上書きされており、当時の正確な状態を復元することは極めて困難になります。
このことから得られる示唆は、プロンプトは単なる「テキストデータ」ではなく、システムの振る舞いを決定する「ソースコード」の一部として扱う必要があるということです。
プロンプトはコード本体から分離しGitで一元管理する
プロンプトをソースコードとして扱うのであれば、Gitを用いたバージョン管理の対象にするのが自然なアプローチです。ただし、PythonやTypeScriptなどのアプリケーションコードの中に、ヒアドキュメントで長文のプロンプトを直接埋め込む手法は推奨できません。
アプリケーションのコードの中に長文のプロンプトがハードコードされているのを発見すると、保守性の低さに頭を抱えたくなります。
プロンプトの変更サイクルとアプリケーションのロジック変更サイクルは異なるため、両者は分離して管理すべきです。実務では、プロンプトを別ファイル(YAMLやJSON、あるいは専用のテンプレートファイル)として切り出し、リポジトリ内でディレクトリを分けて管理します。
LangChainなどを利用している場合、プロンプトテンプレートを外部ファイルから読み込む仕組みを構築することで、コードの見通しが劇的に改善します。プロンプトの変更は必ずPull Requestを通し、変更意図(どのような入力に対して、どのような出力を期待して変更したのか)をコミットメッセージやPRのディスクリプションに残す。このソフトウェアエンジニアリングにおける当たり前の作法をAI開発にもそのまま適用するだけで、属人性は大幅に排除されます。
自動テストとLLM-as-a-Judgeでリグレッションを防ぐ
プロンプトをGitで管理し、外部ファイル化できたら、次は変更の妥当性を担保する仕組みが必要です。
プロンプトの微修正に対して「良くなった気がする」という担当者の感覚値だけでリリースを進めようとする現場には、必ずストップをかけます。
プロンプト変更時には、定量的かつ自動化されたテストが不可欠です。なぜなら、LLMの出力は確率的であり、ある特定のユースケースに対する精度を上げるための変更が、他の正常に動いていたユースケースの劣化を招く「リグレッション」が極めて起きやすいからです。
たとえば、情報抽出タスクにおいて、特定の例外パターンの抽出精度を上げるために指示文を数行追加したとします。すると、意図通りに例外パターンは拾えるようになったものの、今度は全体的な出力フォーマットが崩れ、後続のJSONパース処理でエラーが頻発するようになる、といった事態です。
こうした事故を防ぐためには、CI/CDパイプラインにプロンプトの自動テストを組み込む必要があります。具体的には、過去の代表的な入力データ(ゴールデンデータセット)を用意し、プロンプト変更時に一括で推論を実行します。出力フォーマットの検証(アサーション)に加え、LLM-as-a-Judge(評価用の別のLLMを用いて、出力の妥当性や正確性をスコアリングする手法)を導入することで、精度の変動を定量的に追跡できます。これにより、業務に耐えうる再現性と説明可能性を持ったシステム運用が可能になります。
AIを単なる魔法の箱として扱うのではなく、テスト可能で予測可能なコンポーネントとしてどう制御するかが、実運用におけるアーキテクトの腕の見せ所です。
LLMの評価指標をどのように設計し、実際の業務要件と結びつけるかについては、また別の機会に整理したいと思います。