资讯动态

基于MindSpore与大模型的关系抽取实战:从设计到部署

发布时间:2026/9/19 4:36:43 来源:尧图企业网站定制
1. 关系抽取任务为什么值得单独拎出来做关系抽取Relation Extraction简称 RE在信息抽取这条技术栈里位置其实挺尴尬的。做命名实体识别的人觉得它属于下游做知识图谱的人又觉得它只是上游的一个环节结果就是很多项目里 RE 被草草带过最后整个抽取链路的效果卡在它这里上不去。我从几年前开始接触信息抽取相关的工程踩过最多的坑基本都集中在 RE 这一段实体识别明明召回不错但关系一抽就乱要么漏抽要么把两个八竿子打不着的实体硬扯上关系。这次要聊的是在昇思 MindSpore 框架下用大模型来做 RE 关系抽取子任务的完整实现思路。MindSpore 是华为开源的一套深度学习框架主打全场景统一、自动并行这些特性在国内的 AI 开发生态里用得越来越多。把大模型和 MindSpore 结合起来做关系抽取好处是既能吃到预训练模型带来的语义理解能力又能在国产框架上跑通整条链路对于有信创要求或者想脱离某一家生态的团队来说这条路值得走一遍。这篇文章适合谁看如果你已经做过 NER想往下游走一步把关系也抽出来或者你手上有 MindSpore 环境想拿大模型做点实际的抽取任务再或者你正在搭知识图谱的抽取管线RE 这一段一直调不好——那这篇内容应该能给你一些可以直接抄的作业。我会把整体设计思路、数据准备、模型选型、训练配置、推理部署、问题排查这几个环节都拆开讲尽量把每一步背后的“为什么”说清楚而不是只丢一堆代码让你自己猜。需要提前说明的是RE 这个任务本身有很多种做法有基于规则模板的有基于传统序列标注的也有基于大模型生成式的。我下面讲的方案是以“大模型 提示微调”为主线因为这是目前工程上性价比比较高、迁移性也比较好的一种路子。具体到你的场景可能还需要根据数据量、实体类型、关系种类做调整但核心逻辑是通的。2. 整体方案设计与技术选型拆解2.1 为什么选生成式范式而不是分类式传统的关系抽取主流做法是把问题建模成分类任务给定一个句子和两个实体判断它们之间属于哪种预定义关系或者属于“无关系”。这种做法在 BERT 时代很成熟但有几个明显的短板。第一它依赖实体对枚举一个句子里有 N 个实体就要构造 N×(N-1) 个实体对句子一长计算量就爆炸。第二它很难处理重叠关系也就是同一个实体对之间可能存在多种关系。第三它对未见过的关系类型泛化能力差新增一种关系就得重新标注数据、重新训练。生成式范式换了个思路把关系抽取变成“给定句子让模型直接输出三元组”的任务。模型看到一句话自己判断里面有哪些实体、实体之间是什么关系然后按固定格式吐出来。这样做的好处是实体识别和关系抽取可以放在一个模型里端到端做不用先跑 NER 再跑 RE减少了误差传递。而且新增关系类型时很多时候只需要改一下提示词里的关系列表不用动模型结构。当然生成式也不是没有代价。它的问题在于输出格式的稳定性模型有时候会自由发挥输出一些不符合预期格式的内容。另外推理速度比分类式慢因为要逐 token 生成。所以选生成式的前提是你对抽取精度要求高、关系类型可能动态变化、并且能接受一定的推理延迟。如果是一个关系类型固定、对吞吐量要求极高的场景那分类式可能更合适。2.2 MindSpore 在这个任务里的角色定位MindSpore 在这套方案里承担的是训练和推理的底层框架。它提供了自动微分、算子融合、分布式并行这些能力让你不用手写反向传播也能把大模型跑起来。相比其他框架MindSpore 有几个点在这个任务里比较实用。一个是它的动态图模式调试起来跟写普通 Python 差不多适合在实验阶段快速验证想法。另一个是它的静态图模式训练的时候可以开启图编译优化把计算图整体优化一遍再执行速度会快不少。还有一个是 MindSpore 对昇腾硬件的原生支持如果你手上有昇腾的卡用 MindSpore 能比较充分地利用硬件算力。不过要注意MindSpore 的生态和某些主流框架还是有差异的很多现成的模型权重和工具链需要做转换。比如你想用某个在别的框架上预训练好的大模型可能需要先转成 MindSpore 的格式。这个转换过程有时候会踩坑后面我会专门讲。2.3 大模型选型不是越大越好选大模型做 RE第一个要回答的问题是用多大的模型我的经验是RE 这个任务对模型规模的要求没有通用对话那么高。一个 7B 到 13B 的模型经过合适的微调在关系抽取上的表现往往已经够用了。更大的模型当然可能效果更好但推理成本会成倍上升而且在小数据集上更容易过拟合。具体选哪个模型要看几个因素。如果你的关系类型比较通用比如“位于”“属于”“成立于”这种那用通用能力强的模型就行。如果你的关系类型很垂直比如医疗领域的“药物-治疗-疾病”那最好选一个在这个领域有预训练的模型或者至少用领域数据做过继续预训练。还有一个容易被忽略的点是模型的输出格式遵循能力。生成式 RE 要求模型严格按照你规定的格式输出有些模型虽然语义理解强但就是不爱守格式输出一堆解释性文字。这种模型用在 RE 上会很痛苦因为你要花大量精力做后处理。所以在选型阶段最好先拿几十条样本测一下模型的格式遵循度再决定用哪个。3. 数据准备与标注规范3.1 关系抽取的数据长什么样RE 的数据格式最基础的就是“句子 实体对 关系标签”。但实际做的时候我建议直接按三元组格式来组织也就是“头实体 关系 尾实体”因为这样跟生成式范式的输出格式能对齐后面处理起来省事。一条典型的数据大概是这样句子是“张三于 2010 年加入阿里巴巴担任技术总监”三元组是张三任职于阿里巴巴和阿里巴巴职位是技术总监。注意这里一个句子里可能抽出多个三元组这在生成式范式里是天然支持的模型可以一次输出多个。数据来源上如果你有标注团队那就按标注规范来。如果没有可以考虑用远程监督的方式先造一批弱标注数据再人工筛选。远程监督的思路是拿一个已有的知识库把里面的实体对对齐到语料里如果一句话里同时出现了知识库里的两个实体就假设它们之间是知识库里标注的关系。这种做法噪声很大但作为冷启动的数据来源还是可以的。3.2 标注规范里最容易扯皮的地方做 RE 标注有几个地方特别容易产生分歧必须在规范里写清楚。第一个是关系方向。比如“张三任职于阿里巴巴”和“阿里巴巴雇佣张三”其实是同一个事实但方向相反。你的关系定义里到底是以头实体为主动方还是被动方必须统一。我见过有的项目里不同标注员对方向的理解不一致最后模型学出来的关系全是乱的。第二个是嵌套实体和重叠关系。比如“北京大学附属中学”它本身是一个实体但里面又包含“北京大学”和“附属中学”。这种嵌套情况在 RE 里怎么处理是只标最外层还是每层都标需要提前定好。第三个是负样本的定义。两个实体在句子里同时出现但确实没有关系这种算负样本。但还有一种情况是两个实体之间有关系但这个关系不在你的预定义关系列表里。这种到底算负样本还是忽略也要明确。我的建议是不在列表里的关系直接忽略不要当负样本否则模型会学到“只要不是列表里的关系就输出无关系”泛化能力会变差。3.3 数据格式转换的实操细节假设你拿到的原始数据是 JSON 格式每条数据包含句子和实体列表你需要把它转成生成式 RE 需要的格式。转换的核心是把三元组拼成一段目标文本比如用“头实体 | 关系 | 尾实体”这种分隔符格式。这里有个细节要注意分隔符的选择。不要用句子中可能出现的字符做分隔符比如逗号、句号。我一般用竖线加空格或者用特殊标记。另外如果一句话里有多个三元组它们之间也要有明确的分隔比如用换行或者分号。还有一个坑是实体在句子中的位置信息。生成式范式其实不需要位置信息因为模型是从句子里直接生成实体文本的。但如果你后面要做评估需要把模型输出的实体跟标注的实体对齐那就需要保留位置信息。我的做法是在数据里同时保留三元组和实体的位置训练的时候只用三元组评估的时候用位置来匹配。4. 模型微调与训练配置4.1 提示模板的设计逻辑生成式 RE 的核心是提示模板。模板设计得好不好直接决定模型能不能理解你要它干什么。一个基本的模板大概是这样给定句子{sentence} 请抽取其中的关系三元组关系类型包括{relation_list} 输出格式头实体 | 关系 | 尾实体这个模板看起来简单但有几个地方可以优化。第一关系类型列表的顺序。如果关系类型很多模型可能会因为列表太长而漏掉一些。我的做法是把最常用的关系放在前面或者按字母序排列让模型有个稳定的预期。第二要不要给示例。Few-shot 的方式是在模板里放几个例子让模型照着格式输出。这在数据量少的时候很有用但会占用上下文长度。我的经验是如果训练数据足够zero-shot 模板就够了如果数据少加两三个示例能明显提升格式遵循度。第三输出格式的约束。有些模型会自作主张加一些解释性文字比如“根据句子分析三元组是”。这种输出在训练时可以通过数据清洗去掉但在推理时就需要后处理来提取。更彻底的做法是在模板里明确说“只输出三元组不要输出其他内容”但模型不一定听。所以后处理逻辑还是要准备好。4.2 微调方式的选择全参还是 LoRA大模型微调全参微调效果通常最好但显存占用大训练慢。LoRA 是在模型的部分权重上挂低秩矩阵只训练这些小矩阵显存占用小很多训练也快。对于 RE 这种任务我的经验是 LoRA 基本够用除非你的数据量特别大、关系类型特别复杂才需要考虑全参。LoRA 的几个关键参数秩rank一般取 8 到 64越大拟合能力越强但越容易过拟合alpha 是缩放系数通常取 rank 的两倍dropout 取 0.1 左右防过拟合。这些参数不是绝对的需要根据你的数据量调。数据少的时候 rank 取小一点数据多的时候可以取大一点。在 MindSpore 里做 LoRA需要确认你用的模型实现是否支持。有些 MindSpore 的模型库已经内置了 LoRA 接口直接调用就行。如果没有就需要自己实现主要是把原模型的某些线性层替换成带 LoRA 的版本。这个过程有点繁琐但网上有现成的实现可以参考。4.3 训练参数的实际配置训练参数这块我列一个我常用的配置作为参考具体数值需要根据你的硬件和数据调整。参数推荐值说明学习率1e-4 到 5e-5LoRA 可以用大一点全参要小一点批次大小8 到 32受显存限制可以用梯度累积凑大批次训练轮数3 到 10看验证集效果早停最大序列长度512 到 1024根据句子长度分布定预热比例0.1学习率预热防止初期震荡权重衰减0.01防过拟合这里重点说一下批次大小和学习率的关系。很多人调参的时候只调学习率忽略批次大小的影响。实际上批次大小变了等效学习率也会变。一般来说批次大小翻倍学习率也可以适当调大但不要线性放大大概按平方根比例调就行。还有一个容易忽略的是序列长度。RE 的句子通常不会太长但如果你把提示模板也拼进去整体长度就上去了。我建议先统计一下你的数据里句子长度的分布取 95 分位数作为最大长度这样既能覆盖大部分样本又不会浪费太多计算。5. 推理部署与效果评估5.1 推理阶段的批处理与加速训练完之后推理阶段要考虑的是吞吐量。如果只是跑几百条测试数据那怎么跑都行。但如果要上线服务每天处理几十万条文本那推理效率就很关键了。批处理是最直接的加速手段。把多条输入拼成一个批次一起送给模型能充分利用 GPU 或昇腾卡的并行能力。但批处理有个问题就是不同样本的输出长度不一样需要做 padding。padding 太多会浪费计算所以最好把长度相近的样本放在一个批次里。另一个加速手段是量化。把模型权重从 FP16 量化到 INT8推理速度能提升不少精度损失通常在可接受范围内。MindSpore 支持量化推理具体操作可以参考官方文档。不过量化对 RE 这种生成式任务的影响需要实测有些模型量化后输出格式会变得不稳定。还有一个是 KV Cache 的利用。生成式模型在逐 token 生成时前面已经算过的 key 和 value 可以缓存起来不用重复计算。MindSpore 的推理接口一般会自动处理这个但你需要确认一下是否开启了。5.2 评估指标怎么选RE 的评估最常用的是精确率、召回率和 F1 值。但这里有个细节是按三元组整体算还是按实体对算还是按关系类型算。不同的算法得到的数值可能差很多。我一般会同时看几个层面的指标。三元组级别的 F1 是最严格的要求头实体、关系、尾实体全部正确才算对。实体对级别的 F1 稍微宽松一点只要实体对正确、关系方向正确就算对不要求实体文本完全匹配。关系级别的 F1 只看关系类型判断对不对不管实体。除了这些还有一个容易被忽略的指标是格式错误率。也就是模型输出中有多少条是不符合预期格式的。这个指标在生成式 RE 里很重要因为格式错误意味着这条输出完全不可用。如果格式错误率超过 5%就需要回头检查提示模板或者训练数据。5.3 错误分析与迭代方向评估完之后一定要做错误分析。把模型抽错的三元组拿出来看归类一下错误类型。常见的错误类型有几种实体边界错误比如把“阿里巴巴集团”抽成“阿里巴巴”关系类型混淆比如把“任职于”和“隶属于”搞混漏抽句子里明明有关系但模型没抽出来多抽模型抽出了不存在的关系。针对不同的错误类型迭代方向也不一样。实体边界错误可能需要补充实体识别的训练数据或者在提示模板里强调实体要完整。关系类型混淆需要检查关系定义是否清晰标注是否一致。漏抽和多抽可能是训练数据里负样本比例不对需要调整。我自己的经验是第一轮训练完之后不要急着调参先把错误分析做透。很多时候改数据比调参带来的提升更大。6. 常见问题与排查技巧实录6.1 模型输出格式不稳定的处理这是生成式 RE 最常见的问题。模型有时候输出“头实体 | 关系 | 尾实体”有时候输出“头实体-关系-尾实体”有时候还加一堆解释。处理这个问题我一般分三步走。第一步是在训练数据里统一格式确保所有目标文本都是同一种分隔符。第二步是在推理时加后处理用正则表达式提取符合格式的部分。第三步是如果格式错误率还是很高就在提示模板里加更强的约束比如“必须使用竖线分隔不要使用其他符号”。后处理的正则不用写得太复杂能匹配“任意字符 | 任意字符 | 任意字符”这种模式就行。但要注意如果实体文本里本身包含竖线就会误匹配。所以最好在数据预处理阶段就把实体文本里的特殊字符转义掉。6.2 显存不足的排查思路训练大模型的时候显存不够是另一个高频问题。排查思路是这样的先看模型本身占了多少显存再看批次数据占了多少最后看优化器状态占了多少。模型参数占的显存大致是参数量乘以精度字节数。比如 7B 模型用 FP16就是 7×10^9×2 字节大概 14GB。优化器状态如果是 Adam每个参数要存两个动量又是两倍。所以全参微调 7B 模型光模型和优化器就要 40GB 以上。LoRA 因为只训练少量参数优化器状态小很多显存占用主要就是模型本身。如果显存不够可以尝试几个方向换更小的模型、用 LoRA、减小批次大小、用梯度累积、开启梯度检查点。梯度检查点是用计算换显存会慢一些但能省不少显存。MindSpore 支持这些特性具体怎么开可以查文档。6.3 关系类型新增后的处理业务需求变化要新增关系类型这是很常见的情况。生成式 RE 的好处是新增关系类型不一定需要重新训练。你可以先在提示模板里把新关系加进去直接推理试试。如果模型能理解新关系的含义那就不用重新训练。如果效果不好再考虑用少量新数据做微调。但这里有个坑如果你新增的关系类型跟已有的某个关系类型语义很接近模型可能会混淆。比如已经有“任职于”现在新增“工作于”这两个意思差不多模型可能分不清。这种情况下要么合并这两个关系要么在提示模板里给出明确的区分说明。6.4 常见问题速查表问题现象可能原因排查方向输出格式混乱训练数据格式不统一检查目标文本的分隔符是否一致漏抽严重负样本比例过高调整训练数据中正负样本比例关系类型混淆关系定义不清晰检查标注规范补充区分性描述推理速度慢未开启批处理或量化检查推理配置开启批处理和 KV Cache显存溢出批次太大或模型太大减小批次改用 LoRA开启梯度检查点新增关系效果差模型未见过新关系在提示模板中加说明或用少量数据微调6.5 几个我踩过的坑第一个坑是数据泄露。有一次我做训练集和验证集划分的时候没注意同一个句子可能出现在两个集合里结果验证集 F1 虚高上线后效果差很多。后来我改成按句子去重再划分才反映真实水平。第二个坑是提示模板里的关系列表顺序。我一开始随便排的后来发现模型对列表前面的关系抽得准后面的容易漏。把常用关系放前面之后整体召回提升了不少。第三个坑是忽略了特殊字符的处理。有些句子里包含竖线、换行符直接拼进目标文本里会把格式搞乱。后来我在预处理阶段统一把这些字符替换掉问题就解决了。第四个坑是评估时没对齐实体。模型输出的实体文本跟标注的实体文本可能有细微差异比如多了个空格。如果直接字符串匹配会误判为错误。后来我改成先做标准化再去空格评估结果才准确。7. 一些实操层面的补充建议如果你打算在自己的环境里复现这套方案我建议先从一个小规模的数据集开始比如几百条数据把整条链路跑通。不要一上来就上全量数据那样出了问题很难定位。跑通之后再逐步扩大数据量观察效果变化。MindSpore 的环境配置建议用官方提供的 Docker 镜像能省去很多依赖问题。如果你用的是昇腾硬件还需要装对应的固件和驱动这部分参考官方文档就行。模型权重转换如果遇到问题可以先在 CPU 上跑通小模型确认流程没问题再上大模型。训练过程中建议把日志打全一点包括损失曲线、学习率变化、验证集指标。这些日志在排查问题时很有用。另外定期保存检查点不要只保存最后一个。有时候中间某个检查点的效果反而更好。推理部署的时候如果对延迟敏感可以考虑把模型蒸馏到更小的模型上。蒸馏的做法是用大模型的输出作为软标签训练一个小模型。这样小模型能学到一部分大模型的能力推理速度会快很多。不过蒸馏需要额外的训练成本是否值得要看具体场景。最后说一个关于关系抽取本身的体会。RE 这个任务数据质量比模型结构重要得多。我见过太多项目花大量时间调模型但标注数据里一堆不一致的地方最后效果怎么都上不去。所以如果你刚开始做 RE先把标注规范定清楚把数据质量抓起来比什么都强。模型选型、参数调整这些都是在数据质量过关的前提下才有意义。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价