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

如何让预训练MarianMT模型不翻译或保留指定特殊字符?

解决MarianMT保留特殊标记的问题

核心问题说明

预训练MarianMT模型默认不会识别自定义特殊标记(比如<P>),add_special_tokens参数仅对模型原生定义的特殊token(如<pad>、<unk>)生效,对这类自定义标记完全不起作用,所以才会出现标记被翻译或删除的情况。要实现保留标记,得从输入预处理、tokenizer配置、生成约束这几个环节入手。

具体解决方案

1. 标记替换还原法(无需修改模型)

这是最直接的方案,先把特殊标记替换成模型不会翻译的占位符,翻译完成后再还原回去:

from transformers import MarianMTModel, MarianTokenizer

# 加载示例模型与tokenizer
model_name = "Helsinki-NLP/opus-mt-en-es"
tokenizer = MarianTokenizer.from_pretrained(model_name)
model = MarianMTModel.from_pretrained(model_name)

# 定义自定义标记与占位符的映射
special_tag_map = {"<P>": "[FIXED_TAG_P]"}

def preprocess_input(text):
    for tag, placeholder in special_tag_map.items():
        text = text.replace(tag, placeholder)
    return text

def postprocess_output(text):
    for tag, placeholder in special_tag_map.items():
        text = text.replace(placeholder, tag)
    return text

# 测试流程
input_text = "Hello <P> this is a test"
processed_text = preprocess_input(input_text)
inputs = tokenizer(processed_text, return_tensors="pt")
outputs = model.generate(**inputs)
translated_raw = tokenizer.decode(outputs[0], skip_special_tokens=True)
final_result = postprocess_output(translated_raw)
print(final_result)

2. 扩展Tokenizer词汇表(需适配模型)

把自定义标记加入tokenizer的词汇表,让模型将其视为独立token,避免被拆分或翻译:

# 将自定义标记添加到tokenizer
tokenizer.add_tokens(list(special_tag_map.keys()))
# 调整模型嵌入层尺寸以适配新词汇
model.resize_token_embeddings(len(tokenizer))

# 直接输入带特殊标记的文本推理
input_text = "Hello <P> this is a test"
inputs = tokenizer(input_text, return_tensors="pt")
outputs = model.generate(**inputs)
translated_text = tokenizer.decode(outputs[0], skip_special_tokens=False)
print(translated_text)

如果模型仍尝试翻译这些标记,建议用包含这类标记的平行语料做少量微调,强化模型对标记的认知,让它明白这些标记不需要翻译。

3. 生成时强制约束标记保留

通过prefix_allowed_tokens_fn函数约束模型生成逻辑,确保特殊标记完整保留:

def restrict_token_generation(batch_id, input_ids):
    current_text = tokenizer.decode(input_ids, skip_special_tokens=True)
    # 检查是否有未完成的特殊标记,强制生成剩余部分
    for tag in special_tag_map.keys():
        if tag[:-1] in current_text and not current_text.endswith(tag):
            remaining_part = tag[current_text.rfind(tag[:-1])+len(tag[:-1]):]
            allowed_token_ids = tokenizer.encode(remaining_part, add_special_tokens=False)
            return allowed_token_ids
    return None

# 应用约束生成结果
outputs = model.generate(**inputs, prefix_allowed_tokens_fn=restrict_token_generation)
translated_text = tokenizer.decode(outputs[0], skip_special_tokens=False)
print(translated_text)

方案优先级建议

优先用标记替换还原法,无需修改模型结构,适配所有预训练MarianMT模型;如果要求必须保留原始标记格式,再尝试词汇表扩展+微调的方案;生成约束法可作为补充,用于特殊场景下的标记保护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 10:55:22