@mlx-node/core 0.0.7 → 0.0.8
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/index.cjs +85 -69
- package/index.d.cts +1321 -724
- package/package.json +6 -5
package/index.d.cts
CHANGED
|
@@ -119,81 +119,125 @@ export declare class DocUnwarpModel {
|
|
|
119
119
|
* commands via channels and await responses.
|
|
120
120
|
*/
|
|
121
121
|
export declare class Gemma4Model {
|
|
122
|
+
/**
|
|
123
|
+
* Create an uninitialized `Gemma4Model` stub from a config.
|
|
124
|
+
*
|
|
125
|
+
* **Prefer [`Gemma4Model::load`]** for any real usage — `new(config)`
|
|
126
|
+
* is a config-only stub that matches the OCR-model pattern
|
|
127
|
+
* (`VLModel::new(config)`, `QianfanOCRModel::new(config)`) and is
|
|
128
|
+
* intentionally NOT runnable. It was introduced in the cache-limit
|
|
129
|
+
* coordinator work so that the coordinator's per-model delta is
|
|
130
|
+
* registered exclusively on the `load()` path, eliminating a
|
|
131
|
+
* baseline-registration gap where a no-op `new(config)` would have
|
|
132
|
+
* leaked an empty guard into the coordinator.
|
|
133
|
+
*
|
|
134
|
+
* This path does NOT spawn a model thread, NOT materialize any
|
|
135
|
+
* weights, and NOT register with the cache-limit coordinator. The
|
|
136
|
+
* returned instance is only useful for config inspection — every
|
|
137
|
+
* session method (`chatSessionStart` / `chatSessionContinue` /
|
|
138
|
+
* `chatSessionContinueTool` and their streaming variants) rejects
|
|
139
|
+
* with a `napi::Error` whose message is exactly
|
|
140
|
+
* `"Model not initialized. Call Gemma4Model.load() first."` until
|
|
141
|
+
* `load()` runs and installs the underlying model thread. The
|
|
142
|
+
* synchronous `resetCaches()` call is a silent no-op on the stub
|
|
143
|
+
* to keep `ChatSession.reset()` idempotent across both runnable
|
|
144
|
+
* and stub instances.
|
|
145
|
+
*
|
|
146
|
+
* A runnable model requires `await Gemma4Model.load(path)`. The
|
|
147
|
+
* constructor signature is fixed by NAPI-RS; the stub-only behavior is
|
|
148
|
+
* covered by the regression tests in
|
|
149
|
+
* `__test__/models/model-loader-gemma4.test.ts`.
|
|
150
|
+
*/
|
|
122
151
|
constructor(config: Gemma4Config);
|
|
152
|
+
/** Returns true if weights have been loaded via `load()`. */
|
|
153
|
+
get isInitialized(): boolean;
|
|
154
|
+
/**
|
|
155
|
+
* Whether the block-paged KV cache adapter is active on this model
|
|
156
|
+
* instance.
|
|
157
|
+
*
|
|
158
|
+
* `true` iff `Gemma4Inner::paged_adapter` was successfully
|
|
159
|
+
* constructed at load time (driven by
|
|
160
|
+
* `Gemma4Config::use_block_paged_cache`). The
|
|
161
|
+
* `gemma4_paged_vs_flat_parity` integration test pins greedy
|
|
162
|
+
* byte-equal at BF16 against real Gemma-4-E2B-IT weights. Stubs
|
|
163
|
+
* constructed via `new(config)` always return `false`. Surfaced
|
|
164
|
+
* through this NAPI method so server endpoints can branch on it
|
|
165
|
+
* without a model-thread roundtrip.
|
|
166
|
+
*/
|
|
167
|
+
hasBlockPagedCache(): boolean;
|
|
168
|
+
/**
|
|
169
|
+
* Whether this loaded instance can execute image-bearing chat turns.
|
|
170
|
+
* Config-only stubs and incomplete/non-paged physical paths return false.
|
|
171
|
+
*/
|
|
172
|
+
supportsImages(): boolean;
|
|
123
173
|
modelId(): number;
|
|
124
|
-
/** Load a Gemma4 model from a directory. */
|
|
125
|
-
static load(modelPath: string): Promise<Gemma4Model>;
|
|
126
174
|
/**
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
175
|
+
* Whether a draft model — DSpark or Google assistant — is loaded on
|
|
176
|
+
* this instance (via `Gemma4LoadOptions::draft_model_path`), enabling
|
|
177
|
+
* the speculative-decode whole-turn path.
|
|
130
178
|
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
* `
|
|
137
|
-
|
|
179
|
+
* Note: this only reports draft availability. Whether speculative
|
|
180
|
+
* decoding actually runs on a given call also requires the per-request
|
|
181
|
+
* `enableMtp` flag. Named `hasMtpWeights` for parity with the Qwen3.5
|
|
182
|
+
* surface, but it reports an external draft model (either variant),
|
|
183
|
+
* not in-checkpoint MTP heads. Stubs from `new(config)` always return
|
|
184
|
+
* `false`.
|
|
185
|
+
*/
|
|
186
|
+
hasMtpWeights(): boolean;
|
|
187
|
+
/** Load a Gemma4 model from a directory. */
|
|
188
|
+
static load(modelPath: string, options?: Gemma4LoadOptions | undefined | null): Promise<Gemma4Model>;
|
|
189
|
+
/**
|
|
190
|
+
* Reset all caches and clear cached token history. Exposed
|
|
191
|
+
* so tests and session-management code can start from a
|
|
192
|
+
* known clean state between turns.
|
|
138
193
|
*/
|
|
139
194
|
resetCaches(): void;
|
|
140
195
|
/**
|
|
141
196
|
* Start a new chat session.
|
|
142
197
|
*
|
|
143
|
-
* Runs the full jinja chat template once, decodes until
|
|
144
|
-
*
|
|
145
|
-
* boundary so subsequent `chatSessionContinue` /
|
|
146
|
-
* `chatSessionContinueTool` calls can append a raw delta on
|
|
147
|
-
* without re-rendering the chat template.
|
|
198
|
+
* Runs the full jinja chat template once, decodes until the
|
|
199
|
+
* family's session stop token, and leaves the KV caches on a
|
|
200
|
+
* clean turn boundary so subsequent `chatSessionContinue` /
|
|
201
|
+
* `chatSessionContinueTool` calls can append a raw delta on
|
|
202
|
+
* top without re-rendering the chat template.
|
|
148
203
|
*/
|
|
149
204
|
chatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
150
205
|
/**
|
|
151
206
|
* Continue an existing chat session with a new user message.
|
|
152
207
|
*
|
|
153
|
-
* Appends a raw
|
|
154
|
-
* state, then decodes the
|
|
155
|
-
*
|
|
208
|
+
* Appends a raw user/assistant delta to the session's cached
|
|
209
|
+
* KV state, then decodes the assistant reply, stopping on the
|
|
210
|
+
* family's session boundary token.
|
|
156
211
|
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
* `config.reuse_cache` is explicitly set to `false`.
|
|
160
|
-
*
|
|
161
|
-
* `images` is an opt-in guard parameter: when non-empty the native
|
|
162
|
-
* side returns an error whose message begins with
|
|
212
|
+
* `images` is an opt-in guard parameter: when non-empty the
|
|
213
|
+
* native side returns an error whose message begins with
|
|
163
214
|
* `IMAGE_CHANGE_REQUIRES_SESSION_RESTART:` so the TypeScript
|
|
164
|
-
* `ChatSession` layer can
|
|
165
|
-
*
|
|
166
|
-
* model backends.
|
|
215
|
+
* `ChatSession` layer can route image-changes back through a
|
|
216
|
+
* fresh `chatSessionStart`.
|
|
167
217
|
*/
|
|
168
218
|
chatSessionContinue(
|
|
169
219
|
userMessage: string,
|
|
170
220
|
images: Uint8Array[] | null | undefined,
|
|
221
|
+
audio: Uint8Array[] | null | undefined,
|
|
171
222
|
config: ChatConfig | null | undefined,
|
|
172
223
|
): Promise<ChatResult>;
|
|
173
224
|
/**
|
|
174
225
|
* Continue an existing chat session with a tool-result turn.
|
|
175
226
|
*
|
|
176
|
-
* Builds
|
|
177
|
-
*
|
|
178
|
-
|
|
179
|
-
{content}<turn|>
|
|
180
|
-
<|turn>model
|
|
181
|
-
`) from
|
|
182
|
-
* `content` and prefills it on top of the live session caches,
|
|
183
|
-
* then decodes the model reply. Stops on `<turn|>` so the cache
|
|
184
|
-
* stays on a clean turn boundary for the next turn.
|
|
185
|
-
*
|
|
186
|
-
* The `tool_call_id` is currently dropped by the wire format —
|
|
187
|
-
* Gemma4's chat template identifies tool responses positionally,
|
|
188
|
-
* not via an explicit id. Callers may still log it for their own
|
|
189
|
-
* bookkeeping.
|
|
227
|
+
* Builds the family's tool-result delta from `content` and
|
|
228
|
+
* prefills it on top of the live session caches, then decodes
|
|
229
|
+
* the assistant reply.
|
|
190
230
|
*
|
|
191
|
-
*
|
|
231
|
+
* `is_error` is the structured tool-error signal. When
|
|
232
|
+
* `Some(true)`, the renderer prepends the shared
|
|
233
|
+
* [`crate::tokenizer::TOOL_ERROR_MARKER`] inside the
|
|
234
|
+
* rendered tool block.
|
|
192
235
|
*/
|
|
193
236
|
chatSessionContinueTool(
|
|
194
237
|
toolCallId: string,
|
|
195
238
|
content: string,
|
|
196
239
|
config?: ChatConfig | undefined | null,
|
|
240
|
+
isError?: boolean | undefined | null,
|
|
197
241
|
): Promise<ChatResult>;
|
|
198
242
|
/** Streaming variant of `chatSessionStart`. */
|
|
199
243
|
chatStreamSessionStart(
|
|
@@ -205,15 +249,24 @@ export declare class Gemma4Model {
|
|
|
205
249
|
chatStreamSessionContinue(
|
|
206
250
|
userMessage: string,
|
|
207
251
|
images: Uint8Array[] | null | undefined,
|
|
252
|
+
audio: Uint8Array[] | null | undefined,
|
|
208
253
|
config: ChatConfig | null | undefined,
|
|
209
254
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
210
255
|
): Promise<ChatStreamHandle>;
|
|
211
|
-
/**
|
|
256
|
+
/**
|
|
257
|
+
* Streaming variant of `chatSessionContinueTool`.
|
|
258
|
+
*
|
|
259
|
+
* `is_error` mirrors the non-streaming entry point — when
|
|
260
|
+
* `Some(true)`, the renderer prepends the shared
|
|
261
|
+
* [`crate::tokenizer::TOOL_ERROR_MARKER`] inside the rendered
|
|
262
|
+
* tool block.
|
|
263
|
+
*/
|
|
212
264
|
chatStreamSessionContinueTool(
|
|
213
265
|
toolCallId: string,
|
|
214
266
|
content: string,
|
|
215
267
|
config: ChatConfig | null | undefined,
|
|
216
268
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
269
|
+
isError?: boolean | null | undefined,
|
|
217
270
|
): Promise<ChatStreamHandle>;
|
|
218
271
|
}
|
|
219
272
|
|
|
@@ -471,68 +524,78 @@ export declare class Lfm2Model {
|
|
|
471
524
|
/** Load an LFM2 model from a directory containing safetensors and config.json. */
|
|
472
525
|
static load(modelPath: string): Promise<Lfm2Model>;
|
|
473
526
|
/**
|
|
474
|
-
*
|
|
475
|
-
*
|
|
476
|
-
*
|
|
527
|
+
* Whether the block-paged KV cache adapter is active on this model
|
|
528
|
+
* instance.
|
|
529
|
+
*
|
|
530
|
+
* `true` iff `Lfm2Inner::paged_adapter` was successfully constructed
|
|
531
|
+
* at load time (driven by `Lfm2Config::use_block_paged_cache`,
|
|
532
|
+
* defaulting to `true` after paged-vs-flat parity verification).
|
|
533
|
+
* LFM2 is hybrid (10 conv + 6 full-attention layers); only the
|
|
534
|
+
* full-attention layers route through the adapter, conv layers stay
|
|
535
|
+
* on flat `Lfm2LayerCache::Conv` regardless. When `true`, the native
|
|
536
|
+
* cache reuses SYS blocks across `chatSessionStart` calls via
|
|
537
|
+
* content-addressing, so the JS-side warm slot in
|
|
538
|
+
* `SessionRegistry.getOrCreateWarmAny` is redundant and the
|
|
539
|
+
* `/v1/messages` server endpoint allocates a fresh `ChatSession` per
|
|
540
|
+
* request.
|
|
541
|
+
*/
|
|
542
|
+
hasBlockPagedCache(): boolean;
|
|
543
|
+
/** Get the model configuration. */
|
|
544
|
+
getConfig(): Lfm2Config;
|
|
545
|
+
/** Estimated number of model parameters. */
|
|
546
|
+
numParameters(): number;
|
|
547
|
+
/**
|
|
548
|
+
* Reset all caches and clear cached token history. Exposed
|
|
549
|
+
* so tests and session-management code can start from a
|
|
550
|
+
* known clean state between turns.
|
|
477
551
|
*/
|
|
478
552
|
resetCaches(): void;
|
|
479
553
|
/**
|
|
480
554
|
* Start a new chat session.
|
|
481
555
|
*
|
|
482
|
-
* Runs the full jinja chat template once, decodes until
|
|
483
|
-
*
|
|
484
|
-
* boundary so subsequent `chatSessionContinue` /
|
|
485
|
-
* `chatSessionContinueTool` calls can append a raw delta on
|
|
486
|
-
* without re-rendering the chat template.
|
|
487
|
-
*
|
|
488
|
-
* Requires `config.reuse_cache` to be enabled (the default).
|
|
556
|
+
* Runs the full jinja chat template once, decodes until the
|
|
557
|
+
* family's session stop token, and leaves the KV caches on a
|
|
558
|
+
* clean turn boundary so subsequent `chatSessionContinue` /
|
|
559
|
+
* `chatSessionContinueTool` calls can append a raw delta on
|
|
560
|
+
* top without re-rendering the chat template.
|
|
489
561
|
*/
|
|
490
562
|
chatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
491
563
|
/**
|
|
492
564
|
* Continue an existing chat session with a new user message.
|
|
493
565
|
*
|
|
494
|
-
* Appends a raw
|
|
495
|
-
*
|
|
496
|
-
*
|
|
497
|
-
* the next turn.
|
|
498
|
-
*
|
|
499
|
-
* Requires a live session started via `chatSessionStart`. Errors
|
|
500
|
-
* if the session is empty, carries image state, or if
|
|
501
|
-
* `config.reuse_cache` is explicitly set to `false`.
|
|
566
|
+
* Appends a raw user/assistant delta to the session's cached
|
|
567
|
+
* KV state, then decodes the assistant reply, stopping on the
|
|
568
|
+
* family's session boundary token.
|
|
502
569
|
*
|
|
503
|
-
*
|
|
504
|
-
*
|
|
505
|
-
*
|
|
506
|
-
* `ChatSession` layer can
|
|
507
|
-
*
|
|
508
|
-
* uniformly across all model backends.
|
|
570
|
+
* `images` is an opt-in guard parameter: when non-empty the
|
|
571
|
+
* native side returns an error whose message begins with
|
|
572
|
+
* `IMAGE_CHANGE_REQUIRES_SESSION_RESTART:` so the TypeScript
|
|
573
|
+
* `ChatSession` layer can route image-changes back through a
|
|
574
|
+
* fresh `chatSessionStart`.
|
|
509
575
|
*/
|
|
510
576
|
chatSessionContinue(
|
|
511
577
|
userMessage: string,
|
|
512
578
|
images: Uint8Array[] | null | undefined,
|
|
579
|
+
audio: Uint8Array[] | null | undefined,
|
|
513
580
|
config: ChatConfig | null | undefined,
|
|
514
581
|
): Promise<ChatResult>;
|
|
515
582
|
/**
|
|
516
583
|
* Continue an existing chat session with a tool-result turn.
|
|
517
584
|
*
|
|
518
|
-
* Builds
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
* not via an explicit id. Callers may still log it for their own
|
|
528
|
-
* bookkeeping.
|
|
529
|
-
*
|
|
530
|
-
* Requires a live session started via `chatSessionStart`.
|
|
531
|
-
*/
|
|
585
|
+
* Builds the family's tool-result delta from `content` and
|
|
586
|
+
* prefills it on top of the live session caches, then decodes
|
|
587
|
+
* the assistant reply.
|
|
588
|
+
*
|
|
589
|
+
* `is_error` is the structured tool-error signal. When
|
|
590
|
+
* `Some(true)`, the renderer prepends the shared
|
|
591
|
+
* [`crate::tokenizer::TOOL_ERROR_MARKER`] inside the
|
|
592
|
+
* rendered tool block.
|
|
593
|
+
*/
|
|
532
594
|
chatSessionContinueTool(
|
|
533
595
|
toolCallId: string,
|
|
534
596
|
content: string,
|
|
535
597
|
config?: ChatConfig | undefined | null,
|
|
598
|
+
isError?: boolean | undefined | null,
|
|
536
599
|
): Promise<ChatResult>;
|
|
537
600
|
/** Streaming variant of `chatSessionStart`. */
|
|
538
601
|
chatStreamSessionStart(
|
|
@@ -544,20 +607,25 @@ export declare class Lfm2Model {
|
|
|
544
607
|
chatStreamSessionContinue(
|
|
545
608
|
userMessage: string,
|
|
546
609
|
images: Uint8Array[] | null | undefined,
|
|
610
|
+
audio: Uint8Array[] | null | undefined,
|
|
547
611
|
config: ChatConfig | null,
|
|
548
612
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
549
613
|
): Promise<ChatStreamHandle>;
|
|
550
|
-
/**
|
|
614
|
+
/**
|
|
615
|
+
* Streaming variant of `chatSessionContinueTool`.
|
|
616
|
+
*
|
|
617
|
+
* `is_error` mirrors the non-streaming entry point — when
|
|
618
|
+
* `Some(true)`, the renderer prepends the shared
|
|
619
|
+
* [`crate::tokenizer::TOOL_ERROR_MARKER`] inside the rendered
|
|
620
|
+
* tool block.
|
|
621
|
+
*/
|
|
551
622
|
chatStreamSessionContinueTool(
|
|
552
623
|
toolCallId: string,
|
|
553
624
|
content: string,
|
|
554
625
|
config: ChatConfig | null,
|
|
555
626
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
627
|
+
isError?: boolean | null | undefined,
|
|
556
628
|
): Promise<ChatStreamHandle>;
|
|
557
|
-
/** Get the model configuration. */
|
|
558
|
-
getConfig(): Lfm2Config;
|
|
559
|
-
/** Estimated number of model parameters. */
|
|
560
|
-
numParameters(): number;
|
|
561
629
|
}
|
|
562
630
|
|
|
563
631
|
export declare class MxArray {
|
|
@@ -681,9 +749,20 @@ export declare class MxArray {
|
|
|
681
749
|
divScalar(value: number): MxArray;
|
|
682
750
|
matmul(other: MxArray): MxArray;
|
|
683
751
|
/**
|
|
684
|
-
*
|
|
685
|
-
*
|
|
686
|
-
*
|
|
752
|
+
* Matrix multiply-add: D = beta * C + alpha * (self @ B), where self is A.
|
|
753
|
+
* Default: alpha=1.0, beta=1.0, giving D = C + (self @ B).
|
|
754
|
+
*
|
|
755
|
+
* Computed explicitly (matmul, optional alpha scale, then add beta*C)
|
|
756
|
+
* rather than via the fused `mlx::core::addmm` primitive. The fused
|
|
757
|
+
* primitive is correct on a well-formed metallib, but this project's local
|
|
758
|
+
* release build is known to non-deterministically miscompile fused GEMM
|
|
759
|
+
* kernels (see the metallib-corruption notes), which manifested as the
|
|
760
|
+
* fused addmm dropping `beta*C` and corrupting every biased linear — most
|
|
761
|
+
* visibly the vision tower (`qkv`, `proj`, `fc1`, `fc2`, merger all carry a
|
|
762
|
+
* bias; bias-free LM/MoE linears pass a zero `C` and were unaffected). The
|
|
763
|
+
* explicit form keeps the `C` term robust to that build hazard; the
|
|
764
|
+
* `nn::linear` unit tests assert it applies a non-zero `C`, so they double
|
|
765
|
+
* as a canary if a future build corrupts the matmul kernel too.
|
|
687
766
|
*/
|
|
688
767
|
addmm(c: MxArray, b: MxArray, alpha?: number | undefined | null, beta?: number | undefined | null): MxArray;
|
|
689
768
|
abs(): MxArray;
|
|
@@ -941,23 +1020,43 @@ export declare class OutputStore {
|
|
|
941
1020
|
}
|
|
942
1021
|
|
|
943
1022
|
/**
|
|
944
|
-
*
|
|
1023
|
+
* NAPI-exported view of [`PrivacyFilterModel`].
|
|
945
1024
|
*
|
|
946
|
-
*
|
|
947
|
-
*
|
|
948
|
-
* since the last turn are processed, avoiding redundant computation.
|
|
949
|
-
*
|
|
950
|
-
* Created internally by the model during chat-session turns.
|
|
951
|
-
* Extract via `model.takeCache()`, restore via `model.setCache(cache)`.
|
|
1025
|
+
* Construct via [`PrivacyFilterModelJs::load`] and run end-to-end
|
|
1026
|
+
* classification via [`PrivacyFilterModelJs::classify`].
|
|
952
1027
|
*/
|
|
953
|
-
export declare class
|
|
954
|
-
/**
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
1028
|
+
export declare class PrivacyFilterModel {
|
|
1029
|
+
/**
|
|
1030
|
+
* Load a privacy-filter checkpoint from a directory.
|
|
1031
|
+
*
|
|
1032
|
+
* The directory must contain `config.json`, `model.safetensors`,
|
|
1033
|
+
* `tokenizer.json`, and optionally `viterbi_calibration.json` and
|
|
1034
|
+
* `tokenizer_config.json`. Synchronous to match the loader pattern
|
|
1035
|
+
* used by every other model in this crate (e.g. `TextDetModel`).
|
|
1036
|
+
*/
|
|
1037
|
+
static load(modelPath: string): PrivacyFilterModel;
|
|
1038
|
+
/**
|
|
1039
|
+
* Classify `text` and return detected PII entities (and optionally
|
|
1040
|
+
* per-token tags).
|
|
1041
|
+
*
|
|
1042
|
+
* Pipeline:
|
|
1043
|
+
* 1. Tokenize the text with byte offsets, no special tokens.
|
|
1044
|
+
* 2. Run the forward pass to get `[1, T, 33]` logits.
|
|
1045
|
+
* 3. Compute softmax (for per-tag confidences) and log-softmax (for
|
|
1046
|
+
* Viterbi emissions) over the class axis.
|
|
1047
|
+
* 4. Build the transition matrix from the default calibration
|
|
1048
|
+
* merged with any per-call overrides.
|
|
1049
|
+
* 5. Viterbi-decode using log-softmax emissions to get the BIOES
|
|
1050
|
+
* tag sequence.
|
|
1051
|
+
* 6. For each token, take the softmax probability of the
|
|
1052
|
+
* Viterbi-emitted tag (so per-token `tag` and `score` share
|
|
1053
|
+
* decoders), then walk the tags + offsets + those probabilities
|
|
1054
|
+
* to extract coherent spans whose mean probability clears
|
|
1055
|
+
* `threshold`.
|
|
1056
|
+
*/
|
|
1057
|
+
classify(text: string, opts?: PrivacyClassifyOptions | undefined | null): PrivacyClassifyResult;
|
|
960
1058
|
}
|
|
1059
|
+
export type PrivacyFilterModelJs = PrivacyFilterModel;
|
|
961
1060
|
|
|
962
1061
|
/**
|
|
963
1062
|
* Qianfan-OCR Vision-Language Model (InternVL architecture).
|
|
@@ -973,8 +1072,13 @@ export declare class QianfanOCRModel {
|
|
|
973
1072
|
* Create a new QianfanOCRModel from config (uninitialized, no weights).
|
|
974
1073
|
*
|
|
975
1074
|
* This constructor path does not spawn a model thread — the returned
|
|
976
|
-
* instance is only useful for
|
|
977
|
-
* [`QianfanOCRModel::load`] to actually run inference.
|
|
1075
|
+
* instance is only useful for `is_initialized` queries until
|
|
1076
|
+
* [`QianfanOCRModel::load`] is called to actually run inference. The
|
|
1077
|
+
* `config` argument is accepted to preserve the `new
|
|
1078
|
+
* QianfanOCRModel(config)` JS surface; the value is discarded because
|
|
1079
|
+
* nothing on the uninitialized path consults it (any future config
|
|
1080
|
+
* getter would forward to the inner thread state populated by
|
|
1081
|
+
* `load()`).
|
|
978
1082
|
*/
|
|
979
1083
|
constructor(config: QianfanOcrConfig);
|
|
980
1084
|
/** Returns true if weights have been loaded via `load()`. */
|
|
@@ -1034,10 +1138,19 @@ export declare class QianfanOCRModel {
|
|
|
1034
1138
|
* model backends. Qianfan-OCR is a VLM but the continue path cannot
|
|
1035
1139
|
* splice new vision features into a live KV cache — image changes
|
|
1036
1140
|
* always require a fresh session start.
|
|
1141
|
+
*
|
|
1142
|
+
* `audio` exists only to keep this method's positional ABI aligned
|
|
1143
|
+
* with the shared chat surface every other family exposes (the
|
|
1144
|
+
* `chat_napi_surface!` macro inserts `audio` between `images` and
|
|
1145
|
+
* `config`). Qianfan-OCR has no audio support, so a non-empty
|
|
1146
|
+
* `audio` is rejected at the boundary with the shared no-audio
|
|
1147
|
+
* error; `None` / empty is a complete no-op and audio is never
|
|
1148
|
+
* threaded into the model thread.
|
|
1037
1149
|
*/
|
|
1038
1150
|
chatSessionContinue(
|
|
1039
1151
|
userMessage: string,
|
|
1040
1152
|
images: Uint8Array[] | null | undefined,
|
|
1153
|
+
audio: Uint8Array[] | null | undefined,
|
|
1041
1154
|
config: ChatConfig | null | undefined,
|
|
1042
1155
|
): Promise<ChatResult>;
|
|
1043
1156
|
/**
|
|
@@ -1048,12 +1161,20 @@ export declare class QianfanOCRModel {
|
|
|
1048
1161
|
* decodes the model reply. Stops on `<|im_end|>` so the cache stays
|
|
1049
1162
|
* on a clean turn boundary for the next turn.
|
|
1050
1163
|
*
|
|
1164
|
+
* `is_error` is the structured tool-error signal. When `Some(true)`,
|
|
1165
|
+
* the renderer prepends the shared
|
|
1166
|
+
* [`crate::tokenizer::TOOL_ERROR_MARKER`] inside the
|
|
1167
|
+
* `<tool_response>` wrapper so the model receives a clear text-level
|
|
1168
|
+
* cue. `None` / `Some(false)` keep the wire bytes byte-equal to the
|
|
1169
|
+
* pre-feature output.
|
|
1170
|
+
*
|
|
1051
1171
|
* Requires a live session started via `chatSessionStart`.
|
|
1052
1172
|
*/
|
|
1053
1173
|
chatSessionContinueTool(
|
|
1054
1174
|
toolCallId: string,
|
|
1055
1175
|
content: string,
|
|
1056
1176
|
config?: ChatConfig | undefined | null,
|
|
1177
|
+
isError?: boolean | undefined | null,
|
|
1057
1178
|
): Promise<ChatResult>;
|
|
1058
1179
|
/** Streaming variant of `chatSessionStart`. */
|
|
1059
1180
|
chatStreamSessionStart(
|
|
@@ -1061,19 +1182,35 @@ export declare class QianfanOCRModel {
|
|
|
1061
1182
|
config: ChatConfig | null | undefined,
|
|
1062
1183
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1063
1184
|
): Promise<ChatStreamHandle>;
|
|
1064
|
-
/**
|
|
1185
|
+
/**
|
|
1186
|
+
* Streaming variant of `chatSessionContinue`.
|
|
1187
|
+
*
|
|
1188
|
+
* `audio` mirrors the non-streaming entry point: it exists only to
|
|
1189
|
+
* keep the positional ABI aligned with the shared chat surface, and
|
|
1190
|
+
* a non-empty value is rejected at the boundary with the shared
|
|
1191
|
+
* no-audio error. `None` / empty is a complete no-op.
|
|
1192
|
+
*/
|
|
1065
1193
|
chatStreamSessionContinue(
|
|
1066
1194
|
userMessage: string,
|
|
1067
1195
|
images: Uint8Array[] | null | undefined,
|
|
1196
|
+
audio: Uint8Array[] | null | undefined,
|
|
1068
1197
|
config: ChatConfig | null | undefined,
|
|
1069
1198
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1070
1199
|
): Promise<ChatStreamHandle>;
|
|
1071
|
-
/**
|
|
1200
|
+
/**
|
|
1201
|
+
* Streaming variant of `chatSessionContinueTool`.
|
|
1202
|
+
*
|
|
1203
|
+
* `is_error` mirrors the non-streaming entry point — when
|
|
1204
|
+
* `Some(true)`, the renderer prepends the shared
|
|
1205
|
+
* [`crate::tokenizer::TOOL_ERROR_MARKER`] inside the
|
|
1206
|
+
* `<tool_response>` wrapper.
|
|
1207
|
+
*/
|
|
1072
1208
|
chatStreamSessionContinueTool(
|
|
1073
1209
|
toolCallId: string,
|
|
1074
1210
|
content: string,
|
|
1075
1211
|
config: ChatConfig | null | undefined,
|
|
1076
1212
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1213
|
+
isError?: boolean | null | undefined,
|
|
1077
1214
|
): Promise<ChatStreamHandle>;
|
|
1078
1215
|
}
|
|
1079
1216
|
|
|
@@ -1085,27 +1222,55 @@ export declare class QianfanOCRModel {
|
|
|
1085
1222
|
* routed through `TrainingDispatch` to the model thread.
|
|
1086
1223
|
*/
|
|
1087
1224
|
export declare class Qwen35Model {
|
|
1088
|
-
/** Initialize caches for incremental generation. */
|
|
1089
|
-
initCaches(): void;
|
|
1090
|
-
/** Reset all caches. */
|
|
1091
|
-
resetCaches(): void;
|
|
1092
1225
|
/**
|
|
1093
|
-
*
|
|
1226
|
+
* Whether the block-paged KV cache adapter is active on this model
|
|
1227
|
+
* instance.
|
|
1228
|
+
*
|
|
1229
|
+
* `true` iff `Qwen35Inner::paged_adapter` was successfully
|
|
1230
|
+
* constructed at load time (driven by
|
|
1231
|
+
* `Qwen3_5Config::use_block_paged_cache`, default-OFF for text-only
|
|
1232
|
+
* checkpoints because parity is pending real-weights validation, and
|
|
1233
|
+
* default-ON for VLM checkpoints). On VLM checkpoints dense image turns
|
|
1234
|
+
* ONLY run on the paged-vision core; a vision turn that reaches a None
|
|
1235
|
+
* adapter errors at dispatch. Surfaced through this NAPI method so
|
|
1236
|
+
* server endpoints can branch on it without round-tripping through
|
|
1237
|
+
* the model thread.
|
|
1238
|
+
*/
|
|
1239
|
+
hasBlockPagedCache(): boolean;
|
|
1240
|
+
/**
|
|
1241
|
+
* Whether this checkpoint shipped an MTP head (module loaded by
|
|
1242
|
+
* `persistence::apply_weights_inner`). Snapshotted at load time from
|
|
1243
|
+
* `Qwen35Inner::has_mtp_weights()` so the TS `ChatSession` can
|
|
1244
|
+
* auto-default `enableMtp = true` for MTP-capable checkpoints without
|
|
1245
|
+
* dispatching a command into the model thread.
|
|
1246
|
+
*
|
|
1247
|
+
* Note: this only reports weight availability. Whether the
|
|
1248
|
+
* speculative-decode path actually runs on a given call also requires the
|
|
1249
|
+
* per-request `enableMtp` flag.
|
|
1250
|
+
*/
|
|
1251
|
+
hasMtpWeights(): boolean;
|
|
1252
|
+
/**
|
|
1253
|
+
* Whether this loaded model instance can execute image-bearing turns.
|
|
1094
1254
|
*
|
|
1095
|
-
*
|
|
1096
|
-
*
|
|
1097
|
-
*
|
|
1098
|
-
|
|
1255
|
+
* This is an authoritative load-time snapshot, not a `config.json`
|
|
1256
|
+
* family guess: it requires a loaded vision encoder, image processor,
|
|
1257
|
+
* and the block-paged KV adapter used by the dense vision path.
|
|
1258
|
+
*/
|
|
1259
|
+
supportsImages(): boolean;
|
|
1260
|
+
/**
|
|
1261
|
+
* Synchronous snapshot used by higher layers to preflight rendered
|
|
1262
|
+
* prompts and clamp output before native cache allocation.
|
|
1099
1263
|
*/
|
|
1100
|
-
|
|
1264
|
+
contextLimits(): Qwen35ContextLimits;
|
|
1101
1265
|
/**
|
|
1102
|
-
*
|
|
1266
|
+
* Compute the exact prompt length after Qwen image-placeholder expansion
|
|
1267
|
+
* without running the vision encoder or touching inference caches.
|
|
1103
1268
|
*
|
|
1104
|
-
*
|
|
1105
|
-
*
|
|
1106
|
-
*
|
|
1269
|
+
* `prompt_tokens` is the already-rendered chat-template output. `messages`
|
|
1270
|
+
* supplies the complete image history so both fresh and leased-session
|
|
1271
|
+
* preflights account for every image in template order.
|
|
1107
1272
|
*/
|
|
1108
|
-
|
|
1273
|
+
expandedPromptTokenCount(promptTokens: Uint32Array, messages: Array<ChatMessage>): Promise<number>;
|
|
1109
1274
|
/**
|
|
1110
1275
|
* Load a pretrained model from a directory.
|
|
1111
1276
|
*
|
|
@@ -1117,131 +1282,100 @@ export declare class Qwen35Model {
|
|
|
1117
1282
|
static load(path: string): Promise<Qwen35Model>;
|
|
1118
1283
|
/** Generate text from a prompt token sequence. */
|
|
1119
1284
|
generate(promptTokens: MxArray, config: Qwen35GenerationConfig): Promise<Qwen35GenerationResult>;
|
|
1285
|
+
/**
|
|
1286
|
+
* Get the number of parameters in the model.
|
|
1287
|
+
*
|
|
1288
|
+
* Pure config computation — no model-thread dispatch needed.
|
|
1289
|
+
*/
|
|
1290
|
+
numParameters(): number;
|
|
1291
|
+
/**
|
|
1292
|
+
* Save the model weights and configuration to a directory.
|
|
1293
|
+
*
|
|
1294
|
+
* Dispatches to model thread.
|
|
1295
|
+
*/
|
|
1296
|
+
saveModel(savePath: string): Promise<undefined>;
|
|
1297
|
+
/**
|
|
1298
|
+
* Reset all caches and clear cached token history. Exposed
|
|
1299
|
+
* so tests and session-management code can start from a
|
|
1300
|
+
* known clean state between turns.
|
|
1301
|
+
*/
|
|
1302
|
+
resetCaches(): void;
|
|
1120
1303
|
/**
|
|
1121
1304
|
* Start a new chat session.
|
|
1122
1305
|
*
|
|
1123
|
-
* Runs the full jinja chat template once
|
|
1124
|
-
*
|
|
1125
|
-
*
|
|
1126
|
-
*
|
|
1127
|
-
*
|
|
1128
|
-
* prefill), while a plain text Qwen3.5 checkpoint rejects them
|
|
1129
|
-
* with a runtime error. Subsequent turns in the same session MUST
|
|
1130
|
-
* go through `chatSessionContinue` so the caller appends raw
|
|
1131
|
-
* ChatML deltas on top of the live caches without rerunning the
|
|
1132
|
-
* jinja template; a mid-session image change requires a fresh
|
|
1133
|
-
* `chatSessionStart` call. The session is owned end-to-end by
|
|
1134
|
-
* the `chatSession*` surface.
|
|
1135
|
-
*
|
|
1136
|
-
* This method is the production entry point used by the TypeScript
|
|
1137
|
-
* `ChatSession` wrapper for turn 1 of a multi-round conversation.
|
|
1306
|
+
* Runs the full jinja chat template once, decodes until the
|
|
1307
|
+
* family's session stop token, and leaves the KV caches on a
|
|
1308
|
+
* clean turn boundary so subsequent `chatSessionContinue` /
|
|
1309
|
+
* `chatSessionContinueTool` calls can append a raw delta on
|
|
1310
|
+
* top without re-rendering the chat template.
|
|
1138
1311
|
*/
|
|
1139
1312
|
chatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
1140
1313
|
/**
|
|
1141
1314
|
* Continue an existing chat session with a new user message.
|
|
1142
1315
|
*
|
|
1143
|
-
* Appends a raw
|
|
1144
|
-
* KV state, then decodes the assistant reply
|
|
1145
|
-
*
|
|
1146
|
-
*
|
|
1147
|
-
* Requires a live session started via `chatSessionStart`. Errors
|
|
1148
|
-
* if the session is empty, carries image state, or if
|
|
1149
|
-
* `config.reuse_cache` is explicitly set to `false`.
|
|
1316
|
+
* Appends a raw user/assistant delta to the session's cached
|
|
1317
|
+
* KV state, then decodes the assistant reply, stopping on the
|
|
1318
|
+
* family's session boundary token.
|
|
1150
1319
|
*
|
|
1151
|
-
* `images` is an opt-in guard parameter: when non-empty
|
|
1152
|
-
* side returns an error whose message begins with
|
|
1320
|
+
* `images` is an opt-in guard parameter: when non-empty the
|
|
1321
|
+
* native side returns an error whose message begins with
|
|
1153
1322
|
* `IMAGE_CHANGE_REQUIRES_SESSION_RESTART:` so the TypeScript
|
|
1154
|
-
* `ChatSession` layer can
|
|
1155
|
-
*
|
|
1323
|
+
* `ChatSession` layer can route image-changes back through a
|
|
1324
|
+
* fresh `chatSessionStart`.
|
|
1156
1325
|
*/
|
|
1157
1326
|
chatSessionContinue(
|
|
1158
1327
|
userMessage: string,
|
|
1159
1328
|
images: Uint8Array[] | null | undefined,
|
|
1329
|
+
audio: Uint8Array[] | null | undefined,
|
|
1160
1330
|
config: ChatConfig | null | undefined,
|
|
1161
1331
|
): Promise<ChatResult>;
|
|
1162
1332
|
/**
|
|
1163
1333
|
* Continue an existing chat session with a tool-result turn.
|
|
1164
1334
|
*
|
|
1165
|
-
* Builds
|
|
1166
|
-
* prefills it on top of the live session caches, then decodes
|
|
1167
|
-
* assistant reply.
|
|
1168
|
-
* clean boundary for the next turn.
|
|
1335
|
+
* Builds the family's tool-result delta from `content` and
|
|
1336
|
+
* prefills it on top of the live session caches, then decodes
|
|
1337
|
+
* the assistant reply.
|
|
1169
1338
|
*
|
|
1170
|
-
*
|
|
1171
|
-
*
|
|
1172
|
-
*
|
|
1173
|
-
*
|
|
1174
|
-
*
|
|
1175
|
-
* Requires a live session started via `chatSessionStart`.
|
|
1339
|
+
* `is_error` is the structured tool-error signal. When
|
|
1340
|
+
* `Some(true)`, the renderer prepends the shared
|
|
1341
|
+
* [`crate::tokenizer::TOOL_ERROR_MARKER`] inside the
|
|
1342
|
+
* rendered tool block.
|
|
1176
1343
|
*/
|
|
1177
1344
|
chatSessionContinueTool(
|
|
1178
1345
|
toolCallId: string,
|
|
1179
1346
|
content: string,
|
|
1180
1347
|
config?: ChatConfig | undefined | null,
|
|
1348
|
+
isError?: boolean | undefined | null,
|
|
1181
1349
|
): Promise<ChatResult>;
|
|
1182
|
-
/**
|
|
1183
|
-
* Streaming variant of `chatSessionStart`.
|
|
1184
|
-
*
|
|
1185
|
-
* Dispatches to the dedicated model thread. Behaviourally identical
|
|
1186
|
-
* to `chatSessionStart` (resets caches, uses `<|im_end|>` as
|
|
1187
|
-
* eos, inherits the same VLM-vs-text image-support contract) but
|
|
1188
|
-
* streams token deltas through the JS callback instead of
|
|
1189
|
-
* returning a `ChatResult`. Used by the TypeScript
|
|
1190
|
-
* `ChatSession.sendStream()` for turn 1 of a multi-round streaming
|
|
1191
|
-
* conversation.
|
|
1192
|
-
*/
|
|
1350
|
+
/** Streaming variant of `chatSessionStart`. */
|
|
1193
1351
|
chatStreamSessionStart(
|
|
1194
1352
|
messages: ChatMessage[],
|
|
1195
1353
|
config: ChatConfig | null,
|
|
1196
1354
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1197
1355
|
): Promise<ChatStreamHandle>;
|
|
1198
|
-
/**
|
|
1199
|
-
* Streaming variant of `chatSessionContinue`.
|
|
1200
|
-
*
|
|
1201
|
-
* Appends a ChatML user/assistant delta on top of the live session
|
|
1202
|
-
* caches and streams the decoded reply. Requires a live session
|
|
1203
|
-
* started via `chatStreamSessionStart` (or the non-streaming
|
|
1204
|
-
* `chatSessionStart`). Used by the TypeScript
|
|
1205
|
-
* `ChatSession.sendStream()` for turns 2..N of a multi-round
|
|
1206
|
-
* streaming conversation.
|
|
1207
|
-
*
|
|
1208
|
-
* `images` is an opt-in guard parameter: when non-empty, the
|
|
1209
|
-
* streaming path emits an error chunk whose message begins with
|
|
1210
|
-
* `IMAGE_CHANGE_REQUIRES_SESSION_RESTART:` so the TypeScript
|
|
1211
|
-
* `ChatSession` layer can route image-changes through a fresh
|
|
1212
|
-
* session start.
|
|
1213
|
-
*/
|
|
1356
|
+
/** Streaming variant of `chatSessionContinue`. */
|
|
1214
1357
|
chatStreamSessionContinue(
|
|
1215
1358
|
userMessage: string,
|
|
1216
1359
|
images: Uint8Array[] | null | undefined,
|
|
1360
|
+
audio: Uint8Array[] | null | undefined,
|
|
1217
1361
|
config: ChatConfig | null,
|
|
1218
1362
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1219
1363
|
): Promise<ChatStreamHandle>;
|
|
1220
1364
|
/**
|
|
1221
1365
|
* Streaming variant of `chatSessionContinueTool`.
|
|
1222
1366
|
*
|
|
1223
|
-
*
|
|
1224
|
-
*
|
|
1225
|
-
*
|
|
1367
|
+
* `is_error` mirrors the non-streaming entry point — when
|
|
1368
|
+
* `Some(true)`, the renderer prepends the shared
|
|
1369
|
+
* [`crate::tokenizer::TOOL_ERROR_MARKER`] inside the rendered
|
|
1370
|
+
* tool block.
|
|
1226
1371
|
*/
|
|
1227
1372
|
chatStreamSessionContinueTool(
|
|
1228
1373
|
toolCallId: string,
|
|
1229
1374
|
content: string,
|
|
1230
1375
|
config: ChatConfig | null,
|
|
1231
1376
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1377
|
+
isError?: boolean | null | undefined,
|
|
1232
1378
|
): Promise<ChatStreamHandle>;
|
|
1233
|
-
/**
|
|
1234
|
-
* Get the number of parameters in the model.
|
|
1235
|
-
*
|
|
1236
|
-
* Pure config computation — no model-thread dispatch needed.
|
|
1237
|
-
*/
|
|
1238
|
-
numParameters(): number;
|
|
1239
|
-
/**
|
|
1240
|
-
* Save the model weights and configuration to a directory.
|
|
1241
|
-
*
|
|
1242
|
-
* Dispatches to model thread.
|
|
1243
|
-
*/
|
|
1244
|
-
saveModel(savePath: string): Promise<undefined>;
|
|
1245
1379
|
}
|
|
1246
1380
|
export type Qwen3_5Model = Qwen35Model;
|
|
1247
1381
|
|
|
@@ -1253,142 +1387,147 @@ export type Qwen3_5Model = Qwen35Model;
|
|
|
1253
1387
|
* routed through `TrainingDispatch` to the model thread.
|
|
1254
1388
|
*/
|
|
1255
1389
|
export declare class Qwen35MoeModel {
|
|
1256
|
-
/**
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1390
|
+
/**
|
|
1391
|
+
* Whether the block-paged KV cache adapter is active on this model
|
|
1392
|
+
* instance.
|
|
1393
|
+
*
|
|
1394
|
+
* `true` iff `Qwen35MoeInner::paged_adapter` was successfully
|
|
1395
|
+
* constructed at load time (driven by
|
|
1396
|
+
* `Qwen3_5MoeConfig::use_block_paged_cache`, currently default-OFF
|
|
1397
|
+
* because parity is pending real-weights validation). On VLM
|
|
1398
|
+
* checkpoints the adapter can still be active for text-only
|
|
1399
|
+
* inference; image-bearing chat turns are rejected at runtime by
|
|
1400
|
+
* the chat-entry sites. Surfaced through this NAPI method so
|
|
1401
|
+
* server endpoints can branch on it without round-tripping through
|
|
1402
|
+
* the model thread.
|
|
1403
|
+
*/
|
|
1404
|
+
hasBlockPagedCache(): boolean;
|
|
1405
|
+
/**
|
|
1406
|
+
* Whether this checkpoint shipped an MTP head (module loaded by
|
|
1407
|
+
* `persistence::apply_weights_moe_inner`). Snapshotted at load time from
|
|
1408
|
+
* `Qwen35MoeInner::has_mtp_weights()` so the TS `ChatSession` can
|
|
1409
|
+
* auto-default `enableMtp = true` for MTP-capable checkpoints without
|
|
1410
|
+
* dispatching a command into the model thread. Mirrors
|
|
1411
|
+
* `Qwen3_5Model::has_mtp_weights`.
|
|
1412
|
+
*
|
|
1413
|
+
* Note: this only reports weight availability. Whether the
|
|
1414
|
+
* speculative-decode path actually runs on a given call also requires
|
|
1415
|
+
* the per-request `enableMtp` flag.
|
|
1416
|
+
*/
|
|
1417
|
+
hasMtpWeights(): boolean;
|
|
1418
|
+
/**
|
|
1419
|
+
* Whether this loaded model instance can execute image-bearing turns.
|
|
1420
|
+
*
|
|
1421
|
+
* This is an authoritative load-time snapshot, not a model-family guess:
|
|
1422
|
+
* it requires the loaded vision encoder, image processor, and block-paged
|
|
1423
|
+
* KV adapter used by the MoE vision path.
|
|
1424
|
+
*/
|
|
1425
|
+
supportsImages(): boolean;
|
|
1426
|
+
/** Synchronous active-context snapshot shared with the dense wrapper. */
|
|
1427
|
+
contextLimits(): Qwen35ContextLimits;
|
|
1428
|
+
/**
|
|
1429
|
+
* Exact, non-mutating Qwen image-placeholder expansion count for a fully
|
|
1430
|
+
* rendered prompt and complete message history.
|
|
1431
|
+
*/
|
|
1432
|
+
expandedPromptTokenCount(promptTokens: Uint32Array, messages: Array<ChatMessage>): Promise<number>;
|
|
1264
1433
|
/** Load a pretrained model from a directory. */
|
|
1265
1434
|
static load(path: string): Promise<Qwen35MoeModel>;
|
|
1266
1435
|
/** Generate text from a prompt token sequence. */
|
|
1267
1436
|
generate(promptTokens: MxArray, config: Qwen35MoeGenerationConfig): Promise<Qwen35MoeGenerationResult>;
|
|
1268
1437
|
/**
|
|
1269
|
-
*
|
|
1438
|
+
* Get the number of parameters in the model.
|
|
1270
1439
|
*
|
|
1271
|
-
*
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
*
|
|
1440
|
+
* Pure config computation -- no model-thread dispatch needed.
|
|
1441
|
+
*/
|
|
1442
|
+
numParameters(): number;
|
|
1443
|
+
/**
|
|
1444
|
+
* Save the model weights and configuration to a directory.
|
|
1276
1445
|
*
|
|
1277
|
-
*
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
*
|
|
1282
|
-
*
|
|
1446
|
+
* Dispatches to model thread.
|
|
1447
|
+
*/
|
|
1448
|
+
saveModel(savePath: string): Promise<undefined>;
|
|
1449
|
+
/**
|
|
1450
|
+
* Reset all caches and clear cached token history. Exposed
|
|
1451
|
+
* so tests and session-management code can start from a
|
|
1452
|
+
* known clean state between turns.
|
|
1453
|
+
*/
|
|
1454
|
+
resetCaches(): void;
|
|
1455
|
+
/**
|
|
1456
|
+
* Start a new chat session.
|
|
1283
1457
|
*
|
|
1284
|
-
*
|
|
1458
|
+
* Runs the full jinja chat template once, decodes until the
|
|
1459
|
+
* family's session stop token, and leaves the KV caches on a
|
|
1460
|
+
* clean turn boundary so subsequent `chatSessionContinue` /
|
|
1461
|
+
* `chatSessionContinueTool` calls can append a raw delta on
|
|
1462
|
+
* top without re-rendering the chat template.
|
|
1285
1463
|
*/
|
|
1286
1464
|
chatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
1287
1465
|
/**
|
|
1288
1466
|
* Continue an existing chat session with a new user message.
|
|
1289
1467
|
*
|
|
1290
|
-
* Appends a raw
|
|
1291
|
-
* KV state, then decodes the assistant reply
|
|
1292
|
-
*
|
|
1293
|
-
*
|
|
1294
|
-
* Requires a live session started via `chatSessionStart`.
|
|
1295
|
-
* Errors if the session is empty, carries image state, or if
|
|
1296
|
-
* `config.reuse_cache` is explicitly set to `false`.
|
|
1468
|
+
* Appends a raw user/assistant delta to the session's cached
|
|
1469
|
+
* KV state, then decodes the assistant reply, stopping on the
|
|
1470
|
+
* family's session boundary token.
|
|
1297
1471
|
*
|
|
1298
|
-
* `images` is an opt-in guard parameter: when non-empty
|
|
1299
|
-
* side returns an error whose message begins with
|
|
1472
|
+
* `images` is an opt-in guard parameter: when non-empty the
|
|
1473
|
+
* native side returns an error whose message begins with
|
|
1300
1474
|
* `IMAGE_CHANGE_REQUIRES_SESSION_RESTART:` so the TypeScript
|
|
1301
|
-
* `ChatSession` layer can
|
|
1302
|
-
*
|
|
1475
|
+
* `ChatSession` layer can route image-changes back through a
|
|
1476
|
+
* fresh `chatSessionStart`.
|
|
1303
1477
|
*/
|
|
1304
1478
|
chatSessionContinue(
|
|
1305
1479
|
userMessage: string,
|
|
1306
1480
|
images: Uint8Array[] | null | undefined,
|
|
1481
|
+
audio: Uint8Array[] | null | undefined,
|
|
1307
1482
|
config: ChatConfig | null | undefined,
|
|
1308
1483
|
): Promise<ChatResult>;
|
|
1309
1484
|
/**
|
|
1310
1485
|
* Continue an existing chat session with a tool-result turn.
|
|
1311
1486
|
*
|
|
1312
|
-
* Builds
|
|
1313
|
-
* prefills it on top of the live session caches, then decodes
|
|
1314
|
-
* assistant reply.
|
|
1315
|
-
* clean boundary for the next turn.
|
|
1316
|
-
*
|
|
1317
|
-
* The `tool_call_id` is currently dropped by the wire format —
|
|
1318
|
-
* Qwen3.5's chat template identifies tool responses by position +
|
|
1319
|
-
* wrapper tags, not an explicit id. Callers may still log it for
|
|
1320
|
-
* their own bookkeeping.
|
|
1487
|
+
* Builds the family's tool-result delta from `content` and
|
|
1488
|
+
* prefills it on top of the live session caches, then decodes
|
|
1489
|
+
* the assistant reply.
|
|
1321
1490
|
*
|
|
1322
|
-
*
|
|
1491
|
+
* `is_error` is the structured tool-error signal. When
|
|
1492
|
+
* `Some(true)`, the renderer prepends the shared
|
|
1493
|
+
* [`crate::tokenizer::TOOL_ERROR_MARKER`] inside the
|
|
1494
|
+
* rendered tool block.
|
|
1323
1495
|
*/
|
|
1324
1496
|
chatSessionContinueTool(
|
|
1325
1497
|
toolCallId: string,
|
|
1326
1498
|
content: string,
|
|
1327
1499
|
config?: ChatConfig | undefined | null,
|
|
1500
|
+
isError?: boolean | undefined | null,
|
|
1328
1501
|
): Promise<ChatResult>;
|
|
1329
|
-
/**
|
|
1330
|
-
* Streaming variant of `chatSessionStart`.
|
|
1331
|
-
*
|
|
1332
|
-
* Dispatches to the dedicated model thread. Behaviourally identical
|
|
1333
|
-
* to `chatSessionStart` (resets caches, uses `<|im_end|>` as
|
|
1334
|
-
* eos, inherits the same VLM-vs-text image-support contract) but
|
|
1335
|
-
* streams token deltas through the JS callback instead of
|
|
1336
|
-
* returning a `ChatResult`. Used by the TypeScript
|
|
1337
|
-
* `ChatSession.sendStream()` for turn 1 of a multi-round streaming
|
|
1338
|
-
* conversation.
|
|
1339
|
-
*/
|
|
1502
|
+
/** Streaming variant of `chatSessionStart`. */
|
|
1340
1503
|
chatStreamSessionStart(
|
|
1341
1504
|
messages: ChatMessage[],
|
|
1342
1505
|
config: ChatConfig | null,
|
|
1343
1506
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1344
1507
|
): Promise<ChatStreamHandle>;
|
|
1345
|
-
/**
|
|
1346
|
-
* Streaming variant of `chatSessionContinue`.
|
|
1347
|
-
*
|
|
1348
|
-
* Appends a ChatML user/assistant delta on top of the live session
|
|
1349
|
-
* caches and streams the decoded reply. Requires a live session
|
|
1350
|
-
* started via `chatStreamSessionStart` (or the non-streaming
|
|
1351
|
-
* `chatSessionStart`). Used by the TypeScript
|
|
1352
|
-
* `ChatSession.sendStream()` for turns 2..N of a multi-round
|
|
1353
|
-
* streaming conversation.
|
|
1354
|
-
*
|
|
1355
|
-
* `images` is an opt-in guard parameter: when non-empty, the
|
|
1356
|
-
* streaming path emits an error chunk whose message begins with
|
|
1357
|
-
* `IMAGE_CHANGE_REQUIRES_SESSION_RESTART:` so the TypeScript
|
|
1358
|
-
* `ChatSession` layer can route image-changes through a fresh
|
|
1359
|
-
* session start.
|
|
1360
|
-
*/
|
|
1508
|
+
/** Streaming variant of `chatSessionContinue`. */
|
|
1361
1509
|
chatStreamSessionContinue(
|
|
1362
1510
|
userMessage: string,
|
|
1363
1511
|
images: Uint8Array[] | null | undefined,
|
|
1512
|
+
audio: Uint8Array[] | null | undefined,
|
|
1364
1513
|
config: ChatConfig | null,
|
|
1365
1514
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1366
1515
|
): Promise<ChatStreamHandle>;
|
|
1367
1516
|
/**
|
|
1368
1517
|
* Streaming variant of `chatSessionContinueTool`.
|
|
1369
1518
|
*
|
|
1370
|
-
*
|
|
1371
|
-
*
|
|
1372
|
-
*
|
|
1519
|
+
* `is_error` mirrors the non-streaming entry point — when
|
|
1520
|
+
* `Some(true)`, the renderer prepends the shared
|
|
1521
|
+
* [`crate::tokenizer::TOOL_ERROR_MARKER`] inside the rendered
|
|
1522
|
+
* tool block.
|
|
1373
1523
|
*/
|
|
1374
1524
|
chatStreamSessionContinueTool(
|
|
1375
1525
|
toolCallId: string,
|
|
1376
1526
|
content: string,
|
|
1377
1527
|
config: ChatConfig | null,
|
|
1378
1528
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1529
|
+
isError?: boolean | null | undefined,
|
|
1379
1530
|
): Promise<ChatStreamHandle>;
|
|
1380
|
-
/**
|
|
1381
|
-
* Get the number of parameters in the model.
|
|
1382
|
-
*
|
|
1383
|
-
* Pure config computation -- no model-thread dispatch needed.
|
|
1384
|
-
*/
|
|
1385
|
-
numParameters(): number;
|
|
1386
|
-
/**
|
|
1387
|
-
* Save the model weights and configuration to a directory.
|
|
1388
|
-
*
|
|
1389
|
-
* Dispatches to model thread.
|
|
1390
|
-
*/
|
|
1391
|
-
saveModel(savePath: string): Promise<undefined>;
|
|
1392
1531
|
}
|
|
1393
1532
|
export type Qwen3_5MoeModel = Qwen35MoeModel;
|
|
1394
1533
|
|
|
@@ -1400,117 +1539,21 @@ export type Qwen3_5MoeModel = Qwen35MoeModel;
|
|
|
1400
1539
|
*/
|
|
1401
1540
|
export declare class Qwen3Model {
|
|
1402
1541
|
/**
|
|
1403
|
-
*
|
|
1404
|
-
*
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
*
|
|
1409
|
-
*
|
|
1410
|
-
*
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
*
|
|
1415
|
-
*
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
resetKvCaches(): void;
|
|
1419
|
-
/**
|
|
1420
|
-
* Get paged attention memory statistics (if enabled)
|
|
1421
|
-
*
|
|
1422
|
-
* Returns memory usage statistics for the paged KV cache.
|
|
1423
|
-
*/
|
|
1424
|
-
pagedCacheStats(): PagedCacheStats | null;
|
|
1425
|
-
/**
|
|
1426
|
-
* Get scheduler statistics (if paged attention is enabled)
|
|
1427
|
-
*
|
|
1428
|
-
* Returns the number of waiting, running, and completed sequences.
|
|
1429
|
-
*/
|
|
1430
|
-
schedulerStats(): SchedulerStatsNapi | null;
|
|
1431
|
-
/**
|
|
1432
|
-
* Forward pass with paged attention for memory-efficient inference.
|
|
1433
|
-
*
|
|
1434
|
-
* This method uses block-based KV cache management via Metal kernels for:
|
|
1435
|
-
* - Variable-length sequences with efficient memory usage
|
|
1436
|
-
* - Continuous batching with dynamic batch composition
|
|
1437
|
-
* - Long context support beyond GPU memory limits
|
|
1438
|
-
*
|
|
1439
|
-
* # Arguments
|
|
1440
|
-
* * `input_ids` - Token IDs, shape: [num_seqs, 1] for decode
|
|
1441
|
-
* * `slot_mapping` - Slot indices for cache updates, shape: [num_seqs]
|
|
1442
|
-
* * `seq_ids` - Sequence IDs in the batch (for looking up block tables/context lens)
|
|
1443
|
-
* * `positions` - Token positions for RoPE, shape: [num_seqs] (per-sequence positions)
|
|
1444
|
-
*
|
|
1445
|
-
* # Returns
|
|
1446
|
-
* * Logits, shape: [num_seqs, 1, vocab_size] for decode
|
|
1447
|
-
*/
|
|
1448
|
-
forwardPaged(inputIds: MxArray, slotMapping: MxArray, seqIds: Array<number>, positions: MxArray): MxArray;
|
|
1449
|
-
/**
|
|
1450
|
-
* Prefill a sequence using standard attention and write K/V to paged cache.
|
|
1451
|
-
*
|
|
1452
|
-
* This method should be called before `step_paged_generation()` for each
|
|
1453
|
-
* new prompt. It runs the full forward pass using standard attention
|
|
1454
|
-
* (which is faster for long sequences), then writes the K/V cache to
|
|
1455
|
-
* the paged cache for subsequent decode steps.
|
|
1456
|
-
*
|
|
1457
|
-
* # Arguments
|
|
1458
|
-
* * `prompt_tokens` - Token IDs for the prompt (as u32 array)
|
|
1459
|
-
* * `seq_id` - Sequence ID (obtained from scheduler)
|
|
1460
|
-
*
|
|
1461
|
-
* # Returns
|
|
1462
|
-
* * Logits for the last token, shape: [1, vocab_size]
|
|
1463
|
-
*/
|
|
1464
|
-
prefillPaged(promptTokens: Array<number>, seqId: number): MxArray;
|
|
1465
|
-
/**
|
|
1466
|
-
* Add a request to the paged attention scheduler.
|
|
1467
|
-
*
|
|
1468
|
-
* The scheduler queues requests and allocates blocks for KV cache.
|
|
1469
|
-
* Use `step_paged_generation()` to process the scheduled batch.
|
|
1470
|
-
*
|
|
1471
|
-
* Note: The actual sequence ID is assigned during scheduling, not when the
|
|
1472
|
-
* request is added. Use the `request_id` to track your requests through
|
|
1473
|
-
* the generation process.
|
|
1474
|
-
*
|
|
1475
|
-
* # Arguments
|
|
1476
|
-
* * `request_id` - Unique identifier for the request (returned in outputs)
|
|
1477
|
-
* * `prompt_tokens` - Token IDs for the prompt
|
|
1478
|
-
* * `max_new_tokens` - Maximum new tokens to generate
|
|
1479
|
-
* * `priority` - Optional priority (higher = scheduled first)
|
|
1480
|
-
*
|
|
1481
|
-
* # Returns
|
|
1482
|
-
* * Number of pending requests in the queue
|
|
1483
|
-
*/
|
|
1484
|
-
addPagedRequest(
|
|
1485
|
-
requestId: string,
|
|
1486
|
-
promptTokens: Array<number>,
|
|
1487
|
-
maxNewTokens: number,
|
|
1488
|
-
priority?: number | undefined | null,
|
|
1489
|
-
): number;
|
|
1490
|
-
/**
|
|
1491
|
-
* Schedule and execute one step of paged generation.
|
|
1492
|
-
*
|
|
1493
|
-
* This method:
|
|
1494
|
-
* 1. Schedules the next batch of sequences
|
|
1495
|
-
* 2. Runs forward pass with paged attention
|
|
1496
|
-
* 3. Samples next tokens
|
|
1497
|
-
* 4. Returns the generated tokens for each sequence
|
|
1498
|
-
*
|
|
1499
|
-
* # Arguments
|
|
1500
|
-
* * `config` - Generation configuration (temperature, top_k, etc.)
|
|
1501
|
-
*
|
|
1502
|
-
* # Returns
|
|
1503
|
-
* * `PagedGenerationStep` with token outputs for each sequence
|
|
1504
|
-
*/
|
|
1505
|
-
stepPagedGeneration(config?: GenerationConfig | undefined | null): PagedGenerationStep | null;
|
|
1506
|
-
/**
|
|
1507
|
-
* Get completed sequences from the scheduler.
|
|
1508
|
-
*
|
|
1509
|
-
* Call this after `step_paged_generation()` returns outputs with `is_finished: true`.
|
|
1510
|
-
*/
|
|
1511
|
-
getCompletedSequences(): Array<PagedCompletedSequence>;
|
|
1512
|
-
/** Check if the scheduler has pending work. */
|
|
1513
|
-
hasPagedWork(): boolean;
|
|
1542
|
+
* Whether the block-paged KV cache adapter is active on this model
|
|
1543
|
+
* instance.
|
|
1544
|
+
*
|
|
1545
|
+
* `true` iff `Qwen3Inner::paged_adapter` was successfully constructed
|
|
1546
|
+
* at load time (driven by `Qwen3Config::use_block_paged_cache`,
|
|
1547
|
+
* defaulting to `true` for Qwen3 since paged-vs-flat parity has been
|
|
1548
|
+
* verified). When `true`, the native cache reuses SYS blocks across
|
|
1549
|
+
* `chatSessionStart` calls via content-addressing in
|
|
1550
|
+
* `BlockAllocator`'s prefix-hash table — the JS-side warm slot in
|
|
1551
|
+
* `SessionRegistry.getOrCreateWarmAny` becomes redundant and the
|
|
1552
|
+
* `/v1/messages` server endpoint allocates a fresh `ChatSession` per
|
|
1553
|
+
* request. See `packages/server/src/endpoints/messages.ts` for the
|
|
1554
|
+
* runtime-routing decision.
|
|
1555
|
+
*/
|
|
1556
|
+
hasBlockPagedCache(): boolean;
|
|
1514
1557
|
/** Get model configuration */
|
|
1515
1558
|
getConfig(): Qwen3Config;
|
|
1516
1559
|
/**
|
|
@@ -1544,83 +1587,6 @@ export declare class Qwen3Model {
|
|
|
1544
1587
|
* ```
|
|
1545
1588
|
*/
|
|
1546
1589
|
generate(messages: Array<ChatMessage>, config?: GenerationConfig | undefined | null): Promise<GenerationResult>;
|
|
1547
|
-
/**
|
|
1548
|
-
* Reset all caches and clear cached token history. Exposed so
|
|
1549
|
-
* tests and session-management code can start from a known clean
|
|
1550
|
-
* state between turns.
|
|
1551
|
-
*/
|
|
1552
|
-
resetCaches(): void;
|
|
1553
|
-
/**
|
|
1554
|
-
* Start a new chat session.
|
|
1555
|
-
*
|
|
1556
|
-
* Runs the full jinja chat template once, decodes until `<|im_end|>`,
|
|
1557
|
-
* and leaves the KV caches on a clean ChatML boundary so subsequent
|
|
1558
|
-
* `chatSessionContinue` / `chatSessionContinueTool` calls can
|
|
1559
|
-
* append a raw delta on top without re-rendering the chat
|
|
1560
|
-
* template.
|
|
1561
|
-
*
|
|
1562
|
-
* Requires `config.reuse_cache` to be enabled (the default).
|
|
1563
|
-
*/
|
|
1564
|
-
chatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
1565
|
-
/**
|
|
1566
|
-
* Continue an existing chat session with a new user message.
|
|
1567
|
-
*
|
|
1568
|
-
* Appends a raw ChatML user/assistant delta to the session's
|
|
1569
|
-
* cached KV state, then decodes the assistant reply. Stops on
|
|
1570
|
-
* `<|im_end|>` so the cache remains on a clean boundary for the
|
|
1571
|
-
* next turn.
|
|
1572
|
-
*
|
|
1573
|
-
* Requires a live session started via `chatSessionStart`. Errors
|
|
1574
|
-
* if the session is empty, carries image state, or if
|
|
1575
|
-
* `config.reuse_cache` is explicitly set to `false`.
|
|
1576
|
-
*
|
|
1577
|
-
* Qwen3 legacy is text-only; `images` is an opt-in guard parameter:
|
|
1578
|
-
* when non-empty the native side returns an error whose message
|
|
1579
|
-
* begins with `IMAGE_CHANGE_REQUIRES_SESSION_RESTART:` so the
|
|
1580
|
-
* TypeScript `ChatSession` layer can catch the prefix and route
|
|
1581
|
-
* image-changes back through a fresh `chatSessionStart` uniformly
|
|
1582
|
-
* across all model backends.
|
|
1583
|
-
*/
|
|
1584
|
-
chatSessionContinue(
|
|
1585
|
-
userMessage: string,
|
|
1586
|
-
images: Uint8Array[] | null | undefined,
|
|
1587
|
-
config: ChatConfig | null | undefined,
|
|
1588
|
-
): Promise<ChatResult>;
|
|
1589
|
-
/**
|
|
1590
|
-
* Continue an existing chat session with a tool-result turn.
|
|
1591
|
-
*
|
|
1592
|
-
* Builds a Qwen3.5-style `<tool_response>`-wrapped user-role delta
|
|
1593
|
-
* from `content` and prefills it on top of the live session
|
|
1594
|
-
* caches, then decodes the assistant reply. Stops on `<|im_end|>`
|
|
1595
|
-
* so the cache stays on a clean boundary for the next turn.
|
|
1596
|
-
*
|
|
1597
|
-
* Requires a live session started via `chatSessionStart`.
|
|
1598
|
-
*/
|
|
1599
|
-
chatSessionContinueTool(
|
|
1600
|
-
toolCallId: string,
|
|
1601
|
-
content: string,
|
|
1602
|
-
config?: ChatConfig | undefined | null,
|
|
1603
|
-
): Promise<ChatResult>;
|
|
1604
|
-
/** Streaming variant of `chatSessionStart`. */
|
|
1605
|
-
chatStreamSessionStart(
|
|
1606
|
-
messages: ChatMessage[],
|
|
1607
|
-
config: ChatConfig | null,
|
|
1608
|
-
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1609
|
-
): Promise<ChatStreamHandle>;
|
|
1610
|
-
/** Streaming variant of `chatSessionContinue`. */
|
|
1611
|
-
chatStreamSessionContinue(
|
|
1612
|
-
userMessage: string,
|
|
1613
|
-
images: Uint8Array[] | null | undefined,
|
|
1614
|
-
config: ChatConfig | null,
|
|
1615
|
-
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1616
|
-
): Promise<ChatStreamHandle>;
|
|
1617
|
-
/** Streaming variant of `chatSessionContinueTool`. */
|
|
1618
|
-
chatStreamSessionContinueTool(
|
|
1619
|
-
toolCallId: string,
|
|
1620
|
-
content: string,
|
|
1621
|
-
config: ChatConfig | null,
|
|
1622
|
-
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1623
|
-
): Promise<ChatStreamHandle>;
|
|
1624
1590
|
/**
|
|
1625
1591
|
* Generate multiple completions for multiple prompts in batch
|
|
1626
1592
|
*
|
|
@@ -1660,20 +1626,6 @@ export declare class Qwen3Model {
|
|
|
1660
1626
|
groupSize: number,
|
|
1661
1627
|
config?: GenerationConfig | undefined | null,
|
|
1662
1628
|
): Promise<BatchGenerationResult>;
|
|
1663
|
-
/**
|
|
1664
|
-
* Decode token IDs to text using the internal tokenizer
|
|
1665
|
-
*
|
|
1666
|
-
* Helper method for decoding generated tokens. The model must have been loaded
|
|
1667
|
-
* via load() to have a tokenizer available.
|
|
1668
|
-
*
|
|
1669
|
-
* # Arguments
|
|
1670
|
-
* * `token_ids` - Token IDs to decode as Uint32Array
|
|
1671
|
-
* * `skip_special_tokens` - Whether to skip special tokens (default: true)
|
|
1672
|
-
*
|
|
1673
|
-
* # Returns
|
|
1674
|
-
* * Decoded text string
|
|
1675
|
-
*/
|
|
1676
|
-
decode(tokenIds: Uint32Array, skipSpecialTokens?: boolean | undefined | null): Promise<string>;
|
|
1677
1629
|
/**
|
|
1678
1630
|
* Apply chat template and encode to token IDs
|
|
1679
1631
|
*
|
|
@@ -1695,6 +1647,88 @@ export declare class Qwen3Model {
|
|
|
1695
1647
|
tools?: Array<ToolDefinition> | undefined | null,
|
|
1696
1648
|
enableThinking?: boolean | undefined | null,
|
|
1697
1649
|
): Promise<Uint32Array>;
|
|
1650
|
+
/**
|
|
1651
|
+
* Reset all caches and clear cached token history. Exposed
|
|
1652
|
+
* so tests and session-management code can start from a
|
|
1653
|
+
* known clean state between turns.
|
|
1654
|
+
*/
|
|
1655
|
+
resetCaches(): void;
|
|
1656
|
+
/**
|
|
1657
|
+
* Start a new chat session.
|
|
1658
|
+
*
|
|
1659
|
+
* Runs the full jinja chat template once, decodes until the
|
|
1660
|
+
* family's session stop token, and leaves the KV caches on a
|
|
1661
|
+
* clean turn boundary so subsequent `chatSessionContinue` /
|
|
1662
|
+
* `chatSessionContinueTool` calls can append a raw delta on
|
|
1663
|
+
* top without re-rendering the chat template.
|
|
1664
|
+
*/
|
|
1665
|
+
chatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
1666
|
+
/**
|
|
1667
|
+
* Continue an existing chat session with a new user message.
|
|
1668
|
+
*
|
|
1669
|
+
* Appends a raw user/assistant delta to the session's cached
|
|
1670
|
+
* KV state, then decodes the assistant reply, stopping on the
|
|
1671
|
+
* family's session boundary token.
|
|
1672
|
+
*
|
|
1673
|
+
* `images` is an opt-in guard parameter: when non-empty the
|
|
1674
|
+
* native side returns an error whose message begins with
|
|
1675
|
+
* `IMAGE_CHANGE_REQUIRES_SESSION_RESTART:` so the TypeScript
|
|
1676
|
+
* `ChatSession` layer can route image-changes back through a
|
|
1677
|
+
* fresh `chatSessionStart`.
|
|
1678
|
+
*/
|
|
1679
|
+
chatSessionContinue(
|
|
1680
|
+
userMessage: string,
|
|
1681
|
+
images: Uint8Array[] | null | undefined,
|
|
1682
|
+
audio: Uint8Array[] | null | undefined,
|
|
1683
|
+
config: ChatConfig | null | undefined,
|
|
1684
|
+
): Promise<ChatResult>;
|
|
1685
|
+
/**
|
|
1686
|
+
* Continue an existing chat session with a tool-result turn.
|
|
1687
|
+
*
|
|
1688
|
+
* Builds the family's tool-result delta from `content` and
|
|
1689
|
+
* prefills it on top of the live session caches, then decodes
|
|
1690
|
+
* the assistant reply.
|
|
1691
|
+
*
|
|
1692
|
+
* `is_error` is the structured tool-error signal. When
|
|
1693
|
+
* `Some(true)`, the renderer prepends the shared
|
|
1694
|
+
* [`crate::tokenizer::TOOL_ERROR_MARKER`] inside the
|
|
1695
|
+
* rendered tool block.
|
|
1696
|
+
*/
|
|
1697
|
+
chatSessionContinueTool(
|
|
1698
|
+
toolCallId: string,
|
|
1699
|
+
content: string,
|
|
1700
|
+
config?: ChatConfig | undefined | null,
|
|
1701
|
+
isError?: boolean | undefined | null,
|
|
1702
|
+
): Promise<ChatResult>;
|
|
1703
|
+
/** Streaming variant of `chatSessionStart`. */
|
|
1704
|
+
chatStreamSessionStart(
|
|
1705
|
+
messages: ChatMessage[],
|
|
1706
|
+
config: ChatConfig | null,
|
|
1707
|
+
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1708
|
+
): Promise<ChatStreamHandle>;
|
|
1709
|
+
/** Streaming variant of `chatSessionContinue`. */
|
|
1710
|
+
chatStreamSessionContinue(
|
|
1711
|
+
userMessage: string,
|
|
1712
|
+
images: Uint8Array[] | null | undefined,
|
|
1713
|
+
audio: Uint8Array[] | null | undefined,
|
|
1714
|
+
config: ChatConfig | null,
|
|
1715
|
+
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1716
|
+
): Promise<ChatStreamHandle>;
|
|
1717
|
+
/**
|
|
1718
|
+
* Streaming variant of `chatSessionContinueTool`.
|
|
1719
|
+
*
|
|
1720
|
+
* `is_error` mirrors the non-streaming entry point — when
|
|
1721
|
+
* `Some(true)`, the renderer prepends the shared
|
|
1722
|
+
* [`crate::tokenizer::TOOL_ERROR_MARKER`] inside the rendered
|
|
1723
|
+
* tool block.
|
|
1724
|
+
*/
|
|
1725
|
+
chatStreamSessionContinueTool(
|
|
1726
|
+
toolCallId: string,
|
|
1727
|
+
content: string,
|
|
1728
|
+
config: ChatConfig | null,
|
|
1729
|
+
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1730
|
+
isError?: boolean | null | undefined,
|
|
1731
|
+
): Promise<ChatStreamHandle>;
|
|
1698
1732
|
/**
|
|
1699
1733
|
* Load a pretrained model from disk
|
|
1700
1734
|
*
|
|
@@ -2167,124 +2201,46 @@ export declare class VLModel {
|
|
|
2167
2201
|
* for loading a model from disk.
|
|
2168
2202
|
*/
|
|
2169
2203
|
constructor(config: ModelConfig);
|
|
2170
|
-
/** Set the tokenizer */
|
|
2171
|
-
setTokenizer(tokenizer: Qwen3Tokenizer): void;
|
|
2172
|
-
/** Check if tokenizer is available */
|
|
2173
|
-
get hasTokenizer(): boolean;
|
|
2174
|
-
/**
|
|
2175
|
-
* Chat with the VLM model
|
|
2176
|
-
*
|
|
2177
|
-
* High-level API for conversational interaction with images.
|
|
2178
|
-
*
|
|
2179
|
-
* # Arguments
|
|
2180
|
-
* * `messages` - Chat messages (role + content)
|
|
2181
|
-
* * `config` - Chat configuration (including images for automatic processing)
|
|
2182
|
-
*
|
|
2183
|
-
* # Returns
|
|
2184
|
-
* * VLMChatResult with generated text
|
|
2185
|
-
*
|
|
2186
|
-
* # Example
|
|
2187
|
-
* ```typescript
|
|
2188
|
-
* const result = await model.chat(
|
|
2189
|
-
* [{ role: 'user', content: 'Describe this image.' }],
|
|
2190
|
-
* { images: [readFileSync('./photo.jpg')], maxNewTokens: 256 }
|
|
2191
|
-
* );
|
|
2192
|
-
* ```
|
|
2193
|
-
*/
|
|
2194
|
-
chat(messages: Array<VlmChatMessage>, config?: VlmChatConfig | undefined | null): Promise<VlmChatResult>;
|
|
2195
|
-
/**
|
|
2196
|
-
* Simple OCR: extract text from encoded image bytes
|
|
2197
|
-
*
|
|
2198
|
-
* Convenience method that processes an image and extracts all text.
|
|
2199
|
-
*
|
|
2200
|
-
* # Arguments
|
|
2201
|
-
* * `image_data` - Encoded image bytes (PNG/JPEG)
|
|
2202
|
-
* * `prompt` - Optional custom prompt (default: "Extract all text from this image.")
|
|
2203
|
-
*
|
|
2204
|
-
* # Returns
|
|
2205
|
-
* * Extracted text as a string
|
|
2206
|
-
*
|
|
2207
|
-
* # Example
|
|
2208
|
-
* ```typescript
|
|
2209
|
-
* const text = await model.ocr(imageBuffer);
|
|
2210
|
-
* console.log(text);
|
|
2211
|
-
* ```
|
|
2212
|
-
*/
|
|
2213
|
-
ocr(imageData: Buffer, prompt?: string | undefined | null): Promise<string>;
|
|
2214
|
-
/**
|
|
2215
|
-
* Get input embeddings with vision features merged
|
|
2216
|
-
*
|
|
2217
|
-
* # Arguments
|
|
2218
|
-
* * `input_ids` - Token IDs [batch, seq_len]
|
|
2219
|
-
* * `pixel_values` - Optional image patches [batch, seq, channels, patch_h, patch_w]
|
|
2220
|
-
* * `image_grid_thw` - Optional grid dimensions [num_images, 3]
|
|
2221
|
-
*
|
|
2222
|
-
* # Returns
|
|
2223
|
-
* * Input embeddings with vision features inserted at image token positions
|
|
2224
|
-
*/
|
|
2225
|
-
getInputEmbeddings(
|
|
2226
|
-
inputIds: MxArray,
|
|
2227
|
-
pixelValues?: MxArray | undefined | null,
|
|
2228
|
-
imageGridThw?: MxArray | undefined | null,
|
|
2229
|
-
): MxArray;
|
|
2230
|
-
/**
|
|
2231
|
-
* Forward pass
|
|
2232
|
-
*
|
|
2233
|
-
* # Arguments
|
|
2234
|
-
* * `input_ids` - Token IDs [batch, seq_len]
|
|
2235
|
-
* * `pixel_values` - Optional image patches
|
|
2236
|
-
* * `image_grid_thw` - Optional grid dimensions
|
|
2237
|
-
* * `mask` - Optional attention mask
|
|
2238
|
-
*
|
|
2239
|
-
* # Returns
|
|
2240
|
-
* * Logits [batch, seq_len, vocab_size]
|
|
2241
|
-
*/
|
|
2242
|
-
forward(
|
|
2243
|
-
inputIds: MxArray,
|
|
2244
|
-
pixelValues?: MxArray | undefined | null,
|
|
2245
|
-
imageGridThw?: MxArray | undefined | null,
|
|
2246
|
-
mask?: MxArray | undefined | null,
|
|
2247
|
-
): MxArray;
|
|
2248
2204
|
/**
|
|
2249
|
-
*
|
|
2205
|
+
* Chat with the VLM model
|
|
2250
2206
|
*
|
|
2251
|
-
*
|
|
2207
|
+
* High-level API for conversational interaction with images.
|
|
2252
2208
|
*
|
|
2253
2209
|
* # Arguments
|
|
2254
|
-
* * `
|
|
2255
|
-
* * `
|
|
2256
|
-
* * `image_grid_thw` - Optional grid dimensions [1, 3]
|
|
2257
|
-
* * `config` - Generation configuration
|
|
2210
|
+
* * `messages` - Chat messages (role + content)
|
|
2211
|
+
* * `config` - Chat configuration (including images for automatic processing)
|
|
2258
2212
|
*
|
|
2259
2213
|
* # Returns
|
|
2260
|
-
* *
|
|
2214
|
+
* * VLMChatResult with generated text
|
|
2215
|
+
*
|
|
2216
|
+
* # Example
|
|
2217
|
+
* ```typescript
|
|
2218
|
+
* const result = await model.chat(
|
|
2219
|
+
* [{ role: 'user', content: 'Describe this image.' }],
|
|
2220
|
+
* { images: [readFileSync('./photo.jpg')], maxNewTokens: 256 }
|
|
2221
|
+
* );
|
|
2222
|
+
* ```
|
|
2261
2223
|
*/
|
|
2262
|
-
|
|
2263
|
-
inputIds: MxArray,
|
|
2264
|
-
pixelValues?: MxArray | undefined | null,
|
|
2265
|
-
imageGridThw?: MxArray | undefined | null,
|
|
2266
|
-
config?: GenerationConfig | undefined | null,
|
|
2267
|
-
): Promise<GenerationResult>;
|
|
2224
|
+
chat(messages: Array<VlmChatMessage>, config?: VlmChatConfig | undefined | null): Promise<VlmChatResult>;
|
|
2268
2225
|
/**
|
|
2269
|
-
*
|
|
2226
|
+
* Simple OCR: extract text from encoded image bytes
|
|
2270
2227
|
*
|
|
2271
|
-
*
|
|
2228
|
+
* Convenience method that processes an image and extracts all text.
|
|
2272
2229
|
*
|
|
2273
2230
|
* # Arguments
|
|
2274
|
-
* * `
|
|
2275
|
-
* * `
|
|
2231
|
+
* * `image_data` - Encoded image bytes (PNG/JPEG)
|
|
2232
|
+
* * `prompt` - Optional custom prompt (default: "Extract all text from this image.")
|
|
2276
2233
|
*
|
|
2277
2234
|
* # Returns
|
|
2278
|
-
* *
|
|
2235
|
+
* * Extracted text as a string
|
|
2279
2236
|
*
|
|
2280
2237
|
* # Example
|
|
2281
2238
|
* ```typescript
|
|
2282
|
-
*
|
|
2283
|
-
*
|
|
2284
|
-
* const texts = await model.ocrBatch(images);
|
|
2239
|
+
* const text = await model.ocr(imageBuffer);
|
|
2240
|
+
* console.log(text);
|
|
2285
2241
|
* ```
|
|
2286
2242
|
*/
|
|
2287
|
-
|
|
2243
|
+
ocr(imageData: Buffer, prompt?: string | undefined | null): Promise<string>;
|
|
2288
2244
|
/**
|
|
2289
2245
|
* Batch chat: process multiple items simultaneously
|
|
2290
2246
|
*
|
|
@@ -2323,25 +2279,6 @@ export declare class VLModel {
|
|
|
2323
2279
|
* ```
|
|
2324
2280
|
*/
|
|
2325
2281
|
static load(modelPath: string): Promise<VLModel>;
|
|
2326
|
-
/**
|
|
2327
|
-
* Load model configuration from disk without loading weights
|
|
2328
|
-
*
|
|
2329
|
-
* This is useful for inspecting model configuration before loading the full model.
|
|
2330
|
-
*
|
|
2331
|
-
* # Arguments
|
|
2332
|
-
* * `model_path` - Path to the model directory containing config.json
|
|
2333
|
-
*
|
|
2334
|
-
* # Returns
|
|
2335
|
-
* * ModelConfig with vision and text configuration
|
|
2336
|
-
*
|
|
2337
|
-
* # Example
|
|
2338
|
-
* ```typescript
|
|
2339
|
-
* import { VLModel } from '@mlx-node/vlm';
|
|
2340
|
-
* const config = await VLModel.loadConfig('./models/paddleocr-vl');
|
|
2341
|
-
* console.log(config.visionConfig.hiddenSize);
|
|
2342
|
-
* ```
|
|
2343
|
-
*/
|
|
2344
|
-
static loadConfig(modelPath: string): Promise<ModelConfig>;
|
|
2345
2282
|
}
|
|
2346
2283
|
|
|
2347
2284
|
/**
|
|
@@ -2392,8 +2329,68 @@ export declare const enum BuiltinRewardType {
|
|
|
2392
2329
|
JsonSchema = 'JsonSchema',
|
|
2393
2330
|
}
|
|
2394
2331
|
|
|
2332
|
+
/**
|
|
2333
|
+
* Data-free static FP8 activation-amax calibration over RAW-text PREFILL
|
|
2334
|
+
* (NVIDIA modelopt `MaxCalibrator` parity), end to end in native code.
|
|
2335
|
+
*
|
|
2336
|
+
* The nvidia recipe covers BOTH `qwen3_5` (dense) and `qwen3_5_moe` (MoE), so
|
|
2337
|
+
* this reads `<model_path>/config.json`'s `model_type` and dispatches to the
|
|
2338
|
+
* matching loader + `CalibratePrefillRaw` command (any other `model_type` is a
|
|
2339
|
+
* clear error). Both loaders are the SAME ones the inference session uses
|
|
2340
|
+
* ([`persistence::load_with_thread`]) — the model is only usable on its
|
|
2341
|
+
* dedicated model thread. Then:
|
|
2342
|
+
* 1. dispatches `{Qwen35Cmd,Qwen35MoeCmd}::CalibratePrefillRaw`, which on the
|
|
2343
|
+
* model thread SELF-ARMS that thread's thread-local
|
|
2344
|
+
* [`ActivationAmaxCollector`] flag (RAII, AFTER load so no load-time eval
|
|
2345
|
+
* is recorded), tokenizes each `text` WITHOUT the chat template, truncates
|
|
2346
|
+
* to `calib_seq` tokens, and runs PREFILL ONLY (no generation) so every
|
|
2347
|
+
* mxfp8 attn/GDN projection's activation tap fires over realistic raw-text
|
|
2348
|
+
* activations, resetting caches between rows, then disarms on exit;
|
|
2349
|
+
* 2. ONLY if the full loop succeeded — drains the per-tensor amax and
|
|
2350
|
+
* ATOMICALLY writes it into `<model_path>/config.json` (temp file +
|
|
2351
|
+
* `rename`).
|
|
2352
|
+
*
|
|
2353
|
+
* CONCURRENCY: the whole clear→prefill→take→write section is serialized by
|
|
2354
|
+
* [`calib_guard`] (a process-wide `try_lock`); a second concurrent calibration
|
|
2355
|
+
* fails fast with "another calibration is in progress". The arm flag is
|
|
2356
|
+
* thread-local (so a concurrent inference model can't contaminate the run), but
|
|
2357
|
+
* the running-max MAP is process-global, so serializing RUNS keeps two
|
|
2358
|
+
* calibrations from interleaving `record`/`take` on it. The map is CLEARED at
|
|
2359
|
+
* the very start so stale amax from a prior PANICKED run cannot leak into this
|
|
2360
|
+
* write.
|
|
2361
|
+
*
|
|
2362
|
+
* On ANY error before the final write, the partial amax is discarded and
|
|
2363
|
+
* `config.json` is left UNTOUCHED (a failed calibration must not mutate the
|
|
2364
|
+
* live model in place). A run that prefilled ZERO rows (empty dataset, or every
|
|
2365
|
+
* row tokenized to nothing) is likewise an ERROR that leaves `config.json`
|
|
2366
|
+
* untouched — a no-op calibration must not report a silent success. Returns the
|
|
2367
|
+
* number of projections calibrated (the count of collected amax entries); 0
|
|
2368
|
+
* means a real prefill ran but the model exercised no activation-fp8 sites (not
|
|
2369
|
+
* an nvidia-recipe checkpoint), and in that case `config.json` is left
|
|
2370
|
+
* UNCHANGED (no rewrite).
|
|
2371
|
+
*/
|
|
2372
|
+
export declare function calibrateActivationAmaxRaw(
|
|
2373
|
+
modelPath: string,
|
|
2374
|
+
texts: Array<string>,
|
|
2375
|
+
calibSeq: number,
|
|
2376
|
+
): Promise<number>;
|
|
2377
|
+
|
|
2395
2378
|
/** Unified chat configuration shared by all model variants (Qwen3, Qwen3.5, Qwen3.5 MoE). */
|
|
2396
2379
|
export interface ChatConfig {
|
|
2380
|
+
/**
|
|
2381
|
+
* Internal logical cache owner. The agent provider forwards Pi's stable
|
|
2382
|
+
* session id so model-global GDN sidecars can retain parent and child
|
|
2383
|
+
* branches independently. This does not namespace the physical paged KV
|
|
2384
|
+
* cache; exact token/extra-key hashes remain shareable across owners.
|
|
2385
|
+
*/
|
|
2386
|
+
cacheOwnerId?: string | undefined;
|
|
2387
|
+
/**
|
|
2388
|
+
* Internal top-level owner for the bounded Qwen3.5 GDN sidecar store.
|
|
2389
|
+
* `cache_owner_id` may identify a child Pi session; this separately
|
|
2390
|
+
* identifies the current interactive root so /new and /resume can rotate
|
|
2391
|
+
* the protected branch without changing PagedAttention cache identity.
|
|
2392
|
+
*/
|
|
2393
|
+
cacheRootOwnerId?: string | undefined;
|
|
2397
2394
|
maxNewTokens?: number | undefined;
|
|
2398
2395
|
temperature?: number | undefined;
|
|
2399
2396
|
topK?: number | undefined;
|
|
@@ -2417,11 +2414,11 @@ export interface ChatConfig {
|
|
|
2417
2414
|
frequencyPenalty?: number | undefined;
|
|
2418
2415
|
/** Number of recent tokens to consider for frequency penalty (default: 20) */
|
|
2419
2416
|
frequencyContextSize?: number | undefined;
|
|
2420
|
-
/** Max consecutive identical tokens before stopping (default:
|
|
2417
|
+
/** Max consecutive identical tokens before stopping (default: 0 = disabled; opt in with a positive value) */
|
|
2421
2418
|
maxConsecutiveTokens?: number | undefined;
|
|
2422
|
-
/** Max n-gram repetitions before stopping (default:
|
|
2419
|
+
/** Max n-gram repetitions before stopping (default: 0 = disabled; opt in with a positive value) */
|
|
2423
2420
|
maxNgramRepeats?: number | undefined;
|
|
2424
|
-
/** Max pattern size for n-gram repetition detection (default:
|
|
2421
|
+
/** Max pattern size for n-gram repetition detection (default: 0 = disabled; opt in with a positive value) */
|
|
2425
2422
|
ngramSize?: number | undefined;
|
|
2426
2423
|
tools?: Array<ToolDefinition>;
|
|
2427
2424
|
/**
|
|
@@ -2454,6 +2451,56 @@ export interface ChatConfig {
|
|
|
2454
2451
|
* avoiding redundant computation for multi-turn conversations.
|
|
2455
2452
|
*/
|
|
2456
2453
|
reuseCache?: boolean | undefined;
|
|
2454
|
+
/**
|
|
2455
|
+
* MTP: opt-in flag enabling the Multi-Token Prediction speculative decode
|
|
2456
|
+
* loop (pure-Rust eager; qwen3.5 dense and MoE). Requires the model
|
|
2457
|
+
* checkpoint to carry an MTP head (otherwise silently ignored). Default:
|
|
2458
|
+
* `false`.
|
|
2459
|
+
*/
|
|
2460
|
+
enableMtp?: boolean | undefined;
|
|
2461
|
+
/**
|
|
2462
|
+
* MTP: number of draft tokens per speculative cycle.
|
|
2463
|
+
*
|
|
2464
|
+
* On Qwen3.5 native MTP heads it is clamped to `[1, 5]` by the verify
|
|
2465
|
+
* FFI contract, and when unset native code currently pins depth 1.
|
|
2466
|
+
* When `mtpAdaptiveDepth` is `true`, this value is used as the
|
|
2467
|
+
* throughput-policy seed and the expected-value policy's max depth.
|
|
2468
|
+
* Adaptive depth is opt-in; set `mtpAdaptiveDepth: true` explicitly to
|
|
2469
|
+
* enable it.
|
|
2470
|
+
*
|
|
2471
|
+
* Gemma4 external drafts (`draftModelPath`) resolve the field per draft
|
|
2472
|
+
* variant instead (`gemma4/model.rs` `resolve_params`, always from the
|
|
2473
|
+
* RAW config value — the engine's central `[1, 5]` clamp is an MTP-head
|
|
2474
|
+
* contract that does not apply to external drafts):
|
|
2475
|
+
* - DSpark: with both knobs unset, full draft blocks (the checkpoint's
|
|
2476
|
+
* block size — 7 tokens on `dspark_gemma4_12b_block7`) run behind a
|
|
2477
|
+
* short target-AR/DSpark break-even calibration. A short generation
|
|
2478
|
+
* budget that cannot finish calibration retains the fixed-block
|
|
2479
|
+
* schedule. An explicit
|
|
2480
|
+
* `mtpDepth` caps and pins the block unless `mtpAdaptiveDepth: true`
|
|
2481
|
+
* opts the guard back in; explicit `false` disables it.
|
|
2482
|
+
* - Assistant (Google `gemma-4-*-it-assistant`): an unset `mtpDepth`
|
|
2483
|
+
* drafts 3 tokens per cycle (`ASSISTANT_DEFAULT_DEPTH`), and an
|
|
2484
|
+
* explicit `mtpDepth` clamps to `[1, 8]` (`ASSISTANT_MAX_DEPTH`).
|
|
2485
|
+
*
|
|
2486
|
+
* `mtpAdaptiveDepth` is ignored for the Gemma4 assistant variant.
|
|
2487
|
+
*/
|
|
2488
|
+
mtpDepth?: number | undefined;
|
|
2489
|
+
/**
|
|
2490
|
+
* MTP: when true, the decode loop runs the adaptive
|
|
2491
|
+
* depth policy. Default mode is a per-depth EMA hill-climb plus
|
|
2492
|
+
* DFlash-style 3-state machine `full | reduced | probe`.
|
|
2493
|
+
* `MLX_MTP_ADAPTIVE_DEPTH_MODE=expected-value` instead uses the
|
|
2494
|
+
* MTPLX-style intra-cycle expected-value gate, which deepens toward
|
|
2495
|
+
* `mtpDepth` by default (T=0 byte-parity verified); set
|
|
2496
|
+
* `MLX_MTP_EV_ALLOW_DEEPEN=0` to pin the base depth.
|
|
2497
|
+
* When false, the loop pins `mtpDepth` for every cycle.
|
|
2498
|
+
*
|
|
2499
|
+
* Default: false, except Gemma4 DSpark enables its measured break-even
|
|
2500
|
+
* guard when both this field and `mtpDepth` are unset. An explicit value
|
|
2501
|
+
* always wins over the family default.
|
|
2502
|
+
*/
|
|
2503
|
+
mtpAdaptiveDepth?: boolean | undefined;
|
|
2457
2504
|
}
|
|
2458
2505
|
|
|
2459
2506
|
/** Chat message with tool calling support */
|
|
@@ -2466,10 +2513,40 @@ export interface ChatMessage {
|
|
|
2466
2513
|
toolCalls?: Array<ToolCall>;
|
|
2467
2514
|
/** Tool call ID this message is responding to (for tool messages) */
|
|
2468
2515
|
toolCallId?: string;
|
|
2516
|
+
/**
|
|
2517
|
+
* Whether this tool-role message represents an errored tool result.
|
|
2518
|
+
*
|
|
2519
|
+
* Authoritative, structured signal of tool-call failure. Set to
|
|
2520
|
+
* `Some(true)` when the caller (e.g. the Anthropic
|
|
2521
|
+
* `tool_result.is_error === true` translator) wants the model to
|
|
2522
|
+
* treat the tool output as an error. The renderer prepends a short
|
|
2523
|
+
* `[tool error]` prefix to `content` when emitting the wire-format
|
|
2524
|
+
* tool response so the model receives a clear text-level cue, but
|
|
2525
|
+
* the original `content` stays byte-for-byte intact in the
|
|
2526
|
+
* structured form — no JSON wrapping, no in-band marker that could
|
|
2527
|
+
* collide with a successful tool result whose literal content
|
|
2528
|
+
* happens to start with the same prefix.
|
|
2529
|
+
*
|
|
2530
|
+
* `None` / `Some(false)` produce the unmarked wire format.
|
|
2531
|
+
*/
|
|
2532
|
+
isError?: boolean;
|
|
2469
2533
|
/** Reasoning content for thinking mode (used with <think> tags) */
|
|
2470
2534
|
reasoningContent?: string;
|
|
2535
|
+
/**
|
|
2536
|
+
* Thinking mode used when this assistant message was generated.
|
|
2537
|
+
*
|
|
2538
|
+
* This is replay provenance, not a request override. Gemma4's disabled-
|
|
2539
|
+
* thinking generation prefix contains an explicit empty thought channel,
|
|
2540
|
+
* while an enabled-thinking turn that emitted no reasoning contains no
|
|
2541
|
+
* such channel. Keeping the historical mode on the message lets the chat
|
|
2542
|
+
* template reproduce either byte sequence even when a later request
|
|
2543
|
+
* changes its current thinking setting.
|
|
2544
|
+
*/
|
|
2545
|
+
thinkingEnabled?: boolean;
|
|
2471
2546
|
/** Image data for VLM models (encoded image bytes: PNG/JPEG, passed as Uint8Array/Buffer) */
|
|
2472
2547
|
images?: Array<Uint8Array> | undefined;
|
|
2548
|
+
/** Audio data for unified Gemma 4 (encoded audio bytes: WAV, passed as Uint8Array/Buffer) */
|
|
2549
|
+
audio?: Array<Uint8Array> | undefined;
|
|
2473
2550
|
}
|
|
2474
2551
|
|
|
2475
2552
|
/** Unified chat result shared by all model variants (Qwen3, Qwen3.5, Qwen3.5 MoE). */
|
|
@@ -2482,6 +2559,17 @@ export interface ChatResult {
|
|
|
2482
2559
|
reasoningTokens: number;
|
|
2483
2560
|
finishReason: string;
|
|
2484
2561
|
rawText: string;
|
|
2562
|
+
/**
|
|
2563
|
+
* Number of prompt tokens served from the reused KV-cache prefix.
|
|
2564
|
+
*
|
|
2565
|
+
* When the native prefix-cache machinery successfully matches the new
|
|
2566
|
+
* prompt against the cached conversation history (via
|
|
2567
|
+
* `verify_cache_prefix_direct`), only the trailing delta is re-prefilled
|
|
2568
|
+
* and this field reports the length of the reused prefix. `0` when
|
|
2569
|
+
* the cache was missed or disabled and the full prompt had to be
|
|
2570
|
+
* re-prefilled.
|
|
2571
|
+
*/
|
|
2572
|
+
cachedTokens: number;
|
|
2485
2573
|
/** Performance metrics (present when `reportPerformance: true` in config) */
|
|
2486
2574
|
performance?: PerformanceMetrics;
|
|
2487
2575
|
}
|
|
@@ -2509,6 +2597,19 @@ export interface ChatStreamChunk {
|
|
|
2509
2597
|
promptTokens?: number;
|
|
2510
2598
|
reasoningTokens?: number;
|
|
2511
2599
|
rawText?: string;
|
|
2600
|
+
/**
|
|
2601
|
+
* Number of prompt tokens served from the reused KV-cache prefix on
|
|
2602
|
+
* this turn. Populated on the terminal chunk (`done == true`) only;
|
|
2603
|
+
* `None` on mid-stream delta chunks.
|
|
2604
|
+
*
|
|
2605
|
+
* Zero on a cache miss or disabled reuse; equal to the matched
|
|
2606
|
+
* prefix length on a hit. Mirrors `ChatResult.cached_tokens`
|
|
2607
|
+
* verbatim so session-aware streaming consumers can observe
|
|
2608
|
+
* prefix-cache reuse without round-tripping to the non-streaming
|
|
2609
|
+
* path. Non-terminal chunks always carry `None` — only the
|
|
2610
|
+
* terminal chunk is authoritative.
|
|
2611
|
+
*/
|
|
2612
|
+
cachedTokens?: number | undefined;
|
|
2512
2613
|
/** Performance metrics (only present in the final chunk when `reportPerformance: true`) */
|
|
2513
2614
|
performance?: PerformanceMetrics;
|
|
2514
2615
|
/**
|
|
@@ -2579,7 +2680,11 @@ export interface ConversionOptions {
|
|
|
2579
2680
|
quantBits?: number;
|
|
2580
2681
|
/** Quantization group size (default: 64 for affine, 32 for mxfp8) */
|
|
2581
2682
|
quantGroupSize?: number;
|
|
2582
|
-
/**
|
|
2683
|
+
/**
|
|
2684
|
+
* Quantization mode: "affine" (default), "mxfp4", "mxfp8", "nvfp4", or
|
|
2685
|
+
* "sym8" (per-output-channel symmetric int8; qwen3_5 + qwen3_5_moe + lfm2/lfm2_moe + gemma4,
|
|
2686
|
+
* implies bits=8, no group_size — consciously NOT mlx-lm-loadable)
|
|
2687
|
+
*/
|
|
2583
2688
|
quantMode?: string;
|
|
2584
2689
|
/**
|
|
2585
2690
|
* Quantization recipe for per-layer mixed-bit quantization.
|
|
@@ -2591,6 +2696,35 @@ export interface ConversionOptions {
|
|
|
2591
2696
|
* Improves quantization quality by amplifying important weight channels.
|
|
2592
2697
|
*/
|
|
2593
2698
|
imatrixPath?: string;
|
|
2699
|
+
/**
|
|
2700
|
+
* Upgrade quantization to micro-scaling FP (mxfp4 / mxfp8).
|
|
2701
|
+
* When true, applies after the recipe predicate: eligible 8-bit affine
|
|
2702
|
+
* decisions become mxfp8 and 4-bit become mxfp4. Kept affine (not upgraded):
|
|
2703
|
+
* affine-only loaders (lm_head, embed_tokens, router.proj,
|
|
2704
|
+
* embedding_projection) at their recipe bits, MoE router gates (8-bit affine),
|
|
2705
|
+
* and the recipe-pinned attention/GDN projections (o_proj / out_proj /
|
|
2706
|
+
* in_proj_a / in_proj_b, 8-bit affine). Requires `quant_mode = "affine"`.
|
|
2707
|
+
* Forces `group_size = 32` for upgraded layers.
|
|
2708
|
+
*/
|
|
2709
|
+
quantMxfp?: boolean;
|
|
2710
|
+
/**
|
|
2711
|
+
* Optional Qwen MTP quantization policy: "off" (default), "cyankiwi", "all",
|
|
2712
|
+
* or "split" (alias "drafter").
|
|
2713
|
+
* "cyankiwi" keeps mtp.fc dense and quantizes only the MTP layer linears as
|
|
2714
|
+
* 4-bit affine group_size=32. For dense `qwen3_5` the quantized linears are
|
|
2715
|
+
* emitted into an MTPLX-compatible mtp.safetensors sidecar; for MoE
|
|
2716
|
+
* (`qwen3_5_moe`) there is no sidecar — they are quantized in place and stored
|
|
2717
|
+
* inline in the main safetensors shards.
|
|
2718
|
+
* "all" additionally quantizes mtp.fc. For dense `qwen3_5` the quantized MTP
|
|
2719
|
+
* linears land in the mtp.safetensors sidecar; for MoE (`qwen3_5_moe`) there
|
|
2720
|
+
* is no sidecar — they are quantized in place and stored inline in the main
|
|
2721
|
+
* safetensors shards.
|
|
2722
|
+
* "split"/"drafter" emits a body checkpoint with NO mtp.* tensors plus a
|
|
2723
|
+
* separate `mtp-drafter/` directory in mlx-vlm's `qwen3_5_mtp` format
|
|
2724
|
+
* (bare-keyed MTP head, format:mlx). It does NOT require --quantize/--q-recipe;
|
|
2725
|
+
* the body may be bf16 or already-quantized and the MTP head stays bf16.
|
|
2726
|
+
*/
|
|
2727
|
+
quantMtp?: string;
|
|
2594
2728
|
}
|
|
2595
2729
|
|
|
2596
2730
|
export interface ConversionResult {
|
|
@@ -2662,11 +2796,11 @@ export declare function createRandomQwen35Checkpoint(config: Qwen35Config, saveP
|
|
|
2662
2796
|
/**
|
|
2663
2797
|
* Create a random-init Qwen3.5 MoE model and save it to disk.
|
|
2664
2798
|
*
|
|
2665
|
-
* Spawns a dedicated
|
|
2666
|
-
* random-
|
|
2667
|
-
*
|
|
2668
|
-
*
|
|
2669
|
-
*
|
|
2799
|
+
* Spawns a dedicated model thread whose init runs
|
|
2800
|
+
* [`create_random_qwen35_moe_checkpoint_sync`] (random-init inner + save);
|
|
2801
|
+
* the thread holds no state and is dropped once the promise resolves, so
|
|
2802
|
+
* the in-memory model is released as soon as the checkpoint has been
|
|
2803
|
+
* written. Used by TypeScript test fixtures that need an on-disk
|
|
2670
2804
|
* checkpoint without keeping a NAPI model instance alive.
|
|
2671
2805
|
*/
|
|
2672
2806
|
export declare function createRandomQwen35MoeCheckpoint(config: Qwen35MoeConfig, savePath: string): Promise<undefined>;
|
|
@@ -2717,6 +2851,8 @@ export declare const enum DType {
|
|
|
2717
2851
|
BFloat16 = 3,
|
|
2718
2852
|
Uint32 = 4,
|
|
2719
2853
|
Uint8 = 5,
|
|
2854
|
+
/** Signed int8 — sym8 per-output-channel symmetric quantized weights. */
|
|
2855
|
+
Int8 = 6,
|
|
2720
2856
|
}
|
|
2721
2857
|
|
|
2722
2858
|
/** Document element type */
|
|
@@ -2843,6 +2979,20 @@ export interface Gemma4Config {
|
|
|
2843
2979
|
/** Head dimension for global layers. If None, uses head_dim. */
|
|
2844
2980
|
globalHeadDim?: number;
|
|
2845
2981
|
attentionKEqV: boolean;
|
|
2982
|
+
/**
|
|
2983
|
+
* True for the unified multimodal Gemma 4 checkpoint
|
|
2984
|
+
* (`model_type == "gemma4_unified"` or
|
|
2985
|
+
* `architectures[0] == "Gemma4UnifiedForConditionalGeneration"`).
|
|
2986
|
+
* The text decoder is shared, but the unified checkpoint carries
|
|
2987
|
+
* vision/audio embedder weights that must be dropped in a text-only load.
|
|
2988
|
+
*/
|
|
2989
|
+
isUnified: boolean;
|
|
2990
|
+
/**
|
|
2991
|
+
* `text_config.use_bidirectional_attention` from the unified checkpoint
|
|
2992
|
+
* (e.g. `"vision"`). Parsed for a stable struct surface; the text-only
|
|
2993
|
+
* decode path does not consume it.
|
|
2994
|
+
*/
|
|
2995
|
+
useBidirectionalAttention?: string;
|
|
2846
2996
|
finalLogitSoftcapping?: number;
|
|
2847
2997
|
perLayerInputEmbeds: boolean;
|
|
2848
2998
|
hiddenSizePerLayerInput?: number;
|
|
@@ -2861,10 +3011,88 @@ export interface Gemma4Config {
|
|
|
2861
3011
|
topKExperts?: number;
|
|
2862
3012
|
moeIntermediateSize?: number;
|
|
2863
3013
|
visionConfig?: Gemma4VisionConfig;
|
|
3014
|
+
/**
|
|
3015
|
+
* Encoder-free vision config for the unified multimodal checkpoint.
|
|
3016
|
+
* `Some` only when `is_unified` and the checkpoint carries a
|
|
3017
|
+
* `vision_config` sub-dict. Disjoint from `vision_config` (the SigLIP
|
|
3018
|
+
* path) — the unified vision embedder is built from this instead.
|
|
3019
|
+
*/
|
|
3020
|
+
unifiedVisionConfig?: UnifiedVisionConfig;
|
|
2864
3021
|
imageTokenId?: number;
|
|
2865
3022
|
boiTokenId?: number;
|
|
2866
3023
|
eoiTokenId?: number;
|
|
2867
3024
|
visionSoftTokensPerImage?: number;
|
|
3025
|
+
/**
|
|
3026
|
+
* True when the checkpoint declares an `audio_config` sub-dict. Parallels
|
|
3027
|
+
* `unified_vision_config.is_some()`; gates the un-drop + load of
|
|
3028
|
+
* `embed_audio` weights and the audio merge path.
|
|
3029
|
+
*/
|
|
3030
|
+
hasAudio: boolean;
|
|
3031
|
+
/**
|
|
3032
|
+
* Audio placeholder token id (258881). Each `<audio>` placeholder expands to
|
|
3033
|
+
* `boa + audio_token × n_frames + eoa`.
|
|
3034
|
+
*/
|
|
3035
|
+
audioTokenId?: number;
|
|
3036
|
+
/** Begin-of-audio token id (256000), emitted before the audio token run. */
|
|
3037
|
+
boaTokenId?: number;
|
|
3038
|
+
/**
|
|
3039
|
+
* End-of-audio token id, parsed from the config's `eoa_token_index` (258883).
|
|
3040
|
+
* A real appended token (like `eoi`), despite the "index" name.
|
|
3041
|
+
*/
|
|
3042
|
+
eoaTokenId?: number;
|
|
3043
|
+
/**
|
|
3044
|
+
* Raw audio samples per audio token (640 = 40 ms @ 16 kHz), from
|
|
3045
|
+
* `audio_config.audio_samples_per_token`. Frame size for the encoder-free
|
|
3046
|
+
* pad+reshape feature extractor.
|
|
3047
|
+
*/
|
|
3048
|
+
audioSamplesPerToken?: number;
|
|
3049
|
+
/**
|
|
3050
|
+
* GPU memory budget for paged KV cache in megabytes.
|
|
3051
|
+
* Only used when `use_block_paged_cache` is true.
|
|
3052
|
+
* Default: auto-sized to cover `max_position_embeddings` for the
|
|
3053
|
+
* physical full-attention layers.
|
|
3054
|
+
*/
|
|
3055
|
+
pagedCacheMemoryMb?: number | undefined;
|
|
3056
|
+
/**
|
|
3057
|
+
* Block size for paged attention (tokens per block).
|
|
3058
|
+
* Only used when `use_block_paged_cache` is true.
|
|
3059
|
+
* Default: 16.
|
|
3060
|
+
*/
|
|
3061
|
+
pagedBlockSize?: number | undefined;
|
|
3062
|
+
/**
|
|
3063
|
+
* Use the new block-paged KV cache adapter (`PagedKVCacheAdapter`).
|
|
3064
|
+
*
|
|
3065
|
+
* When `Some(true)` or unset (the default), `Gemma4Inner` builds
|
|
3066
|
+
* model-independent KV-cache specs, groups them, and allocates a
|
|
3067
|
+
* `BlockAllocator` + `LayerKVPool` pair for physical full-attention
|
|
3068
|
+
* layers. Sliding-window layers still use `RotatingKVCache` until
|
|
3069
|
+
* true paged sliding-window groups are wired. KV-shared layers are
|
|
3070
|
+
* aliases: they reuse their anchor's cache slot and do not allocate
|
|
3071
|
+
* separate physical storage.
|
|
3072
|
+
*
|
|
3073
|
+
* Default: `true` (paged adapter on; opt-out via
|
|
3074
|
+
* `use_block_paged_cache: false` in `config.json` to use the flat
|
|
3075
|
+
* (non-paged) all-`Gemma4LayerCache` path instead). Parity between
|
|
3076
|
+
* the two paths is verified by
|
|
3077
|
+
* `crates/mlx-core/tests/gemma4_paged_vs_flat_parity.rs` against
|
|
3078
|
+
* real Gemma-4-E2B weights.
|
|
3079
|
+
*/
|
|
3080
|
+
useBlockPagedCache?: boolean | undefined;
|
|
3081
|
+
}
|
|
3082
|
+
|
|
3083
|
+
/** Optional load-time settings for [`Gemma4Model::load`]. */
|
|
3084
|
+
export interface Gemma4LoadOptions {
|
|
3085
|
+
/**
|
|
3086
|
+
* Directory of a draft checkpoint (config.json + safetensors) to load
|
|
3087
|
+
* alongside the target model for speculative decoding — either a
|
|
3088
|
+
* DSpark draft or a Google assistant draft; the kind is probed from
|
|
3089
|
+
* the draft config.json. When omitted, `<model_path>/draft/` is loaded
|
|
3090
|
+
* automatically when present. Draft decoding runs only on the flat
|
|
3091
|
+
* KV-cache path: setting this while the model config explicitly enables
|
|
3092
|
+
* `use_block_paged_cache` is a hard load error, and an unset
|
|
3093
|
+
* `use_block_paged_cache` is forced to `false`.
|
|
3094
|
+
*/
|
|
3095
|
+
draftModelPath?: string;
|
|
2868
3096
|
}
|
|
2869
3097
|
|
|
2870
3098
|
/**
|
|
@@ -2937,19 +3165,19 @@ export interface GenerationConfig {
|
|
|
2937
3165
|
/** Number of recent tokens to consider for frequency penalty (default: 20) */
|
|
2938
3166
|
frequencyContextSize?: number;
|
|
2939
3167
|
/**
|
|
2940
|
-
* Stop if same token repeats this many times consecutively (default:
|
|
2941
|
-
*
|
|
3168
|
+
* Stop if same token repeats this many times consecutively (default: 0 = disabled).
|
|
3169
|
+
* Opt in by setting a positive value to guard against degenerate repetitive generation.
|
|
2942
3170
|
*/
|
|
2943
3171
|
maxConsecutiveTokens?: number;
|
|
2944
3172
|
/**
|
|
2945
|
-
* Stop if a pattern repeats this many times consecutively (default:
|
|
2946
|
-
*
|
|
3173
|
+
* Stop if a pattern repeats this many times consecutively (default: 0 = disabled).
|
|
3174
|
+
* Opt in with a positive value to detect patterns like "A B A B A B".
|
|
2947
3175
|
* Uses range-based detection: checks all pattern sizes from 2 to ngram_size.
|
|
2948
3176
|
*/
|
|
2949
3177
|
maxNgramRepeats?: number;
|
|
2950
3178
|
/**
|
|
2951
|
-
* Maximum pattern size for repetition detection (default:
|
|
2952
|
-
*
|
|
3179
|
+
* Maximum pattern size for repetition detection (default: 0 = disabled).
|
|
3180
|
+
* When enabled, all pattern sizes from 2 up to this value are checked each decode step.
|
|
2953
3181
|
* Larger values catch long phrase-level repetition common in small models.
|
|
2954
3182
|
*/
|
|
2955
3183
|
ngramSize?: number;
|
|
@@ -2964,29 +3192,6 @@ export interface GenerationConfig {
|
|
|
2964
3192
|
* Set to 0 to disable chunking and process the entire prompt at once.
|
|
2965
3193
|
*/
|
|
2966
3194
|
prefillStepSize?: number;
|
|
2967
|
-
/**
|
|
2968
|
-
* KV cache quantization bits (default: 16 = no quantization)
|
|
2969
|
-
* - 16: Full precision (bfloat16/float16), no quantization
|
|
2970
|
-
* - 8: 8-bit quantization, ~2x memory savings, minimal quality loss
|
|
2971
|
-
* - 4: 4-bit quantization, ~4x memory savings, some quality degradation
|
|
2972
|
-
*
|
|
2973
|
-
* Quantized KV cache is useful for long sequences where memory becomes a bottleneck.
|
|
2974
|
-
* Note: Adds dequantization overhead per forward pass.
|
|
2975
|
-
*/
|
|
2976
|
-
kvCacheBits?: number;
|
|
2977
|
-
/**
|
|
2978
|
-
* KV cache quantization group size (default: 64)
|
|
2979
|
-
* Number of elements per quantization group. Smaller groups = better accuracy
|
|
2980
|
-
* but more overhead from storing scales/biases.
|
|
2981
|
-
* Only used when kv_cache_bits is 4 or 8.
|
|
2982
|
-
*/
|
|
2983
|
-
kvCacheGroupSize?: number;
|
|
2984
|
-
/**
|
|
2985
|
-
* Number of draft tokens to generate speculatively (default: 5)
|
|
2986
|
-
* Only used when a draft model is provided for speculative decoding.
|
|
2987
|
-
* Higher values can increase throughput but may reduce acceptance rate.
|
|
2988
|
-
*/
|
|
2989
|
-
numDraftTokens?: number;
|
|
2990
3195
|
}
|
|
2991
3196
|
|
|
2992
3197
|
export interface GenerationProfile {
|
|
@@ -3010,6 +3215,24 @@ export interface GenerationProfile {
|
|
|
3010
3215
|
timeToFirstTokenMs: number;
|
|
3011
3216
|
/** Per-phase breakdown. */
|
|
3012
3217
|
phases: Array<PhaseProfile>;
|
|
3218
|
+
/**
|
|
3219
|
+
* MTP speculative decode: mean accepted *draft* tokens per cycle
|
|
3220
|
+
* (excludes the always-verified token). Historical drafts-only metric.
|
|
3221
|
+
*/
|
|
3222
|
+
mtpMeanAcceptedTokens?: number;
|
|
3223
|
+
/**
|
|
3224
|
+
* MTP speculative decode: mean *committed* tokens per cycle, INCLUDING
|
|
3225
|
+
* the always-verified token (`mtp_accepted_drafts_total / mtp_cycles
|
|
3226
|
+
* + 1.0`). mlx-vlm-comparable headline; equals mlx-vlm's
|
|
3227
|
+
* `(accepted_drafts + rounds) / rounds` (`common.py:247`).
|
|
3228
|
+
*/
|
|
3229
|
+
mtpMeanAcceptedTokensTotal?: number;
|
|
3230
|
+
/** MTP speculative decode: per-draft-position acceptance rate. */
|
|
3231
|
+
mtpAcceptanceByPosition?: Array<number>;
|
|
3232
|
+
/** MTP speculative decode: number of draft+verify cycles executed. */
|
|
3233
|
+
mtpCycles?: number;
|
|
3234
|
+
/** MTP speculative decode: mean attempted draft depth per cycle. */
|
|
3235
|
+
mtpMeanDepth?: number;
|
|
3013
3236
|
/** Memory snapshot before generation. */
|
|
3014
3237
|
memoryBefore?: MemorySnapshot;
|
|
3015
3238
|
/** Memory snapshot after generation. */
|
|
@@ -3036,8 +3259,8 @@ export interface GenerationWithToolCalls {
|
|
|
3036
3259
|
toolCalls: Array<ToolCallRecord>;
|
|
3037
3260
|
}
|
|
3038
3261
|
|
|
3039
|
-
/**
|
|
3040
|
-
export declare function
|
|
3262
|
+
/** Sample MLX's GPU memory counters. See [`GpuMemorySnapshot`]. */
|
|
3263
|
+
export declare function getMemorySnapshot(): GpuMemorySnapshot;
|
|
3041
3264
|
|
|
3042
3265
|
/** Retrieve all collected profiling data as a `ProfilingSession`. */
|
|
3043
3266
|
export declare function getProfilingData(): ProfilingSession;
|
|
@@ -3047,6 +3270,13 @@ export interface GgufConversionOptions {
|
|
|
3047
3270
|
inputPath: string;
|
|
3048
3271
|
/** Output directory for converted SafeTensors model */
|
|
3049
3272
|
outputDir: string;
|
|
3273
|
+
/**
|
|
3274
|
+
* Optional directory containing the authoritative HuggingFace config and
|
|
3275
|
+
* tokenizer/processor assets. GGUF metadata is not rich enough to recreate
|
|
3276
|
+
* unified Gemma4 config fields such as head_dim, layer_types, vision, and
|
|
3277
|
+
* audio configuration exactly.
|
|
3278
|
+
*/
|
|
3279
|
+
configSourceDir?: string;
|
|
3050
3280
|
/** Target dtype: "float32", "float16", "bfloat16" (default: keep original) */
|
|
3051
3281
|
dtype?: string;
|
|
3052
3282
|
/** Enable verbose logging */
|
|
@@ -3080,6 +3310,17 @@ export interface GgufConversionOptions {
|
|
|
3080
3310
|
* This makes the safetensors compatible with mlx-vlm.
|
|
3081
3311
|
*/
|
|
3082
3312
|
vlmKeyPrefix?: boolean;
|
|
3313
|
+
/**
|
|
3314
|
+
* Upgrade quantization to micro-scaling FP (mxfp4 / mxfp8).
|
|
3315
|
+
* When true, applies after the recipe predicate: eligible 8-bit affine
|
|
3316
|
+
* decisions become mxfp8 and 4-bit become mxfp4. Kept affine (not upgraded):
|
|
3317
|
+
* affine-only loaders (lm_head, embed_tokens, router.proj,
|
|
3318
|
+
* embedding_projection) at their recipe bits, MoE router gates (8-bit affine),
|
|
3319
|
+
* and the recipe-pinned attention/GDN projections (o_proj / out_proj /
|
|
3320
|
+
* in_proj_a / in_proj_b, 8-bit affine). Requires `quant_mode = "affine"`.
|
|
3321
|
+
* Forces `group_size = 32` for upgraded layers.
|
|
3322
|
+
*/
|
|
3323
|
+
quantMxfp?: boolean;
|
|
3083
3324
|
}
|
|
3084
3325
|
|
|
3085
3326
|
export interface GgufConversionResult {
|
|
@@ -3095,6 +3336,33 @@ export interface GpuInfo {
|
|
|
3095
3336
|
architectureGen: number;
|
|
3096
3337
|
}
|
|
3097
3338
|
|
|
3339
|
+
/**
|
|
3340
|
+
* Snapshot of MLX's GPU memory counters at this instant. All values
|
|
3341
|
+
* are in bytes. On Apple Silicon, GPU and CPU share unified memory,
|
|
3342
|
+
* so these are NOT a separate "VRAM" pool — they reflect MLX's own
|
|
3343
|
+
* tracking of `StorageModePrivate` Metal buffers (model weights,
|
|
3344
|
+
* `LayerKVPool`, transient intermediate tensors) attributed to the
|
|
3345
|
+
* MLX runtime in this process.
|
|
3346
|
+
*
|
|
3347
|
+
* Useful for live observability during long-running sessions:
|
|
3348
|
+
*
|
|
3349
|
+
* ```js
|
|
3350
|
+
* const { getMemorySnapshot } = require('@mlx-node/core');
|
|
3351
|
+
* setInterval(() => {
|
|
3352
|
+
* const m = getMemorySnapshot();
|
|
3353
|
+
* console.log(`active=${(m.activeBytes/1e9).toFixed(2)}GB peak=${(m.peakBytes/1e9).toFixed(2)}GB cache=${(m.cacheBytes/1e9).toFixed(2)}GB`);
|
|
3354
|
+
* }, 1000);
|
|
3355
|
+
* ```
|
|
3356
|
+
*/
|
|
3357
|
+
export interface GpuMemorySnapshot {
|
|
3358
|
+
/** Current actively-used GPU buffer bytes (excludes cache pool). */
|
|
3359
|
+
activeBytes: number;
|
|
3360
|
+
/** Peak GPU buffer bytes since the last `resetPeakMemory()` call. */
|
|
3361
|
+
peakBytes: number;
|
|
3362
|
+
/** Bytes held in MLX's caching allocator (released by `clearCache`). */
|
|
3363
|
+
cacheBytes: number;
|
|
3364
|
+
}
|
|
3365
|
+
|
|
3098
3366
|
/** Configuration for the GRPO training engine */
|
|
3099
3367
|
export interface GrpoEngineConfig {
|
|
3100
3368
|
/** Learning rate (default: 1e-6) */
|
|
@@ -3356,6 +3624,69 @@ export interface Lfm2Config {
|
|
|
3356
3624
|
eosTokenId: number;
|
|
3357
3625
|
bosTokenId: number;
|
|
3358
3626
|
padTokenId: number;
|
|
3627
|
+
/**
|
|
3628
|
+
* GPU memory budget for paged KV cache in megabytes.
|
|
3629
|
+
* Only used when `use_block_paged_cache` is true.
|
|
3630
|
+
* Default: 2048 (2GB).
|
|
3631
|
+
*/
|
|
3632
|
+
pagedCacheMemoryMb?: number | undefined;
|
|
3633
|
+
/**
|
|
3634
|
+
* Block size for paged attention (tokens per block).
|
|
3635
|
+
* Only used when `use_block_paged_cache` is true.
|
|
3636
|
+
* Default: 16.
|
|
3637
|
+
*/
|
|
3638
|
+
pagedBlockSize?: number | undefined;
|
|
3639
|
+
/**
|
|
3640
|
+
* Use the new block-paged KV cache adapter (`PagedKVCacheAdapter`).
|
|
3641
|
+
*
|
|
3642
|
+
* Default: `true` since 2026-04-28 (parity-verified via
|
|
3643
|
+
* `crates/mlx-core/tests/lfm2_paged_vs_flat_parity.rs` against real
|
|
3644
|
+
* LFM2.5-1.2B weights: byte-equal greedy decode + prefix-reuse
|
|
3645
|
+
* byte-equal at BF16). Wired through
|
|
3646
|
+
* `Lfm2DecoderLayer::forward_paged_or_flat`.
|
|
3647
|
+
*
|
|
3648
|
+
* Per-layer routing: LFM2's hybrid architecture means only
|
|
3649
|
+
* `full_attention` layers go through the paged adapter; conv layers
|
|
3650
|
+
* stay on the existing flat `Lfm2LayerCache::Conv(ArraysCache)`
|
|
3651
|
+
* storage regardless of this flag. The `LayerKVPool` is sized to
|
|
3652
|
+
* the count of `full_attention` layers and indexed by
|
|
3653
|
+
* attention-ordinal (via `config.full_attn_idxs()`), not by absolute
|
|
3654
|
+
* layer index.
|
|
3655
|
+
*
|
|
3656
|
+
* Opt out with `use_block_paged_cache: Some(false)` to revert to the
|
|
3657
|
+
* fully flat `Lfm2LayerCache` path on all layers.
|
|
3658
|
+
*/
|
|
3659
|
+
useBlockPagedCache?: boolean | undefined;
|
|
3660
|
+
/**
|
|
3661
|
+
* MLP intermediate size for the DENSE-in-MoE layers (`layer_idx <
|
|
3662
|
+
* num_dense_layers`). Used DIRECTLY (no 2/3 `computed_ff_dim()` shrink).
|
|
3663
|
+
* Only present on MoE checkpoints.
|
|
3664
|
+
*/
|
|
3665
|
+
intermediateSize?: number | undefined;
|
|
3666
|
+
/** Per-expert MLP intermediate size for the sparse MoE layers. */
|
|
3667
|
+
moeIntermediateSize?: number | undefined;
|
|
3668
|
+
/** Total number of routed experts. */
|
|
3669
|
+
numExperts?: number | undefined;
|
|
3670
|
+
/** Top-k experts selected per token. */
|
|
3671
|
+
numExpertsPerTok?: number | undefined;
|
|
3672
|
+
/** Number of leading DENSE layers before MoE layers begin. */
|
|
3673
|
+
numDenseLayers?: number | undefined;
|
|
3674
|
+
/**
|
|
3675
|
+
* Renormalize the top-k routing weights to sum to 1 (`/(sum+1e-20)`).
|
|
3676
|
+
*
|
|
3677
|
+
* `Option<bool>` so TS callers may omit it (napi renders bare `bool` as
|
|
3678
|
+
* required). Absent (None) is read as `true` everywhere via
|
|
3679
|
+
* `.unwrap_or(true)`, matching the prior `default = "default_true"`.
|
|
3680
|
+
*/
|
|
3681
|
+
normTopkProb?: boolean | undefined;
|
|
3682
|
+
/**
|
|
3683
|
+
* Add the learned per-expert bias to the post-softmax gates BEFORE top-k.
|
|
3684
|
+
*
|
|
3685
|
+
* `Option<bool>` so TS callers may omit it (napi renders bare `bool` as
|
|
3686
|
+
* required). Absent (None) is read as `true` everywhere via
|
|
3687
|
+
* `.unwrap_or(true)`, matching the prior `default = "default_true"`.
|
|
3688
|
+
*/
|
|
3689
|
+
useExpertBias?: boolean | undefined;
|
|
3359
3690
|
}
|
|
3360
3691
|
|
|
3361
3692
|
export interface MemorySnapshot {
|
|
@@ -3367,6 +3698,28 @@ export interface MemorySnapshot {
|
|
|
3367
3698
|
cacheBytes: number;
|
|
3368
3699
|
}
|
|
3369
3700
|
|
|
3701
|
+
/**
|
|
3702
|
+
* Return a snapshot of the MLX allocator's memory counters. Primarily
|
|
3703
|
+
* useful for dashboards and for debugging the `MLX_CACHE_LIMIT_GB`
|
|
3704
|
+
* override. Read-only — does not mutate allocator state.
|
|
3705
|
+
*/
|
|
3706
|
+
export declare function memoryStats(): MemoryStats;
|
|
3707
|
+
|
|
3708
|
+
/**
|
|
3709
|
+
* Snapshot of the MLX Metal allocator's memory state. All values are in
|
|
3710
|
+
* bytes and returned as `f64` to avoid forcing BigInt round-trips in JS.
|
|
3711
|
+
*/
|
|
3712
|
+
export interface MemoryStats {
|
|
3713
|
+
/** Actively-used memory (excludes the cached free-pool). */
|
|
3714
|
+
active: number;
|
|
3715
|
+
/** Peak memory usage since load / the last `resetPeakMemory`. */
|
|
3716
|
+
peak: number;
|
|
3717
|
+
/** Cache / free-pool memory currently held by the allocator. */
|
|
3718
|
+
cache: number;
|
|
3719
|
+
/** Metal `max_recommended_working_set_size` snapshot (0 on non-Metal). */
|
|
3720
|
+
wiredLimit: number;
|
|
3721
|
+
}
|
|
3722
|
+
|
|
3370
3723
|
/** Full model configuration */
|
|
3371
3724
|
export interface ModelConfig {
|
|
3372
3725
|
visionConfig: VisionConfig;
|
|
@@ -3410,56 +3763,6 @@ export interface OutputStoreConfig {
|
|
|
3410
3763
|
localPath: string;
|
|
3411
3764
|
}
|
|
3412
3765
|
|
|
3413
|
-
/** Paged attention memory statistics (NAPI-compatible) */
|
|
3414
|
-
export interface PagedCacheStats {
|
|
3415
|
-
/** Total number of blocks in the pool */
|
|
3416
|
-
totalBlocks: number;
|
|
3417
|
-
/** Number of free blocks */
|
|
3418
|
-
freeBlocks: number;
|
|
3419
|
-
/** Number of allocated blocks */
|
|
3420
|
-
allocatedBlocks: number;
|
|
3421
|
-
/** Total memory in MB */
|
|
3422
|
-
totalMemoryMb: number;
|
|
3423
|
-
/** Used memory in MB */
|
|
3424
|
-
usedMemoryMb: number;
|
|
3425
|
-
/** Utilization percentage */
|
|
3426
|
-
utilizationPercent: number;
|
|
3427
|
-
}
|
|
3428
|
-
|
|
3429
|
-
/** A completed sequence from paged generation */
|
|
3430
|
-
export interface PagedCompletedSequence {
|
|
3431
|
-
/** Original request ID */
|
|
3432
|
-
requestId: string;
|
|
3433
|
-
/** All generated tokens (excluding prompt) */
|
|
3434
|
-
tokens: Array<number>;
|
|
3435
|
-
/** Reason for completion ("stop", "length", "repetition", "tool_calls") */
|
|
3436
|
-
finishReason: string;
|
|
3437
|
-
}
|
|
3438
|
-
|
|
3439
|
-
/** Result of a paged generation step */
|
|
3440
|
-
export interface PagedGenerationStep {
|
|
3441
|
-
/** Token outputs for each sequence in the batch */
|
|
3442
|
-
outputs: Array<PagedTokenOutput>;
|
|
3443
|
-
/** Number of sequences that were in prefill phase */
|
|
3444
|
-
numPrefill: number;
|
|
3445
|
-
/** Number of sequences that were in decode phase */
|
|
3446
|
-
numDecode: number;
|
|
3447
|
-
}
|
|
3448
|
-
|
|
3449
|
-
/** Output from a single token generation step in paged attention */
|
|
3450
|
-
export interface PagedTokenOutput {
|
|
3451
|
-
/** Sequence ID in the scheduler */
|
|
3452
|
-
seqId: number;
|
|
3453
|
-
/** Request ID for this sequence */
|
|
3454
|
-
requestId: string;
|
|
3455
|
-
/** Generated token ID */
|
|
3456
|
-
token: number;
|
|
3457
|
-
/** Log probability of the token (f64 for NAPI compatibility) */
|
|
3458
|
-
logprob: number;
|
|
3459
|
-
/** Whether this sequence has finished */
|
|
3460
|
-
isFinished: boolean;
|
|
3461
|
-
}
|
|
3462
|
-
|
|
3463
3766
|
/** A text paragraph */
|
|
3464
3767
|
export interface Paragraph {
|
|
3465
3768
|
content: string;
|
|
@@ -3541,6 +3844,52 @@ export interface PerformanceMetrics {
|
|
|
3541
3844
|
* Excludes the first token (counted as prefill).
|
|
3542
3845
|
*/
|
|
3543
3846
|
decodeTokensPerSecond: number;
|
|
3847
|
+
/**
|
|
3848
|
+
* MTP speculative decode: mean accepted *draft* tokens per cycle
|
|
3849
|
+
* (range `[0, depth]`). EXCLUDES the always-verified token each cycle
|
|
3850
|
+
* commits. `None` on plain autoregressive runs where no MTP cycle
|
|
3851
|
+
* executed. This is the historical drafts-only metric; for the
|
|
3852
|
+
* mlx-vlm-comparable headline see [`Self::mtp_mean_accepted_tokens_total`].
|
|
3853
|
+
*/
|
|
3854
|
+
mtpMeanAcceptedTokens?: number;
|
|
3855
|
+
/**
|
|
3856
|
+
* MTP speculative decode: mean *committed* tokens per cycle, INCLUDING
|
|
3857
|
+
* the single always-verified token each cycle emits — i.e.
|
|
3858
|
+
* `mtp_accepted_drafts_total / mtp_cycles + 1.0`. This is the
|
|
3859
|
+
* mlx-vlm-comparable headline accept rate: it equals mlx-vlm's
|
|
3860
|
+
* `mean_accepted_tokens = (accepted_drafts + rounds) / rounds`
|
|
3861
|
+
* (`mlx-vlm/mlx_vlm/speculative/common.py:247`), where our
|
|
3862
|
+
* `mtp_cycles` is the 1:1 analog of mlx-vlm's `rounds` (one
|
|
3863
|
+
* draft+verify iteration; `record_mtp_cycle` is called exactly once
|
|
3864
|
+
* per cycle). The per-cycle `+1.0` matches mlx-vlm's `+rounds`
|
|
3865
|
+
* assumption — every round commits exactly one verified token
|
|
3866
|
+
* (the residual on partial-accept, the bonus on full-accept), even
|
|
3867
|
+
* when the final cycle's tail is EOS/length-truncated downstream
|
|
3868
|
+
* (mlx-vlm makes the same assumption: it appends to `accept_lens`
|
|
3869
|
+
* once per round regardless of truncation). `None` on plain
|
|
3870
|
+
* autoregressive runs.
|
|
3871
|
+
*/
|
|
3872
|
+
mtpMeanAcceptedTokensTotal?: number;
|
|
3873
|
+
/**
|
|
3874
|
+
* MTP speculative decode: per-draft-position acceptance rate
|
|
3875
|
+
* (index = draft position). `None` on plain autoregressive runs.
|
|
3876
|
+
*/
|
|
3877
|
+
mtpAcceptanceByPosition?: Array<number>;
|
|
3878
|
+
/**
|
|
3879
|
+
* MTP speculative decode: number of draft+verify cycles executed.
|
|
3880
|
+
* `None` on plain autoregressive runs.
|
|
3881
|
+
*/
|
|
3882
|
+
mtpCycles?: number;
|
|
3883
|
+
/**
|
|
3884
|
+
* MTP speculative decode: mean attempted draft depth per cycle.
|
|
3885
|
+
* `None` on plain autoregressive runs.
|
|
3886
|
+
*/
|
|
3887
|
+
mtpMeanDepth?: number;
|
|
3888
|
+
/**
|
|
3889
|
+
* Optional decode phase breakdown. Present when decode profiling
|
|
3890
|
+
* is enabled via `MLX_PROFILE_DECODE=1` or `setProfilingEnabled(true)`.
|
|
3891
|
+
*/
|
|
3892
|
+
profilePhases?: Array<PhaseProfile>;
|
|
3544
3893
|
}
|
|
3545
3894
|
|
|
3546
3895
|
export interface PhaseProfile {
|
|
@@ -3554,6 +3903,76 @@ export interface PhaseProfile {
|
|
|
3554
3903
|
count: number;
|
|
3555
3904
|
}
|
|
3556
3905
|
|
|
3906
|
+
/**
|
|
3907
|
+
* Per-call Viterbi calibration overrides.
|
|
3908
|
+
*
|
|
3909
|
+
* Any field set to `Some(_)` overrides the corresponding bias from the
|
|
3910
|
+
* model's default calibration (loaded from `viterbi_calibration.json`
|
|
3911
|
+
* at load time). Missing fields fall back to the default.
|
|
3912
|
+
*/
|
|
3913
|
+
export interface PrivacyCalibration {
|
|
3914
|
+
transitionBiasBackgroundStay?: number;
|
|
3915
|
+
transitionBiasBackgroundToStart?: number;
|
|
3916
|
+
transitionBiasEndToBackground?: number;
|
|
3917
|
+
transitionBiasEndToStart?: number;
|
|
3918
|
+
transitionBiasInsideToContinue?: number;
|
|
3919
|
+
transitionBiasInsideToEnd?: number;
|
|
3920
|
+
}
|
|
3921
|
+
|
|
3922
|
+
/**
|
|
3923
|
+
* Options for [`PrivacyFilterModelJs::classify`].
|
|
3924
|
+
*
|
|
3925
|
+
* - `threshold` (default `0.5`): minimum mean per-token probability for
|
|
3926
|
+
* an extracted span to be returned.
|
|
3927
|
+
* - `calibration`: per-call overrides on top of the checkpoint default.
|
|
3928
|
+
* - `return_tokens` (default `false`): when `true`, the result includes
|
|
3929
|
+
* a `tokens` array with one entry per input token.
|
|
3930
|
+
*/
|
|
3931
|
+
export interface PrivacyClassifyOptions {
|
|
3932
|
+
threshold?: number;
|
|
3933
|
+
calibration?: PrivacyCalibration;
|
|
3934
|
+
returnTokens?: boolean;
|
|
3935
|
+
}
|
|
3936
|
+
|
|
3937
|
+
/** Result of [`PrivacyFilterModelJs::classify`]. */
|
|
3938
|
+
export interface PrivacyClassifyResult {
|
|
3939
|
+
entities: Array<PrivacyEntity>;
|
|
3940
|
+
tokens?: Array<PrivacyToken>;
|
|
3941
|
+
}
|
|
3942
|
+
|
|
3943
|
+
/**
|
|
3944
|
+
* A privacy entity detected by [`PrivacyFilterModelJs::classify`].
|
|
3945
|
+
*
|
|
3946
|
+
* `start`/`end` are byte offsets into the input string (Hugging Face
|
|
3947
|
+
* `tokenizers` convention). `label` is the privacy class without the
|
|
3948
|
+
* BIOES prefix (e.g. `"private_email"`). `score` is the mean — across
|
|
3949
|
+
* the span's tokens — of the softmax probability of the Viterbi-emitted
|
|
3950
|
+
* tag at each token.
|
|
3951
|
+
*/
|
|
3952
|
+
export interface PrivacyEntity {
|
|
3953
|
+
label: string;
|
|
3954
|
+
start: number;
|
|
3955
|
+
end: number;
|
|
3956
|
+
score: number;
|
|
3957
|
+
text: string;
|
|
3958
|
+
}
|
|
3959
|
+
|
|
3960
|
+
/**
|
|
3961
|
+
* Per-token output emitted when [`PrivacyClassifyOptions::return_tokens`]
|
|
3962
|
+
* is `true`. `tag` is the full BIOES tag (`"O"` or `"B-..."`/`"I-..."`/
|
|
3963
|
+
* `"E-..."`/`"S-..."`) chosen by the Viterbi decoder. `score` is the
|
|
3964
|
+
* softmax probability of that emitted tag at this token, so `tag` and
|
|
3965
|
+
* `score` always share decoders (at boundary tokens the Viterbi tag can
|
|
3966
|
+
* differ from the local argmax).
|
|
3967
|
+
*/
|
|
3968
|
+
export interface PrivacyToken {
|
|
3969
|
+
text: string;
|
|
3970
|
+
tag: string;
|
|
3971
|
+
score: number;
|
|
3972
|
+
start: number;
|
|
3973
|
+
end: number;
|
|
3974
|
+
}
|
|
3975
|
+
|
|
3557
3976
|
export interface ProfilingSession {
|
|
3558
3977
|
/** GPU hardware info. */
|
|
3559
3978
|
gpuInfo: GpuInfo;
|
|
@@ -3601,6 +4020,32 @@ export interface QianfanOcrConfig {
|
|
|
3601
4020
|
minDynamicPatch: number;
|
|
3602
4021
|
}
|
|
3603
4022
|
|
|
4023
|
+
/** Microbench result for the production quantized qmv dispatch path. */
|
|
4024
|
+
export interface QmvQuantizedMicrobenchResult {
|
|
4025
|
+
/** Median `quantized_matmul` wall-clock per call, in nanoseconds. */
|
|
4026
|
+
medianNs: number;
|
|
4027
|
+
/** A tiny materialized checksum of the final output, used to keep the call live. */
|
|
4028
|
+
checksum: number;
|
|
4029
|
+
}
|
|
4030
|
+
|
|
4031
|
+
/**
|
|
4032
|
+
* Run the production quantized-qmv microbench in the current process.
|
|
4033
|
+
*
|
|
4034
|
+
* To compare `MLX_MTP_SMALL_M_QMV=0` versus `1`, call this from separate
|
|
4035
|
+
* processes. MLX caches the env-backed dispatch predicate statically.
|
|
4036
|
+
*/
|
|
4037
|
+
export declare function quantizedQmvMicrobench(
|
|
4038
|
+
k: number,
|
|
4039
|
+
n: number,
|
|
4040
|
+
m: number,
|
|
4041
|
+
groupSize: number,
|
|
4042
|
+
bits: number,
|
|
4043
|
+
mode: string,
|
|
4044
|
+
dtype: DType,
|
|
4045
|
+
warmup?: number | undefined | null,
|
|
4046
|
+
iters?: number | undefined | null,
|
|
4047
|
+
): QmvQuantizedMicrobenchResult;
|
|
4048
|
+
|
|
3604
4049
|
/**
|
|
3605
4050
|
* Qwen3.5 model configuration (dense variant).
|
|
3606
4051
|
*
|
|
@@ -3629,6 +4074,72 @@ export interface Qwen35Config {
|
|
|
3629
4074
|
fullAttentionInterval: number;
|
|
3630
4075
|
partialRotaryFactor: number;
|
|
3631
4076
|
ropeTheta: number;
|
|
4077
|
+
/**
|
|
4078
|
+
* GPU memory budget for paged KV cache in megabytes.
|
|
4079
|
+
* Only used when `use_block_paged_cache` is true.
|
|
4080
|
+
* Default: automatically sized for one full-context sequence.
|
|
4081
|
+
*/
|
|
4082
|
+
pagedCacheMemoryMb?: number | undefined;
|
|
4083
|
+
/**
|
|
4084
|
+
* Block size for paged attention (tokens per block).
|
|
4085
|
+
* Only used when `use_block_paged_cache` is true.
|
|
4086
|
+
* Default: 16.
|
|
4087
|
+
*/
|
|
4088
|
+
pagedBlockSize?: number | undefined;
|
|
4089
|
+
/**
|
|
4090
|
+
* Use the block-paged KV cache adapter (`PagedKVCacheAdapter`) for
|
|
4091
|
+
* full-attention layers.
|
|
4092
|
+
*
|
|
4093
|
+
* **OPT-IN — experimental.** When `Some(true)`, `Qwen35Inner`
|
|
4094
|
+
* allocates a `BlockAllocator` + `LayerKVPool` pair sized for the
|
|
4095
|
+
* model's full-attention layer count and constructs a
|
|
4096
|
+
* `PagedKVCacheAdapter`. The chat-session forward dispatch routes
|
|
4097
|
+
* full-attention layers through this adapter while linear-attention
|
|
4098
|
+
* (GatedDeltaNet / GDN) layers continue to use the existing
|
|
4099
|
+
* `Qwen3_5LayerCache::Linear(ArraysCache)` path with no
|
|
4100
|
+
* cross-request prefix reuse — vLLM's `MambaManager`-style "no
|
|
4101
|
+
* prefix reuse for recurrent layers" stance.
|
|
4102
|
+
*
|
|
4103
|
+
* **Paged vs flat eager**: this flag selects the eager paged decode
|
|
4104
|
+
* over the eager flat decode. When `Some(true)`, full-attention
|
|
4105
|
+
* layers run through the paged adapter (cross-request prefix reuse);
|
|
4106
|
+
* when unset, they run the eager flat decode. Either way the forward
|
|
4107
|
+
* is pure-Rust eager.
|
|
4108
|
+
*
|
|
4109
|
+
* **VLM under paged**: a VLM checkpoint defaults this flag ON at load, so
|
|
4110
|
+
* dense image turns ONLY run on the paged-vision core. A fresh single-turn
|
|
4111
|
+
* image-bearing prompt prefills through the paged adapter (M-RoPE positions
|
|
4112
|
+
* feed the rotary; the merged vision embeddings feed the forward) and
|
|
4113
|
+
* decodes plain AR — MTP weights are ignored on image turns. Warm
|
|
4114
|
+
* image-bearing session continues / cache-hit reuse are still rejected at
|
|
4115
|
+
* runtime (the GDN two-pass warm prefix is not byte-exact). A vision turn
|
|
4116
|
+
* that reaches a None adapter (explicit `Some(false)`, non-Metal build, or
|
|
4117
|
+
* a sym8 checkpoint) errors at dispatch.
|
|
4118
|
+
*
|
|
4119
|
+
* Default: `None` for text-only checkpoints (eager flat decode);
|
|
4120
|
+
* `Some(true)` for VLM checkpoints (block-paged, set in `parse_config`).
|
|
4121
|
+
*/
|
|
4122
|
+
useBlockPagedCache?: boolean | undefined;
|
|
4123
|
+
/**
|
|
4124
|
+
* Number of MTP (Multi-Token Prediction) head layers shipped with the
|
|
4125
|
+
* checkpoint. Populated from `mtp_num_hidden_layers` /
|
|
4126
|
+
* `num_nextn_predict_layers` in `config.json`. `0` means the
|
|
4127
|
+
* checkpoint has no MTP heads and the speculative-decode path is
|
|
4128
|
+
* unavailable.
|
|
4129
|
+
*/
|
|
4130
|
+
nMtpLayers: number;
|
|
4131
|
+
}
|
|
4132
|
+
|
|
4133
|
+
/**
|
|
4134
|
+
* Trained and physically available active-context limits for one loaded
|
|
4135
|
+
* Qwen3.5 model. Values are snapshots because the physical pool is fixed for
|
|
4136
|
+
* the lifetime of the resident model.
|
|
4137
|
+
*/
|
|
4138
|
+
export interface Qwen35ContextLimits {
|
|
4139
|
+
trainedWindowTokens: number;
|
|
4140
|
+
effectiveWindowTokens: number;
|
|
4141
|
+
pagedBlockCapacity: number;
|
|
4142
|
+
pagedBlockSize: number;
|
|
3632
4143
|
}
|
|
3633
4144
|
|
|
3634
4145
|
/** Generation configuration for Qwen3.5 */
|
|
@@ -3683,6 +4194,47 @@ export interface Qwen35MoeConfig {
|
|
|
3683
4194
|
moeIntermediateSize?: number | undefined;
|
|
3684
4195
|
normTopkProb: boolean;
|
|
3685
4196
|
mlpOnlyLayers?: number[] | undefined;
|
|
4197
|
+
/**
|
|
4198
|
+
* GPU memory budget for paged KV cache in megabytes.
|
|
4199
|
+
* Only used when `use_block_paged_cache` is true.
|
|
4200
|
+
* Default: automatically sized for one full-context sequence.
|
|
4201
|
+
*/
|
|
4202
|
+
pagedCacheMemoryMb?: number | undefined;
|
|
4203
|
+
/**
|
|
4204
|
+
* Block size for paged attention (tokens per block).
|
|
4205
|
+
* Only used when `use_block_paged_cache` is true.
|
|
4206
|
+
* Default: 16.
|
|
4207
|
+
*/
|
|
4208
|
+
pagedBlockSize?: number | undefined;
|
|
4209
|
+
/**
|
|
4210
|
+
* Use the block-paged KV cache adapter for full-attention layers.
|
|
4211
|
+
*
|
|
4212
|
+
* **OPT-IN — experimental.** Same semantics as the dense
|
|
4213
|
+
* `Qwen3_5Config::use_block_paged_cache` field. Selects the eager
|
|
4214
|
+
* paged decode over the eager flat decode: routes full-attention
|
|
4215
|
+
* layers through `PagedKVCacheAdapter` (cross-request prefix reuse);
|
|
4216
|
+
* GDN linear-attention layers stay on `Qwen3_5LayerCache::Linear`
|
|
4217
|
+
* either way. When disabled, full-attention layers run the eager flat
|
|
4218
|
+
* decode instead.
|
|
4219
|
+
*
|
|
4220
|
+
* **VLM under paged**: a VLM checkpoint loads with this flag set, and a
|
|
4221
|
+
* fresh single-turn image-bearing prompt prefills through the paged
|
|
4222
|
+
* adapter (M-RoPE positions feed the rotary; the merged vision embeddings
|
|
4223
|
+
* feed the forward). Image-bearing MTP turns are still rejected at
|
|
4224
|
+
* runtime; warm image-bearing session continues / cache-hit reuse are
|
|
4225
|
+
* cold-started (no warm GDN two-pass prefix).
|
|
4226
|
+
*
|
|
4227
|
+
* Default: `None` / `false`.
|
|
4228
|
+
*/
|
|
4229
|
+
useBlockPagedCache?: boolean | undefined;
|
|
4230
|
+
/**
|
|
4231
|
+
* Number of MTP (Multi-Token Prediction) head layers shipped with
|
|
4232
|
+
* the checkpoint. Populated from `mtp_num_hidden_layers` /
|
|
4233
|
+
* `num_nextn_predict_layers` in `config.json`. `0` means the
|
|
4234
|
+
* checkpoint has no MTP heads and the speculative-decode path is
|
|
4235
|
+
* unavailable.
|
|
4236
|
+
*/
|
|
4237
|
+
nMtpLayers: number;
|
|
3686
4238
|
}
|
|
3687
4239
|
|
|
3688
4240
|
/** Generation configuration for Qwen3.5 MoE */
|
|
@@ -3719,29 +4271,29 @@ export interface Qwen3Config {
|
|
|
3719
4271
|
padTokenId: number;
|
|
3720
4272
|
eosTokenId: number;
|
|
3721
4273
|
bosTokenId: number;
|
|
3722
|
-
/**
|
|
3723
|
-
* Enable paged attention for memory-efficient inference.
|
|
3724
|
-
* Default: false (use standard KVCache)
|
|
3725
|
-
*/
|
|
3726
|
-
usePagedAttention?: boolean | undefined;
|
|
3727
4274
|
/**
|
|
3728
4275
|
* GPU memory budget for paged KV cache in megabytes.
|
|
3729
|
-
* Only used when use_paged_attention is true.
|
|
3730
4276
|
* Default: 2048 (2GB)
|
|
3731
4277
|
*/
|
|
3732
4278
|
pagedCacheMemoryMb?: number | undefined;
|
|
3733
4279
|
/**
|
|
3734
4280
|
* Block size for paged attention (tokens per block).
|
|
3735
|
-
* Only used when use_paged_attention is true.
|
|
3736
4281
|
* Default: 16
|
|
3737
4282
|
*/
|
|
3738
4283
|
pagedBlockSize?: number | undefined;
|
|
3739
4284
|
/**
|
|
3740
|
-
* Use
|
|
3741
|
-
*
|
|
3742
|
-
*
|
|
4285
|
+
* Use the block-paged KV cache adapter (`PagedKVCacheAdapter`).
|
|
4286
|
+
*
|
|
4287
|
+
* When `Some(true)` (the default for Qwen3), `Qwen3Inner` allocates a
|
|
4288
|
+
* `BlockAllocator` + `LayerKVPool` pair and constructs a
|
|
4289
|
+
* `PagedKVCacheAdapter` for cross-request KV prefix reuse (vLLM-style
|
|
4290
|
+
* block-paged storage with refcounted prefix caching). When
|
|
4291
|
+
* `Some(false)`, the flat (non-paged) `Vec<KVCache>` cache path is
|
|
4292
|
+
* used instead.
|
|
4293
|
+
*
|
|
4294
|
+
* Default: true.
|
|
3743
4295
|
*/
|
|
3744
|
-
|
|
4296
|
+
useBlockPagedCache?: boolean | undefined;
|
|
3745
4297
|
}
|
|
3746
4298
|
|
|
3747
4299
|
/** Qwen3 language model configuration */
|
|
@@ -3768,6 +4320,14 @@ export interface RecResult {
|
|
|
3768
4320
|
score: number;
|
|
3769
4321
|
}
|
|
3770
4322
|
|
|
4323
|
+
/**
|
|
4324
|
+
* Reset MLX's peak-memory counter to the current active level.
|
|
4325
|
+
* Useful for measuring per-request peak memory in a long-running
|
|
4326
|
+
* process — call before a request, sample
|
|
4327
|
+
* `getMemorySnapshot().peakBytes` after.
|
|
4328
|
+
*/
|
|
4329
|
+
export declare function resetPeakMemory(): void;
|
|
4330
|
+
|
|
3771
4331
|
/** Clear all collected profiling data and reset session timer. */
|
|
3772
4332
|
export declare function resetProfilingData(): void;
|
|
3773
4333
|
|
|
@@ -3857,22 +4417,6 @@ export interface SamplingConfig {
|
|
|
3857
4417
|
*/
|
|
3858
4418
|
export declare function saveToXlsx(text: string, filePath: string): void;
|
|
3859
4419
|
|
|
3860
|
-
/** Scheduler statistics (NAPI-compatible) */
|
|
3861
|
-
export interface SchedulerStatsNapi {
|
|
3862
|
-
/** Number of requests waiting to be scheduled */
|
|
3863
|
-
numWaiting: number;
|
|
3864
|
-
/** Number of sequences currently running */
|
|
3865
|
-
numRunning: number;
|
|
3866
|
-
/** Number of completed sequences */
|
|
3867
|
-
numCompleted: number;
|
|
3868
|
-
/** Number of sequences in prefill phase */
|
|
3869
|
-
numPrefill: number;
|
|
3870
|
-
/** Number of sequences in decode phase */
|
|
3871
|
-
numDecode: number;
|
|
3872
|
-
/** Total tokens across all running sequences */
|
|
3873
|
-
totalRunningTokens: number;
|
|
3874
|
-
}
|
|
3875
|
-
|
|
3876
4420
|
/** Enable or disable profiling globally. */
|
|
3877
4421
|
export declare function setProfilingEnabled(enabled: boolean): void;
|
|
3878
4422
|
|
|
@@ -4155,6 +4699,35 @@ export interface TrainStepResultWithOutputs {
|
|
|
4155
4699
|
completionLengths: Array<number>;
|
|
4156
4700
|
}
|
|
4157
4701
|
|
|
4702
|
+
/**
|
|
4703
|
+
* Encoder-free vision configuration for the Gemma 4 unified multimodal model.
|
|
4704
|
+
*
|
|
4705
|
+
* Parsed from the `vision_config` sub-dict of a `gemma4_unified` checkpoint
|
|
4706
|
+
* (`model_type == "gemma4_unified_vision"`). This is a different shape from the
|
|
4707
|
+
* SigLIP-style [`super::vision_config::Gemma4VisionConfig`] used by the dense
|
|
4708
|
+
* gemma4 family: the unified vision path has no transformer encoder, only a
|
|
4709
|
+
* patch embedder (LayerNorm + Linear + 2D positional embedding) feeding the
|
|
4710
|
+
* multimodal projection.
|
|
4711
|
+
*/
|
|
4712
|
+
export interface UnifiedVisionConfig {
|
|
4713
|
+
/** Pixel side length of a single image patch (48 = patch_size 16 × pooling 3). */
|
|
4714
|
+
modelPatchSize: number;
|
|
4715
|
+
/** Embedding width inside the vision embedder (3840, == text hidden_size). */
|
|
4716
|
+
mmEmbedDim: number;
|
|
4717
|
+
/** Number of rows in the 2D positional-embedding table (1120). */
|
|
4718
|
+
mmPosembSize: number;
|
|
4719
|
+
/** Maximum soft tokens (patches) per image after resize (280). */
|
|
4720
|
+
numSoftTokens: number;
|
|
4721
|
+
/** Output projection width of `embed_vision` (3840, == text hidden_size). */
|
|
4722
|
+
outputProjDims: number;
|
|
4723
|
+
/** Pixel-grid patch size used by the resize math (16). */
|
|
4724
|
+
patchSize: number;
|
|
4725
|
+
/** Pooling kernel size used by the resize math (3). */
|
|
4726
|
+
poolingKernelSize: number;
|
|
4727
|
+
/** Epsilon for the embedder LayerNorms and the projection RMSNorm. */
|
|
4728
|
+
rmsNormEps: number;
|
|
4729
|
+
}
|
|
4730
|
+
|
|
4158
4731
|
/** Result from document unwarping. */
|
|
4159
4732
|
export interface UnwarpResult {
|
|
4160
4733
|
/** Unwarped image as PNG bytes */
|
|
@@ -4224,3 +4797,27 @@ export interface VlmChatMessage {
|
|
|
4224
4797
|
/** Text content of the message */
|
|
4225
4798
|
content: string;
|
|
4226
4799
|
}
|
|
4800
|
+
|
|
4801
|
+
export declare namespace __internal__ {
|
|
4802
|
+
/**
|
|
4803
|
+
* Drain the MLX allocator's free-pool.
|
|
4804
|
+
*
|
|
4805
|
+
* @internal
|
|
4806
|
+
*
|
|
4807
|
+
* This is a process-wide drain routed through MLX's default-stream
|
|
4808
|
+
* `mlx_synchronize()`, which does NOT wait on the custom generation
|
|
4809
|
+
* streams that the per-model threads run on. Calling this from user
|
|
4810
|
+
* code while a decode is in flight can race live Metal command buffers
|
|
4811
|
+
* and risk use-after-free. The only safe caller today is
|
|
4812
|
+
* `@mlx-node/server`'s idle sweeper, which only triggers after the
|
|
4813
|
+
* in-flight request counter has returned to zero.
|
|
4814
|
+
*
|
|
4815
|
+
* Exposed under the `__internal__` NAPI namespace — reachable as
|
|
4816
|
+
* `require('@mlx-node/core').__internal__.clearCache()` and NOT on
|
|
4817
|
+
* the root `require('@mlx-node/core')` object. The namespace prefix
|
|
4818
|
+
* is a deliberate speed-bump that forces any caller to acknowledge
|
|
4819
|
+
* this is a private drain with custom-stream caveats; the root
|
|
4820
|
+
* surface stays clean of the footgun.
|
|
4821
|
+
*/
|
|
4822
|
+
export function clearCache(): void;
|
|
4823
|
+
}
|