@houtini/lm 2.4.1 → 2.8.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.
- package/README.md +206 -30
- package/dist/index.js +687 -57
- package/dist/index.js.map +1 -1
- package/dist/model-cache.d.ts +95 -0
- package/dist/model-cache.js +557 -0
- package/dist/model-cache.js.map +1 -0
- package/package.json +5 -3
- package/server.json +44 -44
|
@@ -0,0 +1,557 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite-backed model profile cache.
|
|
3
|
+
*
|
|
4
|
+
* On startup, houtini-lm fetches available models from the LLM server and
|
|
5
|
+
* looks up each one on HuggingFace's free API. The results are cached in a
|
|
6
|
+
* local SQLite database so subsequent startups are instant (no network).
|
|
7
|
+
*
|
|
8
|
+
* Uses sql.js (pure WASM) — zero native deps, works everywhere.
|
|
9
|
+
*/
|
|
10
|
+
import initSqlJs from 'sql.js';
|
|
11
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
import { homedir } from 'node:os';
|
|
14
|
+
const PROMPT_HINTS = [
|
|
15
|
+
{
|
|
16
|
+
pattern: /glm[- ]?4/i,
|
|
17
|
+
hints: {
|
|
18
|
+
codeTemp: 0.1,
|
|
19
|
+
chatTemp: 0.3,
|
|
20
|
+
outputConstraint: 'Respond with ONLY the requested output. No step-by-step reasoning. No preamble. Use markdown formatting: bullet points for lists, fenced code blocks for code.',
|
|
21
|
+
bestTaskTypes: ['chat', 'analysis'],
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
pattern: /qwen3.*coder|qwen.*coder/i,
|
|
26
|
+
hints: {
|
|
27
|
+
codeTemp: 0.1,
|
|
28
|
+
chatTemp: 0.3,
|
|
29
|
+
outputConstraint: 'Be direct. Output only what was asked for. Use markdown formatting: bullet points for lists, fenced code blocks for code. No preamble.',
|
|
30
|
+
bestTaskTypes: ['code'],
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
pattern: /qwen3(?!.*coder)(?!.*vl)/i,
|
|
35
|
+
hints: {
|
|
36
|
+
codeTemp: 0.2,
|
|
37
|
+
chatTemp: 0.3,
|
|
38
|
+
outputConstraint: 'Be direct. Output only what was asked for. Use markdown formatting: bullet points for lists, fenced code blocks for code. No preamble.',
|
|
39
|
+
bestTaskTypes: ['chat', 'analysis', 'code'],
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
pattern: /llama[- ]?3/i,
|
|
44
|
+
hints: {
|
|
45
|
+
codeTemp: 0.2,
|
|
46
|
+
chatTemp: 0.4,
|
|
47
|
+
outputConstraint: '',
|
|
48
|
+
bestTaskTypes: ['chat', 'code', 'analysis'],
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
pattern: /nemotron/i,
|
|
53
|
+
hints: {
|
|
54
|
+
codeTemp: 0.1,
|
|
55
|
+
chatTemp: 0.3,
|
|
56
|
+
outputConstraint: '',
|
|
57
|
+
bestTaskTypes: ['analysis', 'code'],
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
pattern: /granite/i,
|
|
62
|
+
hints: {
|
|
63
|
+
codeTemp: 0.2,
|
|
64
|
+
chatTemp: 0.3,
|
|
65
|
+
outputConstraint: '',
|
|
66
|
+
bestTaskTypes: ['code', 'chat'],
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
pattern: /gpt[- ]?oss/i,
|
|
71
|
+
hints: {
|
|
72
|
+
codeTemp: 0.2,
|
|
73
|
+
chatTemp: 0.4,
|
|
74
|
+
outputConstraint: '',
|
|
75
|
+
bestTaskTypes: ['chat', 'code', 'analysis'],
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
pattern: /nomic.*embed|embed.*nomic/i,
|
|
80
|
+
hints: {
|
|
81
|
+
codeTemp: 0,
|
|
82
|
+
chatTemp: 0,
|
|
83
|
+
outputConstraint: '',
|
|
84
|
+
bestTaskTypes: ['embedding'],
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
];
|
|
88
|
+
/**
|
|
89
|
+
* Get prompt hints for a model by ID or architecture.
|
|
90
|
+
*/
|
|
91
|
+
export function getPromptHints(modelId, arch) {
|
|
92
|
+
for (const { pattern, hints } of PROMPT_HINTS) {
|
|
93
|
+
if (pattern.test(modelId))
|
|
94
|
+
return hints;
|
|
95
|
+
if (arch && pattern.test(arch))
|
|
96
|
+
return hints;
|
|
97
|
+
}
|
|
98
|
+
// Sensible defaults for unknown models
|
|
99
|
+
return {
|
|
100
|
+
codeTemp: 0.2,
|
|
101
|
+
chatTemp: 0.3,
|
|
102
|
+
outputConstraint: '',
|
|
103
|
+
bestTaskTypes: ['chat', 'code', 'analysis'],
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
// ── Constants ────────────────────────────────────────────────────────
|
|
107
|
+
const DB_DIR = join(homedir(), '.houtini-lm');
|
|
108
|
+
const DB_PATH = join(DB_DIR, 'model-cache.db');
|
|
109
|
+
const CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
|
|
110
|
+
const HF_TIMEOUT_MS = 8000;
|
|
111
|
+
// ── Database ─────────────────────────────────────────────────────────
|
|
112
|
+
let db = null;
|
|
113
|
+
export async function initDb() {
|
|
114
|
+
if (db)
|
|
115
|
+
return db;
|
|
116
|
+
const SQL = await initSqlJs();
|
|
117
|
+
// Load existing DB from disk if it exists
|
|
118
|
+
if (existsSync(DB_PATH)) {
|
|
119
|
+
try {
|
|
120
|
+
const buf = readFileSync(DB_PATH);
|
|
121
|
+
db = new SQL.Database(buf);
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
// Corrupt DB — start fresh
|
|
125
|
+
db = new SQL.Database();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
db = new SQL.Database();
|
|
130
|
+
}
|
|
131
|
+
// Create table if not exists
|
|
132
|
+
db.run(`
|
|
133
|
+
CREATE TABLE IF NOT EXISTS model_profiles (
|
|
134
|
+
model_id TEXT PRIMARY KEY,
|
|
135
|
+
hf_id TEXT,
|
|
136
|
+
pipeline_tag TEXT,
|
|
137
|
+
architectures TEXT,
|
|
138
|
+
license TEXT,
|
|
139
|
+
downloads INTEGER,
|
|
140
|
+
likes INTEGER,
|
|
141
|
+
library_name TEXT,
|
|
142
|
+
family TEXT,
|
|
143
|
+
description TEXT,
|
|
144
|
+
strengths TEXT,
|
|
145
|
+
weaknesses TEXT,
|
|
146
|
+
best_for TEXT,
|
|
147
|
+
emits_think_blocks INTEGER NOT NULL DEFAULT 0,
|
|
148
|
+
supports_thinking_toggle INTEGER NOT NULL DEFAULT 0,
|
|
149
|
+
fetched_at INTEGER NOT NULL,
|
|
150
|
+
source TEXT NOT NULL DEFAULT 'huggingface'
|
|
151
|
+
)
|
|
152
|
+
`);
|
|
153
|
+
// Migrate: add thinking columns if upgrading from older schema
|
|
154
|
+
try {
|
|
155
|
+
db.run('ALTER TABLE model_profiles ADD COLUMN emits_think_blocks INTEGER NOT NULL DEFAULT 0');
|
|
156
|
+
}
|
|
157
|
+
catch { /* column already exists */ }
|
|
158
|
+
try {
|
|
159
|
+
db.run('ALTER TABLE model_profiles ADD COLUMN supports_thinking_toggle INTEGER NOT NULL DEFAULT 0');
|
|
160
|
+
}
|
|
161
|
+
catch { /* column already exists */ }
|
|
162
|
+
return db;
|
|
163
|
+
}
|
|
164
|
+
function saveDb() {
|
|
165
|
+
if (!db)
|
|
166
|
+
return;
|
|
167
|
+
try {
|
|
168
|
+
mkdirSync(DB_DIR, { recursive: true });
|
|
169
|
+
const data = db.export();
|
|
170
|
+
writeFileSync(DB_PATH, Buffer.from(data));
|
|
171
|
+
}
|
|
172
|
+
catch (err) {
|
|
173
|
+
process.stderr.write(`[houtini-lm] Failed to save model cache: ${err}\n`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
// ── Cache operations ─────────────────────────────────────────────────
|
|
177
|
+
export async function getCachedProfile(modelId) {
|
|
178
|
+
const database = await initDb();
|
|
179
|
+
const stmt = database.prepare('SELECT * FROM model_profiles WHERE model_id = ?');
|
|
180
|
+
try {
|
|
181
|
+
stmt.bind([modelId]);
|
|
182
|
+
if (stmt.step()) {
|
|
183
|
+
const row = stmt.getAsObject();
|
|
184
|
+
return {
|
|
185
|
+
modelId: row.model_id,
|
|
186
|
+
hfId: row.hf_id,
|
|
187
|
+
pipelineTag: row.pipeline_tag,
|
|
188
|
+
architectures: row.architectures,
|
|
189
|
+
license: row.license,
|
|
190
|
+
downloads: row.downloads,
|
|
191
|
+
likes: row.likes,
|
|
192
|
+
libraryName: row.library_name,
|
|
193
|
+
family: row.family,
|
|
194
|
+
description: row.description,
|
|
195
|
+
strengths: row.strengths,
|
|
196
|
+
weaknesses: row.weaknesses,
|
|
197
|
+
bestFor: row.best_for,
|
|
198
|
+
emitsThinkBlocks: !!row.emits_think_blocks,
|
|
199
|
+
supportsThinkingToggle: !!row.supports_thinking_toggle,
|
|
200
|
+
fetchedAt: row.fetched_at,
|
|
201
|
+
source: row.source,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
finally {
|
|
207
|
+
stmt.free();
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Insert or update a profile in the DB. Saves to disk immediately by default.
|
|
212
|
+
* Pass skipSave=true during batch operations, then call flushDb() when done.
|
|
213
|
+
*/
|
|
214
|
+
export async function upsertProfile(profile, skipSave = false) {
|
|
215
|
+
const database = await initDb();
|
|
216
|
+
database.run(`INSERT OR REPLACE INTO model_profiles
|
|
217
|
+
(model_id, hf_id, pipeline_tag, architectures, license, downloads, likes, library_name,
|
|
218
|
+
family, description, strengths, weaknesses, best_for, emits_think_blocks, supports_thinking_toggle, fetched_at, source)
|
|
219
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
220
|
+
profile.modelId,
|
|
221
|
+
profile.hfId,
|
|
222
|
+
profile.pipelineTag,
|
|
223
|
+
profile.architectures,
|
|
224
|
+
profile.license,
|
|
225
|
+
profile.downloads,
|
|
226
|
+
profile.likes,
|
|
227
|
+
profile.libraryName,
|
|
228
|
+
profile.family,
|
|
229
|
+
profile.description,
|
|
230
|
+
profile.strengths,
|
|
231
|
+
profile.weaknesses,
|
|
232
|
+
profile.bestFor,
|
|
233
|
+
profile.emitsThinkBlocks ? 1 : 0,
|
|
234
|
+
profile.supportsThinkingToggle ? 1 : 0,
|
|
235
|
+
profile.fetchedAt,
|
|
236
|
+
profile.source,
|
|
237
|
+
]);
|
|
238
|
+
if (!skipSave)
|
|
239
|
+
saveDb();
|
|
240
|
+
}
|
|
241
|
+
/** Flush DB to disk. Call after batch upsertProfile(…, true) operations. */
|
|
242
|
+
export function flushDb() {
|
|
243
|
+
saveDb();
|
|
244
|
+
}
|
|
245
|
+
export function isCacheStale(profile) {
|
|
246
|
+
return Date.now() - profile.fetchedAt > CACHE_TTL_MS;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Convert a cached profile to the ModelProfile format used by the rest of the app.
|
|
250
|
+
*/
|
|
251
|
+
export function toModelProfile(cached) {
|
|
252
|
+
if (!cached.family || !cached.description)
|
|
253
|
+
return null;
|
|
254
|
+
return {
|
|
255
|
+
family: cached.family,
|
|
256
|
+
description: cached.description,
|
|
257
|
+
strengths: cached.strengths ? JSON.parse(cached.strengths) : [],
|
|
258
|
+
weaknesses: cached.weaknesses ? JSON.parse(cached.weaknesses) : [],
|
|
259
|
+
bestFor: cached.bestFor ? JSON.parse(cached.bestFor) : [],
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Detect thinking/reasoning support from HF model metadata.
|
|
264
|
+
* Checks the chat_template for enable_thinking and <think> patterns,
|
|
265
|
+
* rather than hardcoding per-family knowledge.
|
|
266
|
+
*/
|
|
267
|
+
function detectThinkingSupport(card) {
|
|
268
|
+
const chatTemplate = card.config?.tokenizer_config?.chat_template || '';
|
|
269
|
+
// Does the template reference <think> blocks at all?
|
|
270
|
+
const emitsThinkBlocks = /<think>/.test(chatTemplate) || /thinking/.test(chatTemplate.toLowerCase());
|
|
271
|
+
// Does the template support enable_thinking toggle? (Qwen3 pattern)
|
|
272
|
+
const supportsThinkingToggle = /enable_thinking/.test(chatTemplate);
|
|
273
|
+
return { emitsThinkBlocks, supportsThinkingToggle };
|
|
274
|
+
}
|
|
275
|
+
async function fetchHF(url) {
|
|
276
|
+
const controller = new AbortController();
|
|
277
|
+
const timer = setTimeout(() => controller.abort(), HF_TIMEOUT_MS);
|
|
278
|
+
try {
|
|
279
|
+
return await fetch(url, { headers: { Accept: 'application/json' }, signal: controller.signal });
|
|
280
|
+
}
|
|
281
|
+
finally {
|
|
282
|
+
clearTimeout(timer);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Try to find a model on HuggingFace given a local model ID and optional publisher.
|
|
287
|
+
* Returns the HF card or null.
|
|
288
|
+
*/
|
|
289
|
+
async function lookupHF(modelId, publisher) {
|
|
290
|
+
const candidates = [];
|
|
291
|
+
if (modelId.includes('/')) {
|
|
292
|
+
candidates.push(modelId);
|
|
293
|
+
}
|
|
294
|
+
if (publisher && !modelId.includes('/')) {
|
|
295
|
+
candidates.push(`${publisher}/${modelId}`);
|
|
296
|
+
}
|
|
297
|
+
for (const hfId of candidates) {
|
|
298
|
+
try {
|
|
299
|
+
const res = await fetchHF(`https://huggingface.co/api/models/${hfId}`);
|
|
300
|
+
if (res.ok)
|
|
301
|
+
return (await res.json());
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
// skip
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
// ── Auto-profile generation ──────────────────────────────────────────
|
|
310
|
+
// When HF gives us metadata but we don't have a hardcoded profile,
|
|
311
|
+
// generate a reasonable one from the available data.
|
|
312
|
+
function inferProfileFromHF(card, modelId) {
|
|
313
|
+
const tag = card.pipeline_tag || '';
|
|
314
|
+
const tags = card.tags || [];
|
|
315
|
+
const arch = card.config?.architectures?.[0] || '';
|
|
316
|
+
// Extract org/family from HF ID
|
|
317
|
+
const parts = card.id.split('/');
|
|
318
|
+
const org = parts.length > 1 ? parts[0] : '';
|
|
319
|
+
const modelName = parts.length > 1 ? parts[1] : parts[0];
|
|
320
|
+
// Infer family name from model ID
|
|
321
|
+
const family = inferFamily(modelName, org);
|
|
322
|
+
// Infer description
|
|
323
|
+
let description = `${org ? org + "'s " : ''}${family} model.`;
|
|
324
|
+
if (tag === 'text-generation')
|
|
325
|
+
description += ' Text generation / chat model.';
|
|
326
|
+
else if (tag === 'image-text-to-text')
|
|
327
|
+
description += ' Vision-language model — handles text and image inputs.';
|
|
328
|
+
else if (tag === 'feature-extraction' || tag === 'sentence-similarity')
|
|
329
|
+
description += ' Embedding model for semantic search.';
|
|
330
|
+
if (card.cardData?.license)
|
|
331
|
+
description += ` License: ${card.cardData.license}.`;
|
|
332
|
+
// Infer strengths from tags
|
|
333
|
+
const strengths = [];
|
|
334
|
+
const weaknesses = [];
|
|
335
|
+
const bestFor = [];
|
|
336
|
+
if (tag === 'text-generation') {
|
|
337
|
+
strengths.push('text generation', 'instruction following');
|
|
338
|
+
bestFor.push('general delegation', 'Q&A');
|
|
339
|
+
}
|
|
340
|
+
if (tag === 'image-text-to-text') {
|
|
341
|
+
strengths.push('image understanding', 'visual Q&A');
|
|
342
|
+
bestFor.push('screenshot analysis', 'diagram interpretation');
|
|
343
|
+
}
|
|
344
|
+
if (tags.includes('code') || modelName.toLowerCase().includes('code')) {
|
|
345
|
+
strengths.push('code generation');
|
|
346
|
+
bestFor.push('code tasks');
|
|
347
|
+
}
|
|
348
|
+
if (tags.includes('math') || modelName.toLowerCase().includes('math')) {
|
|
349
|
+
strengths.push('mathematics', 'reasoning');
|
|
350
|
+
bestFor.push('math/science questions');
|
|
351
|
+
}
|
|
352
|
+
if (tags.includes('conversational')) {
|
|
353
|
+
strengths.push('conversation');
|
|
354
|
+
bestFor.push('chat', 'brainstorming');
|
|
355
|
+
}
|
|
356
|
+
// Default if nothing specific found
|
|
357
|
+
if (strengths.length === 0)
|
|
358
|
+
strengths.push('general reasoning');
|
|
359
|
+
if (bestFor.length === 0)
|
|
360
|
+
bestFor.push('general delegation');
|
|
361
|
+
const thinking = detectThinkingSupport(card);
|
|
362
|
+
return {
|
|
363
|
+
family,
|
|
364
|
+
description,
|
|
365
|
+
strengths: JSON.stringify(strengths),
|
|
366
|
+
weaknesses: JSON.stringify(weaknesses),
|
|
367
|
+
bestFor: JSON.stringify(bestFor),
|
|
368
|
+
emitsThinkBlocks: thinking.emitsThinkBlocks,
|
|
369
|
+
supportsThinkingToggle: thinking.supportsThinkingToggle,
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
function inferFamily(modelName, org) {
|
|
373
|
+
// Try to extract a clean family name from the model ID
|
|
374
|
+
// e.g. "glm-4.7-flash" -> "GLM-4", "qwen3-coder-30b" -> "Qwen3 Coder"
|
|
375
|
+
const lower = modelName.toLowerCase();
|
|
376
|
+
// Common patterns
|
|
377
|
+
const familyPatterns = [
|
|
378
|
+
[/^glm[- ]?(\d)/i, 'GLM-$1'],
|
|
379
|
+
[/^qwen(\d)[- ]?coder/i, 'Qwen$1 Coder'],
|
|
380
|
+
[/^qwen(\d)[- ]?vl/i, 'Qwen$1 VL'],
|
|
381
|
+
[/^qwen(\d)/i, 'Qwen$1'],
|
|
382
|
+
[/^llama[- ]?(\d)/i, 'LLaMA $1'],
|
|
383
|
+
[/^nemotron/i, 'Nemotron'],
|
|
384
|
+
[/^granite/i, 'Granite'],
|
|
385
|
+
[/^mistral/i, 'Mistral'],
|
|
386
|
+
[/^mixtral/i, 'Mixtral'],
|
|
387
|
+
[/^deepseek/i, 'DeepSeek'],
|
|
388
|
+
[/^phi[- ]?(\d)/i, 'Phi-$1'],
|
|
389
|
+
[/^gemma[- ]?(\d)/i, 'Gemma $1'],
|
|
390
|
+
[/^starcoder/i, 'StarCoder'],
|
|
391
|
+
[/^codestral/i, 'Codestral'],
|
|
392
|
+
[/^command[- ]?r/i, 'Command R'],
|
|
393
|
+
[/^internlm/i, 'InternLM'],
|
|
394
|
+
[/^yi[- ]?(\d)/i, 'Yi-$1'],
|
|
395
|
+
[/^nomic/i, 'Nomic'],
|
|
396
|
+
[/^gpt[- ]?oss/i, 'GPT-OSS'],
|
|
397
|
+
[/^minimax/i, 'MiniMax'],
|
|
398
|
+
[/^kimi/i, 'Kimi'],
|
|
399
|
+
];
|
|
400
|
+
for (const [pattern, replacement] of familyPatterns) {
|
|
401
|
+
if (pattern.test(lower)) {
|
|
402
|
+
return modelName.replace(pattern, replacement);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
// Fallback: use org + first meaningful part of name
|
|
406
|
+
const firstPart = modelName.split(/[-_ ]/)[0];
|
|
407
|
+
return org ? `${org}/${firstPart}` : firstPart;
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Profile all models at startup. For each model:
|
|
411
|
+
* 1. Check SQLite cache — if fresh, skip
|
|
412
|
+
* 2. Look up on HuggingFace — if found, auto-generate profile and cache
|
|
413
|
+
* 3. If HF miss, cache as "inferred" with whatever metadata we have
|
|
414
|
+
*
|
|
415
|
+
* Runs in the background — never blocks server startup.
|
|
416
|
+
*/
|
|
417
|
+
export async function profileModelsAtStartup(models) {
|
|
418
|
+
const database = await initDb();
|
|
419
|
+
let profiledCount = 0;
|
|
420
|
+
let cachedCount = 0;
|
|
421
|
+
for (const model of models) {
|
|
422
|
+
try {
|
|
423
|
+
// Check cache
|
|
424
|
+
const cached = await getCachedProfile(model.id);
|
|
425
|
+
if (cached && !isCacheStale(cached)) {
|
|
426
|
+
cachedCount++;
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
429
|
+
// Look up on HuggingFace
|
|
430
|
+
const card = await lookupHF(model.id, model.publisher);
|
|
431
|
+
if (card) {
|
|
432
|
+
const inferred = inferProfileFromHF(card, model.id);
|
|
433
|
+
await upsertProfile({
|
|
434
|
+
modelId: model.id,
|
|
435
|
+
hfId: card.id,
|
|
436
|
+
pipelineTag: card.pipeline_tag || null,
|
|
437
|
+
architectures: card.config?.architectures ? JSON.stringify(card.config.architectures) : null,
|
|
438
|
+
license: card.cardData?.license || null,
|
|
439
|
+
downloads: card.downloads || null,
|
|
440
|
+
likes: card.likes || null,
|
|
441
|
+
libraryName: card.library_name || null,
|
|
442
|
+
family: inferred.family || null,
|
|
443
|
+
description: inferred.description || null,
|
|
444
|
+
strengths: inferred.strengths || null,
|
|
445
|
+
weaknesses: inferred.weaknesses || null,
|
|
446
|
+
bestFor: inferred.bestFor || null,
|
|
447
|
+
emitsThinkBlocks: inferred.emitsThinkBlocks || false,
|
|
448
|
+
supportsThinkingToggle: inferred.supportsThinkingToggle || false,
|
|
449
|
+
fetchedAt: Date.now(),
|
|
450
|
+
source: 'huggingface',
|
|
451
|
+
}, true);
|
|
452
|
+
profiledCount++;
|
|
453
|
+
}
|
|
454
|
+
else {
|
|
455
|
+
// No HF match — cache a minimal profile so we don't retry
|
|
456
|
+
await upsertProfile({
|
|
457
|
+
modelId: model.id,
|
|
458
|
+
hfId: null,
|
|
459
|
+
pipelineTag: model.type || null,
|
|
460
|
+
architectures: model.arch ? JSON.stringify([model.arch]) : null,
|
|
461
|
+
license: null,
|
|
462
|
+
downloads: null,
|
|
463
|
+
likes: null,
|
|
464
|
+
libraryName: null,
|
|
465
|
+
family: inferFamily(model.id.split('/').pop() || model.id, model.publisher || ''),
|
|
466
|
+
description: `${model.publisher ? model.publisher + "'s " : ''}local model. No HuggingFace card found.`,
|
|
467
|
+
strengths: null,
|
|
468
|
+
weaknesses: null,
|
|
469
|
+
bestFor: null,
|
|
470
|
+
emitsThinkBlocks: false,
|
|
471
|
+
supportsThinkingToggle: false,
|
|
472
|
+
fetchedAt: Date.now(),
|
|
473
|
+
source: 'inferred',
|
|
474
|
+
}, true);
|
|
475
|
+
profiledCount++;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
catch (err) {
|
|
479
|
+
process.stderr.write(`[houtini-lm] Failed to profile ${model.id}: ${err}\n`);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
// Flush all changes to disk in one write
|
|
483
|
+
if (profiledCount > 0)
|
|
484
|
+
flushDb();
|
|
485
|
+
process.stderr.write(`[houtini-lm] Model cache: ${cachedCount} cached, ${profiledCount} profiled, ${models.length} total\n`);
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Get a profile for display — checks SQLite first, returns formatted enrichment line.
|
|
489
|
+
*/
|
|
490
|
+
export async function getHFEnrichmentLine(modelId) {
|
|
491
|
+
const cached = await getCachedProfile(modelId);
|
|
492
|
+
if (!cached || cached.source === 'inferred')
|
|
493
|
+
return '';
|
|
494
|
+
const parts = [];
|
|
495
|
+
if (cached.pipelineTag)
|
|
496
|
+
parts.push(`HF task: ${cached.pipelineTag}`);
|
|
497
|
+
if (cached.libraryName)
|
|
498
|
+
parts.push(`library: ${cached.libraryName}`);
|
|
499
|
+
if (cached.downloads)
|
|
500
|
+
parts.push(`${cached.downloads.toLocaleString()} downloads`);
|
|
501
|
+
if (cached.likes)
|
|
502
|
+
parts.push(`${cached.likes.toLocaleString()} likes`);
|
|
503
|
+
if (cached.license)
|
|
504
|
+
parts.push(`license: ${cached.license}`);
|
|
505
|
+
if (cached.architectures) {
|
|
506
|
+
try {
|
|
507
|
+
const archs = JSON.parse(cached.architectures);
|
|
508
|
+
if (archs.length)
|
|
509
|
+
parts.push(`HF arch: ${archs.join(', ')}`);
|
|
510
|
+
}
|
|
511
|
+
catch { /* skip */ }
|
|
512
|
+
}
|
|
513
|
+
return parts.length > 0 ? ` HuggingFace: ${parts.join(' · ')}` : '';
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* Get all cached profiles (for diagnostics or export).
|
|
517
|
+
*/
|
|
518
|
+
export async function getAllCachedProfiles() {
|
|
519
|
+
const database = await initDb();
|
|
520
|
+
const results = [];
|
|
521
|
+
const stmt = database.prepare('SELECT * FROM model_profiles ORDER BY model_id');
|
|
522
|
+
while (stmt.step()) {
|
|
523
|
+
const row = stmt.getAsObject();
|
|
524
|
+
results.push({
|
|
525
|
+
modelId: row.model_id,
|
|
526
|
+
hfId: row.hf_id,
|
|
527
|
+
pipelineTag: row.pipeline_tag,
|
|
528
|
+
architectures: row.architectures,
|
|
529
|
+
license: row.license,
|
|
530
|
+
downloads: row.downloads,
|
|
531
|
+
likes: row.likes,
|
|
532
|
+
libraryName: row.library_name,
|
|
533
|
+
family: row.family,
|
|
534
|
+
description: row.description,
|
|
535
|
+
strengths: row.strengths,
|
|
536
|
+
weaknesses: row.weaknesses,
|
|
537
|
+
bestFor: row.best_for,
|
|
538
|
+
emitsThinkBlocks: !!row.emits_think_blocks,
|
|
539
|
+
supportsThinkingToggle: !!row.supports_thinking_toggle,
|
|
540
|
+
fetchedAt: row.fetched_at,
|
|
541
|
+
source: row.source,
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
stmt.free();
|
|
545
|
+
return results;
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Query thinking support for a model from the cache.
|
|
549
|
+
* Returns null if model is not cached.
|
|
550
|
+
*/
|
|
551
|
+
export async function getThinkingSupport(modelId) {
|
|
552
|
+
const cached = await getCachedProfile(modelId);
|
|
553
|
+
if (!cached)
|
|
554
|
+
return null;
|
|
555
|
+
return { emitsThinkBlocks: cached.emitsThinkBlocks, supportsThinkingToggle: cached.supportsThinkingToggle };
|
|
556
|
+
}
|
|
557
|
+
//# sourceMappingURL=model-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-cache.js","sourceRoot":"","sources":["../src/model-cache.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@houtini/lm",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "MCP server for local LLMs — connects to LM Studio or any OpenAI-compatible endpoint",
|
|
6
6
|
"mcpName": "io.github.houtini-ai/lm",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"llm"
|
|
31
31
|
],
|
|
32
32
|
"author": "Richard Baxter <richard@richardbaxter.co> (https://richardbaxter.co)",
|
|
33
|
-
"license": "
|
|
33
|
+
"license": "Apache-2.0",
|
|
34
34
|
"homepage": "https://houtini.ai",
|
|
35
35
|
"repository": {
|
|
36
36
|
"type": "git",
|
|
@@ -44,10 +44,12 @@
|
|
|
44
44
|
"url": "https://github.com/sponsors/houtini-ai"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@modelcontextprotocol/sdk": "^1.26.0"
|
|
47
|
+
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
48
|
+
"sql.js": "^1.14.1"
|
|
48
49
|
},
|
|
49
50
|
"devDependencies": {
|
|
50
51
|
"@types/node": "^22.0.0",
|
|
52
|
+
"@types/sql.js": "^1.4.9",
|
|
51
53
|
"typescript": "^5.7.0"
|
|
52
54
|
},
|
|
53
55
|
"engines": {
|