拓冰建站拓冰建站
首页 / 资讯中心 / 正文

【Bug已解决】Integrate IndicTrans2 models and tokenizer into HF Transformers 解决方案

【Bug已解决】Integrate IndicTrans2 models and tokenizer into HF Transformers 解决方案一、现象长什么样IndicTrans2 是面向印度多语种互译的模型集成进 HF Transformers 时模型和 tokenizer 单独都能加载但一用translationpipeline 或做多语言推理就出问题# 现象 A语言标签 special token 没被识别 ValueError: Token 2te not in tokenizers added_tokens; cannot set src_lang. # IndicTrans2 用 2xx 形式标记源/目标语言但 tokenizer 没把这些登记为 special token # 现象 Btranslation pipeline 找不到模型 ValueError: The task translation is not supported for model_type indic_trans2. # 模型没注册到 TranslationPipeline 的型号映射 # 现象 C多语言批量推理时标签错位 # 把 2en 放源、2hi 放目标输出却混入了别的语言标签 # 因为 tokenizer 把 2en 拆成了 2 en 多个 token而非整体一个 # 典型触发 from transformers import pipeline pipe pipeline(translation, modelai4bharat/indictrans2-indic-en) out pipe(नमस्ते, src_langhi, tgt_langen) # 报现象 A/B最典型的指纹tokenizer 能encode普通文本但语言标签2xx被拆成多个子 token 或未被当作 special token导致翻译方向错乱或 pipeline 不支持。二、背景IndicTrans2 的翻译机制依赖语言标签 token源语言用2src、目标语言用2tgt如2hi、2en作为 prompt 前缀注入。模型靠这些标签判断从哪翻到哪。这带来两个集成要点tokenizer 必须把这些标签整体登记为 special token / added_tokens否则tokenizer(2hi)会被 BPE 拆成2hi模型收不到完整的语言信号。模型必须注册到TranslationPipeline及其src_lang/tgt_lang→ 标签前缀的映射否则pipeline(translation, ...)不认model_type。此外IndicTrans2 区分indic→indicindic→englishenglish→indic等子方向每个方向用的标签前缀不同集成时还要把src_lang/tgt_lang正确映射到对应的2xx标签模板。三、根因根因有三类语言标签未登记为 added_tokens。 tokenizer 的added_tokens/special_tokens里没有2hi这类标签BPE 把它们当普通字符切分。model input_ids里语言标签变成一串无意义的子 token → 模型不知道翻译方向 → 输出错乱或报错。模型未注册到 TranslationPipeline 映射。indic_trans2的model_type没加进TRANSLATION_TASKS/MODEL_FOR_xxx_MAPPINGpipeline(translation)在任务表里查不到 →ValueError: task not supported。src_lang/tgt_lang到标签的映射缺失。 即使 tokenizer 认标签、pipeline 认模型还需要一个函数把用户传的hi/en转成2hi/2en并拼到输入前。这个映射表缺失 → 用户传了src_lang却没生效。四、最小可运行复现下面用纯 Python 模拟语言标签未被登记为 special token被 BPE 拆成多个 tokenfrom typing import List, Dict # 模拟 tokenizer 的 vocab 与 added_tokens VOCAB {न: 1, म: 2, स: 3, त: 4, े: 5, : 6, 2: 7, h: 8, i: 9, : 10} ADDED: Dict[str, int] {} # 有 bug标签没登记 def tokenize_raw(text: str) - List[str]: 有 bug逐字符切2hi 被拆成多个 token。 return list(text) def tokenize_with_added(text: str, added: Dict[str, int]) - List[str]: 修正优先匹配 added_tokens整体。 # 简化若文本以 2 开头且含 整体作为一个 special token if text.startswith(2) and in text: tag text[text.find(2):text.find()1] return [tag] tokenize_with_added(text[text.find()1:], added) return list(text) # 复现2hi नमस्ते 在 bug 版被拆 buggy tokenize_raw(2hi नमस्ते) print(buggy 标签被拆成:, [c for c in 2hi]) # [,2,h,i,] assert 2hi not in .join(buggy) or .join(buggy).count(2hi) 0 # 修正把 2hi 登记为 added token 后整体识别 ADDED[2hi] 100 fixed tokenize_with_added(2hi नमस्ते, ADDED) print(fixed 整体标签:, [t for t in fixed if t.startswith(2)]) # [2hi] assert any(t 2hi for t in fixed)运行后buggy 版把2hi拆成 5 个字符 tokenfixed 版把它作为整体 special token 识别复现并修复了根因 1。五、解决方案第一层最小直接修复最快的止血在加载 tokenizer 后把 IndicTrans2 的全部语言标签登记为 added_tokens并手动构造translationpipeline 所需的标签映射from transformers import AutoTokenizer, AutoModelForSeq2SeqLM LANGS [hi, en, bn, ta, te, mr, gu, kn, ml, pa, ur] def register_indic_tags(tokenizer): 第一层修复把 2xx 语言标签整体登记为 special token。 tags [] for l in LANGS: tags.append(f2{l}) # 源/目标标签 # 去重后添加避免与已有 token 冲突 existing set(tokenizer.added_tokens) to_add [t for t in tags if t not in existing] if to_add: tokenizer.add_special_tokens({additional_special_tokens: to_add}) return tags # 使用 tok AutoTokenizer.from_pretrained(ai4bharat/indictrans2-indic-en) all_tags register_indic_tags(tok) def build_input(text, src, tgt, tok): # 拼上语言标签前缀 prompt f2{src} {text} 2{tgt} return tok(prompt, return_tensorspt, paddingTrue, truncationTrue) # 推理 model AutoModelForSeq2SeqLM.from_pretrained(ai4bharat/indictrans2-indic-en) inp build_input(नमस्ते, hi, en, tok) out model.generate(**inp, max_new_tokens50) print(tok.decode(out[0], skip_special_tokensFalse))第一层让用户立刻能用正确的语言标签做翻译标签不再被拆。六、解决方案第二层结构性改进用IndicTrans2Integration集中处理标签登记 src/tgt 映射 pipeline 注册from dataclasses import dataclass, field from typing import Dict, List dataclass class IndicTrans2Integration: 集中集成 IndicTrans2标签登记、语言映射、pipeline 任务声明。 lang_codes: List[str] field(default_factorylambda: [hi,en,bn,ta,te,mr,gu,kn,ml,pa,ur]) def tag(self, lang: str) - str: assert lang in self.lang_codes, f未知语言码 {lang} return f2{lang} def register_tokens(self, tokenizer): tags [self.tag(l) for l in self.lang_codes] existing set(tokenizer.added_tokens) to_add [t for t in tags if t not in existing] if to_add: tokenizer.add_special_tokens({additional_special_tokens: to_add}) return tags def build_prompt(self, text: str, src: str, tgt: str) - str: # IndicTrans2 方向约定源标签 文本 目标标签 return f{self.tag(src)} {text} {self.tag(tgt)} def pipeline_task_spec(self) - Dict: # 声明该模型支持 translation并把 src_lang/tgt_lang 映射到标签 return { task: translation, model_type: indic_trans2, lang_to_tag: {l: self.tag(l) for l in self.lang_codes}, } # 使用 integ IndicTrans2Integration() integ.register_tokens(tok) prompt integ.build_prompt(नमस्ते, hi, en) # 注册到 TranslationPipeline 型号映射示意 # TRANSLATION_TASKS[indic_trans2] (IndicTrans2ForConditionalGeneration, ...)IndicTrans2Integration把标签登记 语言映射 任务声明收口集成者不再散落处理也避免漏掉某个语言码。七、解决方案第三层断言 / CI 守护用 pytest 固化所有语言标签被登记为整体 special token、pipeline 任务可用import pytest def test_all_lang_tags_registered(): from indic_integ import IndicTrans2Integration integ IndicTrans2Integration() # 构造一个最小 tokenizer 替身 class MiniTok: def __init__(self): self.added_tokens [] def add_special_tokens(self, d): self.added_tokens d[additional_special_tokens] tok MiniTok() tags integ.register_tokens(tok) for l in integ.lang_codes: assert integ.tag(l) in tok.added_tokens, f标签 {integ.tag(l)} 未登记 def test_build_prompt_has_both_tags(): from indic_integ import IndicTrans2Integration integ IndicTrans2Integration() p integ.build_prompt(hello, en, hi) assert 2en in p and 2hi in p def test_pipeline_task_declared(): from indic_integ import IndicTrans2Integration spec IndicTrans2Integration().pipeline_task_spec() assert spec[task] translation assert spec[model_type] indic_trans2CI 跑pytest tests/test_indictrans2_integration.py以后只要有人加语言码却忘了登记标签或漏了 pipeline 声明测试立刻红灯。八、排查清单当 IndicTrans2 集成后翻译方向错乱 / pipeline 不支持按顺序查标签被拆成多个子 token → 用register_indic_tags把2xx整体登记为 added_tokens。pipeline(translation)报 task not supported → 把indic_trans2注册到 TranslationPipeline 映射。用户传了src_lang/tgt_lang没生效 → 加lang_to_tag映射构造 prompt 时拼上标签。多语言批量错位 → 确认每个样本都独立拼了正确的2src ... 2tgt前后缀。长期方案用IndicTrans2Integration把标签登记/映射/任务声明收口避免漏语言码。九、小结Integrate IndicTrans2 models and tokenizer 的根因是IndicTrans2 依赖2xx语言标签 token 表示翻译方向但集成时这些标签没被登记为整体 special token被 BPE 拆碎、模型没注册到 TranslationPipeline、src/tgt 到标签的映射缺失于是翻译方向错乱或 pipeline 不支持。第一层加载后把全部2xx登记为 added_tokens并手动拼语言标签前缀立刻能翻译。第二层用IndicTrans2Integration集中处理标签登记 语言映射 pipeline 任务声明集成不再散落。第三层pytest 断言所有语言标签被登记、prompt 含双标签、pipeline 任务声明存在防止回归。记住多语言翻译模型的语言方向是靠 special token 传达的这些标签必须整体登记为 added_tokens绝不能让 tokenizer 把它们拆成普通字符。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门