Text Generation
Transformers
Safetensors
English
llama
hand-crafted
compiled
autocomplete
no-training
n-gram
code
browser
text-generation-inference
Instructions to use tmickleydoyle/tiny-autocomplete with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use tmickleydoyle/tiny-autocomplete with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="tmickleydoyle/tiny-autocomplete")# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("tmickleydoyle/tiny-autocomplete") model = AutoModelForCausalLM.from_pretrained("tmickleydoyle/tiny-autocomplete", device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use tmickleydoyle/tiny-autocomplete with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "tmickleydoyle/tiny-autocomplete" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "tmickleydoyle/tiny-autocomplete", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/tmickleydoyle/tiny-autocomplete
- SGLang
How to use tmickleydoyle/tiny-autocomplete with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "tmickleydoyle/tiny-autocomplete" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "tmickleydoyle/tiny-autocomplete", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "tmickleydoyle/tiny-autocomplete" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "tmickleydoyle/tiny-autocomplete", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use tmickleydoyle/tiny-autocomplete with Docker Model Runner:
docker model run hf.co/tmickleydoyle/tiny-autocomplete
Compiled (not trained) 91M-param Llama autocomplete model, TypeScript runtime and UI, docs
Browse files- LICENSE +21 -0
- README.md +160 -0
- autocomplete.ts +37 -0
- build_weights.py +320 -0
- config.json +33 -0
- docs/how-it-works.md +151 -0
- generation_config.json +8 -0
- model.safetensors +3 -0
- model.ts +266 -0
- phrases/everyday.txt +275 -0
- phrases/idioms.txt +321 -0
- phrases/opinions_work.txt +278 -0
- phrases/social.txt +266 -0
- requirements.txt +4 -0
- test_model.py +103 -0
- tokenizer.json +1149 -0
- tokenizer_config.json +15 -0
- ui.html +139 -0
- ui.ts +56 -0
LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2026 tmickleydoyle
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in all
|
| 13 |
+
copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 21 |
+
SOFTWARE.
|
README.md
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: mit
|
| 3 |
+
language:
|
| 4 |
+
- en
|
| 5 |
+
library_name: transformers
|
| 6 |
+
pipeline_tag: text-generation
|
| 7 |
+
tags:
|
| 8 |
+
- llama
|
| 9 |
+
- hand-crafted
|
| 10 |
+
- compiled
|
| 11 |
+
- autocomplete
|
| 12 |
+
- no-training
|
| 13 |
+
- n-gram
|
| 14 |
+
widget:
|
| 15 |
+
- text: Once upon a
|
| 16 |
+
- text: I hope this email
|
| 17 |
+
- text: The quick brown
|
| 18 |
+
---
|
| 19 |
+
|
| 20 |
+
# tiny-autocomplete
|
| 21 |
+
|
| 22 |
+
A 91M-parameter Llama-format model whose weights were **compiled, not trained**.
|
| 23 |
+
No gradient descent was run, and no other model or pretrained weights were used. Every number
|
| 24 |
+
comes from a closed-form rule in [`build_weights.py`](build_weights.py), applied to ~1,100
|
| 25 |
+
common English phrases in [`phrases/`](phrases). Full details are in
|
| 26 |
+
[docs/how-it-works.md](docs/how-it-works.md).
|
| 27 |
+
|
| 28 |
+
| Prompt | Greedy completion |
|
| 29 |
+
|---|---|
|
| 30 |
+
| Once upon a | time. |
|
| 31 |
+
| The quick brown | fox jumps over the lazy dog. |
|
| 32 |
+
| I hope this email | finds you well. |
|
| 33 |
+
| Thank you for your | help. |
|
| 34 |
+
| Can I have the | check, please? |
|
| 35 |
+
| Looking forward to | hearing from you. |
|
| 36 |
+
| Actions speak | louder than words. |
|
| 37 |
+
| How are | you doing? |
|
| 38 |
+
|
| 39 |
+
## Use it with transformers
|
| 40 |
+
|
| 41 |
+
```python
|
| 42 |
+
from transformers import pipeline
|
| 43 |
+
|
| 44 |
+
gen = pipeline("text-generation", model="tmickleydoyle/tiny-autocomplete")
|
| 45 |
+
gen("Once upon a")[0]["generated_text"] # 'Once upon a time.'
|
| 46 |
+
```
|
| 47 |
+
|
| 48 |
+
Next-word suggestions with probabilities:
|
| 49 |
+
|
| 50 |
+
```python
|
| 51 |
+
import torch
|
| 52 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 53 |
+
|
| 54 |
+
tok = AutoTokenizer.from_pretrained("tmickleydoyle/tiny-autocomplete")
|
| 55 |
+
model = AutoModelForCausalLM.from_pretrained("tmickleydoyle/tiny-autocomplete")
|
| 56 |
+
|
| 57 |
+
ids = tok("Thank you for", return_tensors="pt")
|
| 58 |
+
with torch.no_grad():
|
| 59 |
+
probs = model(**ids).logits[0, -1].softmax(-1)
|
| 60 |
+
for p, i in zip(*probs.topk(5)):
|
| 61 |
+
print(repr(tok.decode(i)), f"{p:.1%}") # ' your' 37.6%, ' the' 16.7%, ...
|
| 62 |
+
|
| 63 |
+
out = model.generate(**ids, max_new_tokens=16)
|
| 64 |
+
print(tok.decode(out[0], skip_special_tokens=True)) # ' thank you for your help.'
|
| 65 |
+
```
|
| 66 |
+
|
| 67 |
+
The tokenizer lowercases input, so output is lowercase. A BOS token is prepended
|
| 68 |
+
automatically.
|
| 69 |
+
|
| 70 |
+
## Use it without Python (TypeScript, zero dependencies)
|
| 71 |
+
|
| 72 |
+
`model.ts` reads `config.json`, `model.safetensors` and `tokenizer.json` and runs the Llama
|
| 73 |
+
forward pass in plain TypeScript. It needs no ML library. It runs on [Bun](https://bun.sh)
|
| 74 |
+
or Node ≥ 23.6.
|
| 75 |
+
|
| 76 |
+
```bash
|
| 77 |
+
git lfs install
|
| 78 |
+
git clone https://huggingface.co/tmickleydoyle/tiny-autocomplete
|
| 79 |
+
cd tiny-autocomplete
|
| 80 |
+
|
| 81 |
+
bun ui.ts # web UI at http://localhost:3000
|
| 82 |
+
bun autocomplete.ts # terminal REPL
|
| 83 |
+
bun autocomplete.ts "Once upon a" "Can you"
|
| 84 |
+
```
|
| 85 |
+
|
| 86 |
+
In the web UI, type a prompt to see the predicted completion as gray ghost text and the top
|
| 87 |
+
5 next words with probabilities. **Tab** accepts the completion, **Enter** accepts the
|
| 88 |
+
top next word, and clicking a word appends it.
|
| 89 |
+
|
| 90 |
+
## What it computes
|
| 91 |
+
|
| 92 |
+
The network is an exact transformer implementation of an **interpolated Witten-Bell 5-gram
|
| 93 |
+
language model**. It predicts the next word from the current word plus up to 3 before it,
|
| 94 |
+
falling back to shorter contexts when a longer one is unknown. Its log-probabilities match the
|
| 95 |
+
reference n-gram to within 1e-3 nats.
|
| 96 |
+
|
| 97 |
+
## How the weights are built (summary)
|
| 98 |
+
|
| 99 |
+
The residual stream is split into named slots: a constant 1, the current token's code, the
|
| 100 |
+
codes of the 3 previous tokens, and a logit slot.
|
| 101 |
+
|
| 102 |
+
- **Embeddings:** each token gets a seeded random unit vector of size 256, plus the constant.
|
| 103 |
+
- **Attention:** 3 heads with constant queries and keys. Their RoPE phases make each head look
|
| 104 |
+
exactly 1, 2 or 3 tokens back, with a margin of ≥ 30 nats. The head copies that token's code
|
| 105 |
+
into its slot.
|
| 106 |
+
- **MLP:** one neuron per context of 1–4 tokens seen in the phrases (13,148 neurons in total).
|
| 107 |
+
A neuron fires only when every token in its context matches. It adds
|
| 108 |
+
`log p(next | context) − log p(next | shorter context)` to the logits. These additions
|
| 109 |
+
telescope to the log-probability under the longest known context.
|
| 110 |
+
- **Norms and head:** RMSNorm weights cancel the fixed residual norms. `lm_head` reads the
|
| 111 |
+
logit slot.
|
| 112 |
+
|
| 113 |
+
The [docs](docs/how-it-works.md) have the formulas, the proof of exactness, and how to
|
| 114 |
+
recompile with your own phrases.
|
| 115 |
+
|
| 116 |
+
## Architecture
|
| 117 |
+
|
| 118 |
+
`LlamaForCausalLM` with standard modules only, so no `trust_remote_code` is needed. The settings
|
| 119 |
+
are 1 layer, hidden 2088, 3 query heads, 1 KV head, head_dim 256, MLP width 13,148, vocab 1,053,
|
| 120 |
+
rope_theta 2, float32.
|
| 121 |
+
|
| 122 |
+
| Tensor | Params |
|
| 123 |
+
|---|---|
|
| 124 |
+
| `embed_tokens`, `lm_head` | 4,397,328 |
|
| 125 |
+
| attention q/k/v/o | 4,276,224 |
|
| 126 |
+
| MLP gate/up/down | 82,359,072 |
|
| 127 |
+
| RMSNorms | 6,264 |
|
| 128 |
+
| **total** | **91,038,888** |
|
| 129 |
+
|
| 130 |
+
## Limitations
|
| 131 |
+
|
| 132 |
+
- It only knows its ~1,100 source phrases: 1,053 words, at most 4 tokens of context, and
|
| 133 |
+
128 positions. Unknown words become `<unk>`, and the model backs off past them.
|
| 134 |
+
- It's a lookup machine, not a reasoning model. On novel text it predicts common next
|
| 135 |
+
words, not meaningful continuations.
|
| 136 |
+
- The prompt is treated as the start of a sentence.
|
| 137 |
+
- The phrase list was written by an AI coding assistant (Claude) for this project. No
|
| 138 |
+
corpus was scraped.
|
| 139 |
+
|
| 140 |
+
## Rebuild and verify
|
| 141 |
+
|
| 142 |
+
```bash
|
| 143 |
+
pip install -r requirements.txt
|
| 144 |
+
python build_weights.py # writes config, weights and tokenizer from phrases/*.txt
|
| 145 |
+
python test_model.py # HF loading, n-gram exactness, pipeline, TypeScript parity
|
| 146 |
+
```
|
| 147 |
+
|
| 148 |
+
Tested with transformers 4.52.4 and 5.22.1, Bun 1.3 and Node 24.
|
| 149 |
+
|
| 150 |
+
## Files
|
| 151 |
+
|
| 152 |
+
| File | Purpose |
|
| 153 |
+
|---|---|
|
| 154 |
+
| `config.json`, `generation_config.json`, `model.safetensors` | model |
|
| 155 |
+
| `tokenizer.json`, `tokenizer_config.json` | tokenizer |
|
| 156 |
+
| `build_weights.py` | the compiler that writes every file above |
|
| 157 |
+
| `phrases/*.txt` | source phrases |
|
| 158 |
+
| `test_model.py` | verification suite |
|
| 159 |
+
| `model.ts`, `autocomplete.ts`, `ui.ts`, `ui.html` | zero-dependency TypeScript runtime, CLI and web UI |
|
| 160 |
+
| `docs/how-it-works.md` | full construction details |
|
autocomplete.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Command-line autocomplete tester (zero dependencies).
|
| 2 |
+
//
|
| 3 |
+
// bun autocomplete.ts interactive prompt
|
| 4 |
+
// bun autocomplete.ts "once upon a" complete one or more prompts
|
| 5 |
+
// bun autocomplete.ts --json "how are" machine-readable output (used by tests)
|
| 6 |
+
//
|
| 7 |
+
// Also runs on Node >= 23.6 (`node autocomplete.ts`). For a browser UI see ui.ts.
|
| 8 |
+
|
| 9 |
+
import { createInterface } from "node:readline";
|
| 10 |
+
import { Autocompleter } from "./model.ts";
|
| 11 |
+
|
| 12 |
+
const DIR = import.meta.dirname ?? new URL(".", import.meta.url).pathname;
|
| 13 |
+
const ac = new Autocompleter(DIR);
|
| 14 |
+
|
| 15 |
+
function show(prompt: string): void {
|
| 16 |
+
const t0 = performance.now();
|
| 17 |
+
const r = ac.complete(prompt);
|
| 18 |
+
const ms = Math.round(performance.now() - t0);
|
| 19 |
+
console.log(`${prompt}\x1b[36m${r.completion}\x1b[0m (${ms} ms)`);
|
| 20 |
+
console.log(" next: " + r.top.map((t) => `${JSON.stringify(t.token)} ${(Math.exp(t.logprob) * 100).toFixed(1)}%`).join(" "));
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
const args = process.argv.slice(2);
|
| 24 |
+
if (args[0] === "--json") {
|
| 25 |
+
console.log(JSON.stringify(args.slice(1).map((p) => ac.complete(p))));
|
| 26 |
+
} else if (args.length) {
|
| 27 |
+
args.forEach(show);
|
| 28 |
+
} else {
|
| 29 |
+
const cfg = ac.model.cfg;
|
| 30 |
+
console.log(`Loaded ${cfg.num_hidden_layers}-layer model, vocab ${cfg.vocab_size}. Type a prefix (Ctrl+D to quit).`);
|
| 31 |
+
const rl = createInterface({ input: process.stdin, output: process.stdout, prompt: "> " });
|
| 32 |
+
rl.prompt();
|
| 33 |
+
rl.on("line", (line) => {
|
| 34 |
+
if (line.trim()) show(line);
|
| 35 |
+
rl.prompt();
|
| 36 |
+
});
|
| 37 |
+
}
|
build_weights.py
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Compile phrases/*.txt into a Llama-format autocomplete model. No training.
|
| 2 |
+
|
| 3 |
+
Every weight is set by a closed-form rule; nothing is fit by gradient descent
|
| 4 |
+
and no other model is used. The result is an exact transformer implementation
|
| 5 |
+
of an interpolated Witten-Bell 5-gram language model over the phrase list.
|
| 6 |
+
|
| 7 |
+
Residual stream layout (hidden_size = 1 + 4*CODE_DIM + vocab):
|
| 8 |
+
[0] constant 1 (acts as a bias, Llama has none)
|
| 9 |
+
cur slot (CODE_DIM) code of the current token <- embedding
|
| 10 |
+
prev1..3 (CODE_DIM) codes of the 1..3 previous tokens <- attention
|
| 11 |
+
out slot (vocab) next-token logits, scaled by OUT_SCALE <- MLP
|
| 12 |
+
|
| 13 |
+
Token codes are seeded random unit vectors (nearly orthogonal). Attention head
|
| 14 |
+
a (a = 1..3) has constant query/key vectors whose RoPE phases make the score
|
| 15 |
+
peak at exactly a positions back; its value copies that token's code into
|
| 16 |
+
slot prev_a. Positions before the start fall back to position 0 (BOS).
|
| 17 |
+
|
| 18 |
+
The MLP has one neuron per context seen in the phrases (1-4 tokens, plus one
|
| 19 |
+
always-on unigram neuron). A neuron's gate sums code matches across slots
|
| 20 |
+
minus (k - 0.5), so it fires only when all k tokens match. It writes
|
| 21 |
+
log p(next | ctx) - log p(next | shorter ctx) into the out slot. All suffixes
|
| 22 |
+
of the true context fire together, so the sum telescopes to the log
|
| 23 |
+
probability under the longest matching context.
|
| 24 |
+
"""
|
| 25 |
+
|
| 26 |
+
import json
|
| 27 |
+
import math
|
| 28 |
+
from collections import Counter, defaultdict
|
| 29 |
+
from functools import lru_cache
|
| 30 |
+
from pathlib import Path
|
| 31 |
+
|
| 32 |
+
import torch
|
| 33 |
+
from safetensors.torch import save_file
|
| 34 |
+
from tokenizers import Tokenizer, decoders, models, normalizers, pre_tokenizers, processors
|
| 35 |
+
from transformers import GenerationConfig, LlamaConfig, PreTrainedTokenizerFast
|
| 36 |
+
|
| 37 |
+
ROOT = Path(__file__).parent
|
| 38 |
+
PHRASE_DIR = ROOT / "phrases"
|
| 39 |
+
EOS, UNK = "<|endoftext|>", "<unk>" # EOS doubles as BOS and pad, like GPT-2
|
| 40 |
+
|
| 41 |
+
SEED = 1234
|
| 42 |
+
CODE_DIM = 256
|
| 43 |
+
N_PREV = 3 # previous tokens attended to; context = N_PREV + current
|
| 44 |
+
ORDER = N_PREV + 1
|
| 45 |
+
MAX_POS = 128
|
| 46 |
+
ATTN_MARGIN = 30.0 # min attention logit gap (nats) between target and any other position
|
| 47 |
+
BETA = 100.0 # gate sharpness; matched neurons sit at z = BETA / 2
|
| 48 |
+
OUT_SCALE = 1e-4 # keeps the out slot tiny so the final RMSNorm scale stays fixed
|
| 49 |
+
UNK_LOGIT = -30.0
|
| 50 |
+
ROPE_THETA_CANDIDATES = [2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0, 1000.0, 10000.0]
|
| 51 |
+
|
| 52 |
+
NORMALIZER = normalizers.Sequence([normalizers.NFKC(), normalizers.Lowercase()])
|
| 53 |
+
PRE_TOKENIZER = pre_tokenizers.ByteLevel(add_prefix_space=True)
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def pieces(text: str) -> list[str]:
|
| 57 |
+
return [p for p, _ in PRE_TOKENIZER.pre_tokenize_str(NORMALIZER.normalize_str(text))]
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def load_phrases() -> list[list[str]]:
|
| 61 |
+
seen, out = set(), []
|
| 62 |
+
for path in sorted(PHRASE_DIR.glob("*.txt")):
|
| 63 |
+
for line in path.read_text().splitlines():
|
| 64 |
+
line = line.strip()
|
| 65 |
+
if not line or line.startswith("#"):
|
| 66 |
+
continue
|
| 67 |
+
toks = pieces(line)
|
| 68 |
+
if tuple(toks) not in seen:
|
| 69 |
+
seen.add(tuple(toks))
|
| 70 |
+
out.append(toks)
|
| 71 |
+
return out
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
class NGram:
|
| 75 |
+
"""Interpolated Witten-Bell n-gram; the reference the weights must reproduce."""
|
| 76 |
+
|
| 77 |
+
def __init__(self, sequences: list[list[int]], vocab_size: int):
|
| 78 |
+
self.V = vocab_size
|
| 79 |
+
self.counts = [defaultdict(Counter) for _ in range(ORDER + 1)]
|
| 80 |
+
for seq in sequences:
|
| 81 |
+
# ORDER BOS tokens: the last one is the real BOS position the model sees.
|
| 82 |
+
padded = [0] * ORDER + seq + [0]
|
| 83 |
+
for i in range(ORDER - 1, len(padded) - 1):
|
| 84 |
+
for k in range(ORDER + 1):
|
| 85 |
+
ctx = tuple(padded[i - k + 1 : i + 1]) if k else ()
|
| 86 |
+
self.counts[k][ctx][padded[i + 1]] += 1
|
| 87 |
+
|
| 88 |
+
uni = torch.zeros(vocab_size, dtype=torch.float64)
|
| 89 |
+
for j, c in self.counts[0][()].items():
|
| 90 |
+
uni[j] = c
|
| 91 |
+
logits = torch.log(uni + 1.0) # add-one smoothing
|
| 92 |
+
logits[1] = UNK_LOGIT
|
| 93 |
+
self.base_logits = logits - logits[2:].mean() # constant shift; softmax-invariant
|
| 94 |
+
self.p0 = torch.softmax(self.base_logits, 0)
|
| 95 |
+
|
| 96 |
+
@lru_cache(maxsize=None)
|
| 97 |
+
def prob(self, j: int, ctx: tuple) -> float:
|
| 98 |
+
if not ctx:
|
| 99 |
+
return self.p0[j].item()
|
| 100 |
+
lower = self.prob(j, ctx[1:])
|
| 101 |
+
table = self.counts[len(ctx)].get(ctx)
|
| 102 |
+
if table is None:
|
| 103 |
+
return lower
|
| 104 |
+
total, uniq = sum(table.values()), len(table)
|
| 105 |
+
return (table.get(j, 0) + uniq * lower) / (total + uniq)
|
| 106 |
+
|
| 107 |
+
def delta(self, ctx: tuple) -> dict[int, float]:
|
| 108 |
+
"""log p_k - log p_{k-1}, minus the constant log(u/(c+u)) shared by unseen tokens."""
|
| 109 |
+
table = self.counts[len(ctx)][ctx]
|
| 110 |
+
uniq = len(table)
|
| 111 |
+
out = {}
|
| 112 |
+
for j, c in table.items():
|
| 113 |
+
q = self.prob(j, ctx[1:])
|
| 114 |
+
out[j] = math.log(c + uniq * q) - math.log(uniq * q)
|
| 115 |
+
return out
|
| 116 |
+
|
| 117 |
+
def contexts(self) -> list[tuple]:
|
| 118 |
+
return [ctx for k in range(1, ORDER + 1) for ctx in sorted(self.counts[k])]
|
| 119 |
+
|
| 120 |
+
def reference_logits(self, ids: list[int]) -> torch.Tensor:
|
| 121 |
+
"""Logits (up to a constant) the model should emit after the last token of ids."""
|
| 122 |
+
t = len(ids) - 1
|
| 123 |
+
window = [ids[max(t - a, 0)] for a in range(N_PREV, -1, -1)] # oldest .. current
|
| 124 |
+
logits = self.base_logits.clone()
|
| 125 |
+
for k in range(1, ORDER + 1):
|
| 126 |
+
ctx = tuple(window[-k:])
|
| 127 |
+
if ctx in self.counts[k]:
|
| 128 |
+
for j, d in self.delta(ctx).items():
|
| 129 |
+
logits[j] += d
|
| 130 |
+
return logits
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
def rope_attention_scale(head_dim: int) -> tuple[float, torch.Tensor, float]:
|
| 134 |
+
"""Pick rope_theta maximizing the worst-case attention margin; return (theta, inv_freq, q_amp)."""
|
| 135 |
+
best = None
|
| 136 |
+
for theta in ROPE_THETA_CANDIDATES:
|
| 137 |
+
inv_freq = 1.0 / (theta ** (torch.arange(0, head_dim, 2, dtype=torch.int64).double() / head_dim))
|
| 138 |
+
offsets = torch.arange(-MAX_POS, MAX_POS + 1, dtype=torch.float64)
|
| 139 |
+
kernel = torch.cos(offsets[:, None] * inv_freq[None, :]).sum(1) # K(x), index x + MAX_POS
|
| 140 |
+
worst = math.inf
|
| 141 |
+
for lag in range(1, N_PREV + 1):
|
| 142 |
+
for t in range(MAX_POS):
|
| 143 |
+
s_target = max(t - lag, 0)
|
| 144 |
+
xs = torch.tensor([t - s - lag for s in range(t + 1)]) + MAX_POS
|
| 145 |
+
scores = kernel[xs]
|
| 146 |
+
others = torch.cat([scores[:s_target], scores[s_target + 1 :]])
|
| 147 |
+
if len(others):
|
| 148 |
+
worst = min(worst, (scores[s_target] - others.max()).item())
|
| 149 |
+
if best is None or worst > best[0]:
|
| 150 |
+
best = (worst, theta, inv_freq)
|
| 151 |
+
worst, theta, inv_freq = best
|
| 152 |
+
assert worst > 0, "no rope_theta separates positions"
|
| 153 |
+
# score = q_amp * sum_i cos(...) / sqrt(head_dim) (key amplitude 1)
|
| 154 |
+
q_amp = ATTN_MARGIN * math.sqrt(head_dim) / worst
|
| 155 |
+
return theta, inv_freq, q_amp
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
def build(phrases: list[list[str]]):
|
| 159 |
+
freq = Counter(p for toks in phrases for p in toks)
|
| 160 |
+
vocab = [EOS, UNK] + sorted(freq, key=lambda p: (-freq[p], p))
|
| 161 |
+
index = {p: i for i, p in enumerate(vocab)}
|
| 162 |
+
V, m = len(vocab), CODE_DIM
|
| 163 |
+
ngram = NGram([[index[p] for p in toks] for toks in phrases], V)
|
| 164 |
+
contexts = ngram.contexts()
|
| 165 |
+
|
| 166 |
+
CONST, CUR = 0, 1
|
| 167 |
+
prev_slot = [1 + a * m for a in range(N_PREV + 1)] # prev_slot[0] is the cur slot
|
| 168 |
+
OUT = 1 + (N_PREV + 1) * m
|
| 169 |
+
n_heads, h = N_PREV, m
|
| 170 |
+
# transformers validates hidden_size % num_heads == 0; pad with unused zero dims.
|
| 171 |
+
D = -(-(OUT + V) // (8 * n_heads)) * (8 * n_heads)
|
| 172 |
+
N = 1 + len(contexts)
|
| 173 |
+
|
| 174 |
+
gen = torch.Generator().manual_seed(SEED)
|
| 175 |
+
codes = torch.randn(V, m, generator=gen, dtype=torch.float64)
|
| 176 |
+
codes /= codes.norm(dim=1, keepdim=True)
|
| 177 |
+
gram = codes @ codes.T
|
| 178 |
+
gram.fill_diagonal_(0)
|
| 179 |
+
max_coherence = gram.abs().max().item()
|
| 180 |
+
assert max_coherence < 0.4, max_coherence
|
| 181 |
+
|
| 182 |
+
embed = torch.zeros(V, D, dtype=torch.float64)
|
| 183 |
+
embed[:, CONST] = 1.0
|
| 184 |
+
embed[:, CUR : CUR + m] = codes
|
| 185 |
+
|
| 186 |
+
theta, inv_freq, q_amp = rope_attention_scale(h)
|
| 187 |
+
half = h // 2
|
| 188 |
+
q_proj = torch.zeros(n_heads * h, D, dtype=torch.float64)
|
| 189 |
+
for a in range(n_heads):
|
| 190 |
+
lag = a + 1
|
| 191 |
+
q_proj[a * h : a * h + half, CONST] = q_amp * torch.cos(lag * inv_freq)
|
| 192 |
+
q_proj[a * h + half : (a + 1) * h, CONST] = -q_amp * torch.sin(lag * inv_freq)
|
| 193 |
+
k_proj = torch.zeros(h, D, dtype=torch.float64)
|
| 194 |
+
k_proj[:half, CONST] = 1.0
|
| 195 |
+
v_proj = torch.zeros(h, D, dtype=torch.float64)
|
| 196 |
+
v_proj[:, CUR : CUR + m] = torch.eye(m, dtype=torch.float64)
|
| 197 |
+
o_proj = torch.zeros(D, n_heads * h, dtype=torch.float64)
|
| 198 |
+
for a in range(n_heads):
|
| 199 |
+
o_proj[prev_slot[a + 1] : prev_slot[a + 1] + m, a * h : (a + 1) * h] = torch.eye(m, dtype=torch.float64)
|
| 200 |
+
|
| 201 |
+
gate = torch.zeros(N, D, dtype=torch.float64)
|
| 202 |
+
up = torch.zeros(N, D, dtype=torch.float64)
|
| 203 |
+
down = torch.zeros(D, N, dtype=torch.float64)
|
| 204 |
+
on = (BETA / 2) * torch.sigmoid(torch.tensor(BETA / 2, dtype=torch.float64)).item() # silu(BETA/2)
|
| 205 |
+
up[:, CONST] = 1.0
|
| 206 |
+
gate[0, CONST] = BETA / 2 # always-on unigram neuron
|
| 207 |
+
down[OUT : OUT + V, 0] = OUT_SCALE * ngram.base_logits / on
|
| 208 |
+
for n, ctx in enumerate(contexts, start=1):
|
| 209 |
+
k = len(ctx)
|
| 210 |
+
for a, tok in enumerate(reversed(ctx)): # a = 0 current, a = 1 previous, ...
|
| 211 |
+
gate[n, prev_slot[a] : prev_slot[a] + m] = BETA * codes[tok]
|
| 212 |
+
gate[n, CONST] = -BETA * (k - 0.5)
|
| 213 |
+
for j, d in ngram.delta(ctx).items():
|
| 214 |
+
down[OUT + j, n] = OUT_SCALE * d / on
|
| 215 |
+
|
| 216 |
+
lm_head = torch.zeros(V, D, dtype=torch.float64)
|
| 217 |
+
lm_head[torch.arange(V), OUT + torch.arange(V)] = 1.0 / OUT_SCALE
|
| 218 |
+
|
| 219 |
+
# RMSNorm weights undo the norm for the (fixed) input norms: |x|^2 = 2 before
|
| 220 |
+
# attention, 1 + 1 + N_PREV after it.
|
| 221 |
+
attn_norm = math.sqrt(2 / D)
|
| 222 |
+
mlp_norm = math.sqrt((2 + N_PREV) / D)
|
| 223 |
+
state = {
|
| 224 |
+
"model.embed_tokens.weight": embed,
|
| 225 |
+
"model.layers.0.input_layernorm.weight": torch.full((D,), attn_norm),
|
| 226 |
+
"model.layers.0.self_attn.q_proj.weight": q_proj,
|
| 227 |
+
"model.layers.0.self_attn.k_proj.weight": k_proj,
|
| 228 |
+
"model.layers.0.self_attn.v_proj.weight": v_proj,
|
| 229 |
+
"model.layers.0.self_attn.o_proj.weight": o_proj,
|
| 230 |
+
"model.layers.0.post_attention_layernorm.weight": torch.full((D,), mlp_norm),
|
| 231 |
+
"model.layers.0.mlp.gate_proj.weight": gate,
|
| 232 |
+
"model.layers.0.mlp.up_proj.weight": up,
|
| 233 |
+
"model.layers.0.mlp.down_proj.weight": down,
|
| 234 |
+
"model.norm.weight": torch.full((D,), mlp_norm),
|
| 235 |
+
"lm_head.weight": lm_head,
|
| 236 |
+
}
|
| 237 |
+
state = {k: v.to(torch.float32).contiguous() for k, v in state.items()}
|
| 238 |
+
|
| 239 |
+
config = LlamaConfig(
|
| 240 |
+
vocab_size=V,
|
| 241 |
+
hidden_size=D,
|
| 242 |
+
intermediate_size=N,
|
| 243 |
+
num_hidden_layers=1,
|
| 244 |
+
num_attention_heads=n_heads,
|
| 245 |
+
num_key_value_heads=1,
|
| 246 |
+
head_dim=h,
|
| 247 |
+
hidden_act="silu",
|
| 248 |
+
max_position_embeddings=MAX_POS,
|
| 249 |
+
rms_norm_eps=1e-10,
|
| 250 |
+
rope_theta=theta,
|
| 251 |
+
tie_word_embeddings=False,
|
| 252 |
+
bos_token_id=0,
|
| 253 |
+
eos_token_id=0,
|
| 254 |
+
pad_token_id=0,
|
| 255 |
+
)
|
| 256 |
+
info = {
|
| 257 |
+
"vocab": V,
|
| 258 |
+
"hidden": D,
|
| 259 |
+
"neurons": N,
|
| 260 |
+
"rope_theta": theta,
|
| 261 |
+
"max_code_coherence": round(max_coherence, 3),
|
| 262 |
+
"params": sum(t.numel() for t in state.values()),
|
| 263 |
+
}
|
| 264 |
+
return vocab, ngram, state, config, info
|
| 265 |
+
|
| 266 |
+
|
| 267 |
+
def build_tokenizer(vocab: list[str]) -> PreTrainedTokenizerFast:
|
| 268 |
+
tok = Tokenizer(models.WordLevel({p: i for i, p in enumerate(vocab)}, unk_token=UNK))
|
| 269 |
+
tok.normalizer = NORMALIZER
|
| 270 |
+
tok.pre_tokenizer = PRE_TOKENIZER
|
| 271 |
+
tok.decoder = decoders.ByteLevel()
|
| 272 |
+
tok.post_processor = processors.TemplateProcessing(single=f"{EOS} $A", special_tokens=[(EOS, 0)])
|
| 273 |
+
return PreTrainedTokenizerFast(
|
| 274 |
+
tokenizer_object=tok,
|
| 275 |
+
bos_token=EOS,
|
| 276 |
+
eos_token=EOS,
|
| 277 |
+
unk_token=UNK,
|
| 278 |
+
pad_token=EOS,
|
| 279 |
+
clean_up_tokenization_spaces=False,
|
| 280 |
+
model_max_length=MAX_POS,
|
| 281 |
+
)
|
| 282 |
+
|
| 283 |
+
|
| 284 |
+
def compile_model():
|
| 285 |
+
"""Build everything in memory (used by the tests for the n-gram reference)."""
|
| 286 |
+
phrases = load_phrases()
|
| 287 |
+
return (len(phrases), *build(phrases))
|
| 288 |
+
|
| 289 |
+
|
| 290 |
+
def main() -> None:
|
| 291 |
+
n_phrases, vocab, _, state, config, info = compile_model()
|
| 292 |
+
assert info["params"] <= 1_000_000_000, info
|
| 293 |
+
|
| 294 |
+
save_file(state, ROOT / "model.safetensors", metadata={"format": "pt"})
|
| 295 |
+
config.save_pretrained(ROOT)
|
| 296 |
+
cfg_path = ROOT / "config.json"
|
| 297 |
+
cfg = json.loads(cfg_path.read_text())
|
| 298 |
+
cfg["architectures"] = ["LlamaForCausalLM"]
|
| 299 |
+
cfg["rope_theta"] = info["rope_theta"] # transformers 4.x reads this key, 5.x reads rope_parameters
|
| 300 |
+
cfg["torch_dtype"] = "float32"
|
| 301 |
+
cfg_path.write_text(json.dumps(cfg, indent=2, sort_keys=True) + "\n")
|
| 302 |
+
GenerationConfig(bos_token_id=0, eos_token_id=0, pad_token_id=0, do_sample=False, max_new_tokens=16).save_pretrained(ROOT)
|
| 303 |
+
|
| 304 |
+
build_tokenizer(vocab).save_pretrained(ROOT)
|
| 305 |
+
# transformers 5 writes "TokenizersBackend", which 4.x can't resolve;
|
| 306 |
+
# PreTrainedTokenizerFast loads on both. 4.x also emits token_type_ids
|
| 307 |
+
# by default, which Llama's generate() rejects, and overrides the
|
| 308 |
+
# pre-tokenizer's add_prefix_space unless the config states it.
|
| 309 |
+
tok_cfg_path = ROOT / "tokenizer_config.json"
|
| 310 |
+
tok_cfg = json.loads(tok_cfg_path.read_text())
|
| 311 |
+
tok_cfg["tokenizer_class"] = "PreTrainedTokenizerFast"
|
| 312 |
+
tok_cfg["add_prefix_space"] = True
|
| 313 |
+
tok_cfg["model_input_names"] = ["input_ids", "attention_mask"]
|
| 314 |
+
tok_cfg_path.write_text(json.dumps(tok_cfg, indent=2) + "\n")
|
| 315 |
+
|
| 316 |
+
print(json.dumps({"phrases": n_phrases, **info}, indent=2))
|
| 317 |
+
|
| 318 |
+
|
| 319 |
+
if __name__ == "__main__":
|
| 320 |
+
main()
|
config.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architectures": [
|
| 3 |
+
"LlamaForCausalLM"
|
| 4 |
+
],
|
| 5 |
+
"attention_bias": false,
|
| 6 |
+
"attention_dropout": 0.0,
|
| 7 |
+
"bos_token_id": 0,
|
| 8 |
+
"eos_token_id": 0,
|
| 9 |
+
"head_dim": 256,
|
| 10 |
+
"hidden_act": "silu",
|
| 11 |
+
"hidden_size": 2088,
|
| 12 |
+
"initializer_range": 0.02,
|
| 13 |
+
"intermediate_size": 13148,
|
| 14 |
+
"max_position_embeddings": 128,
|
| 15 |
+
"mlp_bias": false,
|
| 16 |
+
"model_type": "llama",
|
| 17 |
+
"num_attention_heads": 3,
|
| 18 |
+
"num_hidden_layers": 1,
|
| 19 |
+
"num_key_value_heads": 1,
|
| 20 |
+
"pad_token_id": 0,
|
| 21 |
+
"pretraining_tp": 1,
|
| 22 |
+
"rms_norm_eps": 1e-10,
|
| 23 |
+
"rope_parameters": {
|
| 24 |
+
"rope_theta": 2.0,
|
| 25 |
+
"rope_type": "default"
|
| 26 |
+
},
|
| 27 |
+
"rope_theta": 2.0,
|
| 28 |
+
"tie_word_embeddings": false,
|
| 29 |
+
"torch_dtype": "float32",
|
| 30 |
+
"transformers_version": "5.22.1",
|
| 31 |
+
"use_cache": true,
|
| 32 |
+
"vocab_size": 1053
|
| 33 |
+
}
|
docs/how-it-works.md
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# How tiny-autocomplete was built
|
| 2 |
+
|
| 3 |
+
This model was **compiled, not trained**. No gradient descent, no optimizer, no
|
| 4 |
+
pretrained weights, and no other model's outputs were used. `build_weights.py` turns
|
| 5 |
+
a phrase list into a standard `LlamaForCausalLM` checkpoint using closed-form rules.
|
| 6 |
+
Running it twice gives byte-identical weights.
|
| 7 |
+
|
| 8 |
+
The network computes an **interpolated Witten-Bell 5-gram language model** exactly. It
|
| 9 |
+
predicts the next token from the current token and up to 3 before it.
|
| 10 |
+
|
| 11 |
+
## 1. Phrases and tokenizer
|
| 12 |
+
|
| 13 |
+
`phrases/*.txt` holds about 1,100 common English sentences, one per line, in four files:
|
| 14 |
+
social phrases, everyday requests, idioms and proverbs, and opinions and work phrases. The
|
| 15 |
+
list was written for this project by an AI coding assistant (Claude). No corpus was scraped.
|
| 16 |
+
|
| 17 |
+
The tokenizer is word-level with GPT-2 style byte-level pre-tokenization:
|
| 18 |
+
|
| 19 |
+
- NFKC normalization, then lowercase.
|
| 20 |
+
- Split on the GPT-2 regex. Words keep their leading space as `Ġ`, and punctuation and
|
| 21 |
+
contractions (`'s`, `'t`, ...) become their own tokens.
|
| 22 |
+
- Each piece found in the phrases is one vocabulary entry (1,053 total), plus two specials:
|
| 23 |
+
`<|endoftext|>` (id 0, used as BOS, EOS and pad) and `<unk>` (id 1).
|
| 24 |
+
- A post-processor prepends BOS, so every prompt starts at position 0 with `<|endoftext|>`.
|
| 25 |
+
|
| 26 |
+
## 2. The reference n-gram
|
| 27 |
+
|
| 28 |
+
Each phrase becomes `[BOS, BOS, BOS, BOS, w1, ..., wn, EOS]`. For every position, the
|
| 29 |
+
compiler counts which token follows each context of length k = 0..4 that ends there.
|
| 30 |
+
|
| 31 |
+
- **Order 0:** add-one-smoothed unigram, with `<unk>` pinned at logit -30.
|
| 32 |
+
- **Order k ≥ 1:** Witten-Bell interpolation with the next-shorter context (drop the
|
| 33 |
+
oldest token):
|
| 34 |
+
|
| 35 |
+
```
|
| 36 |
+
p_k(j | ctx) = (c(ctx, j) + u(ctx) * p_{k-1}(j | ctx[1:])) / (c(ctx) + u(ctx))
|
| 37 |
+
```
|
| 38 |
+
|
| 39 |
+
Here `c` is a count and `u(ctx)` is the number of distinct tokens seen after `ctx`.
|
| 40 |
+
An unseen context backs off: `p_k = p_{k-1}`.
|
| 41 |
+
|
| 42 |
+
The model must reproduce `p_K(· | longest known context)`, where K is the longest context
|
| 43 |
+
that appears in the phrase list.
|
| 44 |
+
|
| 45 |
+
## 3. The residual stream as named slots
|
| 46 |
+
|
| 47 |
+
| Dims | Slot | Written by |
|
| 48 |
+
|---|---|---|
|
| 49 |
+
| 0 | constant `1` (Llama has no biases; this plays that role) | embedding |
|
| 50 |
+
| 1–256 | code of the **current** token | embedding |
|
| 51 |
+
| 257–512 | code of the token **1 back** | attention head 1 |
|
| 52 |
+
| 513–768 | code of the token **2 back** | attention head 2 |
|
| 53 |
+
| 769–1024 | code of the token **3 back** | attention head 3 |
|
| 54 |
+
| 1025–2077 | **logits**, one dim per vocab entry, scaled by 1e-4 | MLP |
|
| 55 |
+
| 2078–2087 | unused padding (transformers wants hidden % heads == 0) | — |
|
| 56 |
+
|
| 57 |
+
**Token codes** are seeded Gaussian vectors in 256 dimensions, normalized to unit
|
| 58 |
+
length. With 1,053 of them, the largest |cosine| between two different codes is 0.30.
|
| 59 |
+
That's far enough below 1 that a "match" (dot = 1) and a "non-match" (dot ≤ 0.3) can't
|
| 60 |
+
be confused.
|
| 61 |
+
|
| 62 |
+
## 4. Attention: previous-token heads from RoPE alone
|
| 63 |
+
|
| 64 |
+
Llama has no absolute positions. The only position signal is RoPE, which rotates query
|
| 65 |
+
and key pairs by `position * inv_freq[i]`.
|
| 66 |
+
|
| 67 |
+
- The **key** for every token is the same constant (read from the constant dim): 1 on
|
| 68 |
+
the first half of each RoPE pair.
|
| 69 |
+
- The **query** for head *a* is also constant, with each pair's phase set to
|
| 70 |
+
`-a * inv_freq[i]`. The attention score between positions t and s is then
|
| 71 |
+
|
| 72 |
+
```
|
| 73 |
+
score(t, s) = A * Σ_i cos((t - s - a) * inv_freq[i]) / sqrt(head_dim)
|
| 74 |
+
```
|
| 75 |
+
|
| 76 |
+
which peaks exactly when `s = t - a`.
|
| 77 |
+
- When `t < a` there is no position `a` back, and the closest position is 0, which is BOS.
|
| 78 |
+
The model then "sees" BOS in that slot, matching the BOS padding used when counting.
|
| 79 |
+
- `rope_theta` is picked from a candidate list to maximize the worst-case gap between the
|
| 80 |
+
target position and every other position, for all t < 128 and a ∈ {1, 2, 3}. It came out
|
| 81 |
+
to 2. The amplitude `A` then scales that worst gap to **30 nats**, so softmax puts
|
| 82 |
+
> 0.9999999 weight on the target.
|
| 83 |
+
- **Value** = the current-token code. **Output projection** = identity into slot *a*.
|
| 84 |
+
|
| 85 |
+
All 3 heads share one key/value head (`num_key_value_heads = 1`).
|
| 86 |
+
|
| 87 |
+
## 5. MLP: one neuron per context
|
| 88 |
+
|
| 89 |
+
Llama's MLP is `down(silu(gate(x)) * up(x))`. The compiler creates one neuron for each
|
| 90 |
+
context seen in the phrases (13,147 of them, lengths 1–4) and one always-on unigram neuron.
|
| 91 |
+
|
| 92 |
+
For a context `(c_{k-1}, ..., c_1, c_0)` of length k (c_0 = current token):
|
| 93 |
+
|
| 94 |
+
- **gate** = `100 * (code(c_0)·cur + code(c_1)·prev1 + ... - (k - 0.5) * const)`.
|
| 95 |
+
If all k tokens match, this is `+50`. If any one fails (dot ≤ 0.3), it's at most
|
| 96 |
+
`100 * (0.3 - 0.5) = -20`, and `silu(-20)` ≈ -4e-8, effectively off.
|
| 97 |
+
- **up** = 1 (the constant dim).
|
| 98 |
+
- **down** writes, for each token j seen after this context,
|
| 99 |
+
|
| 100 |
+
```
|
| 101 |
+
delta_j = log p_k(j | ctx) - log p_{k-1}(j | ctx[1:])
|
| 102 |
+
```
|
| 103 |
+
|
| 104 |
+
into the logit slot. The constant `log(u/(c+u))` shared by every unseen token is
|
| 105 |
+
dropped, since softmax ignores constant shifts. That makes the column sparse.
|
| 106 |
+
|
| 107 |
+
**Why this is exact.** If a context of length k is in the table, so are all its shorter
|
| 108 |
+
suffixes, and their neurons fire too. The unigram neuron writes `log p_0`, and the
|
| 109 |
+
neurons for lengths 1..K add their deltas. The sum telescopes to `log p_K(· | longest
|
| 110 |
+
known context)` plus a constant. No neuron has to know which context is the longest.
|
| 111 |
+
|
| 112 |
+
## 6. Norms and output head
|
| 113 |
+
|
| 114 |
+
- The residual has a known fixed norm at each point: |x|² = 2 before attention and 5
|
| 115 |
+
after it. Each RMSNorm weight is set to `sqrt(norm² / hidden)`, so the norms leave the
|
| 116 |
+
stream unchanged.
|
| 117 |
+
- The MLP writes logits scaled by 1e-4, so they barely change the final norm (< 0.02%).
|
| 118 |
+
- `lm_head` is `1e4` times the identity on the logit slot.
|
| 119 |
+
|
| 120 |
+
## 7. Verification (`test_model.py`)
|
| 121 |
+
|
| 122 |
+
The tests check the following:
|
| 123 |
+
- **Hugging Face loading:** the files load with `AutoModelForCausalLM`, `AutoTokenizer` and
|
| 124 |
+
`pipeline("text-generation")` on transformers 4.52 and 5.22.
|
| 125 |
+
- **Exactness:** next-token log-probs match the reference n-gram within 5e-3 nats (observed
|
| 126 |
+
~8e-4). This is checked on 200 phrase prefixes and 50 random word-salad sequences of up to
|
| 127 |
+
80 tokens.
|
| 128 |
+
- **Completions:** a set of prompts produce the expected greedy completions.
|
| 129 |
+
- **Unknown words:** out-of-vocabulary words back off cleanly.
|
| 130 |
+
- **TypeScript parity:** the zero-dependency TypeScript runtime (`model.ts`) gives the same
|
| 131 |
+
top-3 tokens and log-probs as PyTorch.
|
| 132 |
+
|
| 133 |
+
## 8. Changing it
|
| 134 |
+
|
| 135 |
+
Edit or add lines in `phrases/*.txt`, then run `python build_weights.py` and
|
| 136 |
+
`python test_model.py`. The size grows with the number of distinct contexts. The MLP
|
| 137 |
+
dominates at about 3 × hidden × contexts parameters. Settings at the top of
|
| 138 |
+
`build_weights.py`:
|
| 139 |
+
|
| 140 |
+
| Constant | Meaning |
|
| 141 |
+
|---|---|
|
| 142 |
+
| `CODE_DIM` | token-code size (bigger means fewer near-collisions and a larger model) |
|
| 143 |
+
| `N_PREV` | how many previous tokens are attended to (n-gram order = N_PREV + 2) |
|
| 144 |
+
| `MAX_POS` | longest sequence the attention margin is guaranteed for |
|
| 145 |
+
| `ATTN_MARGIN`, `BETA` | sharpness of attention and of the neuron gates |
|
| 146 |
+
|
| 147 |
+
## History
|
| 148 |
+
|
| 149 |
+
The first version was a 120-parameter model (hidden size 2) that only knew a single next word
|
| 150 |
+
for each of 22 words. That size can't hold any context, so the design was scaled up to this
|
| 151 |
+
compiled n-gram, staying under a 1B-parameter budget.
|
generation_config.json
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"bos_token_id": 0,
|
| 3 |
+
"do_sample": false,
|
| 4 |
+
"eos_token_id": 0,
|
| 5 |
+
"max_new_tokens": 16,
|
| 6 |
+
"pad_token_id": 0,
|
| 7 |
+
"transformers_version": "5.22.1"
|
| 8 |
+
}
|
model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d7719627f88eaaaa8cbab54d1452596d952e68fdfd1a07b57b51f14209ed3e7b
|
| 3 |
+
size 364156872
|
model.ts
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Zero-dependency inference for this model: reads config.json, model.safetensors
|
| 2 |
+
// and tokenizer.json and runs the Llama forward pass in plain TypeScript.
|
| 3 |
+
// No ML library, no other model. Used by autocomplete.ts (CLI) and ui.ts (web UI).
|
| 4 |
+
|
| 5 |
+
import { readFileSync } from "node:fs";
|
| 6 |
+
import { join } from "node:path";
|
| 7 |
+
|
| 8 |
+
export type Config = {
|
| 9 |
+
vocab_size: number;
|
| 10 |
+
hidden_size: number;
|
| 11 |
+
intermediate_size: number;
|
| 12 |
+
num_hidden_layers: number;
|
| 13 |
+
num_attention_heads: number;
|
| 14 |
+
num_key_value_heads: number;
|
| 15 |
+
head_dim?: number;
|
| 16 |
+
rms_norm_eps: number;
|
| 17 |
+
rope_theta?: number;
|
| 18 |
+
rope_parameters?: { rope_theta: number };
|
| 19 |
+
max_position_embeddings: number;
|
| 20 |
+
eos_token_id: number;
|
| 21 |
+
};
|
| 22 |
+
|
| 23 |
+
// ---------- safetensors ----------
|
| 24 |
+
|
| 25 |
+
function loadSafetensors(path: string): Map<string, Float32Array> {
|
| 26 |
+
const buf = readFileSync(path);
|
| 27 |
+
const headerLen = Number(buf.readBigUInt64LE(0));
|
| 28 |
+
const header = JSON.parse(buf.subarray(8, 8 + headerLen).toString("utf8"));
|
| 29 |
+
const base = 8 + headerLen;
|
| 30 |
+
const tensors = new Map<string, Float32Array>();
|
| 31 |
+
for (const [name, info] of Object.entries<any>(header)) {
|
| 32 |
+
if (name === "__metadata__") continue;
|
| 33 |
+
if (info.dtype !== "F32") throw new Error(`${name}: unsupported dtype ${info.dtype}`);
|
| 34 |
+
const [begin, end] = info.data_offsets as [number, number];
|
| 35 |
+
const offset = buf.byteOffset + base + begin;
|
| 36 |
+
const length = (end - begin) / 4;
|
| 37 |
+
tensors.set(
|
| 38 |
+
name,
|
| 39 |
+
offset % 4 === 0
|
| 40 |
+
? new Float32Array(buf.buffer, offset, length)
|
| 41 |
+
: new Float32Array(buf.buffer.slice(offset, offset + length * 4)),
|
| 42 |
+
);
|
| 43 |
+
}
|
| 44 |
+
return tensors;
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
// ---------- tokenizer (WordLevel + ByteLevel, as in tokenizer.json) ----------
|
| 48 |
+
|
| 49 |
+
function bytesToUnicode(): Map<number, string> {
|
| 50 |
+
const bs: number[] = [];
|
| 51 |
+
for (let b = 33; b <= 126; b++) bs.push(b);
|
| 52 |
+
for (let b = 161; b <= 172; b++) bs.push(b);
|
| 53 |
+
for (let b = 174; b <= 255; b++) bs.push(b);
|
| 54 |
+
const cs = [...bs];
|
| 55 |
+
let n = 0;
|
| 56 |
+
for (let b = 0; b < 256; b++) {
|
| 57 |
+
if (!bs.includes(b)) {
|
| 58 |
+
bs.push(b);
|
| 59 |
+
cs.push(256 + n++);
|
| 60 |
+
}
|
| 61 |
+
}
|
| 62 |
+
return new Map(bs.map((b, i) => [b, String.fromCodePoint(cs[i])]));
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
const GPT2_SPLIT = /'s|'t|'re|'ve|'m|'ll|'d| ?\p{L}+| ?\p{N}+| ?[^\s\p{L}\p{N}]+|\s+(?!\S)|\s+/gu;
|
| 66 |
+
|
| 67 |
+
export class Tokenizer {
|
| 68 |
+
vocab: Map<string, number>;
|
| 69 |
+
inverse: string[];
|
| 70 |
+
special = new Set<number>();
|
| 71 |
+
unkId: number;
|
| 72 |
+
bosId: number;
|
| 73 |
+
private byteEnc = bytesToUnicode();
|
| 74 |
+
private byteDec = new Map([...this.byteEnc].map(([b, c]) => [c, b]));
|
| 75 |
+
|
| 76 |
+
constructor(path: string) {
|
| 77 |
+
const json = JSON.parse(readFileSync(path, "utf8"));
|
| 78 |
+
this.vocab = new Map(Object.entries<number>(json.model.vocab));
|
| 79 |
+
this.inverse = [];
|
| 80 |
+
for (const [tok, id] of this.vocab) this.inverse[id] = tok;
|
| 81 |
+
for (const t of json.added_tokens ?? []) if (t.special) this.special.add(t.id);
|
| 82 |
+
this.unkId = this.vocab.get(json.model.unk_token)!;
|
| 83 |
+
const bos = json.post_processor?.single?.find((p: any) => p.SpecialToken)?.SpecialToken?.id;
|
| 84 |
+
this.bosId = this.vocab.get(bos)!;
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
encode(text: string): number[] {
|
| 88 |
+
let norm = text.normalize("NFKC").toLowerCase();
|
| 89 |
+
if (!/^\s/.test(norm)) norm = " " + norm; // ByteLevel add_prefix_space
|
| 90 |
+
const ids = [this.bosId];
|
| 91 |
+
for (const piece of norm.match(GPT2_SPLIT) ?? []) {
|
| 92 |
+
const mapped = [...new TextEncoder().encode(piece)].map((b) => this.byteEnc.get(b)!).join("");
|
| 93 |
+
ids.push(this.vocab.get(mapped) ?? this.unkId);
|
| 94 |
+
}
|
| 95 |
+
return ids;
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
decode(ids: number[]): string {
|
| 99 |
+
const chars = ids.filter((id) => !this.special.has(id)).map((id) => this.inverse[id]).join("");
|
| 100 |
+
return new TextDecoder().decode(new Uint8Array([...chars].map((c) => this.byteDec.get(c) ?? 63)));
|
| 101 |
+
}
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
// ---------- Llama forward pass ----------
|
| 105 |
+
|
| 106 |
+
function matvec(w: Float32Array, x: Float64Array, rows: number, cols: number): Float64Array {
|
| 107 |
+
const y = new Float64Array(rows);
|
| 108 |
+
for (let r = 0; r < rows; r++) {
|
| 109 |
+
let s = 0;
|
| 110 |
+
const off = r * cols;
|
| 111 |
+
for (let c = 0; c < cols; c++) s += w[off + c] * x[c];
|
| 112 |
+
y[r] = s;
|
| 113 |
+
}
|
| 114 |
+
return y;
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
function rmsnorm(x: Float64Array, w: Float32Array, eps: number): Float64Array {
|
| 118 |
+
let ss = 0;
|
| 119 |
+
for (const v of x) ss += v * v;
|
| 120 |
+
const inv = 1 / Math.sqrt(ss / x.length + eps);
|
| 121 |
+
return x.map((v, i) => v * inv * w[i]);
|
| 122 |
+
}
|
| 123 |
+
|
| 124 |
+
export class Llama {
|
| 125 |
+
cfg: Config;
|
| 126 |
+
w: Map<string, Float32Array>;
|
| 127 |
+
headDim: number;
|
| 128 |
+
invFreq: Float64Array;
|
| 129 |
+
|
| 130 |
+
constructor(dir: string) {
|
| 131 |
+
this.cfg = JSON.parse(readFileSync(join(dir, "config.json"), "utf8"));
|
| 132 |
+
this.w = loadSafetensors(join(dir, "model.safetensors"));
|
| 133 |
+
const c = this.cfg;
|
| 134 |
+
this.headDim = c.head_dim ?? c.hidden_size / c.num_attention_heads;
|
| 135 |
+
const theta = c.rope_parameters?.rope_theta ?? c.rope_theta ?? 10000;
|
| 136 |
+
const half = this.headDim / 2;
|
| 137 |
+
this.invFreq = new Float64Array(half).map((_, i) => 1 / theta ** ((2 * i) / this.headDim));
|
| 138 |
+
}
|
| 139 |
+
|
| 140 |
+
get numParams(): number {
|
| 141 |
+
let n = 0;
|
| 142 |
+
for (const t of this.w.values()) n += t.length;
|
| 143 |
+
return n;
|
| 144 |
+
}
|
| 145 |
+
|
| 146 |
+
private t(name: string): Float32Array {
|
| 147 |
+
const t = this.w.get(name);
|
| 148 |
+
if (!t) throw new Error(`missing tensor ${name}`);
|
| 149 |
+
return t;
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
+
private rope(vec: Float64Array, offset: number, pos: number): void {
|
| 153 |
+
const half = this.headDim / 2;
|
| 154 |
+
for (let i = 0; i < half; i++) {
|
| 155 |
+
const a = pos * this.invFreq[i];
|
| 156 |
+
const cos = Math.cos(a), sin = Math.sin(a);
|
| 157 |
+
const x1 = vec[offset + i], x2 = vec[offset + i + half];
|
| 158 |
+
vec[offset + i] = x1 * cos - x2 * sin;
|
| 159 |
+
vec[offset + i + half] = x2 * cos + x1 * sin;
|
| 160 |
+
}
|
| 161 |
+
}
|
| 162 |
+
|
| 163 |
+
/** Log-probabilities of the next token after `ids`. */
|
| 164 |
+
nextLogprobs(ids: number[]): Float64Array {
|
| 165 |
+
const c = this.cfg, D = c.hidden_size, H = c.num_attention_heads, KV = c.num_key_value_heads;
|
| 166 |
+
const hd = this.headDim, I = c.intermediate_size, L = c.num_hidden_layers;
|
| 167 |
+
const embed = this.t("model.embed_tokens.weight");
|
| 168 |
+
const keys: Float64Array[][] = Array.from({ length: L }, () => []);
|
| 169 |
+
const vals: Float64Array[][] = Array.from({ length: L }, () => []);
|
| 170 |
+
let x = new Float64Array(D);
|
| 171 |
+
|
| 172 |
+
for (let pos = 0; pos < ids.length; pos++) {
|
| 173 |
+
x = Float64Array.from(embed.subarray(ids[pos] * D, (ids[pos] + 1) * D));
|
| 174 |
+
const last = pos === ids.length - 1;
|
| 175 |
+
for (let l = 0; l < L; l++) {
|
| 176 |
+
const p = `model.layers.${l}.`;
|
| 177 |
+
const xn = rmsnorm(x, this.t(p + "input_layernorm.weight"), c.rms_norm_eps);
|
| 178 |
+
const q = matvec(this.t(p + "self_attn.q_proj.weight"), xn, H * hd, D);
|
| 179 |
+
const k = matvec(this.t(p + "self_attn.k_proj.weight"), xn, KV * hd, D);
|
| 180 |
+
const v = matvec(this.t(p + "self_attn.v_proj.weight"), xn, KV * hd, D);
|
| 181 |
+
for (let h = 0; h < H; h++) this.rope(q, h * hd, pos);
|
| 182 |
+
for (let h = 0; h < KV; h++) this.rope(k, h * hd, pos);
|
| 183 |
+
keys[l].push(k);
|
| 184 |
+
vals[l].push(v);
|
| 185 |
+
|
| 186 |
+
const attn = new Float64Array(H * hd);
|
| 187 |
+
for (let h = 0; h < H; h++) {
|
| 188 |
+
const kvh = Math.floor(h / (H / KV)) * hd;
|
| 189 |
+
const scores = keys[l].map((kk) => {
|
| 190 |
+
let s = 0;
|
| 191 |
+
for (let d = 0; d < hd; d++) s += q[h * hd + d] * kk[kvh + d];
|
| 192 |
+
return s / Math.sqrt(hd);
|
| 193 |
+
});
|
| 194 |
+
const max = Math.max(...scores);
|
| 195 |
+
const exps = scores.map((s) => Math.exp(s - max));
|
| 196 |
+
const z = exps.reduce((a, b) => a + b, 0);
|
| 197 |
+
exps.forEach((e, s) => {
|
| 198 |
+
for (let d = 0; d < hd; d++) attn[h * hd + d] += (e / z) * vals[l][s][kvh + d];
|
| 199 |
+
});
|
| 200 |
+
}
|
| 201 |
+
const o = matvec(this.t(p + "self_attn.o_proj.weight"), attn, D, H * hd);
|
| 202 |
+
for (let i = 0; i < D; i++) x[i] += o[i];
|
| 203 |
+
|
| 204 |
+
// The last layer's MLP only matters where we read logits.
|
| 205 |
+
if (l === L - 1 && !last) continue;
|
| 206 |
+
const xn2 = rmsnorm(x, this.t(p + "post_attention_layernorm.weight"), c.rms_norm_eps);
|
| 207 |
+
const g = matvec(this.t(p + "mlp.gate_proj.weight"), xn2, I, D);
|
| 208 |
+
const u = matvec(this.t(p + "mlp.up_proj.weight"), xn2, I, D);
|
| 209 |
+
for (let i = 0; i < I; i++) g[i] = (g[i] / (1 + Math.exp(-g[i]))) * u[i];
|
| 210 |
+
const dn = matvec(this.t(p + "mlp.down_proj.weight"), g, D, I);
|
| 211 |
+
for (let i = 0; i < D; i++) x[i] += dn[i];
|
| 212 |
+
}
|
| 213 |
+
}
|
| 214 |
+
|
| 215 |
+
const logits = matvec(this.t("lm_head.weight"), rmsnorm(x, this.t("model.norm.weight"), c.rms_norm_eps), c.vocab_size, D);
|
| 216 |
+
const max = Math.max(...logits);
|
| 217 |
+
const lse = max + Math.log(logits.reduce((a, v) => a + Math.exp(v - max), 0));
|
| 218 |
+
return logits.map((v) => v - lse);
|
| 219 |
+
}
|
| 220 |
+
}
|
| 221 |
+
|
| 222 |
+
// ---------- autocomplete ----------
|
| 223 |
+
|
| 224 |
+
export type Completion = {
|
| 225 |
+
prompt: string;
|
| 226 |
+
completion: string;
|
| 227 |
+
top: { id: number; token: string; logprob: number }[];
|
| 228 |
+
};
|
| 229 |
+
|
| 230 |
+
export class Autocompleter {
|
| 231 |
+
tok: Tokenizer;
|
| 232 |
+
model: Llama;
|
| 233 |
+
maxNew: number;
|
| 234 |
+
|
| 235 |
+
constructor(dir: string) {
|
| 236 |
+
this.tok = new Tokenizer(join(dir, "tokenizer.json"));
|
| 237 |
+
this.model = new Llama(dir);
|
| 238 |
+
const gen = JSON.parse(readFileSync(join(dir, "generation_config.json"), "utf8"));
|
| 239 |
+
this.maxNew = gen.max_new_tokens ?? 16;
|
| 240 |
+
}
|
| 241 |
+
|
| 242 |
+
/** Greedy completion plus the top-k candidates for the next token. */
|
| 243 |
+
complete(prompt: string, topK = 3): Completion {
|
| 244 |
+
const { tok, model } = this;
|
| 245 |
+
const ids = tok.encode(prompt);
|
| 246 |
+
const first = model.nextLogprobs(ids);
|
| 247 |
+
const top = [...first.keys()]
|
| 248 |
+
.sort((a, b) => first[b] - first[a])
|
| 249 |
+
.slice(0, topK)
|
| 250 |
+
.map((id) => ({ id, token: tok.decode([id]) || tok.inverse[id], logprob: first[id] }));
|
| 251 |
+
const out: number[] = [];
|
| 252 |
+
let next = argmax(first);
|
| 253 |
+
while (next !== model.cfg.eos_token_id && out.length < this.maxNew && ids.length < model.cfg.max_position_embeddings) {
|
| 254 |
+
out.push(next);
|
| 255 |
+
ids.push(next);
|
| 256 |
+
next = argmax(model.nextLogprobs(ids));
|
| 257 |
+
}
|
| 258 |
+
return { prompt, completion: tok.decode(out), top };
|
| 259 |
+
}
|
| 260 |
+
}
|
| 261 |
+
|
| 262 |
+
function argmax(a: Float64Array): number {
|
| 263 |
+
let best = 0;
|
| 264 |
+
for (let i = 1; i < a.length; i++) if (a[i] > a[best]) best = i;
|
| 265 |
+
return best;
|
| 266 |
+
}
|
phrases/everyday.txt
ADDED
|
@@ -0,0 +1,275 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Can you help me?
|
| 2 |
+
Can you help me with this?
|
| 3 |
+
Can you help me, please?
|
| 4 |
+
Can you do me a favor?
|
| 5 |
+
Can you call me back?
|
| 6 |
+
Can you call me back later?
|
| 7 |
+
Can you say that again?
|
| 8 |
+
Can you repeat that, please?
|
| 9 |
+
Can you speak more slowly, please?
|
| 10 |
+
Can you send me the file?
|
| 11 |
+
Can you pick me up?
|
| 12 |
+
Can you pick me up at the airport?
|
| 13 |
+
Can you turn off the lights?
|
| 14 |
+
Can you turn on the lights?
|
| 15 |
+
Can you turn down the music?
|
| 16 |
+
Can you open the window?
|
| 17 |
+
Can you close the door?
|
| 18 |
+
Can you pass the salt, please?
|
| 19 |
+
Can you give me a hand?
|
| 20 |
+
Can you tell me the way to the station?
|
| 21 |
+
Can I have the check, please?
|
| 22 |
+
Can I have a glass of water?
|
| 23 |
+
Can I have the menu, please?
|
| 24 |
+
Can I get a glass of water?
|
| 25 |
+
Can I get a cup of coffee?
|
| 26 |
+
Can I get the bill, please?
|
| 27 |
+
Can I pay by card?
|
| 28 |
+
Can I pay with cash?
|
| 29 |
+
Can I try this on?
|
| 30 |
+
Can I borrow your pen?
|
| 31 |
+
Can I use your phone?
|
| 32 |
+
Can I use the bathroom?
|
| 33 |
+
Can I ask a question?
|
| 34 |
+
Can I talk to you for a minute?
|
| 35 |
+
Can I come with you?
|
| 36 |
+
Could you help me, please?
|
| 37 |
+
Could you please help me?
|
| 38 |
+
Could you tell me where the bathroom is?
|
| 39 |
+
Could you please send me the details?
|
| 40 |
+
Could you please call me back?
|
| 41 |
+
Could I have some water, please?
|
| 42 |
+
Would you like some coffee?
|
| 43 |
+
Would you like some tea?
|
| 44 |
+
Would you like something to drink?
|
| 45 |
+
Would you like to join us?
|
| 46 |
+
Would you like to come over?
|
| 47 |
+
Would you mind closing the door?
|
| 48 |
+
Would you mind helping me?
|
| 49 |
+
Do you have a minute?
|
| 50 |
+
Do you have any questions?
|
| 51 |
+
Do you have the time?
|
| 52 |
+
Do you have a table for two?
|
| 53 |
+
Do you know what time it is?
|
| 54 |
+
Do you know where the station is?
|
| 55 |
+
Do you know how to get there?
|
| 56 |
+
Do you speak English?
|
| 57 |
+
Do you need any help?
|
| 58 |
+
Do you need a ride?
|
| 59 |
+
Do you want something to eat?
|
| 60 |
+
Do you want to go out tonight?
|
| 61 |
+
Do you accept credit cards?
|
| 62 |
+
What time is it?
|
| 63 |
+
What time is it now?
|
| 64 |
+
What time do you open?
|
| 65 |
+
What time do you close?
|
| 66 |
+
What time does the train leave?
|
| 67 |
+
What time does the meeting start?
|
| 68 |
+
What time should we meet?
|
| 69 |
+
What day is it today?
|
| 70 |
+
What is the date today?
|
| 71 |
+
What's the weather like today?
|
| 72 |
+
What's the weather like tomorrow?
|
| 73 |
+
What do you want to eat?
|
| 74 |
+
What do you want to do?
|
| 75 |
+
What do you mean?
|
| 76 |
+
What do you think?
|
| 77 |
+
What happened?
|
| 78 |
+
What is this?
|
| 79 |
+
What is that?
|
| 80 |
+
What's wrong?
|
| 81 |
+
What's for dinner?
|
| 82 |
+
What would you like to order?
|
| 83 |
+
What would you recommend?
|
| 84 |
+
Where is the bathroom?
|
| 85 |
+
Where is the restroom?
|
| 86 |
+
Where is the nearest hospital?
|
| 87 |
+
Where is the train station?
|
| 88 |
+
Where is the bus stop?
|
| 89 |
+
Where is the exit?
|
| 90 |
+
Where are you?
|
| 91 |
+
Where are you going?
|
| 92 |
+
Where are my keys?
|
| 93 |
+
Where did you put it?
|
| 94 |
+
Where do you live?
|
| 95 |
+
Where should we meet?
|
| 96 |
+
How much is this?
|
| 97 |
+
How much does it cost?
|
| 98 |
+
How much is it?
|
| 99 |
+
How much do I owe you?
|
| 100 |
+
How do I get there?
|
| 101 |
+
How do I get to the airport?
|
| 102 |
+
How do you spell that?
|
| 103 |
+
How do you say that in English?
|
| 104 |
+
How do you know?
|
| 105 |
+
How long does it take?
|
| 106 |
+
How long will it take?
|
| 107 |
+
How long have you been here?
|
| 108 |
+
How far is it?
|
| 109 |
+
How many people are coming?
|
| 110 |
+
How old are you?
|
| 111 |
+
How was the movie?
|
| 112 |
+
When is the meeting?
|
| 113 |
+
When are you coming home?
|
| 114 |
+
When will you be back?
|
| 115 |
+
When does the store open?
|
| 116 |
+
When does the store close?
|
| 117 |
+
Why are you late?
|
| 118 |
+
Why not?
|
| 119 |
+
Who is calling, please?
|
| 120 |
+
Who is it?
|
| 121 |
+
Is it going to rain today?
|
| 122 |
+
Is there a bank near here?
|
| 123 |
+
Is there a pharmacy near here?
|
| 124 |
+
Is this the right way?
|
| 125 |
+
Is breakfast included?
|
| 126 |
+
It's going to rain today.
|
| 127 |
+
It's very hot today.
|
| 128 |
+
It's really cold outside.
|
| 129 |
+
It's raining outside.
|
| 130 |
+
It's snowing outside.
|
| 131 |
+
It looks like rain.
|
| 132 |
+
Don't forget your umbrella.
|
| 133 |
+
Don't forget to call me.
|
| 134 |
+
Don't forget to lock the door.
|
| 135 |
+
I'm hungry.
|
| 136 |
+
I'm thirsty.
|
| 137 |
+
I'm tired.
|
| 138 |
+
I'm so tired.
|
| 139 |
+
I'm busy right now.
|
| 140 |
+
I'm running late.
|
| 141 |
+
I'm going to be late.
|
| 142 |
+
I'll be home late tonight.
|
| 143 |
+
I'm going to bed.
|
| 144 |
+
I'm going to the store.
|
| 145 |
+
I'm going to the gym.
|
| 146 |
+
I'm going home.
|
| 147 |
+
I'm leaving now.
|
| 148 |
+
I'm looking for the bathroom.
|
| 149 |
+
I'm looking for a job.
|
| 150 |
+
I'm just looking, thank you.
|
| 151 |
+
I'm not feeling well.
|
| 152 |
+
I don't feel well.
|
| 153 |
+
I have a headache.
|
| 154 |
+
I have a cold.
|
| 155 |
+
I have a doctor's appointment.
|
| 156 |
+
I need to see a doctor.
|
| 157 |
+
I need to go to the hospital.
|
| 158 |
+
I need to go to the store.
|
| 159 |
+
I need to go to work.
|
| 160 |
+
I need to go to bed.
|
| 161 |
+
I need to talk to you.
|
| 162 |
+
I need some help.
|
| 163 |
+
I need your help.
|
| 164 |
+
I need a break.
|
| 165 |
+
I need more time.
|
| 166 |
+
I need to make a reservation.
|
| 167 |
+
I would like to make a reservation.
|
| 168 |
+
I would like to order a pizza.
|
| 169 |
+
I would like a cup of coffee, please.
|
| 170 |
+
I would like the chicken, please.
|
| 171 |
+
I'd like to book a table for two.
|
| 172 |
+
I'd like to check in, please.
|
| 173 |
+
I'd like to check out, please.
|
| 174 |
+
I'll have the same.
|
| 175 |
+
I'll have a coffee, please.
|
| 176 |
+
I'll take it.
|
| 177 |
+
I'll pay for dinner.
|
| 178 |
+
I'll call you back.
|
| 179 |
+
I'll see you there.
|
| 180 |
+
I'll be there in five minutes.
|
| 181 |
+
I'll get back to you.
|
| 182 |
+
I'll do it later.
|
| 183 |
+
I'll think about it.
|
| 184 |
+
I lost my keys.
|
| 185 |
+
I lost my phone.
|
| 186 |
+
I forgot my password.
|
| 187 |
+
I can't find my keys.
|
| 188 |
+
I can't find my phone.
|
| 189 |
+
I can't hear you.
|
| 190 |
+
I don't understand.
|
| 191 |
+
I don't know.
|
| 192 |
+
I don't know what to do.
|
| 193 |
+
I don't have time.
|
| 194 |
+
I didn't know that.
|
| 195 |
+
I have a question.
|
| 196 |
+
I have an idea.
|
| 197 |
+
I have to go.
|
| 198 |
+
I have to go now.
|
| 199 |
+
I have to work tomorrow.
|
| 200 |
+
I got it.
|
| 201 |
+
I understand.
|
| 202 |
+
I agree.
|
| 203 |
+
Let's go.
|
| 204 |
+
Let's go home.
|
| 205 |
+
Let's go out for dinner.
|
| 206 |
+
Let's eat.
|
| 207 |
+
Let's get started.
|
| 208 |
+
Let's meet at the coffee shop.
|
| 209 |
+
Let's talk about it later.
|
| 210 |
+
Let's take a break.
|
| 211 |
+
Let's watch a movie.
|
| 212 |
+
Let me check.
|
| 213 |
+
Let me help you.
|
| 214 |
+
Let me think about it.
|
| 215 |
+
Let me see.
|
| 216 |
+
Let me call you back.
|
| 217 |
+
Please call me back.
|
| 218 |
+
Please wait a moment.
|
| 219 |
+
Please hold on.
|
| 220 |
+
Please sit down.
|
| 221 |
+
Please turn off your phone.
|
| 222 |
+
Please be quiet.
|
| 223 |
+
Please close the door.
|
| 224 |
+
Please wait here.
|
| 225 |
+
Just a moment, please.
|
| 226 |
+
Just a minute.
|
| 227 |
+
One moment, please.
|
| 228 |
+
Hold on a second.
|
| 229 |
+
Wait for me.
|
| 230 |
+
Hurry up.
|
| 231 |
+
Come here.
|
| 232 |
+
Come with me.
|
| 233 |
+
Follow me.
|
| 234 |
+
Turn left at the corner.
|
| 235 |
+
Turn right at the light.
|
| 236 |
+
Go straight ahead.
|
| 237 |
+
It's on the left.
|
| 238 |
+
It's on the right.
|
| 239 |
+
It's right over there.
|
| 240 |
+
It's not far from here.
|
| 241 |
+
It's just around the corner.
|
| 242 |
+
The meeting is at noon.
|
| 243 |
+
The meeting has been canceled.
|
| 244 |
+
The train is late.
|
| 245 |
+
The store is closed.
|
| 246 |
+
The food is delicious.
|
| 247 |
+
The bill, please.
|
| 248 |
+
Check, please.
|
| 249 |
+
Table for two, please.
|
| 250 |
+
A cup of coffee, please.
|
| 251 |
+
A glass of water, please.
|
| 252 |
+
Water, please.
|
| 253 |
+
Keep the change.
|
| 254 |
+
Here you go.
|
| 255 |
+
Here it is.
|
| 256 |
+
This is delicious.
|
| 257 |
+
This is too expensive.
|
| 258 |
+
That sounds good.
|
| 259 |
+
That sounds great.
|
| 260 |
+
That works for me.
|
| 261 |
+
See you at the meeting.
|
| 262 |
+
Call me if you need anything.
|
| 263 |
+
Call an ambulance.
|
| 264 |
+
Help me, please.
|
| 265 |
+
Help!
|
| 266 |
+
Watch out!
|
| 267 |
+
Be careful.
|
| 268 |
+
Drive safely.
|
| 269 |
+
Did you eat yet?
|
| 270 |
+
Did you sleep well?
|
| 271 |
+
Did you get my message?
|
| 272 |
+
Did you see that?
|
| 273 |
+
Have you eaten yet?
|
| 274 |
+
Have you seen my keys?
|
| 275 |
+
Have you been here before?
|
phrases/idioms.txt
ADDED
|
@@ -0,0 +1,321 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Once upon a time.
|
| 2 |
+
The quick brown fox jumps over the lazy dog.
|
| 3 |
+
Better late than never.
|
| 4 |
+
Actions speak louder than words.
|
| 5 |
+
It's raining cats and dogs.
|
| 6 |
+
Practice makes perfect.
|
| 7 |
+
When in Rome, do as the Romans do.
|
| 8 |
+
Better safe than sorry.
|
| 9 |
+
Every cloud has a silver lining.
|
| 10 |
+
A piece of cake.
|
| 11 |
+
A blessing in disguise.
|
| 12 |
+
A penny saved is a penny earned.
|
| 13 |
+
A penny for your thoughts.
|
| 14 |
+
A watched pot never boils.
|
| 15 |
+
A stitch in time saves nine.
|
| 16 |
+
A picture is worth a thousand words.
|
| 17 |
+
A friend in need is a friend indeed.
|
| 18 |
+
A chip off the old block.
|
| 19 |
+
A leopard can't change its spots.
|
| 20 |
+
A bird in the hand is worth two in the bush.
|
| 21 |
+
A rolling stone gathers no moss.
|
| 22 |
+
A dime a dozen.
|
| 23 |
+
A diamond in the rough.
|
| 24 |
+
A fish out of water.
|
| 25 |
+
A jack of all trades.
|
| 26 |
+
A drop in the bucket.
|
| 27 |
+
A needle in a haystack.
|
| 28 |
+
A wild goose chase.
|
| 29 |
+
A lost cause.
|
| 30 |
+
A heart of gold.
|
| 31 |
+
A chip on your shoulder.
|
| 32 |
+
A clean slate.
|
| 33 |
+
A hard pill to swallow.
|
| 34 |
+
A shot in the dark.
|
| 35 |
+
A rule of thumb.
|
| 36 |
+
A red herring.
|
| 37 |
+
A dog eat dog world.
|
| 38 |
+
A light at the end of the tunnel.
|
| 39 |
+
A sight for sore eyes.
|
| 40 |
+
Absence makes the heart grow fonder.
|
| 41 |
+
All that glitters is not gold.
|
| 42 |
+
All's fair in love and war.
|
| 43 |
+
All's well that ends well.
|
| 44 |
+
All good things must come to an end.
|
| 45 |
+
All roads lead to Rome.
|
| 46 |
+
All bark and no bite.
|
| 47 |
+
All in a day's work.
|
| 48 |
+
All thumbs.
|
| 49 |
+
An apple a day keeps the doctor away.
|
| 50 |
+
An eye for an eye.
|
| 51 |
+
An ounce of prevention is worth a pound of cure.
|
| 52 |
+
An eager beaver.
|
| 53 |
+
As easy as pie.
|
| 54 |
+
As American as apple pie.
|
| 55 |
+
As cool as a cucumber.
|
| 56 |
+
As fit as a fiddle.
|
| 57 |
+
As happy as a clam.
|
| 58 |
+
As light as a feather.
|
| 59 |
+
As old as the hills.
|
| 60 |
+
As plain as the nose on your face.
|
| 61 |
+
As quiet as a mouse.
|
| 62 |
+
As right as rain.
|
| 63 |
+
As sly as a fox.
|
| 64 |
+
As stubborn as a mule.
|
| 65 |
+
As white as a ghost.
|
| 66 |
+
As busy as a bee.
|
| 67 |
+
As dead as a doornail.
|
| 68 |
+
As clear as mud.
|
| 69 |
+
As good as gold.
|
| 70 |
+
As mad as a hatter.
|
| 71 |
+
As strong as an ox.
|
| 72 |
+
As cute as a button.
|
| 73 |
+
As blind as a bat.
|
| 74 |
+
Back to the drawing board.
|
| 75 |
+
Barking up the wrong tree.
|
| 76 |
+
Beauty is in the eye of the beholder.
|
| 77 |
+
Beggars can't be choosers.
|
| 78 |
+
Better the devil you know.
|
| 79 |
+
Birds of a feather flock together.
|
| 80 |
+
Bite off more than you can chew.
|
| 81 |
+
Bite the bullet.
|
| 82 |
+
Bite the hand that feeds you.
|
| 83 |
+
Blood is thicker than water.
|
| 84 |
+
Break a leg.
|
| 85 |
+
Burn the midnight oil.
|
| 86 |
+
Burn the candle at both ends.
|
| 87 |
+
By the skin of your teeth.
|
| 88 |
+
Beat around the bush.
|
| 89 |
+
Bend over backwards.
|
| 90 |
+
The best of both worlds.
|
| 91 |
+
Beyond the pale.
|
| 92 |
+
Bite the dust.
|
| 93 |
+
Blow off steam.
|
| 94 |
+
Break the ice.
|
| 95 |
+
Burn your bridges.
|
| 96 |
+
Bury the hatchet.
|
| 97 |
+
His bark is worse than his bite.
|
| 98 |
+
Break even.
|
| 99 |
+
Caught between a rock and a hard place.
|
| 100 |
+
Charity begins at home.
|
| 101 |
+
Cleanliness is next to godliness.
|
| 102 |
+
Curiosity killed the cat.
|
| 103 |
+
Cut corners.
|
| 104 |
+
Cut to the chase.
|
| 105 |
+
Call it a day.
|
| 106 |
+
Caught red-handed.
|
| 107 |
+
Come rain or shine.
|
| 108 |
+
Cost an arm and a leg.
|
| 109 |
+
Cross that bridge when you come to it.
|
| 110 |
+
Cry wolf.
|
| 111 |
+
Call a spade a spade.
|
| 112 |
+
Close but no cigar.
|
| 113 |
+
Cut your losses.
|
| 114 |
+
The calm before the storm.
|
| 115 |
+
The cold shoulder.
|
| 116 |
+
Don't judge a book by its cover.
|
| 117 |
+
Don't cry over spilled milk.
|
| 118 |
+
Don't count your chickens before they hatch.
|
| 119 |
+
Don't look a gift horse in the mouth.
|
| 120 |
+
Don't put all your eggs in one basket.
|
| 121 |
+
Don't rock the boat.
|
| 122 |
+
Don't make a mountain out of a molehill.
|
| 123 |
+
Down in the dumps.
|
| 124 |
+
Draw the line.
|
| 125 |
+
Easy come, easy go.
|
| 126 |
+
Every dog has its day.
|
| 127 |
+
Every man for himself.
|
| 128 |
+
Every rose has its thorn.
|
| 129 |
+
Easier said than done.
|
| 130 |
+
The elephant in the room.
|
| 131 |
+
Familiarity breeds contempt.
|
| 132 |
+
Fight fire with fire.
|
| 133 |
+
First come, first served.
|
| 134 |
+
Fortune favors the bold.
|
| 135 |
+
Face the music.
|
| 136 |
+
A fly on the wall.
|
| 137 |
+
Fool me once, shame on you, fool me twice, shame on me.
|
| 138 |
+
Give him an inch and he'll take a mile.
|
| 139 |
+
Go against the grain.
|
| 140 |
+
Good things come to those who wait.
|
| 141 |
+
Great minds think alike.
|
| 142 |
+
Get a taste of your own medicine.
|
| 143 |
+
Get the ball rolling.
|
| 144 |
+
Get up on the wrong side of the bed.
|
| 145 |
+
Give the benefit of the doubt.
|
| 146 |
+
Go back to square one.
|
| 147 |
+
Go the extra mile.
|
| 148 |
+
Go with the flow.
|
| 149 |
+
It goes without saying.
|
| 150 |
+
Grasping at straws.
|
| 151 |
+
Haste makes waste.
|
| 152 |
+
Health is wealth.
|
| 153 |
+
Herding cats.
|
| 154 |
+
History repeats itself.
|
| 155 |
+
Hit the nail on the head.
|
| 156 |
+
Honesty is the best policy.
|
| 157 |
+
Hope for the best, prepare for the worst.
|
| 158 |
+
Hang in there.
|
| 159 |
+
Head in the clouds.
|
| 160 |
+
Head over heels.
|
| 161 |
+
Hit the hay.
|
| 162 |
+
Hit the sack.
|
| 163 |
+
Hold your horses.
|
| 164 |
+
If it ain't broke, don't fix it.
|
| 165 |
+
If the shoe fits, wear it.
|
| 166 |
+
Ignorance is bliss.
|
| 167 |
+
It never rains but it pours.
|
| 168 |
+
It takes two to tango.
|
| 169 |
+
It's a small world.
|
| 170 |
+
It's better to give than to receive.
|
| 171 |
+
It's never too late.
|
| 172 |
+
It's the thought that counts.
|
| 173 |
+
In a nutshell.
|
| 174 |
+
In the heat of the moment.
|
| 175 |
+
In the nick of time.
|
| 176 |
+
It takes one to know one.
|
| 177 |
+
Jump on the bandwagon.
|
| 178 |
+
Jump the gun.
|
| 179 |
+
Keep your chin up.
|
| 180 |
+
Keep your eye on the ball.
|
| 181 |
+
Keep your friends close and your enemies closer.
|
| 182 |
+
Keep your fingers crossed.
|
| 183 |
+
Kill two birds with one stone.
|
| 184 |
+
Kick the bucket.
|
| 185 |
+
Knowledge is power.
|
| 186 |
+
Laughter is the best medicine.
|
| 187 |
+
Let bygones be bygones.
|
| 188 |
+
Let sleeping dogs lie.
|
| 189 |
+
Let the cat out of the bag.
|
| 190 |
+
Life is short.
|
| 191 |
+
Live and learn.
|
| 192 |
+
Look before you leap.
|
| 193 |
+
Love is blind.
|
| 194 |
+
Learn the ropes.
|
| 195 |
+
Let the chips fall where they may.
|
| 196 |
+
Live and let live.
|
| 197 |
+
Make hay while the sun shines.
|
| 198 |
+
Many hands make light work.
|
| 199 |
+
Measure twice, cut once.
|
| 200 |
+
Misery loves company.
|
| 201 |
+
Money can't buy happiness.
|
| 202 |
+
Money doesn't grow on trees.
|
| 203 |
+
Money is the root of all evil.
|
| 204 |
+
Monkey see, monkey do.
|
| 205 |
+
Make ends meet.
|
| 206 |
+
There's a method to the madness.
|
| 207 |
+
Miss the boat.
|
| 208 |
+
Make a long story short.
|
| 209 |
+
Necessity is the mother of invention.
|
| 210 |
+
Never put off until tomorrow what you can do today.
|
| 211 |
+
Never say never.
|
| 212 |
+
No news is good news.
|
| 213 |
+
No pain, no gain.
|
| 214 |
+
No man is an island.
|
| 215 |
+
No time like the present.
|
| 216 |
+
Nothing ventured, nothing gained.
|
| 217 |
+
There's no rest for the wicked.
|
| 218 |
+
Once bitten, twice shy.
|
| 219 |
+
One good turn deserves another.
|
| 220 |
+
One man's trash is another man's treasure.
|
| 221 |
+
Opportunity knocks but once.
|
| 222 |
+
Out of sight, out of mind.
|
| 223 |
+
Out of the frying pan and into the fire.
|
| 224 |
+
Out of the blue.
|
| 225 |
+
Off the beaten path.
|
| 226 |
+
Off the hook.
|
| 227 |
+
On the ball.
|
| 228 |
+
On the same page.
|
| 229 |
+
On thin ice.
|
| 230 |
+
Once in a blue moon.
|
| 231 |
+
Over the moon.
|
| 232 |
+
Patience is a virtue.
|
| 233 |
+
Pride comes before a fall.
|
| 234 |
+
Put the cart before the horse.
|
| 235 |
+
Par for the course.
|
| 236 |
+
Pass the buck.
|
| 237 |
+
Play it by ear.
|
| 238 |
+
Play devil's advocate.
|
| 239 |
+
Pull yourself together.
|
| 240 |
+
Pull your weight.
|
| 241 |
+
Put your best foot forward.
|
| 242 |
+
Peace of mind.
|
| 243 |
+
Rome wasn't built in a day.
|
| 244 |
+
Rain on your parade.
|
| 245 |
+
Read between the lines.
|
| 246 |
+
Rings a bell.
|
| 247 |
+
Silence is golden.
|
| 248 |
+
Slow and steady wins the race.
|
| 249 |
+
Spare the rod and spoil the child.
|
| 250 |
+
Speak of the devil.
|
| 251 |
+
Still waters run deep.
|
| 252 |
+
Strike while the iron is hot.
|
| 253 |
+
Sit on the fence.
|
| 254 |
+
Skeletons in the closet.
|
| 255 |
+
Spill the beans.
|
| 256 |
+
Steal someone's thunder.
|
| 257 |
+
Straight from the horse's mouth.
|
| 258 |
+
The apple doesn't fall far from the tree.
|
| 259 |
+
The ball is in your court.
|
| 260 |
+
The best things in life are free.
|
| 261 |
+
The customer is always right.
|
| 262 |
+
The early bird catches the worm.
|
| 263 |
+
The end justifies the means.
|
| 264 |
+
The exception proves the rule.
|
| 265 |
+
The grass is always greener on the other side.
|
| 266 |
+
The pen is mightier than the sword.
|
| 267 |
+
The pot calling the kettle black.
|
| 268 |
+
The proof is in the pudding.
|
| 269 |
+
The road to hell is paved with good intentions.
|
| 270 |
+
The squeaky wheel gets the grease.
|
| 271 |
+
The truth hurts.
|
| 272 |
+
The whole nine yards.
|
| 273 |
+
There's more than one way to skin a cat.
|
| 274 |
+
There's no place like home.
|
| 275 |
+
There's no smoke without fire.
|
| 276 |
+
There's no such thing as a free lunch.
|
| 277 |
+
Time flies when you're having fun.
|
| 278 |
+
Time heals all wounds.
|
| 279 |
+
Time is money.
|
| 280 |
+
Time will tell.
|
| 281 |
+
To each his own.
|
| 282 |
+
Too many cooks spoil the broth.
|
| 283 |
+
Two heads are better than one.
|
| 284 |
+
Two wrongs don't make a right.
|
| 285 |
+
Take it with a grain of salt.
|
| 286 |
+
Take the bull by the horns.
|
| 287 |
+
The whole kit and caboodle.
|
| 288 |
+
Through thick and thin.
|
| 289 |
+
Throw in the towel.
|
| 290 |
+
Tie the knot.
|
| 291 |
+
The tip of the iceberg.
|
| 292 |
+
Turn a blind eye.
|
| 293 |
+
Turn over a new leaf.
|
| 294 |
+
Tongue in cheek.
|
| 295 |
+
The last straw.
|
| 296 |
+
United we stand, divided we fall.
|
| 297 |
+
Under the weather.
|
| 298 |
+
Up in the air.
|
| 299 |
+
Variety is the spice of life.
|
| 300 |
+
Walk a mile in someone's shoes.
|
| 301 |
+
Waste not, want not.
|
| 302 |
+
What goes around comes around.
|
| 303 |
+
What doesn't kill you makes you stronger.
|
| 304 |
+
When life gives you lemons, make lemonade.
|
| 305 |
+
When one door closes, another opens.
|
| 306 |
+
When the going gets tough, the tough get going.
|
| 307 |
+
Where there's a will, there's a way.
|
| 308 |
+
Where there's smoke, there's fire.
|
| 309 |
+
Water under the bridge.
|
| 310 |
+
Wear your heart on your sleeve.
|
| 311 |
+
When pigs fly.
|
| 312 |
+
Word of mouth.
|
| 313 |
+
You can't have your cake and eat it too.
|
| 314 |
+
You can't make an omelet without breaking eggs.
|
| 315 |
+
You can't please everyone.
|
| 316 |
+
You can't teach an old dog new tricks.
|
| 317 |
+
You reap what you sow.
|
| 318 |
+
You scratch my back, I'll scratch yours.
|
| 319 |
+
You win some, you lose some.
|
| 320 |
+
Add insult to injury.
|
| 321 |
+
Don't kill the messenger.
|
phrases/opinions_work.txt
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
I think so.
|
| 2 |
+
I think you're right.
|
| 3 |
+
I think we should go.
|
| 4 |
+
I think it's a good idea.
|
| 5 |
+
I think it's a great idea.
|
| 6 |
+
I think that's a good idea.
|
| 7 |
+
I don't think so.
|
| 8 |
+
I don't think that's a good idea.
|
| 9 |
+
I agree with you.
|
| 10 |
+
I completely agree.
|
| 11 |
+
I totally agree.
|
| 12 |
+
I couldn't agree more.
|
| 13 |
+
I disagree.
|
| 14 |
+
I'm not sure.
|
| 15 |
+
I'm not sure about that.
|
| 16 |
+
I'm not so sure.
|
| 17 |
+
I see what you mean.
|
| 18 |
+
I see your point.
|
| 19 |
+
I know what you mean.
|
| 20 |
+
I know how you feel.
|
| 21 |
+
I understand how you feel.
|
| 22 |
+
I believe you.
|
| 23 |
+
I believe in you.
|
| 24 |
+
I trust you.
|
| 25 |
+
I love you.
|
| 26 |
+
I love you so much.
|
| 27 |
+
I love you too.
|
| 28 |
+
I love it.
|
| 29 |
+
I like it.
|
| 30 |
+
I really like it.
|
| 31 |
+
I don't like it.
|
| 32 |
+
I miss you.
|
| 33 |
+
I miss you so much.
|
| 34 |
+
I miss you too.
|
| 35 |
+
I need you.
|
| 36 |
+
I'm proud of you.
|
| 37 |
+
I'm so proud of you.
|
| 38 |
+
I'm happy for you.
|
| 39 |
+
I'm so happy for you.
|
| 40 |
+
I'm so happy.
|
| 41 |
+
I'm happy to help.
|
| 42 |
+
I'm glad to hear that.
|
| 43 |
+
I'm glad you're here.
|
| 44 |
+
I'm glad you liked it.
|
| 45 |
+
I'm excited.
|
| 46 |
+
I'm so excited.
|
| 47 |
+
I'm worried about you.
|
| 48 |
+
I'm here for you.
|
| 49 |
+
I'm always here for you.
|
| 50 |
+
I'm on your side.
|
| 51 |
+
I'm sorry you feel that way.
|
| 52 |
+
I feel the same way.
|
| 53 |
+
I feel great.
|
| 54 |
+
I feel sick.
|
| 55 |
+
I can't believe it.
|
| 56 |
+
I can't wait.
|
| 57 |
+
I can't wait to see you.
|
| 58 |
+
I can't do this anymore.
|
| 59 |
+
I can do it.
|
| 60 |
+
You can do it.
|
| 61 |
+
You can do this.
|
| 62 |
+
You've got this.
|
| 63 |
+
You did a great job.
|
| 64 |
+
You did it.
|
| 65 |
+
You look great.
|
| 66 |
+
You look beautiful.
|
| 67 |
+
You look tired.
|
| 68 |
+
You're right.
|
| 69 |
+
You're so right.
|
| 70 |
+
You're the best.
|
| 71 |
+
You're amazing.
|
| 72 |
+
You're so kind.
|
| 73 |
+
You're very kind.
|
| 74 |
+
You're welcome to join us.
|
| 75 |
+
You deserve it.
|
| 76 |
+
You should try it.
|
| 77 |
+
You know what I mean?
|
| 78 |
+
You never know.
|
| 79 |
+
You're kidding.
|
| 80 |
+
You're kidding me.
|
| 81 |
+
Don't worry.
|
| 82 |
+
Don't worry about it.
|
| 83 |
+
Don't worry, be happy.
|
| 84 |
+
Don't give up.
|
| 85 |
+
Don't be afraid.
|
| 86 |
+
Don't be sad.
|
| 87 |
+
Don't be late.
|
| 88 |
+
Don't be silly.
|
| 89 |
+
Don't do that.
|
| 90 |
+
Don't touch that.
|
| 91 |
+
Don't tell anyone.
|
| 92 |
+
Never give up.
|
| 93 |
+
Keep up the good work.
|
| 94 |
+
Keep going.
|
| 95 |
+
Keep it up.
|
| 96 |
+
Hang in there.
|
| 97 |
+
Take your time.
|
| 98 |
+
Take it easy.
|
| 99 |
+
Calm down.
|
| 100 |
+
Cheer up.
|
| 101 |
+
It's okay.
|
| 102 |
+
It's not your fault.
|
| 103 |
+
It's not a big deal.
|
| 104 |
+
It's going to be okay.
|
| 105 |
+
It's going to be fine.
|
| 106 |
+
Everything is going to be okay.
|
| 107 |
+
Everything will be fine.
|
| 108 |
+
It doesn't matter.
|
| 109 |
+
It's up to you.
|
| 110 |
+
It's my fault.
|
| 111 |
+
It's a good idea.
|
| 112 |
+
It's a deal.
|
| 113 |
+
It's too late.
|
| 114 |
+
It's time to go.
|
| 115 |
+
It's time for bed.
|
| 116 |
+
It's worth it.
|
| 117 |
+
That's right.
|
| 118 |
+
That's true.
|
| 119 |
+
That's not true.
|
| 120 |
+
That's a good idea.
|
| 121 |
+
That's a great idea.
|
| 122 |
+
That's a good question.
|
| 123 |
+
That's a great question.
|
| 124 |
+
That's fine.
|
| 125 |
+
That's fine with me.
|
| 126 |
+
That's okay.
|
| 127 |
+
That's not fair.
|
| 128 |
+
That's enough.
|
| 129 |
+
That's it.
|
| 130 |
+
That makes sense.
|
| 131 |
+
That doesn't make sense.
|
| 132 |
+
That's what I thought.
|
| 133 |
+
That's why I love you.
|
| 134 |
+
Me too.
|
| 135 |
+
Me neither.
|
| 136 |
+
So do I.
|
| 137 |
+
Of course.
|
| 138 |
+
Of course not.
|
| 139 |
+
Absolutely.
|
| 140 |
+
Definitely.
|
| 141 |
+
Exactly.
|
| 142 |
+
Maybe.
|
| 143 |
+
Maybe later.
|
| 144 |
+
Maybe next time.
|
| 145 |
+
Probably.
|
| 146 |
+
Sure.
|
| 147 |
+
Sure, no problem.
|
| 148 |
+
Sure thing.
|
| 149 |
+
Okay.
|
| 150 |
+
Okay, sounds good.
|
| 151 |
+
Sounds good.
|
| 152 |
+
Sounds good to me.
|
| 153 |
+
Sounds like a plan.
|
| 154 |
+
Good idea.
|
| 155 |
+
Good point.
|
| 156 |
+
Good question.
|
| 157 |
+
Fair enough.
|
| 158 |
+
Not really.
|
| 159 |
+
Not at all.
|
| 160 |
+
Not yet.
|
| 161 |
+
Not now.
|
| 162 |
+
I hope this email finds you well.
|
| 163 |
+
I hope you are doing well.
|
| 164 |
+
I hope you had a great weekend.
|
| 165 |
+
I am writing to follow up on our conversation.
|
| 166 |
+
I just wanted to follow up on my last email.
|
| 167 |
+
Just a quick reminder about the meeting.
|
| 168 |
+
Please find attached the report.
|
| 169 |
+
Please find the attached file.
|
| 170 |
+
Please see the attached document.
|
| 171 |
+
Please let me know if you have any questions.
|
| 172 |
+
Please let me know if you need anything else.
|
| 173 |
+
Please let me know your availability.
|
| 174 |
+
Please let me know what you think.
|
| 175 |
+
Please let me know as soon as possible.
|
| 176 |
+
Please feel free to contact me.
|
| 177 |
+
Please feel free to reach out.
|
| 178 |
+
Please don't hesitate to contact me.
|
| 179 |
+
Please review the document.
|
| 180 |
+
Please confirm your attendance.
|
| 181 |
+
Let me know if you need anything.
|
| 182 |
+
Let me know if you have any questions.
|
| 183 |
+
Let me know what you think.
|
| 184 |
+
Let me know if that works for you.
|
| 185 |
+
Let me know when you're free.
|
| 186 |
+
Let me get back to you on that.
|
| 187 |
+
Feel free to reach out.
|
| 188 |
+
Feel free to ask.
|
| 189 |
+
Looking forward to hearing from you.
|
| 190 |
+
Looking forward to seeing you.
|
| 191 |
+
Looking forward to working with you.
|
| 192 |
+
I look forward to hearing from you.
|
| 193 |
+
I look forward to meeting you.
|
| 194 |
+
I look forward to working with you.
|
| 195 |
+
Thank you for your email.
|
| 196 |
+
Thank you for your quick response.
|
| 197 |
+
Thank you for reaching out.
|
| 198 |
+
Thank you for the update.
|
| 199 |
+
Thanks for the update.
|
| 200 |
+
Thanks for getting back to me.
|
| 201 |
+
Thanks for reaching out.
|
| 202 |
+
Thanks in advance.
|
| 203 |
+
Thanks for your hard work.
|
| 204 |
+
Best regards.
|
| 205 |
+
Kind regards.
|
| 206 |
+
Warm regards.
|
| 207 |
+
Sincerely.
|
| 208 |
+
Have a great day ahead.
|
| 209 |
+
As soon as possible.
|
| 210 |
+
At your earliest convenience.
|
| 211 |
+
For your information.
|
| 212 |
+
Sorry for the inconvenience.
|
| 213 |
+
Sorry for the confusion.
|
| 214 |
+
Sorry for the delay.
|
| 215 |
+
I will get back to you as soon as possible.
|
| 216 |
+
I will send you the details.
|
| 217 |
+
I will look into it.
|
| 218 |
+
I will keep you posted.
|
| 219 |
+
I'll keep you updated.
|
| 220 |
+
I'll let you know.
|
| 221 |
+
I'll send it over.
|
| 222 |
+
I'll take care of it.
|
| 223 |
+
I'm working on it.
|
| 224 |
+
I'm in a meeting.
|
| 225 |
+
I'm in a meeting right now.
|
| 226 |
+
I'm out of the office.
|
| 227 |
+
Can we schedule a meeting?
|
| 228 |
+
Can we reschedule the meeting?
|
| 229 |
+
Can we talk tomorrow?
|
| 230 |
+
Can we move the meeting to tomorrow?
|
| 231 |
+
Can you send me an update?
|
| 232 |
+
Can you review this?
|
| 233 |
+
Does that work for you?
|
| 234 |
+
Does that make sense?
|
| 235 |
+
Is that okay with you?
|
| 236 |
+
Are you available tomorrow?
|
| 237 |
+
Are you available for a quick call?
|
| 238 |
+
Let's schedule a call.
|
| 239 |
+
Let's touch base next week.
|
| 240 |
+
Let's discuss this in the meeting.
|
| 241 |
+
Let's circle back on this.
|
| 242 |
+
Let's move forward.
|
| 243 |
+
Let's get to work.
|
| 244 |
+
The meeting is canceled.
|
| 245 |
+
The deadline is tomorrow.
|
| 246 |
+
We need to talk.
|
| 247 |
+
We need to finish this today.
|
| 248 |
+
We need more time.
|
| 249 |
+
We can do it.
|
| 250 |
+
We did it.
|
| 251 |
+
We are happy to help.
|
| 252 |
+
We apologize for the inconvenience.
|
| 253 |
+
We appreciate your patience.
|
| 254 |
+
We appreciate your business.
|
| 255 |
+
We look forward to hearing from you.
|
| 256 |
+
Your order has been shipped.
|
| 257 |
+
Your call is important to us.
|
| 258 |
+
How can I help you today?
|
| 259 |
+
How may I help you?
|
| 260 |
+
Is there anything else I can help you with?
|
| 261 |
+
Thank you for contacting us.
|
| 262 |
+
Thank you for your order.
|
| 263 |
+
Thank you for shopping with us.
|
| 264 |
+
Have a nice day, and thank you.
|
| 265 |
+
Great work, everyone.
|
| 266 |
+
Great job, team.
|
| 267 |
+
Good work.
|
| 268 |
+
Well said.
|
| 269 |
+
Nice work.
|
| 270 |
+
Nice job.
|
| 271 |
+
I appreciate it.
|
| 272 |
+
I really appreciate it.
|
| 273 |
+
I really appreciate your help.
|
| 274 |
+
I appreciate your help.
|
| 275 |
+
I owe you one.
|
| 276 |
+
I'm grateful for your help.
|
| 277 |
+
It means a lot to me.
|
| 278 |
+
It was a pleasure working with you.
|
phrases/social.txt
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Hello, how are you?
|
| 2 |
+
Hello, how are you doing?
|
| 3 |
+
Hi, how are you?
|
| 4 |
+
Hi, how's it going?
|
| 5 |
+
Hey, what's up?
|
| 6 |
+
Hey, how have you been?
|
| 7 |
+
How are you?
|
| 8 |
+
How are you doing?
|
| 9 |
+
How are you doing today?
|
| 10 |
+
How are you feeling?
|
| 11 |
+
How are you feeling today?
|
| 12 |
+
How have you been?
|
| 13 |
+
How's it going?
|
| 14 |
+
How's your day going?
|
| 15 |
+
How was your day?
|
| 16 |
+
How was your weekend?
|
| 17 |
+
How was your trip?
|
| 18 |
+
How is your family?
|
| 19 |
+
I'm fine, thank you.
|
| 20 |
+
I'm fine, thanks. And you?
|
| 21 |
+
I'm doing well, thank you.
|
| 22 |
+
I'm doing well, thanks for asking.
|
| 23 |
+
I'm good, thanks.
|
| 24 |
+
I'm good, how about you?
|
| 25 |
+
Not bad, how about you?
|
| 26 |
+
Not too bad.
|
| 27 |
+
Pretty good, thanks.
|
| 28 |
+
Good morning.
|
| 29 |
+
Good morning, everyone.
|
| 30 |
+
Good morning, how are you?
|
| 31 |
+
Good afternoon.
|
| 32 |
+
Good evening.
|
| 33 |
+
Good night.
|
| 34 |
+
Good night, sleep well.
|
| 35 |
+
Good night and sweet dreams.
|
| 36 |
+
Sweet dreams.
|
| 37 |
+
Sleep well.
|
| 38 |
+
Sleep tight.
|
| 39 |
+
Have a good night.
|
| 40 |
+
Have a good day.
|
| 41 |
+
Have a nice day.
|
| 42 |
+
Have a great day.
|
| 43 |
+
Have a wonderful day.
|
| 44 |
+
Have a good weekend.
|
| 45 |
+
Have a great weekend.
|
| 46 |
+
Have a nice weekend.
|
| 47 |
+
Have a good time.
|
| 48 |
+
Have a great time.
|
| 49 |
+
Have a safe trip.
|
| 50 |
+
Have a safe flight.
|
| 51 |
+
Have fun.
|
| 52 |
+
Have a good one.
|
| 53 |
+
Nice to meet you.
|
| 54 |
+
Nice to meet you too.
|
| 55 |
+
It's nice to meet you.
|
| 56 |
+
It was nice to meet you.
|
| 57 |
+
It was nice meeting you.
|
| 58 |
+
It was nice talking to you.
|
| 59 |
+
It was great to see you.
|
| 60 |
+
It's good to see you.
|
| 61 |
+
It's good to see you again.
|
| 62 |
+
It's been a long time.
|
| 63 |
+
Long time no see.
|
| 64 |
+
Pleased to meet you.
|
| 65 |
+
What is your name?
|
| 66 |
+
What's your name?
|
| 67 |
+
Where are you from?
|
| 68 |
+
What do you do?
|
| 69 |
+
What do you do for a living?
|
| 70 |
+
Thank you.
|
| 71 |
+
Thank you very much.
|
| 72 |
+
Thank you so much.
|
| 73 |
+
Thank you for your help.
|
| 74 |
+
Thank you for your time.
|
| 75 |
+
Thank you for everything.
|
| 76 |
+
Thank you for coming.
|
| 77 |
+
Thank you for listening.
|
| 78 |
+
Thank you for your patience.
|
| 79 |
+
Thank you for your understanding.
|
| 80 |
+
Thank you for the gift.
|
| 81 |
+
Thank you for the invitation.
|
| 82 |
+
Thank you for letting me know.
|
| 83 |
+
Thank you for asking.
|
| 84 |
+
Thanks.
|
| 85 |
+
Thanks a lot.
|
| 86 |
+
Thanks so much.
|
| 87 |
+
Thanks for your help.
|
| 88 |
+
Thanks for everything.
|
| 89 |
+
Thanks for coming.
|
| 90 |
+
Thanks for letting me know.
|
| 91 |
+
Thanks again.
|
| 92 |
+
Thanks anyway.
|
| 93 |
+
You're welcome.
|
| 94 |
+
You are welcome.
|
| 95 |
+
No problem.
|
| 96 |
+
No worries.
|
| 97 |
+
My pleasure.
|
| 98 |
+
It was my pleasure.
|
| 99 |
+
Don't mention it.
|
| 100 |
+
Anytime.
|
| 101 |
+
I'm sorry.
|
| 102 |
+
I'm so sorry.
|
| 103 |
+
I'm very sorry.
|
| 104 |
+
I'm sorry for being late.
|
| 105 |
+
I'm sorry to hear that.
|
| 106 |
+
I'm sorry for your loss.
|
| 107 |
+
I'm sorry, I didn't mean it.
|
| 108 |
+
I apologize for the inconvenience.
|
| 109 |
+
I apologize for the delay.
|
| 110 |
+
Sorry about that.
|
| 111 |
+
Sorry I'm late.
|
| 112 |
+
Sorry to bother you.
|
| 113 |
+
Sorry for the late reply.
|
| 114 |
+
Excuse me.
|
| 115 |
+
Excuse me, can you help me?
|
| 116 |
+
Excuse me, where is the bathroom?
|
| 117 |
+
Pardon me.
|
| 118 |
+
Please.
|
| 119 |
+
Yes, please.
|
| 120 |
+
No, thank you.
|
| 121 |
+
No, thanks.
|
| 122 |
+
See you later.
|
| 123 |
+
See you soon.
|
| 124 |
+
See you tomorrow.
|
| 125 |
+
See you next week.
|
| 126 |
+
See you around.
|
| 127 |
+
See you then.
|
| 128 |
+
Talk to you later.
|
| 129 |
+
Talk to you soon.
|
| 130 |
+
Catch you later.
|
| 131 |
+
Take care.
|
| 132 |
+
Take care of yourself.
|
| 133 |
+
Goodbye.
|
| 134 |
+
Bye for now.
|
| 135 |
+
Bye, see you later.
|
| 136 |
+
Welcome.
|
| 137 |
+
Welcome back.
|
| 138 |
+
Welcome home.
|
| 139 |
+
Welcome to the team.
|
| 140 |
+
Come on in.
|
| 141 |
+
Please come in.
|
| 142 |
+
Please have a seat.
|
| 143 |
+
Make yourself at home.
|
| 144 |
+
Happy birthday.
|
| 145 |
+
Happy birthday to you.
|
| 146 |
+
Happy birthday, have a great day.
|
| 147 |
+
Wishing you a happy birthday.
|
| 148 |
+
Many happy returns.
|
| 149 |
+
Happy new year.
|
| 150 |
+
Happy holidays.
|
| 151 |
+
Merry Christmas.
|
| 152 |
+
Merry Christmas and a happy new year.
|
| 153 |
+
Happy anniversary.
|
| 154 |
+
Happy Thanksgiving.
|
| 155 |
+
Happy Easter.
|
| 156 |
+
Happy Mother's Day.
|
| 157 |
+
Happy Father's Day.
|
| 158 |
+
Happy Valentine's Day.
|
| 159 |
+
Congratulations.
|
| 160 |
+
Congratulations on your new job.
|
| 161 |
+
Congratulations on your graduation.
|
| 162 |
+
Congratulations on your wedding.
|
| 163 |
+
Congratulations on the new baby.
|
| 164 |
+
Congratulations, you deserve it.
|
| 165 |
+
Well done.
|
| 166 |
+
Good job.
|
| 167 |
+
Great job.
|
| 168 |
+
Good luck.
|
| 169 |
+
Good luck with your exam.
|
| 170 |
+
Good luck with everything.
|
| 171 |
+
Best of luck.
|
| 172 |
+
Best wishes.
|
| 173 |
+
Get well soon.
|
| 174 |
+
I hope you feel better soon.
|
| 175 |
+
I hope you have a great day.
|
| 176 |
+
I hope you're doing well.
|
| 177 |
+
I hope everything is okay.
|
| 178 |
+
I hope to see you soon.
|
| 179 |
+
I hope so.
|
| 180 |
+
Cheers.
|
| 181 |
+
Bless you.
|
| 182 |
+
God bless you.
|
| 183 |
+
Same to you.
|
| 184 |
+
You too.
|
| 185 |
+
And you?
|
| 186 |
+
What about you?
|
| 187 |
+
How about you?
|
| 188 |
+
What's new?
|
| 189 |
+
What's going on?
|
| 190 |
+
What are you doing?
|
| 191 |
+
What are you up to?
|
| 192 |
+
What are you doing this weekend?
|
| 193 |
+
Not much, just relaxing.
|
| 194 |
+
Nothing much.
|
| 195 |
+
Are you okay?
|
| 196 |
+
Are you sure?
|
| 197 |
+
Are you ready?
|
| 198 |
+
Are you coming?
|
| 199 |
+
Are you busy?
|
| 200 |
+
Are you free tonight?
|
| 201 |
+
Do you want to hang out?
|
| 202 |
+
Do you want to grab lunch?
|
| 203 |
+
Do you want to come with me?
|
| 204 |
+
Let's get together soon.
|
| 205 |
+
Let's keep in touch.
|
| 206 |
+
Let's grab a coffee sometime.
|
| 207 |
+
Keep in touch.
|
| 208 |
+
Say hi to your family for me.
|
| 209 |
+
Give my love to your family.
|
| 210 |
+
Tell them I said hello.
|
| 211 |
+
I'll text you later.
|
| 212 |
+
I'll call you later.
|
| 213 |
+
I'll call you tomorrow.
|
| 214 |
+
Call me when you get home.
|
| 215 |
+
Text me when you get home.
|
| 216 |
+
Let me know when you get home.
|
| 217 |
+
Let me know when you're here.
|
| 218 |
+
I'm here.
|
| 219 |
+
I'm on my way.
|
| 220 |
+
I'm almost there.
|
| 221 |
+
I'll be there soon.
|
| 222 |
+
I'll be right back.
|
| 223 |
+
Be right back.
|
| 224 |
+
I'm home.
|
| 225 |
+
Just checking in.
|
| 226 |
+
Just wanted to say hi.
|
| 227 |
+
Miss you.
|
| 228 |
+
Love you.
|
| 229 |
+
Love you too.
|
| 230 |
+
Lol, that's so funny.
|
| 231 |
+
That's so funny.
|
| 232 |
+
That's hilarious.
|
| 233 |
+
Oh my god.
|
| 234 |
+
Oh my gosh.
|
| 235 |
+
No way.
|
| 236 |
+
Are you serious?
|
| 237 |
+
Really?
|
| 238 |
+
Wow, that's amazing.
|
| 239 |
+
That's awesome.
|
| 240 |
+
That's great.
|
| 241 |
+
That's great news.
|
| 242 |
+
That's too bad.
|
| 243 |
+
That's a shame.
|
| 244 |
+
What a surprise.
|
| 245 |
+
What a nice surprise.
|
| 246 |
+
What a beautiful day.
|
| 247 |
+
It's a beautiful day.
|
| 248 |
+
It's so nice out today.
|
| 249 |
+
Enjoy your meal.
|
| 250 |
+
Enjoy your day.
|
| 251 |
+
Enjoy your weekend.
|
| 252 |
+
Enjoy your vacation.
|
| 253 |
+
Enjoy the show.
|
| 254 |
+
Bon appetit.
|
| 255 |
+
Cheers to that.
|
| 256 |
+
After you.
|
| 257 |
+
Ladies and gentlemen.
|
| 258 |
+
Can I ask you something?
|
| 259 |
+
Can I help you?
|
| 260 |
+
May I help you?
|
| 261 |
+
May I come in?
|
| 262 |
+
How can I help you?
|
| 263 |
+
Is everything okay?
|
| 264 |
+
Is this seat taken?
|
| 265 |
+
Nice weather today, isn't it?
|
| 266 |
+
It's cold today, isn't it?
|
requirements.txt
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
torch
|
| 2 |
+
transformers>=4.45
|
| 3 |
+
tokenizers
|
| 4 |
+
safetensors
|
test_model.py
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Load the saved files exactly as a Hugging Face user would and check them.
|
| 2 |
+
|
| 3 |
+
Run `python build_weights.py` first.
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
import json
|
| 7 |
+
import random
|
| 8 |
+
import shutil
|
| 9 |
+
import subprocess
|
| 10 |
+
import unittest
|
| 11 |
+
from pathlib import Path
|
| 12 |
+
|
| 13 |
+
import torch
|
| 14 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
|
| 15 |
+
|
| 16 |
+
import build_weights
|
| 17 |
+
|
| 18 |
+
MODEL_DIR = Path(__file__).parent
|
| 19 |
+
|
| 20 |
+
# prompt -> greedy completion (new text only)
|
| 21 |
+
CASES = {
|
| 22 |
+
"Once upon a": "time.",
|
| 23 |
+
"The quick brown": "fox jumps over the lazy dog.",
|
| 24 |
+
"Thank you for your": "help.",
|
| 25 |
+
"I hope this email": "finds you well.",
|
| 26 |
+
"Can I have the": "check, please?",
|
| 27 |
+
"Looking forward to": "hearing from you.",
|
| 28 |
+
"Actions speak": "louder than words.",
|
| 29 |
+
"Where is the": "bathroom?",
|
| 30 |
+
"Happy birthday": ".",
|
| 31 |
+
"I'm so proud": "of you.",
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
class TestModel(unittest.TestCase):
|
| 36 |
+
@classmethod
|
| 37 |
+
def setUpClass(cls):
|
| 38 |
+
cls.tok = AutoTokenizer.from_pretrained(MODEL_DIR)
|
| 39 |
+
cls.model = AutoModelForCausalLM.from_pretrained(MODEL_DIR).eval()
|
| 40 |
+
_, cls.vocab, cls.ngram, _, _, cls.info = build_weights.compile_model()
|
| 41 |
+
|
| 42 |
+
def complete(self, prompt: str) -> str:
|
| 43 |
+
ids = self.tok(prompt, return_tensors="pt")
|
| 44 |
+
out = self.model.generate(**ids, max_new_tokens=16)
|
| 45 |
+
return self.tok.decode(out[0, ids["input_ids"].shape[1] :], skip_special_tokens=True).strip()
|
| 46 |
+
|
| 47 |
+
def test_parameter_count(self):
|
| 48 |
+
n = sum(p.numel() for p in self.model.parameters())
|
| 49 |
+
self.assertEqual(n, self.info["params"])
|
| 50 |
+
self.assertLessEqual(n, 1_000_000_000)
|
| 51 |
+
|
| 52 |
+
def test_greedy_completions(self):
|
| 53 |
+
for prompt, expected in CASES.items():
|
| 54 |
+
with self.subTest(prompt=prompt):
|
| 55 |
+
self.assertEqual(self.complete(prompt), expected)
|
| 56 |
+
|
| 57 |
+
def test_matches_ngram_reference(self):
|
| 58 |
+
"""The transformer's next-token distribution equals the compiled n-gram's."""
|
| 59 |
+
index = {p: i for i, p in enumerate(self.vocab)}
|
| 60 |
+
rng = random.Random(0)
|
| 61 |
+
phrases = build_weights.load_phrases()
|
| 62 |
+
cases = []
|
| 63 |
+
for toks in rng.sample(phrases, 200):
|
| 64 |
+
ids = [0] + [index[p] for p in toks]
|
| 65 |
+
cases.append(ids[: rng.randint(1, len(ids))])
|
| 66 |
+
for _ in range(50): # unseen word salad, up to 80 tokens
|
| 67 |
+
cases.append([0] + [rng.randrange(2, len(self.vocab)) for _ in range(rng.randint(1, 80))])
|
| 68 |
+
with torch.no_grad():
|
| 69 |
+
for ids in cases:
|
| 70 |
+
got = self.model(torch.tensor([ids])).logits[0, -1].double().log_softmax(-1)
|
| 71 |
+
ref = self.ngram.reference_logits(ids).log_softmax(-1)
|
| 72 |
+
self.assertLess((got - ref).abs().max().item(), 5e-3)
|
| 73 |
+
|
| 74 |
+
def test_unknown_words_back_off(self):
|
| 75 |
+
# "zebra" is out of vocabulary; the model backs off to the shorter context.
|
| 76 |
+
self.assertEqual(self.complete("Zebra, thank you for your"), "help.")
|
| 77 |
+
|
| 78 |
+
def test_pipeline(self):
|
| 79 |
+
gen = pipeline("text-generation", model=str(MODEL_DIR))
|
| 80 |
+
self.assertEqual(gen("Once upon a")[0]["generated_text"], "Once upon a time.")
|
| 81 |
+
|
| 82 |
+
@unittest.skipUnless(shutil.which("bun"), "bun not installed")
|
| 83 |
+
def test_typescript_matches(self):
|
| 84 |
+
prompts = ["once upon a", "how are", "zebra", "i hope this email"]
|
| 85 |
+
out = subprocess.run(
|
| 86 |
+
["bun", "autocomplete.ts", "--json", *prompts],
|
| 87 |
+
cwd=MODEL_DIR, capture_output=True, text=True, check=True,
|
| 88 |
+
)
|
| 89 |
+
results = json.loads(out.stdout)
|
| 90 |
+
with torch.no_grad():
|
| 91 |
+
for prompt, res in zip(prompts, results):
|
| 92 |
+
with self.subTest(prompt=prompt):
|
| 93 |
+
ids = self.tok(prompt, return_tensors="pt")
|
| 94 |
+
logp = self.model(**ids).logits[0, -1].log_softmax(-1)
|
| 95 |
+
top = logp.topk(3)
|
| 96 |
+
self.assertEqual([t["id"] for t in res["top"]], top.indices.tolist())
|
| 97 |
+
for t, lp in zip(res["top"], top.values.tolist()):
|
| 98 |
+
self.assertAlmostEqual(t["logprob"], lp, places=3)
|
| 99 |
+
self.assertEqual(res["completion"].strip(), self.complete(prompt))
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
if __name__ == "__main__":
|
| 103 |
+
unittest.main()
|
tokenizer.json
ADDED
|
@@ -0,0 +1,1149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"version": "1.0",
|
| 3 |
+
"truncation": null,
|
| 4 |
+
"padding": null,
|
| 5 |
+
"added_tokens": [
|
| 6 |
+
{
|
| 7 |
+
"id": 0,
|
| 8 |
+
"content": "<|endoftext|>",
|
| 9 |
+
"single_word": false,
|
| 10 |
+
"lstrip": false,
|
| 11 |
+
"rstrip": false,
|
| 12 |
+
"normalized": false,
|
| 13 |
+
"special": true
|
| 14 |
+
},
|
| 15 |
+
{
|
| 16 |
+
"id": 1,
|
| 17 |
+
"content": "<unk>",
|
| 18 |
+
"single_word": false,
|
| 19 |
+
"lstrip": false,
|
| 20 |
+
"rstrip": false,
|
| 21 |
+
"normalized": false,
|
| 22 |
+
"special": true
|
| 23 |
+
}
|
| 24 |
+
],
|
| 25 |
+
"normalizer": {
|
| 26 |
+
"type": "Sequence",
|
| 27 |
+
"normalizers": [
|
| 28 |
+
{
|
| 29 |
+
"type": "NFKC"
|
| 30 |
+
},
|
| 31 |
+
{
|
| 32 |
+
"type": "Lowercase"
|
| 33 |
+
}
|
| 34 |
+
]
|
| 35 |
+
},
|
| 36 |
+
"pre_tokenizer": {
|
| 37 |
+
"type": "ByteLevel",
|
| 38 |
+
"add_prefix_space": true,
|
| 39 |
+
"trim_offsets": true,
|
| 40 |
+
"use_regex": true
|
| 41 |
+
},
|
| 42 |
+
"post_processor": {
|
| 43 |
+
"type": "TemplateProcessing",
|
| 44 |
+
"single": [
|
| 45 |
+
{
|
| 46 |
+
"SpecialToken": {
|
| 47 |
+
"id": "<|endoftext|>",
|
| 48 |
+
"type_id": 0
|
| 49 |
+
}
|
| 50 |
+
},
|
| 51 |
+
{
|
| 52 |
+
"Sequence": {
|
| 53 |
+
"id": "A",
|
| 54 |
+
"type_id": 0
|
| 55 |
+
}
|
| 56 |
+
}
|
| 57 |
+
],
|
| 58 |
+
"pair": [
|
| 59 |
+
{
|
| 60 |
+
"Sequence": {
|
| 61 |
+
"id": "A",
|
| 62 |
+
"type_id": 0
|
| 63 |
+
}
|
| 64 |
+
},
|
| 65 |
+
{
|
| 66 |
+
"Sequence": {
|
| 67 |
+
"id": "B",
|
| 68 |
+
"type_id": 1
|
| 69 |
+
}
|
| 70 |
+
}
|
| 71 |
+
],
|
| 72 |
+
"special_tokens": {
|
| 73 |
+
"<|endoftext|>": {
|
| 74 |
+
"id": "<|endoftext|>",
|
| 75 |
+
"ids": [
|
| 76 |
+
0
|
| 77 |
+
],
|
| 78 |
+
"tokens": [
|
| 79 |
+
"<|endoftext|>"
|
| 80 |
+
]
|
| 81 |
+
}
|
| 82 |
+
}
|
| 83 |
+
},
|
| 84 |
+
"decoder": {
|
| 85 |
+
"type": "ByteLevel",
|
| 86 |
+
"add_prefix_space": true,
|
| 87 |
+
"trim_offsets": true,
|
| 88 |
+
"use_regex": true
|
| 89 |
+
},
|
| 90 |
+
"model": {
|
| 91 |
+
"type": "WordLevel",
|
| 92 |
+
"vocab": {
|
| 93 |
+
"<|endoftext|>": 0,
|
| 94 |
+
"<unk>": 1,
|
| 95 |
+
".": 2,
|
| 96 |
+
"Ġyou": 3,
|
| 97 |
+
"Ġthe": 4,
|
| 98 |
+
"Ġi": 5,
|
| 99 |
+
"?": 6,
|
| 100 |
+
"Ġa": 7,
|
| 101 |
+
"Ġto": 8,
|
| 102 |
+
"'s": 9,
|
| 103 |
+
"Ġit": 10,
|
| 104 |
+
",": 11,
|
| 105 |
+
"Ġis": 12,
|
| 106 |
+
"Ġyour": 13,
|
| 107 |
+
"Ġfor": 14,
|
| 108 |
+
"Ġcan": 15,
|
| 109 |
+
"Ġme": 16,
|
| 110 |
+
"'t": 17,
|
| 111 |
+
"'m": 18,
|
| 112 |
+
"Ġthat": 19,
|
| 113 |
+
"Ġplease": 20,
|
| 114 |
+
"Ġas": 21,
|
| 115 |
+
"Ġdo": 22,
|
| 116 |
+
"Ġwhat": 23,
|
| 117 |
+
"Ġhave": 24,
|
| 118 |
+
"Ġin": 25,
|
| 119 |
+
"Ġof": 26,
|
| 120 |
+
"Ġgood": 27,
|
| 121 |
+
"Ġhow": 28,
|
| 122 |
+
"Ġlet": 29,
|
| 123 |
+
"Ġon": 30,
|
| 124 |
+
"Ġare": 31,
|
| 125 |
+
"Ġdon": 32,
|
| 126 |
+
"Ġtime": 33,
|
| 127 |
+
"Ġknow": 34,
|
| 128 |
+
"Ġthank": 35,
|
| 129 |
+
"Ġhelp": 36,
|
| 130 |
+
"'ll": 37,
|
| 131 |
+
"Ġday": 38,
|
| 132 |
+
"Ġlike": 39,
|
| 133 |
+
"Ġsee": 40,
|
| 134 |
+
"Ġand": 41,
|
| 135 |
+
"Ġget": 42,
|
| 136 |
+
"Ġgreat": 43,
|
| 137 |
+
"Ġhappy": 44,
|
| 138 |
+
"Ġneed": 45,
|
| 139 |
+
"Ġnot": 46,
|
| 140 |
+
"Ġthere": 47,
|
| 141 |
+
"Ġbe": 48,
|
| 142 |
+
"Ġso": 49,
|
| 143 |
+
"Ġwith": 50,
|
| 144 |
+
"Ġgo": 51,
|
| 145 |
+
"Ġno": 52,
|
| 146 |
+
"Ġthanks": 53,
|
| 147 |
+
"Ġwe": 54,
|
| 148 |
+
"Ġwhere": 55,
|
| 149 |
+
"Ġback": 56,
|
| 150 |
+
"Ġgoing": 57,
|
| 151 |
+
"Ġout": 58,
|
| 152 |
+
"Ġcall": 59,
|
| 153 |
+
"Ġmy": 60,
|
| 154 |
+
"Ġthis": 61,
|
| 155 |
+
"Ġup": 62,
|
| 156 |
+
"Ġwhen": 63,
|
| 157 |
+
"'re": 64,
|
| 158 |
+
"Ġsorry": 65,
|
| 159 |
+
"Ġan": 66,
|
| 160 |
+
"Ġmeeting": 67,
|
| 161 |
+
"Ġright": 68,
|
| 162 |
+
"Ġwell": 69,
|
| 163 |
+
"Ġcome": 70,
|
| 164 |
+
"Ġhere": 71,
|
| 165 |
+
"Ġnice": 72,
|
| 166 |
+
"Ġthink": 73,
|
| 167 |
+
"Ġtoday": 74,
|
| 168 |
+
"Ġall": 75,
|
| 169 |
+
"Ġat": 76,
|
| 170 |
+
"Ġmake": 77,
|
| 171 |
+
"Ġone": 78,
|
| 172 |
+
"Ġtoo": 79,
|
| 173 |
+
"Ġwould": 80,
|
| 174 |
+
"Ġabout": 81,
|
| 175 |
+
"Ġfeel": 82,
|
| 176 |
+
"Ġhome": 83,
|
| 177 |
+
"Ġkeep": 84,
|
| 178 |
+
"Ġlate": 85,
|
| 179 |
+
"Ġtake": 86,
|
| 180 |
+
"Ġmuch": 87,
|
| 181 |
+
"Ġthan": 88,
|
| 182 |
+
"Ġwork": 89,
|
| 183 |
+
"Ġbest": 90,
|
| 184 |
+
"Ġhope": 91,
|
| 185 |
+
"Ġlater": 92,
|
| 186 |
+
"Ġlook": 93,
|
| 187 |
+
"Ġlove": 94,
|
| 188 |
+
"Ġokay": 95,
|
| 189 |
+
"Ġsoon": 96,
|
| 190 |
+
"Ġwas": 97,
|
| 191 |
+
"Ġdoing": 98,
|
| 192 |
+
"Ġforward": 99,
|
| 193 |
+
"Ġidea": 100,
|
| 194 |
+
"Ġjust": 101,
|
| 195 |
+
"Ġmeet": 102,
|
| 196 |
+
"Ġnever": 103,
|
| 197 |
+
"Ġover": 104,
|
| 198 |
+
"Ġtomorrow": 105,
|
| 199 |
+
"Ġturn": 106,
|
| 200 |
+
"Ġwill": 107,
|
| 201 |
+
"Ġdid": 108,
|
| 202 |
+
"Ġdoes": 109,
|
| 203 |
+
"Ġfree": 110,
|
| 204 |
+
"Ġif": 111,
|
| 205 |
+
"Ġoff": 112,
|
| 206 |
+
"Ġtwo": 113,
|
| 207 |
+
"Ġwant": 114,
|
| 208 |
+
"Ġwater": 115,
|
| 209 |
+
"Ġway": 116,
|
| 210 |
+
"Ġbeen": 117,
|
| 211 |
+
"Ġcoffee": 118,
|
| 212 |
+
"Ġeverything": 119,
|
| 213 |
+
"Ġfrom": 120,
|
| 214 |
+
"Ġgive": 121,
|
| 215 |
+
"Ġjob": 122,
|
| 216 |
+
"Ġnew": 123,
|
| 217 |
+
"Ġnow": 124,
|
| 218 |
+
"Ġsure": 125,
|
| 219 |
+
"Ġtalk": 126,
|
| 220 |
+
"Ġweekend": 127,
|
| 221 |
+
"Ġwelcome": 128,
|
| 222 |
+
"Ġappreciate": 129,
|
| 223 |
+
"Ġbefore": 130,
|
| 224 |
+
"Ġbetter": 131,
|
| 225 |
+
"Ġbite": 132,
|
| 226 |
+
"Ġclose": 133,
|
| 227 |
+
"Ġcongratulations": 134,
|
| 228 |
+
"Ġcould": 135,
|
| 229 |
+
"Ġeat": 136,
|
| 230 |
+
"Ġfine": 137,
|
| 231 |
+
"Ġlong": 138,
|
| 232 |
+
"Ġlooking": 139,
|
| 233 |
+
"Ġmore": 140,
|
| 234 |
+
"Ġonce": 141,
|
| 235 |
+
"Ġrain": 142,
|
| 236 |
+
"Ġreally": 143,
|
| 237 |
+
"Ġsome": 144,
|
| 238 |
+
"Ġsounds": 145,
|
| 239 |
+
"Ġwait": 146,
|
| 240 |
+
"Ġagree": 147,
|
| 241 |
+
"Ġaround": 148,
|
| 242 |
+
"Ġbathroom": 149,
|
| 243 |
+
"Ġbreak": 150,
|
| 244 |
+
"Ġby": 151,
|
| 245 |
+
"Ġcheck": 152,
|
| 246 |
+
"Ġcoming": 153,
|
| 247 |
+
"Ġdoesn": 154,
|
| 248 |
+
"Ġdog": 155,
|
| 249 |
+
"Ġdoor": 156,
|
| 250 |
+
"Ġenjoy": 157,
|
| 251 |
+
"Ġeye": 158,
|
| 252 |
+
"Ġfire": 159,
|
| 253 |
+
"Ġhas": 160,
|
| 254 |
+
"Ġmakes": 161,
|
| 255 |
+
"Ġmean": 162,
|
| 256 |
+
"Ġmiss": 163,
|
| 257 |
+
"Ġput": 164,
|
| 258 |
+
"Ġquestion": 165,
|
| 259 |
+
"Ġsay": 166,
|
| 260 |
+
"Ġsend": 167,
|
| 261 |
+
"Ġstore": 168,
|
| 262 |
+
"Ġtell": 169,
|
| 263 |
+
"Ġus": 170,
|
| 264 |
+
"Ġany": 171,
|
| 265 |
+
"Ġanything": 172,
|
| 266 |
+
"Ġball": 173,
|
| 267 |
+
"Ġbed": 174,
|
| 268 |
+
"Ġbirthday": 175,
|
| 269 |
+
"Ġcold": 176,
|
| 270 |
+
"Ġcut": 177,
|
| 271 |
+
"Ġdown": 178,
|
| 272 |
+
"Ġeasy": 179,
|
| 273 |
+
"Ġevery": 180,
|
| 274 |
+
"Ġfall": 181,
|
| 275 |
+
"Ġfind": 182,
|
| 276 |
+
"Ġhi": 183,
|
| 277 |
+
"Ġits": 184,
|
| 278 |
+
"Ġkeys": 185,
|
| 279 |
+
"Ġlife": 186,
|
| 280 |
+
"Ġlight": 187,
|
| 281 |
+
"Ġlive": 188,
|
| 282 |
+
"Ġluck": 189,
|
| 283 |
+
"Ġman": 190,
|
| 284 |
+
"Ġmany": 191,
|
| 285 |
+
"Ġmay": 192,
|
| 286 |
+
"Ġmind": 193,
|
| 287 |
+
"Ġmoment": 194,
|
| 288 |
+
"Ġmoney": 195,
|
| 289 |
+
"Ġnext": 196,
|
| 290 |
+
"Ġnight": 197,
|
| 291 |
+
"Ġold": 198,
|
| 292 |
+
"Ġorder": 199,
|
| 293 |
+
"Ġphone": 200,
|
| 294 |
+
"Ġquick": 201,
|
| 295 |
+
"Ġsame": 202,
|
| 296 |
+
"Ġshould": 203,
|
| 297 |
+
"Ġsleep": 204,
|
| 298 |
+
"Ġspeak": 205,
|
| 299 |
+
"Ġtouch": 206,
|
| 300 |
+
"Ġvery": 207,
|
| 301 |
+
"Ġweather": 208,
|
| 302 |
+
"Ġworking": 209,
|
| 303 |
+
"Ġworth": 210,
|
| 304 |
+
"'d": 211,
|
| 305 |
+
"Ġagain": 212,
|
| 306 |
+
"Ġalways": 213,
|
| 307 |
+
"Ġanother": 214,
|
| 308 |
+
"Ġapologize": 215,
|
| 309 |
+
"Ġapple": 216,
|
| 310 |
+
"Ġask": 217,
|
| 311 |
+
"Ġattached": 218,
|
| 312 |
+
"Ġbad": 219,
|
| 313 |
+
"Ġbeautiful": 220,
|
| 314 |
+
"Ġbelieve": 221,
|
| 315 |
+
"Ġblind": 222,
|
| 316 |
+
"Ġburn": 223,
|
| 317 |
+
"Ġbusy": 224,
|
| 318 |
+
"Ġbut": 225,
|
| 319 |
+
"Ġcare": 226,
|
| 320 |
+
"Ġcat": 227,
|
| 321 |
+
"Ġcourse": 228,
|
| 322 |
+
"Ġcup": 229,
|
| 323 |
+
"Ġdevil": 230,
|
| 324 |
+
"Ġdinner": 231,
|
| 325 |
+
"Ġdoctor": 232,
|
| 326 |
+
"Ġemail": 233,
|
| 327 |
+
"Ġend": 234,
|
| 328 |
+
"Ġends": 235,
|
| 329 |
+
"Ġeveryone": 236,
|
| 330 |
+
"Ġexcuse": 237,
|
| 331 |
+
"Ġfair": 238,
|
| 332 |
+
"Ġfamily": 239,
|
| 333 |
+
"Ġfar": 240,
|
| 334 |
+
"Ġfeeling": 241,
|
| 335 |
+
"Ġfollow": 242,
|
| 336 |
+
"Ġforget": 243,
|
| 337 |
+
"Ġglad": 244,
|
| 338 |
+
"Ġglass": 245,
|
| 339 |
+
"Ġgold": 246,
|
| 340 |
+
"Ġhand": 247,
|
| 341 |
+
"Ġhard": 248,
|
| 342 |
+
"Ġhead": 249,
|
| 343 |
+
"Ġhear": 250,
|
| 344 |
+
"Ġhearing": 251,
|
| 345 |
+
"Ġheart": 252,
|
| 346 |
+
"Ġhello": 253,
|
| 347 |
+
"Ġhis": 254,
|
| 348 |
+
"Ġhit": 255,
|
| 349 |
+
"Ġhold": 256,
|
| 350 |
+
"Ġhorse": 257,
|
| 351 |
+
"Ġinconvenience": 258,
|
| 352 |
+
"Ġkill": 259,
|
| 353 |
+
"Ġkind": 260,
|
| 354 |
+
"Ġlost": 261,
|
| 355 |
+
"Ġmaybe": 262,
|
| 356 |
+
"Ġmile": 263,
|
| 357 |
+
"Ġminute": 264,
|
| 358 |
+
"Ġmorning": 265,
|
| 359 |
+
"Ġmouth": 266,
|
| 360 |
+
"Ġnews": 267,
|
| 361 |
+
"Ġnothing": 268,
|
| 362 |
+
"Ġopen": 269,
|
| 363 |
+
"Ġoutside": 270,
|
| 364 |
+
"Ġpatience": 271,
|
| 365 |
+
"Ġpay": 272,
|
| 366 |
+
"Ġpenny": 273,
|
| 367 |
+
"Ġpleasure": 274,
|
| 368 |
+
"Ġpossible": 275,
|
| 369 |
+
"Ġquestions": 276,
|
| 370 |
+
"Ġregards": 277,
|
| 371 |
+
"Ġrome": 278,
|
| 372 |
+
"Ġsafe": 279,
|
| 373 |
+
"Ġsaid": 280,
|
| 374 |
+
"Ġsense": 281,
|
| 375 |
+
"Ġshame": 282,
|
| 376 |
+
"Ġside": 283,
|
| 377 |
+
"Ġsomething": 284,
|
| 378 |
+
"Ġstation": 285,
|
| 379 |
+
"Ġtable": 286,
|
| 380 |
+
"Ġthings": 287,
|
| 381 |
+
"Ġtired": 288,
|
| 382 |
+
"Ġtogether": 289,
|
| 383 |
+
"Ġtonight": 290,
|
| 384 |
+
"Ġtrain": 291,
|
| 385 |
+
"Ġtwice": 292,
|
| 386 |
+
"Ġunderstand": 293,
|
| 387 |
+
"Ġupdate": 294,
|
| 388 |
+
"Ġwho": 295,
|
| 389 |
+
"Ġwhy": 296,
|
| 390 |
+
"Ġwithout": 297,
|
| 391 |
+
"Ġworry": 298,
|
| 392 |
+
"Ġwrong": 299,
|
| 393 |
+
"Ġyet": 300,
|
| 394 |
+
"Ġyourself": 301,
|
| 395 |
+
"!": 302,
|
| 396 |
+
"Ġahead": 303,
|
| 397 |
+
"Ġairport": 304,
|
| 398 |
+
"Ġamazing": 305,
|
| 399 |
+
"Ġasking": 306,
|
| 400 |
+
"Ġavailable": 307,
|
| 401 |
+
"Ġbark": 308,
|
| 402 |
+
"Ġbetween": 309,
|
| 403 |
+
"Ġbill": 310,
|
| 404 |
+
"Ġbird": 311,
|
| 405 |
+
"Ġbirds": 312,
|
| 406 |
+
"Ġbless": 313,
|
| 407 |
+
"Ġblue": 314,
|
| 408 |
+
"Ġboat": 315,
|
| 409 |
+
"Ġbook": 316,
|
| 410 |
+
"Ġboth": 317,
|
| 411 |
+
"Ġbridge": 318,
|
| 412 |
+
"Ġbucket": 319,
|
| 413 |
+
"Ġbush": 320,
|
| 414 |
+
"Ġbye": 321,
|
| 415 |
+
"Ġbygones": 322,
|
| 416 |
+
"Ġcake": 323,
|
| 417 |
+
"Ġcalling": 324,
|
| 418 |
+
"Ġcalm": 325,
|
| 419 |
+
"Ġcanceled": 326,
|
| 420 |
+
"Ġcats": 327,
|
| 421 |
+
"Ġcaught": 328,
|
| 422 |
+
"Ġchange": 329,
|
| 423 |
+
"Ġchase": 330,
|
| 424 |
+
"Ġcheers": 331,
|
| 425 |
+
"Ġchip": 332,
|
| 426 |
+
"Ġchristmas": 333,
|
| 427 |
+
"Ġcomes": 334,
|
| 428 |
+
"Ġcontact": 335,
|
| 429 |
+
"Ġcorner": 336,
|
| 430 |
+
"Ġcost": 337,
|
| 431 |
+
"Ġcry": 338,
|
| 432 |
+
"Ġdeal": 339,
|
| 433 |
+
"Ġdelay": 340,
|
| 434 |
+
"Ġdelicious": 341,
|
| 435 |
+
"Ġdeserve": 342,
|
| 436 |
+
"Ġdetails": 343,
|
| 437 |
+
"Ġdidn": 344,
|
| 438 |
+
"Ġdocument": 345,
|
| 439 |
+
"Ġdogs": 346,
|
| 440 |
+
"Ġdone": 347,
|
| 441 |
+
"Ġdreams": 348,
|
| 442 |
+
"Ġeggs": 349,
|
| 443 |
+
"Ġelse": 350,
|
| 444 |
+
"Ġenglish": 351,
|
| 445 |
+
"Ġenough": 352,
|
| 446 |
+
"Ġexcited": 353,
|
| 447 |
+
"Ġface": 354,
|
| 448 |
+
"Ġfault": 355,
|
| 449 |
+
"Ġfeather": 356,
|
| 450 |
+
"Ġfile": 357,
|
| 451 |
+
"Ġfirst": 358,
|
| 452 |
+
"Ġfly": 359,
|
| 453 |
+
"Ġfool": 360,
|
| 454 |
+
"Ġfox": 361,
|
| 455 |
+
"Ġfriend": 362,
|
| 456 |
+
"Ġfun": 363,
|
| 457 |
+
"Ġfunny": 364,
|
| 458 |
+
"Ġgets": 365,
|
| 459 |
+
"Ġgift": 366,
|
| 460 |
+
"Ġgod": 367,
|
| 461 |
+
"Ġgoes": 368,
|
| 462 |
+
"Ġgot": 369,
|
| 463 |
+
"Ġgrab": 370,
|
| 464 |
+
"Ġgrain": 371,
|
| 465 |
+
"Ġgrow": 372,
|
| 466 |
+
"Ġhang": 373,
|
| 467 |
+
"Ġhay": 374,
|
| 468 |
+
"Ġhey": 375,
|
| 469 |
+
"Ġhospital": 376,
|
| 470 |
+
"Ġhot": 377,
|
| 471 |
+
"Ġice": 378,
|
| 472 |
+
"Ġinto": 379,
|
| 473 |
+
"Ġisn": 380,
|
| 474 |
+
"Ġjoin": 381,
|
| 475 |
+
"Ġjump": 382,
|
| 476 |
+
"Ġkidding": 383,
|
| 477 |
+
"Ġlast": 384,
|
| 478 |
+
"Ġlearn": 385,
|
| 479 |
+
"Ġleft": 386,
|
| 480 |
+
"Ġleg": 387,
|
| 481 |
+
"Ġletting": 388,
|
| 482 |
+
"Ġlights": 389,
|
| 483 |
+
"Ġlot": 390,
|
| 484 |
+
"Ġlunch": 391,
|
| 485 |
+
"Ġmeans": 392,
|
| 486 |
+
"Ġmedicine": 393,
|
| 487 |
+
"Ġmerry": 394,
|
| 488 |
+
"Ġmonkey": 395,
|
| 489 |
+
"Ġmoon": 396,
|
| 490 |
+
"Ġmother": 397,
|
| 491 |
+
"Ġmove": 398,
|
| 492 |
+
"Ġmovie": 399,
|
| 493 |
+
"Ġmusic": 400,
|
| 494 |
+
"Ġname": 401,
|
| 495 |
+
"Ġnear": 402,
|
| 496 |
+
"Ġnine": 403,
|
| 497 |
+
"Ġoh": 404,
|
| 498 |
+
"Ġowe": 405,
|
| 499 |
+
"Ġown": 406,
|
| 500 |
+
"Ġpass": 407,
|
| 501 |
+
"Ġpen": 408,
|
| 502 |
+
"Ġpick": 409,
|
| 503 |
+
"Ġpie": 410,
|
| 504 |
+
"Ġplace": 411,
|
| 505 |
+
"Ġplay": 412,
|
| 506 |
+
"Ġpoint": 413,
|
| 507 |
+
"Ġpot": 414,
|
| 508 |
+
"Ġproblem": 415,
|
| 509 |
+
"Ġproud": 416,
|
| 510 |
+
"Ġpull": 417,
|
| 511 |
+
"Ġquiet": 418,
|
| 512 |
+
"Ġraining": 419,
|
| 513 |
+
"Ġreach": 420,
|
| 514 |
+
"Ġreaching": 421,
|
| 515 |
+
"Ġred": 422,
|
| 516 |
+
"Ġreservation": 423,
|
| 517 |
+
"Ġreview": 424,
|
| 518 |
+
"Ġrock": 425,
|
| 519 |
+
"Ġrolling": 426,
|
| 520 |
+
"Ġrule": 427,
|
| 521 |
+
"Ġsalt": 428,
|
| 522 |
+
"Ġschedule": 429,
|
| 523 |
+
"Ġscratch": 430,
|
| 524 |
+
"Ġseat": 431,
|
| 525 |
+
"Ġshort": 432,
|
| 526 |
+
"Ġshoulder": 433,
|
| 527 |
+
"Ġsight": 434,
|
| 528 |
+
"Ġsit": 435,
|
| 529 |
+
"Ġskin": 436,
|
| 530 |
+
"Ġsmoke": 437,
|
| 531 |
+
"Ġsomeone": 438,
|
| 532 |
+
"Ġspade": 439,
|
| 533 |
+
"Ġspoil": 440,
|
| 534 |
+
"Ġstone": 441,
|
| 535 |
+
"Ġstraight": 442,
|
| 536 |
+
"Ġsurprise": 443,
|
| 537 |
+
"Ġsweet": 444,
|
| 538 |
+
"Ġtakes": 445,
|
| 539 |
+
"Ġteam": 446,
|
| 540 |
+
"Ġtext": 447,
|
| 541 |
+
"Ġthey": 448,
|
| 542 |
+
"Ġthin": 449,
|
| 543 |
+
"Ġthing": 450,
|
| 544 |
+
"Ġthought": 451,
|
| 545 |
+
"Ġtough": 452,
|
| 546 |
+
"Ġtree": 453,
|
| 547 |
+
"Ġtrip": 454,
|
| 548 |
+
"Ġtrue": 455,
|
| 549 |
+
"Ġtry": 456,
|
| 550 |
+
"Ġunder": 457,
|
| 551 |
+
"Ġuse": 458,
|
| 552 |
+
"Ġwanted": 459,
|
| 553 |
+
"Ġwaste": 460,
|
| 554 |
+
"Ġwatch": 461,
|
| 555 |
+
"Ġwear": 462,
|
| 556 |
+
"Ġweek": 463,
|
| 557 |
+
"Ġwhile": 464,
|
| 558 |
+
"Ġwhole": 465,
|
| 559 |
+
"Ġwords": 466,
|
| 560 |
+
"Ġworks": 467,
|
| 561 |
+
"Ġworld": 468,
|
| 562 |
+
"Ġyear": 469,
|
| 563 |
+
"'ve": 470,
|
| 564 |
+
"-": 471,
|
| 565 |
+
"handed": 472,
|
| 566 |
+
"Ġabsence": 473,
|
| 567 |
+
"Ġabsolutely": 474,
|
| 568 |
+
"Ġaccept": 475,
|
| 569 |
+
"Ġactions": 476,
|
| 570 |
+
"Ġadd": 477,
|
| 571 |
+
"Ġadvance": 478,
|
| 572 |
+
"Ġadvocate": 479,
|
| 573 |
+
"Ġafraid": 480,
|
| 574 |
+
"Ġafter": 481,
|
| 575 |
+
"Ġafternoon": 482,
|
| 576 |
+
"Ġagainst": 483,
|
| 577 |
+
"Ġain": 484,
|
| 578 |
+
"Ġair": 485,
|
| 579 |
+
"Ġalike": 486,
|
| 580 |
+
"Ġalmost": 487,
|
| 581 |
+
"Ġam": 488,
|
| 582 |
+
"Ġambulance": 489,
|
| 583 |
+
"Ġamerican": 490,
|
| 584 |
+
"Ġanniversary": 491,
|
| 585 |
+
"Ġanymore": 492,
|
| 586 |
+
"Ġanyone": 493,
|
| 587 |
+
"Ġanytime": 494,
|
| 588 |
+
"Ġanyway": 495,
|
| 589 |
+
"Ġappetit": 496,
|
| 590 |
+
"Ġappointment": 497,
|
| 591 |
+
"Ġarm": 498,
|
| 592 |
+
"Ġattendance": 499,
|
| 593 |
+
"Ġavailability": 500,
|
| 594 |
+
"Ġaway": 501,
|
| 595 |
+
"Ġawesome": 502,
|
| 596 |
+
"Ġbaby": 503,
|
| 597 |
+
"Ġbackwards": 504,
|
| 598 |
+
"Ġbag": 505,
|
| 599 |
+
"Ġbandwagon": 506,
|
| 600 |
+
"Ġbank": 507,
|
| 601 |
+
"Ġbarking": 508,
|
| 602 |
+
"Ġbase": 509,
|
| 603 |
+
"Ġbasket": 510,
|
| 604 |
+
"Ġbat": 511,
|
| 605 |
+
"Ġbeans": 512,
|
| 606 |
+
"Ġbeat": 513,
|
| 607 |
+
"Ġbeaten": 514,
|
| 608 |
+
"Ġbeauty": 515,
|
| 609 |
+
"Ġbeaver": 516,
|
| 610 |
+
"Ġbee": 517,
|
| 611 |
+
"Ġbeggars": 518,
|
| 612 |
+
"Ġbegins": 519,
|
| 613 |
+
"Ġbeholder": 520,
|
| 614 |
+
"Ġbeing": 521,
|
| 615 |
+
"Ġbell": 522,
|
| 616 |
+
"Ġbend": 523,
|
| 617 |
+
"Ġbenefit": 524,
|
| 618 |
+
"Ġbeyond": 525,
|
| 619 |
+
"Ġbig": 526,
|
| 620 |
+
"Ġbitten": 527,
|
| 621 |
+
"Ġblack": 528,
|
| 622 |
+
"Ġblessing": 529,
|
| 623 |
+
"Ġbliss": 530,
|
| 624 |
+
"Ġblock": 531,
|
| 625 |
+
"Ġblood": 532,
|
| 626 |
+
"Ġblow": 533,
|
| 627 |
+
"Ġboard": 534,
|
| 628 |
+
"Ġboils": 535,
|
| 629 |
+
"Ġbold": 536,
|
| 630 |
+
"Ġbon": 537,
|
| 631 |
+
"Ġborrow": 538,
|
| 632 |
+
"Ġbother": 539,
|
| 633 |
+
"Ġbreakfast": 540,
|
| 634 |
+
"Ġbreaking": 541,
|
| 635 |
+
"Ġbreeds": 542,
|
| 636 |
+
"Ġbridges": 543,
|
| 637 |
+
"Ġbroke": 544,
|
| 638 |
+
"Ġbroth": 545,
|
| 639 |
+
"Ġbrown": 546,
|
| 640 |
+
"Ġbuck": 547,
|
| 641 |
+
"Ġbuilt": 548,
|
| 642 |
+
"Ġbull": 549,
|
| 643 |
+
"Ġbullet": 550,
|
| 644 |
+
"Ġbury": 551,
|
| 645 |
+
"Ġbus": 552,
|
| 646 |
+
"Ġbusiness": 553,
|
| 647 |
+
"Ġbutton": 554,
|
| 648 |
+
"Ġbuy": 555,
|
| 649 |
+
"Ġcaboodle": 556,
|
| 650 |
+
"Ġcandle": 557,
|
| 651 |
+
"Ġcard": 558,
|
| 652 |
+
"Ġcards": 559,
|
| 653 |
+
"Ġcareful": 560,
|
| 654 |
+
"Ġcart": 561,
|
| 655 |
+
"Ġcash": 562,
|
| 656 |
+
"Ġcatch": 563,
|
| 657 |
+
"Ġcatches": 564,
|
| 658 |
+
"Ġcause": 565,
|
| 659 |
+
"Ġcharity": 566,
|
| 660 |
+
"Ġchecking": 567,
|
| 661 |
+
"Ġcheek": 568,
|
| 662 |
+
"Ġcheer": 569,
|
| 663 |
+
"Ġchew": 570,
|
| 664 |
+
"Ġchicken": 571,
|
| 665 |
+
"Ġchickens": 572,
|
| 666 |
+
"Ġchild": 573,
|
| 667 |
+
"Ġchin": 574,
|
| 668 |
+
"Ġchips": 575,
|
| 669 |
+
"Ġchoosers": 576,
|
| 670 |
+
"Ġcigar": 577,
|
| 671 |
+
"Ġcircle": 578,
|
| 672 |
+
"Ġclam": 579,
|
| 673 |
+
"Ġclean": 580,
|
| 674 |
+
"Ġcleanliness": 581,
|
| 675 |
+
"Ġclear": 582,
|
| 676 |
+
"Ġclosed": 583,
|
| 677 |
+
"Ġcloser": 584,
|
| 678 |
+
"Ġcloses": 585,
|
| 679 |
+
"Ġcloset": 586,
|
| 680 |
+
"Ġclosing": 587,
|
| 681 |
+
"Ġcloud": 588,
|
| 682 |
+
"Ġclouds": 589,
|
| 683 |
+
"Ġcompany": 590,
|
| 684 |
+
"Ġcompletely": 591,
|
| 685 |
+
"Ġconfirm": 592,
|
| 686 |
+
"Ġconfusion": 593,
|
| 687 |
+
"Ġcontacting": 594,
|
| 688 |
+
"Ġcontempt": 595,
|
| 689 |
+
"Ġconvenience": 596,
|
| 690 |
+
"Ġconversation": 597,
|
| 691 |
+
"Ġcooks": 598,
|
| 692 |
+
"Ġcool": 599,
|
| 693 |
+
"Ġcorners": 600,
|
| 694 |
+
"Ġcouldn": 601,
|
| 695 |
+
"Ġcount": 602,
|
| 696 |
+
"Ġcounts": 603,
|
| 697 |
+
"Ġcourt": 604,
|
| 698 |
+
"Ġcover": 605,
|
| 699 |
+
"Ġcredit": 606,
|
| 700 |
+
"Ġcross": 607,
|
| 701 |
+
"Ġcrossed": 608,
|
| 702 |
+
"Ġcucumber": 609,
|
| 703 |
+
"Ġcure": 610,
|
| 704 |
+
"Ġcuriosity": 611,
|
| 705 |
+
"Ġcustomer": 612,
|
| 706 |
+
"Ġcute": 613,
|
| 707 |
+
"Ġdark": 614,
|
| 708 |
+
"Ġdate": 615,
|
| 709 |
+
"Ġdead": 616,
|
| 710 |
+
"Ġdeadline": 617,
|
| 711 |
+
"Ġdeep": 618,
|
| 712 |
+
"Ġdefinitely": 619,
|
| 713 |
+
"Ġdeserves": 620,
|
| 714 |
+
"Ġdiamond": 621,
|
| 715 |
+
"Ġdime": 622,
|
| 716 |
+
"Ġdisagree": 623,
|
| 717 |
+
"Ġdiscuss": 624,
|
| 718 |
+
"Ġdisguise": 625,
|
| 719 |
+
"Ġdivided": 626,
|
| 720 |
+
"Ġdoornail": 627,
|
| 721 |
+
"Ġdoubt": 628,
|
| 722 |
+
"Ġdozen": 629,
|
| 723 |
+
"Ġdraw": 630,
|
| 724 |
+
"Ġdrawing": 631,
|
| 725 |
+
"Ġdrink": 632,
|
| 726 |
+
"Ġdrive": 633,
|
| 727 |
+
"Ġdrop": 634,
|
| 728 |
+
"Ġdumps": 635,
|
| 729 |
+
"Ġdust": 636,
|
| 730 |
+
"Ġeach": 637,
|
| 731 |
+
"Ġeager": 638,
|
| 732 |
+
"Ġear": 639,
|
| 733 |
+
"Ġearliest": 640,
|
| 734 |
+
"Ġearly": 641,
|
| 735 |
+
"Ġearned": 642,
|
| 736 |
+
"Ġeasier": 643,
|
| 737 |
+
"Ġeaster": 644,
|
| 738 |
+
"Ġeaten": 645,
|
| 739 |
+
"Ġelephant": 646,
|
| 740 |
+
"Ġenemies": 647,
|
| 741 |
+
"Ġeven": 648,
|
| 742 |
+
"Ġevening": 649,
|
| 743 |
+
"Ġevil": 650,
|
| 744 |
+
"Ġexactly": 651,
|
| 745 |
+
"Ġexam": 652,
|
| 746 |
+
"Ġexception": 653,
|
| 747 |
+
"Ġexit": 654,
|
| 748 |
+
"Ġexpensive": 655,
|
| 749 |
+
"Ġextra": 656,
|
| 750 |
+
"Ġeyes": 657,
|
| 751 |
+
"Ġfamiliarity": 658,
|
| 752 |
+
"Ġfather": 659,
|
| 753 |
+
"Ġfavor": 660,
|
| 754 |
+
"Ġfavors": 661,
|
| 755 |
+
"Ġfeeds": 662,
|
| 756 |
+
"Ġfence": 663,
|
| 757 |
+
"Ġfiddle": 664,
|
| 758 |
+
"Ġfight": 665,
|
| 759 |
+
"Ġfinds": 666,
|
| 760 |
+
"Ġfingers": 667,
|
| 761 |
+
"Ġfinish": 668,
|
| 762 |
+
"Ġfish": 669,
|
| 763 |
+
"Ġfit": 670,
|
| 764 |
+
"Ġfits": 671,
|
| 765 |
+
"Ġfive": 672,
|
| 766 |
+
"Ġfix": 673,
|
| 767 |
+
"Ġflies": 674,
|
| 768 |
+
"Ġflight": 675,
|
| 769 |
+
"Ġflock": 676,
|
| 770 |
+
"Ġflow": 677,
|
| 771 |
+
"Ġfonder": 678,
|
| 772 |
+
"Ġfood": 679,
|
| 773 |
+
"Ġfoot": 680,
|
| 774 |
+
"Ġforgot": 681,
|
| 775 |
+
"Ġfortune": 682,
|
| 776 |
+
"Ġfriends": 683,
|
| 777 |
+
"Ġfrying": 684,
|
| 778 |
+
"Ġgain": 685,
|
| 779 |
+
"Ġgained": 686,
|
| 780 |
+
"Ġgathers": 687,
|
| 781 |
+
"Ġgentlemen": 688,
|
| 782 |
+
"Ġgetting": 689,
|
| 783 |
+
"Ġghost": 690,
|
| 784 |
+
"Ġgives": 691,
|
| 785 |
+
"Ġglitters": 692,
|
| 786 |
+
"Ġgodliness": 693,
|
| 787 |
+
"Ġgolden": 694,
|
| 788 |
+
"Ġgoodbye": 695,
|
| 789 |
+
"Ġgoose": 696,
|
| 790 |
+
"Ġgosh": 697,
|
| 791 |
+
"Ġgraduation": 698,
|
| 792 |
+
"Ġgrasping": 699,
|
| 793 |
+
"Ġgrass": 700,
|
| 794 |
+
"Ġgrateful": 701,
|
| 795 |
+
"Ġgrease": 702,
|
| 796 |
+
"Ġgreener": 703,
|
| 797 |
+
"Ġgun": 704,
|
| 798 |
+
"Ġgym": 705,
|
| 799 |
+
"Ġhad": 706,
|
| 800 |
+
"Ġhands": 707,
|
| 801 |
+
"Ġhappened": 708,
|
| 802 |
+
"Ġhappiness": 709,
|
| 803 |
+
"Ġhaste": 710,
|
| 804 |
+
"Ġhatch": 711,
|
| 805 |
+
"Ġhatchet": 712,
|
| 806 |
+
"Ġhatter": 713,
|
| 807 |
+
"Ġhaving": 714,
|
| 808 |
+
"Ġhaystack": 715,
|
| 809 |
+
"Ġhe": 716,
|
| 810 |
+
"Ġheadache": 717,
|
| 811 |
+
"Ġheads": 718,
|
| 812 |
+
"Ġheals": 719,
|
| 813 |
+
"Ġhealth": 720,
|
| 814 |
+
"Ġheat": 721,
|
| 815 |
+
"Ġheels": 722,
|
| 816 |
+
"Ġhell": 723,
|
| 817 |
+
"Ġhelping": 724,
|
| 818 |
+
"Ġherding": 725,
|
| 819 |
+
"Ġherring": 726,
|
| 820 |
+
"Ġhesitate": 727,
|
| 821 |
+
"Ġhilarious": 728,
|
| 822 |
+
"Ġhills": 729,
|
| 823 |
+
"Ġhim": 730,
|
| 824 |
+
"Ġhimself": 731,
|
| 825 |
+
"Ġhistory": 732,
|
| 826 |
+
"Ġholidays": 733,
|
| 827 |
+
"Ġhonesty": 734,
|
| 828 |
+
"Ġhook": 735,
|
| 829 |
+
"Ġhorns": 736,
|
| 830 |
+
"Ġhorses": 737,
|
| 831 |
+
"Ġhungry": 738,
|
| 832 |
+
"Ġhurry": 739,
|
| 833 |
+
"Ġhurts": 740,
|
| 834 |
+
"Ġiceberg": 741,
|
| 835 |
+
"Ġignorance": 742,
|
| 836 |
+
"Ġimportant": 743,
|
| 837 |
+
"Ġinch": 744,
|
| 838 |
+
"Ġincluded": 745,
|
| 839 |
+
"Ġindeed": 746,
|
| 840 |
+
"Ġinformation": 747,
|
| 841 |
+
"Ġinjury": 748,
|
| 842 |
+
"Ġinsult": 749,
|
| 843 |
+
"Ġintentions": 750,
|
| 844 |
+
"Ġinvention": 751,
|
| 845 |
+
"Ġinvitation": 752,
|
| 846 |
+
"Ġiron": 753,
|
| 847 |
+
"Ġisland": 754,
|
| 848 |
+
"Ġitself": 755,
|
| 849 |
+
"Ġjack": 756,
|
| 850 |
+
"Ġjudge": 757,
|
| 851 |
+
"Ġjumps": 758,
|
| 852 |
+
"Ġjustifies": 759,
|
| 853 |
+
"Ġkeeps": 760,
|
| 854 |
+
"Ġkettle": 761,
|
| 855 |
+
"Ġkick": 762,
|
| 856 |
+
"Ġkilled": 763,
|
| 857 |
+
"Ġkit": 764,
|
| 858 |
+
"Ġknocks": 765,
|
| 859 |
+
"Ġknot": 766,
|
| 860 |
+
"Ġknowledge": 767,
|
| 861 |
+
"Ġladies": 768,
|
| 862 |
+
"Ġlaughter": 769,
|
| 863 |
+
"Ġlazy": 770,
|
| 864 |
+
"Ġlead": 771,
|
| 865 |
+
"Ġleaf": 772,
|
| 866 |
+
"Ġleap": 773,
|
| 867 |
+
"Ġleave": 774,
|
| 868 |
+
"Ġleaving": 775,
|
| 869 |
+
"Ġlemonade": 776,
|
| 870 |
+
"Ġlemons": 777,
|
| 871 |
+
"Ġleopard": 778,
|
| 872 |
+
"Ġlie": 779,
|
| 873 |
+
"Ġliked": 780,
|
| 874 |
+
"Ġline": 781,
|
| 875 |
+
"Ġlines": 782,
|
| 876 |
+
"Ġlining": 783,
|
| 877 |
+
"Ġlistening": 784,
|
| 878 |
+
"Ġliving": 785,
|
| 879 |
+
"Ġlock": 786,
|
| 880 |
+
"Ġlol": 787,
|
| 881 |
+
"Ġlooks": 788,
|
| 882 |
+
"Ġlose": 789,
|
| 883 |
+
"Ġloss": 790,
|
| 884 |
+
"Ġlosses": 791,
|
| 885 |
+
"Ġlouder": 792,
|
| 886 |
+
"Ġloves": 793,
|
| 887 |
+
"Ġmad": 794,
|
| 888 |
+
"Ġmadness": 795,
|
| 889 |
+
"Ġmatter": 796,
|
| 890 |
+
"Ġmeal": 797,
|
| 891 |
+
"Ġmeasure": 798,
|
| 892 |
+
"Ġmention": 799,
|
| 893 |
+
"Ġmenu": 800,
|
| 894 |
+
"Ġmessage": 801,
|
| 895 |
+
"Ġmessenger": 802,
|
| 896 |
+
"Ġmethod": 803,
|
| 897 |
+
"Ġmidnight": 804,
|
| 898 |
+
"Ġmightier": 805,
|
| 899 |
+
"Ġmilk": 806,
|
| 900 |
+
"Ġminds": 807,
|
| 901 |
+
"Ġminutes": 808,
|
| 902 |
+
"Ġmisery": 809,
|
| 903 |
+
"Ġmolehill": 810,
|
| 904 |
+
"Ġmoss": 811,
|
| 905 |
+
"Ġmountain": 812,
|
| 906 |
+
"Ġmouse": 813,
|
| 907 |
+
"Ġmud": 814,
|
| 908 |
+
"Ġmule": 815,
|
| 909 |
+
"Ġmust": 816,
|
| 910 |
+
"Ġnail": 817,
|
| 911 |
+
"Ġnearest": 818,
|
| 912 |
+
"Ġnecessity": 819,
|
| 913 |
+
"Ġneedle": 820,
|
| 914 |
+
"Ġneither": 821,
|
| 915 |
+
"Ġnick": 822,
|
| 916 |
+
"Ġnoon": 823,
|
| 917 |
+
"Ġnose": 824,
|
| 918 |
+
"Ġnutshell": 825,
|
| 919 |
+
"Ġoffice": 826,
|
| 920 |
+
"Ġoil": 827,
|
| 921 |
+
"Ġomelet": 828,
|
| 922 |
+
"Ġopens": 829,
|
| 923 |
+
"Ġopportunity": 830,
|
| 924 |
+
"Ġor": 831,
|
| 925 |
+
"Ġother": 832,
|
| 926 |
+
"Ġounce": 833,
|
| 927 |
+
"Ġour": 834,
|
| 928 |
+
"Ġox": 835,
|
| 929 |
+
"Ġpage": 836,
|
| 930 |
+
"Ġpain": 837,
|
| 931 |
+
"Ġpale": 838,
|
| 932 |
+
"Ġpan": 839,
|
| 933 |
+
"Ġpar": 840,
|
| 934 |
+
"Ġparade": 841,
|
| 935 |
+
"Ġpardon": 842,
|
| 936 |
+
"Ġpassword": 843,
|
| 937 |
+
"Ġpath": 844,
|
| 938 |
+
"Ġpaved": 845,
|
| 939 |
+
"Ġpeace": 846,
|
| 940 |
+
"Ġpeople": 847,
|
| 941 |
+
"Ġperfect": 848,
|
| 942 |
+
"Ġpharmacy": 849,
|
| 943 |
+
"Ġpicture": 850,
|
| 944 |
+
"Ġpiece": 851,
|
| 945 |
+
"Ġpigs": 852,
|
| 946 |
+
"Ġpill": 853,
|
| 947 |
+
"Ġpizza": 854,
|
| 948 |
+
"Ġplain": 855,
|
| 949 |
+
"Ġplan": 856,
|
| 950 |
+
"Ġpleased": 857,
|
| 951 |
+
"Ġpolicy": 858,
|
| 952 |
+
"Ġposted": 859,
|
| 953 |
+
"Ġpound": 860,
|
| 954 |
+
"Ġpours": 861,
|
| 955 |
+
"Ġpower": 862,
|
| 956 |
+
"Ġpractice": 863,
|
| 957 |
+
"Ġprepare": 864,
|
| 958 |
+
"Ġpresent": 865,
|
| 959 |
+
"Ġpretty": 866,
|
| 960 |
+
"Ġprevention": 867,
|
| 961 |
+
"Ġpride": 868,
|
| 962 |
+
"Ġprobably": 869,
|
| 963 |
+
"Ġproof": 870,
|
| 964 |
+
"Ġproves": 871,
|
| 965 |
+
"Ġpudding": 872,
|
| 966 |
+
"Ġrace": 873,
|
| 967 |
+
"Ġrains": 874,
|
| 968 |
+
"Ġread": 875,
|
| 969 |
+
"Ġready": 876,
|
| 970 |
+
"Ġreap": 877,
|
| 971 |
+
"Ġreceive": 878,
|
| 972 |
+
"Ġrecommend": 879,
|
| 973 |
+
"Ġrelaxing": 880,
|
| 974 |
+
"Ġreminder": 881,
|
| 975 |
+
"Ġrepeat": 882,
|
| 976 |
+
"Ġrepeats": 883,
|
| 977 |
+
"Ġreply": 884,
|
| 978 |
+
"Ġreport": 885,
|
| 979 |
+
"Ġreschedule": 886,
|
| 980 |
+
"Ġresponse": 887,
|
| 981 |
+
"Ġrest": 888,
|
| 982 |
+
"Ġrestroom": 889,
|
| 983 |
+
"Ġreturns": 890,
|
| 984 |
+
"Ġride": 891,
|
| 985 |
+
"Ġrings": 892,
|
| 986 |
+
"Ġroad": 893,
|
| 987 |
+
"Ġroads": 894,
|
| 988 |
+
"Ġrod": 895,
|
| 989 |
+
"Ġromans": 896,
|
| 990 |
+
"Ġroom": 897,
|
| 991 |
+
"Ġroot": 898,
|
| 992 |
+
"Ġropes": 899,
|
| 993 |
+
"Ġrose": 900,
|
| 994 |
+
"Ġrough": 901,
|
| 995 |
+
"Ġrun": 902,
|
| 996 |
+
"Ġrunning": 903,
|
| 997 |
+
"Ġsack": 904,
|
| 998 |
+
"Ġsad": 905,
|
| 999 |
+
"Ġsafely": 906,
|
| 1000 |
+
"Ġsaved": 907,
|
| 1001 |
+
"Ġsaves": 908,
|
| 1002 |
+
"Ġsaying": 909,
|
| 1003 |
+
"Ġsecond": 910,
|
| 1004 |
+
"Ġseeing": 911,
|
| 1005 |
+
"Ġseen": 912,
|
| 1006 |
+
"Ġserious": 913,
|
| 1007 |
+
"Ġserved": 914,
|
| 1008 |
+
"Ġshine": 915,
|
| 1009 |
+
"Ġshines": 916,
|
| 1010 |
+
"Ġshipped": 917,
|
| 1011 |
+
"Ġshoe": 918,
|
| 1012 |
+
"Ġshoes": 919,
|
| 1013 |
+
"Ġshop": 920,
|
| 1014 |
+
"Ġshopping": 921,
|
| 1015 |
+
"Ġshot": 922,
|
| 1016 |
+
"Ġshow": 923,
|
| 1017 |
+
"Ġshy": 924,
|
| 1018 |
+
"Ġsick": 925,
|
| 1019 |
+
"Ġsilence": 926,
|
| 1020 |
+
"Ġsilly": 927,
|
| 1021 |
+
"Ġsilver": 928,
|
| 1022 |
+
"Ġsincerely": 929,
|
| 1023 |
+
"Ġskeletons": 930,
|
| 1024 |
+
"Ġslate": 931,
|
| 1025 |
+
"Ġsleeping": 932,
|
| 1026 |
+
"Ġsleeve": 933,
|
| 1027 |
+
"Ġslow": 934,
|
| 1028 |
+
"Ġslowly": 935,
|
| 1029 |
+
"Ġsly": 936,
|
| 1030 |
+
"Ġsmall": 937,
|
| 1031 |
+
"Ġsnowing": 938,
|
| 1032 |
+
"Ġsometime": 939,
|
| 1033 |
+
"Ġsore": 940,
|
| 1034 |
+
"Ġsow": 941,
|
| 1035 |
+
"Ġspare": 942,
|
| 1036 |
+
"Ġspell": 943,
|
| 1037 |
+
"Ġspice": 944,
|
| 1038 |
+
"Ġspill": 945,
|
| 1039 |
+
"Ġspilled": 946,
|
| 1040 |
+
"Ġspots": 947,
|
| 1041 |
+
"Ġsquare": 948,
|
| 1042 |
+
"Ġsqueaky": 949,
|
| 1043 |
+
"Ġstand": 950,
|
| 1044 |
+
"Ġstart": 951,
|
| 1045 |
+
"Ġstarted": 952,
|
| 1046 |
+
"Ġsteady": 953,
|
| 1047 |
+
"Ġsteal": 954,
|
| 1048 |
+
"Ġsteam": 955,
|
| 1049 |
+
"Ġstill": 956,
|
| 1050 |
+
"Ġstitch": 957,
|
| 1051 |
+
"Ġstop": 958,
|
| 1052 |
+
"Ġstorm": 959,
|
| 1053 |
+
"Ġstory": 960,
|
| 1054 |
+
"Ġstraw": 961,
|
| 1055 |
+
"Ġstraws": 962,
|
| 1056 |
+
"Ġstrike": 963,
|
| 1057 |
+
"Ġstrong": 964,
|
| 1058 |
+
"Ġstronger": 965,
|
| 1059 |
+
"Ġstubborn": 966,
|
| 1060 |
+
"Ġsuch": 967,
|
| 1061 |
+
"Ġsun": 968,
|
| 1062 |
+
"Ġswallow": 969,
|
| 1063 |
+
"Ġsword": 970,
|
| 1064 |
+
"Ġtaken": 971,
|
| 1065 |
+
"Ġtalking": 972,
|
| 1066 |
+
"Ġtango": 973,
|
| 1067 |
+
"Ġtaste": 974,
|
| 1068 |
+
"Ġtea": 975,
|
| 1069 |
+
"Ġteach": 976,
|
| 1070 |
+
"Ġteeth": 977,
|
| 1071 |
+
"Ġthanksgiving": 978,
|
| 1072 |
+
"Ġthem": 979,
|
| 1073 |
+
"Ġthen": 980,
|
| 1074 |
+
"Ġthick": 981,
|
| 1075 |
+
"Ġthicker": 982,
|
| 1076 |
+
"Ġthirsty": 983,
|
| 1077 |
+
"Ġthorn": 984,
|
| 1078 |
+
"Ġthose": 985,
|
| 1079 |
+
"Ġthoughts": 986,
|
| 1080 |
+
"Ġthousand": 987,
|
| 1081 |
+
"Ġthrough": 988,
|
| 1082 |
+
"Ġthrow": 989,
|
| 1083 |
+
"Ġthumb": 990,
|
| 1084 |
+
"Ġthumbs": 991,
|
| 1085 |
+
"Ġthunder": 992,
|
| 1086 |
+
"Ġtie": 993,
|
| 1087 |
+
"Ġtight": 994,
|
| 1088 |
+
"Ġtip": 995,
|
| 1089 |
+
"Ġtongue": 996,
|
| 1090 |
+
"Ġtotally": 997,
|
| 1091 |
+
"Ġtowel": 998,
|
| 1092 |
+
"Ġtrades": 999,
|
| 1093 |
+
"Ġtrash": 1000,
|
| 1094 |
+
"Ġtreasure": 1001,
|
| 1095 |
+
"Ġtrees": 1002,
|
| 1096 |
+
"Ġtricks": 1003,
|
| 1097 |
+
"Ġtrust": 1004,
|
| 1098 |
+
"Ġtruth": 1005,
|
| 1099 |
+
"Ġtunnel": 1006,
|
| 1100 |
+
"Ġumbrella": 1007,
|
| 1101 |
+
"Ġunderstanding": 1008,
|
| 1102 |
+
"Ġunited": 1009,
|
| 1103 |
+
"Ġuntil": 1010,
|
| 1104 |
+
"Ġupdated": 1011,
|
| 1105 |
+
"Ġupon": 1012,
|
| 1106 |
+
"Ġvacation": 1013,
|
| 1107 |
+
"Ġvalentine": 1014,
|
| 1108 |
+
"Ġvariety": 1015,
|
| 1109 |
+
"Ġventured": 1016,
|
| 1110 |
+
"Ġvirtue": 1017,
|
| 1111 |
+
"Ġwalk": 1018,
|
| 1112 |
+
"Ġwall": 1019,
|
| 1113 |
+
"Ġwar": 1020,
|
| 1114 |
+
"Ġwarm": 1021,
|
| 1115 |
+
"Ġwasn": 1022,
|
| 1116 |
+
"Ġwatched": 1023,
|
| 1117 |
+
"Ġwaters": 1024,
|
| 1118 |
+
"Ġwealth": 1025,
|
| 1119 |
+
"Ġwedding": 1026,
|
| 1120 |
+
"Ġweight": 1027,
|
| 1121 |
+
"Ġwheel": 1028,
|
| 1122 |
+
"Ġwhite": 1029,
|
| 1123 |
+
"Ġwicked": 1030,
|
| 1124 |
+
"Ġwild": 1031,
|
| 1125 |
+
"Ġwin": 1032,
|
| 1126 |
+
"Ġwindow": 1033,
|
| 1127 |
+
"Ġwins": 1034,
|
| 1128 |
+
"Ġwishes": 1035,
|
| 1129 |
+
"Ġwishing": 1036,
|
| 1130 |
+
"Ġwolf": 1037,
|
| 1131 |
+
"Ġwonderful": 1038,
|
| 1132 |
+
"Ġword": 1039,
|
| 1133 |
+
"Ġworlds": 1040,
|
| 1134 |
+
"Ġworm": 1041,
|
| 1135 |
+
"Ġworried": 1042,
|
| 1136 |
+
"Ġworries": 1043,
|
| 1137 |
+
"Ġworse": 1044,
|
| 1138 |
+
"Ġworst": 1045,
|
| 1139 |
+
"Ġwounds": 1046,
|
| 1140 |
+
"Ġwow": 1047,
|
| 1141 |
+
"Ġwriting": 1048,
|
| 1142 |
+
"Ġwrongs": 1049,
|
| 1143 |
+
"Ġyards": 1050,
|
| 1144 |
+
"Ġyes": 1051,
|
| 1145 |
+
"Ġyours": 1052
|
| 1146 |
+
},
|
| 1147 |
+
"unk_token": "<unk>"
|
| 1148 |
+
}
|
| 1149 |
+
}
|
tokenizer_config.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"backend": "tokenizers",
|
| 3 |
+
"bos_token": "<|endoftext|>",
|
| 4 |
+
"clean_up_tokenization_spaces": false,
|
| 5 |
+
"eos_token": "<|endoftext|>",
|
| 6 |
+
"model_max_length": 128,
|
| 7 |
+
"pad_token": "<|endoftext|>",
|
| 8 |
+
"tokenizer_class": "PreTrainedTokenizerFast",
|
| 9 |
+
"unk_token": "<unk>",
|
| 10 |
+
"add_prefix_space": true,
|
| 11 |
+
"model_input_names": [
|
| 12 |
+
"input_ids",
|
| 13 |
+
"attention_mask"
|
| 14 |
+
]
|
| 15 |
+
}
|
ui.html
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!doctype html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="utf-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
| 6 |
+
<title>tiny-autocomplete</title>
|
| 7 |
+
<style>
|
| 8 |
+
:root { --bg: #fafaf9; --fg: #1c1917; --muted: #78716c; --line: #e7e5e4; --accent: #2563eb; --ghost: #a8a29e; --card: #fff; }
|
| 9 |
+
@media (prefers-color-scheme: dark) {
|
| 10 |
+
:root { --bg: #0c0a09; --fg: #f5f5f4; --muted: #a8a29e; --line: #292524; --accent: #60a5fa; --ghost: #57534e; --card: #1c1917; }
|
| 11 |
+
}
|
| 12 |
+
* { box-sizing: border-box; }
|
| 13 |
+
body { margin: 0; font: 16px/1.5 system-ui, -apple-system, sans-serif; background: var(--bg); color: var(--fg); }
|
| 14 |
+
main { max-width: 720px; margin: 0 auto; padding: 48px 20px; }
|
| 15 |
+
h1 { font-size: 24px; margin: 0 0 4px; }
|
| 16 |
+
.sub { color: var(--muted); margin: 0 0 28px; font-size: 14px; }
|
| 17 |
+
.editor { position: relative; background: var(--card); border: 1px solid var(--line); border-radius: 12px; }
|
| 18 |
+
.editor:focus-within { border-color: var(--accent); }
|
| 19 |
+
.layer { font: 20px/1.5 system-ui, -apple-system, sans-serif; padding: 16px 18px; margin: 0; white-space: pre-wrap; word-wrap: break-word; }
|
| 20 |
+
#ghost { position: absolute; inset: 0; pointer-events: none; color: transparent; }
|
| 21 |
+
#ghost span { color: var(--ghost); }
|
| 22 |
+
#prompt { position: relative; width: 100%; min-height: 64px; border: 0; outline: 0; resize: none; background: transparent; color: var(--fg); overflow: hidden; }
|
| 23 |
+
.hint { display: flex; justify-content: space-between; color: var(--muted); font-size: 13px; margin: 8px 2px 24px; }
|
| 24 |
+
kbd { border: 1px solid var(--line); border-radius: 4px; padding: 0 5px; font-size: 12px; background: var(--card); }
|
| 25 |
+
h2 { font-size: 13px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); margin: 0 0 10px; font-weight: 600; }
|
| 26 |
+
#next { display: grid; gap: 6px; margin-bottom: 28px; min-height: 40px; }
|
| 27 |
+
.cand { display: grid; grid-template-columns: 140px 1fr 56px; align-items: center; gap: 12px; padding: 6px 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--card); cursor: pointer; text-align: left; font: inherit; color: inherit; }
|
| 28 |
+
.cand:hover { border-color: var(--accent); }
|
| 29 |
+
.bar { height: 6px; border-radius: 3px; background: var(--line); overflow: hidden; }
|
| 30 |
+
.bar i { display: block; height: 100%; background: var(--accent); }
|
| 31 |
+
.pct { text-align: right; color: var(--muted); font-variant-numeric: tabular-nums; font-size: 14px; }
|
| 32 |
+
.tok { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 14px; white-space: pre; overflow: hidden; text-overflow: ellipsis; }
|
| 33 |
+
.examples { display: flex; flex-wrap: wrap; gap: 8px; }
|
| 34 |
+
.ex { border: 1px solid var(--line); background: var(--card); color: inherit; border-radius: 999px; padding: 4px 12px; font: inherit; font-size: 14px; cursor: pointer; }
|
| 35 |
+
.ex:hover { border-color: var(--accent); }
|
| 36 |
+
.empty { color: var(--muted); font-size: 14px; }
|
| 37 |
+
</style>
|
| 38 |
+
</head>
|
| 39 |
+
<body>
|
| 40 |
+
<main>
|
| 41 |
+
<h1>tiny-autocomplete</h1>
|
| 42 |
+
<p class="sub" id="info">A compiled (not trained) Llama-format model, running in plain TypeScript.</p>
|
| 43 |
+
|
| 44 |
+
<div class="editor">
|
| 45 |
+
<pre class="layer" id="ghost" aria-hidden="true"></pre>
|
| 46 |
+
<textarea class="layer" id="prompt" rows="1" placeholder="Start typing, e.g. Once upon a" autofocus spellcheck="false"></textarea>
|
| 47 |
+
</div>
|
| 48 |
+
<div class="hint">
|
| 49 |
+
<span><kbd>Tab</kbd> accept completion <kbd>Enter</kbd> accept next word</span>
|
| 50 |
+
<span id="status"></span>
|
| 51 |
+
</div>
|
| 52 |
+
|
| 53 |
+
<h2>Next word</h2>
|
| 54 |
+
<div id="next"><div class="empty">Type a prompt to see predictions.</div></div>
|
| 55 |
+
|
| 56 |
+
<h2>Try</h2>
|
| 57 |
+
<div class="examples" id="examples"></div>
|
| 58 |
+
</main>
|
| 59 |
+
<script>
|
| 60 |
+
var EXAMPLES = ["Once upon a", "The quick brown", "Thank you for", "I hope this email", "Can I have the",
|
| 61 |
+
"Actions speak", "How are", "Looking forward to", "Where is the", "Don't worry"];
|
| 62 |
+
var promptEl = document.getElementById("prompt");
|
| 63 |
+
var ghostEl = document.getElementById("ghost");
|
| 64 |
+
var nextEl = document.getElementById("next");
|
| 65 |
+
var statusEl = document.getElementById("status");
|
| 66 |
+
var latest = { completion: "", top: [] };
|
| 67 |
+
var seq = 0, timer = null;
|
| 68 |
+
|
| 69 |
+
function esc(s) { return s.replace(/[&<>]/g, function (c) { return { "&": "&", "<": "<", ">": ">" }[c]; }); }
|
| 70 |
+
|
| 71 |
+
function render() {
|
| 72 |
+
var text = promptEl.value;
|
| 73 |
+
ghostEl.innerHTML = esc(text) + "<span>" + esc(text ? latest.completion : "") + "</span>";
|
| 74 |
+
promptEl.style.height = "auto";
|
| 75 |
+
promptEl.style.height = Math.max(promptEl.scrollHeight, ghostEl.scrollHeight) + "px";
|
| 76 |
+
if (!text.trim() || !latest.top.length) {
|
| 77 |
+
nextEl.innerHTML = '<div class="empty">Type a prompt to see predictions.</div>';
|
| 78 |
+
return;
|
| 79 |
+
}
|
| 80 |
+
nextEl.innerHTML = "";
|
| 81 |
+
latest.top.forEach(function (t) {
|
| 82 |
+
var p = Math.exp(t.logprob) * 100;
|
| 83 |
+
var b = document.createElement("button");
|
| 84 |
+
b.className = "cand";
|
| 85 |
+
b.innerHTML = '<span class="tok"></span><span class="bar"><i style="width:' + p.toFixed(1) + '%"></i></span><span class="pct">' + p.toFixed(1) + "%</span>";
|
| 86 |
+
b.querySelector(".tok").textContent = t.id === 0 ? "<end>" : JSON.stringify(t.token);
|
| 87 |
+
b.onclick = function () { if (t.id !== 0) append(t.token); promptEl.focus(); };
|
| 88 |
+
nextEl.appendChild(b);
|
| 89 |
+
});
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
function append(s) { promptEl.value += s; latest = { completion: "", top: latest.top }; render(); schedule(0); }
|
| 93 |
+
|
| 94 |
+
function schedule(delay) {
|
| 95 |
+
clearTimeout(timer);
|
| 96 |
+
timer = setTimeout(run, delay);
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
function run() {
|
| 100 |
+
var id = ++seq, text = promptEl.value;
|
| 101 |
+
if (!text.trim()) { latest = { completion: "", top: [] }; statusEl.textContent = ""; render(); return; }
|
| 102 |
+
statusEl.textContent = "thinking...";
|
| 103 |
+
fetch("/api/complete", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ prompt: text, topK: 5 }) })
|
| 104 |
+
.then(function (r) { return r.json(); })
|
| 105 |
+
.then(function (r) {
|
| 106 |
+
if (id !== seq || promptEl.value !== text) return; // stale
|
| 107 |
+
if (r.error) { statusEl.textContent = r.error; return; }
|
| 108 |
+
latest = r;
|
| 109 |
+
statusEl.textContent = r.ms + " ms";
|
| 110 |
+
render();
|
| 111 |
+
})
|
| 112 |
+
.catch(function (e) { statusEl.textContent = String(e); });
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
promptEl.addEventListener("input", function () { latest = { completion: "", top: [] }; render(); schedule(200); });
|
| 116 |
+
promptEl.addEventListener("keydown", function (e) {
|
| 117 |
+
if (e.key === "Tab" && latest.completion) { e.preventDefault(); append(latest.completion); }
|
| 118 |
+
else if (e.key === "Enter") {
|
| 119 |
+
e.preventDefault();
|
| 120 |
+
var t = latest.top[0];
|
| 121 |
+
if (t && t.id !== 0) append(t.token);
|
| 122 |
+
}
|
| 123 |
+
});
|
| 124 |
+
|
| 125 |
+
EXAMPLES.forEach(function (ex) {
|
| 126 |
+
var b = document.createElement("button");
|
| 127 |
+
b.className = "ex"; b.textContent = ex;
|
| 128 |
+
b.onclick = function () { promptEl.value = ex; latest = { completion: "", top: [] }; render(); schedule(0); promptEl.focus(); };
|
| 129 |
+
document.getElementById("examples").appendChild(b);
|
| 130 |
+
});
|
| 131 |
+
|
| 132 |
+
fetch("/api/info").then(function (r) { return r.json(); }).then(function (i) {
|
| 133 |
+
document.getElementById("info").textContent = "A compiled (not trained) Llama-format model: " + i.params.toLocaleString() +
|
| 134 |
+
" parameters, " + i.vocab.toLocaleString() + " words, " + i.neurons.toLocaleString() + " n-gram neurons. Running in plain TypeScript.";
|
| 135 |
+
});
|
| 136 |
+
render();
|
| 137 |
+
</script>
|
| 138 |
+
</body>
|
| 139 |
+
</html>
|
ui.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Browser UI for trying prompts (zero dependencies).
|
| 2 |
+
//
|
| 3 |
+
// bun ui.ts then open http://localhost:3000
|
| 4 |
+
// PORT=8080 node ui.ts
|
| 5 |
+
//
|
| 6 |
+
// Serves ui.html and a JSON endpoint backed by the plain-TypeScript model in model.ts.
|
| 7 |
+
|
| 8 |
+
import { readFileSync } from "node:fs";
|
| 9 |
+
import { createServer } from "node:http";
|
| 10 |
+
import { join } from "node:path";
|
| 11 |
+
import { Autocompleter } from "./model.ts";
|
| 12 |
+
|
| 13 |
+
const DIR = import.meta.dirname ?? new URL(".", import.meta.url).pathname;
|
| 14 |
+
const PORT = Number(process.env.PORT ?? 3000);
|
| 15 |
+
|
| 16 |
+
console.log("Loading model...");
|
| 17 |
+
const ac = new Autocompleter(DIR);
|
| 18 |
+
const html = readFileSync(join(DIR, "ui.html"));
|
| 19 |
+
const cfg = ac.model.cfg;
|
| 20 |
+
const info = {
|
| 21 |
+
params: ac.model.numParams,
|
| 22 |
+
vocab: cfg.vocab_size,
|
| 23 |
+
layers: cfg.num_hidden_layers,
|
| 24 |
+
hidden: cfg.hidden_size,
|
| 25 |
+
neurons: cfg.intermediate_size,
|
| 26 |
+
};
|
| 27 |
+
|
| 28 |
+
function json(res: import("node:http").ServerResponse, status: number, body: unknown): void {
|
| 29 |
+
res.writeHead(status, { "content-type": "application/json" });
|
| 30 |
+
res.end(JSON.stringify(body));
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
createServer((req, res) => {
|
| 34 |
+
if (req.method === "GET" && (req.url === "/" || req.url === "/index.html")) {
|
| 35 |
+
res.writeHead(200, { "content-type": "text/html; charset=utf-8" });
|
| 36 |
+
res.end(html);
|
| 37 |
+
} else if (req.method === "GET" && req.url === "/api/info") {
|
| 38 |
+
json(res, 200, info);
|
| 39 |
+
} else if (req.method === "POST" && req.url === "/api/complete") {
|
| 40 |
+
let body = "";
|
| 41 |
+
req.on("data", (chunk) => (body += chunk));
|
| 42 |
+
req.on("end", () => {
|
| 43 |
+
try {
|
| 44 |
+
const { prompt, topK } = JSON.parse(body || "{}");
|
| 45 |
+
if (typeof prompt !== "string" || prompt.length > 1000) return json(res, 400, { error: "prompt must be a string under 1000 chars" });
|
| 46 |
+
const t0 = performance.now();
|
| 47 |
+
const result = prompt.trim() ? ac.complete(prompt, Math.min(Number(topK) || 5, 20)) : { prompt, completion: "", top: [] };
|
| 48 |
+
json(res, 200, { ...result, ms: Math.round(performance.now() - t0) });
|
| 49 |
+
} catch (e) {
|
| 50 |
+
json(res, 400, { error: String(e) });
|
| 51 |
+
}
|
| 52 |
+
});
|
| 53 |
+
} else {
|
| 54 |
+
res.writeHead(404).end();
|
| 55 |
+
}
|
| 56 |
+
}).listen(PORT, "127.0.0.1", () => console.log(`tiny-autocomplete UI: http://localhost:${PORT}`));
|