3秒でわかる
変数の穴を空けたプロンプトを部品として定義する仕組み。文字列を毎回組み立てず、入力だけ差し替えて同じ指示を再利用できます。
30秒図解
もう少し詳しく
どういうものか
LangChain などの LLM 向けフレームワークが提供する、プロンプトのひな型を表すクラスです。{language} のようなプレースホルダーを含む文字列を先に定義しておき、実行時に値を渡して完成形のプロンプトを組み立てます。
役割ごとにメッセージを分ける ChatPromptTemplate もあり、システムメッセージには方針を、ユーザーメッセージには可変の入力を置く、という書き分けができます。
なぜ必要か
プロンプトをコードのあちこちで文字列連結して作ると、同じ指示の少しずつ違う版が散らばります。表現を1つ直したいだけで、grep して回ることになります。テンプレートとして1か所に置けば、修正も差分の追跡も1ファイルで済みます。
RAG のように、検索してきた文書を毎回埋め込む使い方では、埋め込む位置と前後の指示を固定できることが品質に直結します。人が手で組み立てると、区切り記号を入れ忘れて文書と指示が地続きになり、指示が無視される事故が起きます。
具体例
from langchain_core.prompts import ChatPromptTemplate
template = ChatPromptTemplate.from_messages([
("system", "あなたは{language}の講師です。初学者向けに3行で答えます。"),
("user", "{question}"),
])
prompt = template.invoke({
"language": "Python",
"question": "リスト内包表記とは何ですか",
})
print(prompt.messages)同じテンプレートに別の値を渡せば、そのまま他の言語向けの回答生成に使い回せます。
つまずきやすいところ
テンプレート文字列の中で JSON の例を示すと、{ と } が変数の記号として解釈されてエラーになります。文字としての波かっこを書きたいときは {{ }} と二重にします。出力形式を JSON で指定したい場面で必ず踏む罠です。
利用者の入力をテンプレートの変数として渡さず、自分で文字列連結して差し込むのも避けます。連結だと入力の中の指示めいた文がそのまま本文に混ざり、元の指示を上書きされる恐れがあります。
テンプレートの変更は出力の質を大きく動かします。プロンプトもコードと同じくバージョン管理の対象に含め、変更したら評価用の入力で結果を見比べる運用にすると、体感頼みの調整から抜けられます。
似た用語との違い
f 文字列でも変数の差し込みはできます。違いは、テンプレートが「どの変数を必要とするか」を自分で把握していて、渡し漏れをその場で検出できること、そして後続の処理へつなぐ部品として扱えることです。単発の実験なら f 文字列で十分ですが、本数が増えるほどテンプレートの利点が出ます。