@qvac/sdk 0.18.0 → 0.18.2

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 CHANGED
@@ -666,7 +666,7 @@ JavaScript Dependencies
666
666
  https://github.com/tetherto/qvac
667
667
  @qvac/diagnostics@0.1.2
668
668
  https://github.com/tetherto/qvac
669
- @qvac/diffusion-cpp@0.17.0
669
+ @qvac/diffusion-cpp@0.18.0
670
670
  https://github.com/tetherto/qvac
671
671
  @qvac/embed-llamacpp@0.34.0
672
672
  https://github.com/tetherto/qvac
@@ -15,85 +15,129 @@ export const VERBOSITY = {
15
15
  const verbositySchema = z.enum(VERBOSITY);
16
16
  // Base schema - validates types, all fields optional (for client-side validation)
17
17
  export const llmConfigBaseSchema = z.object({
18
- ctx_size: z.number().optional(),
19
- temp: z.number().min(0).max(2).optional(),
20
- top_p: z.number().min(0).max(1).optional(),
21
- top_k: z.number().int().min(0).max(128).optional(),
22
- seed: z.number().optional(),
23
- gpu_layers: z.number().optional(),
24
- lora: z.string().optional(),
25
- device: z.string().optional(),
18
+ ctx_size: z
19
+ .number()
20
+ .optional()
21
+ .describe("Context window size in tokens; `0` uses the model's trained context length. Default 1024."),
22
+ temp: z.number().min(0).max(2).optional().describe('Sampling temperature (0–2). Default 0.8.'),
23
+ top_p: z
24
+ .number()
25
+ .min(0)
26
+ .max(1)
27
+ .optional()
28
+ .describe('Top-p (nucleus) sampling cutoff (0–1). Default 0.9.'),
29
+ top_k: z
30
+ .number()
31
+ .int()
32
+ .min(0)
33
+ .max(128)
34
+ .optional()
35
+ .describe('Top-k sampling — keep only the top K tokens (0–128). Default 40.'),
36
+ seed: z.number().optional().describe('Sampling RNG seed; `-1` (default) picks a random seed.'),
37
+ gpu_layers: z
38
+ .number()
39
+ .optional()
40
+ .describe('Number of model layers to offload to the GPU. Default 99 (offload all).'),
41
+ lora: z
42
+ .string()
43
+ .optional()
44
+ .describe('Path to a LoRA adapter file to apply on top of the base model.'),
45
+ device: z
46
+ .string()
47
+ .optional()
48
+ .describe("Device to run inference on: `'gpu'` or `'cpu'`. Default `'gpu'`."),
26
49
  predict: z
27
50
  .union([
28
51
  z.literal(-1), // special: until stop token
29
52
  z.literal(-2), // special: until context filled
30
53
  z.number().int().min(1) // positive integer: fixed token count
31
54
  ])
32
- .optional(),
33
- /** JS-side only: seeds conversation history. Never forwarded to the C++ addon. */
34
- system_prompt: z.string().optional(),
35
- no_mmap: z.boolean().optional(),
36
- verbosity: verbositySchema.optional(),
37
- presence_penalty: z.number().optional(),
38
- frequency_penalty: z.number().optional(),
39
- repeat_penalty: z.number().optional(),
40
- stop_sequences: z.array(z.string()).optional(),
41
- n_discarded: z.number().optional(),
42
- /**
43
- * Concurrent sequence slots for continuous batching. Defaults to 1
44
- * (sequential, batching disabled); values >= 2 enable batched decoding in
45
- * @qvac/llm-llamacpp.
46
- */
47
- parallel: z.number().int().min(1).optional(),
48
- tools: z.boolean().optional(),
49
- 'cache-type-k': z.string().optional(),
50
- 'cache-type-v': z.string().optional(),
51
- 'main-gpu': z.union([z.number().int().min(0), z.enum(['integrated', 'dedicated'])]).optional(),
52
- 'split-mode': z.enum(['none', 'layer', 'row']).optional(),
53
- 'tensor-split': z.string().optional(),
54
- /**
55
- * Writable directory for OpenCL kernel binary cache. Required on Android
56
- * for fast GPU startup.
57
- */
58
- openclCacheDir: z.string().optional(),
59
- /**
60
- * Reasoning channel token budget. `-1` = unrestricted, `0` = disabled, any
61
- * positive integer caps the reasoning channel at that many tokens (the
62
- * sampler force-emits the closing think tag once the budget is exhausted).
63
- */
64
- reasoning_budget: z.number().int().min(-1).max(REASONING_BUDGET_MAX).optional(),
65
- projectionModelSrc: modelSrcInputSchema.optional(),
66
- /**
67
- * Qwen3.5-VL multi-tile image encoding mode (multimodal models only):
68
- * - `"sequential"` (default): encode image tiles one tile at a time.
69
- * - `"batched"`: encode all tiles in a single batched pass.
70
- * - `"disabled"`: no multi-tile encoding (single tile).
71
- * Ignored by text-only models. Default is `"sequential"`.
72
- */
73
- image_tile_mode: z.enum(['disabled', 'batched', 'sequential']).optional(),
74
- /**
75
- * idefics3-style image preprocessing rule (multimodal models only):
76
- * - `"on"`: round the image's long side up to a whole number of slices and
77
- * cap it, so an image smaller than the cap keeps its own resolution and
78
- * becomes far fewer slices.
79
- * - `"off"`: always stretch the long side to the cap.
80
- * When unset, the model's own GGUF value is used. Ignored with a warning by
81
- * models that do not use idefics3-style preprocessing. Changes the number of
82
- * image tokens, and therefore both accuracy and encode time, so a checkpoint
83
- * whose GGUF omits the key needs this set to preprocess correctly.
84
- */
85
- image_no_upscale: z.enum(['on', 'off']).optional(),
86
- /**
87
- * Run the multimodal projector (mmproj / vision encoder) on the GPU
88
- * (multimodal models only). `true` forces GPU, `false` forces CPU. When
89
- * unset, the llm-llamacpp addon auto-selects the backend per device class:
90
- * GPU on desktop/iOS and positively-detected Android Adreno 800+ GPUs; CPU on
91
- * every other Android GPU — Mali, Adreno <800, and any tier that can't be
92
- * detected (only Adreno 800+ is benchmarked to encode the projector faster on
93
- * the GPU than the CPU). Only honoured when the model itself runs on a GPU
94
- * backend — ignored with a warning on CPU.
95
- */
96
- 'mmproj-use-gpu': z.boolean().optional()
55
+ .optional()
56
+ .describe('Max tokens to predict. `-1` = until stop token, `-2` = until context filled.'),
57
+ system_prompt: z
58
+ .string()
59
+ .optional()
60
+ .describe("Seeds conversation history on the JS side only; never forwarded to the addon. Default `'You are a helpful assistant.'`"),
61
+ no_mmap: z.boolean().optional().describe('Disable memory-mapped model loading. Default false.'),
62
+ verbosity: verbositySchema
63
+ .optional()
64
+ .describe('Native log verbosity: `0`=ERROR, `1`=WARN, `2`=INFO, `3`=DEBUG. Default 0.'),
65
+ presence_penalty: z
66
+ .number()
67
+ .optional()
68
+ .describe('Presence penalty applied to tokens that have already appeared. Default 0.'),
69
+ frequency_penalty: z
70
+ .number()
71
+ .optional()
72
+ .describe('Frequency penalty applied to tokens by their frequency so far. Default 0.'),
73
+ repeat_penalty: z
74
+ .number()
75
+ .optional()
76
+ .describe('Repetition penalty applied to repeated tokens. Default 1.1.'),
77
+ stop_sequences: z
78
+ .array(z.string())
79
+ .optional()
80
+ .describe('Strings that stop generation when produced (forwarded to the addon as `reverse_prompt`).'),
81
+ n_discarded: z
82
+ .number()
83
+ .optional()
84
+ .describe('Tokens to discard from the front of the context when it fills (sliding window); `0` (default) disables sliding. In batch mode clamped to the per-slot window (`ctx_size / parallel`).'),
85
+ parallel: z
86
+ .number()
87
+ .int()
88
+ .min(1)
89
+ .optional()
90
+ .describe('Concurrent sequence slots for continuous batching (1–256). Default 1 (sequential, batching off); `>= 2` enables batched decoding and splits the KV cache evenly across slots.'),
91
+ tools: z
92
+ .boolean()
93
+ .optional()
94
+ .describe("Enable tool calling via the model's jinja chat template. Default false."),
95
+ 'cache-type-k': z
96
+ .string()
97
+ .optional()
98
+ .describe('KV-cache key quantization type (`f16`, `f32`, `bf16`, `q8_0`, `q4_0`, …). Unset selects a backend-safe default.'),
99
+ 'cache-type-v': z
100
+ .string()
101
+ .optional()
102
+ .describe('KV-cache value quantization type; quantizing the value cache requires flash attention. Unset selects a backend-safe default.'),
103
+ 'main-gpu': z
104
+ .union([z.number().int().min(0), z.enum(['integrated', 'dedicated'])])
105
+ .optional()
106
+ .describe("GPU to use on multi-GPU systems: a device index, or `'integrated'`/`'dedicated'` to restrict selection to that class."),
107
+ 'split-mode': z
108
+ .enum(['none', 'layer', 'row'])
109
+ .optional()
110
+ .describe("How to split the model across GPUs: `'none'` (default, single GPU), `'layer'` (pipeline parallelism), or `'row'` (tensor parallelism)."),
111
+ 'tensor-split': z
112
+ .string()
113
+ .optional()
114
+ .describe("Proportions for distributing layers/rows across GPUs, e.g. `'1,1'` (equal) or `'3,1'` (75/25)."),
115
+ openclCacheDir: z
116
+ .string()
117
+ .optional()
118
+ .describe('Writable directory for the OpenCL kernel binary cache; required on Android for fast GPU startup.'),
119
+ reasoning_budget: z
120
+ .number()
121
+ .int()
122
+ .min(-1)
123
+ .max(REASONING_BUDGET_MAX)
124
+ .optional()
125
+ .describe('Reasoning-channel token budget. `-1` (default) unrestricted, `0` disables it, any positive integer caps the reasoning channel at that many tokens (the closing think tag is force-emitted once the budget is spent).'),
126
+ projectionModelSrc: modelSrcInputSchema
127
+ .optional()
128
+ .describe('Multimodal projection (mmproj / vision encoder) model source; multimodal models only.'),
129
+ image_tile_mode: z
130
+ .enum(['disabled', 'batched', 'sequential'])
131
+ .optional()
132
+ .describe("Qwen3.5-VL multi-tile image encoding mode (multimodal models only): `'sequential'` (default) encodes image tiles one at a time, `'batched'` encodes all tiles in a single batched pass, `'disabled'` does no multi-tile encoding (single tile). Ignored by text-only models."),
133
+ image_no_upscale: z
134
+ .enum(['on', 'off'])
135
+ .optional()
136
+ .describe("idefics3-style image preprocessing rule (multimodal models only): `'on'` rounds the image's long side up to a whole number of slices and caps it, so an image smaller than the cap keeps its own resolution and becomes far fewer slices; `'off'` always stretches the long side to the cap. When unset, the model's own GGUF value is used; ignored with a warning by models that do not use idefics3-style preprocessing. Changes the number of image tokens (and therefore both accuracy and encode time), so a checkpoint whose GGUF omits the key needs this set to preprocess correctly."),
137
+ 'mmproj-use-gpu': z
138
+ .boolean()
139
+ .optional()
140
+ .describe('Run the multimodal projector (mmproj / vision encoder) on the GPU (multimodal models only). `true` forces GPU, `false` forces CPU. When unset, the backend is auto-selected per device class: GPU on desktop/iOS and Android Adreno 800+; CPU on every other Android GPU (Arm Mali, Adreno <800, and undetectable Adreno tiers), with the LLM layers still on the GPU. Only honoured when the model itself runs on a GPU backend — ignored with a warning on CPU.')
97
141
  });
98
142
  // Default values - typed as partial of the config
99
143
  export const LLM_CONFIG_DEFAULTS = {
@@ -110,22 +154,57 @@ export const llmConfigSchema = llmConfigBaseSchema.transform((data) => ({
110
154
  }));
111
155
  // Base schema - validates types, all fields optional (for client-side validation)
112
156
  export const embedConfigBaseSchema = z.object({
113
- gpuLayers: z.number().int().optional(),
114
- device: z.enum(['gpu', 'cpu']).optional(),
115
- batchSize: z.number().int().min(1).optional(),
116
- pooling: z.enum(['none', 'mean', 'cls', 'last', 'rank']).optional(),
117
- attention: z.enum(['causal', 'non-causal']).optional(),
118
- embdNormalize: z.number().int().optional(),
119
- flashAttention: z.enum(['on', 'off', 'auto']).optional(),
120
- mainGpu: z.union([z.number().int().min(0), z.enum(['integrated', 'dedicated'])]).optional(),
121
- splitMode: z.enum(['none', 'layer', 'row']).optional(),
122
- tensorSplit: z.string().optional(),
123
- verbosity: verbositySchema.optional(),
124
- /**
125
- * Writable directory for OpenCL kernel binary cache. Required on Android
126
- * for fast GPU startup.
127
- */
128
- openclCacheDir: z.string().optional()
157
+ gpuLayers: z
158
+ .number()
159
+ .int()
160
+ .optional()
161
+ .describe('Number of model layers to offload to the GPU. Default 99 (offload all).'),
162
+ device: z
163
+ .enum(['gpu', 'cpu'])
164
+ .optional()
165
+ .describe("Device to run inference on: `'gpu'` or `'cpu'`. Default `'gpu'`."),
166
+ batchSize: z
167
+ .number()
168
+ .int()
169
+ .min(1)
170
+ .optional()
171
+ .describe('Tokens processed per batch (input throughput). Default 1024.'),
172
+ pooling: z
173
+ .enum(['none', 'mean', 'cls', 'last', 'rank'])
174
+ .optional()
175
+ .describe("Pooling strategy collapsing token embeddings into one sequence vector: `'none'`, `'mean'`, `'cls'`, `'last'`, or `'rank'`. Unset uses the model default."),
176
+ attention: z
177
+ .enum(['causal', 'non-causal'])
178
+ .optional()
179
+ .describe("Attention type: `'causal'` or `'non-causal'`. Unset uses the model default."),
180
+ embdNormalize: z
181
+ .number()
182
+ .int()
183
+ .optional()
184
+ .describe('Embedding normalization: `-1` none, `0` max-abs int16, `1` taxicab, `2` euclidean, `>2` p-norm. Default 2 (euclidean).'),
185
+ flashAttention: z
186
+ .enum(['on', 'off', 'auto'])
187
+ .optional()
188
+ .describe("Flash attention: `'on'`, `'off'`, or `'auto'`. Default `'auto'`."),
189
+ mainGpu: z
190
+ .union([z.number().int().min(0), z.enum(['integrated', 'dedicated'])])
191
+ .optional()
192
+ .describe("GPU to use on multi-GPU systems: a device index, or `'integrated'`/`'dedicated'` to restrict selection to that class."),
193
+ splitMode: z
194
+ .enum(['none', 'layer', 'row'])
195
+ .optional()
196
+ .describe("How to split the model across GPUs: `'none'` (default, single GPU), `'layer'` (pipeline parallelism), or `'row'` (tensor parallelism)."),
197
+ tensorSplit: z
198
+ .string()
199
+ .optional()
200
+ .describe("Proportions for distributing layers/rows across GPUs, e.g. `'1,1'` (equal) or `'3,1'` (75/25)."),
201
+ verbosity: verbositySchema
202
+ .optional()
203
+ .describe('Native log verbosity: `0`=ERROR, `1`=WARN, `2`=INFO, `3`=DEBUG. Default 0.'),
204
+ openclCacheDir: z
205
+ .string()
206
+ .optional()
207
+ .describe('Writable directory for the OpenCL kernel binary cache; required on Android for fast GPU startup.')
129
208
  });
130
209
  // Default values - typed as partial of the config
131
210
  export const EMBED_CONFIG_DEFAULTS = {
@@ -0,0 +1,3 @@
1
+ export { llmConfigBaseSchema as llamacppCompletionConfigSchema, embedConfigBaseSchema as llamacppEmbeddingConfigSchema, type LlmConfigInput as LlamacppCompletionConfig, type EmbedConfigInput as LlamacppEmbeddingConfig } from './llamacpp-config.js';
2
+ export { modelSrcInputSchema as modelSourceSchema, type ModelSrcInput as ModelSource } from './model-src-utils.js';
3
+ //# sourceMappingURL=public.d.ts.map
@@ -0,0 +1,6 @@
1
+ // Public schema surface for `@qvac/sdk/schemas`. Stable, end-user-facing names
2
+ // (aliased from the internal schemas) so consumers such as the CLI can import a
3
+ // model's `modelConfig` schema and read its field descriptions without
4
+ // depending on internal identifiers.
5
+ export { llmConfigBaseSchema as llamacppCompletionConfigSchema, embedConfigBaseSchema as llamacppEmbeddingConfigSchema } from './llamacpp-config.js';
6
+ export { modelSrcInputSchema as modelSourceSchema } from './model-src-utils.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qvac/sdk",
3
- "version": "0.18.0",
3
+ "version": "0.18.2",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -124,6 +124,11 @@
124
124
  "types": "./dist/schemas/plugin.d.ts",
125
125
  "import": "./dist/schemas/plugin.js"
126
126
  },
127
+ "./schemas": {
128
+ "types": "./dist/schemas/public.d.ts",
129
+ "import": "./dist/schemas/public.js",
130
+ "require": "./dist/schemas/public.js"
131
+ },
127
132
  "./expo-plugin": "./dist/expo/plugins/index.js",
128
133
  "./electron-forge": {
129
134
  "require": "./electron-forge/index.cjs",
@@ -211,7 +216,7 @@
211
216
  "@qvac/bci-whispercpp": "^0.7.1",
212
217
  "@qvac/classification-ggml": "^0.20.0",
213
218
  "@qvac/decoder-audio": "^0.5.0",
214
- "@qvac/diffusion-cpp": "^0.17.0",
219
+ "@qvac/diffusion-cpp": "^0.18.0",
215
220
  "@qvac/embed-llamacpp": "^0.34.0",
216
221
  "@qvac/error": "^0.1.1",
217
222
  "@qvac/langdetect-text": "^0.1.2",