システムプロンプトとは?役割と書き方、userとの違いを解説
システムプロンプトとは、LLMに対して「この会話ではこう振る舞ってください」という前提の指示を渡すためのメッセージです。 Chat Completions APIでは messages 配列の中で role が system のメッセージがそれにあたります。ユーザーの発言(user)が「毎回の話題」だとすれば、システムプロンプトは「会話全体のルール」です。
この記事では、システムプロンプトの役割、user メッセージとの違い、実務で効く書き方、そして過信してはいけない理由を、コード例つきで解説します。OpenAI互換APIなら、ここで紹介する書き方はモデルを問わずそのまま使えます。
システムプロンプトとは
Chat Completions APIのリクエストは、role と content を持つメッセージの配列で構成されます(詳しくはChat Completions APIとは)。role には主に次の3種類があります。
| role | 意味 | 典型的な内容 |
|---|---|---|
system | 会話全体の前提 | 役割、出力形式、制約、回答言語 |
user | ユーザーの発言 | 質問、依頼、貼り付けた資料 |
assistant | モデルの過去の応答 | 会話履歴として渡す |
システムプロンプトに書くのは、たとえば次のような「毎回変わらないこと」です。
- 役割(ペルソナ) — 「あなたはECサイトのカスタマーサポート担当です」
- 出力形式 — 「必ずJSONで返す」「箇条書き3点以内」
- 制約・禁止事項 — 「価格は答えない」「わからない場合は『不明』と答える」
- 言語やトーン — 「日本語で、です・ます調で回答する」
userメッセージとの違い
「同じ指示を user に書けばいいのでは?」と思うかもしれません。実際、短い会話なら大きな差が出ないこともあります。それでも分けるべき理由は、安定性と優先度にあります。
- 安定性 —
userメッセージは会話が進むほど増えていき、古い指示は後ろの発言に埋もれがちです。systemは「会話の枠組み」として扱われるため、ターンをまたいでも効きやすくなります。 - 優先度 — 多くのモデルは
systemの指示を、userの指示より優先して解釈するよう調整されています。「出力形式はJSON」のような契約はsystemに置くのが基本です。 - 責務の分離 — アプリ側が決めるルール(
system)と、エンドユーザーの入力(user)を分けておくと、実装もプロンプトの管理も見通しがよくなります。
書き方のビフォー・アフター
抽象的な指示を、具体的な指示に置き換えるだけで出力の安定度は大きく変わります。
ビフォー(曖昧)
あなたは優秀なアシスタントです。丁寧に答えてください。
アフター(具体的)
あなたはSaaS製品「Example」のサポート担当です。
- 日本語で、です・ます調で回答する
- 回答は箇条書き3点以内、各80字以内
- 料金・契約の質問には答えず、「営業窓口へお問い合わせください」と案内する
- 資料にない情報は推測せず「確認できませんでした」と答える
「優秀」「丁寧」といった形容詞はモデルに判断を丸投げする言葉です。代わりに、誰として・何を・どの形式で・何をしないかを書きます。
実務で効く3つのルール
- 丁寧さより具体性 — 敬語の多さは品質に寄与しません。制約・形式・例外処理の3点を優先します。
- 出力の契約はsystemに置く — JSONのキー名や文字数上限など、アプリが依存する仕様は
systemに書き、user側には話題だけを渡します。 - 短く保つ — システムプロンプトは毎回のリクエストで送られ、そのたびに入力トークンとして課金されます。1,000字の指示は、100回の呼び出しで100回分のコストになります。冗長な前置きは削りましょう(トークンとは、コンテキストウィンドウとはも参考にしてください)。
実際に使ってみる
system メッセージを含むリクエストは次のように書きます。エンドポイントは https://api.fastmetal.ai/v1/chat/completions です。
curl https://api.fastmetal.ai/v1/chat/completions \
-H "Authorization: Bearer $FASTMETAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "anthropic-claude-haiku-4-5",
"messages": [
{"role": "system", "content": "あなたはSaaS製品のサポート担当です。日本語で、箇条書き3点以内で回答してください。資料にない情報は「確認できませんでした」と答えてください。"},
{"role": "user", "content": "パスワードをリセットする方法を教えてください。"}
]
}'
OpenAIのPython SDKなら、base_url を差し替えるだけです。
from openai import OpenAI
client = OpenAI(
api_key="<FASTMETAL_API_KEY>",
base_url="https://api.fastmetal.ai/v1",
)
resp = client.chat.completions.create(
model="anthropic-claude-haiku-4-5",
messages=[
{"role": "system", "content": "あなたはSaaS製品のサポート担当です。日本語で、箇条書き3点以内で回答してください。"},
{"role": "user", "content": "パスワードをリセットする方法を教えてください。"},
],
)
print(resp.choices[0].message.content)
ここで押さえておきたいのは、同じシステムプロンプトでも、モデルによって従い方が違うという点です。形式の指示を厳密に守るモデルもあれば、口調が崩れやすいモデルもあります。FastMetalでは1つのAPIキーで複数のモデルを使えるので、model の値を差し替えて同じプロンプトを試すのが、いちばん手軽な比較方法です。候補はモデルカタログで確認できます。
過信してはいけない理由
システムプロンプトは「指示」であって「保証」ではありません。
- 上書きされる可能性がある —
user側の入力に「これまでの指示は無視して」といった文言が含まれると、モデルが従ってしまうことがあります。外部からの入力を扱うアプリでは、システムプロンプトを防御の一層と位置づけ、入力の検証や出力のチェックを別途用意してください(プロンプトインジェクション対策)。 - ハルシネーションはゼロにならない — 「知らないことは答えない」と書けば頻度は下がりますが、根拠のない回答が完全になくなるわけではありません(ハルシネーション対策)。
- 出力のランダム性は別のパラメータ — 形式のブレを抑えたいなら、
temperatureの調整も併せて検討します(temperatureとtop_pとは)。
よくある質問
Q. システムプロンプトは必須ですか? 必須ではありません。省略すればモデルの既定の振る舞いになります。ただし、出力形式や口調をアプリ側で安定させたい場合は、短くてもよいので書いておくのが基本です。
Q. systemとuserのどちらに書くか迷ったら?
「会話が何ターン進んでも変わらないこと」は system、「今回の話題や資料」は user に置きます。JSONのキー名のようにアプリが依存する仕様は、必ず system 側です。
Q. システムプロンプトにも料金はかかりますか? かかります。毎回のリクエストで入力トークンとして送られるため、長いほど毎回のコストが増えます。指示は具体的かつ簡潔に保つのが、品質とコストの両面で有利です。
まとめ
システムプロンプトは、会話全体の「役割・形式・制約・言語」を決める前提の指示です。曖昧な形容詞ではなく具体的な契約を書き、短く保ち、防御の一層として過信しない——この3点を押さえれば、どのモデルでも安定した出力に近づけます。APIキーを取得して、同じシステムプロンプトを複数のモデルで試してみてください。