Text Classification
Transformers
Safetensors
Chinese
spam-detection
advertising-detection
ad-classification
chinese
modernbert
mmbert
multi-task
four-head
Instructions to use x6nux/laya-ad with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use x6nux/laya-ad with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="x6nux/laya-ad")# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("x6nux/laya-ad", device_map="auto") - Notebooks
- Google Colab
- Kaggle
File size: 6,707 Bytes
71dabc7 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | #!/usr/bin/env python3
"""清洗 archive(群消息导出 + 判定流水)→ 微调管线格式。
输入:data/raw/archive/archive/<chat_id>/{messages,judgments}-YYYY-MM-DD.jsonl
- 只取 judgments(自带 text 与 verdict);messages 用于 join 校验与 kind 统计
- verdict ∈ {ad, clean};skipped / error 剔除
- 生产兜底口径:verdict=ad 且 ad_kind 缺失/none → clean
标注强度(decider):
强:llm、systemone+llm、phash、rule:<n>
弱:systemone(旧初判模型自标注,训练默认不用)
去重与裁决(按 text 分组):
同文本多 sighting → 强标注优先;强 vs 强 标签矛盾 → 丢弃(报告计数)
--exclude-against 指定已有语料,剔除已存在的文本(增量净新增)
输出(默认 data/raw/archive/converted/):
archive.strong.binary.jsonl 强标注唯一文本(推荐增补)
archive.all.binary.jsonl 含弱标注的全量唯一文本(参考/弱监督)
archive.report.json 统计与矛盾明细计数
用法:
python scripts/convert_archive.py
python scripts/convert_archive.py --exclude-against data/raw/dataset/converted/gold.binary.jsonl
"""
import argparse
import glob
import json
import re
from collections import Counter
from pathlib import Path
STRONG_DECIDERS = {"llm", "systemone+llm", "phash"}
def is_strong(decider: str) -> bool:
return decider in STRONG_DECIDERS or (decider or "").startswith("rule:")
def load_existing(pattern: str | None) -> set[str]:
if not pattern:
return set()
texts = set()
for p in glob.glob(pattern):
for line in open(p, encoding="utf-8"):
line = line.strip()
if line:
texts.add(json.loads(line)["text"].strip())
return texts
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--src", default="data/raw/archive/archive")
ap.add_argument("--out_dir", default="data/raw/archive/converted")
ap.add_argument("--exclude-against", default=None,
help="已有语料 glob,剔除其中已出现的文本(增量净新增)")
args = ap.parse_args()
existing = load_existing(args.exclude_against)
stat = Counter()
groups: dict[str, list[dict]] = {}
for p in sorted(glob.glob(f"{args.src}/*/judgments-*.jsonl")):
for line in open(p, encoding="utf-8"):
line = line.strip()
if not line:
continue
r = json.loads(line)
verdict = r.get("verdict")
if verdict in ("skipped", "error") or verdict not in ("ad", "clean"):
stat[f"剔除:verdict={verdict}"] += 1
continue
text = (r.get("text") or "").strip()
if not text:
stat["剔除:空文本"] += 1
continue
kind = r.get("ad_kind")
if verdict == "ad" and (not kind or kind == "none"):
verdict = "clean"
stat["修正:ad+kind_none→clean"] += 1
decider = r.get("decider") or ""
groups.setdefault(text, []).append({
"label": "ad" if verdict == "ad" else "normal",
"strong": is_strong(decider),
"decider": decider,
"ad_kind": kind,
"action": r.get("action"),
"chat_id": r.get("chat_id"),
"message_id": r.get("message_id"),
"confidence": r.get("confidence"),
})
stat["judgment 行"] = sum(len(v) for v in groups.values()) + \
sum(v for k, v in stat.items() if k.startswith("剔除"))
resolved: dict[str, dict] = {}
for text, sightings in groups.items():
if len(sightings) > 1:
stat["去重:同文本多 sighting"] += 1
strong = [s for s in sightings if s["strong"]]
pool = strong or sightings
labels = {s["label"] for s in pool}
if len(labels) > 1:
key = "丢弃:强标注矛盾" if strong else "丢弃:弱标注矛盾"
stat[key] += 1
continue
best = sorted(pool, key=lambda s: (s["strong"], s["confidence"] or 0), reverse=True)[0]
resolved[text] = {**best, "text": text}
strong_rows = {t: v for t, v in resolved.items() if v["strong"]}
excluded = 0
if existing:
before = len(strong_rows)
strong_rows = {t: v for t, v in strong_rows.items() if t not in existing}
excluded = before - len(strong_rows)
stat["剔除:已在现有语料中"] = excluded
out_dir = Path(args.out_dir)
out_dir.mkdir(parents=True, exist_ok=True)
def dump(path: Path, rows: dict):
with open(path, "w", encoding="utf-8") as f:
for row in sorted(rows.values(), key=lambda r: (r["label"], r["text"])):
f.write(json.dumps({
"text": row["text"], "label": row["label"],
"source": "archive", "decider": row["decider"],
"ad_kind": row["ad_kind"], "action": row["action"],
"strong": row["strong"],
}, ensure_ascii=False) + "\n")
dump(out_dir / "archive.strong.binary.jsonl", strong_rows)
dump(out_dir / "archive.all.binary.jsonl", resolved)
report = {
"unique_texts_all": len(resolved),
"strong_unique": len({t: v for t, v in resolved.items() if v["strong"]}),
"strong_after_exclude": len(strong_rows),
"label_dist_strong": dict(Counter(r["label"] for r in strong_rows.values())),
"label_dist_all": dict(Counter(r["label"] for r in resolved.values())),
"ad_kind_dist_strong": dict(Counter(r["ad_kind"] for r in strong_rows.values()).most_common()),
"action_dist_strong": dict(Counter(r["action"] for r in strong_rows.values()).most_common()),
"decider_dist_strong": dict(Counter(r["decider"] for r in strong_rows.values()).most_common(10)),
"marker_forms": {
"has_fullwidth_bracket": sum(1 for t in resolved if "[" in t),
"has_xml_tag": sum(1 for t in resolved if re.search(r"<[a-z_]+>", t)),
},
"stats": dict(stat),
}
(out_dir / "archive.report.json").write_text(
json.dumps(report, ensure_ascii=False, indent=2), encoding="utf-8")
print(f"唯一文本 {len(resolved)} | 强标注 {report['strong_unique']} "
f"| 剔除已存在 {excluded} → 净新增 {len(strong_rows)}")
print("净新增 label:", report["label_dist_strong"])
print("统计:", dict(stat))
print(f"[OK] {out_dir}/archive.strong.binary.jsonl, archive.all.binary.jsonl, archive.report.json")
if __name__ == "__main__":
main()
|