@tensor-cad/engine 0.1.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/README.md +80 -0
- package/catalog.d.ts +35 -0
- package/format.d.ts +18 -0
- package/index.d.ts +154 -0
- package/index.js +249 -0
- package/ir.d.ts +23 -0
- package/node.d.ts +53 -0
- package/node.js +1487 -0
- package/package.json +28 -0
- package/tensorcad.wasm +0 -0
- package/types.d.ts +782 -0
- package/wasm_exec.js +575 -0
package/types.d.ts
ADDED
|
@@ -0,0 +1,782 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the engine's JSON means.
|
|
3
|
+
*
|
|
4
|
+
* These are a description of the wire, not a second model of the domain: each
|
|
5
|
+
* one names a shape the Go engine marshals, and nothing here computes. The Go
|
|
6
|
+
* side is where a field's meaning is decided; this is how TypeScript reads it.
|
|
7
|
+
*/
|
|
8
|
+
export declare const DOC_VERSION = 1;
|
|
9
|
+
/** Symbols that stay indeterminate through shape checking. */
|
|
10
|
+
export declare const RUNTIME_SYMBOLS: readonly ["B", "T"];
|
|
11
|
+
/** The generated entry and exit nodes of a container's subgraph. */
|
|
12
|
+
export declare const BOUNDARY_IN = "_in";
|
|
13
|
+
export declare const BOUNDARY_OUT = "_out";
|
|
14
|
+
/** A parameter as the document writes it: a number, a flag, or an expression. */
|
|
15
|
+
export type ParamValue = number | string | boolean | null | ParamObject | ParamValue[];
|
|
16
|
+
export interface ParamObject {
|
|
17
|
+
[key: string]: ParamValue;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A symbol, in any of the four spellings a document uses: a bare number, a bare
|
|
21
|
+
* expression, or an object tagged "runtime" or "design".
|
|
22
|
+
*/
|
|
23
|
+
export type SymbolDef = number | string | {
|
|
24
|
+
kind: "runtime";
|
|
25
|
+
default?: number;
|
|
26
|
+
doc?: string;
|
|
27
|
+
} | {
|
|
28
|
+
kind: "design";
|
|
29
|
+
value: number | string;
|
|
30
|
+
doc?: string;
|
|
31
|
+
};
|
|
32
|
+
/** One block in a graph. */
|
|
33
|
+
export interface NodeDef {
|
|
34
|
+
id: string;
|
|
35
|
+
type: string;
|
|
36
|
+
params?: Record<string, ParamValue>;
|
|
37
|
+
/** The subgraph of a container such as `repeat`. */
|
|
38
|
+
graph?: Graph;
|
|
39
|
+
/** Named subgraph alternatives, for hybrid repeat patterns. */
|
|
40
|
+
variants?: Record<string, Graph>;
|
|
41
|
+
/** Free text shown on the canvas instead of the id. */
|
|
42
|
+
label?: string;
|
|
43
|
+
}
|
|
44
|
+
/** An edge, `"nodeId:portName"` on both ends. */
|
|
45
|
+
export type Edge = [from: string, to: string];
|
|
46
|
+
export interface Graph {
|
|
47
|
+
nodes: NodeDef[];
|
|
48
|
+
edges: Edge[];
|
|
49
|
+
}
|
|
50
|
+
/** The reference numbers a preset is checked against. */
|
|
51
|
+
export interface Published {
|
|
52
|
+
params?: number;
|
|
53
|
+
activeParams?: number;
|
|
54
|
+
kvBytesPerToken?: number;
|
|
55
|
+
source?: string;
|
|
56
|
+
/**
|
|
57
|
+
* Allowed relative difference, defaulting to 0.5%. Set wider only where the
|
|
58
|
+
* published figure is itself a rounded headline number.
|
|
59
|
+
*/
|
|
60
|
+
tolerance?: number;
|
|
61
|
+
}
|
|
62
|
+
export interface DocMeta {
|
|
63
|
+
name: string;
|
|
64
|
+
family?: string;
|
|
65
|
+
notes?: string;
|
|
66
|
+
published?: Published;
|
|
67
|
+
}
|
|
68
|
+
/** The editor's view of a document, carried along with it. */
|
|
69
|
+
export interface UiState {
|
|
70
|
+
positions?: Record<string, [number, number]>;
|
|
71
|
+
collapsed?: string[];
|
|
72
|
+
}
|
|
73
|
+
/** A design. */
|
|
74
|
+
/** One named set of symbol values. */
|
|
75
|
+
export interface Configuration {
|
|
76
|
+
doc?: string;
|
|
77
|
+
/**
|
|
78
|
+
* Overrides the document's own symbols, by name. A symbol it does not
|
|
79
|
+
* mention keeps whatever the design says, so an expression over one that is
|
|
80
|
+
* overridden follows it.
|
|
81
|
+
*/
|
|
82
|
+
symbols: Record<string, SymbolDef>;
|
|
83
|
+
}
|
|
84
|
+
export interface Doc {
|
|
85
|
+
version: number;
|
|
86
|
+
meta: DocMeta;
|
|
87
|
+
symbols: Record<string, SymbolDef>;
|
|
88
|
+
graph: Graph;
|
|
89
|
+
/**
|
|
90
|
+
* What this design has decided the design rules mean to it, keyed by rule id.
|
|
91
|
+
*
|
|
92
|
+
* A rule that is right in general is sometimes wrong here, and the
|
|
93
|
+
* alternative to recording that is people learning to read past a warning.
|
|
94
|
+
* It lives in the document because it is a decision about the design, so it
|
|
95
|
+
* travels with the file and shows up in review. Suppression is never silent:
|
|
96
|
+
* `ValidationReport.overridden` says what it did.
|
|
97
|
+
*/
|
|
98
|
+
rules?: Record<string, RuleSeverity>;
|
|
99
|
+
/**
|
|
100
|
+
* Named sets of symbol values this design can be built at.
|
|
101
|
+
*
|
|
102
|
+
* Four GPT-2 presets are the same architecture at four sizes, and holding
|
|
103
|
+
* them apart means an architectural change has to be made four times. A
|
|
104
|
+
* configuration overrides symbols and nothing else: a variant that changed
|
|
105
|
+
* the graph would be a different design.
|
|
106
|
+
*/
|
|
107
|
+
configurations?: Record<string, Configuration>;
|
|
108
|
+
/**
|
|
109
|
+
* The configuration in force. Absent or unknown means the symbols as
|
|
110
|
+
* written, which is what a design without configurations always has.
|
|
111
|
+
*
|
|
112
|
+
* In the document rather than in the editor, because it changes what the
|
|
113
|
+
* design *is*. The operating point is editor state for the opposite reason:
|
|
114
|
+
* it only changes what the design is measured under.
|
|
115
|
+
*/
|
|
116
|
+
active?: string;
|
|
117
|
+
/** Blocks this design defines for itself, keyed by type name. */
|
|
118
|
+
defs?: Record<string, UserBlockDef>;
|
|
119
|
+
ui?: UiState;
|
|
120
|
+
}
|
|
121
|
+
/** What a document may ask a rule to be. `off` drops its findings. */
|
|
122
|
+
export type RuleSeverity = Severity | "off";
|
|
123
|
+
/** A composite a design defines for itself, written as data. */
|
|
124
|
+
export interface UserBlockDef {
|
|
125
|
+
type?: string;
|
|
126
|
+
category?: string;
|
|
127
|
+
params?: Record<string, ParamSpec>;
|
|
128
|
+
ports: {
|
|
129
|
+
in: Record<string, string | PortSpec>;
|
|
130
|
+
out: Record<string, string | PortSpec>;
|
|
131
|
+
};
|
|
132
|
+
graph: Graph;
|
|
133
|
+
docs?: BlockDocs;
|
|
134
|
+
}
|
|
135
|
+
export type ParamKind = "int" | "num" | "bool" | "enum" | "str" | "pattern" | "obj";
|
|
136
|
+
/** One declared parameter of a block. */
|
|
137
|
+
export interface ParamSpec {
|
|
138
|
+
type: ParamKind;
|
|
139
|
+
default?: ParamValue;
|
|
140
|
+
min?: number;
|
|
141
|
+
max?: number;
|
|
142
|
+
/** The permitted strings of an enum. */
|
|
143
|
+
values?: string[];
|
|
144
|
+
doc?: string;
|
|
145
|
+
/**
|
|
146
|
+
* The heading this field belongs under, for a block with enough parameters
|
|
147
|
+
* that one list is unreadable. Absent puts it with the rest.
|
|
148
|
+
*/
|
|
149
|
+
group?: string;
|
|
150
|
+
/**
|
|
151
|
+
* The condition under which this parameter means anything.
|
|
152
|
+
*
|
|
153
|
+
* A dense block has no `expert_hidden`, grouped-query attention has no
|
|
154
|
+
* `kv_lora`, an RMSNorm has no bias. The block carries a value either way —
|
|
155
|
+
* this is what lets a panel say so rather than showing them all alike.
|
|
156
|
+
*/
|
|
157
|
+
when?: ParamWhen;
|
|
158
|
+
}
|
|
159
|
+
/** One parameter's value deciding whether another is meaningful. */
|
|
160
|
+
export interface ParamWhen {
|
|
161
|
+
/** The other parameter to look at. */
|
|
162
|
+
param: string;
|
|
163
|
+
/** The values of it under which this parameter is meaningful. */
|
|
164
|
+
is: string[];
|
|
165
|
+
}
|
|
166
|
+
/** What a pin declares. See docs/reference/ports.md. */
|
|
167
|
+
export interface PortSpec {
|
|
168
|
+
shape: string;
|
|
169
|
+
/** What the tensor carries; "inherit" takes it from the producer. */
|
|
170
|
+
dtype?: string;
|
|
171
|
+
/** A port that may legitimately dangle. */
|
|
172
|
+
optional?: boolean;
|
|
173
|
+
/** "flow" or "side": which edge of the symbol a wire leaves by. */
|
|
174
|
+
anchor?: "flow" | "side";
|
|
175
|
+
showName?: boolean;
|
|
176
|
+
doc?: string;
|
|
177
|
+
}
|
|
178
|
+
export interface BlockDocs {
|
|
179
|
+
summary?: string;
|
|
180
|
+
formula?: string;
|
|
181
|
+
refs?: string[];
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* One block, as the palette and the inspector need it.
|
|
185
|
+
*
|
|
186
|
+
* Parameters by name with the order beside them: a panel looks one up far more
|
|
187
|
+
* often than it walks them all, and a Go map has no order to inherit.
|
|
188
|
+
*/
|
|
189
|
+
export interface CatalogEntry {
|
|
190
|
+
type: string;
|
|
191
|
+
kind: "primitive" | "composite" | "container";
|
|
192
|
+
category: string;
|
|
193
|
+
docs: BlockDocs;
|
|
194
|
+
params: Record<string, ParamSpec>;
|
|
195
|
+
/** The order the block declares them in, which is how they are laid out. */
|
|
196
|
+
paramOrder: string[];
|
|
197
|
+
/**
|
|
198
|
+
* The pins declared before any parameter is known. A block whose pins depend
|
|
199
|
+
* on its parameters reports none here; ask the analysis for those.
|
|
200
|
+
*/
|
|
201
|
+
ports: {
|
|
202
|
+
in: Record<string, string>;
|
|
203
|
+
out: Record<string, string>;
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
export type Dtype = "fp32" | "bf16" | "fp16" | "fp8";
|
|
207
|
+
export type OptimizerKind = "adamw" | "adamw8bit" | "muon" | "sgd_momentum" | "sgd" | "bf16_adam";
|
|
208
|
+
export type Recompute = "none" | "selective" | "full";
|
|
209
|
+
/** How the model is spread over the devices. */
|
|
210
|
+
export interface ParallelPlan {
|
|
211
|
+
dp: number;
|
|
212
|
+
tp: number;
|
|
213
|
+
pp: number;
|
|
214
|
+
ep: number;
|
|
215
|
+
/** ZeRO/FSDP stage, 0 to 3. */
|
|
216
|
+
zero: 0 | 1 | 2 | 3;
|
|
217
|
+
/** Shard activations along the sequence across the tensor-parallel group. */
|
|
218
|
+
sequenceParallel: boolean;
|
|
219
|
+
}
|
|
220
|
+
export declare const DEFAULT_PARALLEL: ParallelPlan;
|
|
221
|
+
export declare const DEFAULT_HARDWARE = "h100-sxm";
|
|
222
|
+
export declare const DTYPE_BYTES: Record<Dtype, number>;
|
|
223
|
+
/**
|
|
224
|
+
* The conditions a design is measured under.
|
|
225
|
+
*
|
|
226
|
+
* Not properties of the design: batch, sequence length, dtype, device and
|
|
227
|
+
* sharding belong to the question, not to the model.
|
|
228
|
+
*/
|
|
229
|
+
export interface AnalysisOptions {
|
|
230
|
+
T?: number;
|
|
231
|
+
B?: number;
|
|
232
|
+
dtype?: Dtype;
|
|
233
|
+
inferenceDtype?: Dtype;
|
|
234
|
+
kvDtype?: Dtype;
|
|
235
|
+
/** A profile id from `hardware()`. */
|
|
236
|
+
hardware?: string;
|
|
237
|
+
gpus?: number;
|
|
238
|
+
parallel?: Partial<ParallelPlan>;
|
|
239
|
+
optimizer?: OptimizerKind;
|
|
240
|
+
recompute?: Recompute;
|
|
241
|
+
/** Assume a memory-efficient attention kernel. */
|
|
242
|
+
flash?: boolean;
|
|
243
|
+
tokens?: number;
|
|
244
|
+
mfu?: number;
|
|
245
|
+
decodeEfficiency?: number;
|
|
246
|
+
concurrency?: number;
|
|
247
|
+
}
|
|
248
|
+
export interface HardwareProfile {
|
|
249
|
+
id: string;
|
|
250
|
+
name: string;
|
|
251
|
+
peakBf16: number;
|
|
252
|
+
peakFp8: number;
|
|
253
|
+
memory: number;
|
|
254
|
+
bandwidth: number;
|
|
255
|
+
pricePerHour: number;
|
|
256
|
+
mfuHint: [low: number, high: number];
|
|
257
|
+
notes?: string;
|
|
258
|
+
}
|
|
259
|
+
export interface SymbolTable {
|
|
260
|
+
order: string[];
|
|
261
|
+
values: Record<string, number>;
|
|
262
|
+
/** Concrete design symbols only; runtime symbols excluded. */
|
|
263
|
+
designValues: Record<string, number>;
|
|
264
|
+
docs: Record<string, string>;
|
|
265
|
+
errors: string[];
|
|
266
|
+
}
|
|
267
|
+
export interface ParamsResult {
|
|
268
|
+
total: number;
|
|
269
|
+
/** Weights a single token uses. Differs from total only for a mixture. */
|
|
270
|
+
active: number;
|
|
271
|
+
embedding: number;
|
|
272
|
+
head: number;
|
|
273
|
+
nonEmbedding: number;
|
|
274
|
+
/** The N in the 2N rule. */
|
|
275
|
+
nonEmbeddingActive: number;
|
|
276
|
+
byPath: Record<string, number>;
|
|
277
|
+
byCategory: Record<string, number>;
|
|
278
|
+
byType: Record<string, number>;
|
|
279
|
+
errors: string[];
|
|
280
|
+
}
|
|
281
|
+
export interface FlopsResult {
|
|
282
|
+
fwdDense: number;
|
|
283
|
+
fwdAttention: number;
|
|
284
|
+
/** The attention term as a profiler counts it, with nothing masked. */
|
|
285
|
+
fwdAttentionUnmasked: number;
|
|
286
|
+
fwdTotal: number;
|
|
287
|
+
fwdTotalUnmasked: number;
|
|
288
|
+
/** Norms, activations, RoPE and adds: memory-bound, excluded above. */
|
|
289
|
+
elementwise: number;
|
|
290
|
+
trainPerToken: number;
|
|
291
|
+
attentionShare: number;
|
|
292
|
+
ruleOfThumb2N: number;
|
|
293
|
+
ruleOfThumb6N: number;
|
|
294
|
+
byPath: Record<string, number>;
|
|
295
|
+
byCategory: Record<string, number>;
|
|
296
|
+
errors: string[];
|
|
297
|
+
}
|
|
298
|
+
export interface KvResult {
|
|
299
|
+
bytesPerToken: number;
|
|
300
|
+
bytesPerSequenceFixed: number;
|
|
301
|
+
/**
|
|
302
|
+
* The same cache under an engine that does not absorb the weights latent
|
|
303
|
+
* attention compressed against. Equal to `bytesPerToken` for every design
|
|
304
|
+
* that has no latent attention in it; 57x it for DeepSeek-V3.
|
|
305
|
+
*/
|
|
306
|
+
bytesPerTokenDecompressed: number;
|
|
307
|
+
byPath: Record<string, number>;
|
|
308
|
+
errors: string[];
|
|
309
|
+
}
|
|
310
|
+
export interface MemoryResult {
|
|
311
|
+
weightsBytes: number;
|
|
312
|
+
train: {
|
|
313
|
+
weights: number;
|
|
314
|
+
grads: number;
|
|
315
|
+
optimizer: number;
|
|
316
|
+
activations: number;
|
|
317
|
+
/** The part of `activations` that is the vocabulary logits. */
|
|
318
|
+
logits: number;
|
|
319
|
+
total: number;
|
|
320
|
+
perGpu: TrainPerGpu;
|
|
321
|
+
activationsByPath: Record<string, number>;
|
|
322
|
+
/**
|
|
323
|
+
* The same bytes charged to the tensor rather than to the block that
|
|
324
|
+
* produced it, keyed `"path:port"`.
|
|
325
|
+
*
|
|
326
|
+
* Not a reformatting of the line above. They agree row for row in a plain
|
|
327
|
+
* transformer, where every block that holds an activation holds exactly
|
|
328
|
+
* one; they diverge wherever a block fans out. Nemotron-H's `split` holds
|
|
329
|
+
* three tensors from 2 MiB to 167 MiB, and one number for the block
|
|
330
|
+
* answers neither which of them is the big one nor what dropping one would
|
|
331
|
+
* save.
|
|
332
|
+
*/
|
|
333
|
+
activationsByTensor: Record<string, number>;
|
|
334
|
+
};
|
|
335
|
+
infer: {
|
|
336
|
+
weights: number;
|
|
337
|
+
kv: number;
|
|
338
|
+
overhead: number;
|
|
339
|
+
total: number;
|
|
340
|
+
};
|
|
341
|
+
optimizerLabel: string;
|
|
342
|
+
notes: string[];
|
|
343
|
+
errors: string[];
|
|
344
|
+
}
|
|
345
|
+
export interface ThroughputResult {
|
|
346
|
+
/** FLOP per byte above which the device is compute-bound. */
|
|
347
|
+
ridgePoint: number;
|
|
348
|
+
decodeBytesPerStep: number;
|
|
349
|
+
/**
|
|
350
|
+
* The weights of that, which for a mixture of experts is neither the active
|
|
351
|
+
* count nor the resident one: a batch reads the union of what its tokens
|
|
352
|
+
* routed to, and that reaches nearly every expert well before the batch
|
|
353
|
+
* reaches the expert count.
|
|
354
|
+
*/
|
|
355
|
+
decodeWeightBytes: number;
|
|
356
|
+
/** Every weight the device holds, whether or not a given step reads it. */
|
|
357
|
+
residentWeightBytes: number;
|
|
358
|
+
decodeFlopsPerStep: number;
|
|
359
|
+
decodeSecondsPerStep: number;
|
|
360
|
+
decodeTokensPerSecond: number;
|
|
361
|
+
memoryBound: boolean;
|
|
362
|
+
prefillSeconds: number;
|
|
363
|
+
notes: string[];
|
|
364
|
+
}
|
|
365
|
+
export interface CostResult {
|
|
366
|
+
totalFlops: number;
|
|
367
|
+
gpuHours: number;
|
|
368
|
+
wallClockHours: number;
|
|
369
|
+
dollars: number;
|
|
370
|
+
tokens: number;
|
|
371
|
+
mfu: number;
|
|
372
|
+
}
|
|
373
|
+
export interface ChinchillaResult {
|
|
374
|
+
optimalTokens: number;
|
|
375
|
+
tokensPerParam: number;
|
|
376
|
+
/** The meaningful ratio for a sparse model. */
|
|
377
|
+
tokensPerActiveParam: number;
|
|
378
|
+
overTrainingRatio: number;
|
|
379
|
+
predictedLoss: Record<string, number>;
|
|
380
|
+
verdict: string;
|
|
381
|
+
}
|
|
382
|
+
/** The operating point with every default filled in. */
|
|
383
|
+
export interface ResolvedAnalysisOptions {
|
|
384
|
+
T: number;
|
|
385
|
+
B: number;
|
|
386
|
+
dtype: Dtype;
|
|
387
|
+
inferenceDtype: Dtype;
|
|
388
|
+
kvDtype: Dtype;
|
|
389
|
+
hardware: HardwareProfile;
|
|
390
|
+
gpus: number;
|
|
391
|
+
parallel: ParallelPlan;
|
|
392
|
+
optimizer: OptimizerKind;
|
|
393
|
+
recompute: Recompute;
|
|
394
|
+
flash: boolean;
|
|
395
|
+
tokens: number;
|
|
396
|
+
tokensWereDefaulted: boolean;
|
|
397
|
+
mfu: number;
|
|
398
|
+
decodeEfficiency: number;
|
|
399
|
+
concurrency: number;
|
|
400
|
+
}
|
|
401
|
+
export interface AnalysisResult {
|
|
402
|
+
name: string;
|
|
403
|
+
options: ResolvedAnalysisOptions;
|
|
404
|
+
symbols: SymbolTable;
|
|
405
|
+
params: ParamsResult;
|
|
406
|
+
flops: FlopsResult;
|
|
407
|
+
kv: KvResult;
|
|
408
|
+
memory: MemoryResult;
|
|
409
|
+
throughput: ThroughputResult;
|
|
410
|
+
cost: CostResult;
|
|
411
|
+
chinchilla: ChinchillaResult;
|
|
412
|
+
errors: string[];
|
|
413
|
+
}
|
|
414
|
+
export type Severity = "error" | "warning" | "info";
|
|
415
|
+
export interface Finding {
|
|
416
|
+
/** Stable rule identifier, e.g. "flash-head-dim". */
|
|
417
|
+
rule: string;
|
|
418
|
+
severity: Severity;
|
|
419
|
+
path?: string;
|
|
420
|
+
port?: string;
|
|
421
|
+
/** The parameter that caused it, so the inspector can point at the field. */
|
|
422
|
+
param?: string;
|
|
423
|
+
message: string;
|
|
424
|
+
hint?: string;
|
|
425
|
+
}
|
|
426
|
+
export interface ValidationReport {
|
|
427
|
+
name: string;
|
|
428
|
+
findings: Finding[];
|
|
429
|
+
counts: Record<Severity, number>;
|
|
430
|
+
/** True when nothing blocks building this design. */
|
|
431
|
+
ok: boolean;
|
|
432
|
+
analysis: AnalysisResult;
|
|
433
|
+
/**
|
|
434
|
+
* What the document's own severities did, so suppression is never silent: a
|
|
435
|
+
* design cannot drop a finding without the report saying which and from what.
|
|
436
|
+
*/
|
|
437
|
+
overridden: RuleOverride[];
|
|
438
|
+
}
|
|
439
|
+
/** One finding whose severity the document changed. */
|
|
440
|
+
export interface RuleOverride {
|
|
441
|
+
rule: string;
|
|
442
|
+
path?: string;
|
|
443
|
+
/** What the rule produced, and what the document asked for. */
|
|
444
|
+
from: Severity;
|
|
445
|
+
/** `off` means the finding was dropped. An unreadable value arrives as `?x`. */
|
|
446
|
+
to: string;
|
|
447
|
+
}
|
|
448
|
+
export interface ExplainedParam {
|
|
449
|
+
/** The expression as written, when it was an expression. */
|
|
450
|
+
expression?: string;
|
|
451
|
+
value: unknown;
|
|
452
|
+
doc?: string;
|
|
453
|
+
}
|
|
454
|
+
export interface Explanation {
|
|
455
|
+
path: string;
|
|
456
|
+
type: string;
|
|
457
|
+
kind: "primitive" | "composite" | "container";
|
|
458
|
+
label?: string;
|
|
459
|
+
docs: BlockDocs;
|
|
460
|
+
/** How many copies exist, and how many a token passes through. */
|
|
461
|
+
copies: {
|
|
462
|
+
total: number;
|
|
463
|
+
active: number;
|
|
464
|
+
};
|
|
465
|
+
params: Record<string, ExplainedParam>;
|
|
466
|
+
/** The order the block declares its parameters in. */
|
|
467
|
+
paramOrder: string[];
|
|
468
|
+
shapes: {
|
|
469
|
+
in: Record<string, string>;
|
|
470
|
+
out: Record<string, string>;
|
|
471
|
+
};
|
|
472
|
+
contributes: {
|
|
473
|
+
params: number;
|
|
474
|
+
activeParams: number;
|
|
475
|
+
shareOfParams: number;
|
|
476
|
+
flopsPerToken: number;
|
|
477
|
+
shareOfFlops: number;
|
|
478
|
+
activationBytes: number;
|
|
479
|
+
cacheBytesPerToken: number;
|
|
480
|
+
cacheBytesPerSequence: number;
|
|
481
|
+
};
|
|
482
|
+
/** The primitives this block expands into, largest first. */
|
|
483
|
+
breakdown: {
|
|
484
|
+
path: string;
|
|
485
|
+
type: string;
|
|
486
|
+
params: number;
|
|
487
|
+
}[];
|
|
488
|
+
notFound?: boolean;
|
|
489
|
+
}
|
|
490
|
+
export interface TorchOptions {
|
|
491
|
+
className?: string;
|
|
492
|
+
includeSmokeTest?: boolean;
|
|
493
|
+
/**
|
|
494
|
+
* How a mixture-of-experts layer routes. "sparse" is faster but cannot be
|
|
495
|
+
* traced by `torch.export`; "dense" computes the same thing at
|
|
496
|
+
* `experts / top_k` times the cost and traces cleanly.
|
|
497
|
+
*/
|
|
498
|
+
moeDispatch?: "sparse" | "dense";
|
|
499
|
+
/** 0 leaves PyTorch's own initialization alone. */
|
|
500
|
+
initStd?: number;
|
|
501
|
+
}
|
|
502
|
+
export interface GeneratedFile {
|
|
503
|
+
path: string;
|
|
504
|
+
contents: string;
|
|
505
|
+
}
|
|
506
|
+
export interface GeneratedCode {
|
|
507
|
+
files: GeneratedFile[];
|
|
508
|
+
warnings: string[];
|
|
509
|
+
}
|
|
510
|
+
export interface ScaleOptions {
|
|
511
|
+
targetParams: number;
|
|
512
|
+
widthSymbols?: string[];
|
|
513
|
+
depthSymbols?: string[];
|
|
514
|
+
widthMultiple?: number;
|
|
515
|
+
vocab?: number;
|
|
516
|
+
/** Whether `targetParams` counts the embedding tables. */
|
|
517
|
+
targetBasis?: "total" | "non-embedding";
|
|
518
|
+
tieHead?: boolean;
|
|
519
|
+
minHeads?: number;
|
|
520
|
+
keepDepth?: boolean;
|
|
521
|
+
maxIterations?: number;
|
|
522
|
+
}
|
|
523
|
+
/** The training footprint on one device. */
|
|
524
|
+
export interface TrainPerGpu {
|
|
525
|
+
weights: number;
|
|
526
|
+
grads: number;
|
|
527
|
+
optimizer: number;
|
|
528
|
+
activations: number;
|
|
529
|
+
total: number;
|
|
530
|
+
}
|
|
531
|
+
/** One named value that moved between two designs. */
|
|
532
|
+
export interface DiffChange {
|
|
533
|
+
name: string;
|
|
534
|
+
from?: unknown;
|
|
535
|
+
to?: unknown;
|
|
536
|
+
}
|
|
537
|
+
/** A block as it stands in one of the two designs. */
|
|
538
|
+
export interface DiffBlock {
|
|
539
|
+
path: string;
|
|
540
|
+
type: string;
|
|
541
|
+
label?: string;
|
|
542
|
+
params: Record<string, ParamValue>;
|
|
543
|
+
}
|
|
544
|
+
/** One parameter that moved on a block that exists in both. */
|
|
545
|
+
export interface DiffParamChange {
|
|
546
|
+
key: string;
|
|
547
|
+
from?: ParamValue;
|
|
548
|
+
to?: ParamValue;
|
|
549
|
+
}
|
|
550
|
+
export interface DiffBlockChange {
|
|
551
|
+
path: string;
|
|
552
|
+
/** Set when the block became a different kind of block. */
|
|
553
|
+
type?: DiffChange;
|
|
554
|
+
label?: DiffChange;
|
|
555
|
+
params: DiffParamChange[];
|
|
556
|
+
}
|
|
557
|
+
export interface DiffEdge {
|
|
558
|
+
/** The graph the wire sits in; `<root>` is the top level. */
|
|
559
|
+
graph: string;
|
|
560
|
+
from: string;
|
|
561
|
+
to: string;
|
|
562
|
+
}
|
|
563
|
+
/** One number that moved. */
|
|
564
|
+
export interface DiffDelta {
|
|
565
|
+
metric: string;
|
|
566
|
+
a: number;
|
|
567
|
+
b: number;
|
|
568
|
+
delta: number;
|
|
569
|
+
/** Null when `a` is zero, because the ratio says nothing then. */
|
|
570
|
+
ratio: number | null;
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* What changed between two designs.
|
|
574
|
+
*
|
|
575
|
+
* Structure and numbers together, because either alone is misleading: that `F`
|
|
576
|
+
* went from 11008 to 14336 does not tell you the model grew by 1.3B
|
|
577
|
+
* parameters, and that it grew by 1.3B does not tell you where.
|
|
578
|
+
*/
|
|
579
|
+
export interface DesignDiff {
|
|
580
|
+
a: string;
|
|
581
|
+
b: string;
|
|
582
|
+
symbols: {
|
|
583
|
+
added: DiffChange[];
|
|
584
|
+
removed: DiffChange[];
|
|
585
|
+
changed: DiffChange[];
|
|
586
|
+
};
|
|
587
|
+
blocks: {
|
|
588
|
+
added: DiffBlock[];
|
|
589
|
+
removed: DiffBlock[];
|
|
590
|
+
changed: DiffBlockChange[];
|
|
591
|
+
};
|
|
592
|
+
edges: {
|
|
593
|
+
added: DiffEdge[];
|
|
594
|
+
removed: DiffEdge[];
|
|
595
|
+
};
|
|
596
|
+
metrics: DiffDelta[];
|
|
597
|
+
/** The operating point both sides were measured under. */
|
|
598
|
+
at: {
|
|
599
|
+
T: number;
|
|
600
|
+
B: number;
|
|
601
|
+
hardware: string;
|
|
602
|
+
};
|
|
603
|
+
/**
|
|
604
|
+
* True when nothing structural moved. The numbers may still differ, because
|
|
605
|
+
* they are measured at an operating point.
|
|
606
|
+
*/
|
|
607
|
+
identical: boolean;
|
|
608
|
+
}
|
|
609
|
+
/** The cluster a design is being fitted to. */
|
|
610
|
+
export interface ClusterRequest {
|
|
611
|
+
/** How many devices there are. */
|
|
612
|
+
gpus: number;
|
|
613
|
+
/**
|
|
614
|
+
* Bounds the tensor-parallel degree: splitting a matrix across a slower link
|
|
615
|
+
* than NVLink is rarely worth it. Defaults to 8.
|
|
616
|
+
*/
|
|
617
|
+
gpusPerNode?: number;
|
|
618
|
+
/**
|
|
619
|
+
* The fraction of device memory left free for fragmentation, the allocator
|
|
620
|
+
* and the communication buffers. Defaults to 0.1.
|
|
621
|
+
*/
|
|
622
|
+
headroom?: number;
|
|
623
|
+
/** Micro-batch sizes to try. Defaults to the one the analysis options give. */
|
|
624
|
+
microBatch?: number[];
|
|
625
|
+
/** Recompute settings to try. Defaults to all three. */
|
|
626
|
+
recompute?: Recompute[];
|
|
627
|
+
/** How many plans to return. Defaults to 8. */
|
|
628
|
+
limit?: number;
|
|
629
|
+
}
|
|
630
|
+
/** One way of splitting the work, and what it costs to hold. */
|
|
631
|
+
export interface ClusterPlan {
|
|
632
|
+
parallel: ParallelPlan;
|
|
633
|
+
recompute: Recompute;
|
|
634
|
+
microBatch: number;
|
|
635
|
+
perGpu: TrainPerGpu;
|
|
636
|
+
/** The fraction of the budget this plan takes; over 1 does not fit. */
|
|
637
|
+
used: number;
|
|
638
|
+
/** The plan as a person would say it: "DP 8 x TP 2, ZeRO-1". */
|
|
639
|
+
summary: string;
|
|
640
|
+
/** What this plan asks of whoever runs it. */
|
|
641
|
+
notes: string[];
|
|
642
|
+
}
|
|
643
|
+
/** Every plan that fits, least demanding first. */
|
|
644
|
+
export interface ClusterResult {
|
|
645
|
+
fits: ClusterPlan[];
|
|
646
|
+
/** The nearest miss, when nothing fits. */
|
|
647
|
+
closest?: ClusterPlan;
|
|
648
|
+
/** How many combinations were priced. */
|
|
649
|
+
considered: number;
|
|
650
|
+
/** Bytes each device may use, after headroom. */
|
|
651
|
+
budget: number;
|
|
652
|
+
/** The device's own memory, before headroom. */
|
|
653
|
+
memory: number;
|
|
654
|
+
hardware: string;
|
|
655
|
+
notes: string[];
|
|
656
|
+
}
|
|
657
|
+
export interface ScaleResult {
|
|
658
|
+
doc: Doc;
|
|
659
|
+
achieved: number;
|
|
660
|
+
target: number;
|
|
661
|
+
changes: Record<string, {
|
|
662
|
+
from: number;
|
|
663
|
+
to: number;
|
|
664
|
+
}>;
|
|
665
|
+
notes: string[];
|
|
666
|
+
}
|
|
667
|
+
/** Which row of Tensor Programs V's Table 3 a weight belongs to. */
|
|
668
|
+
export type MupClass = "input" | "hidden" | "output";
|
|
669
|
+
/** What to multiply one class's settings by, against the base rung. */
|
|
670
|
+
export interface MupScaling {
|
|
671
|
+
class: MupClass;
|
|
672
|
+
/** Multiplies the base model's initialization standard deviation. */
|
|
673
|
+
initStd: number;
|
|
674
|
+
/** Multiplies the base model's learning rate. */
|
|
675
|
+
adamLr: number;
|
|
676
|
+
/** The blocks in this class, so the grouping can be checked against the design. */
|
|
677
|
+
paths: string[];
|
|
678
|
+
why: string;
|
|
679
|
+
}
|
|
680
|
+
/** One model in the ladder. */
|
|
681
|
+
export interface MupRung {
|
|
682
|
+
/** What the width came out as: a width is held to a whole number of heads. */
|
|
683
|
+
width: number;
|
|
684
|
+
/** `width` over the base width: the m every rule is written in. */
|
|
685
|
+
multiplier: number;
|
|
686
|
+
heads: number;
|
|
687
|
+
params: number;
|
|
688
|
+
doc: Doc;
|
|
689
|
+
/** The rung the hyperparameters are tuned at, where the multiplier is 1. */
|
|
690
|
+
base: boolean;
|
|
691
|
+
scaling: MupScaling[];
|
|
692
|
+
notes: string[];
|
|
693
|
+
}
|
|
694
|
+
export interface MupLadder {
|
|
695
|
+
/** What the ladder moved, normally D. */
|
|
696
|
+
widthSymbol: string;
|
|
697
|
+
baseWidth: number;
|
|
698
|
+
/** What was held fixed while the width moved. */
|
|
699
|
+
headDim: number;
|
|
700
|
+
rungs: MupRung[];
|
|
701
|
+
notes: string[];
|
|
702
|
+
}
|
|
703
|
+
export interface MupOptions {
|
|
704
|
+
/** The rungs. Empty halves the design's own width down to a width worth sweeping at. */
|
|
705
|
+
widths?: number[];
|
|
706
|
+
/** The width the sweep happens at. Omitted takes the narrowest rung. */
|
|
707
|
+
baseWidth?: number;
|
|
708
|
+
/** Symbols that move with the width beyond D. Omitted takes the same set scaling uses. */
|
|
709
|
+
widthSymbols?: string[];
|
|
710
|
+
}
|
|
711
|
+
export interface ImportResult {
|
|
712
|
+
doc: Doc;
|
|
713
|
+
/** What the import could not represent faithfully. */
|
|
714
|
+
warnings: string[];
|
|
715
|
+
}
|
|
716
|
+
/**
|
|
717
|
+
* One tensor shape, in both the forms the editor shows.
|
|
718
|
+
*
|
|
719
|
+
* Symbolic is the honest one: `B T D` says the residual stream is D wide
|
|
720
|
+
* whatever D is. Numeric substitutes the design symbols and leaves the runtime
|
|
721
|
+
* ones alone, which is the quickest way to watch a symbol edit travel through a
|
|
722
|
+
* design. Both come from the engine, because only it holds the polynomial.
|
|
723
|
+
*/
|
|
724
|
+
export interface Shape {
|
|
725
|
+
symbolic: string;
|
|
726
|
+
numeric: string;
|
|
727
|
+
}
|
|
728
|
+
/** One pin, as the canvas draws it. */
|
|
729
|
+
export interface ResolvedPort {
|
|
730
|
+
shape: string;
|
|
731
|
+
dtype: string;
|
|
732
|
+
anchor: "flow" | "side";
|
|
733
|
+
optional?: boolean;
|
|
734
|
+
showName?: boolean;
|
|
735
|
+
doc?: string;
|
|
736
|
+
}
|
|
737
|
+
export interface ResolvedPorts {
|
|
738
|
+
in: Record<string, ResolvedPort>;
|
|
739
|
+
out: Record<string, ResolvedPort>;
|
|
740
|
+
}
|
|
741
|
+
/** A node's parameters after evaluation. */
|
|
742
|
+
export interface Resolved {
|
|
743
|
+
type: string;
|
|
744
|
+
/** The concrete value of each parameter. */
|
|
745
|
+
p: Record<string, ParamValue>;
|
|
746
|
+
/** The symbolic form, so a width can be labelled "D" rather than 4096. */
|
|
747
|
+
s: Record<string, string>;
|
|
748
|
+
}
|
|
749
|
+
/** Something wrong with the wiring, addressed to a node. */
|
|
750
|
+
export interface InferIssue {
|
|
751
|
+
path: string;
|
|
752
|
+
port?: string;
|
|
753
|
+
message: string;
|
|
754
|
+
severity: "error" | "warning";
|
|
755
|
+
/** The block's own rule id, when the issue came from a block constraint. */
|
|
756
|
+
rule?: string;
|
|
757
|
+
param?: string;
|
|
758
|
+
}
|
|
759
|
+
/** Every shape in a design, keyed by `"path:port"`. */
|
|
760
|
+
export interface Inference {
|
|
761
|
+
outputs: Record<string, Shape>;
|
|
762
|
+
inputs: Record<string, Shape>;
|
|
763
|
+
/** Consumer `"path:port"` to producer `"path:port"`. */
|
|
764
|
+
producerOf: Record<string, string>;
|
|
765
|
+
ports: Record<string, ResolvedPorts>;
|
|
766
|
+
resolved: Record<string, Resolved>;
|
|
767
|
+
/**
|
|
768
|
+
* The subgraph each composite stood for, by path.
|
|
769
|
+
*
|
|
770
|
+
* The walk builds these anyway, so the editor draws the inside of a block
|
|
771
|
+
* from what the analysis already saw rather than expanding it a second time
|
|
772
|
+
* with its own copy of the rules.
|
|
773
|
+
*/
|
|
774
|
+
expansions: Record<string, Graph>;
|
|
775
|
+
issues: InferIssue[];
|
|
776
|
+
}
|
|
777
|
+
/** Everything the editor needs for one document at one operating point. */
|
|
778
|
+
export interface Derived {
|
|
779
|
+
report: ValidationReport;
|
|
780
|
+
/** Shape inference with composites expanded, so interiors can be opened. */
|
|
781
|
+
infer: Inference;
|
|
782
|
+
}
|