@tuned-tensor/cli 0.19.0 → 0.21.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 +45 -9
- package/dist/{chunk-4Q54NHKR.js → chunk-PVLX7LJI.js} +381 -148
- package/dist/chunk-PVLX7LJI.js.map +1 -0
- package/dist/index.js +2051 -417
- package/dist/index.js.map +1 -1
- package/dist/local-runtime.js +41 -6
- package/dist/local-runtime.js.map +1 -1
- package/docs/local-runtime/architecture.md +6 -1
- package/docs/local-runtime/decision.md +142 -0
- package/docs/spec-architecture.html +2 -2
- package/docs/spec-workflow.md +16 -7
- package/examples/single-spec/decision/tunedtensor.json +630 -0
- package/package.json +5 -2
- package/training/adapter/src/evaluate.py +14 -7
- package/training/adapter/src/model_contract.py +38 -5
- package/training/adapter/src/prefetch.py +6 -1
- package/training/adapter/src/serve.py +37 -11
- package/training/adapter/src/train.py +8 -0
- package/training/decision/pyproject.toml +25 -0
- package/training/decision/src/common.py +127 -0
- package/training/decision/src/evaluate.py +70 -0
- package/training/decision/src/train.py +181 -0
- package/training/decision/uv.lock +1175 -0
- package/dist/chunk-4Q54NHKR.js.map +0 -1
|
@@ -615,23 +615,52 @@ var TRAINING_MODELS = [
|
|
|
615
615
|
gradientCheckpointing: true
|
|
616
616
|
}
|
|
617
617
|
];
|
|
618
|
-
|
|
618
|
+
var HUGGING_FACE_REPO_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,95}\/[A-Za-z0-9][A-Za-z0-9._-]{0,95}$/;
|
|
619
|
+
function uncertifiedTrainingModel(id) {
|
|
620
|
+
return {
|
|
621
|
+
id,
|
|
622
|
+
family: "uncertified",
|
|
623
|
+
modelLoader: "causal_lm",
|
|
624
|
+
defaultLearningRate: 1e-4,
|
|
625
|
+
defaultPerDeviceBatchSize: 1,
|
|
626
|
+
defaultGradientAccumulationSteps: 8,
|
|
627
|
+
defaultLoraRank: 16,
|
|
628
|
+
defaultLoraAlpha: 32,
|
|
629
|
+
defaultLoraDropout: 0.05,
|
|
630
|
+
defaultMaxSeqLength: 2048,
|
|
631
|
+
loraTargetModules: "all-linear",
|
|
632
|
+
gradientCheckpointing: true
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
function findCertifiedTrainingModel(modelId) {
|
|
619
636
|
const normalized = modelId.trim().toLowerCase();
|
|
620
|
-
|
|
621
|
-
|
|
637
|
+
return TRAINING_MODELS.find((candidate) => candidate.id.toLowerCase() === normalized);
|
|
638
|
+
}
|
|
639
|
+
function isCertifiedTrainingModel(modelId) {
|
|
640
|
+
return findCertifiedTrainingModel(modelId) !== void 0;
|
|
641
|
+
}
|
|
642
|
+
function resolveTrainingModel(modelId) {
|
|
643
|
+
const model = findCertifiedTrainingModel(modelId);
|
|
644
|
+
if (model) return model;
|
|
645
|
+
const id = modelId.trim();
|
|
646
|
+
if (HUGGING_FACE_REPO_ID.test(id)) return uncertifiedTrainingModel(id);
|
|
647
|
+
throw new Error(
|
|
648
|
+
`Unsupported base model "${modelId}". Use a certified model (${TRAINING_MODELS.map((item) => item.id).join(", ")}) or a Hugging Face repo id such as owner/name.`
|
|
649
|
+
);
|
|
650
|
+
}
|
|
651
|
+
function uncertifiedRevisionError(modelId) {
|
|
652
|
+
return new Error(
|
|
653
|
+
`${modelId} is not a TT-certified base model. To fine-tune it anyway, set hyperparameters.base_model_revision to its 40-character commit SHA (see https://huggingface.co/${modelId}/commits/main). Uncertified models load as text causal LMs with safetensors weights and no remote code.`
|
|
622
654
|
);
|
|
623
|
-
if (!model) {
|
|
624
|
-
throw new Error(
|
|
625
|
-
`Unsupported base model "${modelId}". Supported models: ${TRAINING_MODELS.map((item) => item.id).join(", ")}`
|
|
626
|
-
);
|
|
627
|
-
}
|
|
628
|
-
return model;
|
|
629
655
|
}
|
|
630
656
|
function canonicalizeTrainingModel(modelId) {
|
|
631
657
|
return resolveTrainingModel(modelId).id;
|
|
632
658
|
}
|
|
633
659
|
function resolveRequestedBaseModelRevision(modelId, requestedRevision) {
|
|
634
660
|
const model = resolveTrainingModel(modelId);
|
|
661
|
+
if (!isCertifiedTrainingModel(model.id) && !requestedRevision) {
|
|
662
|
+
throw uncertifiedRevisionError(model.id);
|
|
663
|
+
}
|
|
635
664
|
if (model.defaultRevision && requestedRevision && requestedRevision !== model.defaultRevision) {
|
|
636
665
|
throw new Error(
|
|
637
666
|
`${model.id} must use certified revision ${model.defaultRevision}; got ${requestedRevision}.`
|
|
@@ -640,7 +669,7 @@ function resolveRequestedBaseModelRevision(modelId, requestedRevision) {
|
|
|
640
669
|
return requestedRevision ?? model.defaultRevision;
|
|
641
670
|
}
|
|
642
671
|
function defaultBaseModelRevision(modelId) {
|
|
643
|
-
return
|
|
672
|
+
return resolveTrainingModel(modelId).defaultRevision;
|
|
644
673
|
}
|
|
645
674
|
function resolveModelLoader(modelId) {
|
|
646
675
|
return resolveTrainingModel(modelId).modelLoader;
|
|
@@ -703,6 +732,7 @@ function assertCertifiedBaseModelConfig(value, label = "base-model config.json",
|
|
|
703
732
|
throw new Error(`${label} must contain a JSON object.`);
|
|
704
733
|
}
|
|
705
734
|
const config = value;
|
|
735
|
+
if (expectedModelId && !isCertifiedTrainingModel(expectedModelId)) return;
|
|
706
736
|
const expectedFamily = expectedModelId ? resolveTrainingModel(expectedModelId).family : void 0;
|
|
707
737
|
if (config.model_type === "qwen3_5") {
|
|
708
738
|
if (expectedFamily && expectedFamily !== "qwen3_5") {
|
|
@@ -846,6 +876,7 @@ var TUNED_TENSOR_DIR = ".tuned-tensor";
|
|
|
846
876
|
var DEFAULT_ARTIFACT_ROOT = `${TUNED_TENSOR_DIR}/artifacts`;
|
|
847
877
|
var DEFAULT_PROJECT_STORE_ROOT = `${TUNED_TENSOR_DIR}/store`;
|
|
848
878
|
var DEFAULT_FOUNDATION_RUNS_DIR = `${TUNED_TENSOR_DIR}/foundation-runs`;
|
|
879
|
+
var DEFAULT_DECISION_RUNS_DIR = `${TUNED_TENSOR_DIR}/decision-runs`;
|
|
849
880
|
function envHome(env = process.env) {
|
|
850
881
|
const home = env.HOME?.trim();
|
|
851
882
|
return home ? resolve3(home) : homedir();
|
|
@@ -902,6 +933,38 @@ function pythonEnvironmentPath(kind, hash, env = process.env) {
|
|
|
902
933
|
return next;
|
|
903
934
|
}
|
|
904
935
|
|
|
936
|
+
// src/local-runtime/decision-models.ts
|
|
937
|
+
var LAYA_REVISION = "55cf4c4ebb4ebe31b2550e8bdf3bd21b99753851";
|
|
938
|
+
var DECISION_MODELS = [
|
|
939
|
+
{
|
|
940
|
+
id: "convaiinnovations/laya",
|
|
941
|
+
family: "laya",
|
|
942
|
+
revision: LAYA_REVISION,
|
|
943
|
+
parameters: "421M (ModernBERT-large encoder + typed decision head)",
|
|
944
|
+
license: "Apache-2.0",
|
|
945
|
+
defaultLearningRate: 2e-5,
|
|
946
|
+
defaultBatchSize: 8,
|
|
947
|
+
defaultEpochs: 3
|
|
948
|
+
}
|
|
949
|
+
];
|
|
950
|
+
var DEFAULT_DECISION_MODEL = DECISION_MODELS[0].id;
|
|
951
|
+
function resolveDecisionModel(modelId) {
|
|
952
|
+
const normalized = modelId.trim().toLowerCase();
|
|
953
|
+
const model = DECISION_MODELS.find((candidate) => candidate.id.toLowerCase() === normalized);
|
|
954
|
+
if (!model) {
|
|
955
|
+
throw new Error(
|
|
956
|
+
`Unsupported decision model "${modelId}". Supported decision models: ${DECISION_MODELS.map((item) => item.id).join(", ")}`
|
|
957
|
+
);
|
|
958
|
+
}
|
|
959
|
+
return model;
|
|
960
|
+
}
|
|
961
|
+
function isDecisionModel(modelId) {
|
|
962
|
+
return DECISION_MODELS.some((candidate) => candidate.id.toLowerCase() === modelId.trim().toLowerCase());
|
|
963
|
+
}
|
|
964
|
+
function canonicalizeDecisionModel(modelId) {
|
|
965
|
+
return resolveDecisionModel(modelId).id;
|
|
966
|
+
}
|
|
967
|
+
|
|
905
968
|
// src/local-runtime/contracts.ts
|
|
906
969
|
var datasetFormatSchema = z.literal("chat_jsonl");
|
|
907
970
|
var baseModelRevisionSchema = z.string().regex(/^[0-9a-f]{40}$/i, "base_model_revision must be a 40-character Hugging Face commit SHA").transform((value) => value.toLowerCase());
|
|
@@ -974,6 +1037,15 @@ var fineTuneHyperparametersSchema = z.object({
|
|
|
974
1037
|
/** Immutable Hugging Face commit used by every stage of the run. */
|
|
975
1038
|
base_model_revision: baseModelRevisionSchema.optional()
|
|
976
1039
|
}).strict();
|
|
1040
|
+
function requirePinnedUncertifiedModel(spec, context) {
|
|
1041
|
+
const baseModel = "spec_snapshot" in spec ? spec.spec_snapshot.base_model : spec.base_model;
|
|
1042
|
+
if (isCertifiedTrainingModel(baseModel) || spec.hyperparameters?.base_model_revision) return;
|
|
1043
|
+
context.addIssue({
|
|
1044
|
+
code: z.ZodIssueCode.custom,
|
|
1045
|
+
path: ["hyperparameters", "base_model_revision"],
|
|
1046
|
+
message: uncertifiedRevisionError(baseModel).message
|
|
1047
|
+
});
|
|
1048
|
+
}
|
|
977
1049
|
var fineTuneRunRequestSchema = z.object({
|
|
978
1050
|
run_id: z.string().uuid(),
|
|
979
1051
|
user_id: z.string().min(1),
|
|
@@ -983,6 +1055,7 @@ var fineTuneRunRequestSchema = z.object({
|
|
|
983
1055
|
hyperparameters: fineTuneHyperparametersSchema.default({ n_epochs: 1 }),
|
|
984
1056
|
dataset_prebuilt: datasetPrebuiltSchema.optional()
|
|
985
1057
|
}).strict().superRefine((request, context) => {
|
|
1058
|
+
requirePinnedUncertifiedModel(request, context);
|
|
986
1059
|
if (request.spec_snapshot.examples.length === 0 && !request.dataset_prebuilt) {
|
|
987
1060
|
context.addIssue({
|
|
988
1061
|
code: z.ZodIssueCode.custom,
|
|
@@ -1205,9 +1278,54 @@ var localAdapterSpecFileSchema = specSnapshotSchema.extend({
|
|
|
1205
1278
|
id: z.string().uuid().optional(),
|
|
1206
1279
|
hyperparameters: fineTuneHyperparametersSchema.optional(),
|
|
1207
1280
|
dataset_prebuilt: datasetPrebuiltSchema.optional()
|
|
1281
|
+
}).strict().superRefine(requirePinnedUncertifiedModel);
|
|
1282
|
+
var decisionQuestionSchema = z.discriminatedUnion("type", [
|
|
1283
|
+
z.object({
|
|
1284
|
+
type: z.literal("choice"),
|
|
1285
|
+
/** Answer label -> description the model reads. Key order is option order. */
|
|
1286
|
+
criteria: z.record(z.string().min(1), z.string()).refine(
|
|
1287
|
+
(criteria) => Object.keys(criteria).length >= 2 && Object.keys(criteria).length <= 32,
|
|
1288
|
+
"A choice decision needs 2 to 32 labels."
|
|
1289
|
+
)
|
|
1290
|
+
}).strict(),
|
|
1291
|
+
z.object({
|
|
1292
|
+
type: z.literal("noul"),
|
|
1293
|
+
criteria: z.object({ true: z.string().optional(), false: z.string().optional() }).strict().optional()
|
|
1294
|
+
}).strict(),
|
|
1295
|
+
z.object({
|
|
1296
|
+
type: z.literal("score"),
|
|
1297
|
+
/** Level descriptions, index 0 first; example outputs are level indices. */
|
|
1298
|
+
criteria: z.array(z.string().min(1)).min(2).max(10)
|
|
1299
|
+
}).strict()
|
|
1300
|
+
]);
|
|
1301
|
+
var decisionHyperparametersSchema = z.object({
|
|
1302
|
+
n_epochs: z.number().int().min(1).max(50).optional(),
|
|
1303
|
+
learning_rate: z.number().positive().max(1).optional(),
|
|
1304
|
+
batch_size: z.number().int().min(1).max(256).optional(),
|
|
1305
|
+
/** Train only the decision head; faster on CPU, usually less accurate. */
|
|
1306
|
+
freeze_encoder: z.boolean().optional(),
|
|
1307
|
+
/** Shuffle option order per training row so the head learns meaning, not position. */
|
|
1308
|
+
shuffle_options: z.boolean().optional(),
|
|
1309
|
+
seed: z.number().int().min(0).max(2147483647).optional(),
|
|
1310
|
+
device: z.enum(["auto", "cpu", "cuda", "mps"]).optional()
|
|
1208
1311
|
}).strict();
|
|
1312
|
+
var localDecisionSpecFileSchema = behaviorSpecSchema.extend({
|
|
1313
|
+
...projectWorkflowFields,
|
|
1314
|
+
engine: z.literal("decision"),
|
|
1315
|
+
id: z.string().uuid().optional(),
|
|
1316
|
+
// Refine first: a union member must report an issue, not throw, for other engines' specs.
|
|
1317
|
+
base_model: z.string().refine(isDecisionModel, `Unsupported decision model. Supported decision models: ${DECISION_MODELS.map((model) => model.id).join(", ")}`).transform((value) => canonicalizeDecisionModel(value)),
|
|
1318
|
+
decision: decisionQuestionSchema,
|
|
1319
|
+
hyperparameters: decisionHyperparametersSchema.optional()
|
|
1320
|
+
});
|
|
1321
|
+
function decisionLabels(question) {
|
|
1322
|
+
if (question.type === "choice") return Object.keys(question.criteria);
|
|
1323
|
+
if (question.type === "noul") return ["false", "true"];
|
|
1324
|
+
return question.criteria.map((_, index) => String(index));
|
|
1325
|
+
}
|
|
1209
1326
|
var localBehaviorSpecFileSchema = z.union([
|
|
1210
1327
|
localFoundationSpecFileSchema,
|
|
1328
|
+
localDecisionSpecFileSchema,
|
|
1211
1329
|
localAdapterSpecFileSchema
|
|
1212
1330
|
]).superRefine((spec, ctx) => {
|
|
1213
1331
|
if (spec.pipeline && isFoundationPipeline(parsePipeline(spec.pipeline)) !== (spec.engine === "foundation")) {
|
|
@@ -1216,14 +1334,142 @@ var localBehaviorSpecFileSchema = z.union([
|
|
|
1216
1334
|
if (spec.engine === "foundation" && (spec.evaluation || spec.runtime?.storeRoot || spec.runtime?.paths)) {
|
|
1217
1335
|
ctx.addIssue({ code: "custom", path: ["runtime"], message: "Foundation uses foundation settings for evaluation and checkpoints; runtime.artifactRoot and runtime.gpu are supported." });
|
|
1218
1336
|
}
|
|
1337
|
+
if (spec.engine === "decision" && (spec.evaluation || spec.runtime?.gpu || spec.runtime?.storeRoot || spec.runtime?.paths)) {
|
|
1338
|
+
ctx.addIssue({ code: "custom", path: ["runtime"], message: "Decision specs support runtime.artifactRoot only; the device is set in hyperparameters.device." });
|
|
1339
|
+
}
|
|
1219
1340
|
});
|
|
1220
1341
|
function isFoundationSpecFile(spec) {
|
|
1221
1342
|
return spec.engine === "foundation";
|
|
1222
1343
|
}
|
|
1344
|
+
function isDecisionSpecFile(spec) {
|
|
1345
|
+
return spec.engine === "decision";
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
// src/local-runtime/dataset.ts
|
|
1349
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
1350
|
+
async function loadNormalizedChatJsonl(path) {
|
|
1351
|
+
const text = await readFile2(path, "utf8");
|
|
1352
|
+
const rows = [];
|
|
1353
|
+
const jsonLines = [];
|
|
1354
|
+
for (const [index, line] of text.split(/\r?\n/).entries()) {
|
|
1355
|
+
if (!line.trim()) continue;
|
|
1356
|
+
let value;
|
|
1357
|
+
try {
|
|
1358
|
+
value = JSON.parse(line);
|
|
1359
|
+
} catch (error) {
|
|
1360
|
+
throw new Error(`Invalid chat JSONL row ${index + 1}: malformed JSON`, { cause: error });
|
|
1361
|
+
}
|
|
1362
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
1363
|
+
throw new Error(`Invalid chat JSONL row ${index + 1}: expected an object`);
|
|
1364
|
+
}
|
|
1365
|
+
const messages = value.messages;
|
|
1366
|
+
if (!Array.isArray(messages) || ![2, 3].includes(messages.length) || messages.some(
|
|
1367
|
+
(message) => !message || typeof message !== "object" || Array.isArray(message) || !["system", "user", "assistant"].includes(String(message.role)) || typeof message.content !== "string"
|
|
1368
|
+
)) {
|
|
1369
|
+
throw new Error(
|
|
1370
|
+
`Invalid chat JSONL row ${index + 1}: expected an optional system message, one user message, and one assistant answer`
|
|
1371
|
+
);
|
|
1372
|
+
}
|
|
1373
|
+
const row = { messages };
|
|
1374
|
+
const offset = row.messages.length === 3 ? 1 : 0;
|
|
1375
|
+
if (offset === 1 && row.messages[0]?.role !== "system" || row.messages[offset]?.role !== "user" || !row.messages[offset]?.content.trim() || row.messages[offset + 1]?.role !== "assistant" || !row.messages[offset + 1]?.content.trim()) {
|
|
1376
|
+
throw new Error(
|
|
1377
|
+
`Invalid chat JSONL row ${index + 1}: expected an optional system message, one non-empty user message, and one non-empty assistant answer`
|
|
1378
|
+
);
|
|
1379
|
+
}
|
|
1380
|
+
rows.push(row);
|
|
1381
|
+
jsonLines.push(JSON.stringify(row));
|
|
1382
|
+
}
|
|
1383
|
+
if (rows.length === 0) throw new Error(`Chat JSONL contains no examples: ${path}`);
|
|
1384
|
+
return {
|
|
1385
|
+
rows,
|
|
1386
|
+
jsonl: jsonLines.join("\n")
|
|
1387
|
+
};
|
|
1388
|
+
}
|
|
1389
|
+
async function normalizeChatJsonlForRelocation(path) {
|
|
1390
|
+
return (await loadNormalizedChatJsonl(path)).jsonl;
|
|
1391
|
+
}
|
|
1392
|
+
function buildSystemMessage(spec) {
|
|
1393
|
+
const parts = [];
|
|
1394
|
+
const guidelines = spec.guidelines.map((value) => value.trim()).filter(Boolean);
|
|
1395
|
+
const constraints = spec.constraints.map((value) => value.trim()).filter(Boolean);
|
|
1396
|
+
if (spec.system_prompt.trim()) parts.push(spec.system_prompt.trim());
|
|
1397
|
+
if (guidelines.length > 0) {
|
|
1398
|
+
parts.push(`Guidelines:
|
|
1399
|
+
${guidelines.map((guideline) => `- ${guideline}`).join("\n")}`);
|
|
1400
|
+
}
|
|
1401
|
+
if (constraints.length > 0) {
|
|
1402
|
+
parts.push(`Constraints:
|
|
1403
|
+
${constraints.map((constraint) => `- ${constraint}`).join("\n")}`);
|
|
1404
|
+
}
|
|
1405
|
+
return parts.join("\n\n") || "Follow the demonstrated behavior.";
|
|
1406
|
+
}
|
|
1407
|
+
function exampleToChatRow(spec, example) {
|
|
1408
|
+
const system = buildSystemMessage(spec);
|
|
1409
|
+
return {
|
|
1410
|
+
messages: [
|
|
1411
|
+
{ role: "system", content: system },
|
|
1412
|
+
{ role: "user", content: example.input },
|
|
1413
|
+
{ role: "assistant", content: example.output }
|
|
1414
|
+
]
|
|
1415
|
+
};
|
|
1416
|
+
}
|
|
1417
|
+
function compileSpecToJsonl(spec) {
|
|
1418
|
+
return spec.examples.map((example) => JSON.stringify(exampleToChatRow(spec, example))).join("\n");
|
|
1419
|
+
}
|
|
1420
|
+
function examplesFromSpec(spec) {
|
|
1421
|
+
return spec.examples;
|
|
1422
|
+
}
|
|
1423
|
+
async function examplesFromChatJsonl(path) {
|
|
1424
|
+
const normalized = await loadNormalizedChatJsonl(path);
|
|
1425
|
+
const examples = [];
|
|
1426
|
+
for (const [index, row] of normalized.rows.entries()) {
|
|
1427
|
+
const user = row.messages.at(-2);
|
|
1428
|
+
const assistant = row.messages.at(-1);
|
|
1429
|
+
examples.push({
|
|
1430
|
+
input: user.content,
|
|
1431
|
+
output: assistant.content
|
|
1432
|
+
});
|
|
1433
|
+
}
|
|
1434
|
+
return examples;
|
|
1435
|
+
}
|
|
1436
|
+
async function evaluationSuiteFromChatJsonl(path, configuredSystem) {
|
|
1437
|
+
const normalized = await loadNormalizedChatJsonl(path);
|
|
1438
|
+
const inputIdentities = /* @__PURE__ */ new Set();
|
|
1439
|
+
for (const row of normalized.rows) {
|
|
1440
|
+
const input = row.messages.at(-2).content;
|
|
1441
|
+
const identity = input.trim().replace(/\s+/g, " ").toLowerCase();
|
|
1442
|
+
if (inputIdentities.has(identity)) {
|
|
1443
|
+
throw new Error(
|
|
1444
|
+
"General regression data contains duplicate inputs; evaluation prompts must be unique."
|
|
1445
|
+
);
|
|
1446
|
+
}
|
|
1447
|
+
inputIdentities.add(identity);
|
|
1448
|
+
}
|
|
1449
|
+
const systems = new Set(
|
|
1450
|
+
normalized.rows.map((row) => row.messages.find((message) => message.role === "system")?.content).filter((value) => value !== void 0)
|
|
1451
|
+
);
|
|
1452
|
+
if (systems.size > 1) {
|
|
1453
|
+
throw new Error("General regression rows must use one consistent system message.");
|
|
1454
|
+
}
|
|
1455
|
+
const embeddedSystem = [...systems][0];
|
|
1456
|
+
if (configuredSystem !== void 0 && embeddedSystem !== void 0 && configuredSystem !== embeddedSystem) {
|
|
1457
|
+
throw new Error(
|
|
1458
|
+
"evaluation.generalRegression.systemPrompt must match the system message embedded in the dataset."
|
|
1459
|
+
);
|
|
1460
|
+
}
|
|
1461
|
+
return {
|
|
1462
|
+
examples: normalized.rows.map((row) => ({
|
|
1463
|
+
input: row.messages.at(-2).content,
|
|
1464
|
+
output: row.messages.at(-1).content
|
|
1465
|
+
})),
|
|
1466
|
+
system: configuredSystem ?? embeddedSystem ?? "You are a helpful assistant."
|
|
1467
|
+
};
|
|
1468
|
+
}
|
|
1223
1469
|
|
|
1224
1470
|
// src/local-runtime/local-project.ts
|
|
1225
1471
|
import { createHash as createHash2, randomUUID as randomUUID2 } from "crypto";
|
|
1226
|
-
import { readFile as
|
|
1472
|
+
import { readFile as readFile3, stat as stat2, writeFile as writeFile2 } from "fs/promises";
|
|
1227
1473
|
import { dirname as dirname2, isAbsolute as isAbsolute3, relative as relative2, resolve as resolve4, sep as sep2 } from "path";
|
|
1228
1474
|
import { homedir as homedir2 } from "os";
|
|
1229
1475
|
import { mkdir as mkdir2 } from "fs/promises";
|
|
@@ -1432,6 +1678,34 @@ async function initLocalSpecFile(args) {
|
|
|
1432
1678
|
});
|
|
1433
1679
|
await mkdir2(dirname2(args.outputPath), { recursive: true });
|
|
1434
1680
|
await writeFile2(args.outputPath, `${JSON.stringify(spec2, null, 2)}
|
|
1681
|
+
`, "utf8");
|
|
1682
|
+
return spec2;
|
|
1683
|
+
}
|
|
1684
|
+
if (args.engine === "decision") {
|
|
1685
|
+
const spec2 = localDecisionSpecFileSchema.parse({
|
|
1686
|
+
engine: "decision",
|
|
1687
|
+
id: randomUUID2(),
|
|
1688
|
+
name: args.name,
|
|
1689
|
+
description: "Typed decision model: one labelled answer per input.",
|
|
1690
|
+
system_prompt: "Describe the decision this local model should make.",
|
|
1691
|
+
guidelines: [],
|
|
1692
|
+
constraints: [],
|
|
1693
|
+
base_model: args.baseModel ?? DEFAULT_DECISION_MODEL,
|
|
1694
|
+
decision: {
|
|
1695
|
+
type: "choice",
|
|
1696
|
+
criteria: {
|
|
1697
|
+
first_label: "Replace this with what the first label means.",
|
|
1698
|
+
second_label: "Replace this with what the second label means."
|
|
1699
|
+
}
|
|
1700
|
+
},
|
|
1701
|
+
examples: [
|
|
1702
|
+
{ input: "Replace this with a representative input.", output: "first_label" },
|
|
1703
|
+
{ input: "Replace this with a different input.", output: "second_label" }
|
|
1704
|
+
],
|
|
1705
|
+
hyperparameters: { n_epochs: 3 }
|
|
1706
|
+
});
|
|
1707
|
+
await mkdir2(dirname2(args.outputPath), { recursive: true });
|
|
1708
|
+
await writeFile2(args.outputPath, `${JSON.stringify(spec2, null, 2)}
|
|
1435
1709
|
`, "utf8");
|
|
1436
1710
|
return spec2;
|
|
1437
1711
|
}
|
|
@@ -1491,7 +1765,7 @@ async function initLocalRunnerConfigFile(args) {
|
|
|
1491
1765
|
}
|
|
1492
1766
|
function placeholderIssues(systemPrompt, examples) {
|
|
1493
1767
|
const issues = [];
|
|
1494
|
-
if (/describe the behavior this local model should learn/i.test(systemPrompt)) {
|
|
1768
|
+
if (/describe the (behavior|decision) this local model should (learn|make)/i.test(systemPrompt)) {
|
|
1495
1769
|
issues.push("system_prompt still contains the generated placeholder");
|
|
1496
1770
|
}
|
|
1497
1771
|
examples.forEach((example, index) => {
|
|
@@ -1513,6 +1787,14 @@ function assertLocalRunInputReady(request) {
|
|
|
1513
1787
|
function foundationPlaceholderIssues(spec) {
|
|
1514
1788
|
return placeholderIssues(spec.system_prompt, spec.examples);
|
|
1515
1789
|
}
|
|
1790
|
+
function decisionPlaceholderIssues(spec) {
|
|
1791
|
+
const issues = placeholderIssues(spec.system_prompt, spec.examples);
|
|
1792
|
+
const descriptions = spec.decision.type === "noul" ? Object.values(spec.decision.criteria ?? {}) : Object.values(spec.decision.criteria);
|
|
1793
|
+
if (descriptions.some((value) => /replace this with/i.test(value ?? ""))) {
|
|
1794
|
+
issues.push("decision.criteria still contains generated placeholder text");
|
|
1795
|
+
}
|
|
1796
|
+
return issues;
|
|
1797
|
+
}
|
|
1516
1798
|
function assertFoundationSpecReady(spec) {
|
|
1517
1799
|
const issues = foundationPlaceholderIssues(spec);
|
|
1518
1800
|
if (issues.length > 0) {
|
|
@@ -1520,9 +1802,9 @@ function assertFoundationSpecReady(spec) {
|
|
|
1520
1802
|
}
|
|
1521
1803
|
}
|
|
1522
1804
|
function runRequestFromLocalSpec(spec, options = {}) {
|
|
1523
|
-
if (isFoundationSpecFile(spec)) {
|
|
1805
|
+
if (isFoundationSpecFile(spec) || isDecisionSpecFile(spec)) {
|
|
1524
1806
|
throw new Error(
|
|
1525
|
-
"Foundation specs cannot be converted into a LoRA run request. Use
|
|
1807
|
+
`${isFoundationSpecFile(spec) ? "Foundation" : "Decision"} specs cannot be converted into a LoRA run request. Use \`tt pipeline run --spec\`.`
|
|
1526
1808
|
);
|
|
1527
1809
|
}
|
|
1528
1810
|
const {
|
|
@@ -1570,6 +1852,9 @@ function parseLocalRunInput(rawInput, path, options = {}) {
|
|
|
1570
1852
|
if (isFoundationSpecFile(spec)) {
|
|
1571
1853
|
return { kind: "foundation-spec", path, spec };
|
|
1572
1854
|
}
|
|
1855
|
+
if (isDecisionSpecFile(spec)) {
|
|
1856
|
+
return { kind: "decision-spec", path, spec };
|
|
1857
|
+
}
|
|
1573
1858
|
return {
|
|
1574
1859
|
kind: "spec",
|
|
1575
1860
|
path,
|
|
@@ -1579,7 +1864,7 @@ function parseLocalRunInput(rawInput, path, options = {}) {
|
|
|
1579
1864
|
}
|
|
1580
1865
|
async function loadLocalRunInput(path, options = {}) {
|
|
1581
1866
|
return parseLocalRunInput(
|
|
1582
|
-
JSON.parse(await
|
|
1867
|
+
JSON.parse(await readFile3(path, "utf8")),
|
|
1583
1868
|
path,
|
|
1584
1869
|
options
|
|
1585
1870
|
);
|
|
@@ -1594,7 +1879,7 @@ function validateBehaviorSpec(input) {
|
|
|
1594
1879
|
return { valid: false, errors: ["Use a behavior spec, not a run request."], warnings };
|
|
1595
1880
|
}
|
|
1596
1881
|
const { spec } = input;
|
|
1597
|
-
const placeholders = input.kind === "foundation-spec" ? foundationPlaceholderIssues(input.spec) : generatedPlaceholderIssues(input.request);
|
|
1882
|
+
const placeholders = input.kind === "foundation-spec" ? foundationPlaceholderIssues(input.spec) : input.kind === "decision-spec" ? decisionPlaceholderIssues(input.spec) : generatedPlaceholderIssues(input.request);
|
|
1598
1883
|
if (placeholders.length) {
|
|
1599
1884
|
errors.push(`Edit the generated behavior spec before training: ${placeholders.join("; ")}.`);
|
|
1600
1885
|
}
|
|
@@ -1609,6 +1894,29 @@ function validateBehaviorSpec(input) {
|
|
|
1609
1894
|
errors.push("Foundation RL requires numeric expected outputs in every example.");
|
|
1610
1895
|
}
|
|
1611
1896
|
}
|
|
1897
|
+
if (input.kind === "decision-spec") {
|
|
1898
|
+
const labels = decisionLabels(input.spec.decision);
|
|
1899
|
+
const normalized = new Map(labels.map((label) => [label.trim().toLowerCase(), label]));
|
|
1900
|
+
if (normalized.size !== labels.length) {
|
|
1901
|
+
errors.push("decision labels must stay distinct ignoring case and surrounding spaces.");
|
|
1902
|
+
}
|
|
1903
|
+
const counts = /* @__PURE__ */ new Map();
|
|
1904
|
+
for (const [index, example] of spec.examples.entries()) {
|
|
1905
|
+
const label = normalized.get(example.output.trim().toLowerCase());
|
|
1906
|
+
if (!label) {
|
|
1907
|
+
errors.push(`examples[${index}].output must be one of the decision labels: ${labels.join(", ")}.`);
|
|
1908
|
+
} else {
|
|
1909
|
+
counts.set(label, (counts.get(label) ?? 0) + 1);
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
const missing = labels.filter((label) => !counts.has(label));
|
|
1913
|
+
if (missing.length && spec.examples.length) {
|
|
1914
|
+
warnings.push(`No examples use decision label(s) ${missing.join(", ")}; the tuned model learns those only from their descriptions.`);
|
|
1915
|
+
}
|
|
1916
|
+
if (buildSystemMessage(spec).length > 600) {
|
|
1917
|
+
warnings.push("The compiled decision instruction exceeds 600 characters; the decision model reads about 190 tokens of instruction and options, so later text may be truncated.");
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1612
1920
|
for (const key of ["name", "system_prompt"]) {
|
|
1613
1921
|
if (!spec[key].trim()) errors.push(`${key} must not be blank.`);
|
|
1614
1922
|
}
|
|
@@ -1784,7 +2092,7 @@ ${validation.errors.join("\n")}`);
|
|
|
1784
2092
|
const pipeline = parsePipeline2(recipe);
|
|
1785
2093
|
if (isFoundationPipeline2(pipeline) !== foundation) {
|
|
1786
2094
|
const recipeEngine = isFoundationPipeline2(pipeline) ? "a foundation" : "an adapter";
|
|
1787
|
-
const specEngine = foundation ? "a foundation" : "an adapter";
|
|
2095
|
+
const specEngine = foundation ? "a foundation" : input.kind === "decision-spec" ? "a decision" : "an adapter";
|
|
1788
2096
|
throw new Error(`Pipeline is ${recipeEngine} recipe, but the behavior spec is ${specEngine} spec. Use a matching recipe or omit --file.`);
|
|
1789
2097
|
}
|
|
1790
2098
|
if (foundation) assertFoundationSettingsMatch(input.spec.foundation, pipeline);
|
|
@@ -1833,128 +2141,6 @@ function assertFoundationSettingsMatch(hp, plan) {
|
|
|
1833
2141
|
}
|
|
1834
2142
|
}
|
|
1835
2143
|
|
|
1836
|
-
// src/local-runtime/dataset.ts
|
|
1837
|
-
import { readFile as readFile3 } from "fs/promises";
|
|
1838
|
-
async function loadNormalizedChatJsonl(path) {
|
|
1839
|
-
const text = await readFile3(path, "utf8");
|
|
1840
|
-
const rows = [];
|
|
1841
|
-
const jsonLines = [];
|
|
1842
|
-
for (const [index, line] of text.split(/\r?\n/).entries()) {
|
|
1843
|
-
if (!line.trim()) continue;
|
|
1844
|
-
let value;
|
|
1845
|
-
try {
|
|
1846
|
-
value = JSON.parse(line);
|
|
1847
|
-
} catch (error) {
|
|
1848
|
-
throw new Error(`Invalid chat JSONL row ${index + 1}: malformed JSON`, { cause: error });
|
|
1849
|
-
}
|
|
1850
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
1851
|
-
throw new Error(`Invalid chat JSONL row ${index + 1}: expected an object`);
|
|
1852
|
-
}
|
|
1853
|
-
const messages = value.messages;
|
|
1854
|
-
if (!Array.isArray(messages) || ![2, 3].includes(messages.length) || messages.some(
|
|
1855
|
-
(message) => !message || typeof message !== "object" || Array.isArray(message) || !["system", "user", "assistant"].includes(String(message.role)) || typeof message.content !== "string"
|
|
1856
|
-
)) {
|
|
1857
|
-
throw new Error(
|
|
1858
|
-
`Invalid chat JSONL row ${index + 1}: expected an optional system message, one user message, and one assistant answer`
|
|
1859
|
-
);
|
|
1860
|
-
}
|
|
1861
|
-
const row = { messages };
|
|
1862
|
-
const offset = row.messages.length === 3 ? 1 : 0;
|
|
1863
|
-
if (offset === 1 && row.messages[0]?.role !== "system" || row.messages[offset]?.role !== "user" || !row.messages[offset]?.content.trim() || row.messages[offset + 1]?.role !== "assistant" || !row.messages[offset + 1]?.content.trim()) {
|
|
1864
|
-
throw new Error(
|
|
1865
|
-
`Invalid chat JSONL row ${index + 1}: expected an optional system message, one non-empty user message, and one non-empty assistant answer`
|
|
1866
|
-
);
|
|
1867
|
-
}
|
|
1868
|
-
rows.push(row);
|
|
1869
|
-
jsonLines.push(JSON.stringify(row));
|
|
1870
|
-
}
|
|
1871
|
-
if (rows.length === 0) throw new Error(`Chat JSONL contains no examples: ${path}`);
|
|
1872
|
-
return {
|
|
1873
|
-
rows,
|
|
1874
|
-
jsonl: jsonLines.join("\n")
|
|
1875
|
-
};
|
|
1876
|
-
}
|
|
1877
|
-
async function normalizeChatJsonlForRelocation(path) {
|
|
1878
|
-
return (await loadNormalizedChatJsonl(path)).jsonl;
|
|
1879
|
-
}
|
|
1880
|
-
function buildSystemMessage(spec) {
|
|
1881
|
-
const parts = [];
|
|
1882
|
-
const guidelines = spec.guidelines.map((value) => value.trim()).filter(Boolean);
|
|
1883
|
-
const constraints = spec.constraints.map((value) => value.trim()).filter(Boolean);
|
|
1884
|
-
if (spec.system_prompt.trim()) parts.push(spec.system_prompt.trim());
|
|
1885
|
-
if (guidelines.length > 0) {
|
|
1886
|
-
parts.push(`Guidelines:
|
|
1887
|
-
${guidelines.map((guideline) => `- ${guideline}`).join("\n")}`);
|
|
1888
|
-
}
|
|
1889
|
-
if (constraints.length > 0) {
|
|
1890
|
-
parts.push(`Constraints:
|
|
1891
|
-
${constraints.map((constraint) => `- ${constraint}`).join("\n")}`);
|
|
1892
|
-
}
|
|
1893
|
-
return parts.join("\n\n") || "Follow the demonstrated behavior.";
|
|
1894
|
-
}
|
|
1895
|
-
function exampleToChatRow(spec, example) {
|
|
1896
|
-
const system = buildSystemMessage(spec);
|
|
1897
|
-
return {
|
|
1898
|
-
messages: [
|
|
1899
|
-
{ role: "system", content: system },
|
|
1900
|
-
{ role: "user", content: example.input },
|
|
1901
|
-
{ role: "assistant", content: example.output }
|
|
1902
|
-
]
|
|
1903
|
-
};
|
|
1904
|
-
}
|
|
1905
|
-
function compileSpecToJsonl(spec) {
|
|
1906
|
-
return spec.examples.map((example) => JSON.stringify(exampleToChatRow(spec, example))).join("\n");
|
|
1907
|
-
}
|
|
1908
|
-
function examplesFromSpec(spec) {
|
|
1909
|
-
return spec.examples;
|
|
1910
|
-
}
|
|
1911
|
-
async function examplesFromChatJsonl(path) {
|
|
1912
|
-
const normalized = await loadNormalizedChatJsonl(path);
|
|
1913
|
-
const examples = [];
|
|
1914
|
-
for (const [index, row] of normalized.rows.entries()) {
|
|
1915
|
-
const user = row.messages.at(-2);
|
|
1916
|
-
const assistant = row.messages.at(-1);
|
|
1917
|
-
examples.push({
|
|
1918
|
-
input: user.content,
|
|
1919
|
-
output: assistant.content
|
|
1920
|
-
});
|
|
1921
|
-
}
|
|
1922
|
-
return examples;
|
|
1923
|
-
}
|
|
1924
|
-
async function evaluationSuiteFromChatJsonl(path, configuredSystem) {
|
|
1925
|
-
const normalized = await loadNormalizedChatJsonl(path);
|
|
1926
|
-
const inputIdentities = /* @__PURE__ */ new Set();
|
|
1927
|
-
for (const row of normalized.rows) {
|
|
1928
|
-
const input = row.messages.at(-2).content;
|
|
1929
|
-
const identity = input.trim().replace(/\s+/g, " ").toLowerCase();
|
|
1930
|
-
if (inputIdentities.has(identity)) {
|
|
1931
|
-
throw new Error(
|
|
1932
|
-
"General regression data contains duplicate inputs; evaluation prompts must be unique."
|
|
1933
|
-
);
|
|
1934
|
-
}
|
|
1935
|
-
inputIdentities.add(identity);
|
|
1936
|
-
}
|
|
1937
|
-
const systems = new Set(
|
|
1938
|
-
normalized.rows.map((row) => row.messages.find((message) => message.role === "system")?.content).filter((value) => value !== void 0)
|
|
1939
|
-
);
|
|
1940
|
-
if (systems.size > 1) {
|
|
1941
|
-
throw new Error("General regression rows must use one consistent system message.");
|
|
1942
|
-
}
|
|
1943
|
-
const embeddedSystem = [...systems][0];
|
|
1944
|
-
if (configuredSystem !== void 0 && embeddedSystem !== void 0 && configuredSystem !== embeddedSystem) {
|
|
1945
|
-
throw new Error(
|
|
1946
|
-
"evaluation.generalRegression.systemPrompt must match the system message embedded in the dataset."
|
|
1947
|
-
);
|
|
1948
|
-
}
|
|
1949
|
-
return {
|
|
1950
|
-
examples: normalized.rows.map((row) => ({
|
|
1951
|
-
input: row.messages.at(-2).content,
|
|
1952
|
-
output: row.messages.at(-1).content
|
|
1953
|
-
})),
|
|
1954
|
-
system: configuredSystem ?? embeddedSystem ?? "You are a helpful assistant."
|
|
1955
|
-
};
|
|
1956
|
-
}
|
|
1957
|
-
|
|
1958
2144
|
// src/local-runtime/run-reporter.ts
|
|
1959
2145
|
function reportInBackground(action) {
|
|
1960
2146
|
try {
|
|
@@ -2600,6 +2786,31 @@ var foundationRuntimeHash = (() => {
|
|
|
2600
2786
|
return hash.digest("hex").slice(0, 20);
|
|
2601
2787
|
})();
|
|
2602
2788
|
var FOUNDATION_PYTHON_ENVIRONMENT = pythonEnvironmentPath("uv-foundation", foundationRuntimeHash);
|
|
2789
|
+
var decisionProject = join4(packageRoot, "training/decision");
|
|
2790
|
+
var decisionRuntimeHash = (() => {
|
|
2791
|
+
const hash = createHash3("sha256");
|
|
2792
|
+
for (const name of ["pyproject.toml", "uv.lock"]) {
|
|
2793
|
+
hash.update(readFileSync(join4(decisionProject, name)));
|
|
2794
|
+
}
|
|
2795
|
+
return hash.digest("hex").slice(0, 20);
|
|
2796
|
+
})();
|
|
2797
|
+
var DECISION_PYTHON_ENVIRONMENT = pythonEnvironmentPath("uv-decision", decisionRuntimeHash);
|
|
2798
|
+
function buildDecisionPythonCommand(entrypoint, args = []) {
|
|
2799
|
+
const commandArgs = [
|
|
2800
|
+
"run",
|
|
2801
|
+
"--frozen",
|
|
2802
|
+
"--quiet",
|
|
2803
|
+
"--project",
|
|
2804
|
+
decisionProject,
|
|
2805
|
+
"python",
|
|
2806
|
+
join4(decisionProject, "src", entrypoint),
|
|
2807
|
+
...args
|
|
2808
|
+
];
|
|
2809
|
+
return { command: "uv", commandArgs, displayCommand: ["uv", ...commandArgs] };
|
|
2810
|
+
}
|
|
2811
|
+
function withDecisionPythonEnvironment(env) {
|
|
2812
|
+
return { ...env, UV_PROJECT_ENVIRONMENT: DECISION_PYTHON_ENVIRONMENT };
|
|
2813
|
+
}
|
|
2603
2814
|
function buildBundledPythonCommand(entrypoint, args = []) {
|
|
2604
2815
|
const target = entrypoint === "-c" ? entrypoint : join4(bundledProject, "src", entrypoint);
|
|
2605
2816
|
const commandArgs = [
|
|
@@ -4640,7 +4851,7 @@ async function resolveBaseModelRevision(request, config) {
|
|
|
4640
4851
|
request.hyperparameters.base_model_revision
|
|
4641
4852
|
);
|
|
4642
4853
|
if (config.paths.baseModel) {
|
|
4643
|
-
return defaultBaseModelRevision(request.spec_snapshot.base_model);
|
|
4854
|
+
return isCertifiedTrainingModel(request.spec_snapshot.base_model) ? defaultBaseModelRevision(request.spec_snapshot.base_model) : requested;
|
|
4644
4855
|
}
|
|
4645
4856
|
if (requested) return requested;
|
|
4646
4857
|
if (!request.spec_snapshot.base_model.includes("/")) {
|
|
@@ -6026,6 +6237,12 @@ function formatCapabilitySummary(report) {
|
|
|
6026
6237
|
}
|
|
6027
6238
|
function warningsFromSnapshot(report, target) {
|
|
6028
6239
|
const warnings = [];
|
|
6240
|
+
if (target.engine === "decision") {
|
|
6241
|
+
if (!report.cuda_available) {
|
|
6242
|
+
warnings.push("No CUDA GPU detected: decision training runs on CPU or Apple MPS (roughly 15 s per 8-example step on a 4-core CPU).");
|
|
6243
|
+
}
|
|
6244
|
+
return warnings;
|
|
6245
|
+
}
|
|
6029
6246
|
if (target.engine === "foundation") {
|
|
6030
6247
|
for (const kind of ["train", "finetune"]) {
|
|
6031
6248
|
const verdict = report.foundation[kind];
|
|
@@ -6460,6 +6677,7 @@ async function assessHardware(options = {}) {
|
|
|
6460
6677
|
}
|
|
6461
6678
|
|
|
6462
6679
|
export {
|
|
6680
|
+
fileUri,
|
|
6463
6681
|
assertArtifactManifest,
|
|
6464
6682
|
TRAINING_MODELS,
|
|
6465
6683
|
resolveTrainingModel,
|
|
@@ -6467,9 +6685,12 @@ export {
|
|
|
6467
6685
|
defaultBaseModelRevision,
|
|
6468
6686
|
resolveModelLoader,
|
|
6469
6687
|
assertUsableModelArtifact,
|
|
6688
|
+
DECISION_MODELS,
|
|
6689
|
+
resolveDecisionModel,
|
|
6470
6690
|
DEFAULT_ARTIFACT_ROOT,
|
|
6471
6691
|
DEFAULT_PROJECT_STORE_ROOT,
|
|
6472
6692
|
DEFAULT_FOUNDATION_RUNS_DIR,
|
|
6693
|
+
DEFAULT_DECISION_RUNS_DIR,
|
|
6473
6694
|
expandUserPath,
|
|
6474
6695
|
getConfigDir,
|
|
6475
6696
|
getAgentConfigDir,
|
|
@@ -6495,8 +6716,20 @@ export {
|
|
|
6495
6716
|
projectRuntimeSchema,
|
|
6496
6717
|
localFoundationSpecFileSchema,
|
|
6497
6718
|
localAdapterSpecFileSchema,
|
|
6719
|
+
decisionQuestionSchema,
|
|
6720
|
+
decisionHyperparametersSchema,
|
|
6721
|
+
localDecisionSpecFileSchema,
|
|
6722
|
+
decisionLabels,
|
|
6498
6723
|
localBehaviorSpecFileSchema,
|
|
6499
6724
|
isFoundationSpecFile,
|
|
6725
|
+
isDecisionSpecFile,
|
|
6726
|
+
normalizeChatJsonlForRelocation,
|
|
6727
|
+
buildSystemMessage,
|
|
6728
|
+
exampleToChatRow,
|
|
6729
|
+
compileSpecToJsonl,
|
|
6730
|
+
examplesFromSpec,
|
|
6731
|
+
examplesFromChatJsonl,
|
|
6732
|
+
evaluationSuiteFromChatJsonl,
|
|
6500
6733
|
validateEvalCases,
|
|
6501
6734
|
DEFAULT_LOCAL_SPEC_PATH,
|
|
6502
6735
|
localPathsOverlap,
|
|
@@ -6506,6 +6739,7 @@ export {
|
|
|
6506
6739
|
generatedPlaceholderIssues,
|
|
6507
6740
|
assertLocalRunInputReady,
|
|
6508
6741
|
foundationPlaceholderIssues,
|
|
6742
|
+
decisionPlaceholderIssues,
|
|
6509
6743
|
assertFoundationSpecReady,
|
|
6510
6744
|
runRequestFromLocalSpec,
|
|
6511
6745
|
parseLocalRunInput,
|
|
@@ -6522,17 +6756,12 @@ export {
|
|
|
6522
6756
|
canonicalJson2 as canonicalJson,
|
|
6523
6757
|
isFoundationPipeline3 as isFoundationPipeline,
|
|
6524
6758
|
parsePipeline3 as parsePipeline,
|
|
6525
|
-
normalizeChatJsonlForRelocation,
|
|
6526
|
-
buildSystemMessage,
|
|
6527
|
-
exampleToChatRow,
|
|
6528
|
-
compileSpecToJsonl,
|
|
6529
|
-
examplesFromSpec,
|
|
6530
|
-
examplesFromChatJsonl,
|
|
6531
|
-
evaluationSuiteFromChatJsonl,
|
|
6532
6759
|
reportInBackground,
|
|
6533
6760
|
sanitizeLogLine,
|
|
6534
6761
|
forwardStreamLines,
|
|
6535
6762
|
localRuntimePackageRoot,
|
|
6763
|
+
buildDecisionPythonCommand,
|
|
6764
|
+
withDecisionPythonEnvironment,
|
|
6536
6765
|
buildBundledPythonCommand,
|
|
6537
6766
|
withBundledPythonEnvironment,
|
|
6538
6767
|
buildFoundationPythonCommand,
|
|
@@ -6550,6 +6779,9 @@ export {
|
|
|
6550
6779
|
writePrivateJsonAtomic,
|
|
6551
6780
|
createLocalStore,
|
|
6552
6781
|
tokenF1,
|
|
6782
|
+
deriveSampleSeed,
|
|
6783
|
+
splitSpecExamples,
|
|
6784
|
+
compareEvalReports,
|
|
6553
6785
|
verifyModelPrefetchCacheReport,
|
|
6554
6786
|
buildModelPrefetchPayload,
|
|
6555
6787
|
verifyLocalBaseModel,
|
|
@@ -6567,10 +6799,11 @@ export {
|
|
|
6567
6799
|
runLocalFineTune,
|
|
6568
6800
|
configForSpec,
|
|
6569
6801
|
resolveProjectConfig,
|
|
6802
|
+
evaluateCapabilities,
|
|
6570
6803
|
warningsFromSnapshot,
|
|
6571
6804
|
readHardwareSnapshot,
|
|
6572
6805
|
formatHostStatusLine,
|
|
6573
6806
|
formatAgentHostBlock,
|
|
6574
6807
|
assessHardware
|
|
6575
6808
|
};
|
|
6576
|
-
//# sourceMappingURL=chunk-
|
|
6809
|
+
//# sourceMappingURL=chunk-PVLX7LJI.js.map
|