@tuned-tensor/cli 0.13.1-beta.0 → 0.13.1-beta.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/README.md +31 -12
- package/dist/{chunk-YJYCGSHJ.js → chunk-2P2RL23O.js} +144 -6
- package/dist/chunk-2P2RL23O.js.map +1 -0
- package/dist/index.js +548 -43
- package/dist/index.js.map +1 -1
- package/dist/local-runtime.js +77 -9
- package/dist/local-runtime.js.map +1 -1
- package/docs/local-runtime/architecture.md +24 -0
- package/examples/local-runtime/foundation-spec.json +31 -0
- package/package.json +6 -3
- package/training/foundation/pyproject.toml +24 -0
- package/training/foundation/src/common.py +41 -0
- package/training/foundation/src/data.py +135 -0
- package/training/foundation/src/evaluate.py +115 -0
- package/training/foundation/src/finetune.py +96 -0
- package/training/foundation/src/model.py +157 -0
- package/training/foundation/src/pretrain.py +66 -0
- package/training/foundation/src/rl.py +121 -0
- package/training/foundation/src/train_tokenizer.py +26 -0
- package/training/foundation/uv.lock +922 -0
- package/dist/chunk-YJYCGSHJ.js.map +0 -1
package/README.md
CHANGED
|
@@ -84,7 +84,7 @@ such as `runs list` and `doctor` work immediately. Chat waits until you choose
|
|
|
84
84
|
a provider and model from inside the shell:
|
|
85
85
|
|
|
86
86
|
```text
|
|
87
|
-
tt v0.13.1-beta.
|
|
87
|
+
tt v0.13.1-beta.2
|
|
88
88
|
agent not configured · workflow model base
|
|
89
89
|
ctrl+c stop/clear · ctrl+d exit · /help commands · tab complete
|
|
90
90
|
|
|
@@ -113,7 +113,7 @@ After a model is selected, the banner shows it and ordinary sentences go to
|
|
|
113
113
|
the agent:
|
|
114
114
|
|
|
115
115
|
```text
|
|
116
|
-
tt v0.13.1-beta.
|
|
116
|
+
tt v0.13.1-beta.2
|
|
117
117
|
agent anthropic/claude-sonnet-4-5 · workflow model base
|
|
118
118
|
ctrl+c stop/clear · ctrl+d exit · /help commands · tab complete
|
|
119
119
|
|
|
@@ -174,28 +174,47 @@ explicitly.
|
|
|
174
174
|
|
|
175
175
|
## Composable pipelines (v1)
|
|
176
176
|
|
|
177
|
-
A pipeline is an ordered JSON recipe.
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
177
|
+
A pipeline is an ordered JSON recipe. This CLI executes local plans only. The
|
|
178
|
+
portable document contract lives in `@tuned-tensor/pipeline-contract`. The CLI
|
|
179
|
+
adds execution planning (step selection) on top of it.
|
|
180
|
+
|
|
181
|
+
Two local engines share that document version:
|
|
182
|
+
|
|
183
|
+
- **Adapter** (default): LoRA SFT on a certified Hugging Face checkpoint.
|
|
184
|
+
`tt run` and `tt pipeline` both work. Uses `train` / `evaluate` / `compare`
|
|
185
|
+
with `evaluate.with.evaluator: "behavior"`.
|
|
186
|
+
- **Foundation**: from-scratch tokenizer + GPT. `tt pipeline` only. Uses
|
|
187
|
+
`tokenize` / `pretrain` / `finetune` / optional `rl` plus `bpb`, `chat`, and
|
|
188
|
+
`inference` evaluators. Requires a foundation `tunedtensor.json`
|
|
189
|
+
(`engine: "foundation"`, at least two examples, no `base_model`).
|
|
190
|
+
|
|
191
|
+
The foundation engine is a small, readable local baseline inspired by Andrej
|
|
192
|
+
Karpathy's [nanochat](https://github.com/karpathy/nanochat), not a port of its
|
|
193
|
+
compute-optimal training stack. The first version deliberately builds a bounded
|
|
194
|
+
pretraining corpus from the spec prompt and examples, reports chat accuracy on
|
|
195
|
+
those same contract examples, and supports one training process. Foundation
|
|
196
|
+
plans reject `compare` before creating run artifacts; comparison remains an
|
|
197
|
+
adapter-engine capability. Optional RL samples one seeded on-policy completion
|
|
198
|
+
per step with a sparse last-number exact reward and therefore requires a numeric
|
|
199
|
+
expected output for every example. Treat those metrics as an end-to-end
|
|
200
|
+
execution and overfit check—not held-out capability or multi-GPU evidence.
|
|
185
201
|
|
|
186
202
|
```bash
|
|
187
203
|
tt pipeline init --file pipeline.json
|
|
204
|
+
tt pipeline init --engine foundation --file foundation.pipeline.json
|
|
188
205
|
tt pipeline validate --file pipeline.json
|
|
189
206
|
tt --json pipeline plan --file pipeline.json
|
|
190
207
|
tt --json pipeline run --dry-run --file pipeline.json --only baseline
|
|
191
208
|
tt --json pipeline run --file pipeline.json \
|
|
192
209
|
--spec tunedtensor.json --config local-runner.json
|
|
210
|
+
tt init --engine foundation --name "Tiny GPT"
|
|
211
|
+
tt --json pipeline run --spec tunedtensor.json --dry-run
|
|
193
212
|
```
|
|
194
213
|
|
|
195
214
|
`--only` and `--skip` preserve dependency safety: a selected step cannot refer
|
|
196
215
|
to an omitted predecessor. Cloud-targeted steps fail closed unless you pass
|
|
197
|
-
`--dry-run`. The TT agent may describe,
|
|
198
|
-
no direct pipeline-execute tool.
|
|
216
|
+
`--dry-run`. Foundation documents are local-only. The TT agent may describe,
|
|
217
|
+
validate, and prepare a plan, but has no direct pipeline-execute tool.
|
|
199
218
|
|
|
200
219
|
## Quick start
|
|
201
220
|
|
|
@@ -851,6 +851,28 @@ var specSnapshotSchema = z.object({
|
|
|
851
851
|
constraints: z.array(z.string()).default([]),
|
|
852
852
|
base_model: z.string().transform((value) => canonicalizeTrainingModel(value))
|
|
853
853
|
}).strict();
|
|
854
|
+
var foundationHyperparametersSchema = z.object({
|
|
855
|
+
vocab_size: z.number().int().min(64).max(65536).default(256),
|
|
856
|
+
max_chars: z.number().int().min(1e3).max(2e9).default(2e4),
|
|
857
|
+
depth: z.number().int().min(1).max(64).default(2),
|
|
858
|
+
pretrain_steps: z.number().int().min(1).max(1e7).default(2),
|
|
859
|
+
finetune_steps: z.number().int().min(1).max(1e7).default(2),
|
|
860
|
+
rl_steps: z.number().int().min(0).max(1e7).default(0),
|
|
861
|
+
batch_size: z.number().int().min(1).max(1024).default(2),
|
|
862
|
+
sequence_length: z.number().int().min(16).max(8192).default(64),
|
|
863
|
+
nproc_per_node: z.number().int().min(1).max(16).default(1)
|
|
864
|
+
}).strict();
|
|
865
|
+
var localFoundationSpecFileSchema = z.object({
|
|
866
|
+
engine: z.literal("foundation"),
|
|
867
|
+
id: z.string().uuid().optional(),
|
|
868
|
+
name: z.string().min(1),
|
|
869
|
+
description: z.string().default(""),
|
|
870
|
+
system_prompt: z.string().default(""),
|
|
871
|
+
guidelines: z.array(z.string()).default([]),
|
|
872
|
+
examples: z.array(behaviorSpecExampleSchema).min(2),
|
|
873
|
+
constraints: z.array(z.string()).default([]),
|
|
874
|
+
foundation: foundationHyperparametersSchema
|
|
875
|
+
}).strict();
|
|
854
876
|
var datasetPrebuiltSchema = z.object({
|
|
855
877
|
training: z.string().min(1),
|
|
856
878
|
validation: z.string().min(1).optional(),
|
|
@@ -895,11 +917,16 @@ var fineTuneRunRequestSchema = z.object({
|
|
|
895
917
|
});
|
|
896
918
|
}
|
|
897
919
|
});
|
|
898
|
-
var
|
|
920
|
+
var localAdapterSpecFileSchema = specSnapshotSchema.extend({
|
|
921
|
+
engine: z.literal("adapter").optional(),
|
|
899
922
|
id: z.string().uuid().optional(),
|
|
900
923
|
hyperparameters: fineTuneHyperparametersSchema.optional(),
|
|
901
924
|
dataset_prebuilt: datasetPrebuiltSchema.optional()
|
|
902
925
|
}).strict();
|
|
926
|
+
var localBehaviorSpecFileSchema = z.union([
|
|
927
|
+
localFoundationSpecFileSchema,
|
|
928
|
+
localAdapterSpecFileSchema
|
|
929
|
+
]);
|
|
903
930
|
var evalExampleResultSchema = z.object({
|
|
904
931
|
prompt: z.string(),
|
|
905
932
|
expected: z.string(),
|
|
@@ -1080,6 +1107,9 @@ var localRunnerConfigSchema = z.object({
|
|
|
1080
1107
|
baselineCache: true
|
|
1081
1108
|
})
|
|
1082
1109
|
}).strict();
|
|
1110
|
+
function isFoundationSpecFile(spec) {
|
|
1111
|
+
return spec.engine === "foundation";
|
|
1112
|
+
}
|
|
1083
1113
|
|
|
1084
1114
|
// src/local-runtime/local-project.ts
|
|
1085
1115
|
import { createHash as createHash2, randomUUID as randomUUID2 } from "crypto";
|
|
@@ -1121,7 +1151,48 @@ async function initLocalSpecFile(args) {
|
|
|
1121
1151
|
if (!args.force && await exists(args.outputPath)) {
|
|
1122
1152
|
throw new Error(`Refusing to overwrite existing file: ${args.outputPath}`);
|
|
1123
1153
|
}
|
|
1124
|
-
|
|
1154
|
+
if (args.engine === "foundation") {
|
|
1155
|
+
const spec2 = localFoundationSpecFileSchema.parse({
|
|
1156
|
+
engine: "foundation",
|
|
1157
|
+
id: randomUUID2(),
|
|
1158
|
+
name: args.name,
|
|
1159
|
+
description: "From-scratch tokenizer, pretrain, chat SFT, and eval.",
|
|
1160
|
+
system_prompt: "You are a helpful assistant.",
|
|
1161
|
+
guidelines: [
|
|
1162
|
+
"Answer the user request directly."
|
|
1163
|
+
],
|
|
1164
|
+
constraints: [],
|
|
1165
|
+
examples: [
|
|
1166
|
+
{
|
|
1167
|
+
input: "Replace this with representative chat input.",
|
|
1168
|
+
output: "Replace this with the expected assistant reply."
|
|
1169
|
+
},
|
|
1170
|
+
{
|
|
1171
|
+
input: "Replace this with a different chat input.",
|
|
1172
|
+
output: "Replace this with the expected assistant reply."
|
|
1173
|
+
}
|
|
1174
|
+
],
|
|
1175
|
+
foundation: {
|
|
1176
|
+
depth: 2,
|
|
1177
|
+
pretrain_steps: 2,
|
|
1178
|
+
finetune_steps: 2,
|
|
1179
|
+
rl_steps: 0,
|
|
1180
|
+
vocab_size: 256,
|
|
1181
|
+
max_chars: 2e4,
|
|
1182
|
+
sequence_length: 64,
|
|
1183
|
+
batch_size: 2,
|
|
1184
|
+
nproc_per_node: 1
|
|
1185
|
+
}
|
|
1186
|
+
});
|
|
1187
|
+
await mkdir2(dirname2(args.outputPath), { recursive: true });
|
|
1188
|
+
await writeFile2(args.outputPath, `${JSON.stringify(spec2, null, 2)}
|
|
1189
|
+
`, "utf8");
|
|
1190
|
+
return spec2;
|
|
1191
|
+
}
|
|
1192
|
+
if (!args.baseModel) {
|
|
1193
|
+
throw new Error("Adapter specs require --model.");
|
|
1194
|
+
}
|
|
1195
|
+
const spec = localAdapterSpecFileSchema.parse({
|
|
1125
1196
|
id: randomUUID2(),
|
|
1126
1197
|
name: args.name,
|
|
1127
1198
|
description: "",
|
|
@@ -1172,27 +1243,45 @@ async function initLocalRunnerConfigFile(args) {
|
|
|
1172
1243
|
`, "utf8");
|
|
1173
1244
|
return config;
|
|
1174
1245
|
}
|
|
1175
|
-
function
|
|
1246
|
+
function placeholderIssues(systemPrompt, examples) {
|
|
1176
1247
|
const issues = [];
|
|
1177
|
-
if (/describe the behavior this local model should learn/i.test(
|
|
1248
|
+
if (/describe the behavior this local model should learn/i.test(systemPrompt)) {
|
|
1178
1249
|
issues.push("system_prompt still contains the generated placeholder");
|
|
1179
1250
|
}
|
|
1180
|
-
|
|
1251
|
+
examples.forEach((example, index) => {
|
|
1181
1252
|
if (/replace this with/i.test(example.input) || /replace this with/i.test(example.output)) {
|
|
1182
1253
|
issues.push(`examples[${index}] still contains generated placeholder text`);
|
|
1183
1254
|
}
|
|
1184
1255
|
});
|
|
1185
1256
|
return issues;
|
|
1186
1257
|
}
|
|
1258
|
+
function generatedPlaceholderIssues(request) {
|
|
1259
|
+
return placeholderIssues(request.spec_snapshot.system_prompt, request.spec_snapshot.examples);
|
|
1260
|
+
}
|
|
1187
1261
|
function assertLocalRunInputReady(request) {
|
|
1188
1262
|
const issues = generatedPlaceholderIssues(request);
|
|
1189
1263
|
if (issues.length > 0) {
|
|
1190
1264
|
throw new Error(`Edit the generated behavior spec before training: ${issues.join("; ")}.`);
|
|
1191
1265
|
}
|
|
1192
1266
|
}
|
|
1267
|
+
function foundationPlaceholderIssues(spec) {
|
|
1268
|
+
return placeholderIssues(spec.system_prompt, spec.examples);
|
|
1269
|
+
}
|
|
1270
|
+
function assertFoundationSpecReady(spec) {
|
|
1271
|
+
const issues = foundationPlaceholderIssues(spec);
|
|
1272
|
+
if (issues.length > 0) {
|
|
1273
|
+
throw new Error(`Edit the generated foundation spec before training: ${issues.join("; ")}.`);
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1193
1276
|
function runRequestFromLocalSpec(spec, options = {}) {
|
|
1277
|
+
if (isFoundationSpecFile(spec)) {
|
|
1278
|
+
throw new Error(
|
|
1279
|
+
"Foundation specs cannot be converted into a LoRA run request. Use `tt pipeline run --spec`."
|
|
1280
|
+
);
|
|
1281
|
+
}
|
|
1194
1282
|
const {
|
|
1195
1283
|
id,
|
|
1284
|
+
engine: _engine,
|
|
1196
1285
|
hyperparameters,
|
|
1197
1286
|
dataset_prebuilt: datasetPrebuilt,
|
|
1198
1287
|
...specSnapshot
|
|
@@ -1229,6 +1318,9 @@ async function loadLocalRunInput(path, options = {}) {
|
|
|
1229
1318
|
return { kind: "request", path, request: request.data };
|
|
1230
1319
|
}
|
|
1231
1320
|
const spec = localBehaviorSpecFileSchema.parse(raw);
|
|
1321
|
+
if (isFoundationSpecFile(spec)) {
|
|
1322
|
+
return { kind: "foundation-spec", path, spec };
|
|
1323
|
+
}
|
|
1232
1324
|
return {
|
|
1233
1325
|
kind: "spec",
|
|
1234
1326
|
path,
|
|
@@ -1914,6 +2006,20 @@ var BUNDLED_PYTHON_ENVIRONMENT = join3(
|
|
|
1914
2006
|
"uv",
|
|
1915
2007
|
bundledRuntimeHash
|
|
1916
2008
|
);
|
|
2009
|
+
var foundationProject = join3(packageRoot, "training/foundation");
|
|
2010
|
+
var foundationRuntimeHash = (() => {
|
|
2011
|
+
const hash = createHash3("sha256");
|
|
2012
|
+
for (const name of ["pyproject.toml", "uv.lock"]) {
|
|
2013
|
+
hash.update(readFileSync(join3(foundationProject, name)));
|
|
2014
|
+
}
|
|
2015
|
+
return hash.digest("hex").slice(0, 20);
|
|
2016
|
+
})();
|
|
2017
|
+
var FOUNDATION_PYTHON_ENVIRONMENT = join3(
|
|
2018
|
+
resolve6(process.env.XDG_CACHE_HOME ?? join3(homedir3(), ".cache")),
|
|
2019
|
+
"tuned-tensor-local",
|
|
2020
|
+
"uv-foundation",
|
|
2021
|
+
foundationRuntimeHash
|
|
2022
|
+
);
|
|
1917
2023
|
function buildBundledPythonCommand(entrypoint, args = []) {
|
|
1918
2024
|
const target = entrypoint === "-c" ? entrypoint : join3(bundledProject, "src", entrypoint);
|
|
1919
2025
|
const commandArgs = [
|
|
@@ -1938,6 +2044,29 @@ function withBundledPythonEnvironment(env) {
|
|
|
1938
2044
|
UV_PROJECT_ENVIRONMENT: BUNDLED_PYTHON_ENVIRONMENT
|
|
1939
2045
|
};
|
|
1940
2046
|
}
|
|
2047
|
+
function buildFoundationPythonCommand(entrypoint, args = []) {
|
|
2048
|
+
const commandArgs = [
|
|
2049
|
+
"run",
|
|
2050
|
+
"--frozen",
|
|
2051
|
+
"--quiet",
|
|
2052
|
+
"--project",
|
|
2053
|
+
foundationProject,
|
|
2054
|
+
"python",
|
|
2055
|
+
join3(foundationProject, "src", entrypoint),
|
|
2056
|
+
...args
|
|
2057
|
+
];
|
|
2058
|
+
return {
|
|
2059
|
+
command: "uv",
|
|
2060
|
+
commandArgs,
|
|
2061
|
+
displayCommand: ["uv", ...commandArgs]
|
|
2062
|
+
};
|
|
2063
|
+
}
|
|
2064
|
+
function withFoundationPythonEnvironment(env) {
|
|
2065
|
+
return {
|
|
2066
|
+
...env,
|
|
2067
|
+
UV_PROJECT_ENVIRONMENT: FOUNDATION_PYTHON_ENVIRONMENT
|
|
2068
|
+
};
|
|
2069
|
+
}
|
|
1941
2070
|
var ProcessCancelledError = class extends Error {
|
|
1942
2071
|
constructor(message = "Process cancelled.") {
|
|
1943
2072
|
super(message);
|
|
@@ -4755,9 +4884,12 @@ export {
|
|
|
4755
4884
|
baseModelRevisionSchema,
|
|
4756
4885
|
behaviorSpecExampleSchema,
|
|
4757
4886
|
specSnapshotSchema,
|
|
4887
|
+
foundationHyperparametersSchema,
|
|
4888
|
+
localFoundationSpecFileSchema,
|
|
4758
4889
|
datasetPrebuiltSchema,
|
|
4759
4890
|
fineTuneHyperparametersSchema,
|
|
4760
4891
|
fineTuneRunRequestSchema,
|
|
4892
|
+
localAdapterSpecFileSchema,
|
|
4761
4893
|
localBehaviorSpecFileSchema,
|
|
4762
4894
|
evalExampleResultSchema,
|
|
4763
4895
|
jsonFieldMetricsSchema,
|
|
@@ -4767,12 +4899,15 @@ export {
|
|
|
4767
4899
|
trainingReportSchema,
|
|
4768
4900
|
runReportSchema,
|
|
4769
4901
|
localRunnerConfigSchema,
|
|
4902
|
+
isFoundationSpecFile,
|
|
4770
4903
|
DEFAULT_LOCAL_SPEC_PATH,
|
|
4771
4904
|
resolveLocalRunInputPaths,
|
|
4772
4905
|
initLocalSpecFile,
|
|
4773
4906
|
initLocalRunnerConfigFile,
|
|
4774
4907
|
generatedPlaceholderIssues,
|
|
4775
4908
|
assertLocalRunInputReady,
|
|
4909
|
+
foundationPlaceholderIssues,
|
|
4910
|
+
assertFoundationSpecReady,
|
|
4776
4911
|
runRequestFromLocalSpec,
|
|
4777
4912
|
loadLocalRunInput,
|
|
4778
4913
|
normalizeChatJsonlForRelocation,
|
|
@@ -4788,6 +4923,9 @@ export {
|
|
|
4788
4923
|
localRuntimePackageRoot,
|
|
4789
4924
|
buildBundledPythonCommand,
|
|
4790
4925
|
withBundledPythonEnvironment,
|
|
4926
|
+
buildFoundationPythonCommand,
|
|
4927
|
+
withFoundationPythonEnvironment,
|
|
4928
|
+
runLoggedProcess,
|
|
4791
4929
|
isTerminalRunState,
|
|
4792
4930
|
defaultLocalHome,
|
|
4793
4931
|
localStorePaths,
|
|
@@ -4811,4 +4949,4 @@ export {
|
|
|
4811
4949
|
runLocalPipeline,
|
|
4812
4950
|
runLocalFineTune
|
|
4813
4951
|
};
|
|
4814
|
-
//# sourceMappingURL=chunk-
|
|
4952
|
+
//# sourceMappingURL=chunk-2P2RL23O.js.map
|