チャットテンプレート(LLM)(チャットテンプレートエルエルエム)
LLMへの入力テキストを会話ロール(system/user/assistant)付きで構造化するJinja2ベースのフォーマット定義。
チャットテンプレート(LLM)とは
チャットテンプレートは、LLM(大規模言語モデル)への入力テキストを会話ロール(system・user・assistant)付きで構造化するJinja2ベースのフォーマット定義である。モデルの事前学習時に使用した特殊トークンや改行パターンと一致させることで、ファインチューニングや推論の品質を最大化する。
なぜチャットテンプレートが必要か
LLMは事前学習の段階で、特定の区切り文字や特殊トークンを使用して会話構造を学習する。たとえばLlama-3は<|begin_of_text|><|start_header_id|>system<|end_header_id|>という形式を使い、Mistralは[INST]と[/INST]を使う。テンプレートを正しく適用しないと、モデルはシステムプロンプトとユーザー発話を区別できず、性能が著しく低下する。
主要なテンプレート形式
ChatML形式
OpenAIが普及させた形式で、Qwen・Phi・多くのオープンソースモデルが採用:
<|im_start|>system
あなたは優秀なアシスタントです<|im_end|>
<|im_start|>user
質問内容<|im_end|>
<|im_start|>assistant
Llama-3形式
Meta AI公式形式。特殊ヘッダートークンでロールを明示:
<|begin_of_text|><|start_header_id|>system<|end_header_id|>
システムプロンプト<|eot_id|><|start_header_id|>user<|end_header_id|>
ユーザー入力<|eot_id|><|start_header_id|>assistant<|end_header_id|>
Mistral形式
システムプロンプトを最初のユーザーターンに組み込む簡略形式:
[INST] <<SYS>>
システムプロンプト
<</SYS>>
ユーザー入力 [/INST]
HuggingFaceでの実装
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Meta-Llama-3-8B-Instruct")
messages = [
{"role": "system", "content": "あなたはPC自作の専門家です。"},
{"role": "user", "content": "RTX 4070とRTX 4070 Tiの違いは?"}
]
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
print(text)
ファインチューニングでの重要性
SFT(Supervised Fine-Tuning)では学習データもチャットテンプレートを適用する必要がある。テンプレートを適用せずに学習すると、推論時にテンプレートを適用しても性能が出ない「テンプレート不一致問題」が発生する。TRL(Transformer Reinforcement Learning)ライブラリはSFTTrainerで自動的にテンプレートを適用する機能を持つ。
tokenizer_config.jsonでの定義
{
"chat_template": "{% for message in messages %}{% if message['role'] == 'system' %}<|im_start|>system\n{{ message['content'] }}<|im_end|>\n{% endif %}{% endfor %}"
}
モデルリリース時にこのフィールドが欠如していると、ユーザーが手動でテンプレートを指定する必要があり、互換性トラブルの温床となる。
vLLM・llama.cppでの扱い
vLLMはHuggingFaceのtokenizer_config.jsonから自動的にチャットテンプレートを読み取り、OpenAI互換エンドポイントの/v1/chat/completionsで透過的に適用する。llama.cppはGGUFファイル内にテンプレートを埋め込む方式を採用している。