@qvac/sdk 0.17.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE +83 -18
- package/README.md +19 -0
- package/dist/client/api/audio-gen.d.ts +17 -0
- package/dist/client/api/audio-gen.js +17 -0
- package/dist/client/api/finetune.d.ts +2 -0
- package/dist/client/api/finetune.js +7 -1
- package/dist/client/api/index.d.ts +1 -1
- package/dist/client/api/index.js +1 -1
- package/dist/client/api/load-model.d.ts +8 -0
- package/dist/client/api/transcribe.d.ts +19 -2
- package/dist/client/api/transcribe.js +66 -27
- package/dist/client/api/translate.d.ts +3 -2
- package/dist/client/api/translate.js +42 -21
- package/dist/client/api/vla.d.ts +42 -1
- package/dist/client/api/vla.js +50 -1
- package/dist/commands/bundle/entry-gen.d.ts +4 -0
- package/dist/commands/bundle/entry-gen.js +6 -0
- package/dist/commands/bundle/index.js +19 -12
- package/dist/examples/asr/parakeet-indic-conformer-filesystem.d.ts +2 -0
- package/dist/examples/asr/parakeet-indic-conformer-filesystem.js +52 -0
- package/dist/examples/audiogen/generate-cover.d.ts +2 -0
- package/dist/examples/audiogen/generate-cover.js +100 -0
- package/dist/examples/llamacpp-fallback.d.ts +2 -0
- package/dist/examples/llamacpp-fallback.js +34 -0
- package/dist/examples/multi-job-completion.d.ts +28 -0
- package/dist/examples/multi-job-completion.js +128 -0
- package/dist/examples/profiling/basic.js +32 -1
- package/dist/examples/system-resources.d.ts +2 -0
- package/dist/examples/system-resources.js +86 -0
- package/dist/examples/tts/audio8.d.ts +2 -0
- package/dist/examples/tts/audio8.js +54 -0
- package/dist/examples/tts/cosyvoice3.d.ts +2 -0
- package/dist/examples/tts/cosyvoice3.js +52 -0
- package/dist/examples/vla-groot.js +92 -49
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/models/registry/models.d.ts +782 -6
- package/dist/models/registry/models.js +2664 -1859
- package/dist/schemas/audio-gen.d.ts +103 -0
- package/dist/schemas/audio-gen.js +135 -4
- package/dist/schemas/common.d.ts +550 -11
- package/dist/schemas/constants-registry.d.ts +18 -4
- package/dist/schemas/constants-registry.js +16 -3
- package/dist/schemas/index.d.ts +1 -1
- package/dist/schemas/index.js +1 -1
- package/dist/schemas/llamacpp-config.d.ts +10 -10
- package/dist/schemas/llamacpp-config.js +12 -5
- package/dist/schemas/load-model.d.ts +3678 -323
- package/dist/schemas/load-model.js +21 -3
- package/dist/schemas/sdk-config.d.ts +60 -24
- package/dist/schemas/sdk-errors-server.d.ts +1 -0
- package/dist/schemas/sdk-errors-server.js +5 -0
- package/dist/schemas/text-to-speech.d.ts +1086 -110
- package/dist/schemas/text-to-speech.js +194 -4
- package/dist/schemas/tools.d.ts +0 -16
- package/dist/schemas/tools.js +0 -15
- package/dist/schemas/transcription-config.d.ts +2 -0
- package/dist/schemas/transcription-config.js +10 -4
- package/dist/schemas/transcription.d.ts +3 -0
- package/dist/schemas/vla.d.ts +83 -0
- package/dist/schemas/vla.js +105 -2
- package/dist/scripts/link-workspace-inference.d.ts +2 -0
- package/dist/scripts/link-workspace-inference.js +31 -0
- package/dist/server/bare/ops/cancel.d.ts +1 -1
- package/dist/server/bare/ops/cancel.js +1 -1
- package/dist/server/bare/ops/kv-cache-retention.js +11 -0
- package/dist/server/bare/ops/kv-cache-utils.d.ts +1 -1
- package/dist/server/bare/ops/kv-cache-utils.js +40 -12
- package/dist/server/bare/ops/transcribe.d.ts +2 -2
- package/dist/server/bare/ops/transcribe.js +54 -48
- package/dist/server/bare/ops/translate-stats.d.ts +5 -0
- package/dist/server/bare/ops/translate-stats.js +11 -0
- package/dist/server/bare/ops/translate.js +66 -38
- package/dist/server/bare/ops/unload-model.js +30 -24
- package/dist/server/bare/plugins/audiogen-ggml/ops/audio-gen-input.d.ts +20 -0
- package/dist/server/bare/plugins/audiogen-ggml/ops/audio-gen-input.js +153 -0
- package/dist/server/bare/plugins/audiogen-ggml/ops/audio-gen-stream.js +52 -1
- package/dist/server/bare/plugins/audiogen-ggml/plugin.d.ts +28 -0
- package/dist/server/bare/plugins/ggml-ocr/plugin.js +3 -1
- package/dist/server/bare/plugins/ggml-vla/ops/vla-set-embodiment.d.ts +3 -0
- package/dist/server/bare/plugins/ggml-vla/ops/vla-set-embodiment.js +9 -0
- package/dist/server/bare/plugins/ggml-vla/plugin.d.ts +37 -0
- package/dist/server/bare/plugins/ggml-vla/plugin.js +21 -4
- package/dist/server/bare/plugins/llamacpp-completion/ops/batch-completion-stream.js +16 -15
- package/dist/server/bare/plugins/llamacpp-completion/ops/cache-logger.d.ts +1 -1
- package/dist/server/bare/plugins/llamacpp-completion/ops/cache-logger.js +2 -2
- package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stats.d.ts +6 -0
- package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stats.js +10 -0
- package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.d.ts +1 -0
- package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.js +131 -123
- package/dist/server/bare/plugins/llamacpp-completion/ops/finetune.js +110 -20
- package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-session.d.ts +49 -23
- package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-session.js +308 -143
- package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.d.ts +1 -0
- package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.js +2 -2
- package/dist/server/bare/plugins/llamacpp-completion/plugin.d.ts +6 -6
- package/dist/server/bare/plugins/llamacpp-completion/plugin.js +55 -36
- package/dist/server/bare/plugins/llamacpp-completion/transform.js +1 -7
- package/dist/server/bare/plugins/llamacpp-embedding/plugin.js +2 -3
- package/dist/server/bare/plugins/nmtcpp-translation/plugin.js +6 -5
- package/dist/server/bare/plugins/parakeet-transcription/plugin.js +27 -16
- package/dist/server/bare/plugins/tts-ggml/ops/parler-options.js +23 -3
- package/dist/server/bare/plugins/tts-ggml/plugin.d.ts +302 -4
- package/dist/server/bare/plugins/tts-ggml/plugin.js +131 -0
- package/dist/server/bare/plugins/whispercpp-transcription/plugin.js +48 -39
- package/dist/server/bare/registry/model-registry.d.ts +1 -0
- package/dist/server/bare/runtime/request-registry-singleton.js +29 -15
- package/dist/server/bare/runtime/request-registry.d.ts +27 -0
- package/dist/server/bare/runtime/request-registry.js +246 -76
- package/dist/server/bare/types/addon-responses.d.ts +4 -12
- package/dist/server/rpc/handlers/load-model/handler.js +2 -2
- package/dist/server/rpc/handlers/load-model/resolve-session.d.ts +1 -1
- package/dist/server/rpc/handlers/load-model/resolve-session.js +3 -3
- package/dist/server/rpc/handlers/load-model/resolve.d.ts +12 -2
- package/dist/server/rpc/handlers/load-model/resolve.js +90 -12
- package/dist/server/utils/audio/decoder.d.ts +37 -1
- package/dist/server/utils/audio/decoder.js +81 -51
- package/dist/server/utils/config-transform.d.ts +3 -0
- package/dist/server/utils/config-transform.js +6 -0
- package/dist/server/utils/index.d.ts +0 -1
- package/dist/server/utils/index.js +0 -1
- package/dist/server/utils/shard-utils.d.ts +1 -0
- package/dist/server/utils/shard-utils.js +14 -0
- package/dist/server/utils/tool-integration.d.ts +3 -10
- package/dist/server/utils/tool-integration.js +3 -12
- package/dist/utils/errors-server.d.ts +3 -0
- package/dist/utils/errors-server.js +5 -0
- package/package.json +12 -14
- package/dist/examples/llamacpp-dynamic-tools.d.ts +0 -2
- package/dist/examples/llamacpp-dynamic-tools.js +0 -152
- package/dist/models/update-models/codegen.d.ts +0 -3
- package/dist/models/update-models/codegen.js +0 -196
- package/dist/models/update-models/companions.d.ts +0 -30
- package/dist/models/update-models/companions.js +0 -296
- package/dist/models/update-models/history.d.ts +0 -24
- package/dist/models/update-models/history.js +0 -107
- package/dist/models/update-models/index.d.ts +0 -2
- package/dist/models/update-models/index.js +0 -123
- package/dist/models/update-models/naming.d.ts +0 -4
- package/dist/models/update-models/naming.js +0 -396
- package/dist/models/update-models/processing.d.ts +0 -8
- package/dist/models/update-models/processing.js +0 -65
- package/dist/models/update-models/registry.d.ts +0 -5
- package/dist/models/update-models/registry.js +0 -87
- package/dist/models/update-models/shards.d.ts +0 -4
- package/dist/models/update-models/shards.js +0 -57
- package/dist/models/update-models/types.d.ts +0 -88
- package/dist/models/update-models/types.js +0 -1
- package/dist/models/update-models/utils.d.ts +0 -3
- package/dist/models/update-models/utils.js +0 -21
- package/dist/server/bare/plugins/llamacpp-completion/ops/batch-cancelled.d.ts +0 -23
- package/dist/server/bare/plugins/llamacpp-completion/ops/batch-cancelled.js +0 -30
- package/dist/server/utils/expand-gguf-shards.d.ts +0 -3
- package/dist/server/utils/expand-gguf-shards.js +0 -22
|
@@ -37,6 +37,7 @@ interface CacheCommitContext {
|
|
|
37
37
|
producedTokens: boolean;
|
|
38
38
|
generatedTokens?: number | undefined;
|
|
39
39
|
predict?: number | undefined;
|
|
40
|
+
stoppedAtContextBoundary: boolean;
|
|
40
41
|
}
|
|
41
42
|
export declare function shouldCommitCachedTurn(context: CacheCommitContext): boolean;
|
|
42
43
|
/**
|
|
@@ -15,12 +15,12 @@
|
|
|
15
15
|
* slice-decision helper remains here.
|
|
16
16
|
*/
|
|
17
17
|
export function shouldCommitCachedTurn(context) {
|
|
18
|
-
const { aborted, producedTokens, generatedTokens, predict } = context;
|
|
18
|
+
const { aborted, producedTokens, generatedTokens, predict, stoppedAtContextBoundary } = context;
|
|
19
19
|
const stoppedByBudget = predict !== undefined &&
|
|
20
20
|
predict > 0 &&
|
|
21
21
|
generatedTokens !== undefined &&
|
|
22
22
|
generatedTokens >= predict;
|
|
23
|
-
return !aborted && producedTokens && !stoppedByBudget;
|
|
23
|
+
return !aborted && producedTokens && !stoppedByBudget && !stoppedAtContextBoundary;
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
26
|
* Pure slice decision for `prepareMessagesForCache`.
|
|
@@ -28,10 +28,6 @@ export declare const llmPlugin: {
|
|
|
28
28
|
n_discarded: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
29
29
|
parallel: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
30
30
|
tools: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
31
|
-
toolsMode: import("zod").ZodOptional<import("zod").ZodEnum<{
|
|
32
|
-
static: "static";
|
|
33
|
-
dynamic: "dynamic";
|
|
34
|
-
}>>;
|
|
35
31
|
'cache-type-k': import("zod").ZodOptional<import("zod").ZodString>;
|
|
36
32
|
'cache-type-v': import("zod").ZodOptional<import("zod").ZodString>;
|
|
37
33
|
'main-gpu': import("zod").ZodOptional<import("zod").ZodUnion<readonly [import("zod").ZodNumber, import("zod").ZodEnum<{
|
|
@@ -90,6 +86,10 @@ export declare const llmPlugin: {
|
|
|
90
86
|
batched: "batched";
|
|
91
87
|
sequential: "sequential";
|
|
92
88
|
}>>;
|
|
89
|
+
image_no_upscale: import("zod").ZodOptional<import("zod").ZodEnum<{
|
|
90
|
+
on: "on";
|
|
91
|
+
off: "off";
|
|
92
|
+
}>>;
|
|
93
93
|
'mmproj-use-gpu': import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
94
94
|
}, import("zod/v4/core").$strip>;
|
|
95
95
|
resolveConfig(cfg: LlmConfigInput, ctx: ResolveContext): Promise<{
|
|
@@ -113,7 +113,6 @@ export declare const llmPlugin: {
|
|
|
113
113
|
n_discarded?: number | undefined;
|
|
114
114
|
parallel?: number | undefined;
|
|
115
115
|
tools?: boolean | undefined;
|
|
116
|
-
toolsMode?: "static" | "dynamic" | undefined;
|
|
117
116
|
'cache-type-k'?: string | undefined;
|
|
118
117
|
'cache-type-v'?: string | undefined;
|
|
119
118
|
'main-gpu'?: number | "integrated" | "dedicated" | undefined;
|
|
@@ -122,6 +121,7 @@ export declare const llmPlugin: {
|
|
|
122
121
|
openclCacheDir?: string | undefined;
|
|
123
122
|
reasoning_budget?: number | undefined;
|
|
124
123
|
image_tile_mode?: "disabled" | "batched" | "sequential" | undefined;
|
|
124
|
+
image_no_upscale?: "on" | "off" | undefined;
|
|
125
125
|
'mmproj-use-gpu'?: boolean | undefined;
|
|
126
126
|
};
|
|
127
127
|
artifacts?: never;
|
|
@@ -146,7 +146,6 @@ export declare const llmPlugin: {
|
|
|
146
146
|
n_discarded?: number | undefined;
|
|
147
147
|
parallel?: number | undefined;
|
|
148
148
|
tools?: boolean | undefined;
|
|
149
|
-
toolsMode?: "static" | "dynamic" | undefined;
|
|
150
149
|
'cache-type-k'?: string | undefined;
|
|
151
150
|
'cache-type-v'?: string | undefined;
|
|
152
151
|
'main-gpu'?: number | "integrated" | "dedicated" | undefined;
|
|
@@ -155,6 +154,7 @@ export declare const llmPlugin: {
|
|
|
155
154
|
openclCacheDir?: string | undefined;
|
|
156
155
|
reasoning_budget?: number | undefined;
|
|
157
156
|
image_tile_mode?: "disabled" | "batched" | "sequential" | undefined;
|
|
157
|
+
image_no_upscale?: "on" | "off" | undefined;
|
|
158
158
|
'mmproj-use-gpu'?: boolean | undefined;
|
|
159
159
|
};
|
|
160
160
|
artifacts: {
|
|
@@ -54,7 +54,7 @@ import LlmLlamacpp from '@qvac/llm-llamacpp';
|
|
|
54
54
|
import llmAddonLogging from '@qvac/llm-llamacpp/addonLogging';
|
|
55
55
|
import { definePlugin, defineHandler, finetuneRequestSchema, batchCompletionStreamRequestSchema, batchCompletionStreamResponseSchema, completionStreamRequestSchema, completionStreamResponseSchema, finetuneResponseSchema, translateRequestSchema, translateResponseSchema, ModelType, llmConfigBaseSchema, ADDON_LLM } from '../../../../schemas/index.js';
|
|
56
56
|
import { createStreamLogger, registerAddonLogger } from '../../../../logging/index.js';
|
|
57
|
-
import {
|
|
57
|
+
import { getFirstShardPath, getModelParallel } from '../../../../server/utils/index.js';
|
|
58
58
|
import { completion } from '../../../../server/bare/plugins/llamacpp-completion/ops/completion-stream.js';
|
|
59
59
|
import { batchCompletion } from '../../../../server/bare/plugins/llamacpp-completion/ops/batch-completion-stream.js';
|
|
60
60
|
import { finetune } from '../../../../server/bare/plugins/llamacpp-completion/ops/finetune.js';
|
|
@@ -69,7 +69,7 @@ import { generateServerRequestId } from '../../../../server/bare/runtime/request
|
|
|
69
69
|
import { getServerLogger } from '../../../../logging/index.js';
|
|
70
70
|
import { ContextOverflowError } from '../../../../utils/errors-server.js';
|
|
71
71
|
import { isAddonContextOverflowError, parseContextOverflowMessage } from '../../../../server/bare/plugins/llamacpp-completion/ops/context-overflow.js';
|
|
72
|
-
import {
|
|
72
|
+
import { stoppedByLength } from '../../../../server/bare/plugins/llamacpp-completion/ops/completion-stats.js';
|
|
73
73
|
import { isMobile } from '../../../../server/bare/registry/runtime-context-registry.js';
|
|
74
74
|
import { stripMultiGpuKeys } from '../../../../server/utils/multi-gpu-mobile.js';
|
|
75
75
|
function createLlmModel(modelId, modelPath, llmConfig, projectionModelPath) {
|
|
@@ -82,15 +82,17 @@ function createLlmModel(modelId, modelPath, llmConfig, projectionModelPath) {
|
|
|
82
82
|
getServerLogger().warn(`[${ModelType.llamacppCompletion}:${modelId}] Multi-GPU parameters (${stripped.join(', ')}) are not supported on mobile (single-GPU device) — removing from config; model will load with single-GPU defaults`);
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
|
-
|
|
85
|
+
// Addon overflow flag: at a single slot the addon throws when driven over
|
|
86
|
+
// capacity, at parallel>1 it queues the surplus. Not on the SDK surface.
|
|
87
|
+
const rejectWhenBusy = getModelParallel(llmConfig) <= 1;
|
|
86
88
|
const model = new LlmLlamacpp({
|
|
87
89
|
files: {
|
|
88
|
-
model:
|
|
90
|
+
model: [getFirstShardPath(modelPath)],
|
|
89
91
|
...(projectionModelPath && { projectionModel: projectionModelPath })
|
|
90
92
|
},
|
|
91
93
|
config: llmConfigStrings,
|
|
92
94
|
logger,
|
|
93
|
-
opts: { stats: true }
|
|
95
|
+
opts: { stats: true, rejectWhenBusy }
|
|
94
96
|
});
|
|
95
97
|
return { model };
|
|
96
98
|
}
|
|
@@ -136,7 +138,8 @@ export const llmPlugin = definePlugin({
|
|
|
136
138
|
requestSchema: batchCompletionStreamRequestSchema,
|
|
137
139
|
responseSchema: batchCompletionStreamResponseSchema,
|
|
138
140
|
streaming: true,
|
|
139
|
-
|
|
141
|
+
// Request-scope: a model-wide cancel would kill concurrent batching peers.
|
|
142
|
+
cancel: { scope: 'request', hard: true },
|
|
140
143
|
handler: async function* (request) {
|
|
141
144
|
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
142
145
|
try {
|
|
@@ -162,10 +165,14 @@ export const llmPlugin = definePlugin({
|
|
|
162
165
|
}
|
|
163
166
|
return normalizer;
|
|
164
167
|
}
|
|
168
|
+
// Batches share the completion lane at the `parallel` cap. The cap counts
|
|
169
|
+
// requests, not the prompts inside a batch (the addon schedules those).
|
|
170
|
+
const parallel = getModelParallel(modelCfg);
|
|
165
171
|
const ctx = __addDisposableResource(env_1, await getRequestRegistry().begin({
|
|
166
172
|
requestId: request.requestId ?? generateServerRequestId(),
|
|
167
173
|
kind: 'batchCompletion',
|
|
168
|
-
modelId: request.modelId
|
|
174
|
+
modelId: request.modelId,
|
|
175
|
+
maxConcurrentPerModel: parallel
|
|
169
176
|
}), true);
|
|
170
177
|
const requestLogger = withRequestContext(getServerLogger(), ctx);
|
|
171
178
|
if (Boolean(ctx.signal.aborted)) {
|
|
@@ -238,14 +245,11 @@ export const llmPlugin = definePlugin({
|
|
|
238
245
|
const { promptTokens, ctxSize } = parseContextOverflowMessage(err instanceof Error ? err.message : '');
|
|
239
246
|
throw new ContextOverflowError(promptTokens, ctxSize, request.modelId, err);
|
|
240
247
|
}
|
|
241
|
-
//
|
|
242
|
-
//
|
|
243
|
-
//
|
|
244
|
-
//
|
|
245
|
-
|
|
246
|
-
// uses: emit cancelled terminals per id so the client surfaces
|
|
247
|
-
// `InferenceCancelledError`, not a generic `CompletionFailedError`.
|
|
248
|
-
if (ctx.signal.aborted && isAddonCancelledError(err)) {
|
|
248
|
+
// Once the registry accepts cancellation, the request signal owns the
|
|
249
|
+
// terminal outcome. The addon may reject with different shapes
|
|
250
|
+
// depending on whether native sequences were active or queued; those
|
|
251
|
+
// transport details must not change the SDK cancellation contract.
|
|
252
|
+
if (ctx.signal.aborted) {
|
|
249
253
|
const cancelledIds = ids.length > 0
|
|
250
254
|
? ids
|
|
251
255
|
: request.prompts.map((prompt, index) => prompt.id ?? String(index));
|
|
@@ -281,7 +285,8 @@ export const llmPlugin = definePlugin({
|
|
|
281
285
|
requestSchema: completionStreamRequestSchema,
|
|
282
286
|
responseSchema: completionStreamResponseSchema,
|
|
283
287
|
streaming: true,
|
|
284
|
-
|
|
288
|
+
// Request-scope: a model-wide cancel would kill concurrent batching peers.
|
|
289
|
+
cancel: { scope: 'request', hard: true },
|
|
285
290
|
handler: async function* (request) {
|
|
286
291
|
const env_2 = { stack: [], error: void 0, hasError: false };
|
|
287
292
|
try {
|
|
@@ -312,10 +317,14 @@ export const llmPlugin = definePlugin({
|
|
|
312
317
|
// client can target this run with `cancel({ requestId })`.
|
|
313
318
|
// Falls back to a server-generated id if the client (e.g. an
|
|
314
319
|
// older release) didn't send one.
|
|
320
|
+
// Admit up to `parallel` jobs. Disk-KV-cache turns share this lane too;
|
|
321
|
+
// same-file writes serialise per cache path inside the KV-cache session.
|
|
322
|
+
const parallel = getModelParallel(modelCfg);
|
|
315
323
|
const ctx = __addDisposableResource(env_2, await getRequestRegistry().begin({
|
|
316
324
|
requestId: request.requestId ?? generateServerRequestId(),
|
|
317
325
|
kind: 'completion',
|
|
318
|
-
modelId: request.modelId
|
|
326
|
+
modelId: request.modelId,
|
|
327
|
+
maxConcurrentPerModel: parallel
|
|
319
328
|
}), true);
|
|
320
329
|
const requestLogger = withRequestContext(getServerLogger(), ctx);
|
|
321
330
|
// begin() can return already-aborted when the client cancels while
|
|
@@ -361,26 +370,26 @@ export const llmPlugin = definePlugin({
|
|
|
361
370
|
}
|
|
362
371
|
result = await stream.next();
|
|
363
372
|
}
|
|
364
|
-
const { modelExecutionMs, stats, toolCalls } = result.value;
|
|
373
|
+
const { modelExecutionMs, stats, toolCalls, stoppedAtContextBoundary } = result.value;
|
|
365
374
|
// Cancellation rides the done path: observable via the last event's
|
|
366
375
|
// stopReason; client aggregates reject with InferenceCancelledError.
|
|
367
376
|
const cancelled = ctx.signal.aborted;
|
|
368
377
|
// EOS tokens are not decoded by llama_decode, so n_eval (and
|
|
369
378
|
// therefore stats.generatedTokens) counts only real decode calls.
|
|
370
|
-
//
|
|
371
|
-
//
|
|
372
|
-
// -1 (unlimited) and -2 (context fill) must never trigger this.
|
|
379
|
+
// Positive prediction-budget exhaustion and a full context window
|
|
380
|
+
// both map to stopReason "length"; cancellation takes precedence.
|
|
373
381
|
const effectivePredict = request.generationParams?.predict ?? modelCfg.predict;
|
|
374
|
-
const
|
|
375
|
-
|
|
376
|
-
effectivePredict
|
|
377
|
-
stats?.generatedTokens
|
|
378
|
-
|
|
382
|
+
const lengthStop = stoppedByLength({
|
|
383
|
+
cancelled,
|
|
384
|
+
effectivePredict,
|
|
385
|
+
generatedTokens: stats?.generatedTokens,
|
|
386
|
+
stoppedAtContextBoundary
|
|
387
|
+
});
|
|
379
388
|
const terminalEvents = normalizer.finish({
|
|
380
389
|
...(stats && { stats }),
|
|
381
390
|
...(toolCalls.length > 0 && { toolCalls }),
|
|
382
391
|
...(cancelled && { stopReason: 'cancelled' }),
|
|
383
|
-
...(
|
|
392
|
+
...(lengthStop && { stopReason: 'length' })
|
|
384
393
|
});
|
|
385
394
|
if (!request.stream) {
|
|
386
395
|
batchedEvents.push(...terminalEvents);
|
|
@@ -393,18 +402,27 @@ export const llmPlugin = definePlugin({
|
|
|
393
402
|
}, modelExecutionMs);
|
|
394
403
|
}
|
|
395
404
|
catch (err) {
|
|
396
|
-
//
|
|
397
|
-
//
|
|
398
|
-
//
|
|
399
|
-
// surfaces it as a JS Error with `.code = "[ <addonId> :: ContextOverflow ]"`
|
|
400
|
-
// and `.message` carrying the C++-formatted detail. Rethrow as
|
|
401
|
-
// a typed `ContextOverflowError` so consumers can switch on the
|
|
402
|
-
// class (and `err.code === SDK_SERVER_ERROR_CODES.CONTEXT_OVERFLOW`)
|
|
403
|
-
// instead of substring-matching on the raw addon message.
|
|
405
|
+
// Classify a structured ContextOverflow first, even under an aborted
|
|
406
|
+
// signal, so a real overflow racing a cancel surfaces as a typed
|
|
407
|
+
// ContextOverflowError.
|
|
404
408
|
if (isAddonContextOverflowError(err)) {
|
|
405
409
|
const { promptTokens, ctxSize } = parseContextOverflowMessage(err instanceof Error ? err.message : '');
|
|
406
410
|
throw new ContextOverflowError(promptTokens, ctxSize, request.modelId, err);
|
|
407
411
|
}
|
|
412
|
+
// Context overflow is classified above. For every other error after
|
|
413
|
+
// accepted cancellation, the request signal owns the terminal outcome
|
|
414
|
+
// regardless of the addon's active/queued error shape.
|
|
415
|
+
if (ctx.signal.aborted) {
|
|
416
|
+
yield attachModelExecutionMs({
|
|
417
|
+
type: 'completionStream',
|
|
418
|
+
done: true,
|
|
419
|
+
events: normalizer.finish({ stopReason: 'cancelled' })
|
|
420
|
+
},
|
|
421
|
+
// The error path has no model execution time to report; omit it
|
|
422
|
+
// rather than claim 0.
|
|
423
|
+
undefined);
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
408
426
|
throw err;
|
|
409
427
|
}
|
|
410
428
|
finally {
|
|
@@ -442,7 +460,8 @@ export const llmPlugin = definePlugin({
|
|
|
442
460
|
requestSchema: translateRequestSchema,
|
|
443
461
|
responseSchema: translateResponseSchema,
|
|
444
462
|
streaming: true,
|
|
445
|
-
|
|
463
|
+
// LLM translate cancels its own run (request-scoped), like completion.
|
|
464
|
+
cancel: { scope: 'request', hard: true },
|
|
446
465
|
handler: async function* (request) {
|
|
447
466
|
const stream = translate(request, request.requestId);
|
|
448
467
|
try {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {} from '../../../../schemas/index.js';
|
|
2
2
|
/**
|
|
3
3
|
* Converts an LlmConfig into the flat string-keyed map the C++ addon expects.
|
|
4
4
|
*
|
|
@@ -24,11 +24,5 @@ export function transformLlmConfig(llmConfig) {
|
|
|
24
24
|
transformed['openclCacheDir'] = transformed['opencl_cache_dir'];
|
|
25
25
|
delete transformed['opencl_cache_dir'];
|
|
26
26
|
}
|
|
27
|
-
if ('tools_mode' in transformed) {
|
|
28
|
-
if (transformed['tools_mode'] === TOOLS_MODE.dynamic) {
|
|
29
|
-
transformed['tools_compact'] = 'true';
|
|
30
|
-
}
|
|
31
|
-
delete transformed['tools_mode'];
|
|
32
|
-
}
|
|
33
27
|
return transformed;
|
|
34
28
|
}
|
|
@@ -2,7 +2,7 @@ import EmbedLlamacpp, {} from '@qvac/embed-llamacpp';
|
|
|
2
2
|
import embedAddonLogging from '@qvac/embed-llamacpp/addonLogging';
|
|
3
3
|
import { definePlugin, defineHandler, embedRequestSchema, embedResponseSchema, ModelType, embedConfigBaseSchema, ADDON_EMBEDDING } from '../../../../schemas/index.js';
|
|
4
4
|
import { createStreamLogger, registerAddonLogger, getServerLogger } from '../../../../logging/index.js';
|
|
5
|
-
import {
|
|
5
|
+
import { getFirstShardPath } from '../../../../server/utils/index.js';
|
|
6
6
|
import { embed } from '../../../../server/bare/ops/embed.js';
|
|
7
7
|
import { forwardModelExecution } from '../../../../profiling/model-execution.js';
|
|
8
8
|
import { isMobile } from '../../../../server/bare/registry/runtime-context-registry.js';
|
|
@@ -53,9 +53,8 @@ function createEmbeddingsModel(modelId, modelPath, embedConfig) {
|
|
|
53
53
|
getServerLogger().warn(`[${ModelType.llamacppEmbedding}:${modelId}] Multi-GPU parameters (${stripped.join(', ')}) are not supported on mobile (single-GPU device) — removing from config; model will load with single-GPU defaults`);
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
-
const modelFiles = expandGGUFIntoShards(modelPath);
|
|
57
56
|
const model = new EmbedLlamacpp({
|
|
58
|
-
files: { model:
|
|
57
|
+
files: { model: [getFirstShardPath(modelPath)] },
|
|
59
58
|
config,
|
|
60
59
|
logger,
|
|
61
60
|
opts: { stats: true }
|
|
@@ -31,7 +31,7 @@ function deriveColocatedBergamotVocabPaths(modelPath) {
|
|
|
31
31
|
function createNmtModel(modelId, modelPath, nmtConfig, srcVocabPath, dstVocabPath, pivotModelPath, pivotSrcVocabPath, pivotDstVocabPath) {
|
|
32
32
|
const logger = createStreamLogger(modelId, ModelType.nmtcppTranslation);
|
|
33
33
|
registerAddonLogger(modelId, ModelType.nmtcppTranslation, logger);
|
|
34
|
-
const {
|
|
34
|
+
const { from, to, engine, beamsize, lengthpenalty, maxlength, repetitionpenalty, norepeatngramsize, temperature, topk, topp } = nmtConfig;
|
|
35
35
|
const files = {
|
|
36
36
|
model: modelPath,
|
|
37
37
|
...(srcVocabPath && { srcVocab: srcVocabPath }),
|
|
@@ -69,7 +69,7 @@ function createNmtModel(modelId, modelPath, nmtConfig, srcVocabPath, dstVocabPat
|
|
|
69
69
|
};
|
|
70
70
|
const model = new TranslationNmtcpp({
|
|
71
71
|
files,
|
|
72
|
-
params: {
|
|
72
|
+
params: { srcLang: from, dstLang: to },
|
|
73
73
|
config,
|
|
74
74
|
logger,
|
|
75
75
|
opts: { stats: true }
|
|
@@ -107,9 +107,10 @@ export const nmtPlugin = definePlugin({
|
|
|
107
107
|
requestSchema: translateRequestSchema,
|
|
108
108
|
responseSchema: translateResponseSchema,
|
|
109
109
|
streaming: true,
|
|
110
|
-
// nmtcpp
|
|
111
|
-
//
|
|
112
|
-
// post-processing; the C++ work
|
|
110
|
+
// nmtcpp 0.7.0 exposes response.cancel(), but the translate op is not
|
|
111
|
+
// wired for addon-level cancellation yet — SDK keeps soft-cancel (stop
|
|
112
|
+
// yielding, drop result, skip post-processing; the C++ work may run to
|
|
113
|
+
// completion).
|
|
113
114
|
cancel: { scope: 'none' },
|
|
114
115
|
handler: async function* (request) {
|
|
115
116
|
const stream = translate(request, request.requestId);
|
|
@@ -100,26 +100,37 @@ export const parakeetPlugin = definePlugin({
|
|
|
100
100
|
})
|
|
101
101
|
};
|
|
102
102
|
const iterator = transcribeStream(request.modelId, inputStream, undefined, false, streamOpts, request.requestId);
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
103
|
+
try {
|
|
104
|
+
let result = await iterator.next();
|
|
105
|
+
while (!result.done) {
|
|
106
|
+
const value = result.value;
|
|
107
|
+
if (typeof value === 'object' && value !== null && 'type' in value) {
|
|
108
|
+
if (value.type === 'endOfTurn') {
|
|
109
|
+
yield {
|
|
110
|
+
type: 'transcribeStream',
|
|
111
|
+
endOfTurn: { source: 'parakeet' }
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
result = await iterator.next();
|
|
115
|
+
continue;
|
|
110
116
|
}
|
|
111
|
-
|
|
117
|
+
yield {
|
|
118
|
+
type: 'transcribeStream',
|
|
119
|
+
text: value
|
|
120
|
+
};
|
|
121
|
+
result = await iterator.next();
|
|
112
122
|
}
|
|
113
|
-
|
|
123
|
+
const { modelExecutionMs, stats } = result.value;
|
|
124
|
+
yield attachModelExecutionMs({
|
|
114
125
|
type: 'transcribeStream',
|
|
115
|
-
text:
|
|
116
|
-
|
|
126
|
+
text: '',
|
|
127
|
+
done: true,
|
|
128
|
+
...(stats && { stats })
|
|
129
|
+
}, modelExecutionMs);
|
|
130
|
+
}
|
|
131
|
+
finally {
|
|
132
|
+
await iterator.return?.(undefined);
|
|
117
133
|
}
|
|
118
|
-
yield {
|
|
119
|
-
type: 'transcribeStream',
|
|
120
|
-
text: '',
|
|
121
|
-
done: true
|
|
122
|
-
};
|
|
123
134
|
}
|
|
124
135
|
})
|
|
125
136
|
},
|
|
@@ -21,10 +21,30 @@ export function getParlerJobOptions(request) {
|
|
|
21
21
|
...(request.quality !== undefined ? { quality: request.quality } : {})
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
|
+
// Per-call conditioning keys shared by the engines that support them.
|
|
25
|
+
// CosyVoice3 accepts the cross-engine emotion/pace pair; everything else in
|
|
26
|
+
// the description/template surface remains Parler-only.
|
|
27
|
+
const CROSS_ENGINE_CONDITIONING_KEYS = ['emotion', 'pace'];
|
|
24
28
|
export function assertParlerJobOptionsSupported(model, options, handlerName) {
|
|
25
|
-
|
|
29
|
+
const setKeys = Object.keys(options);
|
|
30
|
+
if (setKeys.length === 0)
|
|
26
31
|
return;
|
|
27
|
-
|
|
32
|
+
const engine = hasEngineType(model) ? model.getEngineType() : undefined;
|
|
33
|
+
if (engine === 'parler')
|
|
28
34
|
return;
|
|
29
|
-
|
|
35
|
+
if (engine === 'cosyvoice3') {
|
|
36
|
+
const parlerOnlyKeys = setKeys.filter((key) => !CROSS_ENGINE_CONDITIONING_KEYS.includes(key));
|
|
37
|
+
if (parlerOnlyKeys.length > 0) {
|
|
38
|
+
throw new PluginRequestValidationFailedError(handlerName, `${parlerOnlyKeys.join(', ')} ${parlerOnlyKeys.length === 1 ? 'is' : 'are'} only supported by Parler TTS models; CosyVoice3 supports emotion and pace`);
|
|
39
|
+
}
|
|
40
|
+
// CosyVoice3 is trained on one instruction per synthesis; a request that
|
|
41
|
+
// engages both channels always conflicts regardless of the loaded config.
|
|
42
|
+
if (options.emotion !== undefined &&
|
|
43
|
+
options.pace !== undefined &&
|
|
44
|
+
options.pace !== 'moderate') {
|
|
45
|
+
throw new PluginRequestValidationFailedError(handlerName, 'CosyVoice3 accepts one conditioning control per synthesis; set either emotion or a non-moderate pace, not both');
|
|
46
|
+
}
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
throw new PluginRequestValidationFailedError(handlerName, 'description, voiceDescription, voice, emotion, pitch, pace, expressivity, noise, reverb, and quality are only supported by Parler TTS and CosyVoice3 models (CosyVoice3: emotion and pace only)');
|
|
30
50
|
}
|