> For the complete documentation index, see [llms.txt](https://unsloth.ai/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://unsloth.ai/docs/zh/kai-shi-shi-yong/fine-tuning-llms-guide/datasets-guide.md).

# 数据集指南

## 什么是数据集？

对于 LLM，数据集是可用于训练模型的数据集合。为了便于训练，文本数据需要采用可被分词的格式。你还将学习如何 [在 Unsloth 中使用数据集](#applying-chat-templates-with-unsloth).

创建数据集的关键部分之一是你的 [聊天模板](/docs/zh/ji-chu/chat-templates.md) 以及你将如何设计它。分词也很重要，因为它会将文本拆分为 token，这些 token 可以是词、子词或字符，这样 LLM 就能有效处理它。随后，这些 token 会被转换为嵌入向量，并进行调整，以帮助模型理解含义和上下文。

### 数据格式

为了启用分词过程，数据集需要采用分词器能够读取的格式。

<table data-full-width="false"><thead><tr><th>格式</th><th>说明</th><th>训练类型</th></tr></thead><tbody><tr><td>原始语料</td><td>来自网站、书籍或文章等来源的原始文本。</td><td>持续预训练（CPT）</td></tr><tr><td>指令</td><td>供模型遵循的指令，以及一个期望输出的示例。</td><td>监督式微调（SFT）</td></tr><tr><td>对话</td><td>用户与 AI 助手之间的多轮对话。</td><td>监督式微调（SFT）</td></tr><tr><td>RLHF</td><td>用户与 AI 助手之间的对话，其中助手的回复由脚本、另一个模型或人工评估者进行排序。</td><td>强化学习（RL）</td></tr></tbody></table>

{% hint style="info" %}
值得注意的是，这些类型中的每一种都存在不同的格式风格。
{% endhint %}

## 开始使用

在格式化数据之前，我们想先确定以下内容：

{% stepper %}
{% step %} <mark style="color:绿色;">数据集的用途</mark>

了解数据集的用途将帮助我们确定需要哪些数据以及使用哪种格式。

其用途可能是将模型适配到新任务，例如摘要生成，或提升模型扮演特定角色的能力。例如：

* 基于聊天的对话（问答、学习新语言、客户支持、对话）。
* 结构化任务（[分类](https://colab.research.google.com/github/timothelaborie/text_classification_scripts/blob/main/unsloth_classification.ipynb)，摘要生成、生成任务）。
* 特定领域数据（医疗、金融、技术）。
  {% endstep %}

{% step %} <mark style="color:绿色;">输出风格</mark>

输出风格会让我们知道要使用哪些数据来源来达到期望的输出。

例如，你想实现的输出类型可以是 JSON、HTML、文本或代码。或者你可能希望它是西班牙语、英语或德语等。
{% endstep %}

{% step %} <mark style="color:绿色;">数据来源</mark>

当我们知道所需数据的用途和风格后，就需要分析数据的质量和 [数量](#how-big-should-my-dataset-be) 。Hugging Face 和 Wikipedia 都是很好的数据集来源，而如果你想训练模型学习一门语言，Wikipedia 尤其有用。

数据来源可以是 CSV 文件、PDF，甚至是网站。你也可以 [合成生成](#synthetic-data-generation) 数据，但需要格外小心，确保每个示例都高质量且相关。
{% endstep %}
{% endstepper %}

{% hint style="success" %}
创建更好数据集的最佳方法之一，是将其与 Hugging Face 上更通用的数据集（如 ShareGPT）结合起来，让你的模型更聪明且更多样化。你还可以添加 [合成生成的数据](#synthetic-data-generation).
{% endhint %}

## 🦥 Unsloth 数据配方

[Unsloth 数据配方](/docs/zh/xin/studio/data-recipe.md) 让你上传 PDF 或 CSV 等文档并将其转换为可用的数据集。通过图节点工作流以可视化方式创建和编辑数据集。

recipes 页面是主要入口。Recipes 会本地存储在浏览器中，因此你之后可以返回并继续已保存的工作。从这里，你可以创建一个空白 recipe，或者打开一个引导式学习 recipe。

<div data-with-frame="true"><figure><img src="/files/1a3a53c44a59a493bdab62f046b2394ef4c81b59" alt=""><figcaption></figcaption></figure></div>

数据配方遵循相同的基本流程。先打开配方页面，创建或选择一个配方，在编辑器中构建工作流，验证后运行预览，然后在输出看起来正确时运行完整数据集。添加种子数据和生成块，验证工作流，预览示例输出，然后运行完整数据集构建。

一眼看去，常见的工作流应如下所示：

1. 打开 recipes 页面。
2. 创建一个新 recipe 或打开一个已有 recipe。
3. 添加块来定义你的数据集工作流。
4. 点击 **验证** 以便尽早发现配置问题。
5. 运行预览以快速检查示例行。
6. 当 recipe 准备好后，运行完整的数据集构建。
7. 在图中或在 **执行记录** 视图中查看更多详细信息。
8. 选择 Unsloth 中生成的数据集并对模型进行微调。了解更多：

{% content-ref url="/pages/7223afcfd2df87e1fe32a963c0b5ef0e45f563c5" %}
[Data Recipes](/docs/zh/xin/studio/data-recipe.md)
{% endcontent-ref %}

## 数据格式化

当我们确定了相关标准并收集到必要的数据后，就可以将数据格式化为适合训练的机器可读格式。

### LLM 训练的常见数据格式

对于 [**持续预训练**](/docs/zh/ji-chu/continued-pretraining.md)，我们使用没有特定结构的原始文本格式：

```json
  "text": "Pasta carbonara 是一道传统的罗马意大利面料理。酱汁是通过将生鸡蛋与刨碎的佩科里诺罗马诺奶酪和黑胡椒混合制成的。然后将热意大利面与酥脆的 guanciale（腌制猪颊肉）和蛋液拌匀，利用余热形成奶油般的酱汁。尽管大众普遍认为，正宗的 carbonara 从不包含奶油或大蒜。这道菜很可能起源于20世纪中叶的罗马，但其确切起源仍有争议..."
```

这种格式保留了自然语言流畅性，并允许模型从连续文本中学习。

如果我们要将模型适配到新任务，并希望模型根据一组特定指令一次性输出文本，我们可以使用 **指令** 格式中的 [Alpaca 风格](https://docs.unsloth.ai/basics/tutorial-how-to-finetune-llama-3-and-use-in-ollama#id-6.-alpaca-dataset)

```json
"Instruction": "我们希望模型执行的任务。"

"Input": "可选，但很有用，本质上就是用户的查询。"

"Output": "任务的预期结果以及模型的输出。"
```

当我们需要多轮对话时，可以使用 ShareGPT 格式：

```json
{
  "conversations": [
    {
      "from": "human",
      "value": "你能帮我做卡邦尼意大利面吗？"
    },
    {
      "from": "gpt",
      "value": "你想要传统罗马食谱，还是更简单的版本？"
    },
    {
      "from": "human",
      "value": "请给我传统版本"
    },
    {
      "from": "gpt",
      "value": "正宗的罗马卡邦尼意大利面只使用少数几种食材：意大利面、guanciale、鸡蛋、佩科里诺罗马诺奶酪和黑胡椒。你想要详细食谱吗？"
    }
  ]
}
```

模板格式使用 "from"/"value" 属性键，消息在以下之间交替： `人类`和 `gpt`，从而实现自然的对话流。

另一种常见格式是 OpenAI 的 ChatML 格式，也是 Hugging Face 的默认格式。这可能是使用最广泛的格式，消息在以下之间交替： `用户` 和 `assistant`

```
{
  "messages": [
    {
      "role": "user",
      "content": "1+1 等于多少？"
    },
    {
      "role": "assistant",
      "content": "是 2！"
    },
  ]
}
```

### 使用 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` 函数先将其转换。修改后的代码现在如下：\n\\

  ```
  # 导入数据集
  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,)
  ```

### 数据格式化问答

<mark style="color:绿色;">**问：**</mark> 我如何使用 Alpaca 指令格式？

<mark style="color:绿色;">**答：**</mark> 如果你的数据集已经是 Alpaca 格式，那么请按照 Llama3.1 中所示的格式化步骤 [笔记本 ](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Llama3.1_\(8B\)-Alpaca.ipynb#scrollTo=LjY75GoYUCB8)。如果你需要将数据转换为 Alpaca 格式，一种方法是创建一个 Python 脚本来处理原始数据。如果你正在做摘要任务，可以使用本地 LLM 为每个示例生成指令和输出。

<mark style="color:绿色;">**问：**</mark> 我应该总是使用 standardize\_sharegpt 方法吗？

<mark style="color:绿色;">**答：**</mark> 仅当你的目标数据集采用 sharegpt 格式，而你的模型期望的是 ChatML 格式时，才使用 standardize\_sharegpt 方法。

\ <mark style="color:绿色;">**问：**</mark> 为什么不使用 tokenizer 自带的 apply\_chat\_template 函数。

<mark style="color:绿色;">**答：**</mark> 该 `chat_template` 当模型最初由原始模型所有者上传时，该属性有时会包含错误，并可能需要一段时间才能更新。相比之下，在 Unsloth 中，我们会彻底检查并修复 `chat_template` 我们在将量化版本上传到仓库时，会为每个模型这样做。此外，我们的 `get_chat_template` 和 `apply_chat_template` 方法提供了高级数据处理功能，这些功能已在我们的聊天模板文档中完整记录 [页面](https://docs.unsloth.ai/basics/chat-templates).

<mark style="color:绿色;">**问：**</mark> 如果我的模板目前不被 Unsloth 支持怎么办？

<mark style="color:绿色;">**答：**</mark> 在 unsloth 的 GitHub issues [论坛](https://github.com/unslothai/unsloth)中提交功能请求。作为临时解决方案，你也可以在功能请求获批并合并之前，使用 tokenizer 自己的 apply\_chat\_template 函数。

## 合成数据生成

你也可以使用任何本地 LLM，例如 Llama 3.3（70B）或 OpenAI 的 GPT 4.5 来生成合成数据。通常，最好使用更大的模型，例如 Llama 3.3（70B），以确保最高质量的输出。你可以直接使用 vLLM、Ollama 或 llama.cpp 等推理引擎来生成合成数据，但这需要一些手动工作来收集数据并提示生成更多数据。合成数据有 3 个目标：

* 从零开始产生全新的数据——可以从头生成，也可以基于你现有的数据集。
* 丰富你的数据集，以免你的模型 [过拟合](/docs/zh/kai-shi-shi-yong/fine-tuning-llms-guide/lora-hyperparameters-guide.md#avoiding-overfitting-and-underfitting) 并变得过于特定化
* 增强现有数据，例如自动将你的数据集结构化为正确选定的格式

### 在 Unsloth 中使用合成数据

你可以轻松将任何非结构化或结构化数据上传到 Unsloth Studio 的 [数据 recipes](/docs/zh/xin/studio/data-recipe.md) ，它会自动将其转换为可用的 / 合成数据集。更多详情见 [我们的指南](/docs/zh/xin/studio/data-recipe.md).

<div data-with-frame="true"><figure><img src="/files/d7a623c1009dd96e330afd7e279e05a2e03ae91b" alt="" width="563"><figcaption></figcaption></figure></div>

### 使用本地 LLM 或 ChatGPT 生成合成数据

你的目标是提示模型生成并处理符合你指定格式的 QA 数据。模型需要学习你提供的结构以及上下文，因此请确保你至少已经有 10 个数据示例。示例提示：

* **为现有数据集生成更多对话的提示**:

  <pre data-overflow="wrap"><code><strong>使用我提供的数据集示例，按照其结构并基于这些示例生成对话。
  </strong></code></pre>
* **如果你没有数据集的提示**:

  {% code overflow="wrap" %}

  ```
  为 Coca-Coca 创建 10 个产品评论示例，并将其分类为正面、负面或中性。
  ```

  {% endcode %}
* **未格式化数据集的提示**:

  {% code overflow="wrap" %}

  ```
  将我的数据集整理成适用于微调的 QA ChatML 格式。然后生成 5 个具有相同主题和格式的合成数据示例。
  ```

  {% endcode %}

建议检查生成数据的质量，以移除或改进无关或低质量的回复。根据你的数据集，它在许多方面也可能需要平衡，以免你的模型过拟合。然后你可以将这个清理过的数据集重新输入到你的 LLM 中，以便在更多指导下重新生成数据。

## 数据集常见问题 + 提示

### 我的数据集应该有多大？

我们通常建议用于微调的最低数据量至少为 100 行，以获得较合理的结果。为了获得最佳性能，建议使用超过 1,000 行的数据集，在这种情况下，更多数据通常会带来更好的效果。如果你的数据集太小，你也可以添加合成数据，或者从 Hugging Face 添加一个数据集来丰富它。不过，你微调模型的效果在很大程度上取决于数据集的质量，因此务必彻底清洗并准备好你的数据。

### 如果我想微调一个推理模型，我应该如何构建我的数据集？

如果你想微调一个已经具备推理能力的模型，例如 DeepSeek-R1 的蒸馏版本（例如 DeepSeek-R1-Distill-Llama-8B），你仍然需要遵循问题/任务与答案配对的格式；不过，对于答案，你需要将其改为包含推理/思维链过程以及得出答案所采用的步骤。\n\n对于一个不具备推理能力、而你希望训练其之后具备推理能力的模型，你需要使用标准数据集，但这次不要在答案中包含推理。这一训练过程被称为 [强化学习和 GRPO](/docs/zh/kai-shi-shi-yong/reinforcement-learning-rl-guide.md).

### 多个数据集

如果你有多个用于微调的数据集，你可以：

* 将所有数据集的格式标准化，将它们合并为一个数据集，并在这个统一数据集上进行微调。
* 使用 [多个数据集](https://colab.research.google.com/drive/1njCCbE1YVal9xC83hjdo2hiGItpY_D6t?usp=sharing) 笔记本可直接对多个数据集进行微调。

### 我可以多次微调同一个模型吗？

你可以多次微调一个已经微调过的模型，但更好的做法是将所有数据集合并后一次性完成微调。训练一个已经微调过的模型可能会改变在先前微调过程中获得的质量和知识。

## 在 Unsloth 中使用数据集

### Alpaca 数据集

查看在 Google Colab 中使用 Unsloth 内部 Alpaca 数据集的示例：

<figure><img src="/files/6bd7211a584e8e186a35e687888a7d41336816d3" alt=""><figcaption></figcaption></figure>

现在我们将使用通过 GPT-4 本身生成的 Alpaca 数据集。它包含 52,000 条指令和输出，在 Llama-1 发布时非常受欢迎，因为它使基础 LLM 的微调能够与 ChatGPT 本身相媲美。

你可以访问 GPT4 版本的 Alpaca 数据集 [这里](https://huggingface.co/datasets/vicgalle/alpaca-gpt4.)。下面显示了该数据集的一些示例：

<figure><img src="/files/18ab8cf1c142db8d4ae4237b715b4af08ee5f629" alt=""><figcaption></figcaption></figure>

你可以看到每一行有 3 列——一条指令、一个输入和一个输出。我们本质上会将每一行合并成一个如下所示的大提示词。然后我们用它来对语言模型进行微调，这使它变得非常类似于 ChatGPT。我们将这个过程称为 **监督式指令微调**.

<figure><img src="/files/c0b5a28a20ff7ae93f2c84d93c1f0f1843c402cf" alt=""><figcaption></figcaption></figure>

### 用于微调的多列

但一个大问题是，对于 ChatGPT 风格的助手，我们只允许 1 个指令 / 1 个提示，而不是多列 / 多个输入。例如在 ChatGPT 中，你可以看到我们必须提交 1 个提示，而不是多个提示。

<figure><img src="/files/27ef926c80bbe911b2a6a03ea4cb3e51388853a4" alt=""><figcaption></figcaption></figure>

这实际上意味着，为了使微调真正起作用，我们必须把多列“合并”成 1 个大提示！

例如，著名的 Titanic 数据集有很多很多列。你的任务是根据乘客的年龄、舱位、票价等预测其是幸存还是死亡。我们不能直接把这些信息输入 ChatGPT，而是必须把这些信息“合并”成 1 个大提示。

<figure><img src="/files/51237682d24fcdd7f522c9264e74e906ecce8881" alt=""><figcaption></figcaption></figure>

例如，如果我们用包含该乘客全部信息的“合并”单一提示向 ChatGPT 提问，那么我们就可以让它猜测或预测该乘客是死亡还是幸存。

<figure><img src="/files/988e3dabf006d4e98a3b064c888c3db5ece2ee14" alt=""><figcaption></figcaption></figure>

其他微调库要求你通过将所有列合并为 1 个提示来手动准备微调数据集。而在 Unsloth 中，我们只需提供一个名为 `to_sharegpt` 的函数，它就能一气呵成完成这件事！

<figure><img src="/files/e817fa08b58a208b6effb272b63172d38cfab498" alt=""><figcaption></figcaption></figure>

现在这稍微复杂一些，因为我们允许大量自定义，但有几点需要注意：

* 你必须用花括号括起所有列 `{}`。这些是实际 CSV / Excel 文件中的列名。
* 可选文本组件必须用 `[[]]`包裹。例如如果列 "input" 为空，合并函数就不会显示该文本并跳过它。这对于有缺失值的数据集很有用。
* 选择输出或目标 / 预测列于 `output_column_name`。对于 Alpaca 数据集，这将是 `输出`.

例如在 Titanic 数据集中，我们可以创建如下所示的大型合并提示格式，其中每一列 / 每段文本都变为可选。

<figure><img src="/files/c97fec182823138023625a74acd8bf72566768a0" alt=""><figcaption></figcaption></figure>

例如，假设数据集看起来像这样，且有很多缺失数据：

| 登船港 | 年龄 | 票价   |
| --- | -- | ---- |
| S   | 23 |      |
|     | 18 | 7.25 |

那么，我们不希望结果变成：

1. 该乘客从 S 登船。其年龄是 23。其票价是 **空**.
2. 该乘客从 **空**登船。其年龄是 18。其票价是 7.25 美元。

相反，通过使用 `[[]]`将列可选包裹起来，我们可以完全排除这些信息。

1. \[\[该乘客从 S 登船。]] \[\[其年龄是 23。]] \[\[其票价是 **空**.]]
2. \[\[该乘客从 **空**。]] \[\[其年龄是 18。]] \[\[其票价是 7.25 美元。]]

变为：

1. 该乘客从 S 登船。其年龄是 23。
2. 其年龄是 18。其票价是 7.25 美元。

### 多轮对话

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

<figure><img src="/files/02f83b44488171e282ef1bf51fde26acb96a6a7b" alt=""><figcaption></figcaption></figure>

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

<figure><img src="/files/4849fe401f1d094fbfcce60d2dcb75189316c9ac" alt=""><figcaption></figcaption></figure>

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

然后我们使用 `standardize_sharegpt` 函数，只需将数据集整理成适合微调的正确格式！务必调用这个！

<figure><img src="/files/1e924f8e8f23e8ce40da2876066b9340c6f25e0a" alt=""><figcaption></figcaption></figure>

## 视觉微调

用于微调视觉或多模态模型的数据集也包括图像输入。例如， [Llama 3.2 Vision 笔记本](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Llama3.2_\(11B\)-Vision.ipynb#scrollTo=vITh0KVJ10qX) 使用一个放射学案例来展示 AI 如何更高效地帮助医务人员分析 X 光、CT 扫描和超声图像。

我们将使用 ROCO 放射学数据集的采样版本。你可以访问该数据集 [这里](https://www.google.com/url?q=https%3A%2F%2Fhuggingface.co%2Fdatasets%2Funsloth%2FRadiology_mini)。该数据集包含 X 光、CT 扫描和超声图像，展示医疗状况和疾病。每张图像都附有专家撰写的说明文字。目标是微调一个 VLM，使其成为医务人员有用的分析工具。

让我们看看该数据集，并检查第 1 个示例展示了什么：

```
Dataset({
    features: ['image', 'image_id', 'caption', 'cui'],
    num_rows: 1978
})
```

| 图像                                                                                      | 标注                                    |
| --------------------------------------------------------------------------------------- | ------------------------------------- |
| <img src="/files/e86577dd0fc6ec21972a8e1e764eea71135b9fac" alt="" data-size="original"> | 全景放射图显示右侧后上颌骨有一个溶骨性病灶，并伴有上颌窦底部吸收（箭头）。 |

要格式化数据集，所有视觉微调任务应按如下方式格式化：

```python
[
{ "role": "user",
  "content": [{"type": "text",  "text": instruction}, {"type": "image", "image": image} ]
},
{ "role": "assistant",
  "content": [{"type": "text",  "text": answer} ]
},
]
```

我们将编写一个自定义指令，要求 VLM 扮演放射学专家。注意，不仅可以只有 1 条指令，你还可以添加多轮内容，使其成为动态对话。

```notebook-python
instruction = "你是一位放射学专家。请准确描述你在这张图像中看到的内容。"

def convert_to_conversation(sample):
    conversation = [
        { "role": "user",
          "content" : [
            {"type" : "text",  "text"  : instruction},
            {"type" : "image", "image" : sample["image"]} ]
        },
        { "role" : "assistant",
          "content" : [
            {"type" : "text",  "text"  : sample["caption"]} ]
        },
    ]
    return { "messages" : conversation }
pass
```

让我们将数据集转换为用于微调的“正确”格式：

```notebook-python
converted_dataset = [convert_to_conversation(sample) for sample in dataset]
```

第一个示例如下所示：

```notebook-python
converted_dataset[0]
```

{% code overflow="wrap" %}

```
{'messages': [{'role': 'user',
   'content': [{'type': 'text',
     'text': '你是一位放射学专家。请准确描述你在这张图像中看到的内容。'},
    {'type': 'image',
     'image': <PIL.PngImagePlugin.PngImageFile image mode=L size=657x442>}]},
  {'role': 'assistant',
   'content': [{'type': 'text',
     'text': '全景放射图显示右侧后上颌骨有一个溶骨性病灶，并伴有上颌窦底部吸收（箭头）。'}]}]}
```

{% endcode %}

在我们进行任何微调之前，也许视觉模型已经知道如何分析这些图像了？让我们看看是否如此！

```notebook-python
FastVisionModel.for_inference(model) # 启用推理！

image = dataset[0]["image"]
instruction = "你是一位放射学专家。请准确描述你在这张图像中看到的内容。"

messages = [
    {"role": "user", "content": [
        {"type": "image"},
        {"type": "text", "text": instruction}
    ]}
]
input_text = tokenizer.apply_chat_template(messages, add_generation_prompt = True)
inputs = tokenizer(
    image,
    input_text,
    add_special_tokens = False,
    return_tensors = "pt",
).to("cuda")

from transformers import TextStreamer
text_streamer = TextStreamer(tokenizer, skip_prompt = True)
_ = model.generate(**inputs, streamer = text_streamer, max_new_tokens = 128,
                   use_cache = True, temperature = 1.5, min_p = 0.1)
```

结果如下：

```
这张放射图看起来是上下牙列的全景视图，具体来说是全景断层片（OPG）。

* 全景放射图显示正常的牙科结构。
* 右上方有一个异常区域，表现为一片透亮的骨质区域，对应于上颌窦。

**关键观察**

* 左上牙之间的骨质相对不透光。
* 图像上方有两个大箭头，表明需要更仔细地检查该区域。其中一个箭头位于左侧位置，另一个位于右侧位置。然而，只有
```

更多详情，请查看我们笔记本中的数据集部分 [这里](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Llama3.2_\(11B\)-Vision.ipynb#scrollTo=vITh0KVJ10qX).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://unsloth.ai/docs/zh/kai-shi-shi-yong/fine-tuning-llms-guide/datasets-guide.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
