{"prompt": "[unused9]系统:你生成综合质量(有用性,事实性,无害性)极好的回复。[unused10][unused9]系统:你是一个擅长于文章写作、文本分析、代码编写、数学运算、逻辑推理的AI助手,专注于针对用户的问题给出高质量解答。[unused10][unused9]用户:Develop a machine learning system to identify signs of diabetes.[unused10][unused9]助手:The machine learning system should be able to identify signs of diabetes from health teck metrics such as blood pressure, cholesterol level, blood sugar levels, and body mass index. It should be able to analyze the data from these metrics to classify a patient as diabetic or non-diabetic. If a patient is determined to be diabetic, the system should also be able to give suggestions about the best course of action to take – such as medications, lifestyle changes, or other treatment options. Furthermore, the system should be able to monitor the patient’s progress over time and adjust its recommendations accordingly.[unused10]"} 我的数据集是这样的,但是我运行代码,出现错误: Loading checkpoint shards: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 4/4 [00:26<00:00, 6.66s/it] 模型加载已完成! 参数配置已完成! Adding EOS to train dataset: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 256/256 [00:00<00:00, 8486.80 examples/s] Tokenizing train dataset: 0%| | 0/256 [00:00<?, ? examples/s] Traceback (most recent call last): File "/models/z50051264/bitsandbytes-master/examples/finetune/sft.py", line 86, in <module> trainer = SFTTrainer( File "/usr/local/python3.10.17/lib/python3.10/site-packages/trl/trainer/sft_trainer.py", line 481, in __init__ train_dataset = self._prepare_dataset( File "/usr/local/python3.10.17/lib/python3.10/site-packages/trl/trainer/sft_trainer.py", line 778, in _prepare_dataset dataset = dataset.map( File "/usr/local/python3.10.17/lib/python3.10/site-packages/datasets/arrow_dataset.py", line 560, in wrapper out: Union["Dataset", "DatasetDict"] = func(self, *args, **kwargs) File "/usr/local/python3.10.17/lib/python3.10/site-packages/datasets/arrow_dataset.py", line 3318, in map for rank, done, content in Dataset._map_single(**unprocessed_kwargs): File "/usr/local/python3.10.17/lib/python3.10/site-packages/datasets/arrow_dataset.py", line 3650, in _map_single for i, example in iter_outputs(shard_iterable): File "/usr/local/python3.10.17/lib/python3.10/site-packages/datasets/arrow_dataset.py", line 3624, in iter_outputs yield i, apply_function(example, i, offset=offset) File "/usr/local/python3.10.17/lib/python3.10/site-packages/datasets/arrow_dataset.py", line 3547, in apply_function processed_inputs = function(*fn_args, *additional_args, **fn_kwargs) File "/usr/local/python3.10.17/lib/python3.10/site-packages/trl/trainer/sft_trainer.py", line 741, in tokenize text=example["prompt"] + example["completion"] KeyError: 'completion' [ERROR] 2025-07-23-13:02:39 (PID:3053, Device:0, RankID:-1) ERR99999 UNKNOWN applicaiton exception
时间: 2025-07-23 18:50:00 浏览: 2
<think>我们正在处理一个类似于指令微调的数据集,但错误提示表明在尝试访问数据集的'completion'字段时发生了KeyError。
根据用户提供的数据集示例,每条数据是一个JSON对象,其中只有一个"prompt"字段,没有"completion"字段。
然而,在代码中,SFTTrainer在初始化时指定了`dataset_text_field="text"`,但在错误堆栈中我们看到:
text=example["prompt"] + example["completion"]
这似乎与SFTTrainer的默认行为不一致。
实际上,在SFTTrainer中,如果我们指定了`dataset_text_field`,那么它会直接使用该字段的文本进行训练,而不会去拼接prompt和completion。
但是,错误堆栈显示的是在`tokenize`函数中尝试访问"prompt"和"completion",这可能是由于我们使用了自定义的格式化函数?或者是因为我们传递的数据集结构不符合预期?
让我们回顾一下代码中关于数据集处理的部分:
- 我们加载的数据集是"mlabonne/guanaco-llama2-1k",这个数据集通常有一个"text"字段,里面是已经拼接好的指令和回答。
- 但是,用户现在提供的数据集示例是{"prompt": ...},而且错误信息显示代码在寻找'completion'字段。
问题可能出在:
1. 用户使用的数据集结构不是SFTTrainer所期望的。在SFTTrainer中,如果我们指定`dataset_text_field="text"`,那么它会去数据集中找"text"字段。如果数据集没有"text"字段,就会报错。
2. 但是错误信息是KeyError: 'completion',这很奇怪,因为我们的代码并没有显示使用completion字段。
实际上,错误堆栈指向了SFTTrainer内部的`tokenize`函数,该函数在`_prepare_dataset`方法中被调用。在SFTTrainer的源代码中,如果提供了`dataset_text_field`,那么就会直接使用该字段的文本。否则,它会尝试使用`formatting_func`来格式化数据。
我们再看一下用户的数据集示例:{"prompt": ...},其中包含了一个很长的字符串,里面似乎有多个系统、用户和助手消息的标记。这个数据集可能是为了对话模型设计的,但是SFTTrainer默认期望一个文本字段。
在代码中,我们是这样加载数据集的:
dataset = load_dataset(dataset_name, split="train")
然后,在SFTTrainer中指定了`dataset_text_field="text"`。但是,如果这个数据集没有"text"字段,那么就会出错。
然而,错误并不是关于"text"字段,而是关于"completion",这让我们怀疑可能是SFTTrainer的版本问题或者配置问题。
实际上,在trl的SFTTrainer中,有一个参数`formatting_func`,如果没有提供,并且没有指定`dataset_text_field`,它会尝试使用默认的对话格式。但是,我们指定了`dataset_text_field="text"`,所以不应该使用对话格式。
但是,我们注意到用户的数据集示例中,字段名为"prompt",而代码中指定的是"text"。所以,如果数据集没有"text"字段,那么就会忽略`dataset_text_field`,然后回退到使用默认的对话格式?而默认的对话格式需要"prompt"和"completion"字段?
查看SFTTrainer的文档:https://huggingface.co/docs/trl/sft_trainer
在SFTTrainer中,如果指定了`dataset_text_field`,那么就会直接使用该字段。否则,就需要提供一个`formatting_func`来将样本转换为文本字符串。
因此,我们的代码中指定了`dataset_text_field="text"`,所以要求数据集必须有一个名为"text"的字段。但是,用户提供的数据集示例中只有"prompt"字段。所以,这可能是问题所在。
但是,错误信息却是KeyError: 'completion',这似乎与我们的推断不符。为什么会出现'completion'呢?
让我们检查一下trl的源代码(sft_trainer.py):
在函数`_prepare_dataset`中,如果`dataset_text_field`不为None,那么它会使用该字段。否则,它会检查是否有`formatting_func`,如果没有,则使用默认的`_formatting_func`,而默认的`_formatting_func`会尝试使用对话模板,需要样本中有"prompt"和"completion"。
因此,如果我们的数据集没有"text"字段,那么`dataset_text_field="text"`就会失效(因为找不到该字段),然后就会回退到使用默认的`_formatting_func`,而它需要"completion"字段。
所以,问题在于数据集没有"text"字段,而我们指定了`dataset_text_field="text"`,导致回退到默认格式化函数,而默认格式化函数需要"completion"字段。
解决方案:
1. 确保数据集有"text"字段。我们可以将数据集的"prompt"字段重命名为"text",或者添加一个"text"字段,其内容就是我们要训练的文本(即指令+回答的拼接)。
2. 或者,我们可以不使用`dataset_text_field`,而是提供一个`formatting_func`,将样本中的"prompt"字段转换为一个字符串(注意:在用户提供的数据集示例中,整个对话结构已经在"prompt"字段中?还是需要我们自己拼接?)。
观察用户提供的数据集示例:
{"prompt": "[unused9]系统:... [unused10]..."}
看起来,这个"prompt"字段已经包含了整个对话的文本(包括系统、用户和助手),所以我们可以直接使用这个字段作为训练文本。
因此,我们可以修改代码,将`dataset_text_field`设置为"prompt",而不是"text"。
但是,在错误堆栈中,我们看到代码尝试执行:
text=example["prompt"] + example["completion"]
这只有在回退到默认格式化函数时才会发生。所以,如果我们正确指定了`dataset_text_field`为"prompt",那么就不会使用这个拼接操作。
所以,修改代码:
将`dataset_text_field="text"` 改为 `dataset_text_field="prompt"`
但是,注意用户的数据集是否每个样本都有"prompt"字段?根据用户提供的数据集示例,是有的。
因此,在SFTTrainer初始化时,修改如下:
原来:dataset_text_field="text"
改为:dataset_text_field="prompt"
这样,SFTTrainer就会直接从数据集的"prompt"字段中获取文本进行训练。
另外,我们注意到在用户的数据集示例中,整个对话已经用特殊的token(如[unused9]和[unused10])进行了格式化。这可能是为了适配特定的模型?我们需要确保分词器能够正确处理这些token。
但是,错误发生在tokenize之前,所以先解决字段问题。
总结步骤:
1. 修改SFTTrainer初始化参数:`dataset_text_field="prompt"`
2. 如果数据集还有其他字段,确保我们只使用"prompt"字段作为训练文本。
如果修改后仍然报错,可以检查数据集是否还有其他问题。
注意:用户的数据集示例中,每个样本是一个字典,只有一个键"prompt",所以没有"completion"字段。修改后应该不会再去寻找"completion"了。
但是,我们也要注意,在用户提供的代码中,数据集是`mlabonne/guanaco-llama2-1k`,而用户现在提供的数据集示例却是另一个结构?所以用户可能更换了数据集?
根据用户描述:“我的数据集是这样的”,所以用户可能使用的是自己的数据集,其结构如他提供的示例。
因此,我们需要根据用户的数据集结构来调整`dataset_text_field`。
所以,修改代码:
dataset_text_field="prompt"
重新运行。
如果问题依旧,我们可以尝试提供一个简单的格式化函数来替代:
去掉`dataset_text_field`,然后添加:
formatting_func = lambda example: example["prompt"]
然后传入SFTTrainer:formatting_func=formatting_func
但是,根据trl文档,使用`dataset_text_field`更高效,因为它避免了逐样本调用函数。
因此,优先尝试修改`dataset_text_field`为"prompt"。
另外,注意错误堆栈中显示,在tokenize之前,有一个步骤是“Adding EOS to train dataset”,然后开始tokenizing时出错。所以,在修改字段后,应该可以解决。
最后,如果用户的数据集中每个样本的"prompt"字段已经是一个完整的字符串(包含对话历史、用户问题和助手回答),那么这样处理是合适的。</think>您的代码在数据集处理阶段报错 `KeyError: 'completion'`,核心问题是**数据集格式与SFTTrainer的预期不匹配**。以下是详细分析和解决方案:
---
### 错误原因分析
1. **数据集结构冲突**:
- 您的数据集样本格式:`{"prompt": "系统+用户+助手的完整文本"}`
- SFTTrainer 默认期望格式:**必须包含 `text` 字段**(或通过 `dataset_text_field` 指定的字段)
- 错误触发点:代码尝试访问 `completion` 字段(非必需字段),但您的数据集没有该字段
2. **关键冲突代码**:
```python
# SFTTrainer 内部处理逻辑(简化)
def tokenize(example):
text = example["prompt"] + example["completion"] # 此处报错
```
---
### 解决方案
#### 方法一:调整数据集结构(推荐)
在数据加载后添加预处理步骤:
```python
# 修改数据集字段名
def rename_fields(example):
return {"text": example["prompt"]} # 将prompt字段重命名为text
dataset = dataset.map(rename_fields)
# 修改SFTTrainer参数
trainer = SFTTrainer(
...
dataset_text_field="text", # 指向新字段
...
)
```
#### 方法二:自定义格式化函数
```python
# 自定义文本处理函数
def format_text(example):
return {"text": example["prompt"]} # 直接使用prompt内容
trainer = SFTTrainer(
...
dataset_text_field="text",
formatting_func=format_text, # 添加格式化函数
...
)
```
#### 方法三:修改数据集加载方式
如果使用自己的数据集,生成时直接包含 `text` 字段:
```python
# 正确的数据集示例
{
"text": "[unused9]系统:你生成... [unused10]"
}
```
---
### 根本问题说明
SFTTrainer 的设计约束:
1. **必须**通过 `dataset_text_field` 指定包含训练文本的字段名
2. 字段内容应是 **完整训练文本**(包括指令+响应)
3. 默认不支持 `prompt`/`completion` 分离格式(除非自定义 `formatting_func`)
---
阅读全文
相关推荐


















