@mlx-node/lm 0.0.0 → 0.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/README.md ADDED
@@ -0,0 +1,212 @@
1
+ # @mlx-node/lm
2
+
3
+ High-level language model inference for Node.js on Apple Silicon. Supports Qwen3 and Qwen3.5 (Dense and MoE) with streaming, tool calling, and profiling — all running locally on Metal GPU.
4
+
5
+ ## Requirements
6
+
7
+ - macOS with Apple Silicon (M1 or later)
8
+ - Node.js 18+
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ npm install @mlx-node/lm
14
+ ```
15
+
16
+ ## Quick Start
17
+
18
+ ```typescript
19
+ import { loadModel } from '@mlx-node/lm';
20
+
21
+ const model = await loadModel('./models/Qwen3-0.6B');
22
+
23
+ const result = model.chat([{ role: 'user', content: 'What is the capital of France?' }]);
24
+
25
+ console.log(result.text);
26
+ ```
27
+
28
+ ## Streaming
29
+
30
+ Qwen3.5 models support token-by-token streaming via `AsyncGenerator`:
31
+
32
+ ```typescript
33
+ import { loadModel } from '@mlx-node/lm';
34
+
35
+ const model = await loadModel('./models/Qwen3.5-0.6B');
36
+
37
+ for await (const event of model.chatStream(messages, config)) {
38
+ if (!event.done) {
39
+ process.stdout.write(event.text);
40
+ } else {
41
+ console.log(`\n${event.numTokens} tokens, finish: ${event.finishReason}`);
42
+ }
43
+ }
44
+ ```
45
+
46
+ Breaking out of the loop automatically cancels generation.
47
+
48
+ ## Tool Calling
49
+
50
+ OpenAI-compatible function calling with `createToolDefinition`:
51
+
52
+ ```typescript
53
+ import { loadModel, createToolDefinition, formatToolResponse } from '@mlx-node/lm';
54
+
55
+ const model = await loadModel('./models/Qwen3-0.6B');
56
+
57
+ const tools = [
58
+ createToolDefinition(
59
+ 'get_weather',
60
+ 'Get weather for a city',
61
+ {
62
+ city: { type: 'string', description: 'City name' },
63
+ },
64
+ ['city'],
65
+ ),
66
+ ];
67
+
68
+ const result = model.chat([{ role: 'user', content: 'What is the weather in Tokyo?' }], { tools });
69
+
70
+ // If the model calls a tool, execute it and continue
71
+ if (result.toolCalls?.length) {
72
+ const toolResult = executeMyTool(result.toolCalls[0]);
73
+ const followUp = model.chat(
74
+ [
75
+ ...messages,
76
+ { role: 'assistant', content: result.rawText },
77
+ { role: 'tool', content: formatToolResponse(toolResult) },
78
+ ],
79
+ { tools },
80
+ );
81
+ }
82
+ ```
83
+
84
+ ## Model Loading
85
+
86
+ `loadModel()` auto-detects the model architecture from `config.json`:
87
+
88
+ ```typescript
89
+ import { loadModel, Qwen35Model, Qwen35MoeModel } from '@mlx-node/lm';
90
+
91
+ // Auto-detect (reads config.json model_type field)
92
+ const model = await loadModel('./models/Qwen3-0.6B');
93
+
94
+ // Or load a specific architecture directly
95
+ const dense = await Qwen35Model.load('./models/Qwen3.5-0.8B');
96
+ const moe = await Qwen35MoeModel.load('./models/Qwen3.5-35B-A3B');
97
+ ```
98
+
99
+ ### Pre-defined Configs
100
+
101
+ ```typescript
102
+ import { QWEN3_CONFIGS, QWEN35_CONFIGS, getQwen3Config, getQwen35Config } from '@mlx-node/lm';
103
+
104
+ // Available Qwen3 configs: 'qwen3-0.6b', 'qwen3-1.7b', 'qwen3-7b'
105
+ const config = getQwen3Config('qwen3-0.6b');
106
+
107
+ // Available Qwen3.5 configs: 'qwen3.5-0.8b'
108
+ const config35 = getQwen35Config('qwen3.5-0.8b');
109
+ ```
110
+
111
+ ## Profiling
112
+
113
+ Track per-generation timing, memory usage, and TTFT:
114
+
115
+ ```typescript
116
+ import { enableProfiling, disableProfiling } from '@mlx-node/lm';
117
+
118
+ enableProfiling();
119
+
120
+ // ... run inference ...
121
+
122
+ disableProfiling(); // writes mlx-profile-{timestamp}.json
123
+ ```
124
+
125
+ Or set `MLX_PROFILE_DECODE=1` to auto-enable and write a report on exit.
126
+
127
+ ## API Reference
128
+
129
+ ### Classes
130
+
131
+ | Class | Description |
132
+ | ---------------- | -------------------------------------------------------------------------------- |
133
+ | `loadModel()` | Auto-detect and load any supported model from disk |
134
+ | `Qwen3Model` | Qwen3 inference — `generate()`, `chat()`, paged attention, speculative decoding |
135
+ | `Qwen35Model` | Qwen3.5 Dense — `generate()`, `chat()`, `chatStream()` with compiled C++ forward |
136
+ | `Qwen35MoeModel` | Qwen3.5 MoE — same API as Dense with expert routing |
137
+
138
+ ### Streaming Types
139
+
140
+ ```typescript
141
+ // Intermediate token
142
+ interface ChatStreamDelta {
143
+ text: string;
144
+ done: false;
145
+ }
146
+
147
+ // Final result
148
+ interface ChatStreamFinal {
149
+ text: string;
150
+ done: true;
151
+ finishReason: string;
152
+ toolCalls?: ToolCallResult[];
153
+ thinking?: string;
154
+ numTokens: number;
155
+ rawText: string;
156
+ performance?: PerformanceMetrics;
157
+ }
158
+
159
+ type ChatStreamEvent = ChatStreamDelta | ChatStreamFinal;
160
+ ```
161
+
162
+ ### Tool Types
163
+
164
+ ```typescript
165
+ interface ToolDefinition {
166
+ type: 'function';
167
+ function: FunctionDefinition;
168
+ }
169
+
170
+ interface FunctionDefinition {
171
+ name: string;
172
+ description?: string;
173
+ parameters?: FunctionParameters;
174
+ }
175
+
176
+ function createToolDefinition(
177
+ name: string,
178
+ description?: string,
179
+ properties?: Record<string, FunctionParameterProperty>,
180
+ required?: string[],
181
+ ): ToolDefinition;
182
+
183
+ function formatToolResponse(content: string): string;
184
+ ```
185
+
186
+ ### Functions
187
+
188
+ | Function | Description |
189
+ | ------------------------ | ---------------------------------------------------- |
190
+ | `createToolDefinition()` | Create an OpenAI-compatible tool definition |
191
+ | `formatToolResponse()` | Wrap tool output in `<tool_response>` tags |
192
+ | `detectModelType()` | Read `config.json` and return the `model_type` field |
193
+ | `enableProfiling()` | Start profiling with auto-report on exit |
194
+ | `disableProfiling()` | Stop profiling and write JSON report |
195
+
196
+ ## Supported Models
197
+
198
+ | Model | `chat()` | `chatStream()` | Training | Notes |
199
+ | ------------- | :------: | :------------: | :------: | ------------------------------------- |
200
+ | Qwen3 | Yes | No | GRPO/SFT | Paged attention, speculative decoding |
201
+ | Qwen3.5 Dense | Yes | Yes | GRPO/SFT | Compiled C++ forward, VLM variant |
202
+ | Qwen3.5 MoE | Yes | Yes | GRPO/SFT | Compiled C++ forward, expert routing |
203
+
204
+ ## Performance
205
+
206
+ - Almost the same with the python `mlx-lm` package
207
+ - Metal GPU acceleration on all Apple Silicon
208
+ - Compiled forward passes via `mlx::core::compile` for graph caching
209
+
210
+ ## License
211
+
212
+ [MIT](https://github.com/mlx-node/mlx-node/blob/main/LICENSE)
package/package.json CHANGED
@@ -1,6 +1,16 @@
1
1
  {
2
2
  "name": "@mlx-node/lm",
3
- "version": "0.0.0",
3
+ "version": "0.0.1",
4
+ "homepage": "https://github.com/mlx-node/mlx-node",
5
+ "bugs": {
6
+ "url": "https://github.com/mlx-node/mlx-node/issues"
7
+ },
8
+ "license": "MIT",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/mlx-node/mlx-node.git",
12
+ "directory": "packages/lm"
13
+ },
4
14
  "files": [
5
15
  "dist"
6
16
  ],
@@ -18,6 +28,6 @@
18
28
  "test": "vite test run"
19
29
  },
20
30
  "dependencies": {
21
- "@mlx-node/core": "0.0.0"
31
+ "@mlx-node/core": "0.0.1"
22
32
  }
23
33
  }
package/dist/index.d.ts DELETED
@@ -1,22 +0,0 @@
1
- /**
2
- * @mlx-node/lm - High-level inference API for MLX models
3
- *
4
- * This package provides everything needed for model loading and inference,
5
- * aligned with Python's mlx-lm library.
6
- *
7
- * @example
8
- * ```typescript
9
- * import { Qwen3Model, ModelLoader, QWEN3_CONFIGS } from '@mlx-node/lm';
10
- *
11
- * const model = await ModelLoader.loadPretrained('./models/qwen3-0.6b');
12
- * const result = await model.generate([{ role: 'user', content: 'Hello!' }]);
13
- * ```
14
- */
15
- export { Qwen3Model, Qwen3Tokenizer } from '@mlx-node/core';
16
- export type { DType } from '@mlx-node/core';
17
- export type { SamplingConfig, BatchGenerationResult } from '@mlx-node/core';
18
- export type { ToolCallResult, ChatResult, ChatConfig, ChatMessage } from '@mlx-node/core';
19
- export { type Qwen3Config, QWEN3_CONFIGS, type GenerationResult, type GenerationConfig, getQwen3Config, } from './models/qwen3-configs';
20
- export { ModelLoader } from './models/model-loader';
21
- export * from './tools';
22
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAK5D,YAAY,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC5C,YAAY,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAG5E,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG1F,OAAO,EACL,KAAK,WAAW,EAChB,aAAa,EACb,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,cAAc,GACf,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGpD,cAAc,SAAS,CAAC"}
package/dist/index.js DELETED
@@ -1,21 +0,0 @@
1
- /**
2
- * @mlx-node/lm - High-level inference API for MLX models
3
- *
4
- * This package provides everything needed for model loading and inference,
5
- * aligned with Python's mlx-lm library.
6
- *
7
- * @example
8
- * ```typescript
9
- * import { Qwen3Model, ModelLoader, QWEN3_CONFIGS } from '@mlx-node/lm';
10
- *
11
- * const model = await ModelLoader.loadPretrained('./models/qwen3-0.6b');
12
- * const result = await model.generate([{ role: 'user', content: 'Hello!' }]);
13
- * ```
14
- */
15
- // Model classes (for inference)
16
- export { Qwen3Model, Qwen3Tokenizer } from '@mlx-node/core';
17
- // Model utilities (TypeScript-only)
18
- export { QWEN3_CONFIGS, getQwen3Config, } from './models/qwen3-configs';
19
- export { ModelLoader } from './models/model-loader';
20
- // Tool calling utilities
21
- export * from './tools';
@@ -1,32 +0,0 @@
1
- /**
2
- * Model loader utilities for Qwen3 models
3
- *
4
- * Handles loading pretrained weights from MLX format or converting from HuggingFace.
5
- */
6
- import { Qwen3Model } from '@mlx-node/core';
7
- /**
8
- * Model loader for Qwen3 models
9
- */
10
- export declare class ModelLoader {
11
- /**
12
- * Load a pretrained Qwen3 model from disk
13
- *
14
- * Delegates to Rust implementation for efficient loading without JavaScript memory limits.
15
- *
16
- * @param modelPath - Path to the model directory or file
17
- * @param _deviceMap - Device placement (not used in MLX, kept for compatibility)
18
- * @returns Loaded model
19
- */
20
- static loadPretrained(modelPath: string, _deviceMap?: string): Promise<Qwen3Model>;
21
- /**
22
- * Save model configuration and metadata to disk
23
- *
24
- * This delegates to the Rust implementation which efficiently handles
25
- * model saving without running into JavaScript memory/array size limits.
26
- *
27
- * Note: This saves configuration and parameter metadata only.
28
- * For full model weight serialization, use safetensors or binary format.
29
- */
30
- static saveModel(model: Qwen3Model, savePath: string): Promise<void>;
31
- }
32
- //# sourceMappingURL=model-loader.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"model-loader.d.ts","sourceRoot":"","sources":["../../src/models/model-loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C;;GAEG;AACH,qBAAa,WAAW;IACtB;;;;;;;;OAQG;WACU,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,GAAE,MAAe,GAAG,OAAO,CAAC,UAAU,CAAC;IAKhG;;;;;;;;OAQG;IACH,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAIrE"}
@@ -1,37 +0,0 @@
1
- /**
2
- * Model loader utilities for Qwen3 models
3
- *
4
- * Handles loading pretrained weights from MLX format or converting from HuggingFace.
5
- */
6
- import { Qwen3Model } from '@mlx-node/core';
7
- /**
8
- * Model loader for Qwen3 models
9
- */
10
- export class ModelLoader {
11
- /**
12
- * Load a pretrained Qwen3 model from disk
13
- *
14
- * Delegates to Rust implementation for efficient loading without JavaScript memory limits.
15
- *
16
- * @param modelPath - Path to the model directory or file
17
- * @param _deviceMap - Device placement (not used in MLX, kept for compatibility)
18
- * @returns Loaded model
19
- */
20
- static async loadPretrained(modelPath, _deviceMap = 'auto') {
21
- // Delegate to Rust implementation for efficient loading
22
- return await Qwen3Model.loadPretrained(modelPath);
23
- }
24
- /**
25
- * Save model configuration and metadata to disk
26
- *
27
- * This delegates to the Rust implementation which efficiently handles
28
- * model saving without running into JavaScript memory/array size limits.
29
- *
30
- * Note: This saves configuration and parameter metadata only.
31
- * For full model weight serialization, use safetensors or binary format.
32
- */
33
- static saveModel(model, savePath) {
34
- // Delegate to Rust implementation for efficient saving
35
- return model.saveModel(savePath);
36
- }
37
- }
@@ -1,48 +0,0 @@
1
- /**
2
- * Qwen3 Model Configurations and Type Definitions
3
- *
4
- * This module provides:
5
- * - Default configurations for common Qwen3 model sizes
6
- * - Type re-exports from Rust with enhanced documentation
7
- * - Helper functions for config management
8
- */
9
- import type { Qwen3Config as RustQwen3Config, GenerationConfig as RustGenerationConfig, GenerationResult as RustGenerationResult } from '@mlx-node/core';
10
- /**
11
- * Configuration for Qwen3 models
12
- *
13
- * All fields are required when creating a model directly.
14
- * Use QWEN3_CONFIGS for pre-configured model sizes.
15
- */
16
- export type Qwen3Config = RustQwen3Config;
17
- /**
18
- * Configuration for text generation
19
- *
20
- * Controls sampling behavior, temperature, and stopping criteria.
21
- */
22
- export type GenerationConfig = RustGenerationConfig;
23
- /**
24
- * Result from text generation with detailed metadata
25
- *
26
- * Includes generated tokens, log probabilities, finish reason, and token count.
27
- */
28
- export type GenerationResult = RustGenerationResult;
29
- /**
30
- * Default configurations for common Qwen3 models
31
- *
32
- * Includes optimized hyperparameters for:
33
- * - qwen3-0.6b: Smallest model (1024 hidden size, 28 layers)
34
- * - qwen3-1.8b: Medium model (1536 hidden size, 28 layers)
35
- * - qwen3-7b: Large model (3072 hidden size, 32 layers)
36
- */
37
- export declare const QWEN3_CONFIGS: {
38
- [key: string]: Qwen3Config;
39
- };
40
- /**
41
- * Get a Qwen3 configuration by name
42
- *
43
- * @param name - Model name (e.g., "qwen3-0.6b", "qwen3-1.8b", "qwen3-7b")
44
- * @returns Model configuration
45
- * @throws Error if model name is not recognized
46
- */
47
- export declare function getQwen3Config(name: string): Qwen3Config;
48
- //# sourceMappingURL=qwen3-configs.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"qwen3-configs.d.ts","sourceRoot":"","sources":["../../src/models/qwen3-configs.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,WAAW,IAAI,eAAe,EAC9B,gBAAgB,IAAI,oBAAoB,EACxC,gBAAgB,IAAI,oBAAoB,EACzC,MAAM,gBAAgB,CAAC;AAExB;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG,eAAe,CAAC;AAE1C;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,CAAC;AAEpD;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,CAAC;AAEpD;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAAA;CAoDvD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAMxD"}
@@ -1,83 +0,0 @@
1
- /**
2
- * Qwen3 Model Configurations and Type Definitions
3
- *
4
- * This module provides:
5
- * - Default configurations for common Qwen3 model sizes
6
- * - Type re-exports from Rust with enhanced documentation
7
- * - Helper functions for config management
8
- */
9
- /**
10
- * Default configurations for common Qwen3 models
11
- *
12
- * Includes optimized hyperparameters for:
13
- * - qwen3-0.6b: Smallest model (1024 hidden size, 28 layers)
14
- * - qwen3-1.8b: Medium model (1536 hidden size, 28 layers)
15
- * - qwen3-7b: Large model (3072 hidden size, 32 layers)
16
- */
17
- export const QWEN3_CONFIGS = {
18
- 'qwen3-0.6b': {
19
- vocabSize: 151936,
20
- hiddenSize: 1024,
21
- numLayers: 28,
22
- numHeads: 16,
23
- numKvHeads: 8, // GQA with 2:1 ratio
24
- headDim: 64, // hiddenSize / numHeads = 1024 / 16 = 64
25
- intermediateSize: 3072,
26
- rmsNormEps: 1e-6,
27
- ropeTheta: 1000000.0,
28
- maxPositionEmbeddings: 40960,
29
- useQkNorm: true, // Qwen3 always uses QK normalization (core feature)
30
- tieWordEmbeddings: true,
31
- padTokenId: 151643,
32
- eosTokenId: 151645,
33
- bosTokenId: 151643,
34
- },
35
- 'qwen3-1.8b': {
36
- vocabSize: 151936,
37
- hiddenSize: 1536,
38
- numLayers: 28,
39
- numHeads: 12,
40
- numKvHeads: 2, // GQA with 6:1 ratio
41
- headDim: 128, // hiddenSize / numHeads = 1536 / 12 = 128
42
- intermediateSize: 8960,
43
- rmsNormEps: 1e-6,
44
- ropeTheta: 1000000.0,
45
- maxPositionEmbeddings: 131072,
46
- useQkNorm: true, // Qwen3 always uses QK normalization (core feature)
47
- tieWordEmbeddings: false,
48
- padTokenId: 151643,
49
- eosTokenId: 151645,
50
- bosTokenId: 151643,
51
- },
52
- 'qwen3-7b': {
53
- vocabSize: 151936,
54
- hiddenSize: 3072,
55
- numLayers: 32,
56
- numHeads: 24,
57
- numKvHeads: 4, // GQA with 6:1 ratio
58
- headDim: 128, // hiddenSize / numHeads = 3072 / 24 = 128
59
- intermediateSize: 18944,
60
- rmsNormEps: 1e-6,
61
- ropeTheta: 1000000.0,
62
- maxPositionEmbeddings: 131072,
63
- useQkNorm: true, // Qwen3 always uses QK normalization (core feature)
64
- tieWordEmbeddings: false,
65
- padTokenId: 151643,
66
- eosTokenId: 151645,
67
- bosTokenId: 151643,
68
- },
69
- };
70
- /**
71
- * Get a Qwen3 configuration by name
72
- *
73
- * @param name - Model name (e.g., "qwen3-0.6b", "qwen3-1.8b", "qwen3-7b")
74
- * @returns Model configuration
75
- * @throws Error if model name is not recognized
76
- */
77
- export function getQwen3Config(name) {
78
- const config = QWEN3_CONFIGS[name];
79
- if (!config) {
80
- throw new Error(`Unknown model configuration: ${name}. Available models: ${Object.keys(QWEN3_CONFIGS).join(', ')}`);
81
- }
82
- return config;
83
- }
@@ -1,31 +0,0 @@
1
- /**
2
- * Tool calling utilities for Qwen3
3
- *
4
- * Provides types and helpers for working with tool/function calling in the chat() API.
5
- *
6
- * @example
7
- * ```typescript
8
- * import { createToolDefinition, formatToolResponse } from '@mlx-node/lm';
9
- *
10
- * const weatherTool = createToolDefinition(
11
- * 'get_weather',
12
- * 'Get weather for a location',
13
- * { location: { type: 'string', description: 'City name' } },
14
- * ['location']
15
- * );
16
- *
17
- * const result = await model.chat(messages, { tools: [weatherTool] });
18
- *
19
- * for (const call of result.toolCalls) {
20
- * if (call.status === 'ok') {
21
- * const toolResult = await executeMyTool(call.name, call.arguments);
22
- * // Continue conversation with tool result
23
- * messages.push({ role: 'user', content: formatToolResponse(toolResult) });
24
- * }
25
- * }
26
- * ```
27
- *
28
- * @module tools
29
- */
30
- export * from './types';
31
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,cAAc,SAAS,CAAC"}
@@ -1,30 +0,0 @@
1
- /**
2
- * Tool calling utilities for Qwen3
3
- *
4
- * Provides types and helpers for working with tool/function calling in the chat() API.
5
- *
6
- * @example
7
- * ```typescript
8
- * import { createToolDefinition, formatToolResponse } from '@mlx-node/lm';
9
- *
10
- * const weatherTool = createToolDefinition(
11
- * 'get_weather',
12
- * 'Get weather for a location',
13
- * { location: { type: 'string', description: 'City name' } },
14
- * ['location']
15
- * );
16
- *
17
- * const result = await model.chat(messages, { tools: [weatherTool] });
18
- *
19
- * for (const call of result.toolCalls) {
20
- * if (call.status === 'ok') {
21
- * const toolResult = await executeMyTool(call.name, call.arguments);
22
- * // Continue conversation with tool result
23
- * messages.push({ role: 'user', content: formatToolResponse(toolResult) });
24
- * }
25
- * }
26
- * ```
27
- *
28
- * @module tools
29
- */
30
- export * from './types';
@@ -1,206 +0,0 @@
1
- /**
2
- * OpenAI-compatible tool calling types for Qwen3
3
- *
4
- * These types match the OpenAI function calling API format and can be used
5
- * with applyChatTemplate() when tools are provided.
6
- *
7
- * @remarks
8
- * **Important**: Due to NAPI-RS limitations with recursive generic types,
9
- * `FunctionParameters.properties` must be passed as a JSON string to the Rust layer.
10
- * Use the {@link createToolDefinition} helper to automatically handle this conversion.
11
- *
12
- * @example
13
- * ```typescript
14
- * // Recommended: Use the helper function
15
- * const tool = createToolDefinition('get_weather', 'Get weather info', {
16
- * location: { type: 'string', description: 'City name' },
17
- * units: { type: 'string', enum: ['celsius', 'fahrenheit'] }
18
- * }, ['location']);
19
- *
20
- * // Manual approach (if needed)
21
- * const manualTool: ToolDefinition = {
22
- * type: 'function',
23
- * function: {
24
- * name: 'get_weather',
25
- * parameters: {
26
- * type: 'object',
27
- * properties: JSON.stringify({ location: { type: 'string' } }),
28
- * required: ['location']
29
- * }
30
- * }
31
- * };
32
- * ```
33
- */
34
- /**
35
- * Tool type - currently only "function" is supported
36
- */
37
- export type ToolType = 'function';
38
- /**
39
- * Function parameter property definition (JSON Schema subset)
40
- *
41
- * This type is used for the developer-friendly API in {@link createToolDefinition}.
42
- * It represents the structure of JSON Schema properties.
43
- */
44
- export interface FunctionParameterProperty {
45
- type: 'string' | 'number' | 'boolean' | 'integer' | 'array' | 'object';
46
- description?: string;
47
- enum?: string[];
48
- items?: FunctionParameterProperty;
49
- properties?: Record<string, FunctionParameterProperty>;
50
- required?: string[];
51
- }
52
- /**
53
- * Function parameters schema (JSON Schema subset)
54
- *
55
- * @remarks
56
- * **NAPI Limitation**: The `properties` field must be a JSON string, not an object.
57
- * This is because NAPI-RS cannot expose recursive generic types like
58
- * `Record<string, FunctionParameterProperty>` directly to Rust.
59
- *
60
- * Use {@link createToolDefinition} to avoid manual JSON.stringify() calls.
61
- */
62
- export interface FunctionParameters {
63
- /** Type of the parameters object (always "object") */
64
- type: 'object';
65
- /**
66
- * JSON string of property definitions.
67
- *
68
- * @remarks
69
- * Must be a JSON-stringified object, e.g.: `JSON.stringify({ name: { type: 'string' } })`
70
- * Use {@link createToolDefinition} helper to avoid manual stringification.
71
- */
72
- properties?: string;
73
- /** List of required parameter names */
74
- required?: string[];
75
- }
76
- /**
77
- * Function definition for tool calling
78
- */
79
- export interface FunctionDefinition {
80
- /** Name of the function */
81
- name: string;
82
- /** Description of what the function does */
83
- description?: string;
84
- /** JSON Schema for the function parameters */
85
- parameters?: FunctionParameters;
86
- }
87
- /**
88
- * OpenAI-compatible tool definition
89
- */
90
- export interface ToolDefinition {
91
- /** Tool type (currently only "function" is supported) */
92
- type: ToolType;
93
- /** Function definition */
94
- function: FunctionDefinition;
95
- }
96
- /**
97
- * Tool call made by an assistant
98
- */
99
- export interface ToolCall {
100
- /** Optional unique identifier for the tool call */
101
- id?: string;
102
- /** Name of the tool/function to call */
103
- name: string;
104
- /** JSON string of arguments to pass to the tool */
105
- arguments: string;
106
- }
107
- /**
108
- * Chat message roles
109
- */
110
- export type ChatRole = 'system' | 'user' | 'assistant' | 'tool';
111
- /**
112
- * Chat message with tool calling support
113
- *
114
- * This extends the basic ChatMessage to support tool calls and responses.
115
- */
116
- export interface ChatMessageWithTools {
117
- /** Message role */
118
- role: ChatRole;
119
- /** Message content */
120
- content: string;
121
- /** Tool calls made by the assistant (for assistant messages) */
122
- toolCalls?: ToolCall[];
123
- /** Tool call ID this message is responding to (for tool messages) */
124
- toolCallId?: string;
125
- /** Reasoning content for thinking mode (used with <think> tags) */
126
- reasoningContent?: string;
127
- }
128
- /**
129
- * Options for applying chat template with tools
130
- */
131
- export interface ApplyChatTemplateOptions {
132
- /** Whether to add generation prompt at end (default: true) */
133
- addGenerationPrompt?: boolean;
134
- /** Array of tool definitions for function calling */
135
- tools?: ToolDefinition[];
136
- /**
137
- * Control thinking mode behavior.
138
- *
139
- * @remarks
140
- * **Counter-intuitive semantics** (from Qwen3's Jinja2 template):
141
- * - `undefined` or `true`: Model thinks naturally (no tags added)
142
- * - `false`: Adds empty `<think>\n\n</think>\n\n` tags to **disable** thinking
143
- *
144
- * The default is `false` for tool use, which disables thinking to avoid
145
- * verbose reasoning during tool calls.
146
- *
147
- * @example
148
- * ```typescript
149
- * // Allow model to think (default behavior without tools)
150
- * { enableThinking: true }
151
- *
152
- * // Disable thinking (adds empty <think></think> tags)
153
- * { enableThinking: false }
154
- * ```
155
- */
156
- enableThinking?: boolean;
157
- }
158
- /**
159
- * Create a tool definition with automatic JSON stringification of properties.
160
- *
161
- * This helper handles the NAPI-RS limitation where `properties` must be a JSON string.
162
- *
163
- * @param name - The function name
164
- * @param description - Description of what the function does
165
- * @param properties - Object defining the function parameters (will be JSON stringified)
166
- * @param required - Array of required parameter names
167
- * @returns A properly formatted ToolDefinition ready for use with model.chat()
168
- *
169
- * @example
170
- * ```typescript
171
- * const weatherTool = createToolDefinition(
172
- * 'get_weather',
173
- * 'Get weather information for a location',
174
- * {
175
- * location: { type: 'string', description: 'City name' },
176
- * units: { type: 'string', enum: ['celsius', 'fahrenheit'] }
177
- * },
178
- * ['location']
179
- * );
180
- *
181
- * const result = await model.chat(messages, { tools: [weatherTool] });
182
- * ```
183
- */
184
- export declare function createToolDefinition(name: string, description?: string, properties?: Record<string, FunctionParameterProperty>, required?: string[]): ToolDefinition;
185
- /**
186
- * Format a tool response for inclusion in a message
187
- *
188
- * Creates a properly formatted tool response string that can be used
189
- * in tool messages when continuing a conversation after a tool call.
190
- *
191
- * @param content - The response content (will be JSON stringified if object)
192
- * @returns Formatted tool response string wrapped in `<tool_response>` tags
193
- *
194
- * @example
195
- * ```typescript
196
- * // After executing a tool call from model.chat()
197
- * const toolResult = await executeMyTool(call.arguments);
198
- * const responseMessage = {
199
- * role: 'user',
200
- * content: formatToolResponse(toolResult)
201
- * };
202
- * const finalResult = await model.chat([...messages, responseMessage]);
203
- * ```
204
- */
205
- export declare function formatToolResponse(content: unknown): string;
206
- //# sourceMappingURL=types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,UAAU,CAAC;AAElC;;;;;GAKG;AACH,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;IACvE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,yBAAyB,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;IACvD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,kBAAkB;IACjC,sDAAsD;IACtD,IAAI,EAAE,QAAQ,CAAC;IACf;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,kBAAkB,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,yDAAyD;IACzD,IAAI,EAAE,QAAQ,CAAC;IACf,0BAA0B;IAC1B,QAAQ,EAAE,kBAAkB,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,mDAAmD;IACnD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;AAEhE;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,mBAAmB;IACnB,IAAI,EAAE,QAAQ,CAAC;IACf,sBAAsB;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,8DAA8D;IAC9D,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,qDAAqD;IACrD,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,EACtD,QAAQ,CAAC,EAAE,MAAM,EAAE,GAClB,cAAc,CAehB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAK3D"}
@@ -1,101 +0,0 @@
1
- /**
2
- * OpenAI-compatible tool calling types for Qwen3
3
- *
4
- * These types match the OpenAI function calling API format and can be used
5
- * with applyChatTemplate() when tools are provided.
6
- *
7
- * @remarks
8
- * **Important**: Due to NAPI-RS limitations with recursive generic types,
9
- * `FunctionParameters.properties` must be passed as a JSON string to the Rust layer.
10
- * Use the {@link createToolDefinition} helper to automatically handle this conversion.
11
- *
12
- * @example
13
- * ```typescript
14
- * // Recommended: Use the helper function
15
- * const tool = createToolDefinition('get_weather', 'Get weather info', {
16
- * location: { type: 'string', description: 'City name' },
17
- * units: { type: 'string', enum: ['celsius', 'fahrenheit'] }
18
- * }, ['location']);
19
- *
20
- * // Manual approach (if needed)
21
- * const manualTool: ToolDefinition = {
22
- * type: 'function',
23
- * function: {
24
- * name: 'get_weather',
25
- * parameters: {
26
- * type: 'object',
27
- * properties: JSON.stringify({ location: { type: 'string' } }),
28
- * required: ['location']
29
- * }
30
- * }
31
- * };
32
- * ```
33
- */
34
- /**
35
- * Create a tool definition with automatic JSON stringification of properties.
36
- *
37
- * This helper handles the NAPI-RS limitation where `properties` must be a JSON string.
38
- *
39
- * @param name - The function name
40
- * @param description - Description of what the function does
41
- * @param properties - Object defining the function parameters (will be JSON stringified)
42
- * @param required - Array of required parameter names
43
- * @returns A properly formatted ToolDefinition ready for use with model.chat()
44
- *
45
- * @example
46
- * ```typescript
47
- * const weatherTool = createToolDefinition(
48
- * 'get_weather',
49
- * 'Get weather information for a location',
50
- * {
51
- * location: { type: 'string', description: 'City name' },
52
- * units: { type: 'string', enum: ['celsius', 'fahrenheit'] }
53
- * },
54
- * ['location']
55
- * );
56
- *
57
- * const result = await model.chat(messages, { tools: [weatherTool] });
58
- * ```
59
- */
60
- export function createToolDefinition(name, description, properties, required) {
61
- return {
62
- type: 'function',
63
- function: {
64
- name,
65
- description,
66
- parameters: properties
67
- ? {
68
- type: 'object',
69
- properties: JSON.stringify(properties),
70
- required,
71
- }
72
- : undefined,
73
- },
74
- };
75
- }
76
- /**
77
- * Format a tool response for inclusion in a message
78
- *
79
- * Creates a properly formatted tool response string that can be used
80
- * in tool messages when continuing a conversation after a tool call.
81
- *
82
- * @param content - The response content (will be JSON stringified if object)
83
- * @returns Formatted tool response string wrapped in `<tool_response>` tags
84
- *
85
- * @example
86
- * ```typescript
87
- * // After executing a tool call from model.chat()
88
- * const toolResult = await executeMyTool(call.arguments);
89
- * const responseMessage = {
90
- * role: 'user',
91
- * content: formatToolResponse(toolResult)
92
- * };
93
- * const finalResult = await model.chat([...messages, responseMessage]);
94
- * ```
95
- */
96
- export function formatToolResponse(content) {
97
- const contentStr = typeof content === 'string' ? content : JSON.stringify(content);
98
- return `<tool_response>
99
- ${contentStr}
100
- </tool_response>`;
101
- }