ooognicki chopratejas commited on
Commit
773bc55
·
0 Parent(s):

Duplicate from chopratejas/kompress-base

Browse files

Co-authored-by: Tejas Chopra <chopratejas@users.noreply.huggingface.co>

.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ language:
4
+ - en
5
+ tags:
6
+ - token-compression
7
+ - context-optimization
8
+ - llm
9
+ - agentic
10
+ - modernbert
11
+ datasets:
12
+ - lmsys/lmsys-chat-1m
13
+ - cnn_dailymail
14
+ - EdinburghNLP/xsum
15
+ - ccdv/govreport-summarization
16
+ - ccdv/arxiv-summarization
17
+ - huuuyeah/meetingbank
18
+ - knkarthick/samsum
19
+ metrics:
20
+ - f1
21
+ - accuracy
22
+ pipeline_tag: token-classification
23
+ model-index:
24
+ - name: kompress-base
25
+ results:
26
+ - task:
27
+ type: token-classification
28
+ name: Token Compression
29
+ metrics:
30
+ - name: Quality Score (Claude-judged)
31
+ type: custom
32
+ value: 7.9
33
+ - name: LLMLingua-2 Quality Score
34
+ type: custom
35
+ value: 5.9
36
+ - name: Latency (median, Apple Silicon MPS)
37
+ type: latency
38
+ value: 84ms
39
+ - name: LLMLingua-2 Latency
40
+ type: latency
41
+ value: 117ms
42
+ ---
43
+
44
+ # Kompress: ModernBERT Token Compressor for LLM Context Windows
45
+
46
+ **Kompress compresses text in LLM context windows so agents can do more with less.** It's a drop-in replacement for LLMLingua-2 that's higher quality and 2.3x faster.
47
+
48
+ ## Results
49
+
50
+ | Model | Quality | Latency | Size | Params |
51
+ |-------|---------|---------|------|--------|
52
+ | **kompress-base** | **7.9/10** | **84ms** (MPS) | 600MB | 150M |
53
+ | [kompress-small](https://huggingface.co/chopratejas/kompress-small) | 7.4/10 | **13-29ms** (ONNX) | 279MB | 70M |
54
+ | LLMLingua-2 | 5.9/10 | 117ms | 710MB | 179M |
55
+
56
+ ### Quality on Real Agent Data (Claude-judged)
57
+
58
+ | Eval Set | kompress-base | kompress-small | LLMLingua-2 |
59
+ |----------|--------------|----------------|-------------|
60
+ | Unstructured NL text | **7.9/10** | 7.4/10 | 5.9/10 |
61
+ | Claude Code sessions | **7.3/10** | **7.4/10** | 6.2/10 |
62
+
63
+ Quality scores are judged by Claude Sonnet 4.6: "Can an LLM fully understand and act on the compressed version?" (1-10 scale).
64
+
65
+ ## How It Works
66
+
67
+ Kompress is a **dual-head ModernBERT** model trained to classify each token as keep or discard:
68
+
69
+ - **Token head**: Binary classifier (keep/discard per token via argmax)
70
+ - **Span head**: 1D CNN that identifies important regions, boosts borderline tokens in critical spans
71
+
72
+ The model decides how much to compress based on content density — no fixed compression ratio.
73
+
74
+ ### Example
75
+
76
+ ```
77
+ ORIGINAL (98 words):
78
+ After investigating the memory leak, I traced it to the event listener
79
+ registration in the WebSocket handler. Every time a client connects, we
80
+ register a new listener on the global event bus, but when the client
81
+ disconnects, the cleanup function only removes the WebSocket connection
82
+ from the pool — it doesn't unregister the event listener. Over time,
83
+ these orphaned listeners accumulate and each one holds a reference to
84
+ the connection's closure, which in turn holds the entire request context.
85
+ The fix is straightforward: store the listener reference at connection
86
+ time and explicitly remove it in the disconnect handler.
87
+
88
+ COMPRESSED (59 words, 60% kept):
89
+ investigating memory leak, traced event listener registration WebSocket
90
+ handler. Every time client connects, register new listener global event
91
+ bus, client disconnects, cleanup function only removes WebSocket
92
+ connection pool — doesn't unregister event listener. Over time, orphaned
93
+ listeners accumulate each one holds reference connection's closure, holds
94
+ entire request context. fix straightforward: store listener reference
95
+ connection time explicitly remove disconnect handler.
96
+ ```
97
+
98
+ An LLM can fully understand and act on the compressed version.
99
+
100
+ ## Usage
101
+
102
+ ```python
103
+ from kompress.inference.pytorch_runner import KompressRunner
104
+
105
+ # Auto-downloads from HuggingFace on first use
106
+ runner = KompressRunner()
107
+
108
+ result = runner.compress("Your long text here...")
109
+ print(result.compressed) # Compressed text
110
+ print(result.compression_ratio) # e.g., 0.62
111
+ print(result.tokens_saved) # Number of tokens saved
112
+ ```
113
+
114
+ ### With Headroom (LLM Proxy)
115
+
116
+ ```bash
117
+ pip install headroom-ai
118
+ ```
119
+
120
+ Kompress is built into [Headroom](https://github.com/headroom-ai/headroom) as the default text compressor. It auto-downloads and runs on every API request that passes through the proxy.
121
+
122
+ ## Training
123
+
124
+ ### Architecture
125
+ - **Base**: `answerdotai/ModernBERT-base` (149M params, 8192 token context)
126
+ - **Token head**: Linear(768, 2) — binary keep/discard classifier
127
+ - **Span head**: Conv1d(768→256, k=5) → GELU → Conv1d(256→1, k=3) → Sigmoid
128
+ - **Total**: 150M params
129
+
130
+ ### Data
131
+ 215K extractive compression labels from 8 diverse datasets, labeled by Claude Sonnet 4.6:
132
+
133
+ | Dataset | Count | Type |
134
+ |---------|-------|------|
135
+ | LMSYS-Chat-1M | 57K | LLM conversations |
136
+ | CNN/DailyMail | 50K | News articles |
137
+ | WikiHow | 50K | How-to guides |
138
+ | MeetingBank | 50K | Meeting transcripts |
139
+ | XSum | 47K | News articles |
140
+ | GovReport | 25K | Government reports |
141
+ | ArXiv | 25K | Academic papers |
142
+ | SAMSum | 14K | Dialogues |
143
+
144
+ ### Labeling Approach
145
+
146
+ Key insight: the labels must be **strictly extractive** — a subset of original words in original order. Previous versions failed because the labeling LLM rephrased text, causing alignment failures (5-12% keep ratio instead of the intended 40-60%).
147
+
148
+ The fix: prompt Claude to "select words like highlighting with a marker" rather than "compress this text." This ensures every word in the compressed output exists in the original, and the greedy alignment recovers 95%+ of the intended labels.
149
+
150
+ ### Training Details
151
+ - 3 epochs, batch size 32, learning rate 2e-5
152
+ - BF16 mixed precision on NVIDIA H100
153
+ - HuggingFace Trainer with warmup + cosine schedule
154
+ - ~3 hours training time
155
+
156
+ ## Model Family
157
+
158
+ | | kompress-base | [kompress-small](https://huggingface.co/chopratejas/kompress-small) | LLMLingua-2 |
159
+ |---|---|---|---|
160
+ | Architecture | ModernBERT 22-layer | ModernBERT 6-layer (distilled) | mBERT (2018) |
161
+ | Params | 150M | 70M | 179M |
162
+ | Size | 600MB | 279MB (ONNX: 275MB) | 710MB |
163
+ | Max context | 8,192 tokens | 8,192 tokens | 512 tokens |
164
+ | Quality | **7.9/10** | 7.4/10 | 5.9/10 |
165
+ | Latency | 84ms (MPS) | **13-29ms (ONNX)** | 117ms |
166
+ | Training data | 215K from 8 datasets | Distilled from base | 41K from MeetingBank |
167
+ | Labeling model | Claude Sonnet 4.6 | — | GPT-4 |
168
+ | Compression | Content-adaptive | Content-adaptive | Fixed ratio |
169
+
170
+ ## Limitations
171
+
172
+ - English only (ModernBERT is English-focused)
173
+ - Best on natural language text; structured data (JSON, code, logs) should use specialized compressors
174
+ - Compression ratio varies by content (60-80% kept for dense text, 40-60% for verbose text)
175
+
176
+ ## License
177
+
178
+ Apache 2.0
config.json ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "return_dict": true,
3
+ "output_hidden_states": false,
4
+ "torchscript": false,
5
+ "dtype": "float32",
6
+ "pruned_heads": {},
7
+ "tie_word_embeddings": true,
8
+ "chunk_size_feed_forward": 0,
9
+ "is_encoder_decoder": false,
10
+ "is_decoder": false,
11
+ "cross_attention_hidden_size": null,
12
+ "add_cross_attention": false,
13
+ "tie_encoder_decoder": false,
14
+ "architectures": [
15
+ "HeadroomCompressor"
16
+ ],
17
+ "finetuning_task": null,
18
+ "id2label": {
19
+ "0": "LABEL_0",
20
+ "1": "LABEL_1"
21
+ },
22
+ "label2id": {
23
+ "LABEL_0": 0,
24
+ "LABEL_1": 1
25
+ },
26
+ "task_specific_params": {
27
+ "token_compression": {
28
+ "span_cnn_hidden": 256,
29
+ "span_kernel_sizes": [
30
+ 5,
31
+ 3
32
+ ],
33
+ "span_loss_weight": 0.3
34
+ }
35
+ },
36
+ "problem_type": null,
37
+ "tokenizer_class": null,
38
+ "prefix": null,
39
+ "bos_token_id": 50281,
40
+ "pad_token_id": 50283,
41
+ "eos_token_id": 50282,
42
+ "sep_token_id": 50282,
43
+ "decoder_start_token_id": null,
44
+ "max_length": 20,
45
+ "min_length": 0,
46
+ "do_sample": false,
47
+ "early_stopping": false,
48
+ "num_beams": 1,
49
+ "temperature": 1.0,
50
+ "top_k": 50,
51
+ "top_p": 1.0,
52
+ "typical_p": 1.0,
53
+ "repetition_penalty": 1.0,
54
+ "length_penalty": 1.0,
55
+ "no_repeat_ngram_size": 0,
56
+ "encoder_no_repeat_ngram_size": 0,
57
+ "bad_words_ids": null,
58
+ "num_return_sequences": 1,
59
+ "output_scores": false,
60
+ "return_dict_in_generate": false,
61
+ "forced_bos_token_id": null,
62
+ "forced_eos_token_id": null,
63
+ "remove_invalid_values": false,
64
+ "exponential_decay_length_penalty": null,
65
+ "suppress_tokens": null,
66
+ "begin_suppress_tokens": null,
67
+ "num_beam_groups": 1,
68
+ "diversity_penalty": 0.0,
69
+ "_name_or_path": "answerdotai/ModernBERT-base",
70
+ "transformers_version": "4.57.6",
71
+ "cls_token_id": 50281,
72
+ "gradient_checkpointing": false,
73
+ "layer_norm_eps": 1e-05,
74
+ "model_type": "modernbert",
75
+ "position_embedding_type": "absolute",
76
+ "tf_legacy_loss": false,
77
+ "use_bfloat16": false,
78
+ "vocab_size": 50368,
79
+ "max_position_embeddings": 8192,
80
+ "hidden_size": 768,
81
+ "intermediate_size": 1152,
82
+ "num_hidden_layers": 22,
83
+ "num_attention_heads": 12,
84
+ "initializer_range": 0.02,
85
+ "initializer_cutoff_factor": 2.0,
86
+ "norm_eps": 1e-05,
87
+ "norm_bias": false,
88
+ "global_rope_theta": 160000.0,
89
+ "attention_bias": false,
90
+ "attention_dropout": 0.0,
91
+ "hidden_activation": "gelu",
92
+ "global_attn_every_n_layers": 3,
93
+ "local_attention": 128,
94
+ "local_rope_theta": 10000.0,
95
+ "embedding_dropout": 0.0,
96
+ "mlp_bias": false,
97
+ "mlp_dropout": 0.0,
98
+ "decoder_bias": true,
99
+ "classifier_pooling": "mean",
100
+ "classifier_dropout": 0.0,
101
+ "classifier_bias": false,
102
+ "classifier_activation": "gelu",
103
+ "deterministic_flash_attn": false,
104
+ "sparse_prediction": false,
105
+ "sparse_pred_ignore_index": -100,
106
+ "repad_logits_with_grad": false,
107
+ "output_attentions": false,
108
+ "num_labels": 2
109
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:dc992fb64ff1ddeaa3e858693a8bce0b08f72b2e73d1faa5e5520bcaa2fdc0cd
3
+ size 600014148
onnx/kompress-int8.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3f503efc50410ffe4787fbdaf22de2162717e0cbfebebf5eabd50a2818af91c8
3
+ size 155950298
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "backend": "tokenizers",
3
+ "clean_up_tokenization_spaces": true,
4
+ "cls_token": "[CLS]",
5
+ "is_local": false,
6
+ "mask_token": "[MASK]",
7
+ "model_input_names": [
8
+ "input_ids",
9
+ "attention_mask"
10
+ ],
11
+ "model_max_length": 8192,
12
+ "pad_token": "[PAD]",
13
+ "sep_token": "[SEP]",
14
+ "tokenizer_class": "TokenizersBackend",
15
+ "unk_token": "[UNK]"
16
+ }
training_args.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9732a256f0ed7d7a93adb27ce69451b16a02d5e214f07eb4e7f1f3a9960741ac
3
+ size 5201