node-mlx 1.0.6 → 2.0.1
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/dist/cli.js +38 -24
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +30 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -25
- package/dist/index.d.ts +15 -25
- package/dist/index.js +30 -16
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/prebuilds/darwin-arm64/node.node +0 -0
- package/swift/libNodeMLX.dylib +0 -0
package/dist/cli.js
CHANGED
|
@@ -87,21 +87,28 @@ function loadBinding() {
|
|
|
87
87
|
return binding;
|
|
88
88
|
}
|
|
89
89
|
var RECOMMENDED_MODELS = {
|
|
90
|
-
// Qwen
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
// Qwen 3 (Alibaba) - With Q/K norms
|
|
91
|
+
qwen: "lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit",
|
|
92
|
+
// Default to Qwen3
|
|
93
|
+
qwen3: "lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit",
|
|
94
|
+
"qwen-3": "lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit",
|
|
95
|
+
"qwen-3-4b": "lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit",
|
|
96
|
+
"qwen-3-0.6b": "mlx-community/Qwen3-0.6B-4bit",
|
|
97
|
+
"qwen-3-1.7b": "mlx-community/Qwen3-1.7B-4bit",
|
|
98
|
+
// Qwen 2.5 (Alibaba) - Legacy, with attention bias
|
|
93
99
|
"qwen-2.5": "Qwen/Qwen2.5-1.5B-Instruct",
|
|
94
|
-
"qwen-2.5-0.5b": "Qwen/Qwen2.5-0.5B-Instruct",
|
|
95
100
|
"qwen-2.5-1.5b": "Qwen/Qwen2.5-1.5B-Instruct",
|
|
96
101
|
"qwen-2.5-3b": "Qwen/Qwen2.5-3B-Instruct",
|
|
97
102
|
// Phi (Microsoft) - Working with fused QKV and RoPE
|
|
98
|
-
phi: "
|
|
99
|
-
// Default to
|
|
100
|
-
phi4: "
|
|
101
|
-
"phi-4": "
|
|
102
|
-
|
|
103
|
-
"phi-3": "
|
|
104
|
-
|
|
103
|
+
phi: "mlx-community/Phi-3.5-mini-instruct-4bit",
|
|
104
|
+
// Default to 3.5 (smaller, faster to download)
|
|
105
|
+
phi4: "mlx-community/phi-4-4bit",
|
|
106
|
+
"phi-4": "mlx-community/phi-4-4bit",
|
|
107
|
+
"phi-3.5": "mlx-community/Phi-3.5-mini-instruct-4bit",
|
|
108
|
+
"phi-3.5-mini": "mlx-community/Phi-3.5-mini-instruct-4bit",
|
|
109
|
+
phi3: "mlx-community/Phi-3-mini-4k-instruct-4bit",
|
|
110
|
+
"phi-3": "mlx-community/Phi-3-mini-4k-instruct-4bit",
|
|
111
|
+
"phi-3-mini": "mlx-community/Phi-3-mini-4k-instruct-4bit",
|
|
105
112
|
// Llama 3.2 (Meta) - Requires HuggingFace authentication
|
|
106
113
|
// Note: meta-llama models require accepting license at huggingface.co
|
|
107
114
|
llama: "meta-llama/Llama-3.2-1B-Instruct",
|
|
@@ -119,7 +126,7 @@ var RECOMMENDED_MODELS = {
|
|
|
119
126
|
"gemma-3-27b": "mlx-community/gemma-3-27b-it-4bit",
|
|
120
127
|
// Gemma 3n (Google) - Efficient architecture with AltUp and Laurel
|
|
121
128
|
// Note: Use -lm variants (language model only, no audio/vision)
|
|
122
|
-
"gemma-3n": "mlx-community/gemma-3n-
|
|
129
|
+
"gemma-3n": "mlx-community/gemma-3n-E4B-it-lm-4bit",
|
|
123
130
|
"gemma-3n-e2b": "mlx-community/gemma-3n-E2B-it-lm-4bit",
|
|
124
131
|
"gemma-3n-e4b": "mlx-community/gemma-3n-E4B-it-lm-4bit"
|
|
125
132
|
};
|
|
@@ -137,9 +144,16 @@ function isSupported() {
|
|
|
137
144
|
return false;
|
|
138
145
|
}
|
|
139
146
|
}
|
|
147
|
+
function resolveModelId(modelId) {
|
|
148
|
+
if (modelId in RECOMMENDED_MODELS) {
|
|
149
|
+
return RECOMMENDED_MODELS[modelId];
|
|
150
|
+
}
|
|
151
|
+
return modelId;
|
|
152
|
+
}
|
|
140
153
|
function loadModel(modelId) {
|
|
141
154
|
const b = loadBinding();
|
|
142
|
-
const
|
|
155
|
+
const resolvedId = resolveModelId(modelId);
|
|
156
|
+
const handle = b.loadModel(resolvedId);
|
|
143
157
|
return {
|
|
144
158
|
handle,
|
|
145
159
|
generate(prompt, options) {
|
|
@@ -147,7 +161,7 @@ function loadModel(modelId) {
|
|
|
147
161
|
maxTokens: options?.maxTokens ?? 256,
|
|
148
162
|
temperature: options?.temperature ?? 0.7,
|
|
149
163
|
topP: options?.topP ?? 0.9,
|
|
150
|
-
repetitionPenalty: options?.repetitionPenalty ??
|
|
164
|
+
repetitionPenalty: options?.repetitionPenalty ?? 1.1,
|
|
151
165
|
repetitionContextSize: options?.repetitionContextSize ?? 20
|
|
152
166
|
});
|
|
153
167
|
const result = JSON.parse(jsonStr);
|
|
@@ -165,7 +179,7 @@ function loadModel(modelId) {
|
|
|
165
179
|
maxTokens: options?.maxTokens ?? 256,
|
|
166
180
|
temperature: options?.temperature ?? 0.7,
|
|
167
181
|
topP: options?.topP ?? 0.9,
|
|
168
|
-
repetitionPenalty: options?.repetitionPenalty ??
|
|
182
|
+
repetitionPenalty: options?.repetitionPenalty ?? 1.1,
|
|
169
183
|
repetitionContextSize: options?.repetitionContextSize ?? 20
|
|
170
184
|
});
|
|
171
185
|
const result = JSON.parse(jsonStr);
|
|
@@ -182,7 +196,7 @@ function loadModel(modelId) {
|
|
|
182
196
|
maxTokens: options?.maxTokens ?? 256,
|
|
183
197
|
temperature: options?.temperature ?? 0.7,
|
|
184
198
|
topP: options?.topP ?? 0.9,
|
|
185
|
-
repetitionPenalty: options?.repetitionPenalty ??
|
|
199
|
+
repetitionPenalty: options?.repetitionPenalty ?? 1.1,
|
|
186
200
|
repetitionContextSize: options?.repetitionContextSize ?? 20
|
|
187
201
|
});
|
|
188
202
|
const result = JSON.parse(jsonStr);
|
|
@@ -333,7 +347,8 @@ function runInteractive(initialModel) {
|
|
|
333
347
|
options: {
|
|
334
348
|
maxTokens: 512,
|
|
335
349
|
temperature: 0.7,
|
|
336
|
-
topP: 0.9
|
|
350
|
+
topP: 0.9,
|
|
351
|
+
repetitionPenalty: 1.1
|
|
337
352
|
},
|
|
338
353
|
history: [],
|
|
339
354
|
imagePath: null
|
|
@@ -412,15 +427,16 @@ function buildPrompt(history, current) {
|
|
|
412
427
|
let prompt = "";
|
|
413
428
|
for (const msg of history.slice(-6)) {
|
|
414
429
|
if (msg.role === "user") {
|
|
415
|
-
prompt +=
|
|
430
|
+
prompt += `${msg.content}
|
|
431
|
+
|
|
416
432
|
`;
|
|
417
433
|
} else {
|
|
418
|
-
prompt +=
|
|
434
|
+
prompt += `${msg.content}
|
|
435
|
+
|
|
419
436
|
`;
|
|
420
437
|
}
|
|
421
438
|
}
|
|
422
|
-
prompt +=
|
|
423
|
-
Assistant:`;
|
|
439
|
+
prompt += current;
|
|
424
440
|
return prompt;
|
|
425
441
|
}
|
|
426
442
|
async function handleCommand(input, state, rl) {
|
|
@@ -590,9 +606,7 @@ function parseArgs() {
|
|
|
590
606
|
} else if (arg === "--repetition-penalty" || arg === "-r") {
|
|
591
607
|
options.repetitionPenalty = parseFloat(args[++i] || "1.2");
|
|
592
608
|
} else if (arg && !arg.startsWith("-")) {
|
|
593
|
-
if (
|
|
594
|
-
model = arg;
|
|
595
|
-
} else if (prompt === null) {
|
|
609
|
+
if (prompt === null) {
|
|
596
610
|
prompt = arg;
|
|
597
611
|
command = "oneshot";
|
|
598
612
|
}
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/index.ts"],"sourcesContent":["/**\n * MLX CLI - Interactive chat with LLMs on Apple Silicon\n *\n * Usage:\n * mlx # Interactive mode with default model\n * mlx --model llama-3.2-1b # Use a specific model\n * mlx \"What is 2+2?\" # One-shot query\n * mlx --list # List available models\n */\n\nimport * as readline from \"node:readline\"\nimport {\n loadModel,\n RECOMMENDED_MODELS,\n isSupported,\n isPlatformSupported,\n VERSION,\n type Model,\n type GenerationOptions,\n type RecommendedModelKey\n} from \"./index.js\"\n\n// ANSI colors\nconst colors = {\n reset: \"\\x1b[0m\",\n bold: \"\\x1b[1m\",\n dim: \"\\x1b[2m\",\n cyan: \"\\x1b[36m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n magenta: \"\\x1b[35m\",\n red: \"\\x1b[31m\"\n}\n\nfunction log(msg: string) {\n console.log(msg)\n}\n\nfunction error(msg: string) {\n console.error(`${colors.red}Error:${colors.reset} ${msg}`)\n}\n\nfunction printHeader() {\n log(\"\")\n log(`${colors.bold}${colors.cyan}╔══════════════════════════════════════╗${colors.reset}`)\n log(\n `${colors.bold}${colors.cyan}║${colors.reset} ${colors.bold}MLX CLI${colors.reset} - LLMs on Apple Silicon ${colors.cyan}║${colors.reset}`\n )\n log(`${colors.bold}${colors.cyan}╚══════════════════════════════════════╝${colors.reset}`)\n log(\"\")\n}\n\nfunction printHelp() {\n log(`${colors.bold}Usage:${colors.reset}`)\n log(` mlx Interactive chat`)\n log(` mlx \"prompt\" One-shot generation`)\n log(` mlx --model <name> Use specific model`)\n log(` mlx --image <path> Include image (VLM only)`)\n log(` mlx --repetition-penalty <1-2> Penalize repeated tokens (default: off)`)\n log(` mlx --list List available models`)\n log(` mlx --help Show this help`)\n log(\"\")\n log(`${colors.bold}Vision models (VLM):${colors.reset}`)\n log(` mlx --model gemma-3-4b --image photo.jpg \"What's in this image?\"`)\n log(\"\")\n log(`${colors.bold}Repetition penalty (for models that repeat):${colors.reset}`)\n log(` mlx --model gemma-3n --repetition-penalty 1.2 \"Tell me about AI\"`)\n log(\"\")\n log(`${colors.bold}Interactive commands:${colors.reset}`)\n log(` /model <name> Switch model`)\n log(` /image <path> Set image for next prompt`)\n log(` /temp <0-2> Set temperature`)\n log(` /tokens <n> Set max tokens`)\n log(` /rep <1-2> Set repetition penalty`)\n log(` /clear Clear conversation`)\n log(` /help Show commands`)\n log(` /quit Exit`)\n log(\"\")\n}\n\nfunction printModels() {\n log(`${colors.bold}Available models:${colors.reset}`)\n log(\"\")\n\n // Group models by family, showing unique HuggingFace IDs with all their aliases\n const modelsByHfId = new Map<string, string[]>()\n\n for (const [alias, hfId] of Object.entries(RECOMMENDED_MODELS)) {\n if (!modelsByHfId.has(hfId)) {\n modelsByHfId.set(hfId, [])\n }\n\n modelsByHfId.get(hfId)?.push(alias)\n }\n\n // Organize by family\n const families = [\n {\n name: \"Phi (Microsoft)\",\n prefix: \"Phi\",\n desc: \"Reasoning & coding\"\n },\n {\n name: \"Gemma (Google)\",\n prefix: \"gemma\",\n desc: \"Efficient on-device\"\n },\n {\n name: \"Llama (Meta)\",\n prefix: \"Llama\",\n desc: \"General purpose\"\n },\n {\n name: \"Qwen (Alibaba)\",\n prefix: \"Qwen\",\n desc: \"Multilingual\"\n },\n {\n name: \"Mistral\",\n prefix: \"Mistral\",\n desc: \"Balanced performance\"\n },\n {\n name: \"Ministral\",\n prefix: \"Ministral\",\n desc: \"Fast inference\"\n }\n ]\n\n for (const family of families) {\n const familyModels = Array.from(modelsByHfId.entries()).filter(([hfId]) =>\n hfId.toLowerCase().includes(family.prefix.toLowerCase())\n )\n\n if (familyModels.length === 0) continue\n\n log(`${colors.bold}${family.name}${colors.reset} ${colors.dim}— ${family.desc}${colors.reset}`)\n\n for (const [hfId, aliases] of familyModels) {\n // Sort aliases: shortest first, then alphabetically\n const sortedAliases = aliases.sort((a, b) => a.length - b.length || a.localeCompare(b))\n const primary = sortedAliases[0]\n const others = sortedAliases.slice(1)\n\n const aliasStr =\n others.length > 0\n ? `${colors.green}${primary ?? \"\"}${colors.reset} ${colors.dim}(${others.join(\", \")})${colors.reset}`\n : `${colors.green}${primary ?? \"\"}${colors.reset}`\n\n log(` ${aliasStr.padEnd(45)} ${colors.dim}${hfId}${colors.reset}`)\n }\n\n log(\"\")\n }\n\n log(`${colors.dim}Or use any mlx-community model:${colors.reset}`)\n log(` ${colors.cyan}node-mlx --model mlx-community/YourModel-4bit${colors.reset}`)\n log(\"\")\n}\n\nfunction resolveModel(name: string): string {\n // Check if it's a shortcut\n if (name in RECOMMENDED_MODELS) {\n return RECOMMENDED_MODELS[name as RecommendedModelKey]\n }\n\n // Check if it's already a full model ID\n if (name.includes(\"/\")) {\n return name\n }\n\n // Assume it's from mlx-community\n return `mlx-community/${name}`\n}\n\ninterface ChatState {\n model: Model | null\n modelName: string\n options: GenerationOptions\n history: Array<{ role: \"user\" | \"assistant\"; content: string }>\n imagePath: string | null // For VLM image input\n}\n\nfunction runInteractive(initialModel: string): void {\n const state: ChatState = {\n model: null,\n modelName: initialModel,\n options: {\n maxTokens: 512,\n temperature: 0.7,\n topP: 0.9\n },\n history: [],\n imagePath: null\n }\n\n // Load initial model\n log(`${colors.dim}Loading ${state.modelName}...${colors.reset}`)\n const modelId = resolveModel(state.modelName)\n\n try {\n state.model = loadModel(modelId)\n log(`${colors.green}✓${colors.reset} Model loaded`)\n } catch (err) {\n error(`Failed to load model: ${err instanceof Error ? err.message : String(err)}`)\n process.exit(1)\n }\n\n log(\"\")\n log(`${colors.dim}Type your message or /help for commands${colors.reset}`)\n log(\"\")\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout\n })\n\n const promptUser = (): void => {\n rl.question(`${colors.cyan}You:${colors.reset} `, (input) => {\n void handleUserInput(input, state, rl, promptUser)\n })\n }\n\n const handleUserInput = async (\n input: string,\n state: ChatState,\n rl: readline.Interface,\n next: () => void\n ): Promise<void> => {\n const trimmed = input.trim()\n\n if (!trimmed) {\n next()\n\n return\n }\n\n // Handle commands\n if (trimmed.startsWith(\"/\")) {\n await handleCommand(trimmed, state, rl)\n next()\n\n return\n }\n\n // Generate response\n if (!state.model) {\n error(\"No model loaded\")\n next()\n\n return\n }\n\n // Build prompt with history (simple format)\n const fullPrompt = buildPrompt(state.history, trimmed)\n\n state.history.push({ role: \"user\", content: trimmed })\n\n process.stdout.write(`${colors.magenta}AI:${colors.reset} `)\n\n try {\n let result\n\n // Check if we have an image to send\n if (state.imagePath && state.model.isVLM()) {\n result = state.model.generateWithImage(fullPrompt, state.imagePath, state.options)\n state.imagePath = null // Clear after use\n } else {\n // Use streaming - tokens are written directly to stdout\n result = state.model.generateStreaming(fullPrompt, state.options)\n }\n\n // Note: text already streamed, we only have stats\n log(\"\")\n log(\n `${colors.dim}(${String(result.tokenCount)} tokens, ${result.tokensPerSecond.toFixed(1)} tok/s)${colors.reset}`\n )\n log(\"\")\n\n // For history we'd need to capture the text, but streaming writes to stdout\n // For now, history won't track assistant responses in streaming mode\n state.history.push({ role: \"assistant\", content: \"[streamed response]\" })\n } catch (err) {\n log(\"\")\n error(err instanceof Error ? err.message : String(err))\n }\n\n next()\n }\n\n rl.on(\"close\", () => {\n log(\"\")\n log(`${colors.dim}Goodbye!${colors.reset}`)\n\n if (state.model) {\n state.model.unload()\n }\n\n process.exit(0)\n })\n\n promptUser()\n}\n\nfunction buildPrompt(\n history: Array<{ role: \"user\" | \"assistant\"; content: string }>,\n current: string\n): string {\n // Simple chat format\n let prompt = \"\"\n\n for (const msg of history.slice(-6)) {\n // Keep last 3 exchanges\n if (msg.role === \"user\") {\n prompt += `User: ${msg.content}\\n`\n } else {\n prompt += `Assistant: ${msg.content}\\n`\n }\n }\n\n prompt += `User: ${current}\\nAssistant:`\n\n return prompt\n}\n\nasync function handleCommand(input: string, state: ChatState, rl: readline.Interface) {\n const [cmd, ...args] = input.slice(1).split(\" \")\n const arg = args.join(\" \")\n\n switch (cmd) {\n case \"help\":\n case \"h\":\n printHelp()\n break\n\n case \"quit\":\n case \"q\":\n case \"exit\":\n rl.close()\n break\n\n case \"clear\":\n case \"c\":\n state.history = []\n log(`${colors.dim}Conversation cleared${colors.reset}`)\n break\n\n case \"model\":\n case \"m\":\n if (!arg) {\n log(`${colors.dim}Current model: ${state.modelName}${colors.reset}`)\n log(`${colors.dim}Use /model <name> to switch${colors.reset}`)\n } else {\n log(`${colors.dim}Loading ${arg}...${colors.reset}`)\n\n if (state.model) {\n state.model.unload()\n }\n\n try {\n state.model = loadModel(resolveModel(arg))\n state.modelName = arg\n state.history = []\n log(`${colors.green}✓${colors.reset} Switched to ${arg}`)\n } catch (err) {\n error(err instanceof Error ? err.message : String(err))\n }\n }\n\n break\n\n case \"temp\":\n case \"t\":\n if (!arg) {\n log(`${colors.dim}Temperature: ${String(state.options.temperature)}${colors.reset}`)\n } else {\n const temp = parseFloat(arg)\n\n if (isNaN(temp) || temp < 0 || temp > 2) {\n error(\"Temperature must be between 0 and 2\")\n } else {\n state.options.temperature = temp\n log(`${colors.dim}Temperature set to ${String(temp)}${colors.reset}`)\n }\n }\n\n break\n\n case \"tokens\":\n case \"n\":\n if (!arg) {\n log(`${colors.dim}Max tokens: ${String(state.options.maxTokens)}${colors.reset}`)\n } else {\n const tokens = parseInt(arg, 10)\n\n if (isNaN(tokens) || tokens < 1) {\n error(\"Tokens must be a positive number\")\n } else {\n state.options.maxTokens = tokens\n log(`${colors.dim}Max tokens set to ${String(tokens)}${colors.reset}`)\n }\n }\n\n break\n\n case \"rep\":\n case \"r\":\n if (!arg) {\n log(\n `${colors.dim}Repetition penalty: ${state.options.repetitionPenalty != null ? String(state.options.repetitionPenalty) : \"off\"}${colors.reset}`\n )\n } else {\n const penalty = parseFloat(arg)\n\n if (isNaN(penalty) || penalty < 1 || penalty > 2) {\n error(\"Repetition penalty must be between 1 and 2\")\n } else {\n state.options.repetitionPenalty = penalty\n log(`${colors.dim}Repetition penalty set to ${String(penalty)}${colors.reset}`)\n }\n }\n\n break\n\n case \"list\":\n case \"l\":\n printModels()\n break\n\n case \"image\":\n case \"i\":\n if (!arg) {\n if (state.imagePath) {\n log(`${colors.dim}Current image: ${state.imagePath}${colors.reset}`)\n } else {\n log(`${colors.dim}No image set. Use /image <path> to set one.${colors.reset}`)\n }\n } else {\n // Check if file exists\n const fs = await import(\"node:fs\")\n\n if (!fs.existsSync(arg)) {\n error(`Image not found: ${arg}`)\n } else if (!state.model?.isVLM()) {\n error(`Current model doesn't support images. Use a VLM like gemma-3-4b.`)\n } else {\n state.imagePath = arg\n log(`${colors.green}✓${colors.reset} Image set: ${arg}`)\n log(`${colors.dim}The next message will include this image.${colors.reset}`)\n }\n }\n\n break\n\n default:\n error(`Unknown command: /${cmd ?? \"\"}. Type /help for commands.`)\n }\n}\n\nfunction runOneShot(\n modelName: string,\n prompt: string,\n imagePath: string | null,\n options: GenerationOptions\n) {\n log(`${colors.dim}Loading ${modelName}...${colors.reset}`)\n\n const modelId = resolveModel(modelName)\n\n try {\n const model = loadModel(modelId)\n\n let result\n\n // Check if we have an image to process\n if (imagePath) {\n if (!model.isVLM()) {\n error(`Model ${modelName} doesn't support images. Use a VLM like gemma-3-4b.`)\n model.unload()\n process.exit(1)\n }\n\n result = model.generateWithImage(prompt, imagePath, options)\n } else {\n // Use streaming - tokens are written directly to stdout\n result = model.generateStreaming(prompt, options)\n }\n\n // Add newline after streamed output\n log(\"\")\n log(\n `${colors.dim}(${String(result.tokenCount)} tokens, ${result.tokensPerSecond.toFixed(1)} tok/s)${colors.reset}`\n )\n\n model.unload()\n } catch (err) {\n error(err instanceof Error ? err.message : String(err))\n process.exit(1)\n }\n}\n\n// Parse CLI arguments\nfunction parseArgs(): {\n model: string\n prompt: string | null\n imagePath: string | null\n options: GenerationOptions\n command: \"chat\" | \"oneshot\" | \"list\" | \"help\" | \"version\"\n} {\n const args = process.argv.slice(2)\n let model = \"qwen\" // Default to Qwen (no auth required)\n let prompt: string | null = null\n let imagePath: string | null = null\n const options: GenerationOptions = {\n maxTokens: 512,\n temperature: 0.7,\n topP: 0.9\n }\n let command: \"chat\" | \"oneshot\" | \"list\" | \"help\" | \"version\" = \"chat\"\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]\n\n if (arg === \"--help\" || arg === \"-h\") {\n command = \"help\"\n } else if (arg === \"--version\" || arg === \"-v\") {\n command = \"version\"\n } else if (arg === \"--list\" || arg === \"-l\") {\n command = \"list\"\n } else if (arg === \"--model\" || arg === \"-m\") {\n model = args[++i] || model\n } else if (arg === \"--image\" || arg === \"-i\") {\n imagePath = args[++i] || null\n } else if (arg === \"--temp\" || arg === \"-t\") {\n options.temperature = parseFloat(args[++i] || \"0.7\")\n } else if (arg === \"--tokens\" || arg === \"-n\") {\n options.maxTokens = parseInt(args[++i] || \"512\", 10)\n } else if (arg === \"--repetition-penalty\" || arg === \"-r\") {\n options.repetitionPenalty = parseFloat(args[++i] || \"1.2\")\n } else if (arg && !arg.startsWith(\"-\")) {\n // First positional arg is model, second is prompt\n if (model === \"qwen\") {\n model = arg\n } else if (prompt === null) {\n prompt = arg\n command = \"oneshot\"\n }\n }\n }\n\n return { model, prompt, imagePath, options, command }\n}\n\n// Main\nfunction main(): void {\n const { model, prompt, imagePath, options, command } = parseArgs()\n\n // Commands that don't need Apple Silicon\n switch (command) {\n case \"help\":\n printHeader()\n printHelp()\n\n return\n\n case \"version\":\n log(`node-mlx v${VERSION}`)\n\n return\n\n case \"list\":\n printHeader()\n printModels()\n\n return\n }\n\n // Check platform for commands that need the runtime\n if (!isPlatformSupported()) {\n error(\"node-mlx requires macOS on Apple Silicon (M1/M2/M3/M4)\")\n process.exit(1)\n }\n\n if (!isSupported()) {\n error(\"Native libraries not found. Run 'pnpm build:swift && pnpm build:native' first.\")\n process.exit(1)\n }\n\n switch (command) {\n case \"oneshot\":\n if (prompt) {\n runOneShot(model, prompt, imagePath, options)\n }\n\n break\n\n case \"chat\":\n printHeader()\n runInteractive(model)\n break\n }\n}\n\ntry {\n main()\n} catch (err: unknown) {\n error(err instanceof Error ? err.message : String(err))\n process.exit(1)\n}\n","import { platform, arch } from \"node:os\"\nimport { join, dirname } from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\nimport { existsSync, readFileSync } from \"node:fs\"\nimport { createRequire } from \"node:module\"\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = dirname(__filename)\nconst require = createRequire(import.meta.url)\n\n// Read version from package.json\nconst packageJsonPath = join(__dirname, \"..\", \"package.json\")\nconst packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\")) as { version: string }\n\n/** Package version */\nexport const VERSION = packageJson.version\n\n// Native binding interface\ninterface NativeBinding {\n initialize(dylibPath: string): boolean\n isInitialized(): boolean\n loadModel(modelId: string): number\n unloadModel(handle: number): void\n generate(\n handle: number,\n prompt: string,\n options?: {\n maxTokens?: number\n temperature?: number\n topP?: number\n repetitionPenalty?: number\n repetitionContextSize?: number\n }\n ): string // Returns JSON string\n generateStreaming(\n handle: number,\n prompt: string,\n options?: {\n maxTokens?: number\n temperature?: number\n topP?: number\n repetitionPenalty?: number\n repetitionContextSize?: number\n }\n ): string // Streams to stdout, returns JSON stats\n generateWithImage(\n handle: number,\n prompt: string,\n imagePath: string,\n options?: {\n maxTokens?: number\n temperature?: number\n topP?: number\n repetitionPenalty?: number\n repetitionContextSize?: number\n }\n ): string // VLM: Streams to stdout, returns JSON stats\n isVLM(handle: number): boolean\n isAvailable(): boolean\n getVersion(): string\n}\n\n// JSON response from Swift\ninterface JSONGenerationResult {\n success: boolean\n text?: string\n tokenCount?: number\n tokensPerSecond?: number\n error?: string\n}\n\n// Load the native addon\nlet binding: NativeBinding | null = null\nlet initialized = false\n\n/**\n * Load native addon using node-gyp-build (prebuilds) or fallback to built addon\n */\nfunction loadNativeAddon(): NativeBinding {\n // Try node-gyp-build first (prebuilds)\n try {\n const gypBuild = require(\"node-gyp-build\") as (dir: string) => NativeBinding\n const nativeDir = join(__dirname, \"..\", \"native\")\n\n if (existsSync(join(__dirname, \"..\", \"prebuilds\"))) {\n return gypBuild(join(__dirname, \"..\"))\n }\n\n // Fallback to native/build if no prebuilds\n if (existsSync(join(nativeDir, \"build\"))) {\n return gypBuild(nativeDir)\n }\n } catch {\n // node-gyp-build failed, try manual loading\n }\n\n // Manual fallback: try different paths for the native addon\n const possibleAddonPaths = [\n // From package dist/ (npm installed)\n join(__dirname, \"..\", \"prebuilds\", \"darwin-arm64\", \"node.napi.node\"),\n // From native/build (local development)\n join(__dirname, \"..\", \"native\", \"build\", \"Release\", \"node_mlx.node\"),\n // From project root (monorepo development)\n join(process.cwd(), \"packages\", \"node-mlx\", \"native\", \"build\", \"Release\", \"node_mlx.node\")\n ]\n\n for (const p of possibleAddonPaths) {\n if (existsSync(p)) {\n return require(p) as NativeBinding\n }\n }\n\n throw new Error(\n \"Native addon not found. Run 'pnpm build:native' first.\\n\" +\n `Searched paths:\\n${possibleAddonPaths.join(\"\\n\")}`\n )\n}\n\n/**\n * Find Swift library path\n * Note: The library is expected to be in a directory with mlx.metallib for MLX to find it\n */\nfunction findSwiftLibrary(): string {\n const possibleDylibPaths = [\n // From package swift/ (preferred - has metallib co-located)\n join(__dirname, \"..\", \"swift\", \"libNodeMLX.dylib\"),\n // From project root packages/node-mlx/swift/ (monorepo development)\n join(process.cwd(), \"packages\", \"node-mlx\", \"swift\", \"libNodeMLX.dylib\"),\n // Fallback to packages/swift/.build (monorepo dev)\n join(__dirname, \"..\", \"..\", \"swift\", \".build\", \"release\", \"libNodeMLX.dylib\"),\n join(__dirname, \"..\", \"..\", \"..\", \"swift\", \".build\", \"release\", \"libNodeMLX.dylib\"),\n join(process.cwd(), \"packages\", \"swift\", \".build\", \"release\", \"libNodeMLX.dylib\")\n ]\n\n for (const p of possibleDylibPaths) {\n if (existsSync(p)) {\n return p\n }\n }\n\n throw new Error(\n \"Swift library not found. Run 'pnpm build:swift' first.\\n\" +\n `Searched paths:\\n${possibleDylibPaths.join(\"\\n\")}`\n )\n}\n\nfunction loadBinding(): NativeBinding {\n if (binding && initialized) {\n return binding\n }\n\n if (platform() !== \"darwin\" || arch() !== \"arm64\") {\n throw new Error(\"node-mlx is only supported on macOS Apple Silicon (arm64)\")\n }\n\n binding = loadNativeAddon()\n const dylibPath = findSwiftLibrary()\n const success = binding.initialize(dylibPath)\n\n if (!success) {\n throw new Error(\"Failed to initialize node-mlx native library\")\n }\n\n initialized = true\n\n return binding\n}\n\n// MARK: - Public Types\n\nexport interface GenerationOptions {\n maxTokens?: number\n temperature?: number\n topP?: number\n /** Penalty for repeating tokens (1.0 = no penalty, 1.1-1.2 recommended) */\n repetitionPenalty?: number\n /** Number of recent tokens to consider for penalty (default: 20) */\n repetitionContextSize?: number\n}\n\nexport interface GenerationResult {\n text: string\n tokenCount: number\n tokensPerSecond: number\n}\n\nexport interface StreamingResult {\n tokenCount: number\n tokensPerSecond: number\n}\n\nexport interface Model {\n /** Generate text from a prompt */\n generate(prompt: string, options?: GenerationOptions): GenerationResult\n\n /** Generate text with streaming - tokens are written directly to stdout */\n generateStreaming(prompt: string, options?: GenerationOptions): StreamingResult\n\n /** Generate text from a prompt with an image (VLM only) */\n generateWithImage(prompt: string, imagePath: string, options?: GenerationOptions): StreamingResult\n\n /** Check if this model supports images (is a Vision-Language Model) */\n isVLM(): boolean\n\n /** Unload the model from memory */\n unload(): void\n\n /** Model handle (internal use) */\n readonly handle: number\n}\n\n// MARK: - Recommended Models\n\nexport const RECOMMENDED_MODELS = {\n // Qwen 2.5 (Alibaba) - Working with proper RoPE support\n // Using non-quantized models - quantized models have loading issues\n qwen: \"Qwen/Qwen2.5-1.5B-Instruct\",\n \"qwen-2.5\": \"Qwen/Qwen2.5-1.5B-Instruct\",\n \"qwen-2.5-0.5b\": \"Qwen/Qwen2.5-0.5B-Instruct\",\n \"qwen-2.5-1.5b\": \"Qwen/Qwen2.5-1.5B-Instruct\",\n \"qwen-2.5-3b\": \"Qwen/Qwen2.5-3B-Instruct\",\n\n // Phi (Microsoft) - Working with fused QKV and RoPE\n phi: \"microsoft/phi-4\", // Default to latest\n phi4: \"microsoft/phi-4\",\n \"phi-4\": \"microsoft/phi-4\",\n phi3: \"microsoft/Phi-3-mini-4k-instruct\",\n \"phi-3\": \"microsoft/Phi-3-mini-4k-instruct\",\n \"phi-3-mini\": \"microsoft/Phi-3-mini-4k-instruct\",\n\n // Llama 3.2 (Meta) - Requires HuggingFace authentication\n // Note: meta-llama models require accepting license at huggingface.co\n llama: \"meta-llama/Llama-3.2-1B-Instruct\",\n \"llama-3.2\": \"meta-llama/Llama-3.2-1B-Instruct\",\n \"llama-3.2-1b\": \"meta-llama/Llama-3.2-1B-Instruct\",\n \"llama-3.2-3b\": \"meta-llama/Llama-3.2-3B-Instruct\",\n\n // Gemma 3 (Google) - Standard transformer architecture with sliding window\n gemma: \"mlx-community/gemma-3-1b-it-4bit\",\n \"gemma-3\": \"mlx-community/gemma-3-1b-it-4bit\",\n \"gemma-3-1b\": \"mlx-community/gemma-3-1b-it-4bit\",\n \"gemma-3-1b-bf16\": \"mlx-community/gemma-3-1b-it-bf16\",\n \"gemma-3-4b\": \"mlx-community/gemma-3-4b-it-4bit\",\n \"gemma-3-4b-bf16\": \"mlx-community/gemma-3-4b-it-bf16\",\n \"gemma-3-12b\": \"mlx-community/gemma-3-12b-it-4bit\",\n \"gemma-3-27b\": \"mlx-community/gemma-3-27b-it-4bit\",\n\n // Gemma 3n (Google) - Efficient architecture with AltUp and Laurel\n // Note: Use -lm variants (language model only, no audio/vision)\n \"gemma-3n\": \"mlx-community/gemma-3n-E2B-it-lm-4bit\",\n \"gemma-3n-e2b\": \"mlx-community/gemma-3n-E2B-it-lm-4bit\",\n \"gemma-3n-e4b\": \"mlx-community/gemma-3n-E4B-it-lm-4bit\"\n} as const\n\nexport type RecommendedModelKey = keyof typeof RECOMMENDED_MODELS\n\n// MARK: - Public API\n\n/**\n * Check if the platform is Apple Silicon Mac\n */\nexport function isPlatformSupported(): boolean {\n return platform() === \"darwin\" && arch() === \"arm64\"\n}\n\n/**\n * Check if MLX is available on this system\n * (requires macOS 14+ on Apple Silicon with built binaries)\n */\nexport function isSupported(): boolean {\n if (!isPlatformSupported()) {\n return false\n }\n\n try {\n const b = loadBinding()\n\n return b.isAvailable()\n } catch {\n return false\n }\n}\n\n/**\n * Get the library version\n */\nexport function getVersion(): string {\n const b = loadBinding()\n\n return b.getVersion()\n}\n\n/**\n * Load a model from HuggingFace or local path\n *\n * @param modelId - HuggingFace model ID (e.g., \"mlx-community/gemma-3n-E2B-it-4bit\") or local path\n * @returns Model instance\n *\n * @example\n * ```typescript\n * import { loadModel, RECOMMENDED_MODELS } from \"node-mlx\"\n *\n * const model = loadModel(RECOMMENDED_MODELS[\"gemma-3n\"])\n * const result = model.generate(\"Hello, world!\")\n * console.log(result.text)\n * model.unload()\n * ```\n */\nexport function loadModel(modelId: string): Model {\n const b = loadBinding()\n const handle = b.loadModel(modelId)\n\n return {\n handle,\n\n generate(prompt: string, options?: GenerationOptions): GenerationResult {\n const jsonStr = b.generate(handle, prompt, {\n maxTokens: options?.maxTokens ?? 256,\n temperature: options?.temperature ?? 0.7,\n topP: options?.topP ?? 0.9,\n repetitionPenalty: options?.repetitionPenalty ?? 0,\n repetitionContextSize: options?.repetitionContextSize ?? 20\n })\n\n const result = JSON.parse(jsonStr) as JSONGenerationResult\n\n if (!result.success) {\n throw new Error(result.error ?? \"Generation failed\")\n }\n\n return {\n text: result.text ?? \"\",\n tokenCount: result.tokenCount ?? 0,\n tokensPerSecond: result.tokensPerSecond ?? 0\n }\n },\n\n generateStreaming(prompt: string, options?: GenerationOptions): StreamingResult {\n // Tokens are written directly to stdout by Swift\n const jsonStr = b.generateStreaming(handle, prompt, {\n maxTokens: options?.maxTokens ?? 256,\n temperature: options?.temperature ?? 0.7,\n topP: options?.topP ?? 0.9,\n repetitionPenalty: options?.repetitionPenalty ?? 0,\n repetitionContextSize: options?.repetitionContextSize ?? 20\n })\n\n const result = JSON.parse(jsonStr) as JSONGenerationResult\n\n if (!result.success) {\n throw new Error(result.error ?? \"Generation failed\")\n }\n\n return {\n tokenCount: result.tokenCount ?? 0,\n tokensPerSecond: result.tokensPerSecond ?? 0\n }\n },\n\n generateWithImage(\n prompt: string,\n imagePath: string,\n options?: GenerationOptions\n ): StreamingResult {\n // VLM generation with image - tokens are written directly to stdout by Swift\n const jsonStr = b.generateWithImage(handle, prompt, imagePath, {\n maxTokens: options?.maxTokens ?? 256,\n temperature: options?.temperature ?? 0.7,\n topP: options?.topP ?? 0.9,\n repetitionPenalty: options?.repetitionPenalty ?? 0,\n repetitionContextSize: options?.repetitionContextSize ?? 20\n })\n\n const result = JSON.parse(jsonStr) as JSONGenerationResult\n\n if (!result.success) {\n throw new Error(result.error ?? \"Generation failed\")\n }\n\n return {\n tokenCount: result.tokenCount ?? 0,\n tokensPerSecond: result.tokensPerSecond ?? 0\n }\n },\n\n isVLM(): boolean {\n return b.isVLM(handle)\n },\n\n unload(): void {\n b.unloadModel(handle)\n }\n }\n}\n\n/**\n * Generate text using a model (one-shot, loads and unloads model)\n *\n * @param modelId - HuggingFace model ID or local path\n * @param prompt - Input text\n * @param options - Generation options\n * @returns Generation result\n *\n * @example\n * ```typescript\n * import { generate } from \"node-mlx\"\n *\n * const result = generate(\n * RECOMMENDED_MODELS[\"gemma-3n\"],\n * \"Explain quantum computing\",\n * { maxTokens: 100 }\n * )\n * console.log(result.text)\n * ```\n */\nexport function generate(\n modelId: string,\n prompt: string,\n options?: GenerationOptions\n): GenerationResult {\n const model = loadModel(modelId)\n\n try {\n return model.generate(prompt, options)\n } finally {\n model.unload()\n }\n}\n"],"mappings":"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","names":["require","state","rl"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/index.ts"],"sourcesContent":["/**\n * MLX CLI - Interactive chat with LLMs on Apple Silicon\n *\n * Usage:\n * mlx # Interactive mode with default model\n * mlx --model llama-3.2-1b # Use a specific model\n * mlx \"What is 2+2?\" # One-shot query\n * mlx --list # List available models\n */\n\nimport * as readline from \"node:readline\"\nimport {\n loadModel,\n RECOMMENDED_MODELS,\n isSupported,\n isPlatformSupported,\n VERSION,\n type Model,\n type GenerationOptions,\n type RecommendedModelKey\n} from \"./index.js\"\n\n// ANSI colors\nconst colors = {\n reset: \"\\x1b[0m\",\n bold: \"\\x1b[1m\",\n dim: \"\\x1b[2m\",\n cyan: \"\\x1b[36m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n magenta: \"\\x1b[35m\",\n red: \"\\x1b[31m\"\n}\n\nfunction log(msg: string) {\n console.log(msg)\n}\n\nfunction error(msg: string) {\n console.error(`${colors.red}Error:${colors.reset} ${msg}`)\n}\n\nfunction printHeader() {\n log(\"\")\n log(`${colors.bold}${colors.cyan}╔══════════════════════════════════════╗${colors.reset}`)\n log(\n `${colors.bold}${colors.cyan}║${colors.reset} ${colors.bold}MLX CLI${colors.reset} - LLMs on Apple Silicon ${colors.cyan}║${colors.reset}`\n )\n log(`${colors.bold}${colors.cyan}╚══════════════════════════════════════╝${colors.reset}`)\n log(\"\")\n}\n\nfunction printHelp() {\n log(`${colors.bold}Usage:${colors.reset}`)\n log(` mlx Interactive chat`)\n log(` mlx \"prompt\" One-shot generation`)\n log(` mlx --model <name> Use specific model`)\n log(` mlx --image <path> Include image (VLM only)`)\n log(` mlx --repetition-penalty <1-2> Penalize repeated tokens (default: off)`)\n log(` mlx --list List available models`)\n log(` mlx --help Show this help`)\n log(\"\")\n log(`${colors.bold}Vision models (VLM):${colors.reset}`)\n log(` mlx --model gemma-3-4b --image photo.jpg \"What's in this image?\"`)\n log(\"\")\n log(`${colors.bold}Repetition penalty (for models that repeat):${colors.reset}`)\n log(` mlx --model gemma-3n --repetition-penalty 1.2 \"Tell me about AI\"`)\n log(\"\")\n log(`${colors.bold}Interactive commands:${colors.reset}`)\n log(` /model <name> Switch model`)\n log(` /image <path> Set image for next prompt`)\n log(` /temp <0-2> Set temperature`)\n log(` /tokens <n> Set max tokens`)\n log(` /rep <1-2> Set repetition penalty`)\n log(` /clear Clear conversation`)\n log(` /help Show commands`)\n log(` /quit Exit`)\n log(\"\")\n}\n\nfunction printModels() {\n log(`${colors.bold}Available models:${colors.reset}`)\n log(\"\")\n\n // Group models by family, showing unique HuggingFace IDs with all their aliases\n const modelsByHfId = new Map<string, string[]>()\n\n for (const [alias, hfId] of Object.entries(RECOMMENDED_MODELS)) {\n if (!modelsByHfId.has(hfId)) {\n modelsByHfId.set(hfId, [])\n }\n\n modelsByHfId.get(hfId)?.push(alias)\n }\n\n // Organize by family\n const families = [\n {\n name: \"Phi (Microsoft)\",\n prefix: \"Phi\",\n desc: \"Reasoning & coding\"\n },\n {\n name: \"Gemma (Google)\",\n prefix: \"gemma\",\n desc: \"Efficient on-device\"\n },\n {\n name: \"Llama (Meta)\",\n prefix: \"Llama\",\n desc: \"General purpose\"\n },\n {\n name: \"Qwen (Alibaba)\",\n prefix: \"Qwen\",\n desc: \"Multilingual\"\n },\n {\n name: \"Mistral\",\n prefix: \"Mistral\",\n desc: \"Balanced performance\"\n },\n {\n name: \"Ministral\",\n prefix: \"Ministral\",\n desc: \"Fast inference\"\n }\n ]\n\n for (const family of families) {\n const familyModels = Array.from(modelsByHfId.entries()).filter(([hfId]) =>\n hfId.toLowerCase().includes(family.prefix.toLowerCase())\n )\n\n if (familyModels.length === 0) continue\n\n log(`${colors.bold}${family.name}${colors.reset} ${colors.dim}— ${family.desc}${colors.reset}`)\n\n for (const [hfId, aliases] of familyModels) {\n // Sort aliases: shortest first, then alphabetically\n const sortedAliases = aliases.sort((a, b) => a.length - b.length || a.localeCompare(b))\n const primary = sortedAliases[0]\n const others = sortedAliases.slice(1)\n\n const aliasStr =\n others.length > 0\n ? `${colors.green}${primary ?? \"\"}${colors.reset} ${colors.dim}(${others.join(\", \")})${colors.reset}`\n : `${colors.green}${primary ?? \"\"}${colors.reset}`\n\n log(` ${aliasStr.padEnd(45)} ${colors.dim}${hfId}${colors.reset}`)\n }\n\n log(\"\")\n }\n\n log(`${colors.dim}Or use any mlx-community model:${colors.reset}`)\n log(` ${colors.cyan}node-mlx --model mlx-community/YourModel-4bit${colors.reset}`)\n log(\"\")\n}\n\nfunction resolveModel(name: string): string {\n // Check if it's a shortcut\n if (name in RECOMMENDED_MODELS) {\n return RECOMMENDED_MODELS[name as RecommendedModelKey]\n }\n\n // Check if it's already a full model ID\n if (name.includes(\"/\")) {\n return name\n }\n\n // Assume it's from mlx-community\n return `mlx-community/${name}`\n}\n\ninterface ChatState {\n model: Model | null\n modelName: string\n options: GenerationOptions\n history: Array<{ role: \"user\" | \"assistant\"; content: string }>\n imagePath: string | null // For VLM image input\n}\n\nfunction runInteractive(initialModel: string): void {\n const state: ChatState = {\n model: null,\n modelName: initialModel,\n options: {\n maxTokens: 512,\n temperature: 0.7,\n topP: 0.9,\n repetitionPenalty: 1.1\n },\n history: [],\n imagePath: null\n }\n\n // Load initial model\n log(`${colors.dim}Loading ${state.modelName}...${colors.reset}`)\n const modelId = resolveModel(state.modelName)\n\n try {\n state.model = loadModel(modelId)\n log(`${colors.green}✓${colors.reset} Model loaded`)\n } catch (err) {\n error(`Failed to load model: ${err instanceof Error ? err.message : String(err)}`)\n process.exit(1)\n }\n\n log(\"\")\n log(`${colors.dim}Type your message or /help for commands${colors.reset}`)\n log(\"\")\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout\n })\n\n const promptUser = (): void => {\n rl.question(`${colors.cyan}You:${colors.reset} `, (input) => {\n void handleUserInput(input, state, rl, promptUser)\n })\n }\n\n const handleUserInput = async (\n input: string,\n state: ChatState,\n rl: readline.Interface,\n next: () => void\n ): Promise<void> => {\n const trimmed = input.trim()\n\n if (!trimmed) {\n next()\n\n return\n }\n\n // Handle commands\n if (trimmed.startsWith(\"/\")) {\n await handleCommand(trimmed, state, rl)\n next()\n\n return\n }\n\n // Generate response\n if (!state.model) {\n error(\"No model loaded\")\n next()\n\n return\n }\n\n // Build prompt with history (simple format)\n const fullPrompt = buildPrompt(state.history, trimmed)\n\n state.history.push({ role: \"user\", content: trimmed })\n\n process.stdout.write(`${colors.magenta}AI:${colors.reset} `)\n\n try {\n let result\n\n // Check if we have an image to send\n if (state.imagePath && state.model.isVLM()) {\n result = state.model.generateWithImage(fullPrompt, state.imagePath, state.options)\n state.imagePath = null // Clear after use\n } else {\n // Use streaming - tokens are written directly to stdout\n result = state.model.generateStreaming(fullPrompt, state.options)\n }\n\n // Note: text already streamed, we only have stats\n log(\"\")\n log(\n `${colors.dim}(${String(result.tokenCount)} tokens, ${result.tokensPerSecond.toFixed(1)} tok/s)${colors.reset}`\n )\n log(\"\")\n\n // For history we'd need to capture the text, but streaming writes to stdout\n // For now, history won't track assistant responses in streaming mode\n state.history.push({ role: \"assistant\", content: \"[streamed response]\" })\n } catch (err) {\n log(\"\")\n error(err instanceof Error ? err.message : String(err))\n }\n\n next()\n }\n\n rl.on(\"close\", () => {\n log(\"\")\n log(`${colors.dim}Goodbye!${colors.reset}`)\n\n if (state.model) {\n state.model.unload()\n }\n\n process.exit(0)\n })\n\n promptUser()\n}\n\nfunction buildPrompt(\n history: Array<{ role: \"user\" | \"assistant\"; content: string }>,\n current: string\n): string {\n // Build multi-turn context without explicit role labels\n // The chat template in Swift handles the actual formatting\n // We just provide the conversation context\n let prompt = \"\"\n\n for (const msg of history.slice(-6)) {\n // Keep last 3 exchanges\n if (msg.role === \"user\") {\n prompt += `${msg.content}\\n\\n`\n } else {\n prompt += `${msg.content}\\n\\n`\n }\n }\n\n prompt += current\n\n return prompt\n}\n\nasync function handleCommand(input: string, state: ChatState, rl: readline.Interface) {\n const [cmd, ...args] = input.slice(1).split(\" \")\n const arg = args.join(\" \")\n\n switch (cmd) {\n case \"help\":\n case \"h\":\n printHelp()\n break\n\n case \"quit\":\n case \"q\":\n case \"exit\":\n rl.close()\n break\n\n case \"clear\":\n case \"c\":\n state.history = []\n log(`${colors.dim}Conversation cleared${colors.reset}`)\n break\n\n case \"model\":\n case \"m\":\n if (!arg) {\n log(`${colors.dim}Current model: ${state.modelName}${colors.reset}`)\n log(`${colors.dim}Use /model <name> to switch${colors.reset}`)\n } else {\n log(`${colors.dim}Loading ${arg}...${colors.reset}`)\n\n if (state.model) {\n state.model.unload()\n }\n\n try {\n state.model = loadModel(resolveModel(arg))\n state.modelName = arg\n state.history = []\n log(`${colors.green}✓${colors.reset} Switched to ${arg}`)\n } catch (err) {\n error(err instanceof Error ? err.message : String(err))\n }\n }\n\n break\n\n case \"temp\":\n case \"t\":\n if (!arg) {\n log(`${colors.dim}Temperature: ${String(state.options.temperature)}${colors.reset}`)\n } else {\n const temp = parseFloat(arg)\n\n if (isNaN(temp) || temp < 0 || temp > 2) {\n error(\"Temperature must be between 0 and 2\")\n } else {\n state.options.temperature = temp\n log(`${colors.dim}Temperature set to ${String(temp)}${colors.reset}`)\n }\n }\n\n break\n\n case \"tokens\":\n case \"n\":\n if (!arg) {\n log(`${colors.dim}Max tokens: ${String(state.options.maxTokens)}${colors.reset}`)\n } else {\n const tokens = parseInt(arg, 10)\n\n if (isNaN(tokens) || tokens < 1) {\n error(\"Tokens must be a positive number\")\n } else {\n state.options.maxTokens = tokens\n log(`${colors.dim}Max tokens set to ${String(tokens)}${colors.reset}`)\n }\n }\n\n break\n\n case \"rep\":\n case \"r\":\n if (!arg) {\n log(\n `${colors.dim}Repetition penalty: ${state.options.repetitionPenalty != null ? String(state.options.repetitionPenalty) : \"off\"}${colors.reset}`\n )\n } else {\n const penalty = parseFloat(arg)\n\n if (isNaN(penalty) || penalty < 1 || penalty > 2) {\n error(\"Repetition penalty must be between 1 and 2\")\n } else {\n state.options.repetitionPenalty = penalty\n log(`${colors.dim}Repetition penalty set to ${String(penalty)}${colors.reset}`)\n }\n }\n\n break\n\n case \"list\":\n case \"l\":\n printModels()\n break\n\n case \"image\":\n case \"i\":\n if (!arg) {\n if (state.imagePath) {\n log(`${colors.dim}Current image: ${state.imagePath}${colors.reset}`)\n } else {\n log(`${colors.dim}No image set. Use /image <path> to set one.${colors.reset}`)\n }\n } else {\n // Check if file exists\n const fs = await import(\"node:fs\")\n\n if (!fs.existsSync(arg)) {\n error(`Image not found: ${arg}`)\n } else if (!state.model?.isVLM()) {\n error(`Current model doesn't support images. Use a VLM like gemma-3-4b.`)\n } else {\n state.imagePath = arg\n log(`${colors.green}✓${colors.reset} Image set: ${arg}`)\n log(`${colors.dim}The next message will include this image.${colors.reset}`)\n }\n }\n\n break\n\n default:\n error(`Unknown command: /${cmd ?? \"\"}. Type /help for commands.`)\n }\n}\n\nfunction runOneShot(\n modelName: string,\n prompt: string,\n imagePath: string | null,\n options: GenerationOptions\n) {\n log(`${colors.dim}Loading ${modelName}...${colors.reset}`)\n\n const modelId = resolveModel(modelName)\n\n try {\n const model = loadModel(modelId)\n\n let result\n\n // Check if we have an image to process\n if (imagePath) {\n if (!model.isVLM()) {\n error(`Model ${modelName} doesn't support images. Use a VLM like gemma-3-4b.`)\n model.unload()\n process.exit(1)\n }\n\n result = model.generateWithImage(prompt, imagePath, options)\n } else {\n // Use streaming - tokens are written directly to stdout\n result = model.generateStreaming(prompt, options)\n }\n\n // Add newline after streamed output\n log(\"\")\n log(\n `${colors.dim}(${String(result.tokenCount)} tokens, ${result.tokensPerSecond.toFixed(1)} tok/s)${colors.reset}`\n )\n\n model.unload()\n } catch (err) {\n error(err instanceof Error ? err.message : String(err))\n process.exit(1)\n }\n}\n\n// Parse CLI arguments\nfunction parseArgs(): {\n model: string\n prompt: string | null\n imagePath: string | null\n options: GenerationOptions\n command: \"chat\" | \"oneshot\" | \"list\" | \"help\" | \"version\"\n} {\n const args = process.argv.slice(2)\n let model = \"qwen\" // Default to Qwen (no auth required)\n let prompt: string | null = null\n let imagePath: string | null = null\n const options: GenerationOptions = {\n maxTokens: 512,\n temperature: 0.7,\n topP: 0.9\n }\n let command: \"chat\" | \"oneshot\" | \"list\" | \"help\" | \"version\" = \"chat\"\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]\n\n if (arg === \"--help\" || arg === \"-h\") {\n command = \"help\"\n } else if (arg === \"--version\" || arg === \"-v\") {\n command = \"version\"\n } else if (arg === \"--list\" || arg === \"-l\") {\n command = \"list\"\n } else if (arg === \"--model\" || arg === \"-m\") {\n model = args[++i] || model\n } else if (arg === \"--image\" || arg === \"-i\") {\n imagePath = args[++i] || null\n } else if (arg === \"--temp\" || arg === \"-t\") {\n options.temperature = parseFloat(args[++i] || \"0.7\")\n } else if (arg === \"--tokens\" || arg === \"-n\") {\n options.maxTokens = parseInt(args[++i] || \"512\", 10)\n } else if (arg === \"--repetition-penalty\" || arg === \"-r\") {\n options.repetitionPenalty = parseFloat(args[++i] || \"1.2\")\n } else if (arg && !arg.startsWith(\"-\")) {\n // Positional argument: this is the prompt (model must be set via --model)\n if (prompt === null) {\n prompt = arg\n command = \"oneshot\"\n }\n }\n }\n\n return { model, prompt, imagePath, options, command }\n}\n\n// Main\nfunction main(): void {\n const { model, prompt, imagePath, options, command } = parseArgs()\n\n // Commands that don't need Apple Silicon\n switch (command) {\n case \"help\":\n printHeader()\n printHelp()\n\n return\n\n case \"version\":\n log(`node-mlx v${VERSION}`)\n\n return\n\n case \"list\":\n printHeader()\n printModels()\n\n return\n }\n\n // Check platform for commands that need the runtime\n if (!isPlatformSupported()) {\n error(\"node-mlx requires macOS on Apple Silicon (M1/M2/M3/M4)\")\n process.exit(1)\n }\n\n if (!isSupported()) {\n error(\"Native libraries not found. Run 'pnpm build:swift && pnpm build:native' first.\")\n process.exit(1)\n }\n\n switch (command) {\n case \"oneshot\":\n if (prompt) {\n runOneShot(model, prompt, imagePath, options)\n }\n\n break\n\n case \"chat\":\n printHeader()\n runInteractive(model)\n break\n }\n}\n\ntry {\n main()\n} catch (err: unknown) {\n error(err instanceof Error ? err.message : String(err))\n process.exit(1)\n}\n","import { platform, arch } from \"node:os\"\nimport { join, dirname } from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\nimport { existsSync, readFileSync } from \"node:fs\"\nimport { createRequire } from \"node:module\"\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = dirname(__filename)\nconst require = createRequire(import.meta.url)\n\n// Read version from package.json\nconst packageJsonPath = join(__dirname, \"..\", \"package.json\")\nconst packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\")) as { version: string }\n\n/** Package version */\nexport const VERSION = packageJson.version\n\n// Native binding interface\ninterface NativeBinding {\n initialize(dylibPath: string): boolean\n isInitialized(): boolean\n loadModel(modelId: string): number\n unloadModel(handle: number): void\n generate(\n handle: number,\n prompt: string,\n options?: {\n maxTokens?: number\n temperature?: number\n topP?: number\n repetitionPenalty?: number\n repetitionContextSize?: number\n }\n ): string // Returns JSON string\n generateStreaming(\n handle: number,\n prompt: string,\n options?: {\n maxTokens?: number\n temperature?: number\n topP?: number\n repetitionPenalty?: number\n repetitionContextSize?: number\n }\n ): string // Streams to stdout, returns JSON stats\n generateWithImage(\n handle: number,\n prompt: string,\n imagePath: string,\n options?: {\n maxTokens?: number\n temperature?: number\n topP?: number\n repetitionPenalty?: number\n repetitionContextSize?: number\n }\n ): string // VLM: Streams to stdout, returns JSON stats\n isVLM(handle: number): boolean\n isAvailable(): boolean\n getVersion(): string\n}\n\n// JSON response from Swift\ninterface JSONGenerationResult {\n success: boolean\n text?: string\n tokenCount?: number\n tokensPerSecond?: number\n error?: string\n}\n\n// Load the native addon\nlet binding: NativeBinding | null = null\nlet initialized = false\n\n/**\n * Load native addon using node-gyp-build (prebuilds) or fallback to built addon\n */\nfunction loadNativeAddon(): NativeBinding {\n // Try node-gyp-build first (prebuilds)\n try {\n const gypBuild = require(\"node-gyp-build\") as (dir: string) => NativeBinding\n const nativeDir = join(__dirname, \"..\", \"native\")\n\n if (existsSync(join(__dirname, \"..\", \"prebuilds\"))) {\n return gypBuild(join(__dirname, \"..\"))\n }\n\n // Fallback to native/build if no prebuilds\n if (existsSync(join(nativeDir, \"build\"))) {\n return gypBuild(nativeDir)\n }\n } catch {\n // node-gyp-build failed, try manual loading\n }\n\n // Manual fallback: try different paths for the native addon\n const possibleAddonPaths = [\n // From package dist/ (npm installed)\n join(__dirname, \"..\", \"prebuilds\", \"darwin-arm64\", \"node.napi.node\"),\n // From native/build (local development)\n join(__dirname, \"..\", \"native\", \"build\", \"Release\", \"node_mlx.node\"),\n // From project root (monorepo development)\n join(process.cwd(), \"packages\", \"node-mlx\", \"native\", \"build\", \"Release\", \"node_mlx.node\")\n ]\n\n for (const p of possibleAddonPaths) {\n if (existsSync(p)) {\n return require(p) as NativeBinding\n }\n }\n\n throw new Error(\n \"Native addon not found. Run 'pnpm build:native' first.\\n\" +\n `Searched paths:\\n${possibleAddonPaths.join(\"\\n\")}`\n )\n}\n\n/**\n * Find Swift library path\n * Note: The library is expected to be in a directory with mlx.metallib for MLX to find it\n */\nfunction findSwiftLibrary(): string {\n const possibleDylibPaths = [\n // From package swift/ (preferred - has metallib co-located)\n join(__dirname, \"..\", \"swift\", \"libNodeMLX.dylib\"),\n // From project root packages/node-mlx/swift/ (monorepo development)\n join(process.cwd(), \"packages\", \"node-mlx\", \"swift\", \"libNodeMLX.dylib\"),\n // Fallback to packages/swift/.build (monorepo dev)\n join(__dirname, \"..\", \"..\", \"swift\", \".build\", \"release\", \"libNodeMLX.dylib\"),\n join(__dirname, \"..\", \"..\", \"..\", \"swift\", \".build\", \"release\", \"libNodeMLX.dylib\"),\n join(process.cwd(), \"packages\", \"swift\", \".build\", \"release\", \"libNodeMLX.dylib\")\n ]\n\n for (const p of possibleDylibPaths) {\n if (existsSync(p)) {\n return p\n }\n }\n\n throw new Error(\n \"Swift library not found. Run 'pnpm build:swift' first.\\n\" +\n `Searched paths:\\n${possibleDylibPaths.join(\"\\n\")}`\n )\n}\n\nfunction loadBinding(): NativeBinding {\n if (binding && initialized) {\n return binding\n }\n\n if (platform() !== \"darwin\" || arch() !== \"arm64\") {\n throw new Error(\"node-mlx is only supported on macOS Apple Silicon (arm64)\")\n }\n\n binding = loadNativeAddon()\n const dylibPath = findSwiftLibrary()\n const success = binding.initialize(dylibPath)\n\n if (!success) {\n throw new Error(\"Failed to initialize node-mlx native library\")\n }\n\n initialized = true\n\n return binding\n}\n\n// MARK: - Public Types\n\nexport interface GenerationOptions {\n maxTokens?: number\n temperature?: number\n topP?: number\n /** Penalty for repeating tokens (1.0 = no penalty, 1.1-1.2 recommended) */\n repetitionPenalty?: number\n /** Number of recent tokens to consider for penalty (default: 20) */\n repetitionContextSize?: number\n}\n\nexport interface GenerationResult {\n text: string\n tokenCount: number\n tokensPerSecond: number\n}\n\nexport interface StreamingResult {\n tokenCount: number\n tokensPerSecond: number\n}\n\nexport interface Model {\n /** Generate text from a prompt */\n generate(prompt: string, options?: GenerationOptions): GenerationResult\n\n /** Generate text with streaming - tokens are written directly to stdout */\n generateStreaming(prompt: string, options?: GenerationOptions): StreamingResult\n\n /** Generate text from a prompt with an image (VLM only) */\n generateWithImage(prompt: string, imagePath: string, options?: GenerationOptions): StreamingResult\n\n /** Check if this model supports images (is a Vision-Language Model) */\n isVLM(): boolean\n\n /** Unload the model from memory */\n unload(): void\n\n /** Model handle (internal use) */\n readonly handle: number\n}\n\n// MARK: - Recommended Models\n\nexport const RECOMMENDED_MODELS = {\n // Qwen 3 (Alibaba) - With Q/K norms\n qwen: \"lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit\", // Default to Qwen3\n qwen3: \"lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit\",\n \"qwen-3\": \"lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit\",\n \"qwen-3-4b\": \"lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit\",\n \"qwen-3-0.6b\": \"mlx-community/Qwen3-0.6B-4bit\",\n \"qwen-3-1.7b\": \"mlx-community/Qwen3-1.7B-4bit\",\n\n // Qwen 2.5 (Alibaba) - Legacy, with attention bias\n \"qwen-2.5\": \"Qwen/Qwen2.5-1.5B-Instruct\",\n \"qwen-2.5-1.5b\": \"Qwen/Qwen2.5-1.5B-Instruct\",\n \"qwen-2.5-3b\": \"Qwen/Qwen2.5-3B-Instruct\",\n\n // Phi (Microsoft) - Working with fused QKV and RoPE\n phi: \"mlx-community/Phi-3.5-mini-instruct-4bit\", // Default to 3.5 (smaller, faster to download)\n phi4: \"mlx-community/phi-4-4bit\",\n \"phi-4\": \"mlx-community/phi-4-4bit\",\n \"phi-3.5\": \"mlx-community/Phi-3.5-mini-instruct-4bit\",\n \"phi-3.5-mini\": \"mlx-community/Phi-3.5-mini-instruct-4bit\",\n phi3: \"mlx-community/Phi-3-mini-4k-instruct-4bit\",\n \"phi-3\": \"mlx-community/Phi-3-mini-4k-instruct-4bit\",\n \"phi-3-mini\": \"mlx-community/Phi-3-mini-4k-instruct-4bit\",\n\n // Llama 3.2 (Meta) - Requires HuggingFace authentication\n // Note: meta-llama models require accepting license at huggingface.co\n llama: \"meta-llama/Llama-3.2-1B-Instruct\",\n \"llama-3.2\": \"meta-llama/Llama-3.2-1B-Instruct\",\n \"llama-3.2-1b\": \"meta-llama/Llama-3.2-1B-Instruct\",\n \"llama-3.2-3b\": \"meta-llama/Llama-3.2-3B-Instruct\",\n\n // Gemma 3 (Google) - Standard transformer architecture with sliding window\n gemma: \"mlx-community/gemma-3-1b-it-4bit\",\n \"gemma-3\": \"mlx-community/gemma-3-1b-it-4bit\",\n \"gemma-3-1b\": \"mlx-community/gemma-3-1b-it-4bit\",\n \"gemma-3-1b-bf16\": \"mlx-community/gemma-3-1b-it-bf16\",\n \"gemma-3-4b\": \"mlx-community/gemma-3-4b-it-4bit\",\n \"gemma-3-4b-bf16\": \"mlx-community/gemma-3-4b-it-bf16\",\n \"gemma-3-12b\": \"mlx-community/gemma-3-12b-it-4bit\",\n \"gemma-3-27b\": \"mlx-community/gemma-3-27b-it-4bit\",\n\n // Gemma 3n (Google) - Efficient architecture with AltUp and Laurel\n // Note: Use -lm variants (language model only, no audio/vision)\n \"gemma-3n\": \"mlx-community/gemma-3n-E4B-it-lm-4bit\",\n \"gemma-3n-e2b\": \"mlx-community/gemma-3n-E2B-it-lm-4bit\",\n \"gemma-3n-e4b\": \"mlx-community/gemma-3n-E4B-it-lm-4bit\"\n} as const\n\nexport type RecommendedModelKey = keyof typeof RECOMMENDED_MODELS\n\n// MARK: - Public API\n\n/**\n * Check if the platform is Apple Silicon Mac\n */\nexport function isPlatformSupported(): boolean {\n return platform() === \"darwin\" && arch() === \"arm64\"\n}\n\n/**\n * Check if MLX is available on this system\n * (requires macOS 14+ on Apple Silicon with built binaries)\n */\nexport function isSupported(): boolean {\n if (!isPlatformSupported()) {\n return false\n }\n\n try {\n const b = loadBinding()\n\n return b.isAvailable()\n } catch {\n return false\n }\n}\n\n/**\n * Get the library version\n */\nexport function getVersion(): string {\n const b = loadBinding()\n\n return b.getVersion()\n}\n\n/**\n * Load a model from HuggingFace or local path\n *\n * @param modelId - HuggingFace model ID (e.g., \"mlx-community/gemma-3n-E2B-it-4bit\") or local path\n * @returns Model instance\n *\n * @example\n * ```typescript\n * import { loadModel, RECOMMENDED_MODELS } from \"node-mlx\"\n *\n * const model = loadModel(RECOMMENDED_MODELS[\"gemma-3n\"])\n * const result = model.generate(\"Hello, world!\")\n * console.log(result.text)\n * model.unload()\n * ```\n */\n/**\n * Resolve a model ID or alias to a full HuggingFace model ID\n * @param modelId - Either a full HuggingFace model ID (e.g., \"mlx-community/phi-4-4bit\") or a short alias (e.g., \"phi4\")\n * @returns The full HuggingFace model ID\n */\nfunction resolveModelId(modelId: string): string {\n // Check if it's an alias in RECOMMENDED_MODELS\n if (modelId in RECOMMENDED_MODELS) {\n return RECOMMENDED_MODELS[modelId as keyof typeof RECOMMENDED_MODELS]\n }\n\n // Otherwise assume it's already a full model ID\n return modelId\n}\n\nexport function loadModel(modelId: string): Model {\n const b = loadBinding()\n const resolvedId = resolveModelId(modelId)\n const handle = b.loadModel(resolvedId)\n\n return {\n handle,\n\n generate(prompt: string, options?: GenerationOptions): GenerationResult {\n const jsonStr = b.generate(handle, prompt, {\n maxTokens: options?.maxTokens ?? 256,\n temperature: options?.temperature ?? 0.7,\n topP: options?.topP ?? 0.9,\n repetitionPenalty: options?.repetitionPenalty ?? 1.1,\n repetitionContextSize: options?.repetitionContextSize ?? 20\n })\n\n const result = JSON.parse(jsonStr) as JSONGenerationResult\n\n if (!result.success) {\n throw new Error(result.error ?? \"Generation failed\")\n }\n\n return {\n text: result.text ?? \"\",\n tokenCount: result.tokenCount ?? 0,\n tokensPerSecond: result.tokensPerSecond ?? 0\n }\n },\n\n generateStreaming(prompt: string, options?: GenerationOptions): StreamingResult {\n // Tokens are written directly to stdout by Swift\n const jsonStr = b.generateStreaming(handle, prompt, {\n maxTokens: options?.maxTokens ?? 256,\n temperature: options?.temperature ?? 0.7,\n topP: options?.topP ?? 0.9,\n repetitionPenalty: options?.repetitionPenalty ?? 1.1,\n repetitionContextSize: options?.repetitionContextSize ?? 20\n })\n\n const result = JSON.parse(jsonStr) as JSONGenerationResult\n\n if (!result.success) {\n throw new Error(result.error ?? \"Generation failed\")\n }\n\n return {\n tokenCount: result.tokenCount ?? 0,\n tokensPerSecond: result.tokensPerSecond ?? 0\n }\n },\n\n generateWithImage(\n prompt: string,\n imagePath: string,\n options?: GenerationOptions\n ): StreamingResult {\n // VLM generation with image - tokens are written directly to stdout by Swift\n const jsonStr = b.generateWithImage(handle, prompt, imagePath, {\n maxTokens: options?.maxTokens ?? 256,\n temperature: options?.temperature ?? 0.7,\n topP: options?.topP ?? 0.9,\n repetitionPenalty: options?.repetitionPenalty ?? 1.1,\n repetitionContextSize: options?.repetitionContextSize ?? 20\n })\n\n const result = JSON.parse(jsonStr) as JSONGenerationResult\n\n if (!result.success) {\n throw new Error(result.error ?? \"Generation failed\")\n }\n\n return {\n tokenCount: result.tokenCount ?? 0,\n tokensPerSecond: result.tokensPerSecond ?? 0\n }\n },\n\n isVLM(): boolean {\n return b.isVLM(handle)\n },\n\n unload(): void {\n b.unloadModel(handle)\n }\n }\n}\n\n/**\n * Generate text using a model (one-shot, loads and unloads model)\n *\n * @param modelId - HuggingFace model ID or local path\n * @param prompt - Input text\n * @param options - Generation options\n * @returns Generation result\n *\n * @example\n * ```typescript\n * import { generate } from \"node-mlx\"\n *\n * const result = generate(\n * RECOMMENDED_MODELS[\"gemma-3n\"],\n * \"Explain quantum computing\",\n * { maxTokens: 100 }\n * )\n * console.log(result.text)\n * ```\n */\nexport function generate(\n modelId: string,\n prompt: string,\n options?: GenerationOptions\n): GenerationResult {\n const model = loadModel(modelId)\n\n try {\n return model.generate(prompt, options)\n } finally {\n model.unload()\n }\n}\n"],"mappings":"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","names":["require","state","rl"]}
|
package/dist/index.cjs
CHANGED
|
@@ -118,21 +118,28 @@ function loadBinding() {
|
|
|
118
118
|
return binding;
|
|
119
119
|
}
|
|
120
120
|
var RECOMMENDED_MODELS = {
|
|
121
|
-
// Qwen
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
// Qwen 3 (Alibaba) - With Q/K norms
|
|
122
|
+
qwen: "lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit",
|
|
123
|
+
// Default to Qwen3
|
|
124
|
+
qwen3: "lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit",
|
|
125
|
+
"qwen-3": "lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit",
|
|
126
|
+
"qwen-3-4b": "lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit",
|
|
127
|
+
"qwen-3-0.6b": "mlx-community/Qwen3-0.6B-4bit",
|
|
128
|
+
"qwen-3-1.7b": "mlx-community/Qwen3-1.7B-4bit",
|
|
129
|
+
// Qwen 2.5 (Alibaba) - Legacy, with attention bias
|
|
124
130
|
"qwen-2.5": "Qwen/Qwen2.5-1.5B-Instruct",
|
|
125
|
-
"qwen-2.5-0.5b": "Qwen/Qwen2.5-0.5B-Instruct",
|
|
126
131
|
"qwen-2.5-1.5b": "Qwen/Qwen2.5-1.5B-Instruct",
|
|
127
132
|
"qwen-2.5-3b": "Qwen/Qwen2.5-3B-Instruct",
|
|
128
133
|
// Phi (Microsoft) - Working with fused QKV and RoPE
|
|
129
|
-
phi: "
|
|
130
|
-
// Default to
|
|
131
|
-
phi4: "
|
|
132
|
-
"phi-4": "
|
|
133
|
-
|
|
134
|
-
"phi-3": "
|
|
135
|
-
|
|
134
|
+
phi: "mlx-community/Phi-3.5-mini-instruct-4bit",
|
|
135
|
+
// Default to 3.5 (smaller, faster to download)
|
|
136
|
+
phi4: "mlx-community/phi-4-4bit",
|
|
137
|
+
"phi-4": "mlx-community/phi-4-4bit",
|
|
138
|
+
"phi-3.5": "mlx-community/Phi-3.5-mini-instruct-4bit",
|
|
139
|
+
"phi-3.5-mini": "mlx-community/Phi-3.5-mini-instruct-4bit",
|
|
140
|
+
phi3: "mlx-community/Phi-3-mini-4k-instruct-4bit",
|
|
141
|
+
"phi-3": "mlx-community/Phi-3-mini-4k-instruct-4bit",
|
|
142
|
+
"phi-3-mini": "mlx-community/Phi-3-mini-4k-instruct-4bit",
|
|
136
143
|
// Llama 3.2 (Meta) - Requires HuggingFace authentication
|
|
137
144
|
// Note: meta-llama models require accepting license at huggingface.co
|
|
138
145
|
llama: "meta-llama/Llama-3.2-1B-Instruct",
|
|
@@ -150,7 +157,7 @@ var RECOMMENDED_MODELS = {
|
|
|
150
157
|
"gemma-3-27b": "mlx-community/gemma-3-27b-it-4bit",
|
|
151
158
|
// Gemma 3n (Google) - Efficient architecture with AltUp and Laurel
|
|
152
159
|
// Note: Use -lm variants (language model only, no audio/vision)
|
|
153
|
-
"gemma-3n": "mlx-community/gemma-3n-
|
|
160
|
+
"gemma-3n": "mlx-community/gemma-3n-E4B-it-lm-4bit",
|
|
154
161
|
"gemma-3n-e2b": "mlx-community/gemma-3n-E2B-it-lm-4bit",
|
|
155
162
|
"gemma-3n-e4b": "mlx-community/gemma-3n-E4B-it-lm-4bit"
|
|
156
163
|
};
|
|
@@ -172,9 +179,16 @@ function getVersion() {
|
|
|
172
179
|
const b = loadBinding();
|
|
173
180
|
return b.getVersion();
|
|
174
181
|
}
|
|
182
|
+
function resolveModelId(modelId) {
|
|
183
|
+
if (modelId in RECOMMENDED_MODELS) {
|
|
184
|
+
return RECOMMENDED_MODELS[modelId];
|
|
185
|
+
}
|
|
186
|
+
return modelId;
|
|
187
|
+
}
|
|
175
188
|
function loadModel(modelId) {
|
|
176
189
|
const b = loadBinding();
|
|
177
|
-
const
|
|
190
|
+
const resolvedId = resolveModelId(modelId);
|
|
191
|
+
const handle = b.loadModel(resolvedId);
|
|
178
192
|
return {
|
|
179
193
|
handle,
|
|
180
194
|
generate(prompt, options) {
|
|
@@ -182,7 +196,7 @@ function loadModel(modelId) {
|
|
|
182
196
|
maxTokens: options?.maxTokens ?? 256,
|
|
183
197
|
temperature: options?.temperature ?? 0.7,
|
|
184
198
|
topP: options?.topP ?? 0.9,
|
|
185
|
-
repetitionPenalty: options?.repetitionPenalty ??
|
|
199
|
+
repetitionPenalty: options?.repetitionPenalty ?? 1.1,
|
|
186
200
|
repetitionContextSize: options?.repetitionContextSize ?? 20
|
|
187
201
|
});
|
|
188
202
|
const result = JSON.parse(jsonStr);
|
|
@@ -200,7 +214,7 @@ function loadModel(modelId) {
|
|
|
200
214
|
maxTokens: options?.maxTokens ?? 256,
|
|
201
215
|
temperature: options?.temperature ?? 0.7,
|
|
202
216
|
topP: options?.topP ?? 0.9,
|
|
203
|
-
repetitionPenalty: options?.repetitionPenalty ??
|
|
217
|
+
repetitionPenalty: options?.repetitionPenalty ?? 1.1,
|
|
204
218
|
repetitionContextSize: options?.repetitionContextSize ?? 20
|
|
205
219
|
});
|
|
206
220
|
const result = JSON.parse(jsonStr);
|
|
@@ -217,7 +231,7 @@ function loadModel(modelId) {
|
|
|
217
231
|
maxTokens: options?.maxTokens ?? 256,
|
|
218
232
|
temperature: options?.temperature ?? 0.7,
|
|
219
233
|
topP: options?.topP ?? 0.9,
|
|
220
|
-
repetitionPenalty: options?.repetitionPenalty ??
|
|
234
|
+
repetitionPenalty: options?.repetitionPenalty ?? 1.1,
|
|
221
235
|
repetitionContextSize: options?.repetitionContextSize ?? 20
|
|
222
236
|
});
|
|
223
237
|
const result = JSON.parse(jsonStr);
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_tsx@4.21.0_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js"],"sourcesContent":["import { platform, arch } from \"node:os\"\nimport { join, dirname } from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\nimport { existsSync, readFileSync } from \"node:fs\"\nimport { createRequire } from \"node:module\"\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = dirname(__filename)\nconst require = createRequire(import.meta.url)\n\n// Read version from package.json\nconst packageJsonPath = join(__dirname, \"..\", \"package.json\")\nconst packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\")) as { version: string }\n\n/** Package version */\nexport const VERSION = packageJson.version\n\n// Native binding interface\ninterface NativeBinding {\n initialize(dylibPath: string): boolean\n isInitialized(): boolean\n loadModel(modelId: string): number\n unloadModel(handle: number): void\n generate(\n handle: number,\n prompt: string,\n options?: {\n maxTokens?: number\n temperature?: number\n topP?: number\n repetitionPenalty?: number\n repetitionContextSize?: number\n }\n ): string // Returns JSON string\n generateStreaming(\n handle: number,\n prompt: string,\n options?: {\n maxTokens?: number\n temperature?: number\n topP?: number\n repetitionPenalty?: number\n repetitionContextSize?: number\n }\n ): string // Streams to stdout, returns JSON stats\n generateWithImage(\n handle: number,\n prompt: string,\n imagePath: string,\n options?: {\n maxTokens?: number\n temperature?: number\n topP?: number\n repetitionPenalty?: number\n repetitionContextSize?: number\n }\n ): string // VLM: Streams to stdout, returns JSON stats\n isVLM(handle: number): boolean\n isAvailable(): boolean\n getVersion(): string\n}\n\n// JSON response from Swift\ninterface JSONGenerationResult {\n success: boolean\n text?: string\n tokenCount?: number\n tokensPerSecond?: number\n error?: string\n}\n\n// Load the native addon\nlet binding: NativeBinding | null = null\nlet initialized = false\n\n/**\n * Load native addon using node-gyp-build (prebuilds) or fallback to built addon\n */\nfunction loadNativeAddon(): NativeBinding {\n // Try node-gyp-build first (prebuilds)\n try {\n const gypBuild = require(\"node-gyp-build\") as (dir: string) => NativeBinding\n const nativeDir = join(__dirname, \"..\", \"native\")\n\n if (existsSync(join(__dirname, \"..\", \"prebuilds\"))) {\n return gypBuild(join(__dirname, \"..\"))\n }\n\n // Fallback to native/build if no prebuilds\n if (existsSync(join(nativeDir, \"build\"))) {\n return gypBuild(nativeDir)\n }\n } catch {\n // node-gyp-build failed, try manual loading\n }\n\n // Manual fallback: try different paths for the native addon\n const possibleAddonPaths = [\n // From package dist/ (npm installed)\n join(__dirname, \"..\", \"prebuilds\", \"darwin-arm64\", \"node.napi.node\"),\n // From native/build (local development)\n join(__dirname, \"..\", \"native\", \"build\", \"Release\", \"node_mlx.node\"),\n // From project root (monorepo development)\n join(process.cwd(), \"packages\", \"node-mlx\", \"native\", \"build\", \"Release\", \"node_mlx.node\")\n ]\n\n for (const p of possibleAddonPaths) {\n if (existsSync(p)) {\n return require(p) as NativeBinding\n }\n }\n\n throw new Error(\n \"Native addon not found. Run 'pnpm build:native' first.\\n\" +\n `Searched paths:\\n${possibleAddonPaths.join(\"\\n\")}`\n )\n}\n\n/**\n * Find Swift library path\n * Note: The library is expected to be in a directory with mlx.metallib for MLX to find it\n */\nfunction findSwiftLibrary(): string {\n const possibleDylibPaths = [\n // From package swift/ (preferred - has metallib co-located)\n join(__dirname, \"..\", \"swift\", \"libNodeMLX.dylib\"),\n // From project root packages/node-mlx/swift/ (monorepo development)\n join(process.cwd(), \"packages\", \"node-mlx\", \"swift\", \"libNodeMLX.dylib\"),\n // Fallback to packages/swift/.build (monorepo dev)\n join(__dirname, \"..\", \"..\", \"swift\", \".build\", \"release\", \"libNodeMLX.dylib\"),\n join(__dirname, \"..\", \"..\", \"..\", \"swift\", \".build\", \"release\", \"libNodeMLX.dylib\"),\n join(process.cwd(), \"packages\", \"swift\", \".build\", \"release\", \"libNodeMLX.dylib\")\n ]\n\n for (const p of possibleDylibPaths) {\n if (existsSync(p)) {\n return p\n }\n }\n\n throw new Error(\n \"Swift library not found. Run 'pnpm build:swift' first.\\n\" +\n `Searched paths:\\n${possibleDylibPaths.join(\"\\n\")}`\n )\n}\n\nfunction loadBinding(): NativeBinding {\n if (binding && initialized) {\n return binding\n }\n\n if (platform() !== \"darwin\" || arch() !== \"arm64\") {\n throw new Error(\"node-mlx is only supported on macOS Apple Silicon (arm64)\")\n }\n\n binding = loadNativeAddon()\n const dylibPath = findSwiftLibrary()\n const success = binding.initialize(dylibPath)\n\n if (!success) {\n throw new Error(\"Failed to initialize node-mlx native library\")\n }\n\n initialized = true\n\n return binding\n}\n\n// MARK: - Public Types\n\nexport interface GenerationOptions {\n maxTokens?: number\n temperature?: number\n topP?: number\n /** Penalty for repeating tokens (1.0 = no penalty, 1.1-1.2 recommended) */\n repetitionPenalty?: number\n /** Number of recent tokens to consider for penalty (default: 20) */\n repetitionContextSize?: number\n}\n\nexport interface GenerationResult {\n text: string\n tokenCount: number\n tokensPerSecond: number\n}\n\nexport interface StreamingResult {\n tokenCount: number\n tokensPerSecond: number\n}\n\nexport interface Model {\n /** Generate text from a prompt */\n generate(prompt: string, options?: GenerationOptions): GenerationResult\n\n /** Generate text with streaming - tokens are written directly to stdout */\n generateStreaming(prompt: string, options?: GenerationOptions): StreamingResult\n\n /** Generate text from a prompt with an image (VLM only) */\n generateWithImage(prompt: string, imagePath: string, options?: GenerationOptions): StreamingResult\n\n /** Check if this model supports images (is a Vision-Language Model) */\n isVLM(): boolean\n\n /** Unload the model from memory */\n unload(): void\n\n /** Model handle (internal use) */\n readonly handle: number\n}\n\n// MARK: - Recommended Models\n\nexport const RECOMMENDED_MODELS = {\n // Qwen 2.5 (Alibaba) - Working with proper RoPE support\n // Using non-quantized models - quantized models have loading issues\n qwen: \"Qwen/Qwen2.5-1.5B-Instruct\",\n \"qwen-2.5\": \"Qwen/Qwen2.5-1.5B-Instruct\",\n \"qwen-2.5-0.5b\": \"Qwen/Qwen2.5-0.5B-Instruct\",\n \"qwen-2.5-1.5b\": \"Qwen/Qwen2.5-1.5B-Instruct\",\n \"qwen-2.5-3b\": \"Qwen/Qwen2.5-3B-Instruct\",\n\n // Phi (Microsoft) - Working with fused QKV and RoPE\n phi: \"microsoft/phi-4\", // Default to latest\n phi4: \"microsoft/phi-4\",\n \"phi-4\": \"microsoft/phi-4\",\n phi3: \"microsoft/Phi-3-mini-4k-instruct\",\n \"phi-3\": \"microsoft/Phi-3-mini-4k-instruct\",\n \"phi-3-mini\": \"microsoft/Phi-3-mini-4k-instruct\",\n\n // Llama 3.2 (Meta) - Requires HuggingFace authentication\n // Note: meta-llama models require accepting license at huggingface.co\n llama: \"meta-llama/Llama-3.2-1B-Instruct\",\n \"llama-3.2\": \"meta-llama/Llama-3.2-1B-Instruct\",\n \"llama-3.2-1b\": \"meta-llama/Llama-3.2-1B-Instruct\",\n \"llama-3.2-3b\": \"meta-llama/Llama-3.2-3B-Instruct\",\n\n // Gemma 3 (Google) - Standard transformer architecture with sliding window\n gemma: \"mlx-community/gemma-3-1b-it-4bit\",\n \"gemma-3\": \"mlx-community/gemma-3-1b-it-4bit\",\n \"gemma-3-1b\": \"mlx-community/gemma-3-1b-it-4bit\",\n \"gemma-3-1b-bf16\": \"mlx-community/gemma-3-1b-it-bf16\",\n \"gemma-3-4b\": \"mlx-community/gemma-3-4b-it-4bit\",\n \"gemma-3-4b-bf16\": \"mlx-community/gemma-3-4b-it-bf16\",\n \"gemma-3-12b\": \"mlx-community/gemma-3-12b-it-4bit\",\n \"gemma-3-27b\": \"mlx-community/gemma-3-27b-it-4bit\",\n\n // Gemma 3n (Google) - Efficient architecture with AltUp and Laurel\n // Note: Use -lm variants (language model only, no audio/vision)\n \"gemma-3n\": \"mlx-community/gemma-3n-E2B-it-lm-4bit\",\n \"gemma-3n-e2b\": \"mlx-community/gemma-3n-E2B-it-lm-4bit\",\n \"gemma-3n-e4b\": \"mlx-community/gemma-3n-E4B-it-lm-4bit\"\n} as const\n\nexport type RecommendedModelKey = keyof typeof RECOMMENDED_MODELS\n\n// MARK: - Public API\n\n/**\n * Check if the platform is Apple Silicon Mac\n */\nexport function isPlatformSupported(): boolean {\n return platform() === \"darwin\" && arch() === \"arm64\"\n}\n\n/**\n * Check if MLX is available on this system\n * (requires macOS 14+ on Apple Silicon with built binaries)\n */\nexport function isSupported(): boolean {\n if (!isPlatformSupported()) {\n return false\n }\n\n try {\n const b = loadBinding()\n\n return b.isAvailable()\n } catch {\n return false\n }\n}\n\n/**\n * Get the library version\n */\nexport function getVersion(): string {\n const b = loadBinding()\n\n return b.getVersion()\n}\n\n/**\n * Load a model from HuggingFace or local path\n *\n * @param modelId - HuggingFace model ID (e.g., \"mlx-community/gemma-3n-E2B-it-4bit\") or local path\n * @returns Model instance\n *\n * @example\n * ```typescript\n * import { loadModel, RECOMMENDED_MODELS } from \"node-mlx\"\n *\n * const model = loadModel(RECOMMENDED_MODELS[\"gemma-3n\"])\n * const result = model.generate(\"Hello, world!\")\n * console.log(result.text)\n * model.unload()\n * ```\n */\nexport function loadModel(modelId: string): Model {\n const b = loadBinding()\n const handle = b.loadModel(modelId)\n\n return {\n handle,\n\n generate(prompt: string, options?: GenerationOptions): GenerationResult {\n const jsonStr = b.generate(handle, prompt, {\n maxTokens: options?.maxTokens ?? 256,\n temperature: options?.temperature ?? 0.7,\n topP: options?.topP ?? 0.9,\n repetitionPenalty: options?.repetitionPenalty ?? 0,\n repetitionContextSize: options?.repetitionContextSize ?? 20\n })\n\n const result = JSON.parse(jsonStr) as JSONGenerationResult\n\n if (!result.success) {\n throw new Error(result.error ?? \"Generation failed\")\n }\n\n return {\n text: result.text ?? \"\",\n tokenCount: result.tokenCount ?? 0,\n tokensPerSecond: result.tokensPerSecond ?? 0\n }\n },\n\n generateStreaming(prompt: string, options?: GenerationOptions): StreamingResult {\n // Tokens are written directly to stdout by Swift\n const jsonStr = b.generateStreaming(handle, prompt, {\n maxTokens: options?.maxTokens ?? 256,\n temperature: options?.temperature ?? 0.7,\n topP: options?.topP ?? 0.9,\n repetitionPenalty: options?.repetitionPenalty ?? 0,\n repetitionContextSize: options?.repetitionContextSize ?? 20\n })\n\n const result = JSON.parse(jsonStr) as JSONGenerationResult\n\n if (!result.success) {\n throw new Error(result.error ?? \"Generation failed\")\n }\n\n return {\n tokenCount: result.tokenCount ?? 0,\n tokensPerSecond: result.tokensPerSecond ?? 0\n }\n },\n\n generateWithImage(\n prompt: string,\n imagePath: string,\n options?: GenerationOptions\n ): StreamingResult {\n // VLM generation with image - tokens are written directly to stdout by Swift\n const jsonStr = b.generateWithImage(handle, prompt, imagePath, {\n maxTokens: options?.maxTokens ?? 256,\n temperature: options?.temperature ?? 0.7,\n topP: options?.topP ?? 0.9,\n repetitionPenalty: options?.repetitionPenalty ?? 0,\n repetitionContextSize: options?.repetitionContextSize ?? 20\n })\n\n const result = JSON.parse(jsonStr) as JSONGenerationResult\n\n if (!result.success) {\n throw new Error(result.error ?? \"Generation failed\")\n }\n\n return {\n tokenCount: result.tokenCount ?? 0,\n tokensPerSecond: result.tokensPerSecond ?? 0\n }\n },\n\n isVLM(): boolean {\n return b.isVLM(handle)\n },\n\n unload(): void {\n b.unloadModel(handle)\n }\n }\n}\n\n/**\n * Generate text using a model (one-shot, loads and unloads model)\n *\n * @param modelId - HuggingFace model ID or local path\n * @param prompt - Input text\n * @param options - Generation options\n * @returns Generation result\n *\n * @example\n * ```typescript\n * import { generate } from \"node-mlx\"\n *\n * const result = generate(\n * RECOMMENDED_MODELS[\"gemma-3n\"],\n * \"Explain quantum computing\",\n * { maxTokens: 100 }\n * )\n * console.log(result.text)\n * ```\n */\nexport function generate(\n modelId: string,\n prompt: string,\n options?: GenerationOptions\n): GenerationResult {\n const model = loadModel(modelId)\n\n try {\n return model.generate(prompt, options)\n } finally {\n model.unload()\n }\n}\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n"],"mappings":"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","names":["__filename","require"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_tsx@4.21.0_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js"],"sourcesContent":["import { platform, arch } from \"node:os\"\nimport { join, dirname } from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\nimport { existsSync, readFileSync } from \"node:fs\"\nimport { createRequire } from \"node:module\"\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = dirname(__filename)\nconst require = createRequire(import.meta.url)\n\n// Read version from package.json\nconst packageJsonPath = join(__dirname, \"..\", \"package.json\")\nconst packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\")) as { version: string }\n\n/** Package version */\nexport const VERSION = packageJson.version\n\n// Native binding interface\ninterface NativeBinding {\n initialize(dylibPath: string): boolean\n isInitialized(): boolean\n loadModel(modelId: string): number\n unloadModel(handle: number): void\n generate(\n handle: number,\n prompt: string,\n options?: {\n maxTokens?: number\n temperature?: number\n topP?: number\n repetitionPenalty?: number\n repetitionContextSize?: number\n }\n ): string // Returns JSON string\n generateStreaming(\n handle: number,\n prompt: string,\n options?: {\n maxTokens?: number\n temperature?: number\n topP?: number\n repetitionPenalty?: number\n repetitionContextSize?: number\n }\n ): string // Streams to stdout, returns JSON stats\n generateWithImage(\n handle: number,\n prompt: string,\n imagePath: string,\n options?: {\n maxTokens?: number\n temperature?: number\n topP?: number\n repetitionPenalty?: number\n repetitionContextSize?: number\n }\n ): string // VLM: Streams to stdout, returns JSON stats\n isVLM(handle: number): boolean\n isAvailable(): boolean\n getVersion(): string\n}\n\n// JSON response from Swift\ninterface JSONGenerationResult {\n success: boolean\n text?: string\n tokenCount?: number\n tokensPerSecond?: number\n error?: string\n}\n\n// Load the native addon\nlet binding: NativeBinding | null = null\nlet initialized = false\n\n/**\n * Load native addon using node-gyp-build (prebuilds) or fallback to built addon\n */\nfunction loadNativeAddon(): NativeBinding {\n // Try node-gyp-build first (prebuilds)\n try {\n const gypBuild = require(\"node-gyp-build\") as (dir: string) => NativeBinding\n const nativeDir = join(__dirname, \"..\", \"native\")\n\n if (existsSync(join(__dirname, \"..\", \"prebuilds\"))) {\n return gypBuild(join(__dirname, \"..\"))\n }\n\n // Fallback to native/build if no prebuilds\n if (existsSync(join(nativeDir, \"build\"))) {\n return gypBuild(nativeDir)\n }\n } catch {\n // node-gyp-build failed, try manual loading\n }\n\n // Manual fallback: try different paths for the native addon\n const possibleAddonPaths = [\n // From package dist/ (npm installed)\n join(__dirname, \"..\", \"prebuilds\", \"darwin-arm64\", \"node.napi.node\"),\n // From native/build (local development)\n join(__dirname, \"..\", \"native\", \"build\", \"Release\", \"node_mlx.node\"),\n // From project root (monorepo development)\n join(process.cwd(), \"packages\", \"node-mlx\", \"native\", \"build\", \"Release\", \"node_mlx.node\")\n ]\n\n for (const p of possibleAddonPaths) {\n if (existsSync(p)) {\n return require(p) as NativeBinding\n }\n }\n\n throw new Error(\n \"Native addon not found. Run 'pnpm build:native' first.\\n\" +\n `Searched paths:\\n${possibleAddonPaths.join(\"\\n\")}`\n )\n}\n\n/**\n * Find Swift library path\n * Note: The library is expected to be in a directory with mlx.metallib for MLX to find it\n */\nfunction findSwiftLibrary(): string {\n const possibleDylibPaths = [\n // From package swift/ (preferred - has metallib co-located)\n join(__dirname, \"..\", \"swift\", \"libNodeMLX.dylib\"),\n // From project root packages/node-mlx/swift/ (monorepo development)\n join(process.cwd(), \"packages\", \"node-mlx\", \"swift\", \"libNodeMLX.dylib\"),\n // Fallback to packages/swift/.build (monorepo dev)\n join(__dirname, \"..\", \"..\", \"swift\", \".build\", \"release\", \"libNodeMLX.dylib\"),\n join(__dirname, \"..\", \"..\", \"..\", \"swift\", \".build\", \"release\", \"libNodeMLX.dylib\"),\n join(process.cwd(), \"packages\", \"swift\", \".build\", \"release\", \"libNodeMLX.dylib\")\n ]\n\n for (const p of possibleDylibPaths) {\n if (existsSync(p)) {\n return p\n }\n }\n\n throw new Error(\n \"Swift library not found. Run 'pnpm build:swift' first.\\n\" +\n `Searched paths:\\n${possibleDylibPaths.join(\"\\n\")}`\n )\n}\n\nfunction loadBinding(): NativeBinding {\n if (binding && initialized) {\n return binding\n }\n\n if (platform() !== \"darwin\" || arch() !== \"arm64\") {\n throw new Error(\"node-mlx is only supported on macOS Apple Silicon (arm64)\")\n }\n\n binding = loadNativeAddon()\n const dylibPath = findSwiftLibrary()\n const success = binding.initialize(dylibPath)\n\n if (!success) {\n throw new Error(\"Failed to initialize node-mlx native library\")\n }\n\n initialized = true\n\n return binding\n}\n\n// MARK: - Public Types\n\nexport interface GenerationOptions {\n maxTokens?: number\n temperature?: number\n topP?: number\n /** Penalty for repeating tokens (1.0 = no penalty, 1.1-1.2 recommended) */\n repetitionPenalty?: number\n /** Number of recent tokens to consider for penalty (default: 20) */\n repetitionContextSize?: number\n}\n\nexport interface GenerationResult {\n text: string\n tokenCount: number\n tokensPerSecond: number\n}\n\nexport interface StreamingResult {\n tokenCount: number\n tokensPerSecond: number\n}\n\nexport interface Model {\n /** Generate text from a prompt */\n generate(prompt: string, options?: GenerationOptions): GenerationResult\n\n /** Generate text with streaming - tokens are written directly to stdout */\n generateStreaming(prompt: string, options?: GenerationOptions): StreamingResult\n\n /** Generate text from a prompt with an image (VLM only) */\n generateWithImage(prompt: string, imagePath: string, options?: GenerationOptions): StreamingResult\n\n /** Check if this model supports images (is a Vision-Language Model) */\n isVLM(): boolean\n\n /** Unload the model from memory */\n unload(): void\n\n /** Model handle (internal use) */\n readonly handle: number\n}\n\n// MARK: - Recommended Models\n\nexport const RECOMMENDED_MODELS = {\n // Qwen 3 (Alibaba) - With Q/K norms\n qwen: \"lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit\", // Default to Qwen3\n qwen3: \"lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit\",\n \"qwen-3\": \"lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit\",\n \"qwen-3-4b\": \"lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit\",\n \"qwen-3-0.6b\": \"mlx-community/Qwen3-0.6B-4bit\",\n \"qwen-3-1.7b\": \"mlx-community/Qwen3-1.7B-4bit\",\n\n // Qwen 2.5 (Alibaba) - Legacy, with attention bias\n \"qwen-2.5\": \"Qwen/Qwen2.5-1.5B-Instruct\",\n \"qwen-2.5-1.5b\": \"Qwen/Qwen2.5-1.5B-Instruct\",\n \"qwen-2.5-3b\": \"Qwen/Qwen2.5-3B-Instruct\",\n\n // Phi (Microsoft) - Working with fused QKV and RoPE\n phi: \"mlx-community/Phi-3.5-mini-instruct-4bit\", // Default to 3.5 (smaller, faster to download)\n phi4: \"mlx-community/phi-4-4bit\",\n \"phi-4\": \"mlx-community/phi-4-4bit\",\n \"phi-3.5\": \"mlx-community/Phi-3.5-mini-instruct-4bit\",\n \"phi-3.5-mini\": \"mlx-community/Phi-3.5-mini-instruct-4bit\",\n phi3: \"mlx-community/Phi-3-mini-4k-instruct-4bit\",\n \"phi-3\": \"mlx-community/Phi-3-mini-4k-instruct-4bit\",\n \"phi-3-mini\": \"mlx-community/Phi-3-mini-4k-instruct-4bit\",\n\n // Llama 3.2 (Meta) - Requires HuggingFace authentication\n // Note: meta-llama models require accepting license at huggingface.co\n llama: \"meta-llama/Llama-3.2-1B-Instruct\",\n \"llama-3.2\": \"meta-llama/Llama-3.2-1B-Instruct\",\n \"llama-3.2-1b\": \"meta-llama/Llama-3.2-1B-Instruct\",\n \"llama-3.2-3b\": \"meta-llama/Llama-3.2-3B-Instruct\",\n\n // Gemma 3 (Google) - Standard transformer architecture with sliding window\n gemma: \"mlx-community/gemma-3-1b-it-4bit\",\n \"gemma-3\": \"mlx-community/gemma-3-1b-it-4bit\",\n \"gemma-3-1b\": \"mlx-community/gemma-3-1b-it-4bit\",\n \"gemma-3-1b-bf16\": \"mlx-community/gemma-3-1b-it-bf16\",\n \"gemma-3-4b\": \"mlx-community/gemma-3-4b-it-4bit\",\n \"gemma-3-4b-bf16\": \"mlx-community/gemma-3-4b-it-bf16\",\n \"gemma-3-12b\": \"mlx-community/gemma-3-12b-it-4bit\",\n \"gemma-3-27b\": \"mlx-community/gemma-3-27b-it-4bit\",\n\n // Gemma 3n (Google) - Efficient architecture with AltUp and Laurel\n // Note: Use -lm variants (language model only, no audio/vision)\n \"gemma-3n\": \"mlx-community/gemma-3n-E4B-it-lm-4bit\",\n \"gemma-3n-e2b\": \"mlx-community/gemma-3n-E2B-it-lm-4bit\",\n \"gemma-3n-e4b\": \"mlx-community/gemma-3n-E4B-it-lm-4bit\"\n} as const\n\nexport type RecommendedModelKey = keyof typeof RECOMMENDED_MODELS\n\n// MARK: - Public API\n\n/**\n * Check if the platform is Apple Silicon Mac\n */\nexport function isPlatformSupported(): boolean {\n return platform() === \"darwin\" && arch() === \"arm64\"\n}\n\n/**\n * Check if MLX is available on this system\n * (requires macOS 14+ on Apple Silicon with built binaries)\n */\nexport function isSupported(): boolean {\n if (!isPlatformSupported()) {\n return false\n }\n\n try {\n const b = loadBinding()\n\n return b.isAvailable()\n } catch {\n return false\n }\n}\n\n/**\n * Get the library version\n */\nexport function getVersion(): string {\n const b = loadBinding()\n\n return b.getVersion()\n}\n\n/**\n * Load a model from HuggingFace or local path\n *\n * @param modelId - HuggingFace model ID (e.g., \"mlx-community/gemma-3n-E2B-it-4bit\") or local path\n * @returns Model instance\n *\n * @example\n * ```typescript\n * import { loadModel, RECOMMENDED_MODELS } from \"node-mlx\"\n *\n * const model = loadModel(RECOMMENDED_MODELS[\"gemma-3n\"])\n * const result = model.generate(\"Hello, world!\")\n * console.log(result.text)\n * model.unload()\n * ```\n */\n/**\n * Resolve a model ID or alias to a full HuggingFace model ID\n * @param modelId - Either a full HuggingFace model ID (e.g., \"mlx-community/phi-4-4bit\") or a short alias (e.g., \"phi4\")\n * @returns The full HuggingFace model ID\n */\nfunction resolveModelId(modelId: string): string {\n // Check if it's an alias in RECOMMENDED_MODELS\n if (modelId in RECOMMENDED_MODELS) {\n return RECOMMENDED_MODELS[modelId as keyof typeof RECOMMENDED_MODELS]\n }\n\n // Otherwise assume it's already a full model ID\n return modelId\n}\n\nexport function loadModel(modelId: string): Model {\n const b = loadBinding()\n const resolvedId = resolveModelId(modelId)\n const handle = b.loadModel(resolvedId)\n\n return {\n handle,\n\n generate(prompt: string, options?: GenerationOptions): GenerationResult {\n const jsonStr = b.generate(handle, prompt, {\n maxTokens: options?.maxTokens ?? 256,\n temperature: options?.temperature ?? 0.7,\n topP: options?.topP ?? 0.9,\n repetitionPenalty: options?.repetitionPenalty ?? 1.1,\n repetitionContextSize: options?.repetitionContextSize ?? 20\n })\n\n const result = JSON.parse(jsonStr) as JSONGenerationResult\n\n if (!result.success) {\n throw new Error(result.error ?? \"Generation failed\")\n }\n\n return {\n text: result.text ?? \"\",\n tokenCount: result.tokenCount ?? 0,\n tokensPerSecond: result.tokensPerSecond ?? 0\n }\n },\n\n generateStreaming(prompt: string, options?: GenerationOptions): StreamingResult {\n // Tokens are written directly to stdout by Swift\n const jsonStr = b.generateStreaming(handle, prompt, {\n maxTokens: options?.maxTokens ?? 256,\n temperature: options?.temperature ?? 0.7,\n topP: options?.topP ?? 0.9,\n repetitionPenalty: options?.repetitionPenalty ?? 1.1,\n repetitionContextSize: options?.repetitionContextSize ?? 20\n })\n\n const result = JSON.parse(jsonStr) as JSONGenerationResult\n\n if (!result.success) {\n throw new Error(result.error ?? \"Generation failed\")\n }\n\n return {\n tokenCount: result.tokenCount ?? 0,\n tokensPerSecond: result.tokensPerSecond ?? 0\n }\n },\n\n generateWithImage(\n prompt: string,\n imagePath: string,\n options?: GenerationOptions\n ): StreamingResult {\n // VLM generation with image - tokens are written directly to stdout by Swift\n const jsonStr = b.generateWithImage(handle, prompt, imagePath, {\n maxTokens: options?.maxTokens ?? 256,\n temperature: options?.temperature ?? 0.7,\n topP: options?.topP ?? 0.9,\n repetitionPenalty: options?.repetitionPenalty ?? 1.1,\n repetitionContextSize: options?.repetitionContextSize ?? 20\n })\n\n const result = JSON.parse(jsonStr) as JSONGenerationResult\n\n if (!result.success) {\n throw new Error(result.error ?? \"Generation failed\")\n }\n\n return {\n tokenCount: result.tokenCount ?? 0,\n tokensPerSecond: result.tokensPerSecond ?? 0\n }\n },\n\n isVLM(): boolean {\n return b.isVLM(handle)\n },\n\n unload(): void {\n b.unloadModel(handle)\n }\n }\n}\n\n/**\n * Generate text using a model (one-shot, loads and unloads model)\n *\n * @param modelId - HuggingFace model ID or local path\n * @param prompt - Input text\n * @param options - Generation options\n * @returns Generation result\n *\n * @example\n * ```typescript\n * import { generate } from \"node-mlx\"\n *\n * const result = generate(\n * RECOMMENDED_MODELS[\"gemma-3n\"],\n * \"Explain quantum computing\",\n * { maxTokens: 100 }\n * )\n * console.log(result.text)\n * ```\n */\nexport function generate(\n modelId: string,\n prompt: string,\n options?: GenerationOptions\n): GenerationResult {\n const model = loadModel(modelId)\n\n try {\n return model.generate(prompt, options)\n } finally {\n model.unload()\n }\n}\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n"],"mappings":"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","names":["__filename","require"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -33,17 +33,23 @@ interface Model {
|
|
|
33
33
|
readonly handle: number;
|
|
34
34
|
}
|
|
35
35
|
declare const RECOMMENDED_MODELS: {
|
|
36
|
-
readonly qwen: "
|
|
36
|
+
readonly qwen: "lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit";
|
|
37
|
+
readonly qwen3: "lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit";
|
|
38
|
+
readonly "qwen-3": "lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit";
|
|
39
|
+
readonly "qwen-3-4b": "lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit";
|
|
40
|
+
readonly "qwen-3-0.6b": "mlx-community/Qwen3-0.6B-4bit";
|
|
41
|
+
readonly "qwen-3-1.7b": "mlx-community/Qwen3-1.7B-4bit";
|
|
37
42
|
readonly "qwen-2.5": "Qwen/Qwen2.5-1.5B-Instruct";
|
|
38
|
-
readonly "qwen-2.5-0.5b": "Qwen/Qwen2.5-0.5B-Instruct";
|
|
39
43
|
readonly "qwen-2.5-1.5b": "Qwen/Qwen2.5-1.5B-Instruct";
|
|
40
44
|
readonly "qwen-2.5-3b": "Qwen/Qwen2.5-3B-Instruct";
|
|
41
|
-
readonly phi: "
|
|
42
|
-
readonly phi4: "
|
|
43
|
-
readonly "phi-4": "
|
|
44
|
-
readonly
|
|
45
|
-
readonly "phi-3": "
|
|
46
|
-
readonly
|
|
45
|
+
readonly phi: "mlx-community/Phi-3.5-mini-instruct-4bit";
|
|
46
|
+
readonly phi4: "mlx-community/phi-4-4bit";
|
|
47
|
+
readonly "phi-4": "mlx-community/phi-4-4bit";
|
|
48
|
+
readonly "phi-3.5": "mlx-community/Phi-3.5-mini-instruct-4bit";
|
|
49
|
+
readonly "phi-3.5-mini": "mlx-community/Phi-3.5-mini-instruct-4bit";
|
|
50
|
+
readonly phi3: "mlx-community/Phi-3-mini-4k-instruct-4bit";
|
|
51
|
+
readonly "phi-3": "mlx-community/Phi-3-mini-4k-instruct-4bit";
|
|
52
|
+
readonly "phi-3-mini": "mlx-community/Phi-3-mini-4k-instruct-4bit";
|
|
47
53
|
readonly llama: "meta-llama/Llama-3.2-1B-Instruct";
|
|
48
54
|
readonly "llama-3.2": "meta-llama/Llama-3.2-1B-Instruct";
|
|
49
55
|
readonly "llama-3.2-1b": "meta-llama/Llama-3.2-1B-Instruct";
|
|
@@ -56,7 +62,7 @@ declare const RECOMMENDED_MODELS: {
|
|
|
56
62
|
readonly "gemma-3-4b-bf16": "mlx-community/gemma-3-4b-it-bf16";
|
|
57
63
|
readonly "gemma-3-12b": "mlx-community/gemma-3-12b-it-4bit";
|
|
58
64
|
readonly "gemma-3-27b": "mlx-community/gemma-3-27b-it-4bit";
|
|
59
|
-
readonly "gemma-3n": "mlx-community/gemma-3n-
|
|
65
|
+
readonly "gemma-3n": "mlx-community/gemma-3n-E4B-it-lm-4bit";
|
|
60
66
|
readonly "gemma-3n-e2b": "mlx-community/gemma-3n-E2B-it-lm-4bit";
|
|
61
67
|
readonly "gemma-3n-e4b": "mlx-community/gemma-3n-E4B-it-lm-4bit";
|
|
62
68
|
};
|
|
@@ -74,22 +80,6 @@ declare function isSupported(): boolean;
|
|
|
74
80
|
* Get the library version
|
|
75
81
|
*/
|
|
76
82
|
declare function getVersion(): string;
|
|
77
|
-
/**
|
|
78
|
-
* Load a model from HuggingFace or local path
|
|
79
|
-
*
|
|
80
|
-
* @param modelId - HuggingFace model ID (e.g., "mlx-community/gemma-3n-E2B-it-4bit") or local path
|
|
81
|
-
* @returns Model instance
|
|
82
|
-
*
|
|
83
|
-
* @example
|
|
84
|
-
* ```typescript
|
|
85
|
-
* import { loadModel, RECOMMENDED_MODELS } from "node-mlx"
|
|
86
|
-
*
|
|
87
|
-
* const model = loadModel(RECOMMENDED_MODELS["gemma-3n"])
|
|
88
|
-
* const result = model.generate("Hello, world!")
|
|
89
|
-
* console.log(result.text)
|
|
90
|
-
* model.unload()
|
|
91
|
-
* ```
|
|
92
|
-
*/
|
|
93
83
|
declare function loadModel(modelId: string): Model;
|
|
94
84
|
/**
|
|
95
85
|
* Generate text using a model (one-shot, loads and unloads model)
|
package/dist/index.d.ts
CHANGED
|
@@ -33,17 +33,23 @@ interface Model {
|
|
|
33
33
|
readonly handle: number;
|
|
34
34
|
}
|
|
35
35
|
declare const RECOMMENDED_MODELS: {
|
|
36
|
-
readonly qwen: "
|
|
36
|
+
readonly qwen: "lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit";
|
|
37
|
+
readonly qwen3: "lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit";
|
|
38
|
+
readonly "qwen-3": "lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit";
|
|
39
|
+
readonly "qwen-3-4b": "lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit";
|
|
40
|
+
readonly "qwen-3-0.6b": "mlx-community/Qwen3-0.6B-4bit";
|
|
41
|
+
readonly "qwen-3-1.7b": "mlx-community/Qwen3-1.7B-4bit";
|
|
37
42
|
readonly "qwen-2.5": "Qwen/Qwen2.5-1.5B-Instruct";
|
|
38
|
-
readonly "qwen-2.5-0.5b": "Qwen/Qwen2.5-0.5B-Instruct";
|
|
39
43
|
readonly "qwen-2.5-1.5b": "Qwen/Qwen2.5-1.5B-Instruct";
|
|
40
44
|
readonly "qwen-2.5-3b": "Qwen/Qwen2.5-3B-Instruct";
|
|
41
|
-
readonly phi: "
|
|
42
|
-
readonly phi4: "
|
|
43
|
-
readonly "phi-4": "
|
|
44
|
-
readonly
|
|
45
|
-
readonly "phi-3": "
|
|
46
|
-
readonly
|
|
45
|
+
readonly phi: "mlx-community/Phi-3.5-mini-instruct-4bit";
|
|
46
|
+
readonly phi4: "mlx-community/phi-4-4bit";
|
|
47
|
+
readonly "phi-4": "mlx-community/phi-4-4bit";
|
|
48
|
+
readonly "phi-3.5": "mlx-community/Phi-3.5-mini-instruct-4bit";
|
|
49
|
+
readonly "phi-3.5-mini": "mlx-community/Phi-3.5-mini-instruct-4bit";
|
|
50
|
+
readonly phi3: "mlx-community/Phi-3-mini-4k-instruct-4bit";
|
|
51
|
+
readonly "phi-3": "mlx-community/Phi-3-mini-4k-instruct-4bit";
|
|
52
|
+
readonly "phi-3-mini": "mlx-community/Phi-3-mini-4k-instruct-4bit";
|
|
47
53
|
readonly llama: "meta-llama/Llama-3.2-1B-Instruct";
|
|
48
54
|
readonly "llama-3.2": "meta-llama/Llama-3.2-1B-Instruct";
|
|
49
55
|
readonly "llama-3.2-1b": "meta-llama/Llama-3.2-1B-Instruct";
|
|
@@ -56,7 +62,7 @@ declare const RECOMMENDED_MODELS: {
|
|
|
56
62
|
readonly "gemma-3-4b-bf16": "mlx-community/gemma-3-4b-it-bf16";
|
|
57
63
|
readonly "gemma-3-12b": "mlx-community/gemma-3-12b-it-4bit";
|
|
58
64
|
readonly "gemma-3-27b": "mlx-community/gemma-3-27b-it-4bit";
|
|
59
|
-
readonly "gemma-3n": "mlx-community/gemma-3n-
|
|
65
|
+
readonly "gemma-3n": "mlx-community/gemma-3n-E4B-it-lm-4bit";
|
|
60
66
|
readonly "gemma-3n-e2b": "mlx-community/gemma-3n-E2B-it-lm-4bit";
|
|
61
67
|
readonly "gemma-3n-e4b": "mlx-community/gemma-3n-E4B-it-lm-4bit";
|
|
62
68
|
};
|
|
@@ -74,22 +80,6 @@ declare function isSupported(): boolean;
|
|
|
74
80
|
* Get the library version
|
|
75
81
|
*/
|
|
76
82
|
declare function getVersion(): string;
|
|
77
|
-
/**
|
|
78
|
-
* Load a model from HuggingFace or local path
|
|
79
|
-
*
|
|
80
|
-
* @param modelId - HuggingFace model ID (e.g., "mlx-community/gemma-3n-E2B-it-4bit") or local path
|
|
81
|
-
* @returns Model instance
|
|
82
|
-
*
|
|
83
|
-
* @example
|
|
84
|
-
* ```typescript
|
|
85
|
-
* import { loadModel, RECOMMENDED_MODELS } from "node-mlx"
|
|
86
|
-
*
|
|
87
|
-
* const model = loadModel(RECOMMENDED_MODELS["gemma-3n"])
|
|
88
|
-
* const result = model.generate("Hello, world!")
|
|
89
|
-
* console.log(result.text)
|
|
90
|
-
* model.unload()
|
|
91
|
-
* ```
|
|
92
|
-
*/
|
|
93
83
|
declare function loadModel(modelId: string): Model;
|
|
94
84
|
/**
|
|
95
85
|
* Generate text using a model (one-shot, loads and unloads model)
|
package/dist/index.js
CHANGED
|
@@ -82,21 +82,28 @@ function loadBinding() {
|
|
|
82
82
|
return binding;
|
|
83
83
|
}
|
|
84
84
|
var RECOMMENDED_MODELS = {
|
|
85
|
-
// Qwen
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
// Qwen 3 (Alibaba) - With Q/K norms
|
|
86
|
+
qwen: "lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit",
|
|
87
|
+
// Default to Qwen3
|
|
88
|
+
qwen3: "lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit",
|
|
89
|
+
"qwen-3": "lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit",
|
|
90
|
+
"qwen-3-4b": "lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit",
|
|
91
|
+
"qwen-3-0.6b": "mlx-community/Qwen3-0.6B-4bit",
|
|
92
|
+
"qwen-3-1.7b": "mlx-community/Qwen3-1.7B-4bit",
|
|
93
|
+
// Qwen 2.5 (Alibaba) - Legacy, with attention bias
|
|
88
94
|
"qwen-2.5": "Qwen/Qwen2.5-1.5B-Instruct",
|
|
89
|
-
"qwen-2.5-0.5b": "Qwen/Qwen2.5-0.5B-Instruct",
|
|
90
95
|
"qwen-2.5-1.5b": "Qwen/Qwen2.5-1.5B-Instruct",
|
|
91
96
|
"qwen-2.5-3b": "Qwen/Qwen2.5-3B-Instruct",
|
|
92
97
|
// Phi (Microsoft) - Working with fused QKV and RoPE
|
|
93
|
-
phi: "
|
|
94
|
-
// Default to
|
|
95
|
-
phi4: "
|
|
96
|
-
"phi-4": "
|
|
97
|
-
|
|
98
|
-
"phi-3": "
|
|
99
|
-
|
|
98
|
+
phi: "mlx-community/Phi-3.5-mini-instruct-4bit",
|
|
99
|
+
// Default to 3.5 (smaller, faster to download)
|
|
100
|
+
phi4: "mlx-community/phi-4-4bit",
|
|
101
|
+
"phi-4": "mlx-community/phi-4-4bit",
|
|
102
|
+
"phi-3.5": "mlx-community/Phi-3.5-mini-instruct-4bit",
|
|
103
|
+
"phi-3.5-mini": "mlx-community/Phi-3.5-mini-instruct-4bit",
|
|
104
|
+
phi3: "mlx-community/Phi-3-mini-4k-instruct-4bit",
|
|
105
|
+
"phi-3": "mlx-community/Phi-3-mini-4k-instruct-4bit",
|
|
106
|
+
"phi-3-mini": "mlx-community/Phi-3-mini-4k-instruct-4bit",
|
|
100
107
|
// Llama 3.2 (Meta) - Requires HuggingFace authentication
|
|
101
108
|
// Note: meta-llama models require accepting license at huggingface.co
|
|
102
109
|
llama: "meta-llama/Llama-3.2-1B-Instruct",
|
|
@@ -114,7 +121,7 @@ var RECOMMENDED_MODELS = {
|
|
|
114
121
|
"gemma-3-27b": "mlx-community/gemma-3-27b-it-4bit",
|
|
115
122
|
// Gemma 3n (Google) - Efficient architecture with AltUp and Laurel
|
|
116
123
|
// Note: Use -lm variants (language model only, no audio/vision)
|
|
117
|
-
"gemma-3n": "mlx-community/gemma-3n-
|
|
124
|
+
"gemma-3n": "mlx-community/gemma-3n-E4B-it-lm-4bit",
|
|
118
125
|
"gemma-3n-e2b": "mlx-community/gemma-3n-E2B-it-lm-4bit",
|
|
119
126
|
"gemma-3n-e4b": "mlx-community/gemma-3n-E4B-it-lm-4bit"
|
|
120
127
|
};
|
|
@@ -136,9 +143,16 @@ function getVersion() {
|
|
|
136
143
|
const b = loadBinding();
|
|
137
144
|
return b.getVersion();
|
|
138
145
|
}
|
|
146
|
+
function resolveModelId(modelId) {
|
|
147
|
+
if (modelId in RECOMMENDED_MODELS) {
|
|
148
|
+
return RECOMMENDED_MODELS[modelId];
|
|
149
|
+
}
|
|
150
|
+
return modelId;
|
|
151
|
+
}
|
|
139
152
|
function loadModel(modelId) {
|
|
140
153
|
const b = loadBinding();
|
|
141
|
-
const
|
|
154
|
+
const resolvedId = resolveModelId(modelId);
|
|
155
|
+
const handle = b.loadModel(resolvedId);
|
|
142
156
|
return {
|
|
143
157
|
handle,
|
|
144
158
|
generate(prompt, options) {
|
|
@@ -146,7 +160,7 @@ function loadModel(modelId) {
|
|
|
146
160
|
maxTokens: options?.maxTokens ?? 256,
|
|
147
161
|
temperature: options?.temperature ?? 0.7,
|
|
148
162
|
topP: options?.topP ?? 0.9,
|
|
149
|
-
repetitionPenalty: options?.repetitionPenalty ??
|
|
163
|
+
repetitionPenalty: options?.repetitionPenalty ?? 1.1,
|
|
150
164
|
repetitionContextSize: options?.repetitionContextSize ?? 20
|
|
151
165
|
});
|
|
152
166
|
const result = JSON.parse(jsonStr);
|
|
@@ -164,7 +178,7 @@ function loadModel(modelId) {
|
|
|
164
178
|
maxTokens: options?.maxTokens ?? 256,
|
|
165
179
|
temperature: options?.temperature ?? 0.7,
|
|
166
180
|
topP: options?.topP ?? 0.9,
|
|
167
|
-
repetitionPenalty: options?.repetitionPenalty ??
|
|
181
|
+
repetitionPenalty: options?.repetitionPenalty ?? 1.1,
|
|
168
182
|
repetitionContextSize: options?.repetitionContextSize ?? 20
|
|
169
183
|
});
|
|
170
184
|
const result = JSON.parse(jsonStr);
|
|
@@ -181,7 +195,7 @@ function loadModel(modelId) {
|
|
|
181
195
|
maxTokens: options?.maxTokens ?? 256,
|
|
182
196
|
temperature: options?.temperature ?? 0.7,
|
|
183
197
|
topP: options?.topP ?? 0.9,
|
|
184
|
-
repetitionPenalty: options?.repetitionPenalty ??
|
|
198
|
+
repetitionPenalty: options?.repetitionPenalty ?? 1.1,
|
|
185
199
|
repetitionContextSize: options?.repetitionContextSize ?? 20
|
|
186
200
|
});
|
|
187
201
|
const result = JSON.parse(jsonStr);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { platform, arch } from \"node:os\"\nimport { join, dirname } from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\nimport { existsSync, readFileSync } from \"node:fs\"\nimport { createRequire } from \"node:module\"\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = dirname(__filename)\nconst require = createRequire(import.meta.url)\n\n// Read version from package.json\nconst packageJsonPath = join(__dirname, \"..\", \"package.json\")\nconst packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\")) as { version: string }\n\n/** Package version */\nexport const VERSION = packageJson.version\n\n// Native binding interface\ninterface NativeBinding {\n initialize(dylibPath: string): boolean\n isInitialized(): boolean\n loadModel(modelId: string): number\n unloadModel(handle: number): void\n generate(\n handle: number,\n prompt: string,\n options?: {\n maxTokens?: number\n temperature?: number\n topP?: number\n repetitionPenalty?: number\n repetitionContextSize?: number\n }\n ): string // Returns JSON string\n generateStreaming(\n handle: number,\n prompt: string,\n options?: {\n maxTokens?: number\n temperature?: number\n topP?: number\n repetitionPenalty?: number\n repetitionContextSize?: number\n }\n ): string // Streams to stdout, returns JSON stats\n generateWithImage(\n handle: number,\n prompt: string,\n imagePath: string,\n options?: {\n maxTokens?: number\n temperature?: number\n topP?: number\n repetitionPenalty?: number\n repetitionContextSize?: number\n }\n ): string // VLM: Streams to stdout, returns JSON stats\n isVLM(handle: number): boolean\n isAvailable(): boolean\n getVersion(): string\n}\n\n// JSON response from Swift\ninterface JSONGenerationResult {\n success: boolean\n text?: string\n tokenCount?: number\n tokensPerSecond?: number\n error?: string\n}\n\n// Load the native addon\nlet binding: NativeBinding | null = null\nlet initialized = false\n\n/**\n * Load native addon using node-gyp-build (prebuilds) or fallback to built addon\n */\nfunction loadNativeAddon(): NativeBinding {\n // Try node-gyp-build first (prebuilds)\n try {\n const gypBuild = require(\"node-gyp-build\") as (dir: string) => NativeBinding\n const nativeDir = join(__dirname, \"..\", \"native\")\n\n if (existsSync(join(__dirname, \"..\", \"prebuilds\"))) {\n return gypBuild(join(__dirname, \"..\"))\n }\n\n // Fallback to native/build if no prebuilds\n if (existsSync(join(nativeDir, \"build\"))) {\n return gypBuild(nativeDir)\n }\n } catch {\n // node-gyp-build failed, try manual loading\n }\n\n // Manual fallback: try different paths for the native addon\n const possibleAddonPaths = [\n // From package dist/ (npm installed)\n join(__dirname, \"..\", \"prebuilds\", \"darwin-arm64\", \"node.napi.node\"),\n // From native/build (local development)\n join(__dirname, \"..\", \"native\", \"build\", \"Release\", \"node_mlx.node\"),\n // From project root (monorepo development)\n join(process.cwd(), \"packages\", \"node-mlx\", \"native\", \"build\", \"Release\", \"node_mlx.node\")\n ]\n\n for (const p of possibleAddonPaths) {\n if (existsSync(p)) {\n return require(p) as NativeBinding\n }\n }\n\n throw new Error(\n \"Native addon not found. Run 'pnpm build:native' first.\\n\" +\n `Searched paths:\\n${possibleAddonPaths.join(\"\\n\")}`\n )\n}\n\n/**\n * Find Swift library path\n * Note: The library is expected to be in a directory with mlx.metallib for MLX to find it\n */\nfunction findSwiftLibrary(): string {\n const possibleDylibPaths = [\n // From package swift/ (preferred - has metallib co-located)\n join(__dirname, \"..\", \"swift\", \"libNodeMLX.dylib\"),\n // From project root packages/node-mlx/swift/ (monorepo development)\n join(process.cwd(), \"packages\", \"node-mlx\", \"swift\", \"libNodeMLX.dylib\"),\n // Fallback to packages/swift/.build (monorepo dev)\n join(__dirname, \"..\", \"..\", \"swift\", \".build\", \"release\", \"libNodeMLX.dylib\"),\n join(__dirname, \"..\", \"..\", \"..\", \"swift\", \".build\", \"release\", \"libNodeMLX.dylib\"),\n join(process.cwd(), \"packages\", \"swift\", \".build\", \"release\", \"libNodeMLX.dylib\")\n ]\n\n for (const p of possibleDylibPaths) {\n if (existsSync(p)) {\n return p\n }\n }\n\n throw new Error(\n \"Swift library not found. Run 'pnpm build:swift' first.\\n\" +\n `Searched paths:\\n${possibleDylibPaths.join(\"\\n\")}`\n )\n}\n\nfunction loadBinding(): NativeBinding {\n if (binding && initialized) {\n return binding\n }\n\n if (platform() !== \"darwin\" || arch() !== \"arm64\") {\n throw new Error(\"node-mlx is only supported on macOS Apple Silicon (arm64)\")\n }\n\n binding = loadNativeAddon()\n const dylibPath = findSwiftLibrary()\n const success = binding.initialize(dylibPath)\n\n if (!success) {\n throw new Error(\"Failed to initialize node-mlx native library\")\n }\n\n initialized = true\n\n return binding\n}\n\n// MARK: - Public Types\n\nexport interface GenerationOptions {\n maxTokens?: number\n temperature?: number\n topP?: number\n /** Penalty for repeating tokens (1.0 = no penalty, 1.1-1.2 recommended) */\n repetitionPenalty?: number\n /** Number of recent tokens to consider for penalty (default: 20) */\n repetitionContextSize?: number\n}\n\nexport interface GenerationResult {\n text: string\n tokenCount: number\n tokensPerSecond: number\n}\n\nexport interface StreamingResult {\n tokenCount: number\n tokensPerSecond: number\n}\n\nexport interface Model {\n /** Generate text from a prompt */\n generate(prompt: string, options?: GenerationOptions): GenerationResult\n\n /** Generate text with streaming - tokens are written directly to stdout */\n generateStreaming(prompt: string, options?: GenerationOptions): StreamingResult\n\n /** Generate text from a prompt with an image (VLM only) */\n generateWithImage(prompt: string, imagePath: string, options?: GenerationOptions): StreamingResult\n\n /** Check if this model supports images (is a Vision-Language Model) */\n isVLM(): boolean\n\n /** Unload the model from memory */\n unload(): void\n\n /** Model handle (internal use) */\n readonly handle: number\n}\n\n// MARK: - Recommended Models\n\nexport const RECOMMENDED_MODELS = {\n // Qwen 2.5 (Alibaba) - Working with proper RoPE support\n // Using non-quantized models - quantized models have loading issues\n qwen: \"Qwen/Qwen2.5-1.5B-Instruct\",\n \"qwen-2.5\": \"Qwen/Qwen2.5-1.5B-Instruct\",\n \"qwen-2.5-0.5b\": \"Qwen/Qwen2.5-0.5B-Instruct\",\n \"qwen-2.5-1.5b\": \"Qwen/Qwen2.5-1.5B-Instruct\",\n \"qwen-2.5-3b\": \"Qwen/Qwen2.5-3B-Instruct\",\n\n // Phi (Microsoft) - Working with fused QKV and RoPE\n phi: \"microsoft/phi-4\", // Default to latest\n phi4: \"microsoft/phi-4\",\n \"phi-4\": \"microsoft/phi-4\",\n phi3: \"microsoft/Phi-3-mini-4k-instruct\",\n \"phi-3\": \"microsoft/Phi-3-mini-4k-instruct\",\n \"phi-3-mini\": \"microsoft/Phi-3-mini-4k-instruct\",\n\n // Llama 3.2 (Meta) - Requires HuggingFace authentication\n // Note: meta-llama models require accepting license at huggingface.co\n llama: \"meta-llama/Llama-3.2-1B-Instruct\",\n \"llama-3.2\": \"meta-llama/Llama-3.2-1B-Instruct\",\n \"llama-3.2-1b\": \"meta-llama/Llama-3.2-1B-Instruct\",\n \"llama-3.2-3b\": \"meta-llama/Llama-3.2-3B-Instruct\",\n\n // Gemma 3 (Google) - Standard transformer architecture with sliding window\n gemma: \"mlx-community/gemma-3-1b-it-4bit\",\n \"gemma-3\": \"mlx-community/gemma-3-1b-it-4bit\",\n \"gemma-3-1b\": \"mlx-community/gemma-3-1b-it-4bit\",\n \"gemma-3-1b-bf16\": \"mlx-community/gemma-3-1b-it-bf16\",\n \"gemma-3-4b\": \"mlx-community/gemma-3-4b-it-4bit\",\n \"gemma-3-4b-bf16\": \"mlx-community/gemma-3-4b-it-bf16\",\n \"gemma-3-12b\": \"mlx-community/gemma-3-12b-it-4bit\",\n \"gemma-3-27b\": \"mlx-community/gemma-3-27b-it-4bit\",\n\n // Gemma 3n (Google) - Efficient architecture with AltUp and Laurel\n // Note: Use -lm variants (language model only, no audio/vision)\n \"gemma-3n\": \"mlx-community/gemma-3n-E2B-it-lm-4bit\",\n \"gemma-3n-e2b\": \"mlx-community/gemma-3n-E2B-it-lm-4bit\",\n \"gemma-3n-e4b\": \"mlx-community/gemma-3n-E4B-it-lm-4bit\"\n} as const\n\nexport type RecommendedModelKey = keyof typeof RECOMMENDED_MODELS\n\n// MARK: - Public API\n\n/**\n * Check if the platform is Apple Silicon Mac\n */\nexport function isPlatformSupported(): boolean {\n return platform() === \"darwin\" && arch() === \"arm64\"\n}\n\n/**\n * Check if MLX is available on this system\n * (requires macOS 14+ on Apple Silicon with built binaries)\n */\nexport function isSupported(): boolean {\n if (!isPlatformSupported()) {\n return false\n }\n\n try {\n const b = loadBinding()\n\n return b.isAvailable()\n } catch {\n return false\n }\n}\n\n/**\n * Get the library version\n */\nexport function getVersion(): string {\n const b = loadBinding()\n\n return b.getVersion()\n}\n\n/**\n * Load a model from HuggingFace or local path\n *\n * @param modelId - HuggingFace model ID (e.g., \"mlx-community/gemma-3n-E2B-it-4bit\") or local path\n * @returns Model instance\n *\n * @example\n * ```typescript\n * import { loadModel, RECOMMENDED_MODELS } from \"node-mlx\"\n *\n * const model = loadModel(RECOMMENDED_MODELS[\"gemma-3n\"])\n * const result = model.generate(\"Hello, world!\")\n * console.log(result.text)\n * model.unload()\n * ```\n */\nexport function loadModel(modelId: string): Model {\n const b = loadBinding()\n const handle = b.loadModel(modelId)\n\n return {\n handle,\n\n generate(prompt: string, options?: GenerationOptions): GenerationResult {\n const jsonStr = b.generate(handle, prompt, {\n maxTokens: options?.maxTokens ?? 256,\n temperature: options?.temperature ?? 0.7,\n topP: options?.topP ?? 0.9,\n repetitionPenalty: options?.repetitionPenalty ?? 0,\n repetitionContextSize: options?.repetitionContextSize ?? 20\n })\n\n const result = JSON.parse(jsonStr) as JSONGenerationResult\n\n if (!result.success) {\n throw new Error(result.error ?? \"Generation failed\")\n }\n\n return {\n text: result.text ?? \"\",\n tokenCount: result.tokenCount ?? 0,\n tokensPerSecond: result.tokensPerSecond ?? 0\n }\n },\n\n generateStreaming(prompt: string, options?: GenerationOptions): StreamingResult {\n // Tokens are written directly to stdout by Swift\n const jsonStr = b.generateStreaming(handle, prompt, {\n maxTokens: options?.maxTokens ?? 256,\n temperature: options?.temperature ?? 0.7,\n topP: options?.topP ?? 0.9,\n repetitionPenalty: options?.repetitionPenalty ?? 0,\n repetitionContextSize: options?.repetitionContextSize ?? 20\n })\n\n const result = JSON.parse(jsonStr) as JSONGenerationResult\n\n if (!result.success) {\n throw new Error(result.error ?? \"Generation failed\")\n }\n\n return {\n tokenCount: result.tokenCount ?? 0,\n tokensPerSecond: result.tokensPerSecond ?? 0\n }\n },\n\n generateWithImage(\n prompt: string,\n imagePath: string,\n options?: GenerationOptions\n ): StreamingResult {\n // VLM generation with image - tokens are written directly to stdout by Swift\n const jsonStr = b.generateWithImage(handle, prompt, imagePath, {\n maxTokens: options?.maxTokens ?? 256,\n temperature: options?.temperature ?? 0.7,\n topP: options?.topP ?? 0.9,\n repetitionPenalty: options?.repetitionPenalty ?? 0,\n repetitionContextSize: options?.repetitionContextSize ?? 20\n })\n\n const result = JSON.parse(jsonStr) as JSONGenerationResult\n\n if (!result.success) {\n throw new Error(result.error ?? \"Generation failed\")\n }\n\n return {\n tokenCount: result.tokenCount ?? 0,\n tokensPerSecond: result.tokensPerSecond ?? 0\n }\n },\n\n isVLM(): boolean {\n return b.isVLM(handle)\n },\n\n unload(): void {\n b.unloadModel(handle)\n }\n }\n}\n\n/**\n * Generate text using a model (one-shot, loads and unloads model)\n *\n * @param modelId - HuggingFace model ID or local path\n * @param prompt - Input text\n * @param options - Generation options\n * @returns Generation result\n *\n * @example\n * ```typescript\n * import { generate } from \"node-mlx\"\n *\n * const result = generate(\n * RECOMMENDED_MODELS[\"gemma-3n\"],\n * \"Explain quantum computing\",\n * { maxTokens: 100 }\n * )\n * console.log(result.text)\n * ```\n */\nexport function generate(\n modelId: string,\n prompt: string,\n options?: GenerationOptions\n): GenerationResult {\n const model = loadModel(modelId)\n\n try {\n return model.generate(prompt, options)\n } finally {\n model.unload()\n }\n}\n"],"mappings":"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","names":["require"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { platform, arch } from \"node:os\"\nimport { join, dirname } from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\nimport { existsSync, readFileSync } from \"node:fs\"\nimport { createRequire } from \"node:module\"\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = dirname(__filename)\nconst require = createRequire(import.meta.url)\n\n// Read version from package.json\nconst packageJsonPath = join(__dirname, \"..\", \"package.json\")\nconst packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\")) as { version: string }\n\n/** Package version */\nexport const VERSION = packageJson.version\n\n// Native binding interface\ninterface NativeBinding {\n initialize(dylibPath: string): boolean\n isInitialized(): boolean\n loadModel(modelId: string): number\n unloadModel(handle: number): void\n generate(\n handle: number,\n prompt: string,\n options?: {\n maxTokens?: number\n temperature?: number\n topP?: number\n repetitionPenalty?: number\n repetitionContextSize?: number\n }\n ): string // Returns JSON string\n generateStreaming(\n handle: number,\n prompt: string,\n options?: {\n maxTokens?: number\n temperature?: number\n topP?: number\n repetitionPenalty?: number\n repetitionContextSize?: number\n }\n ): string // Streams to stdout, returns JSON stats\n generateWithImage(\n handle: number,\n prompt: string,\n imagePath: string,\n options?: {\n maxTokens?: number\n temperature?: number\n topP?: number\n repetitionPenalty?: number\n repetitionContextSize?: number\n }\n ): string // VLM: Streams to stdout, returns JSON stats\n isVLM(handle: number): boolean\n isAvailable(): boolean\n getVersion(): string\n}\n\n// JSON response from Swift\ninterface JSONGenerationResult {\n success: boolean\n text?: string\n tokenCount?: number\n tokensPerSecond?: number\n error?: string\n}\n\n// Load the native addon\nlet binding: NativeBinding | null = null\nlet initialized = false\n\n/**\n * Load native addon using node-gyp-build (prebuilds) or fallback to built addon\n */\nfunction loadNativeAddon(): NativeBinding {\n // Try node-gyp-build first (prebuilds)\n try {\n const gypBuild = require(\"node-gyp-build\") as (dir: string) => NativeBinding\n const nativeDir = join(__dirname, \"..\", \"native\")\n\n if (existsSync(join(__dirname, \"..\", \"prebuilds\"))) {\n return gypBuild(join(__dirname, \"..\"))\n }\n\n // Fallback to native/build if no prebuilds\n if (existsSync(join(nativeDir, \"build\"))) {\n return gypBuild(nativeDir)\n }\n } catch {\n // node-gyp-build failed, try manual loading\n }\n\n // Manual fallback: try different paths for the native addon\n const possibleAddonPaths = [\n // From package dist/ (npm installed)\n join(__dirname, \"..\", \"prebuilds\", \"darwin-arm64\", \"node.napi.node\"),\n // From native/build (local development)\n join(__dirname, \"..\", \"native\", \"build\", \"Release\", \"node_mlx.node\"),\n // From project root (monorepo development)\n join(process.cwd(), \"packages\", \"node-mlx\", \"native\", \"build\", \"Release\", \"node_mlx.node\")\n ]\n\n for (const p of possibleAddonPaths) {\n if (existsSync(p)) {\n return require(p) as NativeBinding\n }\n }\n\n throw new Error(\n \"Native addon not found. Run 'pnpm build:native' first.\\n\" +\n `Searched paths:\\n${possibleAddonPaths.join(\"\\n\")}`\n )\n}\n\n/**\n * Find Swift library path\n * Note: The library is expected to be in a directory with mlx.metallib for MLX to find it\n */\nfunction findSwiftLibrary(): string {\n const possibleDylibPaths = [\n // From package swift/ (preferred - has metallib co-located)\n join(__dirname, \"..\", \"swift\", \"libNodeMLX.dylib\"),\n // From project root packages/node-mlx/swift/ (monorepo development)\n join(process.cwd(), \"packages\", \"node-mlx\", \"swift\", \"libNodeMLX.dylib\"),\n // Fallback to packages/swift/.build (monorepo dev)\n join(__dirname, \"..\", \"..\", \"swift\", \".build\", \"release\", \"libNodeMLX.dylib\"),\n join(__dirname, \"..\", \"..\", \"..\", \"swift\", \".build\", \"release\", \"libNodeMLX.dylib\"),\n join(process.cwd(), \"packages\", \"swift\", \".build\", \"release\", \"libNodeMLX.dylib\")\n ]\n\n for (const p of possibleDylibPaths) {\n if (existsSync(p)) {\n return p\n }\n }\n\n throw new Error(\n \"Swift library not found. Run 'pnpm build:swift' first.\\n\" +\n `Searched paths:\\n${possibleDylibPaths.join(\"\\n\")}`\n )\n}\n\nfunction loadBinding(): NativeBinding {\n if (binding && initialized) {\n return binding\n }\n\n if (platform() !== \"darwin\" || arch() !== \"arm64\") {\n throw new Error(\"node-mlx is only supported on macOS Apple Silicon (arm64)\")\n }\n\n binding = loadNativeAddon()\n const dylibPath = findSwiftLibrary()\n const success = binding.initialize(dylibPath)\n\n if (!success) {\n throw new Error(\"Failed to initialize node-mlx native library\")\n }\n\n initialized = true\n\n return binding\n}\n\n// MARK: - Public Types\n\nexport interface GenerationOptions {\n maxTokens?: number\n temperature?: number\n topP?: number\n /** Penalty for repeating tokens (1.0 = no penalty, 1.1-1.2 recommended) */\n repetitionPenalty?: number\n /** Number of recent tokens to consider for penalty (default: 20) */\n repetitionContextSize?: number\n}\n\nexport interface GenerationResult {\n text: string\n tokenCount: number\n tokensPerSecond: number\n}\n\nexport interface StreamingResult {\n tokenCount: number\n tokensPerSecond: number\n}\n\nexport interface Model {\n /** Generate text from a prompt */\n generate(prompt: string, options?: GenerationOptions): GenerationResult\n\n /** Generate text with streaming - tokens are written directly to stdout */\n generateStreaming(prompt: string, options?: GenerationOptions): StreamingResult\n\n /** Generate text from a prompt with an image (VLM only) */\n generateWithImage(prompt: string, imagePath: string, options?: GenerationOptions): StreamingResult\n\n /** Check if this model supports images (is a Vision-Language Model) */\n isVLM(): boolean\n\n /** Unload the model from memory */\n unload(): void\n\n /** Model handle (internal use) */\n readonly handle: number\n}\n\n// MARK: - Recommended Models\n\nexport const RECOMMENDED_MODELS = {\n // Qwen 3 (Alibaba) - With Q/K norms\n qwen: \"lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit\", // Default to Qwen3\n qwen3: \"lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit\",\n \"qwen-3\": \"lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit\",\n \"qwen-3-4b\": \"lmstudio-community/Qwen3-4B-Instruct-2507-MLX-4bit\",\n \"qwen-3-0.6b\": \"mlx-community/Qwen3-0.6B-4bit\",\n \"qwen-3-1.7b\": \"mlx-community/Qwen3-1.7B-4bit\",\n\n // Qwen 2.5 (Alibaba) - Legacy, with attention bias\n \"qwen-2.5\": \"Qwen/Qwen2.5-1.5B-Instruct\",\n \"qwen-2.5-1.5b\": \"Qwen/Qwen2.5-1.5B-Instruct\",\n \"qwen-2.5-3b\": \"Qwen/Qwen2.5-3B-Instruct\",\n\n // Phi (Microsoft) - Working with fused QKV and RoPE\n phi: \"mlx-community/Phi-3.5-mini-instruct-4bit\", // Default to 3.5 (smaller, faster to download)\n phi4: \"mlx-community/phi-4-4bit\",\n \"phi-4\": \"mlx-community/phi-4-4bit\",\n \"phi-3.5\": \"mlx-community/Phi-3.5-mini-instruct-4bit\",\n \"phi-3.5-mini\": \"mlx-community/Phi-3.5-mini-instruct-4bit\",\n phi3: \"mlx-community/Phi-3-mini-4k-instruct-4bit\",\n \"phi-3\": \"mlx-community/Phi-3-mini-4k-instruct-4bit\",\n \"phi-3-mini\": \"mlx-community/Phi-3-mini-4k-instruct-4bit\",\n\n // Llama 3.2 (Meta) - Requires HuggingFace authentication\n // Note: meta-llama models require accepting license at huggingface.co\n llama: \"meta-llama/Llama-3.2-1B-Instruct\",\n \"llama-3.2\": \"meta-llama/Llama-3.2-1B-Instruct\",\n \"llama-3.2-1b\": \"meta-llama/Llama-3.2-1B-Instruct\",\n \"llama-3.2-3b\": \"meta-llama/Llama-3.2-3B-Instruct\",\n\n // Gemma 3 (Google) - Standard transformer architecture with sliding window\n gemma: \"mlx-community/gemma-3-1b-it-4bit\",\n \"gemma-3\": \"mlx-community/gemma-3-1b-it-4bit\",\n \"gemma-3-1b\": \"mlx-community/gemma-3-1b-it-4bit\",\n \"gemma-3-1b-bf16\": \"mlx-community/gemma-3-1b-it-bf16\",\n \"gemma-3-4b\": \"mlx-community/gemma-3-4b-it-4bit\",\n \"gemma-3-4b-bf16\": \"mlx-community/gemma-3-4b-it-bf16\",\n \"gemma-3-12b\": \"mlx-community/gemma-3-12b-it-4bit\",\n \"gemma-3-27b\": \"mlx-community/gemma-3-27b-it-4bit\",\n\n // Gemma 3n (Google) - Efficient architecture with AltUp and Laurel\n // Note: Use -lm variants (language model only, no audio/vision)\n \"gemma-3n\": \"mlx-community/gemma-3n-E4B-it-lm-4bit\",\n \"gemma-3n-e2b\": \"mlx-community/gemma-3n-E2B-it-lm-4bit\",\n \"gemma-3n-e4b\": \"mlx-community/gemma-3n-E4B-it-lm-4bit\"\n} as const\n\nexport type RecommendedModelKey = keyof typeof RECOMMENDED_MODELS\n\n// MARK: - Public API\n\n/**\n * Check if the platform is Apple Silicon Mac\n */\nexport function isPlatformSupported(): boolean {\n return platform() === \"darwin\" && arch() === \"arm64\"\n}\n\n/**\n * Check if MLX is available on this system\n * (requires macOS 14+ on Apple Silicon with built binaries)\n */\nexport function isSupported(): boolean {\n if (!isPlatformSupported()) {\n return false\n }\n\n try {\n const b = loadBinding()\n\n return b.isAvailable()\n } catch {\n return false\n }\n}\n\n/**\n * Get the library version\n */\nexport function getVersion(): string {\n const b = loadBinding()\n\n return b.getVersion()\n}\n\n/**\n * Load a model from HuggingFace or local path\n *\n * @param modelId - HuggingFace model ID (e.g., \"mlx-community/gemma-3n-E2B-it-4bit\") or local path\n * @returns Model instance\n *\n * @example\n * ```typescript\n * import { loadModel, RECOMMENDED_MODELS } from \"node-mlx\"\n *\n * const model = loadModel(RECOMMENDED_MODELS[\"gemma-3n\"])\n * const result = model.generate(\"Hello, world!\")\n * console.log(result.text)\n * model.unload()\n * ```\n */\n/**\n * Resolve a model ID or alias to a full HuggingFace model ID\n * @param modelId - Either a full HuggingFace model ID (e.g., \"mlx-community/phi-4-4bit\") or a short alias (e.g., \"phi4\")\n * @returns The full HuggingFace model ID\n */\nfunction resolveModelId(modelId: string): string {\n // Check if it's an alias in RECOMMENDED_MODELS\n if (modelId in RECOMMENDED_MODELS) {\n return RECOMMENDED_MODELS[modelId as keyof typeof RECOMMENDED_MODELS]\n }\n\n // Otherwise assume it's already a full model ID\n return modelId\n}\n\nexport function loadModel(modelId: string): Model {\n const b = loadBinding()\n const resolvedId = resolveModelId(modelId)\n const handle = b.loadModel(resolvedId)\n\n return {\n handle,\n\n generate(prompt: string, options?: GenerationOptions): GenerationResult {\n const jsonStr = b.generate(handle, prompt, {\n maxTokens: options?.maxTokens ?? 256,\n temperature: options?.temperature ?? 0.7,\n topP: options?.topP ?? 0.9,\n repetitionPenalty: options?.repetitionPenalty ?? 1.1,\n repetitionContextSize: options?.repetitionContextSize ?? 20\n })\n\n const result = JSON.parse(jsonStr) as JSONGenerationResult\n\n if (!result.success) {\n throw new Error(result.error ?? \"Generation failed\")\n }\n\n return {\n text: result.text ?? \"\",\n tokenCount: result.tokenCount ?? 0,\n tokensPerSecond: result.tokensPerSecond ?? 0\n }\n },\n\n generateStreaming(prompt: string, options?: GenerationOptions): StreamingResult {\n // Tokens are written directly to stdout by Swift\n const jsonStr = b.generateStreaming(handle, prompt, {\n maxTokens: options?.maxTokens ?? 256,\n temperature: options?.temperature ?? 0.7,\n topP: options?.topP ?? 0.9,\n repetitionPenalty: options?.repetitionPenalty ?? 1.1,\n repetitionContextSize: options?.repetitionContextSize ?? 20\n })\n\n const result = JSON.parse(jsonStr) as JSONGenerationResult\n\n if (!result.success) {\n throw new Error(result.error ?? \"Generation failed\")\n }\n\n return {\n tokenCount: result.tokenCount ?? 0,\n tokensPerSecond: result.tokensPerSecond ?? 0\n }\n },\n\n generateWithImage(\n prompt: string,\n imagePath: string,\n options?: GenerationOptions\n ): StreamingResult {\n // VLM generation with image - tokens are written directly to stdout by Swift\n const jsonStr = b.generateWithImage(handle, prompt, imagePath, {\n maxTokens: options?.maxTokens ?? 256,\n temperature: options?.temperature ?? 0.7,\n topP: options?.topP ?? 0.9,\n repetitionPenalty: options?.repetitionPenalty ?? 1.1,\n repetitionContextSize: options?.repetitionContextSize ?? 20\n })\n\n const result = JSON.parse(jsonStr) as JSONGenerationResult\n\n if (!result.success) {\n throw new Error(result.error ?? \"Generation failed\")\n }\n\n return {\n tokenCount: result.tokenCount ?? 0,\n tokensPerSecond: result.tokensPerSecond ?? 0\n }\n },\n\n isVLM(): boolean {\n return b.isVLM(handle)\n },\n\n unload(): void {\n b.unloadModel(handle)\n }\n }\n}\n\n/**\n * Generate text using a model (one-shot, loads and unloads model)\n *\n * @param modelId - HuggingFace model ID or local path\n * @param prompt - Input text\n * @param options - Generation options\n * @returns Generation result\n *\n * @example\n * ```typescript\n * import { generate } from \"node-mlx\"\n *\n * const result = generate(\n * RECOMMENDED_MODELS[\"gemma-3n\"],\n * \"Explain quantum computing\",\n * { maxTokens: 100 }\n * )\n * console.log(result.text)\n * ```\n */\nexport function generate(\n modelId: string,\n prompt: string,\n options?: GenerationOptions\n): GenerationResult {\n const model = loadModel(modelId)\n\n try {\n return model.generate(prompt, options)\n } finally {\n model.unload()\n }\n}\n"],"mappings":"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","names":["require"]}
|
package/package.json
CHANGED
|
Binary file
|
package/swift/libNodeMLX.dylib
CHANGED
|
Binary file
|