LLM 课程文档

聊天模板

Hugging Face's logo
加入 Hugging Face 社区

并获取增强的文档体验

开始使用

Ask a Question Open In Colab

聊天模板

导言

聊天模板对于构建语言模型和用户之间的交互至关重要。无论您是构建简单的聊天机器人还是复杂的 AI 代理,了解如何正确格式化您的对话对于从模型中获得最佳结果至关重要。在本指南中,我们将探讨什么是聊天模板、它们为何重要以及如何有效地使用它们。

聊天模板对于以下方面至关重要: - 保持一致的对话结构 - 确保正确的角色识别 - 跨多轮管理上下文 - 支持工具使用等高级功能

模型类型和模板

基础模型 vs 指令模型

基础模型在原始文本数据上进行训练,以预测下一个 token,而指令模型则经过专门的微调,以遵循指令并进行对话。例如,SmolLM2-135M 是一个基础模型,而 SmolLM2-135M-Instruct 是其指令调优变体。

指令调优模型经过训练以遵循特定的对话结构,使其更适合聊天机器人应用。此外,指令模型可以处理复杂的交互,包括工具使用、多模态输入和函数调用。

为了使基础模型表现得像指令模型,我们需要以模型可以理解的一致方式格式化我们的提示。这就是聊天模板的用武之地。ChatML 是一种模板格式,它使用清晰的角色指示符(system、user、assistant)来构建对话。这是一个关于 ChatML 的指南。

当使用指令模型时,请务必验证您是否使用了正确的聊天模板格式。使用错误的模板可能会导致模型性能不佳或出现意外行为。确保这一点的最简单方法是检查 Hub 上的模型分词器配置。例如,`SmolLM2-135M-Instruct` 模型使用 此配置

常用模板格式

在深入研究具体实现之前,重要的是要了解不同的模型期望如何格式化它们的对话。让我们使用一个简单的示例对话来探索一些常见的模板格式

我们将对所有示例使用以下对话结构

messages = [
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": "Hello!"},
    {"role": "assistant", "content": "Hi! How can I help you today?"},
    {"role": "user", "content": "What's the weather?"},
]

这是在 SmolLM2 和 Qwen 2 等模型中使用的 ChatML 模板

<|im_start|>system
You are a helpful assistant.<|im_end|>
<|im_start|>user
Hello!<|im_end|>
<|im_start|>assistant
Hi! How can I help you today?<|im_end|>
<|im_start|>user
What's the weather?<|im_start|>assistant

这是使用 mistral 模板格式

<s>[INST] You are a helpful assistant. [/INST]
Hi! How can I help you today?</s>
[INST] Hello! [/INST]

这些格式之间的主要区别包括

  1. 系统消息处理:

    • Llama 2 将系统消息包装在 <<SYS>> 标签中
    • Llama 3 使用带有 </s> 结尾的 <|system|> 标签
    • Mistral 在第一个指令中包含系统消息
    • Qwen 使用带有 <|im_start|> 标签的显式 system 角色
    • ChatGPT 使用 SYSTEM: 前缀
  2. 消息边界:

    • Llama 2 使用 [INST][/INST] 标签
    • Llama 3 使用角色特定标签(<|system|><|user|><|assistant|>),并带有 </s> 结尾
    • Mistral 使用 [INST][/INST],并带有 <s></s>
    • Qwen 使用角色特定的开始/结束 token
  3. 特殊 Token:

    • Llama 2 使用 <s></s> 来表示对话边界
    • Llama 3 使用 </s> 来结束每条消息
    • Mistral 使用 <s></s> 来表示轮次边界
    • Qwen 使用角色特定的开始/结束 token

理解这些差异是使用各种模型的关键。让我们看看 transformers 库如何帮助我们自动处理这些变化

from transformers import AutoTokenizer

# These will use different templates automatically
mistral_tokenizer = AutoTokenizer.from_pretrained("mistralai/Mistral-7B-Instruct-v0.1")
qwen_tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen-7B-Chat")
smol_tokenizer = AutoTokenizer.from_pretrained("HuggingFaceTB/SmolLM2-135M-Instruct")

messages = [
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": "Hello!"},
]

# Each will format according to its model's template
mistral_chat = mistral_tokenizer.apply_chat_template(messages, tokenize=False)
qwen_chat = qwen_tokenizer.apply_chat_template(messages, tokenize=False)
smol_chat = smol_tokenizer.apply_chat_template(messages, tokenize=False)
点击查看模板示例

Qwen 2 和 SmolLM2 ChatML 模板

<|im_start|>system
You are a helpful assistant.<|im_end|>
<|im_start|>user
Hello!<|im_end|>
<|im_start|>assistant
Hi! How can I help you today?<|im_end|>
<|im_start|>user
What's the weather?<|im_start|>assistant

Mistral 模板

<s>[INST] You are a helpful assistant. [/INST]
Hi! How can I help you today?</s>
[INST] Hello! [/INST]

高级功能

聊天模板可以处理超出对话交互的更复杂场景,包括

  1. 工具使用:当模型需要与外部工具或 API 交互时
  2. 多模态输入:用于处理图像、音频或其他媒体类型
  3. 函数调用:用于结构化函数执行
  4. 多轮上下文:用于维护对话历史记录
在实现高级功能时: - 使用您的特定模型进行彻底测试。视觉和工具使用模板尤其多样化。 - 仔细监控每个功能和模型之间的 token 使用情况。 - 记录每个功能的预期格式

对于多模态对话,聊天模板可以包含图像引用或 base64 编码的图像

messages = [
    {
        "role": "system",
        "content": "You are a helpful vision assistant that can analyze images.",
    },
    {
        "role": "user",
        "content": [
            {"type": "text", "text": "What's in this image?"},
            {"type": "image", "image_url": "https://example.com/image.jpg"},
        ],
    },
]

这是一个带有工具使用的聊天模板示例

messages = [
    {
        "role": "system",
        "content": "You are an AI assistant that can use tools. Available tools: calculator, weather_api",
    },
    {"role": "user", "content": "What's 123 * 456 and is it raining in Paris?"},
    {
        "role": "assistant",
        "content": "Let me help you with that.",
        "tool_calls": [
            {
                "tool": "calculator",
                "parameters": {"operation": "multiply", "x": 123, "y": 456},
            },
            {"tool": "weather_api", "parameters": {"city": "Paris", "country": "France"}},
        ],
    },
    {"role": "tool", "tool_name": "calculator", "content": "56088"},
    {
        "role": "tool",
        "tool_name": "weather_api",
        "content": "{'condition': 'rain', 'temperature': 15}",
    },
]

最佳实践

通用指南

使用聊天模板时,请遵循以下关键实践

  1. 一致的格式:始终在整个应用程序中使用相同的模板格式
  2. 清晰的角色定义:为每条消息明确指定角色(system、user、assistant、tool)
  3. 上下文管理:在维护对话历史记录时,请注意 token 限制
  4. 错误处理:为工具调用和多模态输入包含适当的错误处理
  5. 验证:在发送到模型之前验证消息结构
要避免的常见陷阱: - 在同一应用程序中混合使用不同的模板格式 - 长对话历史记录超出 token 限制 - 未正确转义消息中的特殊字符 - 忘记验证输入消息结构 - 忽略特定于模型的模板要求

实践练习

让我们通过一个真实的示例来练习实现聊天模板。

按照以下步骤将 `HuggingFaceTB/smoltalk` 数据集转换为 chatml 格式
  1. 加载数据集
from datasets import load_dataset

dataset = load_dataset("HuggingFaceTB/smoltalk")
  1. 创建处理函数
def convert_to_chatml(example):
    return {
        "messages": [
            {"role": "user", "content": example["input"]},
            {"role": "assistant", "content": example["output"]},
        ]
    }
  1. 使用您选择的模型的分词器应用聊天模板

请记住验证您的输出格式是否与目标模型的要求匹配!

其他资源

< > 更新 在 GitHub 上