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/scripts/consolidate_images.py from x6nux/laya-ad: direct link, hf CLI and curl.
- Browser
- Download file 5.36 kB
-
https://huggingface.co/x6nux/laya-ad/resolve/main/code/scripts/consolidate_images.py
- Command line
-
hf download hf://x6nux/laya-ad/code/scripts/consolidate_images.py
-
curl -L -o consolidate_images.py https://huggingface.co/x6nux/laya-ad/resolve/main/code/scripts/consolidate_images.py
5.36 kB
| #!/usr/bin/env python3 | |
| """把引用到的图片复制进 data/processed,让清洗产物自包含。 | |
| 清洗产物(image_clf.jsonl 等)本身只有路径清单,图片还在原始导出目录里。 | |
| 删原始数据之前必须先搬,否则清单里的 800 多条路径全部变成死链。 | |
| 搬完后所有清单里的路径都改写成 processed 内的相对路径,原始目录可安全删除。 | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import hashlib | |
| import json | |
| import os | |
| import shutil | |
| import sys | |
| POOL_DIR = "data/processed/image_pool" # 图片落地目录 | |
| POOL_MANIFEST = "data/processed/image_pool.jsonl" # 索引(merge_image_pool.py 的产物) | |
| def sha256(path: str) -> str: | |
| h = hashlib.sha256() | |
| with open(path, "rb") as fh: | |
| for chunk in iter(lambda: fh.read(1 << 20), b""): | |
| h.update(chunk) | |
| return h.hexdigest() | |
| def dest_rel(source: str, abs_path: str, raw_archive: str, channel_src: str) -> str: | |
| """把原始绝对路径映射成 processed 内的相对路径,按来源隔离命名空间。""" | |
| ap = os.path.abspath(abs_path) | |
| if source == "channel": | |
| rel = os.path.relpath(ap, os.path.abspath(channel_src)) | |
| return os.path.join("images", "channel", rel.replace("\\", "/")).replace("\\", "/") | |
| rel = os.path.relpath(ap, os.path.abspath(raw_archive)) | |
| return os.path.join("images", "group", rel.replace("\\", "/")).replace("\\", "/") | |
| def main() -> None: | |
| ap = argparse.ArgumentParser() | |
| ap.add_argument("--raw-archive", default="data/raw/archive/archive") | |
| ap.add_argument("--channel-src", default="存档数据-1") | |
| ap.add_argument("--dry-run", action="store_true") | |
| args = ap.parse_args() | |
| with open(POOL_MANIFEST, encoding="utf-8") as fh: | |
| pool = [json.loads(line) for line in fh] | |
| # 1) 复制 + 校验 | |
| plan: list[tuple[dict, str, str]] = [] | |
| copied = skipped = mismatch = 0 | |
| for r in pool: | |
| src = r["abs_path"] | |
| if not os.path.exists(src): | |
| print(f"[miss] {src}", file=sys.stderr) | |
| continue | |
| rel = dest_rel(r["source"], src, args.raw_archive, args.channel_src) | |
| dst = os.path.join(POOL_DIR, rel) | |
| plan.append((r, src, rel)) | |
| if os.path.exists(dst): | |
| skipped += 1 | |
| else: | |
| if not args.dry_run: | |
| os.makedirs(os.path.dirname(dst), exist_ok=True) | |
| shutil.copy2(src, dst) | |
| copied += 1 | |
| if not args.dry_run and r.get("sha256") and sha256(dst) != r["sha256"]: | |
| mismatch += 1 | |
| print(f"[hash-mismatch] {rel}", file=sys.stderr) | |
| print(f"[copy] 新增 {copied},已存在 {skipped},哈希不符 {mismatch},计划 {len(plan)}") | |
| if args.dry_run: | |
| return | |
| if mismatch: | |
| print("[abort] 存在哈希不符,放弃改写清单", file=sys.stderr) | |
| sys.exit(1) | |
| # 2) 改写 image_pool.jsonl(路径改为 processed 内相对路径) | |
| for r, _src, rel in plan: | |
| r["path"] = rel | |
| r["abs_path"] = os.path.join(os.getcwd(), POOL_DIR, rel).replace("\\", "/") | |
| with open(POOL_MANIFEST, "w", encoding="utf-8") as fh: | |
| for r, _s, _rel in plan: | |
| fh.write(json.dumps(r, ensure_ascii=False) + "\n") | |
| # 3) 改写两个来源清单(archive 用 processed 内绝对路径,channel 用 processed 内相对路径) | |
| by_key = {(r["source"], r["chat_id"], r["message_id"], os.path.basename(r["abs_path"])): r | |
| for r, _s, _rel in plan} | |
| def patch(path: str, key_source: str, fields=("path",)) -> int: | |
| if not os.path.exists(path): | |
| return 0 | |
| rows = [json.loads(line) for line in open(path, encoding="utf-8")] | |
| n = 0 | |
| for row in rows: | |
| for f in fields: | |
| old = row.get(f) | |
| if not isinstance(old, str): | |
| continue | |
| k = (key_source, row.get("chat_id"), row.get("message_id"), os.path.basename(old)) | |
| hit = by_key.get(k) | |
| if hit: | |
| row[f] = os.path.join(os.getcwd(), POOL_DIR, hit["path"]).replace("\\", "/") | |
| n += 1 | |
| with open(path, "w", encoding="utf-8") as fh: | |
| for row in rows: | |
| fh.write(json.dumps(row, ensure_ascii=False) + "\n") | |
| return n | |
| n1 = patch("data/processed/archive/image_clf.jsonl", "group") | |
| n2 = patch("data/processed/channel/images.jsonl", "channel") | |
| # channel messages 的 images 是列表 | |
| msgs = [json.loads(line) for line in open("data/processed/channel/messages.jsonl", encoding="utf-8")] | |
| n3 = 0 | |
| for m in msgs: | |
| new = [] | |
| for old in m.get("images") or []: | |
| k = ("channel", m.get("chat_id"), m.get("message_id"), os.path.basename(old)) | |
| hit = by_key.get(k) | |
| new.append(os.path.join(os.getcwd(), POOL_DIR, hit["path"]).replace("\\", "/") if hit else old) | |
| n3 += bool(hit) | |
| m["images"] = new | |
| with open("data/processed/channel/messages.jsonl", "w", encoding="utf-8") as fh: | |
| for m in msgs: | |
| fh.write(json.dumps(m, ensure_ascii=False) + "\n") | |
| print(f"[patch] image_clf {n1} | channel/images {n2} | channel/messages {n3}") | |
| print(f"[out] {os.path.abspath(POOL_DIR)}") | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |