smallm 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +244 -0
  3. package/dist/benchmark.d.ts +10 -0
  4. package/dist/benchmark.d.ts.map +1 -0
  5. package/dist/benchmark.js +35 -0
  6. package/dist/benchmark.js.map +1 -0
  7. package/dist/cache-file.d.ts +40 -0
  8. package/dist/cache-file.d.ts.map +1 -0
  9. package/dist/cache-file.js +163 -0
  10. package/dist/cache-file.js.map +1 -0
  11. package/dist/cache.d.ts +23 -0
  12. package/dist/cache.d.ts.map +1 -0
  13. package/dist/cache.js +58 -0
  14. package/dist/cache.js.map +1 -0
  15. package/dist/cli.d.ts +32 -0
  16. package/dist/cli.d.ts.map +1 -0
  17. package/dist/cli.js +256 -0
  18. package/dist/cli.js.map +1 -0
  19. package/dist/data/benchmarks.json +61 -0
  20. package/dist/embeddings.d.ts +50 -0
  21. package/dist/embeddings.d.ts.map +1 -0
  22. package/dist/embeddings.js +118 -0
  23. package/dist/embeddings.js.map +1 -0
  24. package/dist/errors.d.ts +18 -0
  25. package/dist/errors.d.ts.map +1 -0
  26. package/dist/errors.js +42 -0
  27. package/dist/errors.js.map +1 -0
  28. package/dist/filters.d.ts +11 -0
  29. package/dist/filters.d.ts.map +1 -0
  30. package/dist/filters.js +66 -0
  31. package/dist/filters.js.map +1 -0
  32. package/dist/index.d.ts +52 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/index.js +110 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/params.d.ts +21 -0
  37. package/dist/params.d.ts.map +1 -0
  38. package/dist/params.js +50 -0
  39. package/dist/params.js.map +1 -0
  40. package/dist/query.d.ts +23 -0
  41. package/dist/query.d.ts.map +1 -0
  42. package/dist/query.js +81 -0
  43. package/dist/query.js.map +1 -0
  44. package/dist/registry/huggingface.d.ts +24 -0
  45. package/dist/registry/huggingface.d.ts.map +1 -0
  46. package/dist/registry/huggingface.js +97 -0
  47. package/dist/registry/huggingface.js.map +1 -0
  48. package/dist/registry/ollama.d.ts +3 -0
  49. package/dist/registry/ollama.d.ts.map +1 -0
  50. package/dist/registry/ollama.js +78 -0
  51. package/dist/registry/ollama.js.map +1 -0
  52. package/dist/registry/provider.d.ts +12 -0
  53. package/dist/registry/provider.d.ts.map +1 -0
  54. package/dist/registry/provider.js +3 -0
  55. package/dist/registry/provider.js.map +1 -0
  56. package/dist/scorer.d.ts +45 -0
  57. package/dist/scorer.d.ts.map +1 -0
  58. package/dist/scorer.js +161 -0
  59. package/dist/scorer.js.map +1 -0
  60. package/dist/types.d.ts +147 -0
  61. package/dist/types.d.ts.map +1 -0
  62. package/dist/types.js +8 -0
  63. package/dist/types.js.map +1 -0
  64. package/package.json +45 -0
package/dist/cli.d.ts ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+ import { ModelQuery, ModelMatch } from "./types";
3
+ /**
4
+ * Thin CLI wrapper around findModels(). Per the v0.5 guide's Do's/Don'ts:
5
+ * this file must contain NO scoring, filtering, or provider logic — only
6
+ * flag parsing (turning argv into a ModelQuery) and output formatting
7
+ * (turning a ModelMatch[] into text). All actual decisions — including
8
+ * input validation — are made by the library itself; this file just calls
9
+ * findModels() and displays whatever it returns or throws.
10
+ */
11
+ /** Thrown for usage problems (unknown flag, unknown command, --help). Caught in main(), never process.exit()'d from inside parseArgs itself — keeps parseArgs testable as a pure function. */
12
+ export declare class CliUsageError extends Error {
13
+ readonly exitCode: number;
14
+ constructor(message: string, exitCode?: number);
15
+ }
16
+ export interface ParsedCli {
17
+ query: ModelQuery;
18
+ json: boolean;
19
+ showHelp: boolean;
20
+ }
21
+ export declare const USAGE = "Usage: smallm find [options]\n\nRequired:\n --task <task> Task type (chat, summarize, classify, extract, code, translate, or any custom string)\n --context <tokens> Required context window, in tokens\n\nOptional (map 1:1 to ModelQuery fields):\n --max-params <billions> Hard filter, e.g. 7 = \"under 7B\"\n --domain <domain> Preferred domain tag, used in scoring only\n --hardware <cpu|gpu-low|gpu-high> Hardware hint (original string form)\n --hardware-type <cpu|gpu> Hardware type (structured form \u2014 use with --hardware-vram)\n --hardware-vram <gb> VRAM budget in GB (structured form only)\n --max-latency <ms> Enforced only when benchmark data exists for the (model, hardware) pair\n --scoring-mode <rule|embedding|hybrid> Scoring strategy (default: rule)\n --providers <list> Comma-separated, e.g. huggingface,ollama (default: huggingface)\n --limit <n> Max results (default: 5)\n --cache-dir <path> File cache directory\n --cache-ttl <ms> File cache TTL in ms\n\nOutput:\n --json Print raw ModelMatch[] JSON instead of a table\n\nExamples:\n npx smallm find --task summarize --context 4096\n npx smallm find --task chat --context 8192 --max-params 7 --json\n npx smallm find --task chat --context 4096 --providers huggingface,ollama --hardware-type gpu --hardware-vram 8\n";
22
+ /** Pure parser: argv (already sliced past "find") -> a ModelQuery + output mode. Never touches process.exit or the network. */
23
+ export declare function parseArgs(argv: string[]): ParsedCli;
24
+ /** Pure formatter: ModelMatch[] -> a human-readable table string. */
25
+ export declare function formatTable(results: ModelMatch[]): string;
26
+ /**
27
+ * Entry point. Only place in this file that touches process.exit/console —
28
+ * everything else (parseArgs, formatTable) is a pure, independently
29
+ * testable function.
30
+ */
31
+ export declare function main(argv: string[]): Promise<number>;
32
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEjD;;;;;;;GAOG;AAEH,8LAA8L;AAC9L,qBAAa,aAAc,SAAQ,KAAK;aACO,QAAQ,EAAE,MAAM;IAA7D,YAAY,OAAO,EAAE,MAAM,EAAkB,QAAQ,GAAE,MAAU,EAGhE;CACF;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,UAAU,CAAC;IAClB,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,eAAO,MAAM,KAAK,i6CA0BjB,CAAC;AAEF,+HAA+H;AAC/H,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAS,CAoInD;AAMD,qEAAqE;AACrE,wBAAgB,WAAW,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,CAmBzD;AAED;;;;GAIG;AACH,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA0C1D"}
package/dist/cli.js ADDED
@@ -0,0 +1,256 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.USAGE = exports.CliUsageError = void 0;
5
+ exports.parseArgs = parseArgs;
6
+ exports.formatTable = formatTable;
7
+ exports.main = main;
8
+ const index_1 = require("./index");
9
+ /**
10
+ * Thin CLI wrapper around findModels(). Per the v0.5 guide's Do's/Don'ts:
11
+ * this file must contain NO scoring, filtering, or provider logic — only
12
+ * flag parsing (turning argv into a ModelQuery) and output formatting
13
+ * (turning a ModelMatch[] into text). All actual decisions — including
14
+ * input validation — are made by the library itself; this file just calls
15
+ * findModels() and displays whatever it returns or throws.
16
+ */
17
+ /** Thrown for usage problems (unknown flag, unknown command, --help). Caught in main(), never process.exit()'d from inside parseArgs itself — keeps parseArgs testable as a pure function. */
18
+ class CliUsageError extends Error {
19
+ constructor(message, exitCode = 1) {
20
+ super(message);
21
+ this.exitCode = exitCode;
22
+ this.name = "CliUsageError";
23
+ }
24
+ }
25
+ exports.CliUsageError = CliUsageError;
26
+ exports.USAGE = `Usage: smallm find [options]
27
+
28
+ Required:
29
+ --task <task> Task type (chat, summarize, classify, extract, code, translate, or any custom string)
30
+ --context <tokens> Required context window, in tokens
31
+
32
+ Optional (map 1:1 to ModelQuery fields):
33
+ --max-params <billions> Hard filter, e.g. 7 = "under 7B"
34
+ --domain <domain> Preferred domain tag, used in scoring only
35
+ --hardware <cpu|gpu-low|gpu-high> Hardware hint (original string form)
36
+ --hardware-type <cpu|gpu> Hardware type (structured form — use with --hardware-vram)
37
+ --hardware-vram <gb> VRAM budget in GB (structured form only)
38
+ --max-latency <ms> Enforced only when benchmark data exists for the (model, hardware) pair
39
+ --scoring-mode <rule|embedding|hybrid> Scoring strategy (default: rule)
40
+ --providers <list> Comma-separated, e.g. huggingface,ollama (default: huggingface)
41
+ --limit <n> Max results (default: 5)
42
+ --cache-dir <path> File cache directory
43
+ --cache-ttl <ms> File cache TTL in ms
44
+
45
+ Output:
46
+ --json Print raw ModelMatch[] JSON instead of a table
47
+
48
+ Examples:
49
+ npx smallm find --task summarize --context 4096
50
+ npx smallm find --task chat --context 8192 --max-params 7 --json
51
+ npx smallm find --task chat --context 4096 --providers huggingface,ollama --hardware-type gpu --hardware-vram 8
52
+ `;
53
+ /** Pure parser: argv (already sliced past "find") -> a ModelQuery + output mode. Never touches process.exit or the network. */
54
+ function parseArgs(argv) {
55
+ const query = {};
56
+ let json = false;
57
+ let showHelp = false;
58
+ let hardwareType;
59
+ let hardwareVram;
60
+ let hardwareString;
61
+ let cacheDir;
62
+ let cacheTtl;
63
+ const takeValue = (flag, i) => {
64
+ const value = argv[i + 1];
65
+ if (value === undefined) {
66
+ throw new CliUsageError(`Flag ${flag} requires a value`);
67
+ }
68
+ return [value, i + 1];
69
+ };
70
+ for (let i = 0; i < argv.length; i++) {
71
+ const arg = argv[i];
72
+ switch (arg) {
73
+ case "--task": {
74
+ const [v, next] = takeValue(arg, i);
75
+ query.task = v;
76
+ i = next;
77
+ break;
78
+ }
79
+ case "--context": {
80
+ const [v, next] = takeValue(arg, i);
81
+ query.contextLength = Number(v);
82
+ i = next;
83
+ break;
84
+ }
85
+ case "--max-params": {
86
+ const [v, next] = takeValue(arg, i);
87
+ query.maxParamsB = Number(v);
88
+ i = next;
89
+ break;
90
+ }
91
+ case "--domain": {
92
+ const [v, next] = takeValue(arg, i);
93
+ query.domain = v;
94
+ i = next;
95
+ break;
96
+ }
97
+ case "--hardware": {
98
+ const [v, next] = takeValue(arg, i);
99
+ hardwareString = v;
100
+ i = next;
101
+ break;
102
+ }
103
+ case "--hardware-type": {
104
+ const [v, next] = takeValue(arg, i);
105
+ hardwareType = v;
106
+ i = next;
107
+ break;
108
+ }
109
+ case "--hardware-vram": {
110
+ const [v, next] = takeValue(arg, i);
111
+ hardwareVram = Number(v);
112
+ i = next;
113
+ break;
114
+ }
115
+ case "--max-latency": {
116
+ const [v, next] = takeValue(arg, i);
117
+ query.maxLatencyMs = Number(v);
118
+ i = next;
119
+ break;
120
+ }
121
+ case "--scoring-mode": {
122
+ const [v, next] = takeValue(arg, i);
123
+ query.scoringMode = v;
124
+ i = next;
125
+ break;
126
+ }
127
+ case "--providers": {
128
+ const [v, next] = takeValue(arg, i);
129
+ query.providers = v.split(",").map((s) => s.trim());
130
+ i = next;
131
+ break;
132
+ }
133
+ case "--limit": {
134
+ const [v, next] = takeValue(arg, i);
135
+ query.limit = Number(v);
136
+ i = next;
137
+ break;
138
+ }
139
+ case "--cache-dir": {
140
+ const [v, next] = takeValue(arg, i);
141
+ cacheDir = v;
142
+ i = next;
143
+ break;
144
+ }
145
+ case "--cache-ttl": {
146
+ const [v, next] = takeValue(arg, i);
147
+ cacheTtl = Number(v);
148
+ i = next;
149
+ break;
150
+ }
151
+ case "--json":
152
+ json = true;
153
+ break;
154
+ case "--help":
155
+ case "-h":
156
+ showHelp = true;
157
+ break;
158
+ default:
159
+ throw new CliUsageError(`Unknown flag: ${arg}`);
160
+ }
161
+ }
162
+ // Structured hardware form takes precedence if given; otherwise fall back
163
+ // to the string-enum form. Both map onto the exact same ModelQuery.hardware
164
+ // field the library already accepts — no new capability invented here.
165
+ if (hardwareType !== undefined) {
166
+ query.hardware = {
167
+ type: hardwareType,
168
+ ...(hardwareVram !== undefined ? { vramGB: hardwareVram } : {}),
169
+ };
170
+ }
171
+ else if (hardwareString !== undefined) {
172
+ query.hardware = hardwareString;
173
+ }
174
+ if (cacheDir !== undefined || cacheTtl !== undefined) {
175
+ query.cacheOptions = {
176
+ ...(cacheDir !== undefined ? { dir: cacheDir } : {}),
177
+ ...(cacheTtl !== undefined ? { ttlMs: cacheTtl } : {}),
178
+ };
179
+ }
180
+ return { query: query, json, showHelp };
181
+ }
182
+ function truncate(str, max) {
183
+ return str.length > max ? str.slice(0, max - 1) + "…" : str;
184
+ }
185
+ /** Pure formatter: ModelMatch[] -> a human-readable table string. */
186
+ function formatTable(results) {
187
+ if (results.length === 0) {
188
+ return "No matching models found.";
189
+ }
190
+ const columns = [
191
+ { header: "NAME", width: 42, get: (m) => truncate(m.name, 42) },
192
+ { header: "PROVIDER", width: 12, get: (m) => m.provider },
193
+ { header: "PARAMS(B)", width: 10, get: (m) => (m.paramsB == null ? "?" : String(m.paramsB)) },
194
+ { header: "SCORE", width: 6, get: (m) => String(m.score) },
195
+ { header: "MODE", width: 10, get: (m) => m.scoringMode ?? "rule" },
196
+ { header: "REASON", width: 50, get: (m) => truncate(m.reasonWhy, 50) },
197
+ ];
198
+ const headerRow = columns.map((c) => c.header.padEnd(c.width)).join(" ");
199
+ const separator = columns.map((c) => "-".repeat(c.width)).join(" ");
200
+ const rows = results.map((m) => columns.map((c) => c.get(m).padEnd(c.width)).join(" "));
201
+ return [headerRow, separator, ...rows].join("\n");
202
+ }
203
+ /**
204
+ * Entry point. Only place in this file that touches process.exit/console —
205
+ * everything else (parseArgs, formatTable) is a pure, independently
206
+ * testable function.
207
+ */
208
+ async function main(argv) {
209
+ if (argv.length === 0 || argv.includes("--help") || argv.includes("-h")) {
210
+ console.log(exports.USAGE);
211
+ return argv.length === 0 ? 1 : 0;
212
+ }
213
+ if (argv[0] !== "find") {
214
+ console.error(`Unknown command: "${argv[0]}". Only "find" is supported.\n`);
215
+ console.log(exports.USAGE);
216
+ return 1;
217
+ }
218
+ let parsed;
219
+ try {
220
+ parsed = parseArgs(argv.slice(1));
221
+ }
222
+ catch (err) {
223
+ if (err instanceof CliUsageError) {
224
+ console.error(`Error: ${err.message}\n`);
225
+ console.log(exports.USAGE);
226
+ return err.exitCode;
227
+ }
228
+ throw err;
229
+ }
230
+ if (parsed.showHelp) {
231
+ console.log(exports.USAGE);
232
+ return 0;
233
+ }
234
+ try {
235
+ // The one line that matters: flags in, library call, nothing invented.
236
+ const results = await (0, index_1.findModels)(parsed.query);
237
+ console.log(parsed.json ? JSON.stringify(results, null, 2) : formatTable(results));
238
+ return 0;
239
+ }
240
+ catch (err) {
241
+ if (err instanceof index_1.SmallmError) {
242
+ console.error(`Error: ${err.message}`);
243
+ }
244
+ else {
245
+ console.error("Unexpected error:", err);
246
+ }
247
+ return 1;
248
+ }
249
+ }
250
+ /* istanbul ignore next -- exercised via the compiled bin, not unit tests */
251
+ if (require.main === module) {
252
+ main(process.argv.slice(2)).then((code) => {
253
+ process.exitCode = code;
254
+ });
255
+ }
256
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ {
2
+ "version": 1,
3
+ "entries": [
4
+ {
5
+ "modelId": "meta-llama/Llama-3-8B-Instruct",
6
+ "hardware": "gpu-low",
7
+ "avgLatencyMs": 850,
8
+ "measuredAt": "2026-08-01",
9
+ "promptTokens": 512,
10
+ "outputTokens": 256
11
+ },
12
+ {
13
+ "modelId": "meta-llama/Llama-3-8B-Instruct",
14
+ "hardware": "gpu-high",
15
+ "avgLatencyMs": 320,
16
+ "measuredAt": "2026-08-01",
17
+ "promptTokens": 512,
18
+ "outputTokens": 256
19
+ },
20
+ {
21
+ "modelId": "meta-llama/Llama-3-8B-Instruct",
22
+ "hardware": "cpu",
23
+ "avgLatencyMs": 9800,
24
+ "measuredAt": "2026-08-01",
25
+ "promptTokens": 512,
26
+ "outputTokens": 256
27
+ },
28
+ {
29
+ "modelId": "TinyLlama/TinyLlama-1.1B-Chat-v1.0",
30
+ "hardware": "cpu",
31
+ "avgLatencyMs": 1400,
32
+ "measuredAt": "2026-08-01",
33
+ "promptTokens": 512,
34
+ "outputTokens": 256
35
+ },
36
+ {
37
+ "modelId": "TinyLlama/TinyLlama-1.1B-Chat-v1.0",
38
+ "hardware": "gpu-low",
39
+ "avgLatencyMs": 180,
40
+ "measuredAt": "2026-08-01",
41
+ "promptTokens": 512,
42
+ "outputTokens": 256
43
+ },
44
+ {
45
+ "modelId": "mistralai/Mistral-7B-Instruct-v0.3",
46
+ "hardware": "gpu-low",
47
+ "avgLatencyMs": 790,
48
+ "measuredAt": "2026-08-01",
49
+ "promptTokens": 512,
50
+ "outputTokens": 256
51
+ },
52
+ {
53
+ "modelId": "mistralai/Mistral-7B-Instruct-v0.3",
54
+ "hardware": "gpu-high",
55
+ "avgLatencyMs": 290,
56
+ "measuredAt": "2026-08-01",
57
+ "promptTokens": 512,
58
+ "outputTokens": 256
59
+ }
60
+ ]
61
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * A small, local, dependency-free text embedding scheme.
3
+ *
4
+ * WHY NOT A REAL NEURAL EMBEDDING MODEL: a genuine pretrained sentence
5
+ * embedding model (e.g. all-MiniLM-L6-v2 via transformers.js) needs to
6
+ * download model weights from HuggingFace at install/first-run time. This
7
+ * package's build/test environment can't verify that network path, so
8
+ * rather than ship an unverified dependency, this is a self-authored
9
+ * character-trigram hashing vectorizer + cosine similarity — a classic,
10
+ * well-understood, fully offline technique with zero external dependencies
11
+ * or license concerns (original code).
12
+ *
13
+ * TRADE-OFF: this captures lexical/surface similarity (shared substrings),
14
+ * not deep semantic meaning. "extract key-value pairs from invoices" and
15
+ * "structured data extraction" would score lower here than they would with
16
+ * a real neural embedding, since they share few character sequences despite
17
+ * being semantically close. Swap in a real model later by replacing embed()
18
+ * with one backed by transformers.js (or similar) — cosineSimilarity() and
19
+ * every caller of embed() would keep working unchanged, since only the
20
+ * vector-production step would change.
21
+ *
22
+ * SWAP-IN NOTE (build order step 6, "benchmark embedding-mode latency —
23
+ * feed into v0.2's benchmark dataset if relevant"): that benchmark dataset
24
+ * (src/data/benchmarks.json) measures LLM *inference* latency per
25
+ * (model, hardware) — a real, meaningful cost that varies by model size and
26
+ * hardware. This embedding scheme is a synchronous, local, sub-millisecond
27
+ * hash computation with no model inference involved, so there's no
28
+ * per-(model, hardware) latency to record there — "not relevant" for this
29
+ * implementation. See test/embeddings.test.ts's performance sanity check
30
+ * for a concrete timing figure instead. If embed() is ever swapped for a
31
+ * real neural embedding model (see the trade-off note above), *that* would
32
+ * introduce real inference latency worth feeding into the benchmark dataset.
33
+ */
34
+ /**
35
+ * Produces a fixed-length (VECTOR_DIM), L2-normalized vector for the given
36
+ * text using hashed character-trigram counts. Deterministic: same text
37
+ * always produces the same vector.
38
+ */
39
+ export declare function embed(text: string): number[];
40
+ /**
41
+ * Cosine similarity between two equal-length vectors, in [0, 1] for these
42
+ * non-negative count-based vectors (in [-1, 1] in general). Since embed()
43
+ * always L2-normalizes, this is just the dot product.
44
+ */
45
+ export declare function cosineSimilarity(a: number[], b: number[]): number;
46
+ /** Exposed for tests. */
47
+ export declare function clearEmbeddingCache(): void;
48
+ /** Exposed for tests/debugging. */
49
+ export declare function embeddingCacheSize(): number;
50
+ //# sourceMappingURL=embeddings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeddings.d.ts","sourceRoot":"","sources":["../src/embeddings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAwCH;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAmB5C;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAOjE;AAED,yBAAyB;AACzB,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAED,mCAAmC;AACnC,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C"}
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ /**
3
+ * A small, local, dependency-free text embedding scheme.
4
+ *
5
+ * WHY NOT A REAL NEURAL EMBEDDING MODEL: a genuine pretrained sentence
6
+ * embedding model (e.g. all-MiniLM-L6-v2 via transformers.js) needs to
7
+ * download model weights from HuggingFace at install/first-run time. This
8
+ * package's build/test environment can't verify that network path, so
9
+ * rather than ship an unverified dependency, this is a self-authored
10
+ * character-trigram hashing vectorizer + cosine similarity — a classic,
11
+ * well-understood, fully offline technique with zero external dependencies
12
+ * or license concerns (original code).
13
+ *
14
+ * TRADE-OFF: this captures lexical/surface similarity (shared substrings),
15
+ * not deep semantic meaning. "extract key-value pairs from invoices" and
16
+ * "structured data extraction" would score lower here than they would with
17
+ * a real neural embedding, since they share few character sequences despite
18
+ * being semantically close. Swap in a real model later by replacing embed()
19
+ * with one backed by transformers.js (or similar) — cosineSimilarity() and
20
+ * every caller of embed() would keep working unchanged, since only the
21
+ * vector-production step would change.
22
+ *
23
+ * SWAP-IN NOTE (build order step 6, "benchmark embedding-mode latency —
24
+ * feed into v0.2's benchmark dataset if relevant"): that benchmark dataset
25
+ * (src/data/benchmarks.json) measures LLM *inference* latency per
26
+ * (model, hardware) — a real, meaningful cost that varies by model size and
27
+ * hardware. This embedding scheme is a synchronous, local, sub-millisecond
28
+ * hash computation with no model inference involved, so there's no
29
+ * per-(model, hardware) latency to record there — "not relevant" for this
30
+ * implementation. See test/embeddings.test.ts's performance sanity check
31
+ * for a concrete timing figure instead. If embed() is ever swapped for a
32
+ * real neural embedding model (see the trade-off note above), *that* would
33
+ * introduce real inference latency worth feeding into the benchmark dataset.
34
+ */
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.embed = embed;
37
+ exports.cosineSimilarity = cosineSimilarity;
38
+ exports.clearEmbeddingCache = clearEmbeddingCache;
39
+ exports.embeddingCacheSize = embeddingCacheSize;
40
+ const VECTOR_DIM = 256;
41
+ const MAX_CACHE_SIZE = 500;
42
+ /** djb2 string hash — fast, deterministic, decent distribution for this use. */
43
+ function hashString(s) {
44
+ let hash = 5381;
45
+ for (let i = 0; i < s.length; i++) {
46
+ hash = ((hash << 5) + hash + s.charCodeAt(i)) >>> 0;
47
+ }
48
+ return hash;
49
+ }
50
+ function normalizeText(text) {
51
+ return text
52
+ .toLowerCase()
53
+ .replace(/[^a-z0-9\s]/g, " ")
54
+ .replace(/\s+/g, " ")
55
+ .trim();
56
+ }
57
+ function charTrigrams(text) {
58
+ const padded = ` ${normalizeText(text)} `;
59
+ const grams = [];
60
+ for (let i = 0; i < padded.length - 2; i++) {
61
+ grams.push(padded.slice(i, i + 3));
62
+ }
63
+ return grams;
64
+ }
65
+ /**
66
+ * Cache of computed embeddings, keyed by exact input text. Per the v0.3
67
+ * Do's/Don'ts ("don't recompute embeddings for the same model description
68
+ * on every call"), repeated calls with identical text are served from here
69
+ * instead of re-hashing. Simple FIFO eviction once MAX_CACHE_SIZE is hit —
70
+ * this is a small in-process cache, not meant to be a durable store.
71
+ */
72
+ const embeddingCache = new Map();
73
+ /**
74
+ * Produces a fixed-length (VECTOR_DIM), L2-normalized vector for the given
75
+ * text using hashed character-trigram counts. Deterministic: same text
76
+ * always produces the same vector.
77
+ */
78
+ function embed(text) {
79
+ const cached = embeddingCache.get(text);
80
+ if (cached)
81
+ return cached;
82
+ const vector = new Array(VECTOR_DIM).fill(0);
83
+ for (const gram of charTrigrams(text)) {
84
+ vector[hashString(gram) % VECTOR_DIM] += 1;
85
+ }
86
+ const norm = Math.sqrt(vector.reduce((sum, v) => sum + v * v, 0));
87
+ const normalized = norm > 0 ? vector.map((v) => v / norm) : vector;
88
+ if (embeddingCache.size >= MAX_CACHE_SIZE) {
89
+ const oldestKey = embeddingCache.keys().next().value;
90
+ if (oldestKey !== undefined)
91
+ embeddingCache.delete(oldestKey);
92
+ }
93
+ embeddingCache.set(text, normalized);
94
+ return normalized;
95
+ }
96
+ /**
97
+ * Cosine similarity between two equal-length vectors, in [0, 1] for these
98
+ * non-negative count-based vectors (in [-1, 1] in general). Since embed()
99
+ * always L2-normalizes, this is just the dot product.
100
+ */
101
+ function cosineSimilarity(a, b) {
102
+ if (a.length !== b.length) {
103
+ throw new Error(`Vectors must be the same length (got ${a.length} and ${b.length})`);
104
+ }
105
+ let dot = 0;
106
+ for (let i = 0; i < a.length; i++)
107
+ dot += a[i] * b[i];
108
+ return dot;
109
+ }
110
+ /** Exposed for tests. */
111
+ function clearEmbeddingCache() {
112
+ embeddingCache.clear();
113
+ }
114
+ /** Exposed for tests/debugging. */
115
+ function embeddingCacheSize() {
116
+ return embeddingCache.size;
117
+ }
118
+ //# sourceMappingURL=embeddings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../src/embeddings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /** Base class for every error smallm throws. Lets callers do `instanceof SmallmError`. */
2
+ export declare class SmallmError extends Error {
3
+ constructor(message: string);
4
+ }
5
+ /** Non-2xx response from the HuggingFace API (excluding the 429 case, see RateLimitError). */
6
+ export declare class HFApiError extends SmallmError {
7
+ readonly status?: number | undefined;
8
+ constructor(message: string, status?: number | undefined);
9
+ }
10
+ /** Specifically a 429 from HuggingFace. Triggers retry/backoff — see registry/huggingface.ts. */
11
+ export declare class RateLimitError extends HFApiError {
12
+ constructor(message: string, status?: number);
13
+ }
14
+ /** Bad ModelQuery input. Never retried — a malformed request will never succeed by retrying. */
15
+ export declare class ValidationError extends SmallmError {
16
+ constructor(message: string);
17
+ }
18
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,qBAAa,WAAY,SAAQ,KAAK;IACpC,YAAY,OAAO,EAAE,MAAM,EAK1B;CACF;AAED,8FAA8F;AAC9F,qBAAa,UAAW,SAAQ,WAAW;aACI,MAAM,CAAC,EAAE,MAAM;IAA5D,YAAY,OAAO,EAAE,MAAM,EAAkB,MAAM,CAAC,EAAE,MAAM,YAAA,EAI3D;CACF;AAED,iGAAiG;AACjG,qBAAa,cAAe,SAAQ,UAAU;IAC5C,YAAY,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,MAAY,EAIhD;CACF;AAED,gGAAgG;AAChG,qBAAa,eAAgB,SAAQ,WAAW;IAC9C,YAAY,OAAO,EAAE,MAAM,EAI1B;CACF"}
package/dist/errors.js ADDED
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ValidationError = exports.RateLimitError = exports.HFApiError = exports.SmallmError = void 0;
4
+ /** Base class for every error smallm throws. Lets callers do `instanceof SmallmError`. */
5
+ class SmallmError extends Error {
6
+ constructor(message) {
7
+ super(message);
8
+ this.name = "SmallmError";
9
+ // Restore prototype chain (needed when compiling to older targets / extending Error in TS).
10
+ Object.setPrototypeOf(this, new.target.prototype);
11
+ }
12
+ }
13
+ exports.SmallmError = SmallmError;
14
+ /** Non-2xx response from the HuggingFace API (excluding the 429 case, see RateLimitError). */
15
+ class HFApiError extends SmallmError {
16
+ constructor(message, status) {
17
+ super(message);
18
+ this.status = status;
19
+ this.name = "HFApiError";
20
+ Object.setPrototypeOf(this, new.target.prototype);
21
+ }
22
+ }
23
+ exports.HFApiError = HFApiError;
24
+ /** Specifically a 429 from HuggingFace. Triggers retry/backoff — see registry/huggingface.ts. */
25
+ class RateLimitError extends HFApiError {
26
+ constructor(message, status = 429) {
27
+ super(message, status);
28
+ this.name = "RateLimitError";
29
+ Object.setPrototypeOf(this, new.target.prototype);
30
+ }
31
+ }
32
+ exports.RateLimitError = RateLimitError;
33
+ /** Bad ModelQuery input. Never retried — a malformed request will never succeed by retrying. */
34
+ class ValidationError extends SmallmError {
35
+ constructor(message) {
36
+ super(message);
37
+ this.name = "ValidationError";
38
+ Object.setPrototypeOf(this, new.target.prototype);
39
+ }
40
+ }
41
+ exports.ValidationError = ValidationError;
42
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;;AAAA,0FAA0F;AAC1F,iBAAyB,SAAQ,KAAK;IACpC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,4FAA4F;QAC5F,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACF;;AAED,8FAA8F;AAC9F,gBAAwB,SAAQ,WAAW;IACzC,YAAY,OAAe,EAAkB,MAAe;QAC1D,KAAK,CAAC,OAAO,CAAC,CAAC;sBAD4B,MAAM;QAEjD,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;QACzB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACF;;AAED,iGAAiG;AACjG,oBAA4B,SAAQ,UAAU;IAC5C,YAAY,OAAe,EAAE,MAAM,GAAW,GAAG;QAC/C,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACF;;AAED,gGAAgG;AAChG,qBAA6B,SAAQ,WAAW;IAC9C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACF"}
@@ -0,0 +1,11 @@
1
+ import { HFModel, ModelQuery } from "./types";
2
+ /**
3
+ * Applies hard filters before any scoring happens. A model failing ANY
4
+ * filter is excluded outright — it never reaches scorer.ts. Unknown values
5
+ * never cause exclusion (MVP Section 4.4's rule, carried forward per the
6
+ * v0.2/v0.3/v0.4 guides' "unknown data is never punished" cross-phase
7
+ * principle). Provider-agnostic throughout — never branches on
8
+ * model.provider (v0.4 Do's/Don'ts).
9
+ */
10
+ export declare function applyHardFilters(models: HFModel[], query: ModelQuery): HFModel[];
11
+ //# sourceMappingURL=filters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filters.d.ts","sourceRoot":"","sources":["../src/filters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAe9C;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,EAAE,CAiDhF"}