relsent-bert-zh-large知更鸟一个中文人际关系情感分析模型的完整实践从数据合成到 ONNX 部署记录一个三任务联合分类中文情感分析模型的完整开发过程一、背景在日常的聊天、评论、对话场景中文本背后往往同时包含三层信息关系类型这两个人是什么关系恋人、家人、朋友、同事、师生还是陌生人情感极性这段话是正面的、中性的还是负面的关系动态这段关系是在拉近、保持稳定还是在疏远传统情感分析模型通常只做“正面/负面”二分类无法刻画人际关系的多维状态。我尝试训练了一个中文模型同时输出这三个维度的分类结果取名为relsent-bert-zh-large中文代号「知更鸟」。模型已在魔搭社区发布ONNX 格式支持多语言调用。二、模型能力输入一段中文互动文本输出三个维度的分类维度类别数标签关系类型7love / family / friendship / colleague / teacher_student / stranger / other情感极性3positive / neutral / negative关系动态3intimacy / stable / distance示例python复制下载predict(下班了一起去喝酒你叫上老张) # {relation: friendship, sentiment: neutral, dynamic: stable}三、技术方案3.1 基座模型最终选用chinese-roberta-wwm-ext-large330M 参数。中间也试过bert-base-chinese但 large 版本在复合句和边界样本上的表现明显更好。3.2 三任务联合分类模型输出 13 维 logits按维度拆分text复制下载relation logits[:, 0:7] # 7 类关系类型 sentiment logits[:, 7:10] # 3 类情感极性 dynamic logits[:, 10:13] # 3 类关系动态每个维度分别取 argmax 得到预测类别。三个任务共享底层表征联合训练比分别训练三个独立模型更省资源效果也更好。3.3 数据构建训练数据采用LLM 合成 边界样本 人工核验的方式构建最终规模约 8,000 条。中间有几个关键节点初始生成 3000 条主数据集补全 7 种零样本情感后合并至 5000 条定向补齐 other / neutral / stranger / teacher_student / distance 等长尾场景扩充至 6,998 条新增 1,000 条复合句边界样本--complex数据集扩充至 7,998 条后续针对 love anger/conflict、colleague anger/conflict 等混淆场景做定向修复合成数据最大的坑是句式塌缩——LLM 会反复生成高度相似的句式。解决办法是禁止高频句式、做场景轮换、适当提高 temperature。3.4 最大长度调整MAX_LENGTH从 128 调到 256。原因是中文互动文本经常出现 2–4 句的复合句128 会截断后半段的情感转折信息。四、模型性能指标测试集 F1 (macro)关系类型0.799情感极性0.894关系动态0.777平均0.823情感极性最好做关系动态最难——因为“疏远”和“稳定”在短文本里界限比较模糊。五、ONNX 部署模型导出为 ONNX 格式约 1.2 GB接口如下名称形状类型输入input_ids[batch, seq_len]int64输入attention_mask[batch, seq_len]int64输出logits[batch, 13]float325.1 Python 调用bash复制下载pip install onnxruntime tokenizers numpypython复制下载import onnxruntime as ort import numpy as np from tokenizers import Tokenizer session ort.InferenceSession(model.onnx) tokenizer Tokenizer.from_file(tokenizer/tokenizer.json) REL [love, family, friendship, colleague, teacher_student, stranger, other] SENT [positive, neutral, negative] DYN [intimacy, stable, distance] def predict(text: str, max_length: int 256): enc tokenizer.encode(text) ids enc.ids[:max_length] mask [1] * len(ids) ids [0] * (max_length - len(ids)) mask [0] * (max_length - len(mask)) logits session.run(None, { input_ids: np.array([ids], dtypenp.int64), attention_mask: np.array([mask], dtypenp.int64), })[0] return { relation: REL[logits[0, :7].argmax()], sentiment: SENT[logits[0, 7:10].argmax()], dynamic: DYN[logits[0, 10:13].argmax()], } print(predict(下班了一起去喝酒你叫上老张))5.2 Node.js 调用bash复制下载npm install onnxruntime-nodejavascript复制下载const ort require(onnxruntime-node); const REL [love,family,friendship,colleague,teacher_student,stranger,other]; const SENT [positive,neutral,negative]; const DYN [intimacy,stable,distance]; async function predict(text, tokenizer, session) { const enc tokenizer.encode(text, { maxLength: 256 }); const ids Array(256).fill(0); const mask Array(256).fill(0); enc.ids.forEach((id, i) { if (i 256) { ids[i] id; mask[i] 1; } }); const feed { input_ids: new ort.Tensor(int64, BigInt64Array.from(ids.map(BigInt)), [1, 256]), attention_mask: new ort.Tensor(int64, BigInt64Array.from(mask.map(BigInt)), [1, 256]), }; const out await session.run(feed); const logits out.logits.data; return { relation: REL[argmax(logits.slice(0, 7))], sentiment: SENT[argmax(logits.slice(7, 10))], dynamic: DYN[argmax(logits.slice(10, 13))], }; } function argmax(arr) { return arr.indexOf(Math.max(...arr)); }任何支持 ONNX Runtime 的语言都可以调用C#、Java、Go、Rust、Swift、Kotlin 等。六、下游应用场景除了直接分类模型的文本表征向量CLS / mean pooling还可以迁移到场景说明中文知识图谱关系三元组抽取从非结构化文本抽取 (主体, 关系类型, 客体)关系句语义相似度计算基于句向量做关系描述句的检索匹配知识库问答关系链接将问句中的关系描述映射到预定义关系类型RAG 关系粒度向量召回以关系维度构建索引提升检索相关性七、踩过的坑中文引号语法错误合成数据里混入未转义的中文引号导致 JSON 解析失败后来在质检流水线里加了正则校验。torch.cuda.amp.autocastFutureWarningPyTorch 版本升级后 API 变了换成torch.amp.autocast(cuda)解决。边界混淆love 和 colleague 场景下的 anger/conflict 容易互串后来专门写了generate_boundary_fix.py做定向补数据。长尾类别other / stranger / distance 这些类别样本少F1 一直上不去靠定向生成补齐。八、免责声明本模型仅用于文本层面的关系/情感状态识别不是心理诊断工具不是人格评估工具不做婚恋匹配预测输出结果仅供参考不构成任何建议训练数据为 LLM 合成 人工核验可能存在偏差九、许可MIT License项目地址魔搭社区搜索「知更鸟」或「relsent-bert-zh-large」如果这篇文章对你有帮助欢迎点赞收藏。有问题可以在评论区交流。