Safeeq commited on
Commit
b36e359
Β·
verified Β·
1 Parent(s): d96c759

docs: add comprehensive model card with GitHub links, quickstarts, GGUF guide, and reproduction pipeline

Browse files
Files changed (1) hide show
  1. README.md +207 -62
README.md CHANGED
@@ -8,121 +8,266 @@ tags:
8
  - edge-ai
9
  - tool-use
10
  - router
 
 
11
  pipeline_tag: text-generation
 
12
  widget:
13
  - text: "weather in tokyo today"
 
14
  - text: "tell me a joke"
 
15
  - text: "who is marie curie"
 
 
 
 
 
16
  ---
17
 
18
- # Tiny Function-Calling LM (TinyLM-FC ~0.47M parameters)
19
 
20
- A sub-half-million parameter decoder-only transformer trained from scratch to act as a **deterministic function-calling router**. Given an incoming user utterance, TinyLM decides whether to invoke an external search tool (`web_search`) with structured parameters or abstain (`none`) for general conversation.
 
21
 
22
- Built as an educational and empirical case study on how small a specialized router model can be while maintaining high precision.
 
 
 
 
 
23
 
24
- - **Checkpoint & Weights:** [Safeeq/tiny-fc-lm](https://huggingface.co/Safeeq/tiny-fc-lm)
25
- - **Source Code Repository:** [GitHub Repository](https://github.com/Safeeq008/tiny-fc-lm)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
  ---
28
 
29
- ## Model Architecture Specifications
30
 
31
- | Hyperparameter | Value | Description |
32
  | :--- | :--- | :--- |
33
- | **Total Parameters** | 471,760 (~0.47M) | Trainable weight count |
34
- | **Layers** | 4 | Transformer decoder blocks |
35
- | **Hidden Dim ($d_{model}$)** | 80 | Embedding and layer dimensionality |
36
- | **Attention Heads** | 4 | Head dimension = 20 (even for RoPE) |
37
- | **Positional Encoding** | RoPE (Rotary) | Base frequency $\theta = 10000.0$ |
38
- | **Normalization** | RMSNorm | $\epsilon = 10^{-6}$ (pre-norm configuration) |
39
- | **Feed-Forward Network** | GELU (4Γ— width) | Hidden dimension = 320 |
40
- | **Weight Tying** | Yes | Input embeddings tied with output linear head |
41
- | **Vocabulary Size** | 2,048 | Custom ByteLevel BPE trained on domain syntax |
42
- | **Context Length** | 80 tokens | Maximum prompt + generation sequence length |
43
 
44
  ---
45
 
46
- ## Output Protocol & Grammar
47
 
48
- TinyLM outputs a strict, pipe-delimited schema:
49
- ```text
50
- web_search|query=<search query>|recency=<day|week|any>
51
- none
 
 
 
52
  ```
53
 
54
- - `web_search`: Invokes external search.
55
- - `query`: Formatted search terms extracted and normalized from user intent.
56
- - `recency`: Temporal constraint bucket (`day`, `week`, or `any`).
57
- - `none`: Abstention signal for greetings, chit-chat, creative prompts, or statements not requiring search.
58
 
59
- ---
 
 
60
 
61
- ## Evaluation Benchmark & Rigor
62
-
63
- The model was evaluated on both in-distribution validation data and out-of-distribution (OOD) phrasing sets containing unseen syntactic templates:
 
64
 
65
- | Metric | Validation Split (In-Distribution) | OOD Split (Held-Out Phrasings) |
66
- | :--- | :---: | :---: |
67
- | **Exact Match Accuracy** | **~99.8%** | **~88.2%** |
68
- | **Routing Decision Accuracy** | **99.9%** | **96.4%** |
69
- | **Routing Precision (Tool)** | **99.9%** | **97.1%** |
70
- | **Routing Recall (Tool)** | **99.9%** | **98.8%** |
71
- | **Query Slot Exact Match** | **99.8%** | **89.5%** |
72
- | **Recency Slot Accuracy** | **99.9%** | **97.2%** |
73
- | **Syntactic Validity Rate** | **100.0%** | **99.8%** |
74
- | **Inference Latency (CPU)** | **~3.2 ms** | **~3.4 ms** |
75
 
76
- *Note: In OOD evaluations, templates were strictly held-out from training. The entity vocabulary remained consistent with training pools.*
77
 
78
- ---
 
 
 
 
 
 
79
 
80
- ## Honest Limitations & Known Failure Modes
81
 
82
- 1. **Narrow Task Domain**: This model is strictly a router for `web_search`. It does not generate conversational responses or answers to search queries.
83
- 2. **Vocabulary Memorization vs Entity Extraction**: At 471k parameters, the model partially memorizes entity associations rather than performing open-world named entity recognition. Genuinely unseen foreign names or novel technical terms outside the 2,048-token vocabulary may be split sub-optimally or mapped to known training concepts.
84
- 3. **English Monolingual**: The custom BPE tokenizer and training corpus are exclusively English.
85
- 4. **Context Window Constraint**: Inputs longer than 60 tokens are truncated to conform to `MAX_LEN=80`.
86
- 5. **Greedy / Constrained Decoding Dependency**: Best results require the constrained decoding routine implemented in `infer.py` (which forces the first-token tool name and validates parameters).
87
 
88
  ---
89
 
90
- ## Quickstart: Python Inference
91
 
92
  ```python
93
  import torch
94
  from safetensors.torch import load_file
95
  from tokenizers import Tokenizer
96
- from model import TinyLM # Available in companion GitHub repo
97
 
98
- # 1. Load weights and custom tokenizer
 
 
 
 
 
99
  state_dict = load_file("model.safetensors")
100
  tok = Tokenizer.from_file("tokenizer.json")
101
 
102
- # 2. Instantiate TinyLM
103
  model = TinyLM(vocab=2048, d=80, n_layers=4, n_heads=4, ffn_mult=4, max_len=80)
104
  model.load_state_dict(state_dict)
105
  model.eval()
106
 
107
- # 3. Format input sequence
108
  user_input = "weather in chennai today"
109
- prompt_ids = [1] + tok.encode(user_input).ids + [2] # <user>=1, <call>=2
110
 
111
- # 4. Generate prediction
112
  with torch.no_grad():
113
- logits = model(torch.tensor([prompt_ids]))[0][0, -1]
114
- # For full constrained decoding and live DuckDuckGo dispatch, see infer.py
 
 
 
 
 
 
 
 
 
 
 
115
  ```
116
 
117
  ---
118
 
119
- ## Ethical Considerations & Environmental Impact
120
 
121
- - **Training Footprint**: Trained on CPU in under 10 minutes (~0.002 kWh energy consumed).
122
- - **Deployment Efficiency**: Runs at sub-5ms latency on a single CPU thread with negligible memory footprint (~2MB RAM).
 
 
 
 
 
 
 
 
 
 
123
 
124
  ---
125
 
126
- ## Citation & License
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
 
128
- Released under the **MIT License**. Free for research, benchmarking, and edge deployment.
 
8
  - edge-ai
9
  - tool-use
10
  - router
11
+ - pytorch
12
+ - gguf
13
  pipeline_tag: text-generation
14
+ library_name: generic
15
  widget:
16
  - text: "weather in tokyo today"
17
+ example_title: "Web Search Intent"
18
  - text: "tell me a joke"
19
+ example_title: "Abstain (none)"
20
  - text: "who is marie curie"
21
+ example_title: "Person Search"
22
+ - text: "latest iphone 16 price in india"
23
+ example_title: "Price Search"
24
+ datasets:
25
+ - Safeeq/FCtiny
26
  ---
27
 
28
+ <div align="center">
29
 
30
+ # πŸ”€ TinyLM-FC β€” Tiny Function-Calling Router
31
+ ### ~0.47M Parameters | CPU < 4ms | MIT License
32
 
33
+ [![GitHub](https://img.shields.io/badge/GitHub-Source%20Code-black?logo=github)](https://github.com/Safeeq008/tiny-fc-lm)
34
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
35
+ [![Python 3.10+](https://img.shields.io/badge/Python-3.10%2B-blue.svg)](https://www.python.org/)
36
+ [![Parameters](https://img.shields.io/badge/Parameters-~0.47M-red.svg)](#architecture)
37
+ [![CPU Latency](https://img.shields.io/badge/CPU%20Latency-~3.2ms-purple.svg)](#benchmarks)
38
+ [![GGUF](https://img.shields.io/badge/Ollama%2FlllamaCpp-GGUF%20Available-green.svg)](#gguf--ollama)
39
 
40
+ </div>
41
+
42
+ A **sub-half-million-parameter decoder-only transformer** trained completely from scratch to act as a lightweight, low-latency **function-calling router**. Given a user utterance, TinyLM decides whether to invoke an external tool (`web_search`) with structured arguments, or abstain (`none`) for chit-chat and greetings.
43
+
44
+ Built as an educational and empirical case study: *how small can a specialized router be while still maintaining high precision?*
45
+
46
+ ---
47
+
48
+ ## πŸš€ Quick Links
49
+
50
+ | Resource | Link |
51
+ | :--- | :--- |
52
+ | πŸ“¦ **Full Source Code, Training & Eval Pipeline** | [github.com/Safeeq008/tiny-fc-lm](https://github.com/Safeeq008/tiny-fc-lm) |
53
+ | πŸ€— **Model Weights (this page)** | [huggingface.co/Safeeq/FCtiny](https://huggingface.co/Safeeq/FCtiny) |
54
+ | πŸ“„ **Detailed README & Architecture Docs** | [README.md on GitHub](https://github.com/Safeeq008/tiny-fc-lm/blob/main/README.md) |
55
+ | 🐳 **Docker Deployment** | [Dockerfile](https://github.com/Safeeq008/tiny-fc-lm/blob/main/Dockerfile) · [DEPLOY.md](https://github.com/Safeeq008/tiny-fc-lm/blob/main/DEPLOY.md) |
56
+ | πŸ¦™ **Ollama / llama.cpp Guide** | [OLLAMA.md](https://github.com/Safeeq008/tiny-fc-lm/blob/main/OLLAMA.md) |
57
 
58
  ---
59
 
60
+ ## πŸ“¦ Files in This Repository
61
 
62
+ | File | Size | Description |
63
  | :--- | :--- | :--- |
64
+ | `model.safetensors` | ~1.8 MB | PyTorch weights in safe zero-copy format |
65
+ | `config.json` | ~1 KB | Architecture hyperparameters |
66
+ | `tokenizer.json` | ~121 KB | Custom 2048-vocab ByteLevel BPE tokenizer |
67
+ | `tinyfc.gguf` | ~1.0 MB | Quantized model for Ollama & llama.cpp |
 
 
 
 
 
 
68
 
69
  ---
70
 
71
+ ## ⚑ Quickstart
72
 
73
+ ### Option A β€” Python (from this Hub)
74
+
75
+ ```bash
76
+ git clone https://github.com/Safeeq008/tiny-fc-lm.git
77
+ cd tiny-fc-lm
78
+ pip install -r requirements.txt
79
+ python infer.py
80
  ```
81
 
82
+ ### Option B β€” GGUF via Ollama (zero-install inference)
 
 
 
83
 
84
+ ```bash
85
+ # Download the GGUF and Modelfile from GitHub
86
+ curl -LO https://github.com/Safeeq008/tiny-fc-lm/raw/main/Modelfile
87
 
88
+ # Pull the GGUF from Hugging Face and register it
89
+ ollama pull hf.co/Safeeq/FCtiny:latest
90
+ ollama run hf.co/Safeeq/FCtiny
91
+ ```
92
 
93
+ Or using the local GGUF:
94
+ ```bash
95
+ # Download tinyfc.gguf from the Files tab above, then:
96
+ ollama create tinyfc -f Modelfile
97
+ ollama run tinyfc "weather in new york today"
98
+ ```
 
 
 
 
99
 
100
+ ### Option C β€” FastAPI REST Server (from GitHub)
101
 
102
+ ```bash
103
+ git clone https://github.com/Safeeq008/tiny-fc-lm.git
104
+ cd tiny-fc-lm && pip install -r requirements.txt
105
+ python serve.py 8000
106
+ ```
107
+ - Web UI: `http://localhost:8000`
108
+ - Swagger docs: `http://localhost:8000/docs`
109
 
110
+ ### Option D β€” Docker
111
 
112
+ ```bash
113
+ docker pull ghcr.io/safeeq008/tiny-fc-lm:latest # or build locally:
114
+ git clone https://github.com/Safeeq008/tiny-fc-lm.git
115
+ docker build -t tiny-fc-lm . && docker run -p 8000:8000 tiny-fc-lm
116
+ ```
117
 
118
  ---
119
 
120
+ ## πŸ” Python Inference (Manual)
121
 
122
  ```python
123
  import torch
124
  from safetensors.torch import load_file
125
  from tokenizers import Tokenizer
 
126
 
127
+ # ── Clone the repo for model.py ──
128
+ # git clone https://github.com/Safeeq008/tiny-fc-lm.git
129
+ import sys; sys.path.insert(0, "tiny-fc-lm")
130
+ from model import TinyLM
131
+
132
+ # 1. Load weights + tokenizer (download from Files tab above)
133
  state_dict = load_file("model.safetensors")
134
  tok = Tokenizer.from_file("tokenizer.json")
135
 
136
+ # 2. Instantiate model
137
  model = TinyLM(vocab=2048, d=80, n_layers=4, n_heads=4, ffn_mult=4, max_len=80)
138
  model.load_state_dict(state_dict)
139
  model.eval()
140
 
141
+ # 3. Encode prompt with special tokens (<user>=1, <call>=2)
142
  user_input = "weather in chennai today"
143
+ prompt_ids = [1] + tok.encode(user_input).ids + [2]
144
 
145
+ # 4. Greedily decode
146
  with torch.no_grad():
147
+ ids = torch.tensor([prompt_ids])
148
+ for _ in range(30):
149
+ logits = model(ids)[0]
150
+ next_id = logits[0, -1].argmax().item()
151
+ if next_id == 3: # <end> token
152
+ break
153
+ ids = torch.cat([ids, torch.tensor([[next_id]])], dim=-1)
154
+ output_ids = ids[0, len(prompt_ids):].tolist()
155
+ print(tok.decode(output_ids))
156
+ # β†’ web_search|query=chennai weather today|recency=day
157
+
158
+ # For full constrained decoding + live DuckDuckGo dispatch, see:
159
+ # https://github.com/Safeeq008/tiny-fc-lm/blob/main/infer.py
160
  ```
161
 
162
  ---
163
 
164
+ ## πŸ“ Architecture
165
 
166
+ | Hyperparameter | Value | Notes |
167
+ | :--- | :---: | :--- |
168
+ | **Total Parameters** | 471,760 (~0.47M) | Trainable weight count |
169
+ | **Layers** | 4 | Transformer decoder blocks |
170
+ | **Hidden Dim** | 80 | Embedding & layer dimensionality |
171
+ | **Attention Heads** | 4 | Head dim = 20 (even for RoPE) |
172
+ | **Positional Encoding** | RoPE | ΞΈ = 10000.0 |
173
+ | **Normalization** | RMSNorm | Ξ΅ = 1e-6, pre-norm |
174
+ | **FFN** | GELU (4Γ— width) | Hidden dim = 320 |
175
+ | **Weight Tying** | βœ… Yes | Input embeddings = output head |
176
+ | **Vocabulary Size** | 2,048 | Custom ByteLevel BPE |
177
+ | **Context Length** | 80 tokens | Max prompt + generation |
178
 
179
  ---
180
 
181
+ ## πŸ“Š Benchmarks
182
+
183
+ | Metric | Val (In-Distribution) | OOD (Held-Out Phrasings) |
184
+ | :--- | :---: | :---: |
185
+ | **Exact Match Accuracy** | **~99.8%** | **~88.2%** |
186
+ | **Routing Decision Accuracy** | **99.9%** | **96.4%** |
187
+ | **Routing Precision (Tool)** | **99.9%** | **97.1%** |
188
+ | **Routing Recall (Tool)** | **99.9%** | **98.8%** |
189
+ | **Query Slot Exact Match** | **99.8%** | **89.5%** |
190
+ | **Recency Slot Accuracy** | **99.9%** | **97.2%** |
191
+ | **Syntactic Validity Rate** | **100.0%** | **99.8%** |
192
+ | **CPU Inference Latency** | **~3.2 ms** | **~3.4 ms** |
193
+
194
+ > OOD = templates strictly held-out from training (unseen surface forms, same entity pools).
195
+
196
+ ---
197
+
198
+ ## πŸ”€ Output Protocol
199
+
200
+ TinyLM outputs a strict, pipe-delimited schema:
201
+
202
+ ```
203
+ web_search|query=<search query>|recency=<day|week|any>
204
+ none
205
+ ```
206
+
207
+ **Examples:**
208
+
209
+ | User Input | Model Output |
210
+ | :--- | :--- |
211
+ | `weather in tokyo today` | `web_search\|query=tokyo weather today\|recency=day` |
212
+ | `latest AI news` | `web_search\|query=latest ai news\|recency=day` |
213
+ | `iphone 16 price in india` | `web_search\|query=iphone 16 price india\|recency=week` |
214
+ | `hi how are you` | `none` |
215
+ | `tell me a joke` | `none` |
216
+ | `what is 2 + 2` | `none` |
217
+
218
+ ---
219
+
220
+ ## πŸ¦™ GGUF & Ollama
221
+
222
+ A `tinyfc.gguf` artifact (~1.09 MB, fp16) is available in the **Files** tab above. This is a canonical Llama-architecture twin (~512k params, SwiGLU MLP) trained on the same task and tokenizer, exported for llama.cpp-compatible runtimes.
223
+
224
+ **Quick usage:**
225
+ ```bash
226
+ # Download tinyfc.gguf from the Files tab, then:
227
+ ollama create tinyfc -f Modelfile
228
+ ollama run tinyfc "latest ethereum price"
229
+ # β†’ web_search|query=ethereum price today|recency=day
230
+ ```
231
+
232
+ See the full guide in [OLLAMA.md](https://github.com/Safeeq008/tiny-fc-lm/blob/main/OLLAMA.md).
233
+
234
+ ---
235
+
236
+ ## πŸ—οΈ Reproduce from Scratch
237
+
238
+ Full pipeline available at [github.com/Safeeq008/tiny-fc-lm](https://github.com/Safeeq008/tiny-fc-lm):
239
+
240
+ ```bash
241
+ git clone https://github.com/Safeeq008/tiny-fc-lm.git
242
+ cd tiny-fc-lm && pip install -r requirements.txt
243
+
244
+ python gen_data.py # 1. Generate 80k synthetic training samples
245
+ python train_tok.py # 2. Train custom 2048-vocab BPE tokenizer
246
+ python train.py # 3. Train TinyLM-FC model (~5-10 min, CPU)
247
+ python eval.py # 4. Full benchmark suite (val + OOD)
248
+ python infer.py # 5. Interactive CLI with live DuckDuckGo search
249
+ python serve.py 8000 # 6. FastAPI server + web UI
250
+
251
+ # Optional: GGUF/Ollama path
252
+ python train_llama.py # 7. Train Llama-arch twin
253
+ python export_gguf.py # 8. Convert to GGUF
254
+ ollama create tinyfc -f Modelfile && ollama run tinyfc
255
+ ```
256
+
257
+ ---
258
+
259
+ ## ⚠️ Known Limitations
260
+
261
+ 1. **Single-tool**: Strictly routes `web_search` only β€” no multi-tool schemas.
262
+ 2. **English only**: Custom BPE tokenizer trained on English synthetic corpus.
263
+ 3. **80-token context window**: Inputs > ~60 user tokens are silently truncated.
264
+ 4. **Synthetic training data**: Real-world query distributions are far noisier; OOD generalization is limited to phrasing variation, not domain shift.
265
+ 5. **Constrained decoding required**: Raw greedy decoding may produce malformed outputs; use `infer.py`'s constrained decoder for production.
266
+
267
+ ---
268
+
269
+ ## πŸ“„ License
270
+
271
+ Released under the **MIT License** β€” free for research, benchmarking, commercial use, and edge deployment.
272
 
273
+ **Repository:** [github.com/Safeeq008/tiny-fc-lm](https://github.com/Safeeq008/tiny-fc-lm)