为InternLM2-Chat-1.8B添加自定义词表:适应特定领域术语

张开发
2026/4/7 10:35:30 15 分钟阅读

分享文章

为InternLM2-Chat-1.8B添加自定义词表:适应特定领域术语
为InternLM2-Chat-1.8B添加自定义词表适应特定领域术语你是不是遇到过这样的情况让一个通用的大模型去处理你专业领域的问题比如让它写一份医疗报告或者分析一份法律合同结果它生成的文本要么词不达意要么干脆把一些专业术语拆得七零八落这背后的一个关键原因就是模型的分词器“不认识”你的专业词汇。它就像一本通用的新华字典里面收录的都是日常用词突然遇到“冠状动脉粥样硬化”或者“不可抗力条款”这种专业组合它就懵了只能按照它自己的规则拆成“冠状”、“动脉”、“粥样”、“硬化”完全失去了这个词作为一个整体的专业含义。今天我们就来解决这个问题。我将手把手带你为InternLM2-Chat-1.8B这个轻量又实用的模型添加上属于你自己领域的“专业词典”。整个过程并不复杂跟着步骤走你就能让模型更好地理解和生成你所在行业的专业内容。1. 准备工作理解核心概念与准备环境在开始动手之前我们先花几分钟把几个核心概念搞清楚。这样后面的操作你会更明白每一步在做什么。1.1 分词器到底是什么你可以把分词器想象成模型阅读和写作时用的“切词刀”和“粘合剂”。阅读时理解你的输入当你输入一句话“患者患有急性阑尾炎”分词器负责把这句话切分成一个个模型能理解的“最小单位”token比如可能是[“患者” “患有” “急性” “阑尾炎”]。如果分词器不认识“阑尾炎”它可能会错误地切成[“阑” “尾” “炎”]模型基于错误的分词去理解结果自然就偏了。写作时生成回答模型思考完毕后也是输出一串token分词器再把这些token“粘”回成我们能读懂的汉字或词语。所以一个适配你领域的分词器是模型在你专业领域表现好的基础。1.2 为什么InternLM2-Chat-1.8B需要添加词表InternLM2-Chat-1.8B是一个在大量通用文本上训练出来的模型它的分词器词表可以理解为它的“词汇库”已经非常庞大覆盖了绝大多数日常用语。但对于某些非常垂直、新兴或者专业的领域比如生物医药特定的基因名称如“BRCA1”、药物化学名如“对乙酰氨基酚”。法律金融法律条文编号如“《民法典》第五百六十三条”、金融产品缩写如“ABS”、“MBS”。特定行业企业内部特有的产品代号、流程术语。这些词可能不在它原始的词汇库里。添加自定义词表就是把这些“生词”提前教给分词器告诉它“以后看到这个词要把它当作一个整体来对待不要拆开。”1.3 你需要准备什么操作很简单你只需要一台有Python环境的电脑Linux/Mac/Windows均可。安装好主要的深度学习库transformers和torch。一份你想要添加的自定义词汇列表一个纯文本文件.txt格式。我们先来把环境准备好。打开你的终端或命令行执行下面的命令安装必要的库。pip install transformers torch2. 第一步准备你的自定义词表文件这是最关键的一步你的词表文件决定了要给模型添加哪些“新知识”。创建一个纯文本文件比如我命名为my_custom_words.txt。每一行写一个你想要添加的词汇。这里有几个注意事项一个词一行不要用逗号或空格分隔。优先添加完整术语添加那些作为一个整体才有意义的短语而不是单个字。可以包含数字、字母和符号比如产品型号“ABC-123V2”也可以添加。下面我以医疗领域为例创建了一个词表文件内容冠状动脉粥样硬化 急性淋巴细胞白血病 磁共振成像 腹腔镜手术 幽门螺杆菌 CT检查 核酸检测你可以根据你的领域准备你自己的词表。把它保存好我们下一步就要用到它。3. 第二步加载模型与分词器现在我们开始写Python代码。首先我们需要把原始的InternLM2-Chat-1.8B模型和它的分词器从网上下载到本地。创建一个新的Python脚本比如叫add_vocab.py然后写入以下代码from transformers import AutoTokenizer, AutoModelForCausalLM # 指定模型名称InternLM2-Chat-1.8B model_name internlm/internlm2-chat-1_8b print(f正在加载模型和分词器: {model_name}...) # 加载分词器 tokenizer AutoTokenizer.from_pretrained(model_name, trust_remote_codeTrue) # 加载模型我们主要需要分词器但有时保存时需要模型配置 model AutoModelForCausalLM.from_pretrained(model_name, trust_remote_codeTrue, torch_dtypetorch.float16) print(原始分词器词汇表大小:, len(tokenizer))运行这段代码它会自动从Hugging Face下载模型和分词器。trust_remote_codeTrue参数是因为InternLM系列模型可能需要运行一些自定义的代码来正确加载。看到输出类似“原始分词器词汇表大小: 92544”这样的信息说明加载成功了。这个数字就是当前分词器里有多少个不同的词汇单位。4. 第三步将自定义词汇添加到分词器接下来我们要读取刚才准备的词表文件并把里面的词一个个“喂”给分词器。在上面的代码后面继续添加# 读取自定义词表文件 custom_vocab_file my_custom_words.txt print(f\n正在读取自定义词表文件: {custom_vocab_file}) new_tokens [] with open(custom_vocab_file, r, encodingutf-8) as f: for line in f: token line.strip() # 去掉首尾空白字符 if token and token not in new_tokens: # 确保非空且不重复添加 new_tokens.append(token) print(f发现 {len(new_tokens)} 个自定义词汇待添加。) print(前5个词汇示例:, new_tokens[:5]) # 关键步骤将新词汇添加到分词器 num_added tokenizer.add_tokens(new_tokens) print(f成功向分词器添加了 {num_added} 个新词汇。) # 非常重要调整模型词嵌入层的大小 # 因为模型输入输出的“查找表”需要为新词腾出位置 model.resize_token_embeddings(len(tokenizer)) print(f模型词嵌入层已调整新词汇表大小: {len(tokenizer)})这段代码做了几件事读取你的my_custom_words.txt文件。清理每一行得到纯净的词汇。调用tokenizer.add_tokens()方法将这些词加入到分词器的词汇表中。调用model.resize_token_embeddings()方法告诉模型“我们的词汇表变大了你那个用来表示词义的矩阵词嵌入也需要相应扩大。” 新增词汇的嵌入向量会被随机初始化在后续使用中可以通过微调来学习其含义。5. 第四步测试与验证添加效果添加完了我们得试试看效果。在代码最后加上测试部分# 测试1查看新词是否被正确分配了ID test_phrase 患者需进行冠状动脉粥样硬化检查 print(f\n测试分词效果:) print(f原始句子: {test_phrase}) tokens tokenizer.tokenize(test_phrase) token_ids tokenizer.encode(test_phrase) print(f分词结果: {tokens}) print(f对应的Token ID: {token_ids}) # 测试2反向解码看ID是否能变回原词 decoded tokenizer.decode(token_ids) print(f解码回文本: {decoded}) # 重点检查如果“冠状动脉粥样硬化”被当作一个整体那么它在tokens列表里应该只占一项 if 冠状动脉粥样硬化 in test_phrase: # 简单判断如果分词后的列表长度远小于按字拆分的长度说明可能合并成功了 # 例如“冠状动脉粥样硬化”有7个字如果分词后它只对应1个token那就太好了。 print(\n检查冠状动脉粥样硬化的分词情况:) # 查找这个字符串在分词结果中是否作为一个连续序列出现比较麻烦这里我们用更直观的方法 # 我们分别对“冠状动脉粥样硬化”和它的字进行分词看结果长度 long_word 冠状动脉粥样硬化 chars_of_word list(long_word) # [冠, 状, 动, 脉, 粥, 样, 硬, 化] tokenized_word tokenizer.tokenize(long_word) tokenized_chars [] for char in chars_of_word: tokenized_chars.extend(tokenizer.tokenize(char)) print(f 整体分词: {tokenized_word} (长度{len(tokenized_word)})) print(f 拆字分词: {tokenized_chars} (长度{len(tokenized_chars)})) if len(tokenized_word) len(tokenized_chars): print( ✅ 成功自定义词汇被作为一个整体处理了。) else: print( ⚠️ 该词汇可能未被识别为整体请确认是否已添加至词表文件。)运行你的完整脚本。如果一切顺利你会在输出中看到“冠状动脉粥样硬化”这个长词在tokenized_word结果中很可能被显示为一个单独的token如冠状动脉粥样硬化而在tokenized_chars中则是被拆散的多个字。这就说明我们的添加成功了6. 第五步保存修改后的模型与分词器测试无误后最后一步就是把我们“升级”过的分词器和模型保存下来方便以后直接使用而不用每次都重新添加。在脚本末尾添加保存代码# 保存到新目录 output_dir ./internlm2-chat-1.8b-custom-vocab print(f\n正在保存修改后的模型和分词器到: {output_dir}) # 保存分词器 tokenizer.save_pretrained(output_dir) # 保存模型 model.save_pretrained(output_dir) print(保存完成) print(f你现在可以通过以下方式加载这个定制版模型:) print(f tokenizer AutoTokenizer.from_pretrained({output_dir}, trust_remote_codeTrue)) print(f model AutoModelForCausalLM.from_pretrained({output_dir}, trust_remote_codeTrue))保存后你的本地就会多出一个internlm2-chat-1.8b-custom-vocab文件夹里面包含了模型的所有文件以及我们新定制的分词器配置文件。7. 总结与后续建议走完整个流程你会发现为模型添加自定义词表其实是一个很直观的工程操作。它的核心价值在于用很小的成本准备一个词表文件运行一次脚本就能显著提升模型在特定专业场景下的基础理解能力。不过有几点需要你了解这只是一个开始添加词表只是让模型“认识”了这些词把它们当作一个整体来处理。但这些新词的具体含义、如何在上下文中正确使用模型还没有学到。这需要通过在专业语料上进一步微调模型才能让模型真正掌握这些术语的用法。词表质量很重要不要盲目添加大量词汇。只添加那些高频、关键且确实会被分词器错误拆分的复合术语。过多的无效添加可能会略微拖慢分词速度。后续使用以后你使用这个模型时就加载你保存的./internlm2-chat-1.8b-custom-vocab目录它已经内置了你的专业词表。对于大多数专业领域应用来说先通过添加词表解决“术语识别”问题再考虑是否需要进行深度的模型微调是一个性价比很高的技术路径。你不妨现在就动手为你所在的领域创建一个专属词表体验一下模型理解能力提升带来的变化。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。

更多文章