# 聊天模板

在我们的 GitHub 中，我们列出了 Unsloth 使用的每个聊天模板，包括 Llama、Mistral、Phi-4 等。因此，如果你需要关于格式或用例的任何提示，可以在此查看： [github.com/unslothai/unsloth/blob/main/unsloth/chat\_templates.py](https://github.com/unslothai/unsloth/blob/main/unsloth/chat_templates.py)

#### Colab 聊天模板笔记本列表：

* [对话式](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Llama3.2_\(1B_and_3B\)-Conversational.ipynb)
* [ChatML](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Llama3_\(8B\)-Ollama.ipynb)
* [Ollama](https://colab.research.google.com/drive/1WZDi7APtQ9VsvOrQSSC5DDtxq159j8iZ?usp=sharing)
* [文本分类](https://github.com/timothelaborie/text_classification_scripts/blob/main/unsloth_classification.ipynb) 作者：Timotheeee
* [多个数据集](https://colab.research.google.com/drive/1njCCbE1YVal9xC83hjdo2hiGItpY_D6t?usp=sharing) 作者：Flail

### 添加新标记

Unsloth 有一个名为 `add_new_tokens` 的函数，允许你向微调中添加新标记。例如，如果你想添加 `<CHARACTER_1>`, `<THINKING>` 和 `<SCRATCH_PAD>` 我们可以做如下操作：

```python
model, tokenizer = FastLanguageModel.from_pretrained(...)
from unsloth import add_new_tokens
add_new_tokens(model, tokenizer, new_tokens = ["<CHARACTER_1>", "<THINKING>", "<SCRATCH_PAD>"])
model = FastLanguageModel.get_peft_model(...)
```

{% hint style="warning" %}
注意 - 你必须始终在 `add_new_tokens` 之前调用 `FastLanguageModel.get_peft_model`!
{% endhint %}

## 多轮对话

一个你可能没注意到的问题是 Alpaca 数据集是单轮的，而使用 ChatGPT 时是交互式的，可以进行多轮对话。例如，左侧是我们想要的，但右侧（即 Alpaca 数据集）只提供单次对话。我们希望微调后的语言模型能以某种方式学会像 ChatGPT 一样进行多轮对话。

<figure><img src="https://2657992854-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2Fgit-blob-2a65cd74ddd03a6bcbbc9827d9d034e4879a8e6a%2Fdiff.png?alt=media" alt=""><figcaption></figcaption></figure>

因此我们引入了 `conversation_extension` 参数，该参数本质上会在你的单轮数据集中选择一些随机行，并将它们合并成一个对话！例如，如果你将其设置为 3，我们会随机选择 3 行并合并为 1 条！设置得太长会使训练变慢，但可能会让你的聊天机器人和最终微调效果更好！

<figure><img src="https://2657992854-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2Fgit-blob-2b1b3494b260f1102942d86143a885225c6a06f2%2Fcombine.png?alt=media" alt=""><figcaption></figcaption></figure>

然后设置 `output_column_name` 为预测/输出列。对于 Alpaca 数据集，它将是输出列。

然后我们使用 `standardize_sharegpt` 函数将数据集规范为适合微调的正确格式！务必调用此函数！

<figure><img src="https://2657992854-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2Fgit-blob-7bf83bf802191bda9e417bbe45afa181e7f24f38%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

## 可自定义的聊天模板

我们现在可以为微调本身指定聊天模板。非常著名的 Alpaca 格式如下：

<figure><img src="https://2657992854-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2Fgit-blob-59737e6dcb09fed15487d5a57c69f07cb40bb8e7%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

但请记住我们说过这是个糟糕的主意，因为 ChatGPT 风格的微调只需要 1 个提示？由于我们已通过 Unsloth 成功将所有数据列合并为 1 列，因此我们基本上可以创建下面这种样式的聊天模板，使用 1 个输入列（instruction）和 1 个输出：

<figure><img src="https://2657992854-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2Fgit-blob-d54582ae98c396d51bfb85628b46c54f2517d030%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

我们只要求你必须放置一个 `{INPUT}` 字段作为指令，以及一个 `{OUTPUT}` 字段作为模型的输出字段。我们实际上还允许可选的 `{SYSTEM}` 字段，这在自定义系统提示（就像在 ChatGPT 中）时很有用。例如，下面是一些很酷的示例，你可以自定义聊天模板为：

<figure><img src="https://2657992854-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2Fgit-blob-cc455dc380d3d44ef136e485754964159dc773d8%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

对于在 OpenAI 模型中使用的 ChatML 格式：

<figure><img src="https://2657992854-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2Fgit-blob-15bfca9cfadf10d54b4d3f66e3050044317d62c5%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

或者你可以使用 Llama-3 本身的模板（仅在使用 Llama-3 的 instruct 版本时有效）：我们实际上还允许一个可选的 `{SYSTEM}` 字段，这在自定义系统提示（就像在 ChatGPT 中）时很有用。

<figure><img src="https://2657992854-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2Fgit-blob-80a2ed4de2ca323ac192c513cac65e9e8bf475db%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

或者在 Titanic 预测任务中，你需要预测某个乘客在这个包含 CSV 和 Excel 上传的 Colab 笔记本中是死亡还是幸存： <https://colab.research.google.com/drive/1VYkncZMfGFkeCEgN2IzbZIKEDkyQuJAS?usp=sharing>

<figure><img src="https://2657992854-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2Fgit-blob-20911ab305c1a10e85859c703157b80175141eb1%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

## 在 Unsloth 中应用聊天模板

对于通常遵循通用 chatml 格式的数据集，将数据集准备用于训练或微调的过程包括四个简单步骤：

* 检查 Unsloth 当前支持的聊天模板：\\

  ```
  from unsloth.chat_templates import CHAT_TEMPLATES
  print(list(CHAT_TEMPLATES.keys()))
  ```

  \
  这将打印出 Unsloth 当前支持的模板列表。以下是示例输出：\\

  ```
  ['unsloth', 'zephyr', 'chatml', 'mistral', 'llama', 'vicuna', 'vicuna_old', 'vicuna old', 'alpaca', 'gemma', 'gemma_chatml', 'gemma2', 'gemma2_chatml', 'llama-3', 'llama3', 'phi-3', 'phi-35', 'phi-3.5', 'llama-3.1', 'llama-31', 'llama-3.2', 'llama-3.3', 'llama-32', 'llama-33', 'qwen-2.5', 'qwen-25', 'qwen25', 'qwen2.5', 'phi-4', 'gemma-3', 'gemma3']
  ```

  \\
* 使用 `get_chat_template` 将合适的聊天模板应用到你的分词器：\\

  ```
  from unsloth.chat_templates import get_chat_template

  tokenizer = get_chat_template(
      tokenizer,
      chat_template = "gemma-3", # 将此更改为正确的 chat_template 名称
  )
  ```

  \\
* 定义你的格式化函数。示例如下：\\

  ```
  def formatting_prompts_func(examples):
     convos = examples["conversations"]
     texts = [tokenizer.apply_chat_template(convo, tokenize = False, add_generation_prompt = False) for convo in convos]
     return { "text" : texts, }
  ```

  \
  \
  该函数遍历你的数据集，将你定义的聊天模板应用于每个样本。\\
* 最后，让我们加载数据集并对其应用所需的修改： \\

  ```
  # 导入并加载数据集
  from datasets import load_dataset
  dataset = load_dataset("repo_name/dataset_name", split = "train")

  # 使用 map 方法将格式化函数应用到你的数据集
  dataset = dataset.map(formatting_prompts_func, batched = True,)
  ```

  \
  如果你的数据集使用 ShareGPT 格式的 "from"/"value" 键而不是 ChatML 的 "role"/"content" 格式，你可以先使用 `standardize_sharegpt` 函数将其转换。修改后的代码如下所示：\
  \\

  ```
  # 导入数据集
  from datasets import load_dataset
  dataset = load_dataset("mlabonne/FineTome-100k", split = "train")

  # 如有必要，将数据集转换为 "role"/"content" 格式
  from unsloth.chat_templates import standardize_sharegpt
  dataset = standardize_sharegpt(dataset)

  # 使用 map 方法将格式化函数应用到你的数据集
  dataset = dataset.map(formatting_prompts_func, batched = True,)
  ```

## 更多信息

假设你的数据集是下面这种字典列表的列表：

```python
[
    [{'from': 'human', 'value': 'Hi there!'},
     {'from': 'gpt', 'value': 'Hi how can I help?'},
     {'from': 'human', 'value': 'What is 2+2?'}],
    [{'from': 'human', 'value': 'What's your name?'},
     {'from': 'gpt', 'value': 'I'm Daniel!'},
     {'from': 'human', 'value': 'Ok! Nice!'},
     {'from': 'gpt', 'value': 'What can I do for you?'},
     {'from': 'human', 'value': 'Oh nothing :)'},],
]
```

你可以使用我们的 `get_chat_template` 来进行格式化。选择 `chat_template` 为以下任意一种 `zephyr, chatml, mistral, llama, alpaca, vicuna, vicuna_old, unsloth`，并使用 `mapping` 来映射字典值 `从`, `value` 等等。 `map_eos_token` 允许你将 `<|im_end|>` 映射为 EOS，而无需任何训练。

```python
from unsloth.chat_templates import get_chat_template

tokenizer = get_chat_template(
    tokenizer,
    chat_template = "chatml", # 支持 zephyr, chatml, mistral, llama, alpaca, vicuna, vicuna_old, unsloth
    mapping = {"role" : "from", "content" : "value", "user" : "human", "assistant" : "gpt"}, # ShareGPT 风格
    map_eos_token = True, # 将 <|im_end|> 映射为 </s>
)

def formatting_prompts_func(examples):
    convos = examples["conversations"]
    texts = [tokenizer.apply_chat_template(convo, tokenize = False, add_generation_prompt = False) for convo in convos]
    return { "text" : texts, }
pass

from datasets import load_dataset
dataset = load_dataset("philschmid/guanaco-sharegpt-style", split = "train")
dataset = dataset.map(formatting_prompts_func, batched = True,)
```

你也可以制作自己的自定义聊天模板！例如我们内部使用的聊天模板如下。你必须传入一个 `tuple` 由 `(custom_template, eos_token)` 组成，其中 `eos_token` 必须在模板内部使用。

```python
unsloth_template = \
    "{{ bos_token }}"\
    "{{ 'You are a helpful assistant to the user\n' }}"\
    "</div>"\
    "<div data-gb-custom-block data-tag=\"for\">"\
        "<div data-gb-custom-block data-tag=\"if\" data-0='role' data-1='role' data-2='] == ' data-3='user'>"\
            "{{ '>>> User: ' + message['content'] + '\n' }}"\
        "<div data-gb-custom-block data-tag=\"elif\" data-0='role' data-1='role' data-2='] == ' data-3='assistant'></div>"\
            "{{ '>>> Assistant: ' + message['content'] + eos_token + '\n' }}"\
        "</div>"\
    "</div>"\
    "<div data-gb-custom-block data-tag=\"if\">"\
        "{{ '>>> Assistant: ' }}"\
    "</div>"
unsloth_eos_token = "eos_token"

tokenizer = get_chat_template(
    tokenizer,
    chat_template = (unsloth_template, unsloth_eos_token,), # 你必须提供模板和 EOS 标记
    mapping = {"role" : "from", "content" : "value", "user" : "human", "assistant" : "gpt"}, # ShareGPT 风格
    map_eos_token = True, # 将 <|im_end|> 映射为 </s>
)
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://unsloth.ai/docs/zh/ji-chu/chat-templates.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
