@mlx-node/core 0.0.7 → 0.0.9
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 +91 -69
- package/index.d.cts +1459 -879
- package/package.json +6 -5
package/index.d.cts
CHANGED
|
@@ -119,82 +119,100 @@ 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
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
* `chatSessionContinueTool` calls can append a raw delta on top
|
|
147
|
-
* without re-rendering the chat template.
|
|
198
|
+
* Renders the complete conversation through the loaded chat
|
|
199
|
+
* template, decodes until the family's session stop token, and
|
|
200
|
+
* preserves the resulting KV state for exact-prefix reuse.
|
|
148
201
|
*/
|
|
149
202
|
chatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
150
203
|
/**
|
|
151
|
-
* Continue an existing chat session
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
* Requires a live session started via `chatSessionStart`. Errors
|
|
158
|
-
* if the session is empty, carries image state, or if
|
|
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
|
|
163
|
-
* `IMAGE_CHANGE_REQUIRES_SESSION_RESTART:` so the TypeScript
|
|
164
|
-
* `ChatSession` layer can catch the prefix and route image-changes
|
|
165
|
-
* back through a fresh `chatSessionStart` uniformly across all
|
|
166
|
-
* model backends.
|
|
204
|
+
* Continue an existing chat session from the complete
|
|
205
|
+
* structured conversation. The loaded model template is the
|
|
206
|
+
* sole authority for the rendered suffix; native cache reuse
|
|
207
|
+
* occurs only after the completed structured history is verified
|
|
208
|
+
* against the saved token history.
|
|
167
209
|
*/
|
|
168
|
-
chatSessionContinue(
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
* Continue an existing chat session with a tool-result turn.
|
|
175
|
-
*
|
|
176
|
-
* Builds a Gemma4-format tool delta
|
|
177
|
-
* (`
|
|
178
|
-
<|turn>tool
|
|
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.
|
|
190
|
-
*
|
|
191
|
-
* Requires a live session started via `chatSessionStart`.
|
|
192
|
-
*/
|
|
193
|
-
chatSessionContinueTool(
|
|
194
|
-
toolCallId: string,
|
|
195
|
-
content: string,
|
|
196
|
-
config?: ChatConfig | undefined | null,
|
|
197
|
-
): Promise<ChatResult>;
|
|
210
|
+
chatSessionContinue(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
211
|
+
/**
|
|
212
|
+
* Continue an existing chat session from a complete
|
|
213
|
+
* structured conversation ending in a tool-role message.
|
|
214
|
+
*/
|
|
215
|
+
chatSessionContinueTool(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
198
216
|
/** Streaming variant of `chatSessionStart`. */
|
|
199
217
|
chatStreamSessionStart(
|
|
200
218
|
messages: ChatMessage[],
|
|
@@ -203,15 +221,13 @@ export declare class Gemma4Model {
|
|
|
203
221
|
): Promise<ChatStreamHandle>;
|
|
204
222
|
/** Streaming variant of `chatSessionContinue`. */
|
|
205
223
|
chatStreamSessionContinue(
|
|
206
|
-
|
|
207
|
-
images: Uint8Array[] | null | undefined,
|
|
224
|
+
messages: ChatMessage[],
|
|
208
225
|
config: ChatConfig | null | undefined,
|
|
209
226
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
210
227
|
): Promise<ChatStreamHandle>;
|
|
211
228
|
/** Streaming variant of `chatSessionContinueTool`. */
|
|
212
229
|
chatStreamSessionContinueTool(
|
|
213
|
-
|
|
214
|
-
content: string,
|
|
230
|
+
messages: ChatMessage[],
|
|
215
231
|
config: ChatConfig | null | undefined,
|
|
216
232
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
217
233
|
): Promise<ChatStreamHandle>;
|
|
@@ -471,69 +487,53 @@ export declare class Lfm2Model {
|
|
|
471
487
|
/** Load an LFM2 model from a directory containing safetensors and config.json. */
|
|
472
488
|
static load(modelPath: string): Promise<Lfm2Model>;
|
|
473
489
|
/**
|
|
474
|
-
*
|
|
475
|
-
*
|
|
476
|
-
*
|
|
490
|
+
* Whether the block-paged KV cache adapter is active on this model
|
|
491
|
+
* instance.
|
|
492
|
+
*
|
|
493
|
+
* `true` iff `Lfm2Inner::paged_adapter` was successfully constructed
|
|
494
|
+
* at load time (driven by `Lfm2Config::use_block_paged_cache`,
|
|
495
|
+
* defaulting to `true` after paged-vs-flat parity verification).
|
|
496
|
+
* LFM2 is hybrid (10 conv + 6 full-attention layers); only the
|
|
497
|
+
* full-attention layers route through the adapter, conv layers stay
|
|
498
|
+
* on flat `Lfm2LayerCache::Conv` regardless. When `true`, the native
|
|
499
|
+
* cache reuses SYS blocks across `chatSessionStart` calls via
|
|
500
|
+
* content-addressing, so the JS-side warm slot in
|
|
501
|
+
* `SessionRegistry.getOrCreateWarmAny` is redundant and the
|
|
502
|
+
* `/v1/messages` server endpoint allocates a fresh `ChatSession` per
|
|
503
|
+
* request.
|
|
504
|
+
*/
|
|
505
|
+
hasBlockPagedCache(): boolean;
|
|
506
|
+
/** Get the model configuration. */
|
|
507
|
+
getConfig(): Lfm2Config;
|
|
508
|
+
/** Estimated number of model parameters. */
|
|
509
|
+
numParameters(): number;
|
|
510
|
+
/**
|
|
511
|
+
* Reset all caches and clear cached token history. Exposed
|
|
512
|
+
* so tests and session-management code can start from a
|
|
513
|
+
* known clean state between turns.
|
|
477
514
|
*/
|
|
478
515
|
resetCaches(): void;
|
|
479
516
|
/**
|
|
480
517
|
* Start a new chat session.
|
|
481
518
|
*
|
|
482
|
-
*
|
|
483
|
-
*
|
|
484
|
-
*
|
|
485
|
-
* `chatSessionContinueTool` calls can append a raw delta on top
|
|
486
|
-
* without re-rendering the chat template.
|
|
487
|
-
*
|
|
488
|
-
* Requires `config.reuse_cache` to be enabled (the default).
|
|
519
|
+
* Renders the complete conversation through the loaded chat
|
|
520
|
+
* template, decodes until the family's session stop token, and
|
|
521
|
+
* preserves the resulting KV state for exact-prefix reuse.
|
|
489
522
|
*/
|
|
490
523
|
chatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
491
524
|
/**
|
|
492
|
-
* Continue an existing chat session
|
|
493
|
-
*
|
|
494
|
-
*
|
|
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`.
|
|
502
|
-
*
|
|
503
|
-
* LFM2 is text-only; `images` is an opt-in guard parameter: when
|
|
504
|
-
* non-empty the native side returns an error whose message begins
|
|
505
|
-
* with `IMAGE_CHANGE_REQUIRES_SESSION_RESTART:` so the TypeScript
|
|
506
|
-
* `ChatSession` layer can catch the prefix and route
|
|
507
|
-
* image-changes back through a fresh `chatSessionStart`
|
|
508
|
-
* uniformly across all model backends.
|
|
525
|
+
* Continue an existing chat session from the complete
|
|
526
|
+
* structured conversation. The loaded model template is the
|
|
527
|
+
* sole authority for the rendered suffix; native cache reuse
|
|
528
|
+
* occurs only after the completed structured history is verified
|
|
529
|
+
* against the saved token history.
|
|
509
530
|
*/
|
|
510
|
-
chatSessionContinue(
|
|
511
|
-
userMessage: string,
|
|
512
|
-
images: Uint8Array[] | null | undefined,
|
|
513
|
-
config: ChatConfig | null | undefined,
|
|
514
|
-
): Promise<ChatResult>;
|
|
531
|
+
chatSessionContinue(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
515
532
|
/**
|
|
516
|
-
* Continue an existing chat session
|
|
517
|
-
*
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
* <|im_end|>`) from `content` and prefills it on top of the live
|
|
521
|
-
* session caches, then decodes the assistant reply. Stops on
|
|
522
|
-
* `<|im_end|>` so the cache stays on a clean boundary for the
|
|
523
|
-
* next turn.
|
|
524
|
-
*
|
|
525
|
-
* The `tool_call_id` is currently dropped by the wire format —
|
|
526
|
-
* LFM2's chat template identifies tool responses positionally,
|
|
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
|
-
*/
|
|
532
|
-
chatSessionContinueTool(
|
|
533
|
-
toolCallId: string,
|
|
534
|
-
content: string,
|
|
535
|
-
config?: ChatConfig | undefined | null,
|
|
536
|
-
): Promise<ChatResult>;
|
|
533
|
+
* Continue an existing chat session from a complete
|
|
534
|
+
* structured conversation ending in a tool-role message.
|
|
535
|
+
*/
|
|
536
|
+
chatSessionContinueTool(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
537
537
|
/** Streaming variant of `chatSessionStart`. */
|
|
538
538
|
chatStreamSessionStart(
|
|
539
539
|
messages: ChatMessage[],
|
|
@@ -542,22 +542,16 @@ export declare class Lfm2Model {
|
|
|
542
542
|
): Promise<ChatStreamHandle>;
|
|
543
543
|
/** Streaming variant of `chatSessionContinue`. */
|
|
544
544
|
chatStreamSessionContinue(
|
|
545
|
-
|
|
546
|
-
images: Uint8Array[] | null | undefined,
|
|
545
|
+
messages: ChatMessage[],
|
|
547
546
|
config: ChatConfig | null,
|
|
548
547
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
549
548
|
): Promise<ChatStreamHandle>;
|
|
550
549
|
/** Streaming variant of `chatSessionContinueTool`. */
|
|
551
550
|
chatStreamSessionContinueTool(
|
|
552
|
-
|
|
553
|
-
content: string,
|
|
551
|
+
messages: ChatMessage[],
|
|
554
552
|
config: ChatConfig | null,
|
|
555
553
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
556
554
|
): Promise<ChatStreamHandle>;
|
|
557
|
-
/** Get the model configuration. */
|
|
558
|
-
getConfig(): Lfm2Config;
|
|
559
|
-
/** Estimated number of model parameters. */
|
|
560
|
-
numParameters(): number;
|
|
561
555
|
}
|
|
562
556
|
|
|
563
557
|
export declare class MxArray {
|
|
@@ -681,9 +675,20 @@ export declare class MxArray {
|
|
|
681
675
|
divScalar(value: number): MxArray;
|
|
682
676
|
matmul(other: MxArray): MxArray;
|
|
683
677
|
/**
|
|
684
|
-
*
|
|
685
|
-
*
|
|
686
|
-
*
|
|
678
|
+
* Matrix multiply-add: D = beta * C + alpha * (self @ B), where self is A.
|
|
679
|
+
* Default: alpha=1.0, beta=1.0, giving D = C + (self @ B).
|
|
680
|
+
*
|
|
681
|
+
* Computed explicitly (matmul, optional alpha scale, then add beta*C)
|
|
682
|
+
* rather than via the fused `mlx::core::addmm` primitive. The fused
|
|
683
|
+
* primitive is correct on a well-formed metallib, but this project's local
|
|
684
|
+
* release build is known to non-deterministically miscompile fused GEMM
|
|
685
|
+
* kernels (see the metallib-corruption notes), which manifested as the
|
|
686
|
+
* fused addmm dropping `beta*C` and corrupting every biased linear — most
|
|
687
|
+
* visibly the vision tower (`qkv`, `proj`, `fc1`, `fc2`, merger all carry a
|
|
688
|
+
* bias; bias-free LM/MoE linears pass a zero `C` and were unaffected). The
|
|
689
|
+
* explicit form keeps the `C` term robust to that build hazard; the
|
|
690
|
+
* `nn::linear` unit tests assert it applies a non-zero `C`, so they double
|
|
691
|
+
* as a canary if a future build corrupts the matmul kernel too.
|
|
687
692
|
*/
|
|
688
693
|
addmm(c: MxArray, b: MxArray, alpha?: number | undefined | null, beta?: number | undefined | null): MxArray;
|
|
689
694
|
abs(): MxArray;
|
|
@@ -941,23 +946,43 @@ export declare class OutputStore {
|
|
|
941
946
|
}
|
|
942
947
|
|
|
943
948
|
/**
|
|
944
|
-
*
|
|
945
|
-
*
|
|
946
|
-
* Pass this back via `model.setCache(cache)` before the next
|
|
947
|
-
* chat-session call to enable incremental prefill — only new tokens
|
|
948
|
-
* since the last turn are processed, avoiding redundant computation.
|
|
949
|
+
* NAPI-exported view of [`PrivacyFilterModel`].
|
|
949
950
|
*
|
|
950
|
-
*
|
|
951
|
-
*
|
|
951
|
+
* Construct via [`PrivacyFilterModelJs::load`] and run end-to-end
|
|
952
|
+
* classification via [`PrivacyFilterModelJs::classify`].
|
|
952
953
|
*/
|
|
953
|
-
export declare class
|
|
954
|
-
/**
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
954
|
+
export declare class PrivacyFilterModel {
|
|
955
|
+
/**
|
|
956
|
+
* Load a privacy-filter checkpoint from a directory.
|
|
957
|
+
*
|
|
958
|
+
* The directory must contain `config.json`, `model.safetensors`,
|
|
959
|
+
* `tokenizer.json`, and optionally `viterbi_calibration.json` and
|
|
960
|
+
* `tokenizer_config.json`. Synchronous to match the loader pattern
|
|
961
|
+
* used by every other model in this crate (e.g. `TextDetModel`).
|
|
962
|
+
*/
|
|
963
|
+
static load(modelPath: string): PrivacyFilterModel;
|
|
964
|
+
/**
|
|
965
|
+
* Classify `text` and return detected PII entities (and optionally
|
|
966
|
+
* per-token tags).
|
|
967
|
+
*
|
|
968
|
+
* Pipeline:
|
|
969
|
+
* 1. Tokenize the text with byte offsets, no special tokens.
|
|
970
|
+
* 2. Run the forward pass to get `[1, T, 33]` logits.
|
|
971
|
+
* 3. Compute softmax (for per-tag confidences) and log-softmax (for
|
|
972
|
+
* Viterbi emissions) over the class axis.
|
|
973
|
+
* 4. Build the transition matrix from the default calibration
|
|
974
|
+
* merged with any per-call overrides.
|
|
975
|
+
* 5. Viterbi-decode using log-softmax emissions to get the BIOES
|
|
976
|
+
* tag sequence.
|
|
977
|
+
* 6. For each token, take the softmax probability of the
|
|
978
|
+
* Viterbi-emitted tag (so per-token `tag` and `score` share
|
|
979
|
+
* decoders), then walk the tags + offsets + those probabilities
|
|
980
|
+
* to extract coherent spans whose mean probability clears
|
|
981
|
+
* `threshold`.
|
|
982
|
+
*/
|
|
983
|
+
classify(text: string, opts?: PrivacyClassifyOptions | undefined | null): PrivacyClassifyResult;
|
|
960
984
|
}
|
|
985
|
+
export type PrivacyFilterModelJs = PrivacyFilterModel;
|
|
961
986
|
|
|
962
987
|
/**
|
|
963
988
|
* Qianfan-OCR Vision-Language Model (InternVL architecture).
|
|
@@ -973,8 +998,13 @@ export declare class QianfanOCRModel {
|
|
|
973
998
|
* Create a new QianfanOCRModel from config (uninitialized, no weights).
|
|
974
999
|
*
|
|
975
1000
|
* This constructor path does not spawn a model thread — the returned
|
|
976
|
-
* instance is only useful for
|
|
977
|
-
* [`QianfanOCRModel::load`] to actually run inference.
|
|
1001
|
+
* instance is only useful for `is_initialized` queries until
|
|
1002
|
+
* [`QianfanOCRModel::load`] is called to actually run inference. The
|
|
1003
|
+
* `config` argument is accepted to preserve the `new
|
|
1004
|
+
* QianfanOCRModel(config)` JS surface; the value is discarded because
|
|
1005
|
+
* nothing on the uninitialized path consults it (any future config
|
|
1006
|
+
* getter would forward to the inner thread state populated by
|
|
1007
|
+
* `load()`).
|
|
978
1008
|
*/
|
|
979
1009
|
constructor(config: QianfanOcrConfig);
|
|
980
1010
|
/** Returns true if weights have been loaded via `load()`. */
|
|
@@ -1004,11 +1034,9 @@ export declare class QianfanOCRModel {
|
|
|
1004
1034
|
/**
|
|
1005
1035
|
* Start a new chat session.
|
|
1006
1036
|
*
|
|
1007
|
-
*
|
|
1008
|
-
*
|
|
1009
|
-
*
|
|
1010
|
-
* append a raw ChatML delta on top without re-rendering the chat
|
|
1011
|
-
* template.
|
|
1037
|
+
* Renders the complete structured conversation through the checkpoint
|
|
1038
|
+
* template, decodes until `<|im_end|>`, and preserves KV state for an
|
|
1039
|
+
* exact-prefix check against the next complete template render.
|
|
1012
1040
|
*
|
|
1013
1041
|
* Qianfan-OCR is always a VLM (InternViT + Qwen3 language model), so
|
|
1014
1042
|
* this entry point accepts images in `messages` without the text-only
|
|
@@ -1016,62 +1044,31 @@ export declare class QianfanOCRModel {
|
|
|
1016
1044
|
*/
|
|
1017
1045
|
chatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
1018
1046
|
/**
|
|
1019
|
-
* Continue
|
|
1020
|
-
*
|
|
1021
|
-
*
|
|
1022
|
-
* KV state, then decodes the model reply. Stops on `<|im_end|>` so
|
|
1023
|
-
* the cache remains on a clean turn boundary for the next turn.
|
|
1024
|
-
*
|
|
1025
|
-
* Requires a live session started via `chatSessionStart`. Errors
|
|
1026
|
-
* if the session is empty or if `config.reuse_cache` is
|
|
1027
|
-
* explicitly set to `false`.
|
|
1028
|
-
*
|
|
1029
|
-
* `images` is an opt-in guard parameter: when non-empty the native
|
|
1030
|
-
* side returns an error whose message begins with
|
|
1031
|
-
* `IMAGE_CHANGE_REQUIRES_SESSION_RESTART:` so the TypeScript
|
|
1032
|
-
* `ChatSession` layer can catch the prefix and route image-changes
|
|
1033
|
-
* back through a fresh `chatSessionStart` uniformly across all
|
|
1034
|
-
* model backends. Qianfan-OCR is a VLM but the continue path cannot
|
|
1035
|
-
* splice new vision features into a live KV cache — image changes
|
|
1036
|
-
* always require a fresh session start.
|
|
1047
|
+
* Continue from the caller's complete conversation history. The
|
|
1048
|
+
* checkpoint's chat template is rendered again and exact prefix matching
|
|
1049
|
+
* decides whether the live cache can be reused.
|
|
1037
1050
|
*/
|
|
1038
|
-
chatSessionContinue(
|
|
1039
|
-
userMessage: string,
|
|
1040
|
-
images: Uint8Array[] | null | undefined,
|
|
1041
|
-
config: ChatConfig | null | undefined,
|
|
1042
|
-
): Promise<ChatResult>;
|
|
1051
|
+
chatSessionContinue(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
1043
1052
|
/**
|
|
1044
|
-
*
|
|
1045
|
-
*
|
|
1046
|
-
* Builds a ChatML `<tool_response>` delta from `tool_call_id` and
|
|
1047
|
-
* `content` and prefills it on top of the live session caches, then
|
|
1048
|
-
* decodes the model reply. Stops on `<|im_end|>` so the cache stays
|
|
1049
|
-
* on a clean turn boundary for the next turn.
|
|
1050
|
-
*
|
|
1051
|
-
* Requires a live session started via `chatSessionStart`.
|
|
1053
|
+
* Tool-result continuation over a full history. Tool representation is
|
|
1054
|
+
* owned entirely by the model-provided template.
|
|
1052
1055
|
*/
|
|
1053
|
-
chatSessionContinueTool(
|
|
1054
|
-
toolCallId: string,
|
|
1055
|
-
content: string,
|
|
1056
|
-
config?: ChatConfig | undefined | null,
|
|
1057
|
-
): Promise<ChatResult>;
|
|
1056
|
+
chatSessionContinueTool(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
1058
1057
|
/** Streaming variant of `chatSessionStart`. */
|
|
1059
1058
|
chatStreamSessionStart(
|
|
1060
1059
|
messages: ChatMessage[],
|
|
1061
1060
|
config: ChatConfig | null | undefined,
|
|
1062
1061
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1063
1062
|
): Promise<ChatStreamHandle>;
|
|
1064
|
-
/** Streaming
|
|
1063
|
+
/** Streaming continuation over a complete conversation history. */
|
|
1065
1064
|
chatStreamSessionContinue(
|
|
1066
|
-
|
|
1067
|
-
images: Uint8Array[] | null | undefined,
|
|
1065
|
+
messages: ChatMessage[],
|
|
1068
1066
|
config: ChatConfig | null | undefined,
|
|
1069
1067
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1070
1068
|
): Promise<ChatStreamHandle>;
|
|
1071
|
-
/** Streaming
|
|
1069
|
+
/** Streaming tool-result continuation over a complete history. */
|
|
1072
1070
|
chatStreamSessionContinueTool(
|
|
1073
|
-
|
|
1074
|
-
content: string,
|
|
1071
|
+
messages: ChatMessage[],
|
|
1075
1072
|
config: ChatConfig | null | undefined,
|
|
1076
1073
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1077
1074
|
): Promise<ChatStreamHandle>;
|
|
@@ -1085,27 +1082,55 @@ export declare class QianfanOCRModel {
|
|
|
1085
1082
|
* routed through `TrainingDispatch` to the model thread.
|
|
1086
1083
|
*/
|
|
1087
1084
|
export declare class Qwen35Model {
|
|
1088
|
-
/** Initialize caches for incremental generation. */
|
|
1089
|
-
initCaches(): void;
|
|
1090
|
-
/** Reset all caches. */
|
|
1091
|
-
resetCaches(): void;
|
|
1092
1085
|
/**
|
|
1093
|
-
*
|
|
1086
|
+
* Whether the block-paged KV cache adapter is active on this model
|
|
1087
|
+
* instance.
|
|
1094
1088
|
*
|
|
1095
|
-
*
|
|
1096
|
-
*
|
|
1097
|
-
*
|
|
1098
|
-
*
|
|
1089
|
+
* `true` iff `Qwen35Inner::paged_adapter` was successfully
|
|
1090
|
+
* constructed at load time (driven by
|
|
1091
|
+
* `Qwen3_5Config::use_block_paged_cache`, default-OFF for text-only
|
|
1092
|
+
* checkpoints because parity is pending real-weights validation, and
|
|
1093
|
+
* default-ON for VLM checkpoints). On VLM checkpoints dense image turns
|
|
1094
|
+
* ONLY run on the paged-vision core; a vision turn that reaches a None
|
|
1095
|
+
* adapter errors at dispatch. Surfaced through this NAPI method so
|
|
1096
|
+
* server endpoints can branch on it without round-tripping through
|
|
1097
|
+
* the model thread.
|
|
1098
|
+
*/
|
|
1099
|
+
hasBlockPagedCache(): boolean;
|
|
1100
|
+
/**
|
|
1101
|
+
* Whether this checkpoint shipped an MTP head (module loaded by
|
|
1102
|
+
* `persistence::apply_weights_inner`). Snapshotted at load time from
|
|
1103
|
+
* `Qwen35Inner::has_mtp_weights()` so the TS `ChatSession` can
|
|
1104
|
+
* auto-default `enableMtp = true` for MTP-capable checkpoints without
|
|
1105
|
+
* dispatching a command into the model thread.
|
|
1106
|
+
*
|
|
1107
|
+
* Note: this only reports weight availability. Whether the
|
|
1108
|
+
* speculative-decode path actually runs on a given call also requires the
|
|
1109
|
+
* per-request `enableMtp` flag.
|
|
1110
|
+
*/
|
|
1111
|
+
hasMtpWeights(): boolean;
|
|
1112
|
+
/**
|
|
1113
|
+
* Whether this loaded model instance can execute image-bearing turns.
|
|
1114
|
+
*
|
|
1115
|
+
* This is an authoritative load-time snapshot, not a `config.json`
|
|
1116
|
+
* family guess: it requires a loaded vision encoder, image processor,
|
|
1117
|
+
* and the block-paged KV adapter used by the dense vision path.
|
|
1118
|
+
*/
|
|
1119
|
+
supportsImages(): boolean;
|
|
1120
|
+
/**
|
|
1121
|
+
* Synchronous snapshot used by higher layers to preflight rendered
|
|
1122
|
+
* prompts and clamp output before native cache allocation.
|
|
1099
1123
|
*/
|
|
1100
|
-
|
|
1124
|
+
contextLimits(): Qwen35ContextLimits;
|
|
1101
1125
|
/**
|
|
1102
|
-
*
|
|
1126
|
+
* Compute the exact prompt length after Qwen image-placeholder expansion
|
|
1127
|
+
* without running the vision encoder or touching inference caches.
|
|
1103
1128
|
*
|
|
1104
|
-
*
|
|
1105
|
-
*
|
|
1106
|
-
*
|
|
1129
|
+
* `prompt_tokens` is the already-rendered chat-template output. `messages`
|
|
1130
|
+
* supplies the complete image history so both fresh and leased-session
|
|
1131
|
+
* preflights account for every image in template order.
|
|
1107
1132
|
*/
|
|
1108
|
-
|
|
1133
|
+
expandedPromptTokenCount(promptTokens: Uint32Array, messages: Array<ChatMessage>): Promise<number>;
|
|
1109
1134
|
/**
|
|
1110
1135
|
* Load a pretrained model from a directory.
|
|
1111
1136
|
*
|
|
@@ -1118,130 +1143,62 @@ export declare class Qwen35Model {
|
|
|
1118
1143
|
/** Generate text from a prompt token sequence. */
|
|
1119
1144
|
generate(promptTokens: MxArray, config: Qwen35GenerationConfig): Promise<Qwen35GenerationResult>;
|
|
1120
1145
|
/**
|
|
1121
|
-
*
|
|
1146
|
+
* Get the number of parameters in the model.
|
|
1122
1147
|
*
|
|
1123
|
-
*
|
|
1124
|
-
* its stop token so the cached KV state ends on a clean ChatML
|
|
1125
|
-
* boundary. Image support is conditional on the loaded
|
|
1126
|
-
* checkpoint: a Qwen3.5-VL dense model loaded with vision weights
|
|
1127
|
-
* accepts images in `messages` (the vision encoder handles
|
|
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.
|
|
1148
|
+
* Pure config computation — no model-thread dispatch needed.
|
|
1138
1149
|
*/
|
|
1139
|
-
|
|
1150
|
+
numParameters(): number;
|
|
1140
1151
|
/**
|
|
1141
|
-
*
|
|
1142
|
-
*
|
|
1143
|
-
* Appends a raw ChatML user/assistant delta to the session's cached
|
|
1144
|
-
* KV state, then decodes the assistant reply. Stops on `<|im_end|>`
|
|
1145
|
-
* so the cache remains on a clean boundary for the next turn.
|
|
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`.
|
|
1152
|
+
* Save the model weights and configuration to a directory.
|
|
1150
1153
|
*
|
|
1151
|
-
*
|
|
1152
|
-
* side returns an error whose message begins with
|
|
1153
|
-
* `IMAGE_CHANGE_REQUIRES_SESSION_RESTART:` so the TypeScript
|
|
1154
|
-
* `ChatSession` layer can catch the prefix and route image-changes
|
|
1155
|
-
* back through a fresh `chatSessionStart`.
|
|
1154
|
+
* Dispatches to model thread.
|
|
1156
1155
|
*/
|
|
1157
|
-
|
|
1158
|
-
userMessage: string,
|
|
1159
|
-
images: Uint8Array[] | null | undefined,
|
|
1160
|
-
config: ChatConfig | null | undefined,
|
|
1161
|
-
): Promise<ChatResult>;
|
|
1156
|
+
saveModel(savePath: string): Promise<undefined>;
|
|
1162
1157
|
/**
|
|
1163
|
-
*
|
|
1164
|
-
*
|
|
1165
|
-
*
|
|
1166
|
-
* prefills it on top of the live session caches, then decodes the
|
|
1167
|
-
* assistant reply. Stops on `<|im_end|>` so the cache stays on a
|
|
1168
|
-
* clean boundary for the next turn.
|
|
1169
|
-
*
|
|
1170
|
-
* The `tool_call_id` is currently dropped by the wire format —
|
|
1171
|
-
* Qwen3.5's chat template identifies tool responses by position +
|
|
1172
|
-
* wrapper tags, not an explicit id. Callers may still log it for
|
|
1173
|
-
* their own bookkeeping.
|
|
1174
|
-
*
|
|
1175
|
-
* Requires a live session started via `chatSessionStart`.
|
|
1158
|
+
* Reset all caches and clear cached token history. Exposed
|
|
1159
|
+
* so tests and session-management code can start from a
|
|
1160
|
+
* known clean state between turns.
|
|
1176
1161
|
*/
|
|
1177
|
-
|
|
1178
|
-
toolCallId: string,
|
|
1179
|
-
content: string,
|
|
1180
|
-
config?: ChatConfig | undefined | null,
|
|
1181
|
-
): Promise<ChatResult>;
|
|
1162
|
+
resetCaches(): void;
|
|
1182
1163
|
/**
|
|
1183
|
-
*
|
|
1164
|
+
* Start a new chat session.
|
|
1184
1165
|
*
|
|
1185
|
-
*
|
|
1186
|
-
*
|
|
1187
|
-
*
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
*
|
|
1166
|
+
* Renders the complete conversation through the loaded chat
|
|
1167
|
+
* template, decodes until the family's session stop token, and
|
|
1168
|
+
* preserves the resulting KV state for exact-prefix reuse.
|
|
1169
|
+
*/
|
|
1170
|
+
chatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
1171
|
+
/**
|
|
1172
|
+
* Continue an existing chat session from the complete
|
|
1173
|
+
* structured conversation. The loaded model template is the
|
|
1174
|
+
* sole authority for the rendered suffix; native cache reuse
|
|
1175
|
+
* occurs only after the completed structured history is verified
|
|
1176
|
+
* against the saved token history.
|
|
1177
|
+
*/
|
|
1178
|
+
chatSessionContinue(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
1179
|
+
/**
|
|
1180
|
+
* Continue an existing chat session from a complete
|
|
1181
|
+
* structured conversation ending in a tool-role message.
|
|
1192
1182
|
*/
|
|
1183
|
+
chatSessionContinueTool(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
1184
|
+
/** Streaming variant of `chatSessionStart`. */
|
|
1193
1185
|
chatStreamSessionStart(
|
|
1194
1186
|
messages: ChatMessage[],
|
|
1195
1187
|
config: ChatConfig | null,
|
|
1196
1188
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1197
1189
|
): 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
|
-
*/
|
|
1190
|
+
/** Streaming variant of `chatSessionContinue`. */
|
|
1214
1191
|
chatStreamSessionContinue(
|
|
1215
|
-
|
|
1216
|
-
images: Uint8Array[] | null | undefined,
|
|
1192
|
+
messages: ChatMessage[],
|
|
1217
1193
|
config: ChatConfig | null,
|
|
1218
1194
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1219
1195
|
): Promise<ChatStreamHandle>;
|
|
1220
|
-
/**
|
|
1221
|
-
* Streaming variant of `chatSessionContinueTool`.
|
|
1222
|
-
*
|
|
1223
|
-
* Builds a ChatML tool-response delta on top of the live session
|
|
1224
|
-
* caches and streams the decoded reply. Requires a live session
|
|
1225
|
-
* started via `chatSessionStart` / `chatStreamSessionStart`.
|
|
1226
|
-
*/
|
|
1196
|
+
/** Streaming variant of `chatSessionContinueTool`. */
|
|
1227
1197
|
chatStreamSessionContinueTool(
|
|
1228
|
-
|
|
1229
|
-
content: string,
|
|
1198
|
+
messages: ChatMessage[],
|
|
1230
1199
|
config: ChatConfig | null,
|
|
1231
1200
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1232
1201
|
): 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
1202
|
}
|
|
1246
1203
|
export type Qwen3_5Model = Qwen35Model;
|
|
1247
1204
|
|
|
@@ -1253,142 +1210,110 @@ export type Qwen3_5Model = Qwen35Model;
|
|
|
1253
1210
|
* routed through `TrainingDispatch` to the model thread.
|
|
1254
1211
|
*/
|
|
1255
1212
|
export declare class Qwen35MoeModel {
|
|
1256
|
-
/**
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1213
|
+
/**
|
|
1214
|
+
* Whether the block-paged KV cache adapter is active on this model
|
|
1215
|
+
* instance.
|
|
1216
|
+
*
|
|
1217
|
+
* `true` iff `Qwen35MoeInner::paged_adapter` was successfully
|
|
1218
|
+
* constructed at load time (driven by
|
|
1219
|
+
* `Qwen3_5MoeConfig::use_block_paged_cache`, currently default-OFF
|
|
1220
|
+
* because parity is pending real-weights validation). On VLM
|
|
1221
|
+
* checkpoints the adapter can still be active for text-only
|
|
1222
|
+
* inference; image-bearing chat turns are rejected at runtime by
|
|
1223
|
+
* the chat-entry sites. Surfaced through this NAPI method so
|
|
1224
|
+
* server endpoints can branch on it without round-tripping through
|
|
1225
|
+
* the model thread.
|
|
1226
|
+
*/
|
|
1227
|
+
hasBlockPagedCache(): boolean;
|
|
1228
|
+
/**
|
|
1229
|
+
* Whether this checkpoint shipped an MTP head (module loaded by
|
|
1230
|
+
* `persistence::apply_weights_moe_inner`). Snapshotted at load time from
|
|
1231
|
+
* `Qwen35MoeInner::has_mtp_weights()` so the TS `ChatSession` can
|
|
1232
|
+
* auto-default `enableMtp = true` for MTP-capable checkpoints without
|
|
1233
|
+
* dispatching a command into the model thread. Mirrors
|
|
1234
|
+
* `Qwen3_5Model::has_mtp_weights`.
|
|
1235
|
+
*
|
|
1236
|
+
* Note: this only reports weight availability. Whether the
|
|
1237
|
+
* speculative-decode path actually runs on a given call also requires
|
|
1238
|
+
* the per-request `enableMtp` flag.
|
|
1239
|
+
*/
|
|
1240
|
+
hasMtpWeights(): boolean;
|
|
1241
|
+
/**
|
|
1242
|
+
* Whether this loaded model instance can execute image-bearing turns.
|
|
1243
|
+
*
|
|
1244
|
+
* This is an authoritative load-time snapshot, not a model-family guess:
|
|
1245
|
+
* it requires the loaded vision encoder, image processor, and block-paged
|
|
1246
|
+
* KV adapter used by the MoE vision path.
|
|
1247
|
+
*/
|
|
1248
|
+
supportsImages(): boolean;
|
|
1249
|
+
/** Synchronous active-context snapshot shared with the dense wrapper. */
|
|
1250
|
+
contextLimits(): Qwen35ContextLimits;
|
|
1251
|
+
/**
|
|
1252
|
+
* Exact, non-mutating Qwen image-placeholder expansion count for a fully
|
|
1253
|
+
* rendered prompt and complete message history.
|
|
1254
|
+
*/
|
|
1255
|
+
expandedPromptTokenCount(promptTokens: Uint32Array, messages: Array<ChatMessage>): Promise<number>;
|
|
1264
1256
|
/** Load a pretrained model from a directory. */
|
|
1265
1257
|
static load(path: string): Promise<Qwen35MoeModel>;
|
|
1266
1258
|
/** Generate text from a prompt token sequence. */
|
|
1267
1259
|
generate(promptTokens: MxArray, config: Qwen35MoeGenerationConfig): Promise<Qwen35MoeGenerationResult>;
|
|
1268
1260
|
/**
|
|
1269
|
-
*
|
|
1270
|
-
*
|
|
1271
|
-
* Runs the full jinja chat template once, decodes until `<|im_end|>`,
|
|
1272
|
-
* and leaves the KV caches on a clean ChatML boundary so subsequent
|
|
1273
|
-
* `chatSessionContinue` / `chatSessionContinueTool` calls can
|
|
1274
|
-
* append a raw delta on top without re-rendering the chat
|
|
1275
|
-
* template.
|
|
1276
|
-
*
|
|
1277
|
-
* Image support is conditional on the loaded checkpoint: a
|
|
1278
|
-
* Qwen3.5-VL MoE model loaded with vision weights accepts images
|
|
1279
|
-
* in `messages` (the vision encoder handles prefill), while a
|
|
1280
|
-
* plain text Qwen3.5 MoE checkpoint rejects them with a runtime
|
|
1281
|
-
* error. A mid-session image change requires a fresh
|
|
1282
|
-
* `chatSessionStart` call.
|
|
1261
|
+
* Get the number of parameters in the model.
|
|
1283
1262
|
*
|
|
1284
|
-
*
|
|
1263
|
+
* Pure config computation -- no model-thread dispatch needed.
|
|
1285
1264
|
*/
|
|
1286
|
-
|
|
1265
|
+
numParameters(): number;
|
|
1287
1266
|
/**
|
|
1288
|
-
*
|
|
1289
|
-
*
|
|
1290
|
-
* Appends a raw ChatML user/assistant delta to the session's cached
|
|
1291
|
-
* KV state, then decodes the assistant reply. Stops on `<|im_end|>`
|
|
1292
|
-
* so the cache remains on a clean boundary for the next turn.
|
|
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`.
|
|
1267
|
+
* Save the model weights and configuration to a directory.
|
|
1297
1268
|
*
|
|
1298
|
-
*
|
|
1299
|
-
* side returns an error whose message begins with
|
|
1300
|
-
* `IMAGE_CHANGE_REQUIRES_SESSION_RESTART:` so the TypeScript
|
|
1301
|
-
* `ChatSession` layer can catch the prefix and route image-changes
|
|
1302
|
-
* back through a fresh `chatSessionStart`.
|
|
1269
|
+
* Dispatches to model thread.
|
|
1303
1270
|
*/
|
|
1304
|
-
|
|
1305
|
-
userMessage: string,
|
|
1306
|
-
images: Uint8Array[] | null | undefined,
|
|
1307
|
-
config: ChatConfig | null | undefined,
|
|
1308
|
-
): Promise<ChatResult>;
|
|
1271
|
+
saveModel(savePath: string): Promise<undefined>;
|
|
1309
1272
|
/**
|
|
1310
|
-
*
|
|
1311
|
-
*
|
|
1312
|
-
*
|
|
1313
|
-
* prefills it on top of the live session caches, then decodes the
|
|
1314
|
-
* assistant reply. Stops on `<|im_end|>` so the cache stays on a
|
|
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.
|
|
1321
|
-
*
|
|
1322
|
-
* Requires a live session started via `chatSessionStart`.
|
|
1273
|
+
* Reset all caches and clear cached token history. Exposed
|
|
1274
|
+
* so tests and session-management code can start from a
|
|
1275
|
+
* known clean state between turns.
|
|
1323
1276
|
*/
|
|
1324
|
-
|
|
1325
|
-
toolCallId: string,
|
|
1326
|
-
content: string,
|
|
1327
|
-
config?: ChatConfig | undefined | null,
|
|
1328
|
-
): Promise<ChatResult>;
|
|
1277
|
+
resetCaches(): void;
|
|
1329
1278
|
/**
|
|
1330
|
-
*
|
|
1279
|
+
* Start a new chat session.
|
|
1331
1280
|
*
|
|
1332
|
-
*
|
|
1333
|
-
*
|
|
1334
|
-
*
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
*
|
|
1281
|
+
* Renders the complete conversation through the loaded chat
|
|
1282
|
+
* template, decodes until the family's session stop token, and
|
|
1283
|
+
* preserves the resulting KV state for exact-prefix reuse.
|
|
1284
|
+
*/
|
|
1285
|
+
chatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
1286
|
+
/**
|
|
1287
|
+
* Continue an existing chat session from the complete
|
|
1288
|
+
* structured conversation. The loaded model template is the
|
|
1289
|
+
* sole authority for the rendered suffix; native cache reuse
|
|
1290
|
+
* occurs only after the completed structured history is verified
|
|
1291
|
+
* against the saved token history.
|
|
1292
|
+
*/
|
|
1293
|
+
chatSessionContinue(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
1294
|
+
/**
|
|
1295
|
+
* Continue an existing chat session from a complete
|
|
1296
|
+
* structured conversation ending in a tool-role message.
|
|
1339
1297
|
*/
|
|
1298
|
+
chatSessionContinueTool(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
1299
|
+
/** Streaming variant of `chatSessionStart`. */
|
|
1340
1300
|
chatStreamSessionStart(
|
|
1341
1301
|
messages: ChatMessage[],
|
|
1342
1302
|
config: ChatConfig | null,
|
|
1343
1303
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1344
1304
|
): 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
|
-
*/
|
|
1305
|
+
/** Streaming variant of `chatSessionContinue`. */
|
|
1361
1306
|
chatStreamSessionContinue(
|
|
1362
|
-
|
|
1363
|
-
images: Uint8Array[] | null | undefined,
|
|
1307
|
+
messages: ChatMessage[],
|
|
1364
1308
|
config: ChatConfig | null,
|
|
1365
1309
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1366
1310
|
): Promise<ChatStreamHandle>;
|
|
1367
|
-
/**
|
|
1368
|
-
* Streaming variant of `chatSessionContinueTool`.
|
|
1369
|
-
*
|
|
1370
|
-
* Builds a ChatML tool-response delta on top of the live session
|
|
1371
|
-
* caches and streams the decoded reply. Requires a live session
|
|
1372
|
-
* started via `chatSessionStart` / `chatStreamSessionStart`.
|
|
1373
|
-
*/
|
|
1311
|
+
/** Streaming variant of `chatSessionContinueTool`. */
|
|
1374
1312
|
chatStreamSessionContinueTool(
|
|
1375
|
-
|
|
1376
|
-
content: string,
|
|
1313
|
+
messages: ChatMessage[],
|
|
1377
1314
|
config: ChatConfig | null,
|
|
1378
1315
|
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1379
1316
|
): 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
1317
|
}
|
|
1393
1318
|
export type Qwen3_5MoeModel = Qwen35MoeModel;
|
|
1394
1319
|
|
|
@@ -1400,117 +1325,21 @@ export type Qwen3_5MoeModel = Qwen35MoeModel;
|
|
|
1400
1325
|
*/
|
|
1401
1326
|
export declare class Qwen3Model {
|
|
1402
1327
|
/**
|
|
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;
|
|
1328
|
+
* Whether the block-paged KV cache adapter is active on this model
|
|
1329
|
+
* instance.
|
|
1330
|
+
*
|
|
1331
|
+
* `true` iff `Qwen3Inner::paged_adapter` was successfully constructed
|
|
1332
|
+
* at load time (driven by `Qwen3Config::use_block_paged_cache`,
|
|
1333
|
+
* defaulting to `true` for Qwen3 since paged-vs-flat parity has been
|
|
1334
|
+
* verified). When `true`, the native cache reuses SYS blocks across
|
|
1335
|
+
* `chatSessionStart` calls via content-addressing in
|
|
1336
|
+
* `BlockAllocator`'s prefix-hash table — the JS-side warm slot in
|
|
1337
|
+
* `SessionRegistry.getOrCreateWarmAny` becomes redundant and the
|
|
1338
|
+
* `/v1/messages` server endpoint allocates a fresh `ChatSession` per
|
|
1339
|
+
* request. See `packages/server/src/endpoints/messages.ts` for the
|
|
1340
|
+
* runtime-routing decision.
|
|
1341
|
+
*/
|
|
1342
|
+
hasBlockPagedCache(): boolean;
|
|
1514
1343
|
/** Get model configuration */
|
|
1515
1344
|
getConfig(): Qwen3Config;
|
|
1516
1345
|
/**
|
|
@@ -1544,83 +1373,6 @@ export declare class Qwen3Model {
|
|
|
1544
1373
|
* ```
|
|
1545
1374
|
*/
|
|
1546
1375
|
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
1376
|
/**
|
|
1625
1377
|
* Generate multiple completions for multiple prompts in batch
|
|
1626
1378
|
*
|
|
@@ -1660,20 +1412,6 @@ export declare class Qwen3Model {
|
|
|
1660
1412
|
groupSize: number,
|
|
1661
1413
|
config?: GenerationConfig | undefined | null,
|
|
1662
1414
|
): 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
1415
|
/**
|
|
1678
1416
|
* Apply chat template and encode to token IDs
|
|
1679
1417
|
*
|
|
@@ -1695,6 +1433,51 @@ export declare class Qwen3Model {
|
|
|
1695
1433
|
tools?: Array<ToolDefinition> | undefined | null,
|
|
1696
1434
|
enableThinking?: boolean | undefined | null,
|
|
1697
1435
|
): Promise<Uint32Array>;
|
|
1436
|
+
/**
|
|
1437
|
+
* Reset all caches and clear cached token history. Exposed
|
|
1438
|
+
* so tests and session-management code can start from a
|
|
1439
|
+
* known clean state between turns.
|
|
1440
|
+
*/
|
|
1441
|
+
resetCaches(): void;
|
|
1442
|
+
/**
|
|
1443
|
+
* Start a new chat session.
|
|
1444
|
+
*
|
|
1445
|
+
* Renders the complete conversation through the loaded chat
|
|
1446
|
+
* template, decodes until the family's session stop token, and
|
|
1447
|
+
* preserves the resulting KV state for exact-prefix reuse.
|
|
1448
|
+
*/
|
|
1449
|
+
chatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
1450
|
+
/**
|
|
1451
|
+
* Continue an existing chat session from the complete
|
|
1452
|
+
* structured conversation. The loaded model template is the
|
|
1453
|
+
* sole authority for the rendered suffix; native cache reuse
|
|
1454
|
+
* occurs only after the completed structured history is verified
|
|
1455
|
+
* against the saved token history.
|
|
1456
|
+
*/
|
|
1457
|
+
chatSessionContinue(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
1458
|
+
/**
|
|
1459
|
+
* Continue an existing chat session from a complete
|
|
1460
|
+
* structured conversation ending in a tool-role message.
|
|
1461
|
+
*/
|
|
1462
|
+
chatSessionContinueTool(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
|
|
1463
|
+
/** Streaming variant of `chatSessionStart`. */
|
|
1464
|
+
chatStreamSessionStart(
|
|
1465
|
+
messages: ChatMessage[],
|
|
1466
|
+
config: ChatConfig | null,
|
|
1467
|
+
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1468
|
+
): Promise<ChatStreamHandle>;
|
|
1469
|
+
/** Streaming variant of `chatSessionContinue`. */
|
|
1470
|
+
chatStreamSessionContinue(
|
|
1471
|
+
messages: ChatMessage[],
|
|
1472
|
+
config: ChatConfig | null,
|
|
1473
|
+
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1474
|
+
): Promise<ChatStreamHandle>;
|
|
1475
|
+
/** Streaming variant of `chatSessionContinueTool`. */
|
|
1476
|
+
chatStreamSessionContinueTool(
|
|
1477
|
+
messages: ChatMessage[],
|
|
1478
|
+
config: ChatConfig | null,
|
|
1479
|
+
callback: (err: Error | null, chunk: ChatStreamChunk) => void,
|
|
1480
|
+
): Promise<ChatStreamHandle>;
|
|
1698
1481
|
/**
|
|
1699
1482
|
* Load a pretrained model from disk
|
|
1700
1483
|
*
|
|
@@ -1828,6 +1611,9 @@ export declare class Qwen3Tokenizer {
|
|
|
1828
1611
|
* * `add_generation_prompt` - Whether to add assistant prompt at end (default: true)
|
|
1829
1612
|
* * `tools` - Optional array of tool definitions for function calling
|
|
1830
1613
|
* * `enable_thinking` - Optional flag to enable thinking mode (<think> tags)
|
|
1614
|
+
* * `content_order` - Optional structured multimodal content ordering
|
|
1615
|
+
* * `existing_image_placeholder` - Optional model marker that suppresses
|
|
1616
|
+
* synthetic image parts when it is already present in sanitized text
|
|
1831
1617
|
*
|
|
1832
1618
|
* # Returns
|
|
1833
1619
|
* Encoded token IDs ready for model input
|
|
@@ -1853,6 +1639,8 @@ export declare class Qwen3Tokenizer {
|
|
|
1853
1639
|
addGenerationPrompt?: boolean | undefined | null,
|
|
1854
1640
|
tools?: Array<ToolDefinition> | undefined | null,
|
|
1855
1641
|
enableThinking?: boolean | undefined | null,
|
|
1642
|
+
contentOrder?: MultimodalContentOrder | undefined | null,
|
|
1643
|
+
existingImagePlaceholder?: string | undefined | null,
|
|
1856
1644
|
): Promise<Uint32Array>;
|
|
1857
1645
|
/** Get vocabulary size */
|
|
1858
1646
|
vocabSize(): number;
|
|
@@ -2135,17 +1923,11 @@ export declare class TextRecModel {
|
|
|
2135
1923
|
recognizeCrop(rgbData: Uint8Array, width: number, height: number): RecResult;
|
|
2136
1924
|
}
|
|
2137
1925
|
|
|
2138
|
-
/** Result from VLM chat */
|
|
2139
1926
|
export declare class VlmChatResult {
|
|
2140
|
-
/** Get the response text */
|
|
2141
1927
|
get text(): string;
|
|
2142
|
-
/** Get the generated tokens */
|
|
2143
1928
|
get tokens(): MxArray;
|
|
2144
|
-
/** Get the log probabilities */
|
|
2145
1929
|
get logprobs(): MxArray;
|
|
2146
|
-
/** Get the finish reason */
|
|
2147
1930
|
get finishReason(): 'stop' | 'length' | 'repetition';
|
|
2148
|
-
/** Get the number of tokens generated */
|
|
2149
1931
|
get numTokens(): number;
|
|
2150
1932
|
}
|
|
2151
1933
|
export type VLMChatResult = VlmChatResult;
|
|
@@ -2167,10 +1949,6 @@ export declare class VLModel {
|
|
|
2167
1949
|
* for loading a model from disk.
|
|
2168
1950
|
*/
|
|
2169
1951
|
constructor(config: ModelConfig);
|
|
2170
|
-
/** Set the tokenizer */
|
|
2171
|
-
setTokenizer(tokenizer: Qwen3Tokenizer): void;
|
|
2172
|
-
/** Check if tokenizer is available */
|
|
2173
|
-
get hasTokenizer(): boolean;
|
|
2174
1952
|
/**
|
|
2175
1953
|
* Chat with the VLM model
|
|
2176
1954
|
*
|
|
@@ -2211,80 +1989,6 @@ export declare class VLModel {
|
|
|
2211
1989
|
* ```
|
|
2212
1990
|
*/
|
|
2213
1991
|
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
|
-
/**
|
|
2249
|
-
* Generate text tokens given input tokens and optional image
|
|
2250
|
-
*
|
|
2251
|
-
* Uses KV caching for efficient generation.
|
|
2252
|
-
*
|
|
2253
|
-
* # Arguments
|
|
2254
|
-
* * `input_ids` - Input token IDs [1, seq_len]
|
|
2255
|
-
* * `pixel_values` - Optional image patches [1, num_patches, C, H, W]
|
|
2256
|
-
* * `image_grid_thw` - Optional grid dimensions [1, 3]
|
|
2257
|
-
* * `config` - Generation configuration
|
|
2258
|
-
*
|
|
2259
|
-
* # Returns
|
|
2260
|
-
* * GenerationResult with tokens, logprobs, and finish reason
|
|
2261
|
-
*/
|
|
2262
|
-
generate(
|
|
2263
|
-
inputIds: MxArray,
|
|
2264
|
-
pixelValues?: MxArray | undefined | null,
|
|
2265
|
-
imageGridThw?: MxArray | undefined | null,
|
|
2266
|
-
config?: GenerationConfig | undefined | null,
|
|
2267
|
-
): Promise<GenerationResult>;
|
|
2268
|
-
/**
|
|
2269
|
-
* Batch OCR: extract text from multiple images simultaneously
|
|
2270
|
-
*
|
|
2271
|
-
* Processes N images with sequential prefill + batched decode for ~N× decode throughput.
|
|
2272
|
-
*
|
|
2273
|
-
* # Arguments
|
|
2274
|
-
* * `images` - Encoded image buffers
|
|
2275
|
-
* * `config` - Optional chat configuration (shared across all items)
|
|
2276
|
-
*
|
|
2277
|
-
* # Returns
|
|
2278
|
-
* * Vec of extracted text strings, one per image
|
|
2279
|
-
*
|
|
2280
|
-
* # Example
|
|
2281
|
-
* ```typescript
|
|
2282
|
-
* import { readFileSync } from 'fs';
|
|
2283
|
-
* const images = ['page1.jpg', 'page2.jpg'].map(p => readFileSync(p));
|
|
2284
|
-
* const texts = await model.ocrBatch(images);
|
|
2285
|
-
* ```
|
|
2286
|
-
*/
|
|
2287
|
-
ocrBatch(images: Array<Buffer>, config?: VlmChatConfig | undefined | null): Promise<Array<string>>;
|
|
2288
1992
|
/**
|
|
2289
1993
|
* Batch chat: process multiple items simultaneously
|
|
2290
1994
|
*
|
|
@@ -2323,25 +2027,6 @@ export declare class VLModel {
|
|
|
2323
2027
|
* ```
|
|
2324
2028
|
*/
|
|
2325
2029
|
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
2030
|
}
|
|
2346
2031
|
|
|
2347
2032
|
/**
|
|
@@ -2392,8 +2077,68 @@ export declare const enum BuiltinRewardType {
|
|
|
2392
2077
|
JsonSchema = 'JsonSchema',
|
|
2393
2078
|
}
|
|
2394
2079
|
|
|
2080
|
+
/**
|
|
2081
|
+
* Data-free static FP8 activation-amax calibration over RAW-text PREFILL
|
|
2082
|
+
* (NVIDIA modelopt `MaxCalibrator` parity), end to end in native code.
|
|
2083
|
+
*
|
|
2084
|
+
* The nvidia recipe covers BOTH `qwen3_5` (dense) and `qwen3_5_moe` (MoE), so
|
|
2085
|
+
* this reads `<model_path>/config.json`'s `model_type` and dispatches to the
|
|
2086
|
+
* matching loader + `CalibratePrefillRaw` command (any other `model_type` is a
|
|
2087
|
+
* clear error). Both loaders are the SAME ones the inference session uses
|
|
2088
|
+
* ([`persistence::load_with_thread`]) — the model is only usable on its
|
|
2089
|
+
* dedicated model thread. Then:
|
|
2090
|
+
* 1. dispatches `{Qwen35Cmd,Qwen35MoeCmd}::CalibratePrefillRaw`, which on the
|
|
2091
|
+
* model thread SELF-ARMS that thread's thread-local
|
|
2092
|
+
* [`ActivationAmaxCollector`] flag (RAII, AFTER load so no load-time eval
|
|
2093
|
+
* is recorded), tokenizes each `text` WITHOUT the chat template, truncates
|
|
2094
|
+
* to `calib_seq` tokens, and runs PREFILL ONLY (no generation) so every
|
|
2095
|
+
* mxfp8 attn/GDN projection's activation tap fires over realistic raw-text
|
|
2096
|
+
* activations, resetting caches between rows, then disarms on exit;
|
|
2097
|
+
* 2. ONLY if the full loop succeeded — drains the per-tensor amax and
|
|
2098
|
+
* ATOMICALLY writes it into `<model_path>/config.json` (temp file +
|
|
2099
|
+
* `rename`).
|
|
2100
|
+
*
|
|
2101
|
+
* CONCURRENCY: the whole clear→prefill→take→write section is serialized by
|
|
2102
|
+
* [`calib_guard`] (a process-wide `try_lock`); a second concurrent calibration
|
|
2103
|
+
* fails fast with "another calibration is in progress". The arm flag is
|
|
2104
|
+
* thread-local (so a concurrent inference model can't contaminate the run), but
|
|
2105
|
+
* the running-max MAP is process-global, so serializing RUNS keeps two
|
|
2106
|
+
* calibrations from interleaving `record`/`take` on it. The map is CLEARED at
|
|
2107
|
+
* the very start so stale amax from a prior PANICKED run cannot leak into this
|
|
2108
|
+
* write.
|
|
2109
|
+
*
|
|
2110
|
+
* On ANY error before the final write, the partial amax is discarded and
|
|
2111
|
+
* `config.json` is left UNTOUCHED (a failed calibration must not mutate the
|
|
2112
|
+
* live model in place). A run that prefilled ZERO rows (empty dataset, or every
|
|
2113
|
+
* row tokenized to nothing) is likewise an ERROR that leaves `config.json`
|
|
2114
|
+
* untouched — a no-op calibration must not report a silent success. Returns the
|
|
2115
|
+
* number of projections calibrated (the count of collected amax entries); 0
|
|
2116
|
+
* means a real prefill ran but the model exercised no activation-fp8 sites (not
|
|
2117
|
+
* an nvidia-recipe checkpoint), and in that case `config.json` is left
|
|
2118
|
+
* UNCHANGED (no rewrite).
|
|
2119
|
+
*/
|
|
2120
|
+
export declare function calibrateActivationAmaxRaw(
|
|
2121
|
+
modelPath: string,
|
|
2122
|
+
texts: Array<string>,
|
|
2123
|
+
calibSeq: number,
|
|
2124
|
+
): Promise<number>;
|
|
2125
|
+
|
|
2395
2126
|
/** Unified chat configuration shared by all model variants (Qwen3, Qwen3.5, Qwen3.5 MoE). */
|
|
2396
2127
|
export interface ChatConfig {
|
|
2128
|
+
/**
|
|
2129
|
+
* Internal logical cache owner. The agent provider forwards Pi's stable
|
|
2130
|
+
* session id so model-global GDN sidecars can retain parent and child
|
|
2131
|
+
* branches independently. This does not namespace the physical paged KV
|
|
2132
|
+
* cache; exact token/extra-key hashes remain shareable across owners.
|
|
2133
|
+
*/
|
|
2134
|
+
cacheOwnerId?: string | undefined;
|
|
2135
|
+
/**
|
|
2136
|
+
* Internal top-level owner for the bounded Qwen3.5 GDN sidecar store.
|
|
2137
|
+
* `cache_owner_id` may identify a child Pi session; this separately
|
|
2138
|
+
* identifies the current interactive root so /new and /resume can rotate
|
|
2139
|
+
* the protected branch without changing PagedAttention cache identity.
|
|
2140
|
+
*/
|
|
2141
|
+
cacheRootOwnerId?: string | undefined;
|
|
2397
2142
|
maxNewTokens?: number | undefined;
|
|
2398
2143
|
temperature?: number | undefined;
|
|
2399
2144
|
topK?: number | undefined;
|
|
@@ -2417,11 +2162,11 @@ export interface ChatConfig {
|
|
|
2417
2162
|
frequencyPenalty?: number | undefined;
|
|
2418
2163
|
/** Number of recent tokens to consider for frequency penalty (default: 20) */
|
|
2419
2164
|
frequencyContextSize?: number | undefined;
|
|
2420
|
-
/** Max consecutive identical tokens before stopping (default:
|
|
2165
|
+
/** Max consecutive identical tokens before stopping (default: 0 = disabled; opt in with a positive value) */
|
|
2421
2166
|
maxConsecutiveTokens?: number | undefined;
|
|
2422
|
-
/** Max n-gram repetitions before stopping (default:
|
|
2167
|
+
/** Max n-gram repetitions before stopping (default: 0 = disabled; opt in with a positive value) */
|
|
2423
2168
|
maxNgramRepeats?: number | undefined;
|
|
2424
|
-
/** Max pattern size for n-gram repetition detection (default:
|
|
2169
|
+
/** Max pattern size for n-gram repetition detection (default: 0 = disabled; opt in with a positive value) */
|
|
2425
2170
|
ngramSize?: number | undefined;
|
|
2426
2171
|
tools?: Array<ToolDefinition>;
|
|
2427
2172
|
/**
|
|
@@ -2454,6 +2199,56 @@ export interface ChatConfig {
|
|
|
2454
2199
|
* avoiding redundant computation for multi-turn conversations.
|
|
2455
2200
|
*/
|
|
2456
2201
|
reuseCache?: boolean | undefined;
|
|
2202
|
+
/**
|
|
2203
|
+
* MTP: opt-in flag enabling the Multi-Token Prediction speculative decode
|
|
2204
|
+
* loop (pure-Rust eager; qwen3.5 dense and MoE). Requires the model
|
|
2205
|
+
* checkpoint to carry an MTP head (otherwise silently ignored). Default:
|
|
2206
|
+
* `false`.
|
|
2207
|
+
*/
|
|
2208
|
+
enableMtp?: boolean | undefined;
|
|
2209
|
+
/**
|
|
2210
|
+
* MTP: number of draft tokens per speculative cycle.
|
|
2211
|
+
*
|
|
2212
|
+
* On Qwen3.5 native MTP heads it is clamped to `[1, 5]` by the verify
|
|
2213
|
+
* FFI contract, and when unset native code currently pins depth 1.
|
|
2214
|
+
* When `mtpAdaptiveDepth` is `true`, this value is used as the
|
|
2215
|
+
* throughput-policy seed and the expected-value policy's max depth.
|
|
2216
|
+
* Adaptive depth is opt-in; set `mtpAdaptiveDepth: true` explicitly to
|
|
2217
|
+
* enable it.
|
|
2218
|
+
*
|
|
2219
|
+
* Gemma4 external drafts (`draftModelPath`) resolve the field per draft
|
|
2220
|
+
* variant instead (`gemma4/model.rs` `resolve_params`, always from the
|
|
2221
|
+
* RAW config value — the engine's central `[1, 5]` clamp is an MTP-head
|
|
2222
|
+
* contract that does not apply to external drafts):
|
|
2223
|
+
* - DSpark: with both knobs unset, full draft blocks (the checkpoint's
|
|
2224
|
+
* block size — 7 tokens on `dspark_gemma4_12b_block7`) run behind a
|
|
2225
|
+
* short target-AR/DSpark break-even calibration. A short generation
|
|
2226
|
+
* budget that cannot finish calibration retains the fixed-block
|
|
2227
|
+
* schedule. An explicit
|
|
2228
|
+
* `mtpDepth` caps and pins the block unless `mtpAdaptiveDepth: true`
|
|
2229
|
+
* opts the guard back in; explicit `false` disables it.
|
|
2230
|
+
* - Assistant (Google `gemma-4-*-it-assistant`): an unset `mtpDepth`
|
|
2231
|
+
* drafts 3 tokens per cycle (`ASSISTANT_DEFAULT_DEPTH`), and an
|
|
2232
|
+
* explicit `mtpDepth` clamps to `[1, 8]` (`ASSISTANT_MAX_DEPTH`).
|
|
2233
|
+
*
|
|
2234
|
+
* `mtpAdaptiveDepth` is ignored for the Gemma4 assistant variant.
|
|
2235
|
+
*/
|
|
2236
|
+
mtpDepth?: number | undefined;
|
|
2237
|
+
/**
|
|
2238
|
+
* MTP: when true, the decode loop runs the adaptive
|
|
2239
|
+
* depth policy. Default mode is a per-depth EMA hill-climb plus
|
|
2240
|
+
* DFlash-style 3-state machine `full | reduced | probe`.
|
|
2241
|
+
* `MLX_MTP_ADAPTIVE_DEPTH_MODE=expected-value` instead uses the
|
|
2242
|
+
* MTPLX-style intra-cycle expected-value gate, which deepens toward
|
|
2243
|
+
* `mtpDepth` by default (T=0 byte-parity verified); set
|
|
2244
|
+
* `MLX_MTP_EV_ALLOW_DEEPEN=0` to pin the base depth.
|
|
2245
|
+
* When false, the loop pins `mtpDepth` for every cycle.
|
|
2246
|
+
*
|
|
2247
|
+
* Default: false, except Gemma4 DSpark enables its measured break-even
|
|
2248
|
+
* guard when both this field and `mtpDepth` are unset. An explicit value
|
|
2249
|
+
* always wins over the family default.
|
|
2250
|
+
*/
|
|
2251
|
+
mtpAdaptiveDepth?: boolean | undefined;
|
|
2457
2252
|
}
|
|
2458
2253
|
|
|
2459
2254
|
/** Chat message with tool calling support */
|
|
@@ -2466,10 +2261,34 @@ export interface ChatMessage {
|
|
|
2466
2261
|
toolCalls?: Array<ToolCall>;
|
|
2467
2262
|
/** Tool call ID this message is responding to (for tool messages) */
|
|
2468
2263
|
toolCallId?: string;
|
|
2264
|
+
/**
|
|
2265
|
+
* Whether this tool-role message represents an errored tool result.
|
|
2266
|
+
*
|
|
2267
|
+
* Authoritative, structured signal of tool-call failure. Set to
|
|
2268
|
+
* `Some(true)` when the caller (e.g. the Anthropic
|
|
2269
|
+
* `tool_result.is_error === true` translator) wants the model to
|
|
2270
|
+
* treat the tool output as an error. It is exposed to the model's
|
|
2271
|
+
* chat template as `message.is_error`; Rust never rewrites `content`
|
|
2272
|
+
* or invents a model-facing error marker.
|
|
2273
|
+
*/
|
|
2274
|
+
isError?: boolean;
|
|
2469
2275
|
/** Reasoning content for thinking mode (used with <think> tags) */
|
|
2470
2276
|
reasoningContent?: string;
|
|
2277
|
+
/**
|
|
2278
|
+
* Thinking mode used when this assistant message was generated.
|
|
2279
|
+
*
|
|
2280
|
+
* This is replay provenance, not a request override. Gemma4's disabled-
|
|
2281
|
+
* thinking generation prefix contains an explicit empty thought channel,
|
|
2282
|
+
* while an enabled-thinking turn that emitted no reasoning contains no
|
|
2283
|
+
* such channel. Keeping the historical mode on the message lets the chat
|
|
2284
|
+
* template reproduce either byte sequence even when a later request
|
|
2285
|
+
* changes its current thinking setting.
|
|
2286
|
+
*/
|
|
2287
|
+
thinkingEnabled?: boolean;
|
|
2471
2288
|
/** Image data for VLM models (encoded image bytes: PNG/JPEG, passed as Uint8Array/Buffer) */
|
|
2472
2289
|
images?: Array<Uint8Array> | undefined;
|
|
2290
|
+
/** Audio data for unified Gemma 4 (encoded audio bytes: WAV, passed as Uint8Array/Buffer) */
|
|
2291
|
+
audio?: Array<Uint8Array> | undefined;
|
|
2473
2292
|
}
|
|
2474
2293
|
|
|
2475
2294
|
/** Unified chat result shared by all model variants (Qwen3, Qwen3.5, Qwen3.5 MoE). */
|
|
@@ -2477,24 +2296,45 @@ export interface ChatResult {
|
|
|
2477
2296
|
text: string;
|
|
2478
2297
|
toolCalls: Array<ToolCallResult>;
|
|
2479
2298
|
thinking?: string;
|
|
2299
|
+
/**
|
|
2300
|
+
* Effective `enable_thinking` boolean passed to the model-provided
|
|
2301
|
+
* chat template for this turn. This is replay provenance and is
|
|
2302
|
+
* intentionally distinct from the family's decode-time
|
|
2303
|
+
* [`ThinkingSetup`](crate::engine::ThinkingSetup).
|
|
2304
|
+
*/
|
|
2305
|
+
thinkingEnabled: boolean;
|
|
2480
2306
|
numTokens: number;
|
|
2481
2307
|
promptTokens: number;
|
|
2482
2308
|
reasoningTokens: number;
|
|
2483
2309
|
finishReason: string;
|
|
2484
2310
|
rawText: string;
|
|
2311
|
+
/**
|
|
2312
|
+
* Reasoning-redacted raw output computed from the same token-aware
|
|
2313
|
+
* boundary as `raw_text`. Session wrappers may request full reasoning
|
|
2314
|
+
* internally for deterministic replay, then expose this safe view to a
|
|
2315
|
+
* caller that set `includeReasoning: false`.
|
|
2316
|
+
*/
|
|
2317
|
+
publicRawText?: string | undefined;
|
|
2318
|
+
/**
|
|
2319
|
+
* Number of prompt tokens served from the reused KV-cache prefix.
|
|
2320
|
+
*
|
|
2321
|
+
* When the native prefix-cache machinery successfully matches the new
|
|
2322
|
+
* prompt against the cached conversation history (via
|
|
2323
|
+
* `verify_cache_prefix_direct`), only the trailing delta is re-prefilled
|
|
2324
|
+
* and this field reports the length of the reused prefix. `0` when
|
|
2325
|
+
* the cache was missed or disabled and the full prompt had to be
|
|
2326
|
+
* re-prefilled.
|
|
2327
|
+
*/
|
|
2328
|
+
cachedTokens: number;
|
|
2485
2329
|
/** Performance metrics (present when `reportPerformance: true` in config) */
|
|
2486
2330
|
performance?: PerformanceMetrics;
|
|
2487
2331
|
}
|
|
2488
2332
|
|
|
2489
|
-
/** Chat message role (lowercase values matching standard convention) */
|
|
2333
|
+
/** Chat message role (lowercase values matching standard convention). */
|
|
2490
2334
|
export declare const enum ChatRole {
|
|
2491
|
-
/** User message */
|
|
2492
2335
|
User = 'user',
|
|
2493
|
-
/** Assistant response */
|
|
2494
2336
|
Assistant = 'assistant',
|
|
2495
|
-
/** System prompt */
|
|
2496
2337
|
System = 'system',
|
|
2497
|
-
/** Tool response */
|
|
2498
2338
|
Tool = 'tool',
|
|
2499
2339
|
}
|
|
2500
2340
|
|
|
@@ -2505,10 +2345,36 @@ export interface ChatStreamChunk {
|
|
|
2505
2345
|
finishReason?: string;
|
|
2506
2346
|
toolCalls?: Array<ToolCallResult>;
|
|
2507
2347
|
thinking?: string;
|
|
2348
|
+
/**
|
|
2349
|
+
* Effective template `enable_thinking` value. Present on the terminal
|
|
2350
|
+
* chunk only; incremental text/reasoning chunks leave it unset.
|
|
2351
|
+
*/
|
|
2352
|
+
thinkingEnabled?: boolean | undefined;
|
|
2508
2353
|
numTokens?: number;
|
|
2509
2354
|
promptTokens?: number;
|
|
2510
2355
|
reasoningTokens?: number;
|
|
2511
2356
|
rawText?: string;
|
|
2357
|
+
/** Reasoning-redacted counterpart to `raw_text` on terminal chunks. */
|
|
2358
|
+
publicRawText?: string | undefined;
|
|
2359
|
+
/**
|
|
2360
|
+
* Whether terminal `text` is the authoritative parsed assistant content.
|
|
2361
|
+
* Generic emitters set true; Gemma streams visible content exclusively as
|
|
2362
|
+
* deltas and set false so session history commits the accumulated text.
|
|
2363
|
+
*/
|
|
2364
|
+
textAuthoritative?: boolean | undefined;
|
|
2365
|
+
/**
|
|
2366
|
+
* Number of prompt tokens served from the reused KV-cache prefix on
|
|
2367
|
+
* this turn. Populated on the terminal chunk (`done == true`) only;
|
|
2368
|
+
* `None` on mid-stream delta chunks.
|
|
2369
|
+
*
|
|
2370
|
+
* Zero on a cache miss or disabled reuse; equal to the matched
|
|
2371
|
+
* prefix length on a hit. Mirrors `ChatResult.cached_tokens`
|
|
2372
|
+
* verbatim so session-aware streaming consumers can observe
|
|
2373
|
+
* prefix-cache reuse without round-tripping to the non-streaming
|
|
2374
|
+
* path. Non-terminal chunks always carry `None` — only the
|
|
2375
|
+
* terminal chunk is authoritative.
|
|
2376
|
+
*/
|
|
2377
|
+
cachedTokens?: number | undefined;
|
|
2512
2378
|
/** Performance metrics (only present in the final chunk when `reportPerformance: true`) */
|
|
2513
2379
|
performance?: PerformanceMetrics;
|
|
2514
2380
|
/**
|
|
@@ -2531,16 +2397,181 @@ export interface ClassifyRotateResult {
|
|
|
2531
2397
|
image: Uint8Array;
|
|
2532
2398
|
}
|
|
2533
2399
|
|
|
2534
|
-
/** Statistics about cleanup operations (NAPI wrapper) */
|
|
2535
|
-
export interface CleanupStats {
|
|
2536
|
-
/** Number of training steps deleted */
|
|
2537
|
-
stepsDeleted: number;
|
|
2538
|
-
/** Number of generations deleted */
|
|
2539
|
-
generationsDeleted: number;
|
|
2540
|
-
/** Number of tool calls deleted */
|
|
2541
|
-
toolCallsDeleted: number;
|
|
2542
|
-
/** Number of logs deleted */
|
|
2543
|
-
logsDeleted: number;
|
|
2400
|
+
/** Statistics about cleanup operations (NAPI wrapper) */
|
|
2401
|
+
export interface CleanupStats {
|
|
2402
|
+
/** Number of training steps deleted */
|
|
2403
|
+
stepsDeleted: number;
|
|
2404
|
+
/** Number of generations deleted */
|
|
2405
|
+
generationsDeleted: number;
|
|
2406
|
+
/** Number of tool calls deleted */
|
|
2407
|
+
toolCallsDeleted: number;
|
|
2408
|
+
/** Number of logs deleted */
|
|
2409
|
+
logsDeleted: number;
|
|
2410
|
+
}
|
|
2411
|
+
|
|
2412
|
+
/**
|
|
2413
|
+
* Flush every accepted cold-tier block to disk, blocking until the
|
|
2414
|
+
* background writer has fsync+renamed each write enqueued before this call,
|
|
2415
|
+
* or `timeout_ms` elapses. Returns `true` when the drain completed — or when
|
|
2416
|
+
* the tier was never opened (nothing to flush) — and `false` on timeout.
|
|
2417
|
+
*
|
|
2418
|
+
* Called from the agent's one-shot (`mlx agent -p`) shutdown so a prompt's
|
|
2419
|
+
* just-persisted prefix blocks reach the drive before the process exits,
|
|
2420
|
+
* rather than being abandoned in the write queue.
|
|
2421
|
+
*
|
|
2422
|
+
* The payload flush is `fsync(2)`, not `F_FULLFSYNC`: a drained block
|
|
2423
|
+
* survives process death and kernel panic, but a sudden power loss can leave
|
|
2424
|
+
* it torn. Torn objects fail the payload checksum on the next read and are
|
|
2425
|
+
* pruned as a miss, so the cost is a recomputed prefix, never wrong state.
|
|
2426
|
+
*/
|
|
2427
|
+
export declare function coldCacheDrain(timeoutMs: number): boolean;
|
|
2428
|
+
|
|
2429
|
+
/**
|
|
2430
|
+
* Return a snapshot of the process-wide cold tier. Read-only: never opens
|
|
2431
|
+
* the tier itself, so it reports `enabled: false` until inference first
|
|
2432
|
+
* initializes the tier.
|
|
2433
|
+
*
|
|
2434
|
+
* The source snapshot is DESTRUCTURED rather than field-accessed, so a
|
|
2435
|
+
* counter added to `ColdCacheStats` and forgotten here fails to compile.
|
|
2436
|
+
* The failure this guards is silent and has already happened twice: a native
|
|
2437
|
+
* counter that never reaches this struct reaches no JS consumer either, and
|
|
2438
|
+
* nothing downstream can tell "the counter is zero" from "the counter was
|
|
2439
|
+
* never carried across".
|
|
2440
|
+
*/
|
|
2441
|
+
export declare function coldCacheStats(): ColdCacheStats;
|
|
2442
|
+
|
|
2443
|
+
/**
|
|
2444
|
+
* Snapshot of the process-wide SSD cold tier for paged prefix blocks.
|
|
2445
|
+
* Counters are cumulative since the tier was opened; all numeric values
|
|
2446
|
+
* are returned as `f64` to avoid BigInt round-trips in JS.
|
|
2447
|
+
*/
|
|
2448
|
+
export interface ColdCacheStats {
|
|
2449
|
+
/**
|
|
2450
|
+
* `false` until the tier is first opened by inference, or when opening
|
|
2451
|
+
* failed (fail-open: inference then runs without persistence).
|
|
2452
|
+
*/
|
|
2453
|
+
enabled: boolean;
|
|
2454
|
+
/** Cache root directory (empty while disabled). */
|
|
2455
|
+
root: string;
|
|
2456
|
+
/** Disk quota in bytes. */
|
|
2457
|
+
quotaBytes: number;
|
|
2458
|
+
/** Blocks restored from disk after validation. */
|
|
2459
|
+
hits: number;
|
|
2460
|
+
/** Lookups that found no usable block (includes corrupt entries). */
|
|
2461
|
+
misses: number;
|
|
2462
|
+
/**
|
|
2463
|
+
* Objects accepted onto the background write queue — K/V blocks and
|
|
2464
|
+
* family state sidecars alike, since both take a slot in the same queue.
|
|
2465
|
+
* `coldSidecarEnqueued` counts a subset of this; never sum them.
|
|
2466
|
+
*/
|
|
2467
|
+
enqueued: number;
|
|
2468
|
+
/**
|
|
2469
|
+
* Writes REFUSED at admission because the bounded queue was full. Same
|
|
2470
|
+
* object scope as `enqueued`. Disjoint from `writeErrors`, which counts
|
|
2471
|
+
* accepted writes that then failed to land — never sum the two into one
|
|
2472
|
+
* "lost writes" number.
|
|
2473
|
+
*/
|
|
2474
|
+
queueDrops: number;
|
|
2475
|
+
/**
|
|
2476
|
+
* Bytes that LANDED, credited after the payload sync, the commit rename
|
|
2477
|
+
* and the directory fsync all succeeded. Not an enqueue-time estimate:
|
|
2478
|
+
* a failed write credits nothing here and one `writeErrors` instead.
|
|
2479
|
+
*/
|
|
2480
|
+
bytesWritten: number;
|
|
2481
|
+
/** Total bytes read back on validated hits. */
|
|
2482
|
+
bytesRestored: number;
|
|
2483
|
+
/** Entries evicted to respect the quota / free-space reserve. */
|
|
2484
|
+
evictions: number;
|
|
2485
|
+
/** Entries that failed checksum/identity validation and were removed. */
|
|
2486
|
+
corruptions: number;
|
|
2487
|
+
/**
|
|
2488
|
+
* Writes the queue accepted that never reached disk — a read-only, full
|
|
2489
|
+
* or unmounted cache root, a failed rename, a failed fsync. The writer is
|
|
2490
|
+
* fail-open and reports the error to nobody, so without this a cache that
|
|
2491
|
+
* stores nothing at all still looks perfectly healthy.
|
|
2492
|
+
*/
|
|
2493
|
+
writeErrors: number;
|
|
2494
|
+
/**
|
|
2495
|
+
* Restores refused before any block was looked up. Neither a hit nor a
|
|
2496
|
+
* miss — so a refused restore reads as `0/0`, exactly like a turn that
|
|
2497
|
+
* never consulted the tier.
|
|
2498
|
+
*/
|
|
2499
|
+
restoreDeclines: number;
|
|
2500
|
+
}
|
|
2501
|
+
|
|
2502
|
+
/**
|
|
2503
|
+
* The native cold-restore allowlist, exposed so a test can assert it agrees
|
|
2504
|
+
* exactly with the TypeScript `COLD_TIER_RESTORE_FAMILIES` set.
|
|
2505
|
+
*/
|
|
2506
|
+
export declare function coldRestoreFamilies(): Array<string>;
|
|
2507
|
+
|
|
2508
|
+
/**
|
|
2509
|
+
* Return the process-wide sidecar counters. Unlike [`cold_cache_stats`] this
|
|
2510
|
+
* never consults the tier at all, so it is valid before any inference has run
|
|
2511
|
+
* and reports honestly even when the tier failed to open.
|
|
2512
|
+
*
|
|
2513
|
+
* The plain-Rust [`cold_sidecar_telemetry`] stays as it is: the parity harness
|
|
2514
|
+
* and the in-crate tests destructure `ColdSidecarTelemetry`, and a napi
|
|
2515
|
+
* `#[napi(object)]` return type cannot serve both.
|
|
2516
|
+
*/
|
|
2517
|
+
export declare function coldSidecarStats(): ColdSidecarStats;
|
|
2518
|
+
|
|
2519
|
+
/**
|
|
2520
|
+
* Snapshot of [`ColdSidecarTelemetry`] for JS. Counters are cumulative since
|
|
2521
|
+
* process start; all values are `f64` to avoid BigInt round-trips.
|
|
2522
|
+
*
|
|
2523
|
+
* Separate from [`ColdCacheStatsJs`] because this one isolates SIDECARS — the
|
|
2524
|
+
* recurrent and sliding-window state that lives outside the pool — while that
|
|
2525
|
+
* one is scoped to the write queue as a whole. Both structs carry an
|
|
2526
|
+
* `enqueued` and a `queue_drops`, and they are NOT disjoint: a sidecar
|
|
2527
|
+
* admission bumps both, so these are a subset of those and summing them
|
|
2528
|
+
* double-counts. The JS side keeps them apart by prefix (`coldEnqueued` vs
|
|
2529
|
+
* `coldSidecarEnqueued`); read the sidecar pair when you need "did the family
|
|
2530
|
+
* state persist?", the block pair when you need "is the writer keeping up?".
|
|
2531
|
+
*/
|
|
2532
|
+
export interface ColdSidecarStats {
|
|
2533
|
+
/**
|
|
2534
|
+
* Turns that reached a family's sidecar capture at all. Every other
|
|
2535
|
+
* counter here is a sub-count of this one, so `captureReached == 0`
|
|
2536
|
+
* separates "the finalize path never calls the capture" from "the capture
|
|
2537
|
+
* ran and declined".
|
|
2538
|
+
*/
|
|
2539
|
+
captureReached: number;
|
|
2540
|
+
/**
|
|
2541
|
+
* Turns whose persisted K/V chain covered no whole block, so there was no
|
|
2542
|
+
* prefix to anchor recurrent state under.
|
|
2543
|
+
*/
|
|
2544
|
+
chainEmpty: number;
|
|
2545
|
+
/**
|
|
2546
|
+
* Turns whose chain covered blocks but where no retained checkpoint sat at
|
|
2547
|
+
* or below its reach.
|
|
2548
|
+
*/
|
|
2549
|
+
boundarySkips: number;
|
|
2550
|
+
/**
|
|
2551
|
+
* Turns that selected a boundary already on disk — nothing written, and
|
|
2552
|
+
* nothing needed to be. The steady state of a repeated prompt, and the
|
|
2553
|
+
* only thing that tells a healthy run from a collapsed ladder.
|
|
2554
|
+
*/
|
|
2555
|
+
alreadyPersisted: number;
|
|
2556
|
+
/** Sidecars handed to the bounded writer queue. */
|
|
2557
|
+
enqueued: number;
|
|
2558
|
+
/** Sidecars the bounded writer queue refused because it was full. */
|
|
2559
|
+
queueDrops: number;
|
|
2560
|
+
/**
|
|
2561
|
+
* Restored sidecars a family actually INSTALLED as its live per-turn
|
|
2562
|
+
* state. The one read-side counter, and the only signal that separates
|
|
2563
|
+
* "restored and used" from "restored and silently re-derived by a full
|
|
2564
|
+
* O(prefix) replay" — every other counter, and text parity itself, is
|
|
2565
|
+
* satisfied by the replay.
|
|
2566
|
+
*/
|
|
2567
|
+
installed: number;
|
|
2568
|
+
/**
|
|
2569
|
+
* Restores a family THREW AWAY after the walk served them, restarting the
|
|
2570
|
+
* turn cold. Unlike `ColdCacheStats.restoreDeclines` this one comes AFTER
|
|
2571
|
+
* real `coldHits` and `coldBytesRestored`, so the turn looks like it
|
|
2572
|
+
* reused a prefix right up to the point where it recomputed all of it.
|
|
2573
|
+
*/
|
|
2574
|
+
restoreSuppressed: number;
|
|
2544
2575
|
}
|
|
2545
2576
|
|
|
2546
2577
|
/**
|
|
@@ -2579,7 +2610,11 @@ export interface ConversionOptions {
|
|
|
2579
2610
|
quantBits?: number;
|
|
2580
2611
|
/** Quantization group size (default: 64 for affine, 32 for mxfp8) */
|
|
2581
2612
|
quantGroupSize?: number;
|
|
2582
|
-
/**
|
|
2613
|
+
/**
|
|
2614
|
+
* Quantization mode: "affine" (default), "mxfp4", "mxfp8", "nvfp4", or
|
|
2615
|
+
* "sym8" (per-output-channel symmetric int8; qwen3_5 + qwen3_5_moe + lfm2/lfm2_moe + gemma4,
|
|
2616
|
+
* implies bits=8, no group_size — consciously NOT mlx-lm-loadable)
|
|
2617
|
+
*/
|
|
2583
2618
|
quantMode?: string;
|
|
2584
2619
|
/**
|
|
2585
2620
|
* Quantization recipe for per-layer mixed-bit quantization.
|
|
@@ -2591,6 +2626,35 @@ export interface ConversionOptions {
|
|
|
2591
2626
|
* Improves quantization quality by amplifying important weight channels.
|
|
2592
2627
|
*/
|
|
2593
2628
|
imatrixPath?: string;
|
|
2629
|
+
/**
|
|
2630
|
+
* Upgrade quantization to micro-scaling FP (mxfp4 / mxfp8).
|
|
2631
|
+
* When true, applies after the recipe predicate: eligible 8-bit affine
|
|
2632
|
+
* decisions become mxfp8 and 4-bit become mxfp4. Kept affine (not upgraded):
|
|
2633
|
+
* affine-only loaders (lm_head, embed_tokens, router.proj,
|
|
2634
|
+
* embedding_projection) at their recipe bits, MoE router gates (8-bit affine),
|
|
2635
|
+
* and the recipe-pinned attention/GDN projections (o_proj / out_proj /
|
|
2636
|
+
* in_proj_a / in_proj_b, 8-bit affine). Requires `quant_mode = "affine"`.
|
|
2637
|
+
* Forces `group_size = 32` for upgraded layers.
|
|
2638
|
+
*/
|
|
2639
|
+
quantMxfp?: boolean;
|
|
2640
|
+
/**
|
|
2641
|
+
* Optional Qwen MTP quantization policy: "off" (default), "cyankiwi", "all",
|
|
2642
|
+
* or "split" (alias "drafter").
|
|
2643
|
+
* "cyankiwi" keeps mtp.fc dense and quantizes only the MTP layer linears as
|
|
2644
|
+
* 4-bit affine group_size=32. For dense `qwen3_5` the quantized linears are
|
|
2645
|
+
* emitted into an MTPLX-compatible mtp.safetensors sidecar; for MoE
|
|
2646
|
+
* (`qwen3_5_moe`) there is no sidecar — they are quantized in place and stored
|
|
2647
|
+
* inline in the main safetensors shards.
|
|
2648
|
+
* "all" additionally quantizes mtp.fc. For dense `qwen3_5` the quantized MTP
|
|
2649
|
+
* linears land in the mtp.safetensors sidecar; for MoE (`qwen3_5_moe`) there
|
|
2650
|
+
* is no sidecar — they are quantized in place and stored inline in the main
|
|
2651
|
+
* safetensors shards.
|
|
2652
|
+
* "split"/"drafter" emits a body checkpoint with NO mtp.* tensors plus a
|
|
2653
|
+
* separate `mtp-drafter/` directory in mlx-vlm's `qwen3_5_mtp` format
|
|
2654
|
+
* (bare-keyed MTP head, format:mlx). It does NOT require --quantize/--q-recipe;
|
|
2655
|
+
* the body may be bf16 or already-quantized and the MTP head stays bf16.
|
|
2656
|
+
*/
|
|
2657
|
+
quantMtp?: string;
|
|
2594
2658
|
}
|
|
2595
2659
|
|
|
2596
2660
|
export interface ConversionResult {
|
|
@@ -2662,11 +2726,11 @@ export declare function createRandomQwen35Checkpoint(config: Qwen35Config, saveP
|
|
|
2662
2726
|
/**
|
|
2663
2727
|
* Create a random-init Qwen3.5 MoE model and save it to disk.
|
|
2664
2728
|
*
|
|
2665
|
-
* Spawns a dedicated
|
|
2666
|
-
* random-
|
|
2667
|
-
*
|
|
2668
|
-
*
|
|
2669
|
-
*
|
|
2729
|
+
* Spawns a dedicated model thread whose init runs
|
|
2730
|
+
* [`create_random_qwen35_moe_checkpoint_sync`] (random-init inner + save);
|
|
2731
|
+
* the thread holds no state and is dropped once the promise resolves, so
|
|
2732
|
+
* the in-memory model is released as soon as the checkpoint has been
|
|
2733
|
+
* written. Used by TypeScript test fixtures that need an on-disk
|
|
2670
2734
|
* checkpoint without keeping a NAPI model instance alive.
|
|
2671
2735
|
*/
|
|
2672
2736
|
export declare function createRandomQwen35MoeCheckpoint(config: Qwen35MoeConfig, savePath: string): Promise<undefined>;
|
|
@@ -2717,6 +2781,8 @@ export declare const enum DType {
|
|
|
2717
2781
|
BFloat16 = 3,
|
|
2718
2782
|
Uint32 = 4,
|
|
2719
2783
|
Uint8 = 5,
|
|
2784
|
+
/** Signed int8 — sym8 per-output-channel symmetric quantized weights. */
|
|
2785
|
+
Int8 = 6,
|
|
2720
2786
|
}
|
|
2721
2787
|
|
|
2722
2788
|
/** Document element type */
|
|
@@ -2809,6 +2875,26 @@ export interface FunctionParameters {
|
|
|
2809
2875
|
required?: Array<string>;
|
|
2810
2876
|
}
|
|
2811
2877
|
|
|
2878
|
+
/**
|
|
2879
|
+
* How many GDN prefix checkpoints the native store holds across all owners
|
|
2880
|
+
* ([`GDN_PREFIX_CHECKPOINT_LIMIT`]), exposed for the same reason
|
|
2881
|
+
* [`cold_restore_families`] is: it is one half of a cross-language invariant
|
|
2882
|
+
* and nothing else carries it over the boundary.
|
|
2883
|
+
*
|
|
2884
|
+
* The other half is `MAX_CONCURRENCY` in
|
|
2885
|
+
* `packages/agent/src/extensions/subagent.ts`. The store's demand is
|
|
2886
|
+
* `MAX_CONCURRENCY + 1` — one owner per concurrent child loop plus the root
|
|
2887
|
+
* session — and the cliff sits exactly one owner past the cap, where every
|
|
2888
|
+
* owner holds a single entry and the store is still over it, so each publish
|
|
2889
|
+
* takes somebody's last checkpoint. `retention_sim` measures that as 0 blind
|
|
2890
|
+
* turns at five owners and 28 of 40 at six.
|
|
2891
|
+
*
|
|
2892
|
+
* No Rust gate can see a TypeScript-only edit, so raising the fleet alone
|
|
2893
|
+
* would land in that regime with every Rust gate still green.
|
|
2894
|
+
* `packages/agent/__test__/gdn-checkpoint-capacity.test.ts` is what stops it.
|
|
2895
|
+
*/
|
|
2896
|
+
export declare function gdnPrefixCheckpointLimit(): number;
|
|
2897
|
+
|
|
2812
2898
|
/**
|
|
2813
2899
|
* Gemma 4 model configuration (dense variant).
|
|
2814
2900
|
*
|
|
@@ -2843,6 +2929,20 @@ export interface Gemma4Config {
|
|
|
2843
2929
|
/** Head dimension for global layers. If None, uses head_dim. */
|
|
2844
2930
|
globalHeadDim?: number;
|
|
2845
2931
|
attentionKEqV: boolean;
|
|
2932
|
+
/**
|
|
2933
|
+
* True for the unified multimodal Gemma 4 checkpoint
|
|
2934
|
+
* (`model_type == "gemma4_unified"` or
|
|
2935
|
+
* `architectures[0] == "Gemma4UnifiedForConditionalGeneration"`).
|
|
2936
|
+
* The text decoder is shared, but the unified checkpoint carries
|
|
2937
|
+
* vision/audio embedder weights that must be dropped in a text-only load.
|
|
2938
|
+
*/
|
|
2939
|
+
isUnified: boolean;
|
|
2940
|
+
/**
|
|
2941
|
+
* `text_config.use_bidirectional_attention` from the unified checkpoint
|
|
2942
|
+
* (e.g. `"vision"`). Parsed for a stable struct surface; the text-only
|
|
2943
|
+
* decode path does not consume it.
|
|
2944
|
+
*/
|
|
2945
|
+
useBidirectionalAttention?: string;
|
|
2846
2946
|
finalLogitSoftcapping?: number;
|
|
2847
2947
|
perLayerInputEmbeds: boolean;
|
|
2848
2948
|
hiddenSizePerLayerInput?: number;
|
|
@@ -2861,10 +2961,97 @@ export interface Gemma4Config {
|
|
|
2861
2961
|
topKExperts?: number;
|
|
2862
2962
|
moeIntermediateSize?: number;
|
|
2863
2963
|
visionConfig?: Gemma4VisionConfig;
|
|
2964
|
+
/**
|
|
2965
|
+
* Encoder-free vision config for the unified multimodal checkpoint.
|
|
2966
|
+
* `Some` only when `is_unified` and the checkpoint carries a
|
|
2967
|
+
* `vision_config` sub-dict. Disjoint from `vision_config` (the SigLIP
|
|
2968
|
+
* path) — the unified vision embedder is built from this instead.
|
|
2969
|
+
*/
|
|
2970
|
+
unifiedVisionConfig?: UnifiedVisionConfig;
|
|
2864
2971
|
imageTokenId?: number;
|
|
2865
2972
|
boiTokenId?: number;
|
|
2866
2973
|
eoiTokenId?: number;
|
|
2867
2974
|
visionSoftTokensPerImage?: number;
|
|
2975
|
+
/**
|
|
2976
|
+
* True when the checkpoint declares an `audio_config` sub-dict. Parallels
|
|
2977
|
+
* `unified_vision_config.is_some()`; gates the un-drop + load of
|
|
2978
|
+
* `embed_audio` weights and the audio merge path.
|
|
2979
|
+
*/
|
|
2980
|
+
hasAudio: boolean;
|
|
2981
|
+
/**
|
|
2982
|
+
* Audio placeholder token id (258881). Each `<audio>` placeholder expands to
|
|
2983
|
+
* `boa + audio_token × n_frames + eoa`.
|
|
2984
|
+
*/
|
|
2985
|
+
audioTokenId?: number;
|
|
2986
|
+
/** Begin-of-audio token id (256000), emitted before the audio token run. */
|
|
2987
|
+
boaTokenId?: number;
|
|
2988
|
+
/**
|
|
2989
|
+
* End-of-audio token id, parsed from the config's `eoa_token_index` (258883).
|
|
2990
|
+
* A real appended token (like `eoi`), despite the "index" name.
|
|
2991
|
+
*/
|
|
2992
|
+
eoaTokenId?: number;
|
|
2993
|
+
/**
|
|
2994
|
+
* Raw audio samples per audio token (640 = 40 ms @ 16 kHz), from
|
|
2995
|
+
* `audio_config.audio_samples_per_token`. Frame size for the encoder-free
|
|
2996
|
+
* pad+reshape feature extractor.
|
|
2997
|
+
*/
|
|
2998
|
+
audioSamplesPerToken?: number;
|
|
2999
|
+
/**
|
|
3000
|
+
* GPU memory budget for paged KV cache in megabytes.
|
|
3001
|
+
* Only used when `use_block_paged_cache` is true.
|
|
3002
|
+
* Default: auto-sized to cover `max_position_embeddings` for the
|
|
3003
|
+
* physical full-attention layers.
|
|
3004
|
+
*/
|
|
3005
|
+
pagedCacheMemoryMb?: number | undefined;
|
|
3006
|
+
/**
|
|
3007
|
+
* Block size for paged attention (tokens per block).
|
|
3008
|
+
* Only used when `use_block_paged_cache` is true.
|
|
3009
|
+
* Default: 16.
|
|
3010
|
+
*/
|
|
3011
|
+
pagedBlockSize?: number | undefined;
|
|
3012
|
+
/**
|
|
3013
|
+
* Use the new block-paged KV cache adapter (`PagedKVCacheAdapter`).
|
|
3014
|
+
*
|
|
3015
|
+
* When `Some(true)` or unset (the default), `Gemma4Inner` builds
|
|
3016
|
+
* model-independent KV-cache specs, groups them, and allocates a
|
|
3017
|
+
* `BlockAllocator` + `LayerKVPool` pair for physical full-attention
|
|
3018
|
+
* layers. Sliding-window layers still use `RotatingKVCache` until
|
|
3019
|
+
* true paged sliding-window groups are wired. KV-shared layers are
|
|
3020
|
+
* aliases: they reuse their anchor's cache slot and do not allocate
|
|
3021
|
+
* separate physical storage.
|
|
3022
|
+
*
|
|
3023
|
+
* Default: `true` (paged adapter on; opt-out via
|
|
3024
|
+
* `use_block_paged_cache: false` in `config.json` to use the flat
|
|
3025
|
+
* (non-paged) all-`Gemma4LayerCache` path instead). Parity between
|
|
3026
|
+
* the two paths is verified by
|
|
3027
|
+
* `crates/mlx-core/tests/gemma4_paged_vs_flat_parity.rs` against
|
|
3028
|
+
* real Gemma-4-E2B weights.
|
|
3029
|
+
*/
|
|
3030
|
+
useBlockPagedCache?: boolean | undefined;
|
|
3031
|
+
/**
|
|
3032
|
+
* Persist full paged KV blocks — and gemma4's out-of-pool sliding-window
|
|
3033
|
+
* state, as a cold-tier sidecar — to the SSD cold tier so warm prefixes
|
|
3034
|
+
* survive process restarts. Off unless explicitly enabled.
|
|
3035
|
+
*
|
|
3036
|
+
* An EXPLICIT value here is authoritative and beats the ambient
|
|
3037
|
+
* `MLX_PERSIST_PAGED_CACHE` default (`cold_tier::resolve_persist_cold`).
|
|
3038
|
+
*/
|
|
3039
|
+
persistPagedCache?: boolean | undefined;
|
|
3040
|
+
}
|
|
3041
|
+
|
|
3042
|
+
/** Optional load-time settings for [`Gemma4Model::load`]. */
|
|
3043
|
+
export interface Gemma4LoadOptions {
|
|
3044
|
+
/**
|
|
3045
|
+
* Directory of a draft checkpoint (config.json + safetensors) to load
|
|
3046
|
+
* alongside the target model for speculative decoding — either a
|
|
3047
|
+
* DSpark draft or a Google assistant draft; the kind is probed from
|
|
3048
|
+
* the draft config.json. When omitted, `<model_path>/draft/` is loaded
|
|
3049
|
+
* automatically when present. Draft decoding runs only on the flat
|
|
3050
|
+
* KV-cache path: setting this while the model config explicitly enables
|
|
3051
|
+
* `use_block_paged_cache` is a hard load error, and an unset
|
|
3052
|
+
* `use_block_paged_cache` is forced to `false`.
|
|
3053
|
+
*/
|
|
3054
|
+
draftModelPath?: string;
|
|
2868
3055
|
}
|
|
2869
3056
|
|
|
2870
3057
|
/**
|
|
@@ -2937,19 +3124,19 @@ export interface GenerationConfig {
|
|
|
2937
3124
|
/** Number of recent tokens to consider for frequency penalty (default: 20) */
|
|
2938
3125
|
frequencyContextSize?: number;
|
|
2939
3126
|
/**
|
|
2940
|
-
* Stop if same token repeats this many times consecutively (default:
|
|
2941
|
-
*
|
|
3127
|
+
* Stop if same token repeats this many times consecutively (default: 0 = disabled).
|
|
3128
|
+
* Opt in by setting a positive value to guard against degenerate repetitive generation.
|
|
2942
3129
|
*/
|
|
2943
3130
|
maxConsecutiveTokens?: number;
|
|
2944
3131
|
/**
|
|
2945
|
-
* Stop if a pattern repeats this many times consecutively (default:
|
|
2946
|
-
*
|
|
3132
|
+
* Stop if a pattern repeats this many times consecutively (default: 0 = disabled).
|
|
3133
|
+
* Opt in with a positive value to detect patterns like "A B A B A B".
|
|
2947
3134
|
* Uses range-based detection: checks all pattern sizes from 2 to ngram_size.
|
|
2948
3135
|
*/
|
|
2949
3136
|
maxNgramRepeats?: number;
|
|
2950
3137
|
/**
|
|
2951
|
-
* Maximum pattern size for repetition detection (default:
|
|
2952
|
-
*
|
|
3138
|
+
* Maximum pattern size for repetition detection (default: 0 = disabled).
|
|
3139
|
+
* When enabled, all pattern sizes from 2 up to this value are checked each decode step.
|
|
2953
3140
|
* Larger values catch long phrase-level repetition common in small models.
|
|
2954
3141
|
*/
|
|
2955
3142
|
ngramSize?: number;
|
|
@@ -2964,29 +3151,6 @@ export interface GenerationConfig {
|
|
|
2964
3151
|
* Set to 0 to disable chunking and process the entire prompt at once.
|
|
2965
3152
|
*/
|
|
2966
3153
|
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
3154
|
}
|
|
2991
3155
|
|
|
2992
3156
|
export interface GenerationProfile {
|
|
@@ -3010,6 +3174,24 @@ export interface GenerationProfile {
|
|
|
3010
3174
|
timeToFirstTokenMs: number;
|
|
3011
3175
|
/** Per-phase breakdown. */
|
|
3012
3176
|
phases: Array<PhaseProfile>;
|
|
3177
|
+
/**
|
|
3178
|
+
* MTP speculative decode: mean accepted *draft* tokens per cycle
|
|
3179
|
+
* (excludes the always-verified token). Historical drafts-only metric.
|
|
3180
|
+
*/
|
|
3181
|
+
mtpMeanAcceptedTokens?: number;
|
|
3182
|
+
/**
|
|
3183
|
+
* MTP speculative decode: mean *committed* tokens per cycle, INCLUDING
|
|
3184
|
+
* the always-verified token (`mtp_accepted_drafts_total / mtp_cycles
|
|
3185
|
+
* + 1.0`). mlx-vlm-comparable headline; equals mlx-vlm's
|
|
3186
|
+
* `(accepted_drafts + rounds) / rounds` (`common.py:247`).
|
|
3187
|
+
*/
|
|
3188
|
+
mtpMeanAcceptedTokensTotal?: number;
|
|
3189
|
+
/** MTP speculative decode: per-draft-position acceptance rate. */
|
|
3190
|
+
mtpAcceptanceByPosition?: Array<number>;
|
|
3191
|
+
/** MTP speculative decode: number of draft+verify cycles executed. */
|
|
3192
|
+
mtpCycles?: number;
|
|
3193
|
+
/** MTP speculative decode: mean attempted draft depth per cycle. */
|
|
3194
|
+
mtpMeanDepth?: number;
|
|
3013
3195
|
/** Memory snapshot before generation. */
|
|
3014
3196
|
memoryBefore?: MemorySnapshot;
|
|
3015
3197
|
/** Memory snapshot after generation. */
|
|
@@ -3036,8 +3218,8 @@ export interface GenerationWithToolCalls {
|
|
|
3036
3218
|
toolCalls: Array<ToolCallRecord>;
|
|
3037
3219
|
}
|
|
3038
3220
|
|
|
3039
|
-
/**
|
|
3040
|
-
export declare function
|
|
3221
|
+
/** Sample MLX's GPU memory counters. See [`GpuMemorySnapshot`]. */
|
|
3222
|
+
export declare function getMemorySnapshot(): GpuMemorySnapshot;
|
|
3041
3223
|
|
|
3042
3224
|
/** Retrieve all collected profiling data as a `ProfilingSession`. */
|
|
3043
3225
|
export declare function getProfilingData(): ProfilingSession;
|
|
@@ -3047,6 +3229,13 @@ export interface GgufConversionOptions {
|
|
|
3047
3229
|
inputPath: string;
|
|
3048
3230
|
/** Output directory for converted SafeTensors model */
|
|
3049
3231
|
outputDir: string;
|
|
3232
|
+
/**
|
|
3233
|
+
* Optional directory containing the authoritative HuggingFace config and
|
|
3234
|
+
* tokenizer/processor assets. GGUF metadata is not rich enough to recreate
|
|
3235
|
+
* unified Gemma4 config fields such as head_dim, layer_types, vision, and
|
|
3236
|
+
* audio configuration exactly.
|
|
3237
|
+
*/
|
|
3238
|
+
configSourceDir?: string;
|
|
3050
3239
|
/** Target dtype: "float32", "float16", "bfloat16" (default: keep original) */
|
|
3051
3240
|
dtype?: string;
|
|
3052
3241
|
/** Enable verbose logging */
|
|
@@ -3080,6 +3269,25 @@ export interface GgufConversionOptions {
|
|
|
3080
3269
|
* This makes the safetensors compatible with mlx-vlm.
|
|
3081
3270
|
*/
|
|
3082
3271
|
vlmKeyPrefix?: boolean;
|
|
3272
|
+
/**
|
|
3273
|
+
* Upgrade quantization to micro-scaling FP (mxfp4 / mxfp8).
|
|
3274
|
+
* When true, applies after the recipe predicate: eligible 8-bit affine
|
|
3275
|
+
* decisions become mxfp8 and 4-bit become mxfp4. Kept affine (not upgraded):
|
|
3276
|
+
* affine-only loaders (lm_head, embed_tokens, router.proj,
|
|
3277
|
+
* embedding_projection) at their recipe bits, MoE router gates (8-bit affine),
|
|
3278
|
+
* and the recipe-pinned attention/GDN projections (o_proj / out_proj /
|
|
3279
|
+
* in_proj_a / in_proj_b, 8-bit affine). Requires `quant_mode = "affine"`.
|
|
3280
|
+
* Forces `group_size = 32` for upgraded layers.
|
|
3281
|
+
*/
|
|
3282
|
+
quantMxfp?: boolean;
|
|
3283
|
+
/**
|
|
3284
|
+
* Import ggml Q4_K / Q5_K / Q6_K tensors as MLX K-quant arrays instead of
|
|
3285
|
+
* rejecting them (default: false). The blocks are repacked, never
|
|
3286
|
+
* dequantized, so the output keeps the source file's weights and byte size.
|
|
3287
|
+
* With this off, Q6_K remains the Gemma4 token-embedding BF16 fallback and
|
|
3288
|
+
* Q4_K / Q5_K are an error.
|
|
3289
|
+
*/
|
|
3290
|
+
importKQuants?: boolean;
|
|
3083
3291
|
}
|
|
3084
3292
|
|
|
3085
3293
|
export interface GgufConversionResult {
|
|
@@ -3095,6 +3303,33 @@ export interface GpuInfo {
|
|
|
3095
3303
|
architectureGen: number;
|
|
3096
3304
|
}
|
|
3097
3305
|
|
|
3306
|
+
/**
|
|
3307
|
+
* Snapshot of MLX's GPU memory counters at this instant. All values
|
|
3308
|
+
* are in bytes. On Apple Silicon, GPU and CPU share unified memory,
|
|
3309
|
+
* so these are NOT a separate "VRAM" pool — they reflect MLX's own
|
|
3310
|
+
* tracking of `StorageModePrivate` Metal buffers (model weights,
|
|
3311
|
+
* `LayerKVPool`, transient intermediate tensors) attributed to the
|
|
3312
|
+
* MLX runtime in this process.
|
|
3313
|
+
*
|
|
3314
|
+
* Useful for live observability during long-running sessions:
|
|
3315
|
+
*
|
|
3316
|
+
* ```js
|
|
3317
|
+
* const { getMemorySnapshot } = require('@mlx-node/core');
|
|
3318
|
+
* setInterval(() => {
|
|
3319
|
+
* const m = getMemorySnapshot();
|
|
3320
|
+
* console.log(`active=${(m.activeBytes/1e9).toFixed(2)}GB peak=${(m.peakBytes/1e9).toFixed(2)}GB cache=${(m.cacheBytes/1e9).toFixed(2)}GB`);
|
|
3321
|
+
* }, 1000);
|
|
3322
|
+
* ```
|
|
3323
|
+
*/
|
|
3324
|
+
export interface GpuMemorySnapshot {
|
|
3325
|
+
/** Current actively-used GPU buffer bytes (excludes cache pool). */
|
|
3326
|
+
activeBytes: number;
|
|
3327
|
+
/** Peak GPU buffer bytes since the last `resetPeakMemory()` call. */
|
|
3328
|
+
peakBytes: number;
|
|
3329
|
+
/** Bytes held in MLX's caching allocator (released by `clearCache`). */
|
|
3330
|
+
cacheBytes: number;
|
|
3331
|
+
}
|
|
3332
|
+
|
|
3098
3333
|
/** Configuration for the GRPO training engine */
|
|
3099
3334
|
export interface GrpoEngineConfig {
|
|
3100
3335
|
/** Learning rate (default: 1e-6) */
|
|
@@ -3356,6 +3591,69 @@ export interface Lfm2Config {
|
|
|
3356
3591
|
eosTokenId: number;
|
|
3357
3592
|
bosTokenId: number;
|
|
3358
3593
|
padTokenId: number;
|
|
3594
|
+
/**
|
|
3595
|
+
* GPU memory budget for paged KV cache in megabytes.
|
|
3596
|
+
* Only used when `use_block_paged_cache` is true.
|
|
3597
|
+
* Default: 2048 (2GB).
|
|
3598
|
+
*/
|
|
3599
|
+
pagedCacheMemoryMb?: number | undefined;
|
|
3600
|
+
/**
|
|
3601
|
+
* Block size for paged attention (tokens per block).
|
|
3602
|
+
* Only used when `use_block_paged_cache` is true.
|
|
3603
|
+
* Default: 16.
|
|
3604
|
+
*/
|
|
3605
|
+
pagedBlockSize?: number | undefined;
|
|
3606
|
+
/**
|
|
3607
|
+
* Use the new block-paged KV cache adapter (`PagedKVCacheAdapter`).
|
|
3608
|
+
*
|
|
3609
|
+
* Default: `true` since 2026-04-28 (parity-verified via
|
|
3610
|
+
* `crates/mlx-core/tests/lfm2_paged_vs_flat_parity.rs` against real
|
|
3611
|
+
* LFM2.5-1.2B weights: byte-equal greedy decode + prefix-reuse
|
|
3612
|
+
* byte-equal at BF16). Wired through
|
|
3613
|
+
* `Lfm2DecoderLayer::forward_paged_or_flat`.
|
|
3614
|
+
*
|
|
3615
|
+
* Per-layer routing: LFM2's hybrid architecture means only
|
|
3616
|
+
* `full_attention` layers go through the paged adapter; conv layers
|
|
3617
|
+
* stay on the existing flat `Lfm2LayerCache::Conv(ArraysCache)`
|
|
3618
|
+
* storage regardless of this flag. The `LayerKVPool` is sized to
|
|
3619
|
+
* the count of `full_attention` layers and indexed by
|
|
3620
|
+
* attention-ordinal (via `config.full_attn_idxs()`), not by absolute
|
|
3621
|
+
* layer index.
|
|
3622
|
+
*
|
|
3623
|
+
* Opt out with `use_block_paged_cache: Some(false)` to revert to the
|
|
3624
|
+
* fully flat `Lfm2LayerCache` path on all layers.
|
|
3625
|
+
*/
|
|
3626
|
+
useBlockPagedCache?: boolean | undefined;
|
|
3627
|
+
/**
|
|
3628
|
+
* MLP intermediate size for the DENSE-in-MoE layers (`layer_idx <
|
|
3629
|
+
* num_dense_layers`). Used DIRECTLY (no 2/3 `computed_ff_dim()` shrink).
|
|
3630
|
+
* Only present on MoE checkpoints.
|
|
3631
|
+
*/
|
|
3632
|
+
intermediateSize?: number | undefined;
|
|
3633
|
+
/** Per-expert MLP intermediate size for the sparse MoE layers. */
|
|
3634
|
+
moeIntermediateSize?: number | undefined;
|
|
3635
|
+
/** Total number of routed experts. */
|
|
3636
|
+
numExperts?: number | undefined;
|
|
3637
|
+
/** Top-k experts selected per token. */
|
|
3638
|
+
numExpertsPerTok?: number | undefined;
|
|
3639
|
+
/** Number of leading DENSE layers before MoE layers begin. */
|
|
3640
|
+
numDenseLayers?: number | undefined;
|
|
3641
|
+
/**
|
|
3642
|
+
* Renormalize the top-k routing weights to sum to 1 (`/(sum+1e-20)`).
|
|
3643
|
+
*
|
|
3644
|
+
* `Option<bool>` so TS callers may omit it (napi renders bare `bool` as
|
|
3645
|
+
* required). Absent (None) is read as `true` everywhere via
|
|
3646
|
+
* `.unwrap_or(true)`, matching the prior `default = "default_true"`.
|
|
3647
|
+
*/
|
|
3648
|
+
normTopkProb?: boolean | undefined;
|
|
3649
|
+
/**
|
|
3650
|
+
* Add the learned per-expert bias to the post-softmax gates BEFORE top-k.
|
|
3651
|
+
*
|
|
3652
|
+
* `Option<bool>` so TS callers may omit it (napi renders bare `bool` as
|
|
3653
|
+
* required). Absent (None) is read as `true` everywhere via
|
|
3654
|
+
* `.unwrap_or(true)`, matching the prior `default = "default_true"`.
|
|
3655
|
+
*/
|
|
3656
|
+
useExpertBias?: boolean | undefined;
|
|
3359
3657
|
}
|
|
3360
3658
|
|
|
3361
3659
|
export interface MemorySnapshot {
|
|
@@ -3367,6 +3665,28 @@ export interface MemorySnapshot {
|
|
|
3367
3665
|
cacheBytes: number;
|
|
3368
3666
|
}
|
|
3369
3667
|
|
|
3668
|
+
/**
|
|
3669
|
+
* Return a snapshot of the MLX allocator's memory counters. Primarily
|
|
3670
|
+
* useful for dashboards and for debugging the `MLX_CACHE_LIMIT_GB`
|
|
3671
|
+
* override. Read-only — does not mutate allocator state.
|
|
3672
|
+
*/
|
|
3673
|
+
export declare function memoryStats(): MemoryStats;
|
|
3674
|
+
|
|
3675
|
+
/**
|
|
3676
|
+
* Snapshot of the MLX Metal allocator's memory state. All values are in
|
|
3677
|
+
* bytes and returned as `f64` to avoid forcing BigInt round-trips in JS.
|
|
3678
|
+
*/
|
|
3679
|
+
export interface MemoryStats {
|
|
3680
|
+
/** Actively-used memory (excludes the cached free-pool). */
|
|
3681
|
+
active: number;
|
|
3682
|
+
/** Peak memory usage since load / the last `resetPeakMemory`. */
|
|
3683
|
+
peak: number;
|
|
3684
|
+
/** Cache / free-pool memory currently held by the allocator. */
|
|
3685
|
+
cache: number;
|
|
3686
|
+
/** Metal `max_recommended_working_set_size` snapshot (0 on non-Metal). */
|
|
3687
|
+
wiredLimit: number;
|
|
3688
|
+
}
|
|
3689
|
+
|
|
3370
3690
|
/** Full model configuration */
|
|
3371
3691
|
export interface ModelConfig {
|
|
3372
3692
|
visionConfig: VisionConfig;
|
|
@@ -3380,6 +3700,21 @@ export interface ModelConfig {
|
|
|
3380
3700
|
eosTokenId: number;
|
|
3381
3701
|
}
|
|
3382
3702
|
|
|
3703
|
+
/**
|
|
3704
|
+
* Ordering policy for structured multimodal content parts handed to a
|
|
3705
|
+
* checkpoint-provided Jinja template.
|
|
3706
|
+
*
|
|
3707
|
+
* The default preserves the generic serializer's existing text-before-media
|
|
3708
|
+
* behavior. PaddleOCR-VL and Qianfan-OCR were trained with image placeholders
|
|
3709
|
+
* before the instruction and opt into
|
|
3710
|
+
* [`MultimodalContentOrder::ImagesThenText`] at their adapter boundaries.
|
|
3711
|
+
* Audio remains after text in both modes.
|
|
3712
|
+
*/
|
|
3713
|
+
export declare const enum MultimodalContentOrder {
|
|
3714
|
+
TextThenMedia = 'textThenMedia',
|
|
3715
|
+
ImagesThenText = 'imagesThenText',
|
|
3716
|
+
}
|
|
3717
|
+
|
|
3383
3718
|
/** Result from document orientation classification. */
|
|
3384
3719
|
export interface OrientationResult {
|
|
3385
3720
|
/** Detected rotation angle (0, 90, 180, or 270 degrees) */
|
|
@@ -3410,56 +3745,6 @@ export interface OutputStoreConfig {
|
|
|
3410
3745
|
localPath: string;
|
|
3411
3746
|
}
|
|
3412
3747
|
|
|
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
3748
|
/** A text paragraph */
|
|
3464
3749
|
export interface Paragraph {
|
|
3465
3750
|
content: string;
|
|
@@ -3541,6 +3826,52 @@ export interface PerformanceMetrics {
|
|
|
3541
3826
|
* Excludes the first token (counted as prefill).
|
|
3542
3827
|
*/
|
|
3543
3828
|
decodeTokensPerSecond: number;
|
|
3829
|
+
/**
|
|
3830
|
+
* MTP speculative decode: mean accepted *draft* tokens per cycle
|
|
3831
|
+
* (range `[0, depth]`). EXCLUDES the always-verified token each cycle
|
|
3832
|
+
* commits. `None` on plain autoregressive runs where no MTP cycle
|
|
3833
|
+
* executed. This is the historical drafts-only metric; for the
|
|
3834
|
+
* mlx-vlm-comparable headline see [`Self::mtp_mean_accepted_tokens_total`].
|
|
3835
|
+
*/
|
|
3836
|
+
mtpMeanAcceptedTokens?: number;
|
|
3837
|
+
/**
|
|
3838
|
+
* MTP speculative decode: mean *committed* tokens per cycle, INCLUDING
|
|
3839
|
+
* the single always-verified token each cycle emits — i.e.
|
|
3840
|
+
* `mtp_accepted_drafts_total / mtp_cycles + 1.0`. This is the
|
|
3841
|
+
* mlx-vlm-comparable headline accept rate: it equals mlx-vlm's
|
|
3842
|
+
* `mean_accepted_tokens = (accepted_drafts + rounds) / rounds`
|
|
3843
|
+
* (`mlx-vlm/mlx_vlm/speculative/common.py:247`), where our
|
|
3844
|
+
* `mtp_cycles` is the 1:1 analog of mlx-vlm's `rounds` (one
|
|
3845
|
+
* draft+verify iteration; `record_mtp_cycle` is called exactly once
|
|
3846
|
+
* per cycle). The per-cycle `+1.0` matches mlx-vlm's `+rounds`
|
|
3847
|
+
* assumption — every round commits exactly one verified token
|
|
3848
|
+
* (the residual on partial-accept, the bonus on full-accept), even
|
|
3849
|
+
* when the final cycle's tail is EOS/length-truncated downstream
|
|
3850
|
+
* (mlx-vlm makes the same assumption: it appends to `accept_lens`
|
|
3851
|
+
* once per round regardless of truncation). `None` on plain
|
|
3852
|
+
* autoregressive runs.
|
|
3853
|
+
*/
|
|
3854
|
+
mtpMeanAcceptedTokensTotal?: number;
|
|
3855
|
+
/**
|
|
3856
|
+
* MTP speculative decode: per-draft-position acceptance rate
|
|
3857
|
+
* (index = draft position). `None` on plain autoregressive runs.
|
|
3858
|
+
*/
|
|
3859
|
+
mtpAcceptanceByPosition?: Array<number>;
|
|
3860
|
+
/**
|
|
3861
|
+
* MTP speculative decode: number of draft+verify cycles executed.
|
|
3862
|
+
* `None` on plain autoregressive runs.
|
|
3863
|
+
*/
|
|
3864
|
+
mtpCycles?: number;
|
|
3865
|
+
/**
|
|
3866
|
+
* MTP speculative decode: mean attempted draft depth per cycle.
|
|
3867
|
+
* `None` on plain autoregressive runs.
|
|
3868
|
+
*/
|
|
3869
|
+
mtpMeanDepth?: number;
|
|
3870
|
+
/**
|
|
3871
|
+
* Optional decode phase breakdown. Present when decode profiling
|
|
3872
|
+
* is enabled via `MLX_PROFILE_DECODE=1` or `setProfilingEnabled(true)`.
|
|
3873
|
+
*/
|
|
3874
|
+
profilePhases?: Array<PhaseProfile>;
|
|
3544
3875
|
}
|
|
3545
3876
|
|
|
3546
3877
|
export interface PhaseProfile {
|
|
@@ -3554,6 +3885,76 @@ export interface PhaseProfile {
|
|
|
3554
3885
|
count: number;
|
|
3555
3886
|
}
|
|
3556
3887
|
|
|
3888
|
+
/**
|
|
3889
|
+
* Per-call Viterbi calibration overrides.
|
|
3890
|
+
*
|
|
3891
|
+
* Any field set to `Some(_)` overrides the corresponding bias from the
|
|
3892
|
+
* model's default calibration (loaded from `viterbi_calibration.json`
|
|
3893
|
+
* at load time). Missing fields fall back to the default.
|
|
3894
|
+
*/
|
|
3895
|
+
export interface PrivacyCalibration {
|
|
3896
|
+
transitionBiasBackgroundStay?: number;
|
|
3897
|
+
transitionBiasBackgroundToStart?: number;
|
|
3898
|
+
transitionBiasEndToBackground?: number;
|
|
3899
|
+
transitionBiasEndToStart?: number;
|
|
3900
|
+
transitionBiasInsideToContinue?: number;
|
|
3901
|
+
transitionBiasInsideToEnd?: number;
|
|
3902
|
+
}
|
|
3903
|
+
|
|
3904
|
+
/**
|
|
3905
|
+
* Options for [`PrivacyFilterModelJs::classify`].
|
|
3906
|
+
*
|
|
3907
|
+
* - `threshold` (default `0.5`): minimum mean per-token probability for
|
|
3908
|
+
* an extracted span to be returned.
|
|
3909
|
+
* - `calibration`: per-call overrides on top of the checkpoint default.
|
|
3910
|
+
* - `return_tokens` (default `false`): when `true`, the result includes
|
|
3911
|
+
* a `tokens` array with one entry per input token.
|
|
3912
|
+
*/
|
|
3913
|
+
export interface PrivacyClassifyOptions {
|
|
3914
|
+
threshold?: number;
|
|
3915
|
+
calibration?: PrivacyCalibration;
|
|
3916
|
+
returnTokens?: boolean;
|
|
3917
|
+
}
|
|
3918
|
+
|
|
3919
|
+
/** Result of [`PrivacyFilterModelJs::classify`]. */
|
|
3920
|
+
export interface PrivacyClassifyResult {
|
|
3921
|
+
entities: Array<PrivacyEntity>;
|
|
3922
|
+
tokens?: Array<PrivacyToken>;
|
|
3923
|
+
}
|
|
3924
|
+
|
|
3925
|
+
/**
|
|
3926
|
+
* A privacy entity detected by [`PrivacyFilterModelJs::classify`].
|
|
3927
|
+
*
|
|
3928
|
+
* `start`/`end` are byte offsets into the input string (Hugging Face
|
|
3929
|
+
* `tokenizers` convention). `label` is the privacy class without the
|
|
3930
|
+
* BIOES prefix (e.g. `"private_email"`). `score` is the mean — across
|
|
3931
|
+
* the span's tokens — of the softmax probability of the Viterbi-emitted
|
|
3932
|
+
* tag at each token.
|
|
3933
|
+
*/
|
|
3934
|
+
export interface PrivacyEntity {
|
|
3935
|
+
label: string;
|
|
3936
|
+
start: number;
|
|
3937
|
+
end: number;
|
|
3938
|
+
score: number;
|
|
3939
|
+
text: string;
|
|
3940
|
+
}
|
|
3941
|
+
|
|
3942
|
+
/**
|
|
3943
|
+
* Per-token output emitted when [`PrivacyClassifyOptions::return_tokens`]
|
|
3944
|
+
* is `true`. `tag` is the full BIOES tag (`"O"` or `"B-..."`/`"I-..."`/
|
|
3945
|
+
* `"E-..."`/`"S-..."`) chosen by the Viterbi decoder. `score` is the
|
|
3946
|
+
* softmax probability of that emitted tag at this token, so `tag` and
|
|
3947
|
+
* `score` always share decoders (at boundary tokens the Viterbi tag can
|
|
3948
|
+
* differ from the local argmax).
|
|
3949
|
+
*/
|
|
3950
|
+
export interface PrivacyToken {
|
|
3951
|
+
text: string;
|
|
3952
|
+
tag: string;
|
|
3953
|
+
score: number;
|
|
3954
|
+
start: number;
|
|
3955
|
+
end: number;
|
|
3956
|
+
}
|
|
3957
|
+
|
|
3557
3958
|
export interface ProfilingSession {
|
|
3558
3959
|
/** GPU hardware info. */
|
|
3559
3960
|
gpuInfo: GpuInfo;
|
|
@@ -3601,6 +4002,32 @@ export interface QianfanOcrConfig {
|
|
|
3601
4002
|
minDynamicPatch: number;
|
|
3602
4003
|
}
|
|
3603
4004
|
|
|
4005
|
+
/** Microbench result for the production quantized qmv dispatch path. */
|
|
4006
|
+
export interface QmvQuantizedMicrobenchResult {
|
|
4007
|
+
/** Median `quantized_matmul` wall-clock per call, in nanoseconds. */
|
|
4008
|
+
medianNs: number;
|
|
4009
|
+
/** A tiny materialized checksum of the final output, used to keep the call live. */
|
|
4010
|
+
checksum: number;
|
|
4011
|
+
}
|
|
4012
|
+
|
|
4013
|
+
/**
|
|
4014
|
+
* Run the production quantized-qmv microbench in the current process.
|
|
4015
|
+
*
|
|
4016
|
+
* To compare `MLX_MTP_SMALL_M_QMV=0` versus `1`, call this from separate
|
|
4017
|
+
* processes. MLX caches the env-backed dispatch predicate statically.
|
|
4018
|
+
*/
|
|
4019
|
+
export declare function quantizedQmvMicrobench(
|
|
4020
|
+
k: number,
|
|
4021
|
+
n: number,
|
|
4022
|
+
m: number,
|
|
4023
|
+
groupSize: number,
|
|
4024
|
+
bits: number,
|
|
4025
|
+
mode: string,
|
|
4026
|
+
dtype: DType,
|
|
4027
|
+
warmup?: number | undefined | null,
|
|
4028
|
+
iters?: number | undefined | null,
|
|
4029
|
+
): QmvQuantizedMicrobenchResult;
|
|
4030
|
+
|
|
3604
4031
|
/**
|
|
3605
4032
|
* Qwen3.5 model configuration (dense variant).
|
|
3606
4033
|
*
|
|
@@ -3629,6 +4056,79 @@ export interface Qwen35Config {
|
|
|
3629
4056
|
fullAttentionInterval: number;
|
|
3630
4057
|
partialRotaryFactor: number;
|
|
3631
4058
|
ropeTheta: number;
|
|
4059
|
+
/**
|
|
4060
|
+
* GPU memory budget for paged KV cache in megabytes.
|
|
4061
|
+
* Only used when `use_block_paged_cache` is true.
|
|
4062
|
+
* Default: automatically sized for one full-context sequence.
|
|
4063
|
+
*/
|
|
4064
|
+
pagedCacheMemoryMb?: number | undefined;
|
|
4065
|
+
/**
|
|
4066
|
+
* Block size for paged attention (tokens per block).
|
|
4067
|
+
* Only used when `use_block_paged_cache` is true.
|
|
4068
|
+
* Default: 16.
|
|
4069
|
+
*/
|
|
4070
|
+
pagedBlockSize?: number | undefined;
|
|
4071
|
+
/**
|
|
4072
|
+
* Use the block-paged KV cache adapter (`PagedKVCacheAdapter`) for
|
|
4073
|
+
* full-attention layers.
|
|
4074
|
+
*
|
|
4075
|
+
* **OPT-IN — experimental.** When `Some(true)`, `Qwen35Inner`
|
|
4076
|
+
* allocates a `BlockAllocator` + `LayerKVPool` pair sized for the
|
|
4077
|
+
* model's full-attention layer count and constructs a
|
|
4078
|
+
* `PagedKVCacheAdapter`. The chat-session forward dispatch routes
|
|
4079
|
+
* full-attention layers through this adapter while linear-attention
|
|
4080
|
+
* (GatedDeltaNet / GDN) layers continue to use the existing
|
|
4081
|
+
* `Qwen3_5LayerCache::Linear(ArraysCache)` path with no
|
|
4082
|
+
* cross-request prefix reuse — vLLM's `MambaManager`-style "no
|
|
4083
|
+
* prefix reuse for recurrent layers" stance.
|
|
4084
|
+
*
|
|
4085
|
+
* **Paged vs flat eager**: this flag selects the eager paged decode
|
|
4086
|
+
* over the eager flat decode. When `Some(true)`, full-attention
|
|
4087
|
+
* layers run through the paged adapter (cross-request prefix reuse);
|
|
4088
|
+
* when unset, they run the eager flat decode. Either way the forward
|
|
4089
|
+
* is pure-Rust eager.
|
|
4090
|
+
*
|
|
4091
|
+
* **VLM under paged**: a VLM checkpoint defaults this flag ON at load, so
|
|
4092
|
+
* dense image turns ONLY run on the paged-vision core. A fresh single-turn
|
|
4093
|
+
* image-bearing prompt prefills through the paged adapter (M-RoPE positions
|
|
4094
|
+
* feed the rotary; the merged vision embeddings feed the forward) and
|
|
4095
|
+
* decodes plain AR — MTP weights are ignored on image turns. Warm
|
|
4096
|
+
* image-bearing session continues / cache-hit reuse are still rejected at
|
|
4097
|
+
* runtime (the GDN two-pass warm prefix is not byte-exact). A vision turn
|
|
4098
|
+
* that reaches a None adapter (explicit `Some(false)`, non-Metal build, or
|
|
4099
|
+
* a sym8 checkpoint) errors at dispatch.
|
|
4100
|
+
*
|
|
4101
|
+
* Default: `None` for text-only checkpoints (eager flat decode);
|
|
4102
|
+
* `Some(true)` for VLM checkpoints (block-paged, set in `parse_config`).
|
|
4103
|
+
*/
|
|
4104
|
+
useBlockPagedCache?: boolean | undefined;
|
|
4105
|
+
/**
|
|
4106
|
+
* Persist the out-of-pool GDN recurrent state (and the paged KV blocks it
|
|
4107
|
+
* gates) to the SSD cold tier so warm prefixes survive process restarts.
|
|
4108
|
+
* Off unless explicitly enabled. See `crate::models::qwen3_5::gdn_sidecar`
|
|
4109
|
+
* and `crate::cold_tier::resolve_persist_cold`.
|
|
4110
|
+
*/
|
|
4111
|
+
persistPagedCache?: boolean | undefined;
|
|
4112
|
+
/**
|
|
4113
|
+
* Number of MTP (Multi-Token Prediction) head layers shipped with the
|
|
4114
|
+
* checkpoint. Populated from `mtp_num_hidden_layers` /
|
|
4115
|
+
* `num_nextn_predict_layers` in `config.json`. `0` means the
|
|
4116
|
+
* checkpoint has no MTP heads and the speculative-decode path is
|
|
4117
|
+
* unavailable.
|
|
4118
|
+
*/
|
|
4119
|
+
nMtpLayers: number;
|
|
4120
|
+
}
|
|
4121
|
+
|
|
4122
|
+
/**
|
|
4123
|
+
* Trained and physically available active-context limits for one loaded
|
|
4124
|
+
* Qwen3.5 model. Values are snapshots because the physical pool is fixed for
|
|
4125
|
+
* the lifetime of the resident model.
|
|
4126
|
+
*/
|
|
4127
|
+
export interface Qwen35ContextLimits {
|
|
4128
|
+
trainedWindowTokens: number;
|
|
4129
|
+
effectiveWindowTokens: number;
|
|
4130
|
+
pagedBlockCapacity: number;
|
|
4131
|
+
pagedBlockSize: number;
|
|
3632
4132
|
}
|
|
3633
4133
|
|
|
3634
4134
|
/** Generation configuration for Qwen3.5 */
|
|
@@ -3683,6 +4183,55 @@ export interface Qwen35MoeConfig {
|
|
|
3683
4183
|
moeIntermediateSize?: number | undefined;
|
|
3684
4184
|
normTopkProb: boolean;
|
|
3685
4185
|
mlpOnlyLayers?: number[] | undefined;
|
|
4186
|
+
/**
|
|
4187
|
+
* GPU memory budget for paged KV cache in megabytes.
|
|
4188
|
+
* Only used when `use_block_paged_cache` is true.
|
|
4189
|
+
* Default: automatically sized for one full-context sequence.
|
|
4190
|
+
*/
|
|
4191
|
+
pagedCacheMemoryMb?: number | undefined;
|
|
4192
|
+
/**
|
|
4193
|
+
* Block size for paged attention (tokens per block).
|
|
4194
|
+
* Only used when `use_block_paged_cache` is true.
|
|
4195
|
+
* Default: 16.
|
|
4196
|
+
*/
|
|
4197
|
+
pagedBlockSize?: number | undefined;
|
|
4198
|
+
/**
|
|
4199
|
+
* Use the block-paged KV cache adapter for full-attention layers.
|
|
4200
|
+
*
|
|
4201
|
+
* **OPT-IN — experimental.** Same semantics as the dense
|
|
4202
|
+
* `Qwen3_5Config::use_block_paged_cache` field. Selects the eager
|
|
4203
|
+
* paged decode over the eager flat decode: routes full-attention
|
|
4204
|
+
* layers through `PagedKVCacheAdapter` (cross-request prefix reuse);
|
|
4205
|
+
* GDN linear-attention layers stay on `Qwen3_5LayerCache::Linear`
|
|
4206
|
+
* either way. When disabled, full-attention layers run the eager flat
|
|
4207
|
+
* decode instead.
|
|
4208
|
+
*
|
|
4209
|
+
* **VLM under paged**: a VLM checkpoint loads with this flag set, and a
|
|
4210
|
+
* fresh single-turn image-bearing prompt prefills through the paged
|
|
4211
|
+
* adapter (M-RoPE positions feed the rotary; the merged vision embeddings
|
|
4212
|
+
* feed the forward). Image-bearing MTP turns are still rejected at
|
|
4213
|
+
* runtime; warm image-bearing session continues / cache-hit reuse are
|
|
4214
|
+
* cold-started (no warm GDN two-pass prefix).
|
|
4215
|
+
*
|
|
4216
|
+
* Default: `None` / `false`.
|
|
4217
|
+
*/
|
|
4218
|
+
useBlockPagedCache?: boolean | undefined;
|
|
4219
|
+
/**
|
|
4220
|
+
* Persist the out-of-pool GDN recurrent state (and the paged KV blocks it
|
|
4221
|
+
* gates) to the SSD cold tier so warm prefixes survive process restarts.
|
|
4222
|
+
* Off unless explicitly enabled. Shares the dense qwen3_5 GDN sidecar codec
|
|
4223
|
+
* (`crate::models::qwen3_5::gdn_sidecar`) via `to_dense_config`; the
|
|
4224
|
+
* precedence rules live in `crate::cold_tier::resolve_persist_cold`.
|
|
4225
|
+
*/
|
|
4226
|
+
persistPagedCache?: boolean | undefined;
|
|
4227
|
+
/**
|
|
4228
|
+
* Number of MTP (Multi-Token Prediction) head layers shipped with
|
|
4229
|
+
* the checkpoint. Populated from `mtp_num_hidden_layers` /
|
|
4230
|
+
* `num_nextn_predict_layers` in `config.json`. `0` means the
|
|
4231
|
+
* checkpoint has no MTP heads and the speculative-decode path is
|
|
4232
|
+
* unavailable.
|
|
4233
|
+
*/
|
|
4234
|
+
nMtpLayers: number;
|
|
3686
4235
|
}
|
|
3687
4236
|
|
|
3688
4237
|
/** Generation configuration for Qwen3.5 MoE */
|
|
@@ -3719,29 +4268,34 @@ export interface Qwen3Config {
|
|
|
3719
4268
|
padTokenId: number;
|
|
3720
4269
|
eosTokenId: number;
|
|
3721
4270
|
bosTokenId: number;
|
|
3722
|
-
/**
|
|
3723
|
-
* Enable paged attention for memory-efficient inference.
|
|
3724
|
-
* Default: false (use standard KVCache)
|
|
3725
|
-
*/
|
|
3726
|
-
usePagedAttention?: boolean | undefined;
|
|
3727
4271
|
/**
|
|
3728
4272
|
* GPU memory budget for paged KV cache in megabytes.
|
|
3729
|
-
* Only used when use_paged_attention is true.
|
|
3730
4273
|
* Default: 2048 (2GB)
|
|
3731
4274
|
*/
|
|
3732
4275
|
pagedCacheMemoryMb?: number | undefined;
|
|
3733
4276
|
/**
|
|
3734
4277
|
* Block size for paged attention (tokens per block).
|
|
3735
|
-
* Only used when use_paged_attention is true.
|
|
3736
4278
|
* Default: 16
|
|
3737
4279
|
*/
|
|
3738
4280
|
pagedBlockSize?: number | undefined;
|
|
3739
4281
|
/**
|
|
3740
|
-
* Use
|
|
3741
|
-
*
|
|
3742
|
-
*
|
|
4282
|
+
* Use the block-paged KV cache adapter (`PagedKVCacheAdapter`).
|
|
4283
|
+
*
|
|
4284
|
+
* When `Some(true)` (the default for Qwen3), `Qwen3Inner` allocates a
|
|
4285
|
+
* `BlockAllocator` + `LayerKVPool` pair and constructs a
|
|
4286
|
+
* `PagedKVCacheAdapter` for cross-request KV prefix reuse (vLLM-style
|
|
4287
|
+
* block-paged storage with refcounted prefix caching). When
|
|
4288
|
+
* `Some(false)`, the flat (non-paged) `Vec<KVCache>` cache path is
|
|
4289
|
+
* used instead.
|
|
4290
|
+
*
|
|
4291
|
+
* Default: true.
|
|
4292
|
+
*/
|
|
4293
|
+
useBlockPagedCache?: boolean | undefined;
|
|
4294
|
+
/**
|
|
4295
|
+
* Persist full paged KV blocks to the SSD cold tier so warm prefixes
|
|
4296
|
+
* survive process restarts. Off unless explicitly enabled.
|
|
3743
4297
|
*/
|
|
3744
|
-
|
|
4298
|
+
persistPagedCache?: boolean | undefined;
|
|
3745
4299
|
}
|
|
3746
4300
|
|
|
3747
4301
|
/** Qwen3 language model configuration */
|
|
@@ -3768,6 +4322,14 @@ export interface RecResult {
|
|
|
3768
4322
|
score: number;
|
|
3769
4323
|
}
|
|
3770
4324
|
|
|
4325
|
+
/**
|
|
4326
|
+
* Reset MLX's peak-memory counter to the current active level.
|
|
4327
|
+
* Useful for measuring per-request peak memory in a long-running
|
|
4328
|
+
* process — call before a request, sample
|
|
4329
|
+
* `getMemorySnapshot().peakBytes` after.
|
|
4330
|
+
*/
|
|
4331
|
+
export declare function resetPeakMemory(): void;
|
|
4332
|
+
|
|
3771
4333
|
/** Clear all collected profiling data and reset session timer. */
|
|
3772
4334
|
export declare function resetProfilingData(): void;
|
|
3773
4335
|
|
|
@@ -3857,22 +4419,6 @@ export interface SamplingConfig {
|
|
|
3857
4419
|
*/
|
|
3858
4420
|
export declare function saveToXlsx(text: string, filePath: string): void;
|
|
3859
4421
|
|
|
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
4422
|
/** Enable or disable profiling globally. */
|
|
3877
4423
|
export declare function setProfilingEnabled(enabled: boolean): void;
|
|
3878
4424
|
|
|
@@ -4155,6 +4701,35 @@ export interface TrainStepResultWithOutputs {
|
|
|
4155
4701
|
completionLengths: Array<number>;
|
|
4156
4702
|
}
|
|
4157
4703
|
|
|
4704
|
+
/**
|
|
4705
|
+
* Encoder-free vision configuration for the Gemma 4 unified multimodal model.
|
|
4706
|
+
*
|
|
4707
|
+
* Parsed from the `vision_config` sub-dict of a `gemma4_unified` checkpoint
|
|
4708
|
+
* (`model_type == "gemma4_unified_vision"`). This is a different shape from the
|
|
4709
|
+
* SigLIP-style [`super::vision_config::Gemma4VisionConfig`] used by the dense
|
|
4710
|
+
* gemma4 family: the unified vision path has no transformer encoder, only a
|
|
4711
|
+
* patch embedder (LayerNorm + Linear + 2D positional embedding) feeding the
|
|
4712
|
+
* multimodal projection.
|
|
4713
|
+
*/
|
|
4714
|
+
export interface UnifiedVisionConfig {
|
|
4715
|
+
/** Pixel side length of a single image patch (48 = patch_size 16 × pooling 3). */
|
|
4716
|
+
modelPatchSize: number;
|
|
4717
|
+
/** Embedding width inside the vision embedder (3840, == text hidden_size). */
|
|
4718
|
+
mmEmbedDim: number;
|
|
4719
|
+
/** Number of rows in the 2D positional-embedding table (1120). */
|
|
4720
|
+
mmPosembSize: number;
|
|
4721
|
+
/** Maximum soft tokens (patches) per image after resize (280). */
|
|
4722
|
+
numSoftTokens: number;
|
|
4723
|
+
/** Output projection width of `embed_vision` (3840, == text hidden_size). */
|
|
4724
|
+
outputProjDims: number;
|
|
4725
|
+
/** Pixel-grid patch size used by the resize math (16). */
|
|
4726
|
+
patchSize: number;
|
|
4727
|
+
/** Pooling kernel size used by the resize math (3). */
|
|
4728
|
+
poolingKernelSize: number;
|
|
4729
|
+
/** Epsilon for the embedder LayerNorms and the projection RMSNorm. */
|
|
4730
|
+
rmsNormEps: number;
|
|
4731
|
+
}
|
|
4732
|
+
|
|
4158
4733
|
/** Result from document unwarping. */
|
|
4159
4734
|
export interface UnwarpResult {
|
|
4160
4735
|
/** Unwarped image as PNG bytes */
|
|
@@ -4177,50 +4752,55 @@ export interface VisionConfig {
|
|
|
4177
4752
|
spatialMergeSize: number;
|
|
4178
4753
|
}
|
|
4179
4754
|
|
|
4180
|
-
/** A batch item for VLM batch inference */
|
|
4181
4755
|
export interface VlmBatchItem {
|
|
4182
|
-
/** Chat messages for this item */
|
|
4183
4756
|
messages: Array<VlmChatMessage>;
|
|
4184
|
-
/** Encoded image buffers for this item (one image per item for OCR) */
|
|
4185
4757
|
images?: Array<Buffer>;
|
|
4186
4758
|
}
|
|
4187
4759
|
|
|
4188
|
-
/** Configuration for VLM chat */
|
|
4189
4760
|
export interface VlmChatConfig {
|
|
4190
|
-
/** Encoded image buffers to process (PNG/JPEG bytes) */
|
|
4191
4761
|
images?: Array<Buffer>;
|
|
4192
|
-
/** Maximum number of new tokens to generate (default: 512) */
|
|
4193
4762
|
maxNewTokens?: number;
|
|
4194
|
-
/** Sampling temperature (0 = greedy, higher = more random) (default: 0.0 for OCR) */
|
|
4195
4763
|
temperature?: number;
|
|
4196
|
-
/** Top-k sampling (default: 0) */
|
|
4197
4764
|
topK?: number;
|
|
4198
|
-
/** Top-p (nucleus) sampling (default: 1.0) */
|
|
4199
4765
|
topP?: number;
|
|
4200
|
-
/** Repetition penalty (default: 1.5) */
|
|
4201
4766
|
repetitionPenalty?: number;
|
|
4202
|
-
/**
|
|
4203
|
-
* Presence penalty (0.0 = disabled). Subtracts a flat penalty from logits of any
|
|
4204
|
-
* token that appeared at least once in context. Matches OpenAI API semantics.
|
|
4205
|
-
*/
|
|
4206
4767
|
presencePenalty?: number;
|
|
4207
|
-
/** Number of recent tokens to consider for presence penalty (default: 20) */
|
|
4208
4768
|
presenceContextSize?: number;
|
|
4209
|
-
/**
|
|
4210
|
-
* Frequency penalty (0.0 = disabled). Subtracts penalty * occurrence_count from
|
|
4211
|
-
* logits of each token in context. Matches OpenAI API semantics.
|
|
4212
|
-
*/
|
|
4213
4769
|
frequencyPenalty?: number;
|
|
4214
|
-
/** Number of recent tokens to consider for frequency penalty (default: 20) */
|
|
4215
4770
|
frequencyContextSize?: number;
|
|
4216
|
-
/** Whether to return log probabilities (default: false) */
|
|
4217
4771
|
returnLogprobs?: boolean;
|
|
4218
4772
|
}
|
|
4219
4773
|
|
|
4220
|
-
/**
|
|
4774
|
+
/**
|
|
4775
|
+
* A chat message with textual content. Images are supplied through
|
|
4776
|
+
* [`VLMChatConfig`] and attached to the first user content part before the
|
|
4777
|
+
* model template is rendered.
|
|
4778
|
+
*/
|
|
4221
4779
|
export interface VlmChatMessage {
|
|
4222
|
-
/** Role of the message sender */
|
|
4223
4780
|
role: ChatRole;
|
|
4224
|
-
/** Text content of the message */
|
|
4225
4781
|
content: string;
|
|
4226
4782
|
}
|
|
4783
|
+
|
|
4784
|
+
export declare namespace __internal__ {
|
|
4785
|
+
/**
|
|
4786
|
+
* Drain the MLX allocator's free-pool.
|
|
4787
|
+
*
|
|
4788
|
+
* @internal
|
|
4789
|
+
*
|
|
4790
|
+
* This is a process-wide drain routed through MLX's default-stream
|
|
4791
|
+
* `mlx_synchronize()`, which does NOT wait on the custom generation
|
|
4792
|
+
* streams that the per-model threads run on. Calling this from user
|
|
4793
|
+
* code while a decode is in flight can race live Metal command buffers
|
|
4794
|
+
* and risk use-after-free. The only safe caller today is
|
|
4795
|
+
* `@mlx-node/server`'s idle sweeper, which only triggers after the
|
|
4796
|
+
* in-flight request counter has returned to zero.
|
|
4797
|
+
*
|
|
4798
|
+
* Exposed under the `__internal__` NAPI namespace — reachable as
|
|
4799
|
+
* `require('@mlx-node/core').__internal__.clearCache()` and NOT on
|
|
4800
|
+
* the root `require('@mlx-node/core')` object. The namespace prefix
|
|
4801
|
+
* is a deliberate speed-bump that forces any caller to acknowledge
|
|
4802
|
+
* this is a private drain with custom-stream caveats; the root
|
|
4803
|
+
* surface stays clean of the footgun.
|
|
4804
|
+
*/
|
|
4805
|
+
export function clearCache(): void;
|
|
4806
|
+
}
|