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
Download code/laya-server/backend/tests/test_ad_classifier.py from x6nux/laya-ad: direct link, hf CLI and curl.
- Browser
- Download file 7.38 kB
-
https://huggingface.co/x6nux/laya-ad/resolve/main/code/laya-server/backend/tests/test_ad_classifier.py
- Command line
-
hf download hf://x6nux/laya-ad/code/laya-server/backend/tests/test_ad_classifier.py
-
curl -L -o test_ad_classifier.py https://huggingface.co/x6nux/laya-ad/resolve/main/code/laya-server/backend/tests/test_ad_classifier.py
7.38 kB
| """ad-clf 后端端到端测试:微型随机权重模型走完整 API 流程(不依赖真实权重/数据)。""" | |
| from pathlib import Path | |
| import pytest | |
| from argon2 import PasswordHasher | |
| from fastapi.testclient import TestClient | |
| from server.config import Settings | |
| from server.main import create_app | |
| PASSWORD = "correct horse battery staple" | |
| ORIGIN = {"Origin": "http://testserver"} | |
| def tiny_model_dir(tmp_path_factory): | |
| """微型 ModernBERT(2 层 × 32 hidden)+ 真实 tokenizer,落成 fp32 safetensors 目录。""" | |
| import torch | |
| from transformers import AutoModelForSequenceClassification, AutoTokenizer, ModernBertConfig | |
| d = tmp_path_factory.mktemp("tiny-model") | |
| tok = AutoTokenizer.from_pretrained("bert-base-cased") | |
| tok.save_pretrained(d) | |
| cfg = ModernBertConfig(vocab_size=len(tok), hidden_size=32, intermediate_size=64, | |
| num_hidden_layers=2, num_attention_heads=2, | |
| max_position_embeddings=128, | |
| pad_token_id=tok.pad_token_id or 0, | |
| bos_token_id=tok.cls_token_id or 0, | |
| eos_token_id=tok.sep_token_id or 0, | |
| cls_token_id=tok.cls_token_id or 0, | |
| mask_token_id=None) | |
| model = AutoModelForSequenceClassification.from_config(cfg) | |
| model.config.id2label = {0: "ad", 1: "normal"} | |
| model.config.label2id = {"ad": 0, "normal": 1} | |
| model.save_pretrained(d, safe_serialization=True) | |
| (d / "PRECISION.txt").write_text("fp8", encoding="utf-8") | |
| (d / "MODEL_ID.txt").write_text("laya-test-fp8", encoding="utf-8") | |
| return d | |
| def _settings(model_dir: Path, tmp_path: Path) -> Settings: | |
| frontend = tmp_path / "frontend-dist" | |
| frontend.mkdir(exist_ok=True) | |
| return Settings("admin", PasswordHasher().hash(PASSWORD), tmp_path / "db.sqlite3", | |
| 1, Path(model_dir), None, frontend) | |
| def client(client_factory, tiny_model_dir, tmp_path): | |
| c = client_factory(create_app(_settings(tiny_model_dir, tmp_path))) | |
| assert c.get("/health/ready").status_code == 200 | |
| assert c.post("/internal/auth/login", json={"username": "admin", "password": PASSWORD}, | |
| headers=ORIGIN).status_code == 200 | |
| csrf = c.get("/internal/auth/session").json()["csrf_token"] | |
| key = c.post("/internal/api-keys", json={"name": "smoke"}, | |
| headers={**ORIGIN, "X-CSRF-Token": csrf}).json()["key"] | |
| c.headers.update({"Authorization": f"Bearer {key}"}) | |
| return c | |
| def test_models_list(client): | |
| assert client.get("/internal/models").json() == { | |
| "models": ["auto", "laya", "laya-test", "laya-test-fp8"]} | |
| def test_laya_alias_accepted(client): | |
| r = client.post("/v1/systemone", json={ | |
| "state": "hello", | |
| "questions": {"q": {"type": "noul", "instructions": "这是 advertisement 广告吗?"}}, | |
| "model": "laya", | |
| }) | |
| assert r.status_code == 200 | |
| assert r.json()["model"] == "laya-test-fp8" | |
| def test_rejects_unbundled_models(client): | |
| r = client.post("/v1/systemone", json={ | |
| "state": "hello", | |
| "questions": {"q": {"type": "noul", "instructions": "urgent?"}}, | |
| "model": "multilingual", | |
| }) | |
| assert r.status_code == 422 | |
| assert r.json()["detail"]["code"] == "MODEL_NOT_AVAILABLE" | |
| def test_systemone_answers(client): | |
| payload = { | |
| "state": {"message": {"text": "加微信免费领取涨粉秘籍,名额有限!"}}, | |
| "questions": { | |
| "is_ad": {"type": "choice", "instructions": "判断", | |
| "criteria": {"clean": "正常内容", "ad": "广告"}}, | |
| "ad_kind": {"type": "choice", "instructions": "类别", | |
| "criteria": {"promo": "推广", "scam": "诈骗"}}, | |
| "refund": {"type": "noul", "instructions": "Does the sender ask for a refund?"}, | |
| "is_ad_noul": {"type": "noul", "instructions": "这条消息是 advertisement 广告吗?"}, | |
| }, | |
| } | |
| r = client.post("/v1/systemone", json=payload) | |
| assert r.status_code == 200, r.text | |
| body = r.json() | |
| ans = body["answers"] | |
| assert ans["is_ad"]["unsupported"] is False | |
| assert ans["is_ad"]["choice"] in ("ad", "clean") | |
| assert abs(sum(ans["is_ad"]["probabilities"].values()) - 1.0) < 0.01 | |
| # is_ad 的键序保持请求原序(clean 在前) | |
| assert set(ans["is_ad"]["probabilities"]) == {"clean", "ad"} | |
| assert ans["ad_kind"]["unsupported"] is True | |
| assert ans["refund"]["unsupported"] is True and ans["refund"]["noul"] == 0.5 | |
| assert ans["is_ad_noul"]["unsupported"] is False | |
| usage = body["usage"] | |
| assert isinstance(usage["input_tokens"], int) and usage["input_tokens"] > 0 | |
| assert usage["output_tokens"] == len(payload["questions"]) | |
| assert body["model"] == "laya-test-fp8" | |
| def test_state_string_and_variants(client): | |
| r = client.post("/v1/systemone", json={ | |
| "state": "限时特惠 原价299今日99元 点击抢购", | |
| "questions": {"q": {"type": "choice", "instructions": "判断", | |
| "criteria": ["ad", "clean"]}}, | |
| }) | |
| assert r.status_code == 200 | |
| assert r.json()["answers"]["q"]["choice"] in ("ad", "clean") | |
| def test_multi_precision_root(client_factory, tiny_model_dir, tmp_path): | |
| """multi 模式:根目录下多个精度子目录,按 model id 懒加载切换。""" | |
| import shutil | |
| root = tmp_path / "multi-root" | |
| root.mkdir() | |
| for mid, prec in (("laya-test-fp8", "fp8"), ("laya-test-int4", "int4")): | |
| d = root / f"variant-{prec}" | |
| d.mkdir() | |
| for f in ("model.safetensors", "config.json", "tokenizer.json", "tokenizer_config.json"): | |
| shutil.copy(tiny_model_dir / f, d / f) | |
| (d / "PRECISION.txt").write_text(prec, encoding="utf-8") | |
| (d / "MODEL_ID.txt").write_text(mid, encoding="utf-8") | |
| c = client_factory(create_app(_settings(root, tmp_path))) | |
| assert c.post("/internal/auth/login", json={"username": "admin", "password": PASSWORD}, | |
| headers=ORIGIN).status_code == 200 | |
| csrf = c.get("/internal/auth/session").json()["csrf_token"] | |
| key = c.post("/internal/api-keys", json={"name": "multi"}, | |
| headers={**ORIGIN, "X-CSRF-Token": csrf}).json()["key"] | |
| c.headers.update({"Authorization": f"Bearer {key}"}) | |
| assert c.get("/internal/models").json() == { | |
| "models": ["auto", "laya", "laya-test", "laya-test-fp8", "laya-test-int4"]} | |
| payload = {"state": "加微信免费领取涨粉秘籍,名额有限!", | |
| "questions": {"is_ad": {"type": "choice", "instructions": "判断", | |
| "criteria": {"ad": "广告", "clean": "正常"}}}} | |
| r = c.post("/v1/systemone", json={**payload, "model": "laya-test-int4"}) | |
| assert r.status_code == 200 | |
| assert r.json()["model"] == "laya-test-int4" | |
| r = c.post("/v1/systemone", json={**payload, "model": "laya"}) | |
| assert r.status_code == 200 | |
| assert r.json()["model"] == "laya-test-fp8" # laya 别名 → fp8 默认变体 | |
| r = c.post("/v1/systemone", json={**payload, "model": "laya-nonexist"}) | |
| assert r.status_code == 422 | |