Instructions to use MaYiding/EventTwin with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use MaYiding/EventTwin with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="MaYiding/EventTwin")# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("MaYiding/EventTwin") model = AutoModelForCausalLM.from_pretrained("MaYiding/EventTwin", device_map="auto") - Notebooks
- Google Colab
- Kaggle
# pip install -U transformers accelerate
# Load model directly
from transformers import AutoTokenizer, AutoModelForCausalLM
tokenizer = AutoTokenizer.from_pretrained("MaYiding/EventTwin")
model = AutoModelForCausalLM.from_pretrained("MaYiding/EventTwin", device_map="auto")EventTwin v2.6 · 中文同事件判定器
TL;DR (EN) — EventTwin judges whether two Chinese event-mention frames refer to the same real-world
event instance (cross-document event coreference for news clustering). v2.6 is a correction release.
We found and fixed a training-loss bug present in every 4B version (v2.0–v2.5), re-labelled the benchmark
with independent LLM annotators (gold v2), added a separate calibration set for thresholds, and audited
the training data. On gold v2 (strict "same instance" labels, full-length input) v2.6 reaches AUROC 0.9966
(v2.5: 0.9824, v2.3: 0.9864). With the published three-way thresholds it auto-merges 94.7% of true
pairs and escalates only 3.8% of the stratified hard set, at 1.06% false merges / 1.22% misses
(v2.5 under the same protocol: 18.7% escalation, 1.46% / 1.63%). Several headline numbers reported for
v2.5 were measurement artefacts and are retracted below. v2.6 changes the input protocol: full-length input,
decisions on the logit difference ld, thresholds in eventtwin.json. Older versions remain available
as tags. Data: EventTwin-Data v2.6.
这个模型做什么
输入两条中文事件提及(结构化框架文本:类型/阶段/主体/对象/动作/范围/时间 + [类型] + (时间) + 证据引文),
判断它们是否指同一次现实发生(口径 A:只有 SAME_INSTANCE 算同一事件;同一进程的不同阶段、整体与其中一项、
同一进程的先后里程碑都算不同事件)。输出 ld = logit(yes) − logit(no),按发布阈值三路路由:自动并 / 自动拒 / 升级终审。
⚠️ 输入协议(v2.6 变化,必读)
发布阈值只在下面这个协议下成立:
- 全长输入,不做字符截断(v2.0–v2.5 每侧截 200 字,会丢掉 57% 提及的证据引文;v2.6 训练与定阈都用全长);
- 模板 = Qwen3-Reranker 打分模板,system prompt 见下(yes/no 不加引号),左 padding,
max_length=1152,add_special_tokens=False,取末位 yes/no 两个 logit 之差ld; - 判定看
ld与eventtwin.json里的阈值;校准概率p = sigmoid(ld / T),T = 0.5045(calibration.json)。
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
tok = AutoTokenizer.from_pretrained("MaYiding/EventTwin"); tok.padding_side = "left"
model = AutoModelForCausalLM.from_pretrained("MaYiding/EventTwin", dtype=torch.bfloat16).cuda().eval()
SYSTEM = ("Judge whether the Document meets the requirements based on the Query. Only give me the judgment "
"and do not output any other words or explanations. The judgment should be yes or no.")
TPL = ("<|im_start|>system\n{s}<|im_end|>\n<|im_start|>user\nQuery: {a}\nDocument: {b}\n"
"Judgment: <|im_end|>\n<|im_start|>assistant\n")
YES, NO = tok("yes", add_special_tokens=False)["input_ids"][0], tok("no", add_special_tokens=False)["input_ids"][0]
@torch.no_grad()
def ld(a: str, b: str) -> float:
inp = tok(TPL.format(s=SYSTEM, a=a, b=b), return_tensors="pt", truncation=True,
max_length=1152, add_special_tokens=False).to("cuda")
la = model(**inp).logits[0, -1].float()
return float(la[YES] - la[NO])
def route(x: float, auto_merge=-0.28125, auto_reject=-1.8359375) -> str: # eventtwin.json · default
return "SAME" if x >= auto_merge else "DIFF" if x <= auto_reject else "ESCALATE"
批量推理、阈值档切换与概率换算:GitHub inference_v2_6.py。
决策阈值(eventtwin.json)
阈值在定阈集(与金标同一抽样器换种子的 1,000 对,独立代理标注)上按分位数定,在金标 v2(1,000 对)上测:
| 档 | 目标(定阈集) | 自动并 ld ≥ |
自动拒 ld ≤ |
金标误并 [CP95] | 金标漏并 | 升级率 | 真同事件自动并 |
|---|---|---|---|---|---|---|---|
| default | FM ≤1%、miss ≤1% | −0.281(p 0.364) | −1.836(p 0.026) | 1.06%(8/755) [0.46, 2.08] | 1.22%(3/245) | 3.8% | 94.7% |
| conservative | FM ≤0.6%、miss ≤1% | +0.422(p 0.698) | −1.836(p 0.026) | 0.79%(6/755)[0.29, 1.72] | 1.22% | 4.9% | 91.0% |
- 默认档的 8 对误并:子事件 4、阶段变体 3、兄弟子事件 1——都是"相关但不是同一次"的结构关系,没有无关事件被并。
- 金标与定阈集合并后做 300 次分层折半交叉验证(一半定阈、一半测):目标 1% 时测试 FM 1.03%、自动并 93.2%、升级率 3.9%。
- 两套样本都是生产库分层抽样(难例占比远高于真实流),真实流的类先验不同:上线后请按簇抽检复核阈值; p 阈值只是同一点在 T 下的换算,看起来低(0.364)是因为 FM 按全部负例计、而阈值附近的对本来就难。
版本对比(同一评测协议)
金标 v2 · 口径 A · 全长输入 · 阈值都在定阈集上按 FM ≤1%、miss ≤1% 定(各版本自己的分数):
| v2.3(v26) | v2.5(v32) | v2.6 | |
|---|---|---|---|
| AUROC 口径 A(只 SAME_INSTANCE 算同一) | 0.9864 | 0.9824 | 0.9966 |
| AUROC 口径 B(阶段变体也算同一) | 0.9945 | 0.9916 | 0.9968 |
| 金标误并 / 漏并 | 0.79% / 0.41% | 1.46% / 1.63% | 1.06% / 1.22% |
| 升级率 | 19.4% | 18.7% | 3.8% |
| 真同事件自动并 | 43.7% | 44.9% | 94.7% |
| ECE(T 在定阈集上拟合) | 0.297 | 0.037 | 0.011 |
v2.6 − v2.5 = **+0.0143 [+0.0079, +0.0216]**,v2.6 − v2.3 = +0.0103 [+0.0047, +0.0167](配对分层 bootstrap)。 v2.3/v2.5 的训练集与金标/定阈集有 37–39% 的对逐字重叠,它们的数字只会偏乐观;v2.6 的训练集已去掉这些行, 且代理改标从不施加于触及任何评测提及的行(见下文"X 协议")。
撤回与更正(v2.5 及更早的发布说明)
- 训练损失有缺陷(v2.0–v2.5 全部受影响):decoder 分支把
log σ(ld)当 logit 再过一次 BCE(双重 sigmoid), 正例目标不可达、正侧饱和、负侧被钉在不动点。v2.6 用--loss ce(BCEWithLogits(ld, y),与推理同一函数)。 - "v2.5 AUROC/pos 家族纪录""误并最低""ECE 最佳"撤回:它们来自 float32 饱和造成的大量并列分数、 v1 教师标签(不确定带错 28%)、以及 200 字截断。换成金标 v2 + ld 排序 + 全长输入后,v2.5 相对 v2.3 显著退步。
- v1 benchmark 的标签不再作为主金标:改用金标 v2(Opus + Sonnet 双盲 + 仲裁,九类关系,κ 0.94)。 注意这是独立 LLM 代理标注,不是人工金标。
v2.6 训练方法
- 基座:Qwen/Qwen3-Reranker-4B,decoder 式 yes/no 打分; LoRA r=32 / α=64(q/k/v)、R-Drop 2.0、EMA、标签平滑 0.05、软标签裁剪 [0.05, 0.95]、lr 1e-4、1 epoch、max_len 768; 损失 = ce(修复后的 BCEWithLogits(ld, y))。
- 数据(63,563 个训练样本,EventTwin-Data v2.6): v2.5 的短句对换成补全证据 / [类型] / ISO 时间的部署格式框架;删去与评测对逐字相同的 761 行; 1,465 行教师标签被代理定稿替换(四轮:教师不确定带、置信学习、阶段字段定向复核、折外置信学习;Opus + Sonnet 双盲, 分歧交 GLM 第三票);其中真实数据通道、两侧"阶段"字段不同的 426 行对比样本复制为 4 份。
- X 协议:代理定稿只施加于两侧提及都不在任何评测对中的训练行——模型从未在评测提及上见过代理标签, 改标收益只能来自泛化,不能来自记忆。
- 权重平均(model soup):同配方两种子(20261012 / 20261013)各自合并 LoRA 后逐参数平均,发布的是平均后的完整权重。 三个种子相对同种子的对照配方(不含后两轮定稿与阶段加权)AUROC 都显著更高(+0.0014 / +0.0018 / +0.0018); 三种子 soup 与两种子 soup 无差别;复制份数 ×2 / ×4 / ×8 中 ×4 的阈值迁移最稳。
- 温度:T = 0.5045,在定阈集上最小化 NLL 拟合;金标 ECE 0.0106(T=1 时 0.0886)。
评测与可信度
- 金标 v2:1,000 对分层样本(簇内 210 / 转载 90 / 同类型负 200 / 跨类型负 200 / 灰带 300); 需要复核的 345 对由 Opus + Sonnet 拆问式双盲 + Opus 仲裁,其余置信带对沿用教师标签(抽检 0/100 分歧)。
- 定阈集:同一抽样器换种子的 1,000 对,Opus + Sonnet 双盲 + GLM 第三票(口径 A κ 0.965),只用于定阈与拟合温度。
- 真实决策回放(独立的回放实验,2026-10-01 库快照,763 条有候选的生产决策、27,702 对):自动并 93.8%、升级 5.2%; 545 对裁决中,与现网决策一致的自动并对口径 A 假并 2.1%(口径 B 0%)。回放对有 61% 出现在训练集中,仅作参考。
- 统计口径:配对分层 bootstrap;工作点比较一律两种子以上或 soup——单种子的阈值与"显著"都不可靠。
局限(如实)
- 金标与定阈集都是 LLM 代理标注,不是人工金标;代理之间可能共享先验。
- 剩余误并集中在子事件与阶段变体(同一进程的不同阶段、整体公告与其中一项)。若下游把阶段变体视为同一事件(口径 B), 同阈值下误并约 0.7%。
- "阶段字段不同"这一加权规则是在评测集上发现的,评测收益可能偏乐观;上线前请在真实流上按簇抽检。
- 输入是事件抽取器产出的框架文本;长文原文、其他语言、非企业新闻域未验证。4B 权重 8 GB,需要 GPU。
选型
- v2.6(main):默认之选。
- v2.5 / v2.4 / v2.3 / v2.2 / v2.1 / v2.0 / v1.x:tag 保留用于复现;它们的发布阈值基于 v1 标签与 200 字截断协议, 不建议新接入。
版本说明
公开版本与内部代号解耦:v1.0 = v8 / v1.1 = v9 / v1.2 = v10a / v2.0 = v15_4b / v2.1 = v23b / v2.2 = v24b / v2.3 = v26 / v2.4 = v29 / v2.5 = v32 / v2.6 = rcsx_soup(ab_loss_rcsx_s12 + ab_loss_rcsx_s13)。注意 v2.6 ≠ 内部 v26。
引用
@misc{eventtwin-2026,
title = {EventTwin: A Calibrated Chinese Cross-Encoder Family for Same-Event Judgment},
author = {Ma, Yiding},
year = {2026},
url = {https://huggingface.co/MaYiding/EventTwin},
note = {v2.6: loss fix, LLM-annotated gold v2, calibration-set thresholds, stage-contrast reweighting, 2-seed soup}
}
许可
Apache 2.0(基座 Qwen3-Reranker-4B 为 Apache 2.0)。训练与评测数据见 EventTwin-Data(CC BY-NC 4.0,含新闻摘录)。
- Downloads last month
- 155
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="MaYiding/EventTwin")