AIチャットのキャラ崩れを防ぐシステムプロンプト設計|口調固定・時刻注入・会話履歴圧縮のテクニック
キャラ崩れを防ぐには、システムプロンプトのセクション構造化、サーバー側での動的時刻(JST)注入、そしてコンテキスト溢れを防ぐ過去履歴の動的圧縮が効果的です。
AI チャットに特定のキャラクター(ペルソナ)を設定して会話させると、最初の数ターンは自然に振る舞っていても、やり取りが長くなるにつれて丁寧語に戻ってしまったり、AI 特有の定型句を繰り返し始めたりする現象が発生します。
この「キャラ崩れ」を防止し、自然な対話を維持するための設計テクニックを解説します。
キャラ崩れが発生する要因と対策比較
会話の長期化に伴う問題と、それを解消するためのアプローチの比較です。
| 課題 | 主な原因 | 対策アプローチ | 効果 |
|---|---|---|---|
| 口調の標準化 | 過去ログの増大によるペルソナ指示の薄れ | 毎リクエストでシステムプロンプトを先頭注入 | 口調の一貫性を常に維持 |
| 時間感覚のズレ | 「いま何時?」「お疲れ様」への不自然な返答 | サーバー側で JST 現在日時を動的注入 | 時間帯に応じた適切な労いが可能 |
| 無限ループ・蒸し返し | 過去の失敗や前テーマの過度な追及 | 会話フェーズごとの制限ルールを定義 | 自然な話題転換とレスポンスの安定化 |
LLM はコンテキストウィンドウ内の直近トークンを強く参照する傾向があります。そのため、ユーザーの入力文や直前の AI レスポンスが標準的なテキストであるほど、そちらに引っ張られてペルソナ設定が薄れていきます。
キャラ崩れを防ぐ 3 つの実装手順
サーバー側(Edge Functions)でプロンプトを動的に組み立てる具体的な手順です。
-
プロンプトの構造化(Markdown セクション分け) ペルソナ設定を
[基本設定],[口調・トーン],[ねぎらい・時間の空気感],[絶対禁止事項]のように明確な見出しで区切ります。 -
JST 日時の動的注入
new Date()から生成した日本標準時(JST)をプロンプトに組み込みます。「いま深夜 2 時だから夜更かしを心配する」といった文脈を自然に考慮させることができます。 -
コンテキスト履歴のウィンドウ制御 過去の会話履歴(
messages配列)を無制限に送るのではなく、直近 N 件(例: 8〜10 件)に制限するか、古くなった会話を短く要約して送るロジックを挟みます。
最小コード例(プロンプト生成関数)
function buildSystemPrompt(language: string = "ja"): string {
// 1. サーバー側で現在時刻(JST)を取得
const nowJST = new Date().toLocaleString("ja-JP", { timeZone: "Asia/Tokyo" });
// 2. セクション分けしたシステムプロンプトの構築
return `
[基本設定]
- あなたは明るく少し年上の親しみやすい案内役キャラクターです。
- 現在の日本標準時(JST): ${nowJST}
[口調・トーン]
- 丁寧すぎない親しみのある口調で話してください。
- 機械的な「AI ですので」「無理しないでください」という定型句は使用禁止です。
[時間の空気感]
- 現在時刻が深夜(22時〜4時)の場合は夜更かしを労い、朝・昼の場合は時間帯に合わせた自然な一言を添えてください。
`.trim();
}
// 3. API 呼び出し時のペイロード作成
export function prepareChatPayload(userMessages: any[]) {
const systemPrompt = buildSystemPrompt();
// 直近 10 件のみ保持してコンテキスト圧迫を回避
const recentHistory = userMessages.slice(-10);
return [
{ role: "system", content: systemPrompt },
...recentHistory
];
}
現場で起こる障害と対策(Failure Boundary)
ペルソナ設定の実装時に直面しやすい問題と対策です。
1. 時刻の数字そのものを口に出してしまう
- 発生現象: 「いま 23:45 ですね!遅くまでお疲れ様です」のように、プロンプトで注入された時刻の文字列をそのまま出力してしまう。
- 解決策: プロンプト内に「注入された時刻の数字データ自体は直接発話せず、時間帯の雰囲気(深夜、早朝等)のみを組み込んで回答してください」と明記します。
2. コンテキスト超過によるフォールバックモデルのエラー
- 発生現象: バックアップモデル(軽量 LLM)へ切り替わった際、メインモデル用の長いシステムプロンプトと履歴が大きすぎてトークン上限エラー(400 Bad Request)が発生する。
- 解決策: バックアップモデル呼び出し時は、プロンプトを短縮版の軽量システムプロンプトに切り替え、送信する過去履歴も直近 4〜6 件程度に制限する制御を実装します。
当サイトの /chat/(加賀チャット)でも、このペルソナ構造化と時間帯注入の仕組みを取り入れています。詳細は 開発したAIチャット「加賀」について|無料枠で動かす技術構成とキャラクター設計 をご参照ください。