ThingsAI commited on
Commit
9bab82f
·
verified ·
1 Parent(s): 5434506

Update README.md

Browse files
Files changed (1) hide show
  1. README.md +49 -49
README.md CHANGED
@@ -12,52 +12,52 @@ tags:
12
  - lightweight
13
  pipeline_tag: text-classification
14
  ---
15
-
16
- # ThingsLID — Multi-Task Byte-Level Text Classifier
17
-
18
  **4M parameters** · **5 tasks** · **No tokenizer needed** · **Runs on CPU**
19
-
20
- ThingsLID is an ultra-compact multi-task text classification model that operates directly on raw UTF-8 bytes. A single shared backbone serves 5 classification heads simultaneously.
21
-
22
  ## Tasks & Performance
23
-
24
  | Task | Labels | Val Accuracy | Description |
25
  |------|--------|-------------|-------------|
26
- | `lang_id` | 351 | 94.3% | Language identification |
27
- | `prog_lang` | 30 | 94.4% | Programming language detection |
28
- | `spam` | 2 | 96.1% | Spam vs ham classification |
29
- | `toxic` | 2 | 67.3% | Toxicity detection (multilingual) |
30
-
31
- **Average validation accuracy: 88.0%**
32
-
33
  ## Architecture
34
-
35
- ThingsLID uses a byte-level hybrid architecture inspired by [CommonLingua](https://huggingface.co/PleIAs/CommonLingua):
36
-
37
  - **Input**: Raw UTF-8 bytes (no tokenizer), padded to 512 bytes
38
  - **Trigram hash embedding**: Polynomial rolling hash of byte 3-grams → 8192-bucket embedding table
39
  - **Byte unigram embedding**: Standard embedding for individual bytes
40
  - **4× Conv1D blocks**: Causal convolutions + BatchNorm + GELU + residual
41
  - **2× Bidirectional attention**: Multi-head self-attention with RoPE
42
  - **Global average pooling** → per-task classification heads
43
-
44
  Total: ~4M shared parameters + small per-task linear heads.
45
-
46
  ## Usage
47
-
48
  ```python
49
  import torch
50
  from huggingface_hub import hf_hub_download
51
-
52
  # Download and load
53
- ckpt_path = hf_hub_download("ThingAI/ThingsLID", "model.pt")
54
  ckpt = torch.load(ckpt_path, map_location="cpu", weights_only=False)
55
-
56
  # Reconstruct model (see model.py in repo)
57
  from model import MultiTaskLID
58
  model = MultiTaskLID(ckpt["task_configs"]).eval()
59
  model.load_state_dict(ckpt["model"])
60
-
61
  # Predict
62
  def predict(text, task="lang_id", top_k=3):
63
  raw = text.encode("utf-8")[:512]
@@ -66,68 +66,68 @@ def predict(text, task="lang_id", top_k=3):
66
  with torch.no_grad():
67
  logits = model(inp, task)["logits"][0]
68
  probs = torch.softmax(logits, dim=-1)
69
- idx2label = {i: l for l, i in ckpt["label_maps"][task].items()}
70
  topk = probs.topk(top_k)
71
  return [(idx2label[topk.indices[i].item()], topk.values[i].item()) for i in range(top_k)]
72
-
73
  # Examples
74
  print(predict("La pizza napoletana è patrimonio UNESCO", task="lang_id"))
75
  # [('ita', 0.98), ('cos', 0.003), ...]
76
-
77
  print(predict("def foo(x): return x + 1", task="prog_lang"))
78
  # [('Python', 0.95), ...]
79
-
80
  print(predict("You won a FREE iPhone!!!", task="spam"))
81
  # [('spam', 0.99), ...]
82
  ```
83
-
84
  ## Quick predict script
85
-
86
  ```bash
87
  python predict.py --text "Ciao, come stai?"
88
  # lang_id: ita (98.2%)
89
-
90
- python predict.py --task prog_lang --text "fn main() { println!("hello"); }"
91
  # prog_lang: Rust (97.1%)
92
-
93
  python predict.py --task spam --text "URGENT: Click here to win!"
94
  # spam: spam (99.5%)
95
  ```
96
-
97
  ## Training Data
98
-
99
  | Task | Dataset | Samples |
100
  |------|---------|---------|
101
  | Language ID | [PleIAs/CommonLingua-Train](https://huggingface.co/datasets/PleIAs/CommonLingua-Train) | 200K (capped) |
102
  | Programming Language | [cakiki/rosetta-code](https://huggingface.co/datasets/cakiki/rosetta-code) | ~26K |
103
  | Spam Detection | [ucirvine/sms_spam](https://huggingface.co/datasets/ucirvine/sms_spam) | 5.5K |
104
  | Toxicity | [textdetox/multilingual_toxicity_dataset](https://huggingface.co/datasets/textdetox/multilingual_toxicity_dataset) | ~45K |
105
-
106
  ## Key Design Decisions
107
-
108
  - **Byte-level input**: No tokenizer means it works on any language, script, or encoding without preprocessing
109
  - **Trigram hashing**: +1.2 F1 over unigram-only baseline, acts as regularization via hash collisions
110
  - **Multi-task learning**: Shared backbone learns universal text representations; per-task heads are tiny (~130K params each)
111
  - **No attention masking**: Bidirectional attention for classification (not causal)
112
  - **OneCycleLR**: Fast convergence in few epochs
113
-
114
  ## Limitations
115
-
116
  - Designed for paragraph-level classification (50+ bytes). Short texts (<20 bytes) may be unreliable
117
  - Toxicity detection accuracy is lower than specialized models (trained on limited multilingual data)
118
  - Programming language detection trained on Rosetta Code samples which have a specific style
119
-
120
  ## Citation
121
-
122
  ```bibtex
123
- @misc{thingslid2026,
124
- author = {ThingAI},
125
- title = {ThingsLID: Multi-Task Byte-Level Text Classifier},
126
- year = {2026},
127
- url = {https://huggingface.co/ThingAI/ThingsLID}
128
- }
129
  ```
130
-
131
  ## License
132
-
133
  Apache 2.0
 
12
  - lightweight
13
  pipeline_tag: text-classification
14
  ---
15
+
16
+ # Glyph — Multi-Task Byte-Level Text Classifier
17
+
18
  **4M parameters** · **5 tasks** · **No tokenizer needed** · **Runs on CPU**
19
+
20
+ Glyph is an ultra-compact multi-task text classification model that operates directly on raw UTF-8 bytes. A single shared backbone serves 5 classification heads simultaneously.
21
+
22
  ## Tasks & Performance
23
+
24
  | Task | Labels | Val Accuracy | Description |
25
  |------|--------|-------------|-------------|
26
+ | `lang_id` | {n_lang_id} | {acc_lang_id:.1f}% | Language identification |
27
+ | `prog_lang` | {n_prog_lang} | {acc_prog_lang:.1f}% | Programming language detection |
28
+ | `spam` | 2 | {acc_spam:.1f}% | Spam vs ham classification |
29
+ | `toxic` | 2 | {acc_toxic:.1f}% | Toxicity detection (multilingual) |
30
+
31
+ **Average validation accuracy: {avg_acc:.1f}%**
32
+
33
  ## Architecture
34
+
35
+ Glyph uses a byte-level hybrid architecture inspired by [CommonLingua](https://huggingface.co/PleIAs/CommonLingua):
36
+
37
  - **Input**: Raw UTF-8 bytes (no tokenizer), padded to 512 bytes
38
  - **Trigram hash embedding**: Polynomial rolling hash of byte 3-grams → 8192-bucket embedding table
39
  - **Byte unigram embedding**: Standard embedding for individual bytes
40
  - **4× Conv1D blocks**: Causal convolutions + BatchNorm + GELU + residual
41
  - **2× Bidirectional attention**: Multi-head self-attention with RoPE
42
  - **Global average pooling** → per-task classification heads
43
+
44
  Total: ~4M shared parameters + small per-task linear heads.
45
+
46
  ## Usage
47
+
48
  ```python
49
  import torch
50
  from huggingface_hub import hf_hub_download
51
+
52
  # Download and load
53
+ ckpt_path = hf_hub_download("ThingAI/Glyph", "model.pt")
54
  ckpt = torch.load(ckpt_path, map_location="cpu", weights_only=False)
55
+
56
  # Reconstruct model (see model.py in repo)
57
  from model import MultiTaskLID
58
  model = MultiTaskLID(ckpt["task_configs"]).eval()
59
  model.load_state_dict(ckpt["model"])
60
+
61
  # Predict
62
  def predict(text, task="lang_id", top_k=3):
63
  raw = text.encode("utf-8")[:512]
 
66
  with torch.no_grad():
67
  logits = model(inp, task)["logits"][0]
68
  probs = torch.softmax(logits, dim=-1)
69
+ idx2label = {{i: l for l, i in ckpt["label_maps"][task].items()}}
70
  topk = probs.topk(top_k)
71
  return [(idx2label[topk.indices[i].item()], topk.values[i].item()) for i in range(top_k)]
72
+
73
  # Examples
74
  print(predict("La pizza napoletana è patrimonio UNESCO", task="lang_id"))
75
  # [('ita', 0.98), ('cos', 0.003), ...]
76
+
77
  print(predict("def foo(x): return x + 1", task="prog_lang"))
78
  # [('Python', 0.95), ...]
79
+
80
  print(predict("You won a FREE iPhone!!!", task="spam"))
81
  # [('spam', 0.99), ...]
82
  ```
83
+
84
  ## Quick predict script
85
+
86
  ```bash
87
  python predict.py --text "Ciao, come stai?"
88
  # lang_id: ita (98.2%)
89
+
90
+ python predict.py --task prog_lang --text "fn main() {{ println!(\"hello\"); }}"
91
  # prog_lang: Rust (97.1%)
92
+
93
  python predict.py --task spam --text "URGENT: Click here to win!"
94
  # spam: spam (99.5%)
95
  ```
96
+
97
  ## Training Data
98
+
99
  | Task | Dataset | Samples |
100
  |------|---------|---------|
101
  | Language ID | [PleIAs/CommonLingua-Train](https://huggingface.co/datasets/PleIAs/CommonLingua-Train) | 200K (capped) |
102
  | Programming Language | [cakiki/rosetta-code](https://huggingface.co/datasets/cakiki/rosetta-code) | ~26K |
103
  | Spam Detection | [ucirvine/sms_spam](https://huggingface.co/datasets/ucirvine/sms_spam) | 5.5K |
104
  | Toxicity | [textdetox/multilingual_toxicity_dataset](https://huggingface.co/datasets/textdetox/multilingual_toxicity_dataset) | ~45K |
105
+
106
  ## Key Design Decisions
107
+
108
  - **Byte-level input**: No tokenizer means it works on any language, script, or encoding without preprocessing
109
  - **Trigram hashing**: +1.2 F1 over unigram-only baseline, acts as regularization via hash collisions
110
  - **Multi-task learning**: Shared backbone learns universal text representations; per-task heads are tiny (~130K params each)
111
  - **No attention masking**: Bidirectional attention for classification (not causal)
112
  - **OneCycleLR**: Fast convergence in few epochs
113
+
114
  ## Limitations
115
+
116
  - Designed for paragraph-level classification (50+ bytes). Short texts (<20 bytes) may be unreliable
117
  - Toxicity detection accuracy is lower than specialized models (trained on limited multilingual data)
118
  - Programming language detection trained on Rosetta Code samples which have a specific style
119
+
120
  ## Citation
121
+
122
  ```bibtex
123
+ @misc{{glyph2026,
124
+ author = {{ThingAI}},
125
+ title = {{Glyph: Multi-Task Byte-Level Text Classifier}},
126
+ year = {{2026}},
127
+ url = {{https://huggingface.co/ThingAI/Glyph}}
128
+ }}
129
  ```
130
+
131
  ## License
132
+
133
  Apache 2.0