@simulatte/doppler 0.1.4 → 0.1.5
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/README.md +4 -3
- package/package.json +25 -4
- package/src/client/doppler-api.browser.d.ts +1 -0
- package/src/client/doppler-api.browser.js +288 -0
- package/src/client/doppler-api.js +1 -1
- package/src/client/doppler-provider/types.js +1 -1
- package/src/config/execution-contract-check.d.ts +33 -0
- package/src/config/execution-contract-check.js +72 -0
- package/src/config/execution-v0-contract-check.d.ts +94 -0
- package/src/config/execution-v0-contract-check.js +251 -0
- package/src/config/execution-v0-graph-contract-check.d.ts +20 -0
- package/src/config/execution-v0-graph-contract-check.js +64 -0
- package/src/config/kernel-path-contract-check.d.ts +76 -0
- package/src/config/kernel-path-contract-check.js +479 -0
- package/src/config/kernel-path-loader.d.ts +16 -0
- package/src/config/kernel-path-loader.js +54 -0
- package/src/config/kernels/kernel-ref-digests.js +12 -0
- package/src/config/kernels/registry.json +556 -0
- package/src/config/loader.js +50 -46
- package/src/config/merge-contract-check.d.ts +16 -0
- package/src/config/merge-contract-check.js +321 -0
- package/src/config/merge-helpers.d.ts +58 -0
- package/src/config/merge-helpers.js +54 -0
- package/src/config/merge.js +3 -6
- package/src/config/presets/models/janus-text.json +2 -0
- package/src/config/quantization-contract-check.d.ts +12 -0
- package/src/config/quantization-contract-check.js +91 -0
- package/src/config/required-inference-fields-contract-check.d.ts +24 -0
- package/src/config/required-inference-fields-contract-check.js +231 -0
- package/src/config/schema/browser-suite-metrics.schema.d.ts +17 -0
- package/src/config/schema/browser-suite-metrics.schema.js +46 -0
- package/src/config/schema/conversion-report.schema.d.ts +40 -0
- package/src/config/schema/conversion-report.schema.js +108 -0
- package/src/config/schema/doppler.schema.js +12 -18
- package/src/config/schema/index.d.ts +22 -0
- package/src/config/schema/index.js +18 -0
- package/src/converter/core.d.ts +10 -0
- package/src/converter/core.js +27 -2
- package/src/converter/parsers/diffusion.js +63 -3
- package/src/gpu/kernels/depthwise_conv2d.d.ts +29 -0
- package/src/gpu/kernels/depthwise_conv2d.js +98 -0
- package/src/gpu/kernels/depthwise_conv2d.wgsl +58 -0
- package/src/gpu/kernels/depthwise_conv2d_f16.wgsl +62 -0
- package/src/gpu/kernels/grouped_pointwise_conv2d.d.ts +27 -0
- package/src/gpu/kernels/grouped_pointwise_conv2d.js +92 -0
- package/src/gpu/kernels/grouped_pointwise_conv2d.wgsl +47 -0
- package/src/gpu/kernels/grouped_pointwise_conv2d_f16.wgsl +51 -0
- package/src/gpu/kernels/index.d.ts +30 -0
- package/src/gpu/kernels/index.js +25 -0
- package/src/gpu/kernels/relu.d.ts +18 -0
- package/src/gpu/kernels/relu.js +45 -0
- package/src/gpu/kernels/relu.wgsl +21 -0
- package/src/gpu/kernels/relu_f16.wgsl +23 -0
- package/src/gpu/kernels/repeat_channels.d.ts +21 -0
- package/src/gpu/kernels/repeat_channels.js +60 -0
- package/src/gpu/kernels/repeat_channels.wgsl +29 -0
- package/src/gpu/kernels/repeat_channels_f16.wgsl +31 -0
- package/src/gpu/kernels/sana_linear_attention.d.ts +27 -0
- package/src/gpu/kernels/sana_linear_attention.js +122 -0
- package/src/gpu/kernels/sana_linear_attention_apply.wgsl +44 -0
- package/src/gpu/kernels/sana_linear_attention_apply_f16.wgsl +47 -0
- package/src/gpu/kernels/sana_linear_attention_summary.wgsl +47 -0
- package/src/gpu/kernels/sana_linear_attention_summary_f16.wgsl +49 -0
- package/src/index-browser.d.ts +1 -1
- package/src/index-browser.js +2 -2
- package/src/index.js +1 -1
- package/src/inference/browser-harness.js +62 -22
- package/src/inference/pipelines/diffusion/init.js +14 -0
- package/src/inference/pipelines/diffusion/pipeline.js +206 -77
- package/src/inference/pipelines/diffusion/sana-transformer.d.ts +53 -0
- package/src/inference/pipelines/diffusion/sana-transformer.js +738 -0
- package/src/inference/pipelines/diffusion/scheduler.d.ts +17 -1
- package/src/inference/pipelines/diffusion/scheduler.js +91 -3
- package/src/inference/pipelines/diffusion/text-encoder-gpu.d.ts +6 -4
- package/src/inference/pipelines/diffusion/text-encoder-gpu.js +270 -0
- package/src/inference/pipelines/diffusion/text-encoder.js +18 -1
- package/src/inference/pipelines/diffusion/types.d.ts +4 -0
- package/src/inference/pipelines/diffusion/vae.js +782 -78
- package/src/inference/pipelines/text/config.d.ts +5 -0
- package/src/inference/pipelines/text/config.js +1 -1
- package/src/inference/pipelines/text/execution-v0.js +14 -93
- package/src/rules/execution-rules-contract-check.d.ts +17 -0
- package/src/rules/execution-rules-contract-check.js +245 -0
- package/src/rules/kernels/depthwise-conv2d.rules.json +6 -0
- package/src/rules/kernels/grouped-pointwise-conv2d.rules.json +6 -0
- package/src/rules/kernels/relu.rules.json +6 -0
- package/src/rules/kernels/repeat-channels.rules.json +6 -0
- package/src/rules/kernels/sana-linear-attention.rules.json +6 -0
- package/src/rules/layer-pattern-contract-check.d.ts +17 -0
- package/src/rules/layer-pattern-contract-check.js +231 -0
- package/src/rules/rule-registry.d.ts +28 -0
- package/src/rules/rule-registry.js +38 -0
- package/src/tooling/conversion-config-materializer.d.ts +24 -0
- package/src/tooling/conversion-config-materializer.js +99 -0
- package/src/tooling/lean-execution-contract-runner.d.ts +43 -0
- package/src/tooling/lean-execution-contract-runner.js +158 -0
- package/src/tooling/node-convert.d.ts +10 -0
- package/src/tooling/node-converter.js +59 -0
- package/src/tooling/node-webgpu.js +9 -9
- package/src/version.d.ts +2 -0
- package/src/version.js +2 -0
- package/tools/convert-safetensors-node.js +47 -0
- package/tools/doppler-cli.js +115 -1
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import { resolveConfig, resolvePreset } from './loader.js';
|
|
2
|
+
import {
|
|
3
|
+
chooseNullish,
|
|
4
|
+
chooseDefinedWithSource,
|
|
5
|
+
mergeExecutionPatchLists,
|
|
6
|
+
mergeKernelPathPolicy,
|
|
7
|
+
mergeLayeredShallowObjects,
|
|
8
|
+
mergeShallowObject,
|
|
9
|
+
replaceSubtree,
|
|
10
|
+
} from './merge-helpers.js';
|
|
11
|
+
import { mergeConfig } from './merge.js';
|
|
12
|
+
import { createDopplerConfig } from './schema/index.js';
|
|
13
|
+
|
|
14
|
+
function buildWitnessManifestForArchitecture() {
|
|
15
|
+
return {
|
|
16
|
+
modelId: 'merge-semantics-witness',
|
|
17
|
+
modelType: 'transformer',
|
|
18
|
+
architecture: {
|
|
19
|
+
numLayers: 2,
|
|
20
|
+
hiddenSize: 256,
|
|
21
|
+
intermediateSize: 512,
|
|
22
|
+
numAttentionHeads: 4,
|
|
23
|
+
numKeyValueHeads: 4,
|
|
24
|
+
headDim: 64,
|
|
25
|
+
vocabSize: 1024,
|
|
26
|
+
maxSeqLen: 2048,
|
|
27
|
+
ropeTheta: null,
|
|
28
|
+
rmsNormEps: 1e-6,
|
|
29
|
+
},
|
|
30
|
+
config: {},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function buildWitnessMergeManifest() {
|
|
35
|
+
return {
|
|
36
|
+
modelId: 'merge-overlay-witness',
|
|
37
|
+
inference: {
|
|
38
|
+
attention: {
|
|
39
|
+
queryPreAttnScalar: 1,
|
|
40
|
+
attentionBias: false,
|
|
41
|
+
attnLogitSoftcapping: null,
|
|
42
|
+
slidingWindow: 4096,
|
|
43
|
+
queryKeyNorm: false,
|
|
44
|
+
attentionOutputGate: false,
|
|
45
|
+
causal: true,
|
|
46
|
+
},
|
|
47
|
+
normalization: {
|
|
48
|
+
rmsNormEps: 1e-6,
|
|
49
|
+
rmsNormWeightOffset: 0,
|
|
50
|
+
postAttentionNorm: true,
|
|
51
|
+
preFeedforwardNorm: true,
|
|
52
|
+
postFeedforwardNorm: false,
|
|
53
|
+
},
|
|
54
|
+
ffn: {
|
|
55
|
+
activation: 'gelu',
|
|
56
|
+
gatedActivation: false,
|
|
57
|
+
swigluLimit: null,
|
|
58
|
+
},
|
|
59
|
+
rope: {
|
|
60
|
+
ropeTheta: 1000000,
|
|
61
|
+
ropeLocalTheta: null,
|
|
62
|
+
ropeScalingType: null,
|
|
63
|
+
ropeScalingFactor: null,
|
|
64
|
+
ropeLocalScalingType: null,
|
|
65
|
+
ropeLocalScalingFactor: null,
|
|
66
|
+
yarnBetaFast: null,
|
|
67
|
+
yarnBetaSlow: null,
|
|
68
|
+
yarnOriginalMaxPos: null,
|
|
69
|
+
ropeLocalYarnBetaFast: null,
|
|
70
|
+
ropeLocalYarnBetaSlow: null,
|
|
71
|
+
ropeLocalYarnOriginalMaxPos: null,
|
|
72
|
+
},
|
|
73
|
+
output: {
|
|
74
|
+
finalLogitSoftcapping: 30,
|
|
75
|
+
tieWordEmbeddings: true,
|
|
76
|
+
scaleEmbeddings: false,
|
|
77
|
+
embeddingTranspose: false,
|
|
78
|
+
embeddingVocabSize: 1024,
|
|
79
|
+
},
|
|
80
|
+
layerPattern: null,
|
|
81
|
+
chatTemplate: {
|
|
82
|
+
type: 'gemma',
|
|
83
|
+
enabled: true,
|
|
84
|
+
},
|
|
85
|
+
defaultKernelPath: 'gemma3-f16-fused-f16a-online',
|
|
86
|
+
},
|
|
87
|
+
architecture: {
|
|
88
|
+
headDim: 64,
|
|
89
|
+
maxSeqLen: 2048,
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function recordCheck(results, id, ok, detail, mode = 'actual') {
|
|
95
|
+
results.push({ id, ok, detail, mode });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function buildMergeContractArtifact() {
|
|
99
|
+
const checks = [];
|
|
100
|
+
const preset = resolvePreset('gemma3');
|
|
101
|
+
const resolved = resolveConfig(buildWitnessManifestForArchitecture(), 'gemma3');
|
|
102
|
+
recordCheck(
|
|
103
|
+
checks,
|
|
104
|
+
'loader.architecture.nullish_null_falls_through',
|
|
105
|
+
resolved.architecture.ropeTheta === preset.architecture.ropeTheta,
|
|
106
|
+
`resolved ropeTheta=${resolved.architecture.ropeTheta}, preset ropeTheta=${preset.architecture.ropeTheta}`
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
const mergedUndefined = mergeConfig(buildWitnessMergeManifest(), {});
|
|
110
|
+
recordCheck(
|
|
111
|
+
checks,
|
|
112
|
+
'runtime.mergeConfig.defined_overlay_missing_falls_through',
|
|
113
|
+
mergedUndefined.inference.defaultKernelPath === 'gemma3-f16-fused-f16a-online'
|
|
114
|
+
&& mergedUndefined._sources.get('inference.defaultKernelPath') === 'manifest',
|
|
115
|
+
`value=${mergedUndefined.inference.defaultKernelPath}, source=${mergedUndefined._sources.get('inference.defaultKernelPath')}`
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
const mergedNull = mergeConfig(buildWitnessMergeManifest(), {
|
|
119
|
+
defaultKernelPath: null,
|
|
120
|
+
chatTemplate: {
|
|
121
|
+
enabled: null,
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
recordCheck(
|
|
125
|
+
checks,
|
|
126
|
+
'runtime.mergeConfig.defined_overlay_preserves_null',
|
|
127
|
+
mergedNull.inference.defaultKernelPath === null
|
|
128
|
+
&& mergedNull._sources.get('inference.defaultKernelPath') === 'runtime',
|
|
129
|
+
`value=${mergedNull.inference.defaultKernelPath}, source=${mergedNull._sources.get('inference.defaultKernelPath')}`
|
|
130
|
+
);
|
|
131
|
+
recordCheck(
|
|
132
|
+
checks,
|
|
133
|
+
'runtime.inference.chatTemplate.spread_preserves_null',
|
|
134
|
+
mergedNull.inference.chatTemplate.enabled === null
|
|
135
|
+
&& mergedNull._sources.get('inference.chatTemplate.enabled') === 'runtime',
|
|
136
|
+
`value=${String(mergedNull.inference.chatTemplate.enabled)}`
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
const runtimeConfig = createDopplerConfig({
|
|
140
|
+
runtime: {
|
|
141
|
+
inference: {
|
|
142
|
+
chatTemplate: {
|
|
143
|
+
enabled: null,
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
recordCheck(
|
|
149
|
+
checks,
|
|
150
|
+
'runtime.schema.chatTemplate.spread_preserves_null',
|
|
151
|
+
runtimeConfig.runtime.inference.chatTemplate.enabled === null,
|
|
152
|
+
`value=${String(runtimeConfig.runtime.inference.chatTemplate.enabled)}`
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
const overlaySources = new Map();
|
|
156
|
+
const chosenRuntimeValue = chooseDefinedWithSource(
|
|
157
|
+
'inference.defaultKernelPath',
|
|
158
|
+
null,
|
|
159
|
+
'manifest-path',
|
|
160
|
+
overlaySources
|
|
161
|
+
);
|
|
162
|
+
recordCheck(
|
|
163
|
+
checks,
|
|
164
|
+
'runtime.mergeHelpers.chooseDefinedWithSource.runtime_marks_source',
|
|
165
|
+
chosenRuntimeValue === null && overlaySources.get('inference.defaultKernelPath') === 'runtime',
|
|
166
|
+
`value=${String(chosenRuntimeValue)}, source=${overlaySources.get('inference.defaultKernelPath')}`,
|
|
167
|
+
'actual'
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
const manifestSources = new Map();
|
|
171
|
+
const chosenManifestValue = chooseDefinedWithSource(
|
|
172
|
+
'inference.defaultKernelPath',
|
|
173
|
+
undefined,
|
|
174
|
+
'manifest-path',
|
|
175
|
+
manifestSources
|
|
176
|
+
);
|
|
177
|
+
recordCheck(
|
|
178
|
+
checks,
|
|
179
|
+
'runtime.mergeHelpers.chooseDefinedWithSource.manifest_marks_source',
|
|
180
|
+
chosenManifestValue === 'manifest-path' && manifestSources.get('inference.defaultKernelPath') === 'manifest',
|
|
181
|
+
`value=${String(chosenManifestValue)}, source=${manifestSources.get('inference.defaultKernelPath')}`,
|
|
182
|
+
'actual'
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
const executionPatchBase = {
|
|
186
|
+
set: [{ op: 'seed' }],
|
|
187
|
+
remove: ['old_step'],
|
|
188
|
+
add: [{ id: 'new_step' }],
|
|
189
|
+
};
|
|
190
|
+
const executionPatchOverride = {
|
|
191
|
+
set: null,
|
|
192
|
+
remove: [],
|
|
193
|
+
add: undefined,
|
|
194
|
+
};
|
|
195
|
+
const mergedExecutionPatch = {
|
|
196
|
+
...mergeExecutionPatchLists(executionPatchBase, executionPatchOverride),
|
|
197
|
+
};
|
|
198
|
+
recordCheck(
|
|
199
|
+
checks,
|
|
200
|
+
'runtime.inference.executionPatch.nullish_null_falls_through',
|
|
201
|
+
mergedExecutionPatch.set === executionPatchBase.set
|
|
202
|
+
&& mergedExecutionPatch.add === executionPatchBase.add
|
|
203
|
+
&& Array.isArray(mergedExecutionPatch.remove)
|
|
204
|
+
&& mergedExecutionPatch.remove.length === 0,
|
|
205
|
+
`setLength=${mergedExecutionPatch.set.length}, removeLength=${mergedExecutionPatch.remove.length}, addLength=${mergedExecutionPatch.add.length}`,
|
|
206
|
+
'actual'
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
const sessionBase = {
|
|
210
|
+
kvcache: {
|
|
211
|
+
layout: 'paged',
|
|
212
|
+
maxSeqLen: 8192,
|
|
213
|
+
kvDtype: 'f16',
|
|
214
|
+
},
|
|
215
|
+
decodeLoop: {
|
|
216
|
+
batchSize: 16,
|
|
217
|
+
disableCommandBatching: false,
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
const sessionOverride = {
|
|
221
|
+
kvcache: {
|
|
222
|
+
layout: 'tiered',
|
|
223
|
+
},
|
|
224
|
+
decodeLoop: {
|
|
225
|
+
batchSize: 1,
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
const mergedSession = {
|
|
229
|
+
kvcache: replaceSubtree(sessionOverride.kvcache, sessionBase.kvcache),
|
|
230
|
+
decodeLoop: replaceSubtree(sessionOverride.decodeLoop, sessionBase.decodeLoop),
|
|
231
|
+
};
|
|
232
|
+
recordCheck(
|
|
233
|
+
checks,
|
|
234
|
+
'runtime.inference.session.subtree_override_replaces_base',
|
|
235
|
+
mergedSession.kvcache.layout === 'tiered'
|
|
236
|
+
&& mergedSession.kvcache.maxSeqLen === undefined
|
|
237
|
+
&& mergedSession.decodeLoop.batchSize === 1
|
|
238
|
+
&& mergedSession.decodeLoop.disableCommandBatching === undefined,
|
|
239
|
+
`kvcacheKeys=${Object.keys(mergedSession.kvcache).join(',')}; decodeLoopKeys=${Object.keys(mergedSession.decodeLoop).join(',')}`,
|
|
240
|
+
'actual'
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
const mergedChatTemplate = mergeShallowObject(
|
|
244
|
+
{ type: 'base', enabled: true },
|
|
245
|
+
{ enabled: null }
|
|
246
|
+
);
|
|
247
|
+
recordCheck(
|
|
248
|
+
checks,
|
|
249
|
+
'runtime.mergeShallowObject.spread_preserves_null',
|
|
250
|
+
mergedChatTemplate.enabled === null && mergedChatTemplate.type === 'base',
|
|
251
|
+
`type=${mergedChatTemplate.type}, enabled=${String(mergedChatTemplate.enabled)}`,
|
|
252
|
+
'actual'
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
const layeredAttention = mergeLayeredShallowObjects(
|
|
256
|
+
{ slidingWindow: 4096, attentionBias: false },
|
|
257
|
+
{ slidingWindow: 2048 },
|
|
258
|
+
{ slidingWindow: null }
|
|
259
|
+
);
|
|
260
|
+
recordCheck(
|
|
261
|
+
checks,
|
|
262
|
+
'loader.mergeLayeredShallowObjects.spread_preserves_null',
|
|
263
|
+
layeredAttention.slidingWindow === null && layeredAttention.attentionBias === false,
|
|
264
|
+
`slidingWindow=${String(layeredAttention.slidingWindow)}, attentionBias=${String(layeredAttention.attentionBias)}`,
|
|
265
|
+
'actual'
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
const mergedKernelPathPolicy = mergeKernelPathPolicy(
|
|
269
|
+
{
|
|
270
|
+
mode: 'locked',
|
|
271
|
+
sourceScope: ['model', 'manifest'],
|
|
272
|
+
allowSources: ['model', 'manifest'],
|
|
273
|
+
onIncompatible: 'error',
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
allowSources: ['runtime', 'execution-v0'],
|
|
277
|
+
onIncompatible: 'remap',
|
|
278
|
+
}
|
|
279
|
+
);
|
|
280
|
+
recordCheck(
|
|
281
|
+
checks,
|
|
282
|
+
'runtime.kernelPathPolicy.source_scope_mirrors_allow_sources',
|
|
283
|
+
Array.isArray(mergedKernelPathPolicy.sourceScope)
|
|
284
|
+
&& Array.isArray(mergedKernelPathPolicy.allowSources)
|
|
285
|
+
&& mergedKernelPathPolicy.sourceScope.length === 2
|
|
286
|
+
&& mergedKernelPathPolicy.sourceScope[0] === 'runtime'
|
|
287
|
+
&& mergedKernelPathPolicy.allowSources[1] === 'execution-v0'
|
|
288
|
+
&& mergedKernelPathPolicy.onIncompatible === 'remap',
|
|
289
|
+
`sourceScope=${JSON.stringify(mergedKernelPathPolicy.sourceScope)}, allowSources=${JSON.stringify(mergedKernelPathPolicy.allowSources)}`,
|
|
290
|
+
'actual'
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
const runtimeConfigWithKernelPathPolicy = createDopplerConfig({
|
|
294
|
+
runtime: {
|
|
295
|
+
inference: {
|
|
296
|
+
kernelPathPolicy: {
|
|
297
|
+
allowSources: ['runtime', 'execution-v0'],
|
|
298
|
+
},
|
|
299
|
+
},
|
|
300
|
+
},
|
|
301
|
+
});
|
|
302
|
+
recordCheck(
|
|
303
|
+
checks,
|
|
304
|
+
'runtime.schema.kernelPathPolicy.helper_is_used',
|
|
305
|
+
Array.isArray(runtimeConfigWithKernelPathPolicy.runtime.inference.kernelPathPolicy.sourceScope)
|
|
306
|
+
&& runtimeConfigWithKernelPathPolicy.runtime.inference.kernelPathPolicy.sourceScope[0] === 'runtime'
|
|
307
|
+
&& runtimeConfigWithKernelPathPolicy.runtime.inference.kernelPathPolicy.allowSources[1] === 'execution-v0',
|
|
308
|
+
`policy=${JSON.stringify(runtimeConfigWithKernelPathPolicy.runtime.inference.kernelPathPolicy)}`,
|
|
309
|
+
'actual'
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
const errors = checks.filter((entry) => !entry.ok).map((entry) => `[MergeContract] ${entry.id}: ${entry.detail}`);
|
|
313
|
+
|
|
314
|
+
return {
|
|
315
|
+
schemaVersion: 1,
|
|
316
|
+
source: 'doppler',
|
|
317
|
+
ok: errors.length === 0,
|
|
318
|
+
checks,
|
|
319
|
+
errors,
|
|
320
|
+
};
|
|
321
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export declare function chooseNullish<T>(
|
|
2
|
+
overrideValue: T | null | undefined,
|
|
3
|
+
fallbackValue: T
|
|
4
|
+
): T;
|
|
5
|
+
|
|
6
|
+
export declare function chooseDefined<T>(
|
|
7
|
+
overrideValue: T | undefined,
|
|
8
|
+
fallbackValue: T
|
|
9
|
+
): T;
|
|
10
|
+
|
|
11
|
+
export declare function chooseDefinedWithSource<T>(
|
|
12
|
+
path: string,
|
|
13
|
+
overrideValue: T | undefined,
|
|
14
|
+
fallbackValue: T,
|
|
15
|
+
sources: Map<string, string> | null | undefined
|
|
16
|
+
): T;
|
|
17
|
+
|
|
18
|
+
export declare function mergeShallowObject<T extends object>(
|
|
19
|
+
base: T,
|
|
20
|
+
override: Partial<T> | null | undefined
|
|
21
|
+
): T;
|
|
22
|
+
|
|
23
|
+
export declare function mergeLayeredShallowObjects<T extends object>(
|
|
24
|
+
...layers: Array<Partial<T> | null | undefined>
|
|
25
|
+
): T;
|
|
26
|
+
|
|
27
|
+
export declare function replaceSubtree<T>(
|
|
28
|
+
overrideValue: T | null | undefined,
|
|
29
|
+
fallbackValue: T
|
|
30
|
+
): T;
|
|
31
|
+
|
|
32
|
+
export declare function mergeKernelPathPolicy<T extends {
|
|
33
|
+
mode?: unknown;
|
|
34
|
+
sourceScope?: unknown;
|
|
35
|
+
allowSources?: unknown;
|
|
36
|
+
onIncompatible?: unknown;
|
|
37
|
+
}>(
|
|
38
|
+
basePolicy: T | null | undefined,
|
|
39
|
+
overridePolicy: T | null | undefined
|
|
40
|
+
): {
|
|
41
|
+
mode: unknown;
|
|
42
|
+
sourceScope: unknown;
|
|
43
|
+
allowSources: unknown;
|
|
44
|
+
onIncompatible: unknown;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export declare function mergeExecutionPatchLists<T extends {
|
|
48
|
+
set?: unknown;
|
|
49
|
+
remove?: unknown;
|
|
50
|
+
add?: unknown;
|
|
51
|
+
}>(
|
|
52
|
+
basePatch: T | null | undefined,
|
|
53
|
+
overridePatch: T | null | undefined
|
|
54
|
+
): {
|
|
55
|
+
set: unknown;
|
|
56
|
+
remove: unknown;
|
|
57
|
+
add: unknown;
|
|
58
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export function chooseNullish(overrideValue, fallbackValue) {
|
|
2
|
+
return overrideValue ?? fallbackValue;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function chooseDefined(overrideValue, fallbackValue) {
|
|
6
|
+
return overrideValue !== undefined ? overrideValue : fallbackValue;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function chooseDefinedWithSource(path, overrideValue, fallbackValue, sources) {
|
|
10
|
+
const value = chooseDefined(overrideValue, fallbackValue);
|
|
11
|
+
if (sources && typeof sources.set === 'function') {
|
|
12
|
+
sources.set(path, overrideValue !== undefined ? 'runtime' : 'manifest');
|
|
13
|
+
}
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function mergeShallowObject(base, override) {
|
|
18
|
+
if (!override || typeof override !== 'object' || Array.isArray(override)) {
|
|
19
|
+
return base;
|
|
20
|
+
}
|
|
21
|
+
return { ...base, ...override };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function mergeLayeredShallowObjects(...layers) {
|
|
25
|
+
return layers.reduce((merged, layer) => mergeShallowObject(merged, layer), {});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function replaceSubtree(overrideValue, fallbackValue) {
|
|
29
|
+
return chooseNullish(overrideValue, fallbackValue);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function mergeKernelPathPolicy(basePolicy, overridePolicy) {
|
|
33
|
+
const base = basePolicy ?? {};
|
|
34
|
+
const override = overridePolicy ?? {};
|
|
35
|
+
const baseSourceScope = base.sourceScope ?? base.allowSources;
|
|
36
|
+
const overrideSourceScope = override.sourceScope ?? override.allowSources;
|
|
37
|
+
const sourceScope = overrideSourceScope ?? baseSourceScope;
|
|
38
|
+
return {
|
|
39
|
+
mode: override.mode ?? base.mode,
|
|
40
|
+
sourceScope,
|
|
41
|
+
allowSources: sourceScope,
|
|
42
|
+
onIncompatible: override.onIncompatible ?? base.onIncompatible,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function mergeExecutionPatchLists(basePatch, overridePatch) {
|
|
47
|
+
const base = basePatch ?? {};
|
|
48
|
+
const override = overridePatch ?? {};
|
|
49
|
+
return {
|
|
50
|
+
set: chooseNullish(override.set, chooseNullish(base.set, [])),
|
|
51
|
+
remove: chooseNullish(override.remove, chooseNullish(base.remove, [])),
|
|
52
|
+
add: chooseNullish(override.add, chooseNullish(base.add, [])),
|
|
53
|
+
};
|
|
54
|
+
}
|
package/src/config/merge.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { chooseDefined, chooseDefinedWithSource } from './merge-helpers.js';
|
|
2
|
+
|
|
1
3
|
// =============================================================================
|
|
2
4
|
// Merge Implementation
|
|
3
5
|
// =============================================================================
|
|
@@ -8,12 +10,7 @@ function overlay(
|
|
|
8
10
|
runtimeValue,
|
|
9
11
|
sources
|
|
10
12
|
) {
|
|
11
|
-
|
|
12
|
-
sources.set(path, 'runtime');
|
|
13
|
-
return runtimeValue;
|
|
14
|
-
}
|
|
15
|
-
sources.set(path, 'manifest');
|
|
16
|
-
return manifestValue;
|
|
13
|
+
return chooseDefinedWithSource(path, runtimeValue, manifestValue, sources);
|
|
17
14
|
}
|
|
18
15
|
|
|
19
16
|
function mergeAttention(
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface QuantizationContractArtifact {
|
|
2
|
+
schemaVersion: 1;
|
|
3
|
+
source: 'doppler';
|
|
4
|
+
ok: boolean;
|
|
5
|
+
checks: Array<{ id: string; ok: boolean }>;
|
|
6
|
+
errors: string[];
|
|
7
|
+
stats: {
|
|
8
|
+
sampledSizes: number;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export declare function buildQuantizationContractArtifact(): QuantizationContractArtifact;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import {
|
|
2
|
+
K_SCALE_SIZE,
|
|
3
|
+
Q4K_BLOCK_BYTES,
|
|
4
|
+
Q6K_BLOCK_BYTES,
|
|
5
|
+
Q8_0_BLOCK_BYTES,
|
|
6
|
+
Q8_0_BLOCK_SIZE,
|
|
7
|
+
QK4_K_BLOCK_SIZE,
|
|
8
|
+
QK_K,
|
|
9
|
+
padToQ4KBlock,
|
|
10
|
+
q4kBlockCount,
|
|
11
|
+
} from './schema/quantization.schema.js';
|
|
12
|
+
import {
|
|
13
|
+
TILE_SIZES,
|
|
14
|
+
QUANTIZATION,
|
|
15
|
+
} from '../gpu/kernels/constants.js';
|
|
16
|
+
import * as loaderQuantization from '../loader/quantization-constants.js';
|
|
17
|
+
|
|
18
|
+
const EXPECTED_CONSTANTS = Object.freeze({
|
|
19
|
+
QK_K: 256,
|
|
20
|
+
Q4K_BLOCK_BYTES: 144,
|
|
21
|
+
Q6K_BLOCK_BYTES: 210,
|
|
22
|
+
Q8_0_BLOCK_BYTES: 34,
|
|
23
|
+
Q8_0_BLOCK_SIZE: 32,
|
|
24
|
+
K_SCALE_SIZE: 12,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export function buildQuantizationContractArtifact() {
|
|
28
|
+
const errors = [];
|
|
29
|
+
const checks = [];
|
|
30
|
+
|
|
31
|
+
const literalConstantsOk =
|
|
32
|
+
QK_K === EXPECTED_CONSTANTS.QK_K
|
|
33
|
+
&& Q4K_BLOCK_BYTES === EXPECTED_CONSTANTS.Q4K_BLOCK_BYTES
|
|
34
|
+
&& Q6K_BLOCK_BYTES === EXPECTED_CONSTANTS.Q6K_BLOCK_BYTES
|
|
35
|
+
&& Q8_0_BLOCK_BYTES === EXPECTED_CONSTANTS.Q8_0_BLOCK_BYTES
|
|
36
|
+
&& Q8_0_BLOCK_SIZE === EXPECTED_CONSTANTS.Q8_0_BLOCK_SIZE
|
|
37
|
+
&& K_SCALE_SIZE === EXPECTED_CONSTANTS.K_SCALE_SIZE
|
|
38
|
+
&& QK4_K_BLOCK_SIZE === Q4K_BLOCK_BYTES;
|
|
39
|
+
if (!literalConstantsOk) {
|
|
40
|
+
errors.push('[QuantizationContract] schema constants drifted from the expected Q4K/Q6K/Q8 values.');
|
|
41
|
+
}
|
|
42
|
+
checks.push({ id: 'quantization.constants.schema', ok: literalConstantsOk });
|
|
43
|
+
|
|
44
|
+
const crossModuleOk =
|
|
45
|
+
loaderQuantization.QK_K === QK_K
|
|
46
|
+
&& loaderQuantization.Q4K_BLOCK_BYTES === Q4K_BLOCK_BYTES
|
|
47
|
+
&& loaderQuantization.Q6K_BLOCK_BYTES === Q6K_BLOCK_BYTES
|
|
48
|
+
&& loaderQuantization.Q8_0_BLOCK_BYTES === Q8_0_BLOCK_BYTES
|
|
49
|
+
&& loaderQuantization.Q8_0_BLOCK_SIZE === Q8_0_BLOCK_SIZE
|
|
50
|
+
&& TILE_SIZES.Q4K_SUPER_BLOCK_SIZE === QK_K
|
|
51
|
+
&& QUANTIZATION.Q4K_BLOCK_BYTES === Q4K_BLOCK_BYTES;
|
|
52
|
+
if (!crossModuleOk) {
|
|
53
|
+
errors.push('[QuantizationContract] loader/GPU quantization constants drifted from schema constants.');
|
|
54
|
+
}
|
|
55
|
+
checks.push({ id: 'quantization.constants.crossModule', ok: crossModuleOk });
|
|
56
|
+
|
|
57
|
+
let padPropertiesOk = true;
|
|
58
|
+
let q4kCoverageOk = true;
|
|
59
|
+
let previous = -1;
|
|
60
|
+
for (let size = 0; size <= QK_K * 2 + 7; size += 1) {
|
|
61
|
+
const padded = padToQ4KBlock(size);
|
|
62
|
+
if (padded < size || padded % QK_K !== 0 || padToQ4KBlock(padded) !== padded || padded < previous) {
|
|
63
|
+
padPropertiesOk = false;
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
previous = padded;
|
|
67
|
+
if (q4kBlockCount(size) * QK_K < size) {
|
|
68
|
+
q4kCoverageOk = false;
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (!padPropertiesOk) {
|
|
73
|
+
errors.push('[QuantizationContract] padToQ4KBlock must be monotone, aligned, and idempotent.');
|
|
74
|
+
}
|
|
75
|
+
checks.push({ id: 'quantization.padToQ4KBlock.properties', ok: padPropertiesOk });
|
|
76
|
+
if (!q4kCoverageOk) {
|
|
77
|
+
errors.push('[QuantizationContract] q4kBlockCount must cover the requested element count.');
|
|
78
|
+
}
|
|
79
|
+
checks.push({ id: 'quantization.q4kBlockCount.coverage', ok: q4kCoverageOk });
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
schemaVersion: 1,
|
|
83
|
+
source: 'doppler',
|
|
84
|
+
ok: errors.length === 0,
|
|
85
|
+
checks,
|
|
86
|
+
errors,
|
|
87
|
+
stats: {
|
|
88
|
+
sampledSizes: QK_K * 2 + 8,
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface RequiredInferenceFieldsContractArtifact {
|
|
2
|
+
schemaVersion: 1;
|
|
3
|
+
source: 'doppler';
|
|
4
|
+
ok: boolean;
|
|
5
|
+
checks: Array<{ id: string; ok: boolean }>;
|
|
6
|
+
errors: string[];
|
|
7
|
+
stats: {
|
|
8
|
+
fieldCases: number;
|
|
9
|
+
nullableCases: number;
|
|
10
|
+
nonNullableCases: number;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export declare function buildRequiredInferenceFieldsContractArtifact(): RequiredInferenceFieldsContractArtifact;
|
|
15
|
+
|
|
16
|
+
export interface ManifestRequiredInferenceFieldsArtifact extends RequiredInferenceFieldsContractArtifact {
|
|
17
|
+
scope: 'manifest';
|
|
18
|
+
label: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export declare function buildManifestRequiredInferenceFieldsArtifact(
|
|
22
|
+
inference: Record<string, unknown> | null | undefined,
|
|
23
|
+
label?: string
|
|
24
|
+
): ManifestRequiredInferenceFieldsArtifact;
|