You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用BertForQuestionAnswering构建问答机器人遇两类报错求助

解决Hugging Face QA机器人的两类报错问题

先搞懂为啥报错

  • 用DataCollatorForLanguageModeling报错:这个工具是给掩码语言建模(MLM)设计的,会自动生成labels参数,但BertForQuestionAnswering的前向传播只认start_positions和end_positions这俩标签,根本不接受labels,所以直接触发报错。
  • 换DefaultDataCollator后没返回loss:这个工具仅做基础的数据拼接,不会把你的标签转换成QA模型需要的格式,模型拿不到计算损失的必要参数,自然返回不了loss。

具体解决步骤

1. 修正预处理函数(preprocess_func)

必须让预处理后的数据带上start_positions和end_positions,这是QA模型计算损失的核心。参考实现如下:

def preprocess_func(examples):
    tokenizer = AutoTokenizer.from_pretrained("bert-base-chinese")
    
    # 先把intents.json的数据转成标准QA格式:问题、上下文、答案
    questions = [item["question"] for item in examples["intents"]]
    contexts = [item["context"] for item in examples["intents"]]
    answers = [item["answer"] for item in examples["intents"]]
    
    # Tokenize时要返回offset_mapping,用来定位答案在token序列中的位置
    tokenized = tokenizer(
        questions,
        contexts,
        truncation="only_second",
        max_length=512,
        return_offsets_mapping=True,
        padding="max_length"
    )
    
    start_pos = []
    end_pos = []
    
    for i, offset in enumerate(tokenized["offset_mapping"]):
        ans = answers[i]
        start_char = ans["start"]
        end_char = start_char + len(ans["text"])
        
        # 定位答案对应的token起始位置
        token_start = 0
        while token_start < len(offset) and offset[token_start][0] <= start_char:
            token_start += 1
        token_start -= 1
        
        # 定位答案对应的token结束位置
        token_end = len(offset) - 1
        while token_end >= 0 and offset[token_end][1] >= end_char:
            token_end -= 1
        token_end += 1
        
        start_pos.append(token_start)
        end_pos.append(token_end)
    
    # 添加模型需要的标签字段,删除用不上的offset_mapping
    tokenized["start_positions"] = start_pos
    tokenized["end_positions"] = end_pos
    del tokenized["offset_mapping"]
    
    return tokenized

注意:你的intents.json需要先转换为标准QA结构,每条数据需包含question(问题)、context(上下文,若原数据无此字段,可将该意图下的所有回答拼接作为上下文)、answer(包含start字符起始位置和text答案内容)。

2. 使用正确的数据收集器

QA任务不能用MLM专属的收集器,推荐用DataCollatorForTokenClassification,它能正确处理start_positions和end_positions:

from transformers import DataCollatorForTokenClassification

data_collator = DataCollatorForTokenClassification(tokenizer=tokenizer)

也可以自定义一个极简收集器,只要能将所有字段拼接成batch即可:

def qa_collator(features):
    batch = {}
    for key in features[0].keys():
        if isinstance(features[0][key], torch.Tensor):
            batch[key] = torch.stack([f[key] for f in features])
    return batch

3. 验证修复效果

改完后可以做两步验证:

  • 运行预处理函数,检查输出是否包含start_positions和end_positions字段;
  • 用收集器生成batch,喂给模型后查看是否能输出损失:
model = BertForQuestionAnswering.from_pretrained("bert-base-chinese")
outputs = model(**batch)
print(outputs.loss)  # 能打印出具体数值即为修复成功

内容的提问来源于stack exchange,提问作者George

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 16:02:04