Skip to content

HomeSense NLI 方向判定模型测试报告(MiniLMv2-XNLI)

🕒 Published at:

HomeSense NLI 方向判定模型测试报告(MiniLMv2-XNLI) ​

日期:2026-09-02 模型:onnx-community/multilingual-MiniLMv2-L6-mnli-xnli-ONNX(int8) 格式:XLMRobertaForSequenceClassification,输入 input_ids+attention_mask,输出 logits(3类) 体积:107MB(单文件,无外部数据) 测试环境:本机 x86_64,onnxruntime-purego(纯 Go,无 cgo)


1. 背景 ​

为缓解 v2 混合检索的方向性硬伤(反义误报:熄灯→开灯、放大→调小),调研业界用 NLI(自然语言推理)模型做方向校准:判定 query 与候选意图是「蕴含 / 矛盾 / 中立」。

对比过的中文 NLI 现成模型:

模型语言ONNX?大小结论
IDEA-CCNL/Erlangshen-Roberta-110M-NLI中文❌ 仅 pytorch409MB无法跑
uer/sbert-base-chinese-nli中文❌ 仅 pytorch-无法跑
onnx-community/EttinX-nli-xxs英文✅17MB中文不支持
onnx-community/multilingual-nli-bert多语含zh✅179MB可用但大
multilingual-MiniLMv2-L6-mnli-xnli多语含zh✅107MB选用(最小中文可用)

2. 调用方式验证 ​

model card 官方用法(NLI):

python
tokenizer(premise, hypothesis, truncation=True)  # <s> premise </s></s> hypothesis </s>
output = model(input_ids)  → logits → softmax → [entailment, neutral, contradiction]

Go 端实现:

  • tok.Encode(tokenizer.NewDualEncodeInput(NewInputSequence(premise), NewInputSequence(hypothesis)), true) 生成 <s> A </s></s> B </s> ✅
  • 输入 input_ids + attention_mask,输出取 logits → softmax → 3 类 ✅
  • 验证 IO:inputs=[input_ids attention_mask] outputs=[logits] ✅

调用方式完全正确,不是误用。


3. 速度实测(x86_64 本机,含 tokenize,IntraOpNumThreads=4) ​

maxLen平均延迟
324.6 ms
646.7 ms
12811.7 ms
长句 12812.3 ms

比 bge embedding(~33ms)还快。ARM64 手机预估放大 2-4 倍 ≈ 30-50ms。速度完全不是问题。


4. 方向判定质量实测(18 组) ​

premisehypothesisENC判定期望正确?
把声音放大调高音量0.330.570.10neutralentail❌
把声音放大调低音量0.130.450.43neutralcontradiction⚠️方向可区分但不够
大声点调高音量0.330.580.09neutralentail❌
小声点调低音量0.140.470.39neutralentail❌
熄灯关灯0.230.190.58contradictionentail❌ 熄=关 判成矛盾
熄灯开灯0.140.090.77contradictioncontradiction✅
把客厅灯灭了关客厅灯0.470.390.14entailentail✅
把客厅灯灭了开客厅灯0.510.360.13entailcontradiction❌ 反义判成蕴含
我到家了回家模式0.220.630.15neutralentail⚠️弱
我要出门了离家模式0.280.420.31neutralentail⚠️弱
我要出门了回家模式0.270.570.16neutralcontradiction⚠️弱
回家回家模式0.610.310.08entailentail✅
开冷气开空调0.310.500.19neutralentail❌弱
投屏到电视投屏0.470.220.30entailentail✅
投屏到电视关电视0.400.350.25entailneutral❌
打开电视开空调0.160.620.21neutralneutral✅
今天天气怎么样回家模式0.100.750.15neutralneutral✅
帮我订个外卖投屏0.170.110.73contradictioncontradiction✅

5. 结论(不粉饰) ​

5.1 能力上限 ​

  • model card 明示 XNLI 平均准确率仅 0.71(15 语言平均),且作者推荐更高性能用 mDeBERTa-v3-base
  • 对中文超短口语短语(熄灯/小声点/灭了)是盲区:
    • 熄灯 → 关灯 被判 contradiction(大错)
    • 把客厅灯灭了 → 开客厅灯 被判 entail(反义判成蕴含)
  • 单独当硬 gate 会引入新的误判,不比现有 hard-negative 方案强

5.2 速度 ​

  • 107MB int8,x86 6-12ms/次,速度完全够用(非瓶颈)

5.3 部署代价 ​

  • 体积 42MB → 149MB(+107MB)
  • 结论:速度可接受,但能力上限(0.71)撑不起方向性硬裁决

6. 后续选项 ​

方案速度体积方向性效果
A. MiniLM 当软校准(与 embedding 加权,不当唯一裁判)+7ms+107MB⚠️ 有改善但不稳
B. mDeBERTa-v3-base NLI❌ 见 7❌❌ 开箱即用的 ONNX 导出不可用
C. hard-negative 逐个钉方向坑(零新增)00⚠️ 治标,已知坑有效
D. 高置信本地 / 低置信云端 LLM(业界混合路由)--✅ 最终形态

7. mDeBERTa-v3-base 实测追击记录(B 方案彻底否决) ​

追加:2026-09-02 晚。MiniLM 不够用时一度想上 mDeBERTa-v3-base(XNLI 中文 accuracy 0.803),对开箱即用的 ONNX 版本做了实测,结论是此路不通,已正式移除 B 方案。

7.1 下载与体积 ​

  • 仓库 onnx-community/mDeBERTa-v3-base-xnli-multilingual-nli-2mil7-ONNX
  • onnx/model_int8.onnx = 338MB(int8);model.onnx = 566MB(fp32)
  • 下载走 hf-mirror.com 镜像,~2MB/s,curl 顺畅(浏览器/hf_hub 直连 huggingface.co 国内不可用)

7.2 架构差异(Disentangled Relative Position) ​

  • config:model_type=deberta-v2,type_vocab_size=0,12 层,hidden 768
  • ONNX 图输入:只有 input_ids + attention_mask(无 token_type_ids)
  • 查证:导出器在 type_vocab_size==0 时会主动删除 token_type_ids → 图里没有它是正常导出,不是漏传。但代价是 DeBERTa 原版用于区分两段话语的 disentangled relative position 信息在 ONNX 图中先天残缺

7.3 速度实测(本机 x86_64,int8,含 tokenize,4 线程) ​

maxLenmDeBERTa-base(12层,338MB)MiniLM-L6(6层,107MB)倍数
3231.7 ms3.4 ms~9x
6459.0 ms6.0 ms~10x
128121.6 ms11.4 ms~11x
  • 速度是致命伤:12 层 attention + disentangled 每层加一个位置计算,延迟几乎随句长线性翻倍
  • 手机 ARM 再放大 2-4x → 家宽指令(64)约 120-240ms,已超短口语输入的手感阈值

7.4 方向判定质量(18 组同款样例)—— 输出退化 ​

全部 18 组样例结果几乎相同,分类头对输入几乎不响应:

premisehypothesisENC
熄灯开灯(应矛盾)0.520.470.01
熄灯关灯(应蕴含)0.470.520.01
把声音放大调高音量(应蕴含)0.560.440.01
把声音放大调低音量(应矛盾)0.550.450.01
帮我订个外卖投屏(应矛盾)0.510.480.01
  • raw logits:entail/neutral 只在 1.37~1.65 区间微动,contradiction logit 被恒定钳在 -2.7 附近 → softmax 后 C 恒为 ~0.01
  • MiniLM 同路径、同代码能给出极化区分(熄灯→开灯 C=0.77),且 Python tokenizers 复现了完全一致的退化结果 → 不是 Go 代码、不是 tokenizer 用法问题
  • 单句输入 vs 双句输入输出几乎相同 → int8 量化把分类头压扁,contradiction 门死亡

7.5 关键否决依据(模型卡原文 + 导出机制) ​

  • 模型卡原文:"mDeBERTa currently does not support FP16" → fp16 版不可用;fp32 原始权重 2GB+,手机存不下
  • XNLI 中文 accuracy 0.803 是长句基准成绩,非超短口语短语
  • int8 量化退化 + ONNX 导出缺失 relative-position 信息双重打击 → 现成 ONNX 无法直接裁决最需要的「反义」

7.6 新结论 ​

  1. mDeBERTa ONNX 这条路整体关闭。不是慢不慢的问题,是现成 int8 导出质量不行(分类头退化)
  2. 要用 mDeBERTa 必须自己做 fp32→int8 重新校准量化,且仍受 TypeVocabSize=0 导出限制 → 投入产出比差
  3. NLI 模型线(MiniLM / mDeBERTa)均不采用,方向性回到规则硬钉(方案 C),云端 LLM 路由(方案 D)作为长期形态
  4. 教训:下大文件(>300MB)用 hf-mirror.com + curl -L 带断点续传,别用浏览器直连 huggingface.co

8. 相关文件 ​

  • 模型:/tmp/minilm-nli/model_nli_int8.onnx + tokenizer.json + config.json(MiniLM,保留)
  • mDeBERTa:/tmp/mdeberta-nli/(int8 338MB,结论不可用,可删)
  • 测试:/tmp/nli-bench/(infer 方向判定、bench 延迟)
  • 模型源:onnx-community/multilingual-MiniLMv2-L6-mnli-xnli-ONNX;onnx-community/mDeBERTa-v3-base-xnli-multilingual-nli-2mil7-ONNX
  • 姊妹篇:~/Desktop/HomeSense-L2-混合检索测试报告.md