@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
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import fs from 'bare-fs';
|
|
2
|
+
import { AUDIOGEN_INPUT_CHANNELS, AUDIOGEN_INPUT_MAX_SECONDS, AUDIOGEN_INPUT_SAMPLE_RATE } from '../../../../../schemas/audio-gen.js';
|
|
3
|
+
import { decodeAudioToStream, needsDecoding } from '../../../../../server/utils/audio/decoder.js';
|
|
4
|
+
import { AudioFileNotFoundError, InvalidAudioInputError } from '../../../../../utils/errors-server.js';
|
|
5
|
+
const FLOAT32_BYTES = Float32Array.BYTES_PER_ELEMENT;
|
|
6
|
+
const STEREO_FRAME_BYTES = FLOAT32_BYTES * AUDIOGEN_INPUT_CHANNELS;
|
|
7
|
+
/** Upper bound for raw stereo input bytes (base64 payloads and raw PCM files). */
|
|
8
|
+
const MAX_STEREO_BYTES = AUDIOGEN_INPUT_MAX_SECONDS * AUDIOGEN_INPUT_SAMPLE_RATE * STEREO_FRAME_BYTES;
|
|
9
|
+
/** Upper bound for the mono float stream the FFmpeg decoder may emit. */
|
|
10
|
+
const MAX_DECODED_MONO_BYTES = AUDIOGEN_INPUT_MAX_SECONDS * AUDIOGEN_INPUT_SAMPLE_RATE * FLOAT32_BYTES;
|
|
11
|
+
/**
|
|
12
|
+
* Resolve a reference/source audio input into the interleaved stereo 48 kHz
|
|
13
|
+
* Float32 PCM the ACE-Step engine consumes.
|
|
14
|
+
*
|
|
15
|
+
* - `base64` inputs (client `Buffer`/`Uint8Array`) must already be raw
|
|
16
|
+
* interleaved stereo 48 kHz Float32 LE PCM; they are handed over as-is
|
|
17
|
+
* (a copy is made only when the bytes are not 4-byte aligned).
|
|
18
|
+
* - `filePath` inputs with a decodable extension (`.wav`, `.mp3`, `.m4a`,
|
|
19
|
+
* `.ogg`, `.flac`, `.aac`) are decoded through the SDK's FFmpeg decoder to
|
|
20
|
+
* 48 kHz mono float PCM and duplicated onto both channels. Any other
|
|
21
|
+
* extension is streamed in as raw interleaved stereo 48 kHz Float32 LE PCM.
|
|
22
|
+
*
|
|
23
|
+
* Every path is bounded by `AUDIOGEN_INPUT_MAX_SECONDS` and rejects
|
|
24
|
+
* non-finite samples, so malformed or oversized input fails with
|
|
25
|
+
* `InvalidAudioInputError` before the engine is invoked.
|
|
26
|
+
*/
|
|
27
|
+
export async function resolveAudioGenPcm(input, name) {
|
|
28
|
+
switch (input.type) {
|
|
29
|
+
case 'base64':
|
|
30
|
+
return toStereoFloat32(Buffer.from(input.value, 'base64'), name);
|
|
31
|
+
case 'filePath': {
|
|
32
|
+
const filePath = input.value;
|
|
33
|
+
if (!needsDecoding(filePath)) {
|
|
34
|
+
return toStereoFloat32(await readRawPcmFile(filePath, name), name);
|
|
35
|
+
}
|
|
36
|
+
await assertDecodableFileSize(filePath, name);
|
|
37
|
+
return monoToStereo(await decodeMonoFloat32(filePath, name), name);
|
|
38
|
+
}
|
|
39
|
+
default:
|
|
40
|
+
throw new InvalidAudioInputError(`${name} must be a file path or raw PCM bytes`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async function statInput(filePath) {
|
|
44
|
+
try {
|
|
45
|
+
return await fs.promises.stat(filePath);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
throw new AudioFileNotFoundError(filePath, error);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The FFmpeg decoder buffers the whole input file before emitting PCM, so the
|
|
53
|
+
* file itself is bounded up front: no encoded container for a clip within
|
|
54
|
+
* `AUDIOGEN_INPUT_MAX_SECONDS` exceeds the size of that clip as raw stereo
|
|
55
|
+
* Float32 PCM.
|
|
56
|
+
*/
|
|
57
|
+
async function assertDecodableFileSize(filePath, name) {
|
|
58
|
+
const stats = await statInput(filePath);
|
|
59
|
+
if (stats.size <= MAX_STEREO_BYTES)
|
|
60
|
+
return;
|
|
61
|
+
throw new InvalidAudioInputError(`${name} (${filePath}) is ${Math.round(stats.size / 1_000_000)} MB; ` +
|
|
62
|
+
`files over ${Math.round(MAX_STEREO_BYTES / 1_000_000)} MB cannot fit the ` +
|
|
63
|
+
`${AUDIOGEN_INPUT_MAX_SECONDS} s limit and are rejected before decoding`);
|
|
64
|
+
}
|
|
65
|
+
/** Stream a raw PCM file into memory without blocking the event loop, capped by size. */
|
|
66
|
+
async function readRawPcmFile(filePath, name) {
|
|
67
|
+
const stats = await statInput(filePath);
|
|
68
|
+
assertWithinLimit(stats.size, MAX_STEREO_BYTES, STEREO_FRAME_BYTES, name, filePath);
|
|
69
|
+
const chunks = [];
|
|
70
|
+
let total = 0;
|
|
71
|
+
const stream = fs.createReadStream(filePath);
|
|
72
|
+
for await (const chunk of stream) {
|
|
73
|
+
total += chunk.byteLength;
|
|
74
|
+
assertWithinLimit(total, MAX_STEREO_BYTES, STEREO_FRAME_BYTES, name, filePath);
|
|
75
|
+
chunks.push(chunk);
|
|
76
|
+
}
|
|
77
|
+
return chunks.length === 1 ? chunks[0] : Buffer.concat(chunks, total);
|
|
78
|
+
}
|
|
79
|
+
async function decodeMonoFloat32(filePath, name) {
|
|
80
|
+
const chunks = [];
|
|
81
|
+
let total = 0;
|
|
82
|
+
try {
|
|
83
|
+
const stream = await decodeAudioToStream(filePath, 'f32le', {
|
|
84
|
+
sampleRate: AUDIOGEN_INPUT_SAMPLE_RATE
|
|
85
|
+
});
|
|
86
|
+
for await (const chunk of stream) {
|
|
87
|
+
total += chunk.byteLength;
|
|
88
|
+
if (total > MAX_DECODED_MONO_BYTES) {
|
|
89
|
+
;
|
|
90
|
+
stream.destroy();
|
|
91
|
+
assertWithinLimit(total, MAX_DECODED_MONO_BYTES, FLOAT32_BYTES, name, filePath);
|
|
92
|
+
}
|
|
93
|
+
chunks.push(chunk);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
if (error instanceof InvalidAudioInputError)
|
|
98
|
+
throw error;
|
|
99
|
+
throw new InvalidAudioInputError(`${name} could not be decoded from ${filePath}`, error);
|
|
100
|
+
}
|
|
101
|
+
if (total === 0 || total % FLOAT32_BYTES !== 0) {
|
|
102
|
+
throw new InvalidAudioInputError(`${name} decoded to no usable audio from ${filePath}`);
|
|
103
|
+
}
|
|
104
|
+
return asFloat32(chunks.length === 1 ? chunks[0] : Buffer.concat(chunks, total));
|
|
105
|
+
}
|
|
106
|
+
function monoToStereo(mono, name) {
|
|
107
|
+
if (mono.length === 0) {
|
|
108
|
+
throw new InvalidAudioInputError(`${name} decoded to no usable audio`);
|
|
109
|
+
}
|
|
110
|
+
const stereo = new Float32Array(mono.length * AUDIOGEN_INPUT_CHANNELS);
|
|
111
|
+
for (let frame = 0; frame < mono.length; frame++) {
|
|
112
|
+
const sample = mono[frame];
|
|
113
|
+
if (!Number.isFinite(sample))
|
|
114
|
+
throw nonFiniteError(name);
|
|
115
|
+
stereo[frame * AUDIOGEN_INPUT_CHANNELS] = sample;
|
|
116
|
+
stereo[frame * AUDIOGEN_INPUT_CHANNELS + 1] = sample;
|
|
117
|
+
}
|
|
118
|
+
return stereo;
|
|
119
|
+
}
|
|
120
|
+
function toStereoFloat32(bytes, name) {
|
|
121
|
+
if (bytes.byteLength === 0 || bytes.byteLength % STEREO_FRAME_BYTES !== 0) {
|
|
122
|
+
throw new InvalidAudioInputError(`${name} must be non-empty interleaved stereo ${AUDIOGEN_INPUT_SAMPLE_RATE} Hz Float32 PCM ` +
|
|
123
|
+
`(byte length a multiple of ${STEREO_FRAME_BYTES}, got ${bytes.byteLength})`);
|
|
124
|
+
}
|
|
125
|
+
assertWithinLimit(bytes.byteLength, MAX_STEREO_BYTES, STEREO_FRAME_BYTES, name);
|
|
126
|
+
const pcm = asFloat32(bytes);
|
|
127
|
+
for (let index = 0; index < pcm.length; index++) {
|
|
128
|
+
if (!Number.isFinite(pcm[index]))
|
|
129
|
+
throw nonFiniteError(name);
|
|
130
|
+
}
|
|
131
|
+
return pcm;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* View the bytes as Float32 without copying when they are 4-byte aligned
|
|
135
|
+
* (fresh Buffers from base64/file reads and `Buffer.concat` are); only a
|
|
136
|
+
* misaligned pooled slice needs to be copied out.
|
|
137
|
+
*/
|
|
138
|
+
function asFloat32(bytes) {
|
|
139
|
+
if (bytes.byteOffset % FLOAT32_BYTES === 0) {
|
|
140
|
+
return new Float32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / FLOAT32_BYTES);
|
|
141
|
+
}
|
|
142
|
+
return new Float32Array(bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength));
|
|
143
|
+
}
|
|
144
|
+
function assertWithinLimit(bytes, limit, frameBytes, name, filePath) {
|
|
145
|
+
if (bytes <= limit)
|
|
146
|
+
return;
|
|
147
|
+
const seconds = Math.round(bytes / frameBytes / AUDIOGEN_INPUT_SAMPLE_RATE);
|
|
148
|
+
throw new InvalidAudioInputError(`${name}${filePath ? ` (${filePath})` : ''} is about ${seconds} s long; ` +
|
|
149
|
+
`the limit is ${AUDIOGEN_INPUT_MAX_SECONDS} s`);
|
|
150
|
+
}
|
|
151
|
+
function nonFiniteError(name) {
|
|
152
|
+
return new InvalidAudioInputError(`${name} must contain only finite samples`);
|
|
153
|
+
}
|
|
@@ -53,6 +53,7 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
53
53
|
import { AudioGen } from '@qvac/audiogen-ggml';
|
|
54
54
|
import { audioGenStatsSchema } from '../../../../../schemas/audio-gen.js';
|
|
55
55
|
import { getServerLogger } from '../../../../../logging/index.js';
|
|
56
|
+
import { resolveAudioGenPcm } from '../../../../../server/bare/plugins/audiogen-ggml/ops/audio-gen-input.js';
|
|
56
57
|
import { getModel } from '../../../../../server/bare/registry/model-registry.js';
|
|
57
58
|
import { getRequestRegistry, withRequestContext } from '../../../../../server/bare/runtime/index.js';
|
|
58
59
|
import { generateServerRequestId } from '../../../../../server/bare/runtime/request-id.js';
|
|
@@ -97,6 +98,14 @@ export async function* audioGenStream(request) {
|
|
|
97
98
|
});
|
|
98
99
|
let response;
|
|
99
100
|
try {
|
|
101
|
+
// Reference/source audio is decoded before the run is admitted so the
|
|
102
|
+
// model slot is never held by a request that fails on input decoding.
|
|
103
|
+
// Decoding can take real time, so the abort state is re-checked after it:
|
|
104
|
+
// an abort that fired mid-decode found no active native job to cancel, and
|
|
105
|
+
// starting the run afterwards would leave a ghost generation on the slot.
|
|
106
|
+
const { referenceAudio, sourceAudio } = ctx.signal.aborted
|
|
107
|
+
? {}
|
|
108
|
+
: await resolveAudioInputs(request, logger);
|
|
100
109
|
if (!ctx.signal.aborted) {
|
|
101
110
|
response = await model.run(request.caption, {
|
|
102
111
|
...(request.lyrics !== undefined && { lyrics: request.lyrics }),
|
|
@@ -105,7 +114,24 @@ export async function* audioGenStream(request) {
|
|
|
105
114
|
...(request.bpm !== undefined && { bpm: request.bpm }),
|
|
106
115
|
...(request.keyscale !== undefined && { keyscale: request.keyscale }),
|
|
107
116
|
...(request.timesignature !== undefined && { timesignature: request.timesignature }),
|
|
108
|
-
...(request.duration !== undefined && { duration: request.duration })
|
|
117
|
+
...(request.duration !== undefined && { duration: request.duration }),
|
|
118
|
+
...(request.lmTemperature !== undefined && { lmTemperature: request.lmTemperature }),
|
|
119
|
+
...(request.lmTopP !== undefined && { lmTopP: request.lmTopP }),
|
|
120
|
+
...(request.lmTopK !== undefined && { lmTopK: request.lmTopK }),
|
|
121
|
+
...(request.lmCfgScale !== undefined && { lmCfgScale: request.lmCfgScale }),
|
|
122
|
+
...(request.lmPhase1 !== undefined && { lmPhase1: request.lmPhase1 }),
|
|
123
|
+
...(request.dcwEnabled !== undefined && { dcwEnabled: request.dcwEnabled }),
|
|
124
|
+
...(request.dcwScaler !== undefined && { dcwScaler: request.dcwScaler }),
|
|
125
|
+
...(request.dcwHighScaler !== undefined && { dcwHighScaler: request.dcwHighScaler }),
|
|
126
|
+
...(request.taskType !== undefined && { taskType: request.taskType }),
|
|
127
|
+
...(request.audioCoverStrength !== undefined && {
|
|
128
|
+
audioCoverStrength: request.audioCoverStrength
|
|
129
|
+
}),
|
|
130
|
+
...(request.coverNoiseStrength !== undefined && {
|
|
131
|
+
coverNoiseStrength: request.coverNoiseStrength
|
|
132
|
+
}),
|
|
133
|
+
...(referenceAudio && { referenceAudio }),
|
|
134
|
+
...(sourceAudio && { sourceAudio })
|
|
109
135
|
});
|
|
110
136
|
for await (const chunk of response.iterate()) {
|
|
111
137
|
if (ctx.signal.aborted)
|
|
@@ -160,3 +186,28 @@ export async function* audioGenStream(request) {
|
|
|
160
186
|
await result_1;
|
|
161
187
|
}
|
|
162
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* Decode both optional audio inputs concurrently. When both fail, the first
|
|
191
|
+
* failure is thrown and the second is logged so neither diagnostic is lost.
|
|
192
|
+
*/
|
|
193
|
+
async function resolveAudioInputs(request, logger) {
|
|
194
|
+
const [reference, source] = await Promise.allSettled([
|
|
195
|
+
request.referenceAudio
|
|
196
|
+
? resolveAudioGenPcm(request.referenceAudio, 'referenceAudio')
|
|
197
|
+
: Promise.resolve(undefined),
|
|
198
|
+
request.sourceAudio
|
|
199
|
+
? resolveAudioGenPcm(request.sourceAudio, 'sourceAudio')
|
|
200
|
+
: Promise.resolve(undefined)
|
|
201
|
+
]);
|
|
202
|
+
const failures = [reference, source].filter((result) => result.status === 'rejected');
|
|
203
|
+
if (failures.length > 0) {
|
|
204
|
+
for (const extra of failures.slice(1)) {
|
|
205
|
+
logger.warn(`[audiogen] additional audio input failure for modelId=${request.modelId}: ${extra.reason instanceof Error ? extra.reason.message : String(extra.reason)}`);
|
|
206
|
+
}
|
|
207
|
+
throw failures[0].reason;
|
|
208
|
+
}
|
|
209
|
+
return {
|
|
210
|
+
referenceAudio: reference.status === 'fulfilled' ? reference.value : undefined,
|
|
211
|
+
sourceAudio: source.status === 'fulfilled' ? source.value : undefined
|
|
212
|
+
};
|
|
213
|
+
}
|
|
@@ -175,6 +175,20 @@ export declare const audioGenPlugin: {
|
|
|
175
175
|
audioGenStream: import("../../../../schemas/index.js").PluginHandlerDefinition<import("zod").ZodObject<{
|
|
176
176
|
type: import("zod").ZodLiteral<"audioGenStream">;
|
|
177
177
|
requestId: import("zod").ZodOptional<import("zod").ZodString>;
|
|
178
|
+
referenceAudio: import("zod").ZodOptional<import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
|
|
179
|
+
type: import("zod").ZodLiteral<"base64">;
|
|
180
|
+
value: import("zod").ZodString;
|
|
181
|
+
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
182
|
+
type: import("zod").ZodLiteral<"filePath">;
|
|
183
|
+
value: import("zod").ZodString;
|
|
184
|
+
}, import("zod/v4/core").$strip>], "type">>;
|
|
185
|
+
sourceAudio: import("zod").ZodOptional<import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
|
|
186
|
+
type: import("zod").ZodLiteral<"base64">;
|
|
187
|
+
value: import("zod").ZodString;
|
|
188
|
+
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
189
|
+
type: import("zod").ZodLiteral<"filePath">;
|
|
190
|
+
value: import("zod").ZodString;
|
|
191
|
+
}, import("zod/v4/core").$strip>], "type">>;
|
|
178
192
|
modelId: import("zod").ZodString;
|
|
179
193
|
caption: import("zod").ZodString;
|
|
180
194
|
lyrics: import("zod").ZodOptional<import("zod").ZodString>;
|
|
@@ -184,6 +198,20 @@ export declare const audioGenPlugin: {
|
|
|
184
198
|
keyscale: import("zod").ZodOptional<import("zod").ZodString>;
|
|
185
199
|
timesignature: import("zod").ZodOptional<import("zod").ZodString>;
|
|
186
200
|
duration: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
201
|
+
lmTemperature: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
202
|
+
lmTopP: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
203
|
+
lmTopK: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
204
|
+
lmCfgScale: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
205
|
+
lmPhase1: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
206
|
+
dcwEnabled: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
207
|
+
dcwScaler: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
208
|
+
dcwHighScaler: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
209
|
+
taskType: import("zod").ZodOptional<import("zod").ZodEnum<{
|
|
210
|
+
text2music: "text2music";
|
|
211
|
+
"cover-nofsq": "cover-nofsq";
|
|
212
|
+
}>>;
|
|
213
|
+
audioCoverStrength: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
214
|
+
coverNoiseStrength: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
187
215
|
}, import("zod/v4/core").$strict>, import("zod").ZodObject<{
|
|
188
216
|
type: import("zod").ZodLiteral<"audioGenStream">;
|
|
189
217
|
progress: import("zod").ZodOptional<import("zod").ZodObject<{
|
|
@@ -12,7 +12,9 @@ function createOCRModel(modelId, detectorPath, recognizerPath, ocrConfig) {
|
|
|
12
12
|
const params = {
|
|
13
13
|
pathDetector: detectorPath,
|
|
14
14
|
pathRecognizer: recognizerPath,
|
|
15
|
-
|
|
15
|
+
...(ocrConfig.langList !== undefined
|
|
16
|
+
? { langList: ocrConfig.langList }
|
|
17
|
+
: ocrConfig.pipelineType !== 'doctr' && { langList: ['en'] }),
|
|
16
18
|
...(ocrConfig.pipelineType !== undefined && {
|
|
17
19
|
pipelineType: ocrConfig.pipelineType
|
|
18
20
|
}),
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { getModel } from '../../../../../server/bare/registry/model-registry.js';
|
|
2
|
+
import { vlaHparamsSchema } from '../../../../../schemas/index.js';
|
|
3
|
+
export async function vlaSetEmbodiment(request) {
|
|
4
|
+
const model = getModel(request.modelId);
|
|
5
|
+
const hparams = await model.setEmbodiment(request.embodiment);
|
|
6
|
+
// Validate the addon-reported hparams against our schema so the wire
|
|
7
|
+
// shape stays consistent even if the underlying addon changes.
|
|
8
|
+
return { hparams: vlaHparamsSchema.parse(hparams) };
|
|
9
|
+
}
|
|
@@ -9,6 +9,11 @@ export declare const vlaPlugin: {
|
|
|
9
9
|
auto: "auto";
|
|
10
10
|
}>>;
|
|
11
11
|
verbosity: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
12
|
+
embodiment: import("zod").ZodOptional<import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodNumber, import("zod").ZodObject<{
|
|
13
|
+
tag: import("zod").ZodOptional<import("zod").ZodString>;
|
|
14
|
+
catId: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
15
|
+
numCameras: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
16
|
+
}, import("zod/v4/core").$strip>]>>;
|
|
12
17
|
}, import("zod/v4/core").$strip>;
|
|
13
18
|
createModel(params: CreateModelParams): PluginModelResult;
|
|
14
19
|
handlers: {
|
|
@@ -58,9 +63,41 @@ export declare const vlaPlugin: {
|
|
|
58
63
|
patches: "patches";
|
|
59
64
|
}>>;
|
|
60
65
|
imagePatchElems: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
66
|
+
selectedEmbodimentTag: import("zod").ZodOptional<import("zod").ZodString>;
|
|
67
|
+
selectedEmbodimentCatId: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
61
68
|
}, import("zod/v4/core").$strip>;
|
|
62
69
|
backendName: import("zod").ZodNullable<import("zod").ZodString>;
|
|
63
70
|
}, import("zod/v4/core").$strip>>;
|
|
71
|
+
vlaSetEmbodiment: import("../../../../schemas/index.js").PluginHandlerDefinition<import("zod").ZodObject<{
|
|
72
|
+
type: import("zod").ZodLiteral<"vlaSetEmbodiment">;
|
|
73
|
+
modelId: import("zod").ZodString;
|
|
74
|
+
embodiment: import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodNumber, import("zod").ZodObject<{
|
|
75
|
+
tag: import("zod").ZodOptional<import("zod").ZodString>;
|
|
76
|
+
catId: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
77
|
+
numCameras: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
78
|
+
}, import("zod/v4/core").$strip>]>;
|
|
79
|
+
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
80
|
+
hparams: import("zod").ZodObject<{
|
|
81
|
+
chunkSize: import("zod").ZodNumber;
|
|
82
|
+
actionDim: import("zod").ZodNumber;
|
|
83
|
+
maxActionDim: import("zod").ZodNumber;
|
|
84
|
+
maxStateDim: import("zod").ZodNumber;
|
|
85
|
+
tokenizerMaxLength: import("zod").ZodNumber;
|
|
86
|
+
visionImageSize: import("zod").ZodNumber;
|
|
87
|
+
numCameras: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
88
|
+
stateInputMode: import("zod").ZodOptional<import("zod").ZodEnum<{
|
|
89
|
+
discrete: "discrete";
|
|
90
|
+
continuous: "continuous";
|
|
91
|
+
}>>;
|
|
92
|
+
imageInputMode: import("zod").ZodOptional<import("zod").ZodEnum<{
|
|
93
|
+
pixels: "pixels";
|
|
94
|
+
patches: "patches";
|
|
95
|
+
}>>;
|
|
96
|
+
imagePatchElems: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
97
|
+
selectedEmbodimentTag: import("zod").ZodOptional<import("zod").ZodString>;
|
|
98
|
+
selectedEmbodimentCatId: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
99
|
+
}, import("zod/v4/core").$strip>;
|
|
100
|
+
}, import("zod/v4/core").$strip>>;
|
|
64
101
|
};
|
|
65
102
|
};
|
|
66
103
|
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { VlaModel } from '@qvac/vla-ggml';
|
|
2
|
-
import { definePlugin, defineHandler, vlaConfigSchema, vlaRunRequestSchema, vlaRunResponseSchema, vlaHparamsRequestSchema, vlaHparamsResponseSchema, ModelType, ADDON_VLA } from '../../../../schemas/index.js';
|
|
2
|
+
import { definePlugin, defineHandler, vlaConfigSchema, vlaRunRequestSchema, vlaRunResponseSchema, vlaHparamsRequestSchema, vlaHparamsResponseSchema, vlaSetEmbodimentRequestSchema, vlaSetEmbodimentResponseSchema, ModelType, ADDON_VLA } from '../../../../schemas/index.js';
|
|
3
3
|
import { createStreamLogger, registerAddonLogger } from '../../../../logging/index.js';
|
|
4
4
|
import { vlaRun } from './ops/vla-run.js';
|
|
5
5
|
import { vlaGetHparams } from './ops/vla-hparams.js';
|
|
6
|
+
import { vlaSetEmbodiment } from './ops/vla-set-embodiment.js';
|
|
6
7
|
// The `@qvac/vla-ggml` VlaModel exposes `load({ backend })` rather than the
|
|
7
8
|
// `load(force?)` signature `PluginModel` expects. Wrap it so the plugin
|
|
8
9
|
// framework can call `load()` and have the configured backend flow through.
|
|
@@ -23,11 +24,18 @@ export const vlaPlugin = definePlugin({
|
|
|
23
24
|
const config = (params.modelConfig ?? {});
|
|
24
25
|
const logger = createStreamLogger(params.modelId, ModelType.ggmlVla);
|
|
25
26
|
registerAddonLogger(params.modelId, ModelType.ggmlVla, logger);
|
|
27
|
+
const addonConfig = {
|
|
28
|
+
...(config.verbosity !== undefined && { verbosity: config.verbosity }),
|
|
29
|
+
// The zod-inferred selector widens optional props with `| undefined`,
|
|
30
|
+
// which exactOptionalPropertyTypes rejects against the addon's exact
|
|
31
|
+
// shape — the runtime value is identical, so re-assert the addon type.
|
|
32
|
+
...(config.embodiment !== undefined && {
|
|
33
|
+
embodiment: config.embodiment
|
|
34
|
+
})
|
|
35
|
+
};
|
|
26
36
|
const inner = new VlaModel({
|
|
27
37
|
files: { model: [params.modelPath] },
|
|
28
|
-
...(
|
|
29
|
-
config: { verbosity: config.verbosity }
|
|
30
|
-
}),
|
|
38
|
+
...(Object.keys(addonConfig).length > 0 && { config: addonConfig }),
|
|
31
39
|
logger,
|
|
32
40
|
opts: { stats: true }
|
|
33
41
|
});
|
|
@@ -52,6 +60,15 @@ export const vlaPlugin = definePlugin({
|
|
|
52
60
|
streaming: false,
|
|
53
61
|
cancel: { scope: 'none' },
|
|
54
62
|
handler: vlaGetHparams
|
|
63
|
+
}),
|
|
64
|
+
vlaSetEmbodiment: defineHandler({
|
|
65
|
+
requestSchema: vlaSetEmbodimentRequestSchema,
|
|
66
|
+
responseSchema: vlaSetEmbodimentResponseSchema,
|
|
67
|
+
streaming: false,
|
|
68
|
+
// The addon refuses to switch while an inference job is in flight
|
|
69
|
+
// (JOB_ALREADY_RUNNING), so there is nothing meaningful to cancel here.
|
|
70
|
+
cancel: { scope: 'none' },
|
|
71
|
+
handler: vlaSetEmbodiment
|
|
55
72
|
})
|
|
56
73
|
}
|
|
57
74
|
});
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { TOOLS_MODE } from '../../../../../schemas/tools.js';
|
|
2
1
|
import { getModel, getModelConfig } from '../../../../../server/bare/registry/model-registry.js';
|
|
3
2
|
import { getServerLogger } from '../../../../../logging/index.js';
|
|
4
3
|
import { nowMs } from '../../../../../profiling/index.js';
|
|
@@ -6,7 +5,7 @@ import { buildStreamResult } from '../../../../../profiling/model-execution.js';
|
|
|
6
5
|
import { getResponseFormatJsonSchema } from '../../../../../server/utils/response-format.js';
|
|
7
6
|
import { transformMessages } from '../../../../../server/bare/plugins/llamacpp-completion/ops/completion-stream.js';
|
|
8
7
|
import { normalizeCompletionStats } from '../../../../../server/bare/plugins/llamacpp-completion/ops/completion-stats.js';
|
|
9
|
-
import {
|
|
8
|
+
import { prependToolsToHistory } from '../../../../../server/utils/tool-integration.js';
|
|
10
9
|
const logger = getServerLogger();
|
|
11
10
|
function runBatchModel(model, prompts) {
|
|
12
11
|
const run = model.run.bind(model);
|
|
@@ -27,10 +26,7 @@ function renderPromptHistory(prompt, options) {
|
|
|
27
26
|
const tools = options.toolsEnabled && prompt.tools && prompt.tools.length > 0 ? prompt.tools : undefined;
|
|
28
27
|
let historyWithTools = prompt.history;
|
|
29
28
|
if (tools) {
|
|
30
|
-
historyWithTools =
|
|
31
|
-
options.toolsMode === TOOLS_MODE.dynamic
|
|
32
|
-
? appendToolsToHistory(prompt.history, tools)
|
|
33
|
-
: prependToolsToHistory(prompt.history, tools);
|
|
29
|
+
historyWithTools = prependToolsToHistory(prompt.history, tools);
|
|
34
30
|
}
|
|
35
31
|
// Uses the same attachment expansion as single completion: each SDK
|
|
36
32
|
// attachment becomes an addon `type: "media"` message before the text turn.
|
|
@@ -61,26 +57,31 @@ export async function* batchCompletion(params, opts) {
|
|
|
61
57
|
const model = getModel(modelId);
|
|
62
58
|
const modelConfig = getModelConfig(modelId);
|
|
63
59
|
const renderOptions = {
|
|
64
|
-
toolsEnabled: modelConfig.tools === true
|
|
65
|
-
toolsMode: modelConfig.toolsMode
|
|
60
|
+
toolsEnabled: modelConfig.tools === true
|
|
66
61
|
};
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
62
|
+
// Cancel via the batch response, mirroring completion(): the addon routes
|
|
63
|
+
// response.cancel() to cancelJob for this batch group only, so a concurrent
|
|
64
|
+
// peer batch or completion on the same model keeps decoding.
|
|
65
|
+
let activeResponse = null;
|
|
66
|
+
const cancelActive = () => {
|
|
67
|
+
activeResponse?.cancel().catch((err) => {
|
|
68
|
+
requestLogger.warn(`[cancel] batch response.cancel() rejected during abort for modelId=${modelId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
69
|
+
});
|
|
74
70
|
};
|
|
71
|
+
const onAbort = () => cancelActive();
|
|
75
72
|
signal.addEventListener('abort', onAbort, { once: true });
|
|
76
73
|
if (signal.aborted)
|
|
77
74
|
onAbort();
|
|
78
75
|
scope.defer(() => {
|
|
79
76
|
signal.removeEventListener('abort', onAbort);
|
|
77
|
+
activeResponse = null;
|
|
80
78
|
});
|
|
81
79
|
const addonPrompts = prompts.map((prompt) => buildBatchPrompt(prompt, renderOptions));
|
|
82
80
|
const modelStart = nowMs();
|
|
83
81
|
const response = await runBatchModel(model, addonPrompts);
|
|
82
|
+
activeResponse = response;
|
|
83
|
+
if (signal.aborted)
|
|
84
|
+
cancelActive();
|
|
84
85
|
const ids = response.ids;
|
|
85
86
|
yield { type: 'ids', ids };
|
|
86
87
|
for await (const output of response.iterate()) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare function logCacheStatus(cacheKey: string, isReusing: boolean): void;
|
|
2
|
-
export declare function logCacheInit(cacheKey: string, systemPrompt: string
|
|
2
|
+
export declare function logCacheInit(cacheKey: string, systemPrompt: string): void;
|
|
3
3
|
export declare function logMessagesToAddon(messages: unknown[], phase?: 'CACHE_INIT' | 'PROMPT_SEND' | 'NO_CACHE'): void;
|
|
4
4
|
export declare function logCacheDisabled(): void;
|
|
5
5
|
export declare function logCacheSave(sessionPath: string): void;
|
|
@@ -17,9 +17,9 @@ export function logCacheStatus(cacheKey, isReusing) {
|
|
|
17
17
|
const status = isReusing ? 'REUSING' : 'CREATING';
|
|
18
18
|
logger.debug(`[kv-cache] [${cacheKey}] ${status} cache`);
|
|
19
19
|
}
|
|
20
|
-
export function logCacheInit(cacheKey, systemPrompt
|
|
20
|
+
export function logCacheInit(cacheKey, systemPrompt) {
|
|
21
21
|
const promptLen = systemPrompt.length;
|
|
22
|
-
logger.debug(`[kv-cache] [${cacheKey}] Initializing cache (prompt: ${promptLen} chars
|
|
22
|
+
logger.debug(`[kv-cache] [${cacheKey}] Initializing cache (prompt: ${promptLen} chars)`);
|
|
23
23
|
}
|
|
24
24
|
export function logMessagesToAddon(messages, phase = 'PROMPT_SEND') {
|
|
25
25
|
const typedMessages = messages;
|
|
@@ -18,4 +18,10 @@ export declare function normalizeCompletionStats(stats: LlmStats | undefined): {
|
|
|
18
18
|
* when nothing was streamed.
|
|
19
19
|
*/
|
|
20
20
|
export declare function withEmittedTokens(stats: CompletionStats | undefined, emittedPieces: number): CompletionStats | undefined;
|
|
21
|
+
export declare function stoppedByLength({ cancelled, effectivePredict, generatedTokens, stoppedAtContextBoundary }: {
|
|
22
|
+
cancelled: boolean;
|
|
23
|
+
effectivePredict: number | undefined;
|
|
24
|
+
generatedTokens: number | undefined;
|
|
25
|
+
stoppedAtContextBoundary: boolean;
|
|
26
|
+
}): boolean;
|
|
21
27
|
//# sourceMappingURL=completion-stats.d.ts.map
|
|
@@ -46,3 +46,13 @@ export function withEmittedTokens(stats, emittedPieces) {
|
|
|
46
46
|
emittedTokens
|
|
47
47
|
};
|
|
48
48
|
}
|
|
49
|
+
export function stoppedByLength({ cancelled, effectivePredict, generatedTokens, stoppedAtContextBoundary }) {
|
|
50
|
+
if (cancelled)
|
|
51
|
+
return false;
|
|
52
|
+
if (stoppedAtContextBoundary)
|
|
53
|
+
return true;
|
|
54
|
+
return (effectivePredict !== undefined &&
|
|
55
|
+
effectivePredict > 0 &&
|
|
56
|
+
generatedTokens !== undefined &&
|
|
57
|
+
generatedTokens >= effectivePredict);
|
|
58
|
+
}
|