@tuned-tensor/cli 0.13.1 → 0.15.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 +153 -69
- package/dist/{chunk-CAEBS5HH.js → chunk-YGN26POJ.js} +4 -3
- package/dist/chunk-YGN26POJ.js.map +1 -0
- package/dist/index.js +4405 -201
- package/dist/index.js.map +1 -1
- package/dist/local-runtime.js +124 -33
- package/dist/local-runtime.js.map +1 -1
- package/docs/local-runtime/architecture.md +11 -7
- package/docs/local-runtime/serving.md +171 -0
- package/docs/local-runtime/spark.md +4 -2
- package/package.json +3 -1
- package/training/adapter/src/model_contract.py +1 -1
- package/training/adapter/src/prefetch.py +1 -1
- package/training/adapter/src/serve.py +133 -267
- package/training/adapter/src/train.py +2 -2
- package/training/serving/pyproject.toml +9 -0
- package/training/serving/uv.lock +2785 -0
- package/dist/chunk-CAEBS5HH.js.map +0 -1
package/dist/local-runtime.js
CHANGED
|
@@ -58,6 +58,7 @@ import {
|
|
|
58
58
|
parseLocalRunInput,
|
|
59
59
|
parseLocalRunnerConfig,
|
|
60
60
|
prefetchBaseModel,
|
|
61
|
+
pythonEnvironmentPath,
|
|
61
62
|
reportInBackground,
|
|
62
63
|
resolveLocalRunInputPaths,
|
|
63
64
|
resolveModelLoader,
|
|
@@ -80,13 +81,13 @@ import {
|
|
|
80
81
|
withHuggingFaceCacheEnvironment,
|
|
81
82
|
withOfflineHuggingFaceCacheEnvironment,
|
|
82
83
|
writePrivateJsonAtomic
|
|
83
|
-
} from "./chunk-
|
|
84
|
+
} from "./chunk-YGN26POJ.js";
|
|
84
85
|
|
|
85
86
|
// src/local-runtime/index.ts
|
|
86
|
-
import { readFileSync, realpathSync } from "fs";
|
|
87
|
-
import { createHash } from "crypto";
|
|
87
|
+
import { readFileSync as readFileSync2, realpathSync } from "fs";
|
|
88
|
+
import { createHash as createHash2 } from "crypto";
|
|
88
89
|
import { readFile as readFile2, stat } from "fs/promises";
|
|
89
|
-
import { basename, dirname, join as
|
|
90
|
+
import { basename, dirname, join as join4, resolve as resolve3 } from "path";
|
|
90
91
|
import { cwd } from "process";
|
|
91
92
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
92
93
|
|
|
@@ -294,7 +295,7 @@ function pythonProbeSource(device) {
|
|
|
294
295
|
"import json",
|
|
295
296
|
"import torch, transformers, peft, huggingface_hub",
|
|
296
297
|
`requested = ${JSON.stringify(device)}`,
|
|
297
|
-
"assert torch.cuda.is_available(), 'TT
|
|
298
|
+
"assert torch.cuda.is_available(), 'TT local training requires CUDA but torch.cuda.is_available() is false'",
|
|
298
299
|
"props = torch.cuda.get_device_properties(0)",
|
|
299
300
|
"print(json.dumps({'python_ok': True, 'torch': torch.__version__, 'transformers': transformers.__version__, 'cuda_available': True, 'cuda_device': torch.cuda.get_device_name(0), 'compute_capability': list(torch.cuda.get_device_capability(0)), 'total_memory_bytes': props.total_memory, 'evaluation_device': requested}))"
|
|
300
301
|
].join("; ");
|
|
@@ -505,10 +506,43 @@ async function runDoctor(config, request, foundationSpec) {
|
|
|
505
506
|
import { spawn as spawn2 } from "child_process";
|
|
506
507
|
import { resolve as resolve2 } from "path";
|
|
507
508
|
import { fileURLToPath } from "url";
|
|
509
|
+
|
|
510
|
+
// src/local-runtime/serving-runtime.ts
|
|
511
|
+
import { createHash } from "crypto";
|
|
512
|
+
import { readFileSync } from "fs";
|
|
513
|
+
import { join as join2 } from "path";
|
|
514
|
+
var root = localRuntimePackageRoot(import.meta.url);
|
|
515
|
+
var project = join2(root, "training/serving");
|
|
516
|
+
var hash = createHash("sha256");
|
|
517
|
+
for (const name of ["pyproject.toml", "uv.lock"]) hash.update(readFileSync(join2(project, name)));
|
|
518
|
+
var SERVING_PYTHON_ENVIRONMENT = pythonEnvironmentPath("uv-serving", hash.digest("hex").slice(0, 20));
|
|
519
|
+
function buildServingPythonCommand() {
|
|
520
|
+
const commandArgs = [
|
|
521
|
+
"run",
|
|
522
|
+
"--frozen",
|
|
523
|
+
"--quiet",
|
|
524
|
+
"--project",
|
|
525
|
+
project,
|
|
526
|
+
"python",
|
|
527
|
+
join2(root, "training/adapter/src/serve.py")
|
|
528
|
+
];
|
|
529
|
+
return { command: "uv", commandArgs, displayCommand: ["uv", ...commandArgs] };
|
|
530
|
+
}
|
|
531
|
+
function withServingPythonEnvironment(env) {
|
|
532
|
+
return {
|
|
533
|
+
...env,
|
|
534
|
+
UV_PROJECT_ENVIRONMENT: SERVING_PYTHON_ENVIRONMENT,
|
|
535
|
+
VLLM_NO_USAGE_STATS: "1",
|
|
536
|
+
DO_NOT_TRACK: "1",
|
|
537
|
+
VLLM_ALLOW_RUNTIME_LORA_UPDATING: "0"
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// src/local-runtime/model-server.ts
|
|
508
542
|
function localArtifactPath(uri) {
|
|
509
543
|
if (uri.startsWith("file://")) return fileURLToPath(uri);
|
|
510
544
|
if (/^[a-z][a-z0-9+.-]*:/i.test(uri)) {
|
|
511
|
-
throw new Error(`TT
|
|
545
|
+
throw new Error(`Local TT serving requires a local file artifact, got: ${uri}`);
|
|
512
546
|
}
|
|
513
547
|
return resolve2(uri);
|
|
514
548
|
}
|
|
@@ -526,6 +560,10 @@ function httpHost(host) {
|
|
|
526
560
|
}
|
|
527
561
|
function buildModelServerLaunch(args) {
|
|
528
562
|
const options = args.options ?? {};
|
|
563
|
+
const device = options.device ?? args.config.evaluation.inference.device;
|
|
564
|
+
if (device !== "cuda") throw new Error("The pinned vLLM serving runtime requires CUDA; CPU serving is not supported.");
|
|
565
|
+
const contextLength = boundedNumber("contextLength", options.contextLength ?? 16384, 512, 131072, true);
|
|
566
|
+
const gpuMemoryUtilization = boundedNumber("gpuMemoryUtilization", options.gpuMemoryUtilization ?? 0.8, 0.05, 0.95);
|
|
529
567
|
const host = options.host ?? "127.0.0.1";
|
|
530
568
|
const remote = !isLoopbackHost(host);
|
|
531
569
|
if (remote && !options.allowRemote) {
|
|
@@ -561,8 +599,8 @@ function buildModelServerLaunch(args) {
|
|
|
561
599
|
options.baseModelRevision
|
|
562
600
|
);
|
|
563
601
|
const baseModelRevision = localBaseModelPath ? defaultBaseModelRevision(args.baseModel) : requestedBaseModelRevision;
|
|
564
|
-
const entrypoint =
|
|
565
|
-
const env =
|
|
602
|
+
const entrypoint = buildServingPythonCommand();
|
|
603
|
+
const env = withServingPythonEnvironment(
|
|
566
604
|
withOfflineHuggingFaceCacheEnvironment({
|
|
567
605
|
...minimalMachineLearningEnvironment(process.env),
|
|
568
606
|
...artifactPath ? { TT_MODEL_ARTIFACT: artifactPath } : {},
|
|
@@ -570,10 +608,12 @@ function buildModelServerLaunch(args) {
|
|
|
570
608
|
...localBaseModelPath ? { TT_MODEL_SOURCE: localBaseModelPath } : {},
|
|
571
609
|
...baseModelRevision ? { TT_BASE_MODEL_REVISION: baseModelRevision } : {},
|
|
572
610
|
TT_MODEL_NAME: args.modelName,
|
|
611
|
+
TT_CONTEXT_LENGTH: String(contextLength),
|
|
612
|
+
TT_GPU_MEMORY_UTILIZATION: String(gpuMemoryUtilization),
|
|
573
613
|
TT_MODEL_LOADER: resolveModelLoader(args.baseModel),
|
|
574
614
|
TT_HOST: host,
|
|
575
615
|
TT_PORT: String(port),
|
|
576
|
-
TT_DEVICE:
|
|
616
|
+
TT_DEVICE: device,
|
|
577
617
|
TT_MAX_TOKENS: String(maxTokens),
|
|
578
618
|
TT_TEMPERATURE: String(temperature),
|
|
579
619
|
TT_TOP_P: String(topP),
|
|
@@ -618,6 +658,7 @@ async function verifyLocalModelServerLaunch(launch) {
|
|
|
618
658
|
}
|
|
619
659
|
}
|
|
620
660
|
async function serveLocalModel(launch) {
|
|
661
|
+
if (process.platform !== "linux") throw new Error("Local vLLM serving requires Linux and an NVIDIA CUDA GPU.");
|
|
621
662
|
await verifyLocalModelServerLaunch(launch);
|
|
622
663
|
await new Promise((resolveServer, reject) => {
|
|
623
664
|
const child = spawn2(launch.command, launch.commandArgs, {
|
|
@@ -673,12 +714,12 @@ async function serveLocalModel(launch) {
|
|
|
673
714
|
// src/local-runtime/active-model.ts
|
|
674
715
|
import { randomUUID } from "crypto";
|
|
675
716
|
import { appendFile, chmod, readFile, rename, writeFile as writeFile2 } from "fs/promises";
|
|
676
|
-
import { join as
|
|
717
|
+
import { join as join3 } from "path";
|
|
677
718
|
function pointerPath(store) {
|
|
678
|
-
return
|
|
719
|
+
return join3(store.root, "active-model.json");
|
|
679
720
|
}
|
|
680
721
|
function historyPath(store) {
|
|
681
|
-
return
|
|
722
|
+
return join3(store.root, "activation-history.jsonl");
|
|
682
723
|
}
|
|
683
724
|
async function readPointer(store) {
|
|
684
725
|
if (!await hardenExistingLocalStore(store.root)) return null;
|
|
@@ -718,7 +759,7 @@ async function assertModelCanActivate(store, modelId) {
|
|
|
718
759
|
throw new Error(`Model ${model.id} belongs to run ${run.id}, which is not completed.`);
|
|
719
760
|
}
|
|
720
761
|
const report = runReportSchema.parse(
|
|
721
|
-
JSON.parse(await readFile(
|
|
762
|
+
JSON.parse(await readFile(join3(model.artifact_dir, "run-report.json"), "utf8"))
|
|
722
763
|
);
|
|
723
764
|
if (!report.general_regression) {
|
|
724
765
|
throw new Error(`Model ${model.id} has no general regression evaluation.`);
|
|
@@ -775,7 +816,7 @@ async function rollbackActiveModel(store) {
|
|
|
775
816
|
function packageVersion() {
|
|
776
817
|
try {
|
|
777
818
|
const packageJson = JSON.parse(
|
|
778
|
-
|
|
819
|
+
readFileSync2(resolve3(localRuntimePackageRoot(import.meta.url), "package.json"), "utf8")
|
|
779
820
|
);
|
|
780
821
|
return typeof packageJson.version === "string" ? packageJson.version : "unknown";
|
|
781
822
|
} catch {
|
|
@@ -830,21 +871,24 @@ var MODEL_SERVE_OPTIONS = [
|
|
|
830
871
|
CONFIG_OPTION,
|
|
831
872
|
{ name: "--host", value: "host", description: "Bind host (localhost by default)" },
|
|
832
873
|
{ name: "--port", value: "port", description: "Bind port" },
|
|
833
|
-
{ name: "--device", value: "device", description: "cuda
|
|
874
|
+
{ name: "--device", value: "device", description: "cuda (pinned vLLM runtime)" },
|
|
834
875
|
{ name: "--max-tokens", value: "count", description: "Default response token limit" },
|
|
835
876
|
{ name: "--temperature", value: "number", description: "Default sampling temperature" },
|
|
836
877
|
{ name: "--top-p", value: "number", description: "Default nucleus sampling threshold" },
|
|
837
|
-
{ name: "--max-concurrent-requests", value: "count", description: "
|
|
878
|
+
{ name: "--max-concurrent-requests", value: "count", description: "Maximum sequences in an upstream generation batch" },
|
|
879
|
+
{ name: "--context-length", value: "count", description: "Total context token budget (default 16384)" },
|
|
880
|
+
{ name: "--gpu-memory-utilization", value: "fraction", description: "vLLM GPU memory budget fraction (default 0.8)" },
|
|
838
881
|
{ name: "--spec", value: "path", description: "Behavior spec whose instructions are enforced" },
|
|
839
882
|
{ name: "--no-spec-prompt", description: "Do not enforce the stored behavior-spec prompt" },
|
|
840
883
|
{ name: "--allow-remote", description: "Allow a non-loopback bind" },
|
|
841
884
|
{ name: "--api-key-env", value: "name", description: "Environment variable containing a bearer token" },
|
|
842
|
-
{ name: "--print-command", description: "Validate and print the launch plan without starting" }
|
|
885
|
+
{ name: "--print-command", description: "Validate and print the launch plan without starting" },
|
|
886
|
+
{ name: "--print-client-config", value: "client", description: "Print Pi models.json; does not start serving" }
|
|
843
887
|
];
|
|
844
888
|
var COMMAND_DEFINITIONS = {
|
|
845
889
|
info: {
|
|
846
890
|
usage: "tt info",
|
|
847
|
-
description: "Show the installed TT
|
|
891
|
+
description: "Show the installed TT local runtime version and runner status.",
|
|
848
892
|
options: [],
|
|
849
893
|
maxPositionals: 0
|
|
850
894
|
},
|
|
@@ -1102,7 +1146,7 @@ function readNumberOption(argv, name) {
|
|
|
1102
1146
|
async function selectedConfigPath(argv, adjacentTo) {
|
|
1103
1147
|
const explicitPath = readOption(argv, "--config");
|
|
1104
1148
|
if (explicitPath) return resolve3(explicitPath);
|
|
1105
|
-
const candidate =
|
|
1149
|
+
const candidate = join4(adjacentTo ? dirname(resolve3(adjacentTo)) : cwd(), "local-runner.json");
|
|
1106
1150
|
const metadata = await stat(candidate).catch(() => null);
|
|
1107
1151
|
return metadata?.isFile() ? candidate : void 0;
|
|
1108
1152
|
}
|
|
@@ -1126,7 +1170,7 @@ async function loadCliBehaviorSpec(inputPath, runId) {
|
|
|
1126
1170
|
);
|
|
1127
1171
|
}
|
|
1128
1172
|
if (input.kind !== "spec") {
|
|
1129
|
-
throw new Error(`TT
|
|
1173
|
+
throw new Error(`TT expects a tunedtensor.json behavior spec, not a full run request: ${input.path}`);
|
|
1130
1174
|
}
|
|
1131
1175
|
return input;
|
|
1132
1176
|
}
|
|
@@ -1146,7 +1190,7 @@ function formatEvent(event) {
|
|
|
1146
1190
|
const formatted = key === "command" && Array.isArray(value) ? value.join(" ") : shortValue(value);
|
|
1147
1191
|
return formatted ? `${key}=${formatted}` : null;
|
|
1148
1192
|
}).filter((value) => Boolean(value)).slice(0, 5).join(" ");
|
|
1149
|
-
return sanitizeLogLine(`[tt
|
|
1193
|
+
return sanitizeLogLine(`[tt] ${event.stage}: ${event.message}${detailText ? ` (${detailText})` : ""}`);
|
|
1150
1194
|
}
|
|
1151
1195
|
function createConsoleReporter(options) {
|
|
1152
1196
|
if (options.quiet) return void 0;
|
|
@@ -1158,7 +1202,7 @@ function createConsoleReporter(options) {
|
|
|
1158
1202
|
`);
|
|
1159
1203
|
},
|
|
1160
1204
|
onLog(log) {
|
|
1161
|
-
const line = sanitizeLogLine(`[tt
|
|
1205
|
+
const line = sanitizeLogLine(`[tt] ${log.stage}${log.stream ? ` ${log.stream}` : ""}: ${log.message}`);
|
|
1162
1206
|
if (line === lastLogLine) return;
|
|
1163
1207
|
lastLogLine = line;
|
|
1164
1208
|
process.stderr.write(`${line}
|
|
@@ -1167,7 +1211,7 @@ function createConsoleReporter(options) {
|
|
|
1167
1211
|
};
|
|
1168
1212
|
}
|
|
1169
1213
|
async function verifyStoredModel(model, config) {
|
|
1170
|
-
const manifestPath =
|
|
1214
|
+
const manifestPath = join4(model.artifact_dir, "artifact-manifest.json");
|
|
1171
1215
|
const integrity = await assertArtifactManifest(manifestPath, {
|
|
1172
1216
|
requiredPaths: ["stage-metadata.json", "training-report.json"],
|
|
1173
1217
|
scopeToRequired: true,
|
|
@@ -1202,8 +1246,8 @@ async function verifyStoredModel(model, config) {
|
|
|
1202
1246
|
};
|
|
1203
1247
|
}
|
|
1204
1248
|
async function verifyActivationEvidence(model) {
|
|
1205
|
-
const generalBaseline =
|
|
1206
|
-
const generalCandidate =
|
|
1249
|
+
const generalBaseline = join4(model.artifact_dir, "general-baseline-eval.json");
|
|
1250
|
+
const generalCandidate = join4(model.artifact_dir, "general-candidate-eval.json");
|
|
1207
1251
|
const [hasBaseline, hasCandidate] = await Promise.all([
|
|
1208
1252
|
stat(generalBaseline).then((metadata) => metadata.isFile(), () => false),
|
|
1209
1253
|
stat(generalCandidate).then((metadata) => metadata.isFile(), () => false)
|
|
@@ -1213,7 +1257,7 @@ async function verifyActivationEvidence(model) {
|
|
|
1213
1257
|
"This model cannot be activated because the run did not include a general-regression suite. Add evaluation.generalRegression to local-runner.json with a held-out dataset, re-run training, then activate. Until then, serve the adapter with `tt serve local-<run-id>`."
|
|
1214
1258
|
);
|
|
1215
1259
|
}
|
|
1216
|
-
await assertArtifactManifest(
|
|
1260
|
+
await assertArtifactManifest(join4(model.artifact_dir, "artifact-manifest.json"), {
|
|
1217
1261
|
requiredPaths: [
|
|
1218
1262
|
"run-report.json",
|
|
1219
1263
|
"general-baseline-eval.json",
|
|
@@ -1239,7 +1283,7 @@ async function verifyModelArtifactPath(input, config) {
|
|
|
1239
1283
|
if (!metadata) throw new Error(`Model not found and artifact path does not exist: ${input}`);
|
|
1240
1284
|
let current = metadata.isDirectory() ? inputPath : dirname(inputPath);
|
|
1241
1285
|
for (let depth = 0; depth < 8; depth += 1) {
|
|
1242
|
-
const candidate =
|
|
1286
|
+
const candidate = join4(current, "artifact-manifest.json");
|
|
1243
1287
|
const raw = await readFile2(candidate, "utf8").catch(() => null);
|
|
1244
1288
|
if (raw) {
|
|
1245
1289
|
const parsed = JSON.parse(raw);
|
|
@@ -1297,7 +1341,7 @@ async function modelSystemPrompt(args) {
|
|
|
1297
1341
|
}
|
|
1298
1342
|
spec = local.data;
|
|
1299
1343
|
} else {
|
|
1300
|
-
const runRequestPath =
|
|
1344
|
+
const runRequestPath = join4(args.store.paths.runsDir, args.model.run_id, "request.json");
|
|
1301
1345
|
let persistedRequest = null;
|
|
1302
1346
|
try {
|
|
1303
1347
|
persistedRequest = fineTuneRunRequestSchema.parse(JSON.parse(await readFile2(runRequestPath, "utf8")));
|
|
@@ -1313,9 +1357,9 @@ async function modelSystemPrompt(args) {
|
|
|
1313
1357
|
}
|
|
1314
1358
|
const prompt = buildSystemMessage(spec);
|
|
1315
1359
|
const metadata = JSON.parse(
|
|
1316
|
-
await readFile2(
|
|
1360
|
+
await readFile2(join4(args.model.artifact_dir, "stage-metadata.json"), "utf8")
|
|
1317
1361
|
);
|
|
1318
|
-
const promptHash =
|
|
1362
|
+
const promptHash = createHash2("sha256").update(prompt).digest("hex");
|
|
1319
1363
|
if (metadata.system_prompt_sha256 !== promptHash) {
|
|
1320
1364
|
throw new Error(
|
|
1321
1365
|
"Behavior spec instructions do not match the prompt fingerprint used for this trained model. Pass the original --spec, or use --no-spec-prompt only when this change is intentional."
|
|
@@ -1330,6 +1374,47 @@ function modelServeDevice(argv) {
|
|
|
1330
1374
|
}
|
|
1331
1375
|
throw new Error(`--device must be cuda or cpu; got: ${value}`);
|
|
1332
1376
|
}
|
|
1377
|
+
function printServeClientConfig(argv, launch) {
|
|
1378
|
+
const client = readOption(argv, "--print-client-config");
|
|
1379
|
+
if (client === void 0) return false;
|
|
1380
|
+
if (client !== "pi") throw new Error("--print-client-config must be pi.");
|
|
1381
|
+
if (hasFlag(argv, "--print-command")) throw new Error("Use only one of --print-command or --print-client-config.");
|
|
1382
|
+
const apiKeyEnv = readOption(argv, "--api-key-env");
|
|
1383
|
+
if (apiKeyEnv && !/^[A-Za-z_][A-Za-z0-9_]*$/.test(apiKeyEnv)) {
|
|
1384
|
+
throw new Error("--api-key-env must be a plain environment variable name for Pi config.");
|
|
1385
|
+
}
|
|
1386
|
+
const url = new URL(launch.url);
|
|
1387
|
+
if (url.hostname === "0.0.0.0") url.hostname = "127.0.0.1";
|
|
1388
|
+
if (url.hostname === "[::]") url.hostname = "[::1]";
|
|
1389
|
+
url.pathname = "/v1";
|
|
1390
|
+
printJson({
|
|
1391
|
+
providers: {
|
|
1392
|
+
"tt-local": {
|
|
1393
|
+
baseUrl: url.toString(),
|
|
1394
|
+
api: "openai-completions",
|
|
1395
|
+
apiKey: apiKeyEnv ? "${" + apiKeyEnv + "}" : "tt-local",
|
|
1396
|
+
compat: {
|
|
1397
|
+
supportsStore: false,
|
|
1398
|
+
supportsDeveloperRole: false,
|
|
1399
|
+
supportsReasoningEffort: false,
|
|
1400
|
+
supportsUsageInStreaming: true,
|
|
1401
|
+
maxTokensField: "max_tokens"
|
|
1402
|
+
},
|
|
1403
|
+
models: [.../* @__PURE__ */ new Set([launch.modelName, `base:${launch.env.TT_BASE_MODEL}`])].map((id) => ({
|
|
1404
|
+
id,
|
|
1405
|
+
name: id,
|
|
1406
|
+
// This endpoint exports ordinary text/tool calls, not reasoning-effort controls.
|
|
1407
|
+
reasoning: false,
|
|
1408
|
+
input: ["text"],
|
|
1409
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
1410
|
+
contextWindow: Number(launch.env.TT_CONTEXT_LENGTH),
|
|
1411
|
+
maxTokens: Number(launch.env.TT_MAX_TOKENS)
|
|
1412
|
+
}))
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
});
|
|
1416
|
+
return true;
|
|
1417
|
+
}
|
|
1333
1418
|
async function serveStoredModelFromCli(args) {
|
|
1334
1419
|
const store = createLocalStore(args.config.storeRoot);
|
|
1335
1420
|
const model = await store.getModel(args.modelId);
|
|
@@ -1345,6 +1430,8 @@ async function serveStoredModelFromCli(args) {
|
|
|
1345
1430
|
temperature: readNumberOption(args.argv, "--temperature"),
|
|
1346
1431
|
topP: readNumberOption(args.argv, "--top-p"),
|
|
1347
1432
|
maxConcurrentRequests: readNumberOption(args.argv, "--max-concurrent-requests"),
|
|
1433
|
+
contextLength: readNumberOption(args.argv, "--context-length"),
|
|
1434
|
+
gpuMemoryUtilization: readNumberOption(args.argv, "--gpu-memory-utilization"),
|
|
1348
1435
|
systemPrompt: await modelSystemPrompt({ argv: args.argv, model, store }),
|
|
1349
1436
|
allowRemote: hasFlag(args.argv, "--allow-remote"),
|
|
1350
1437
|
apiKeyEnv: readOption(args.argv, "--api-key-env"),
|
|
@@ -1358,6 +1445,7 @@ async function serveStoredModelFromCli(args) {
|
|
|
1358
1445
|
})()
|
|
1359
1446
|
}
|
|
1360
1447
|
});
|
|
1448
|
+
if (printServeClientConfig(args.argv, launch)) return;
|
|
1361
1449
|
if (hasFlag(args.argv, "--print-command")) {
|
|
1362
1450
|
printJson({
|
|
1363
1451
|
ok: true,
|
|
@@ -1370,7 +1458,7 @@ async function serveStoredModelFromCli(args) {
|
|
|
1370
1458
|
});
|
|
1371
1459
|
return;
|
|
1372
1460
|
}
|
|
1373
|
-
process.stderr.write(`[tt
|
|
1461
|
+
process.stderr.write(`[tt] verified ${verified.integrity.checked} artifact file(s)
|
|
1374
1462
|
`);
|
|
1375
1463
|
await serveLocalModel(launch);
|
|
1376
1464
|
}
|
|
@@ -1383,6 +1471,8 @@ function serveOptionsFromArgv(argv) {
|
|
|
1383
1471
|
temperature: readNumberOption(argv, "--temperature"),
|
|
1384
1472
|
topP: readNumberOption(argv, "--top-p"),
|
|
1385
1473
|
maxConcurrentRequests: readNumberOption(argv, "--max-concurrent-requests"),
|
|
1474
|
+
contextLength: readNumberOption(argv, "--context-length"),
|
|
1475
|
+
gpuMemoryUtilization: readNumberOption(argv, "--gpu-memory-utilization"),
|
|
1386
1476
|
allowRemote: hasFlag(argv, "--allow-remote"),
|
|
1387
1477
|
apiKeyEnv: readOption(argv, "--api-key-env")
|
|
1388
1478
|
};
|
|
@@ -1421,6 +1511,7 @@ async function serveBaseModelFromCli(args) {
|
|
|
1421
1511
|
baseModelRevision: spec?.hyperparameters?.base_model_revision ?? defaultBaseModelRevision(baseModel)
|
|
1422
1512
|
}
|
|
1423
1513
|
});
|
|
1514
|
+
if (printServeClientConfig(args.argv, launch)) return;
|
|
1424
1515
|
if (hasFlag(args.argv, "--print-command")) {
|
|
1425
1516
|
printJson({
|
|
1426
1517
|
ok: true,
|
|
@@ -1496,7 +1587,7 @@ async function main(argv) {
|
|
|
1496
1587
|
} else if (input.kind === "spec") {
|
|
1497
1588
|
request = input.request;
|
|
1498
1589
|
} else {
|
|
1499
|
-
throw new Error(`TT
|
|
1590
|
+
throw new Error(`TT expects a tunedtensor.json behavior spec, not a full run request: ${input.path}`);
|
|
1500
1591
|
}
|
|
1501
1592
|
}
|
|
1502
1593
|
const checks = await runDoctor(configSelection.config, request, foundationSpec);
|
|
@@ -1583,7 +1674,7 @@ async function main(argv) {
|
|
|
1583
1674
|
return;
|
|
1584
1675
|
}
|
|
1585
1676
|
if (loaded.kind !== "spec") {
|
|
1586
|
-
throw new Error(`TT
|
|
1677
|
+
throw new Error(`TT expects a tunedtensor.json behavior spec, not a full run request: ${loaded.path}`);
|
|
1587
1678
|
}
|
|
1588
1679
|
const input = loaded;
|
|
1589
1680
|
assertLocalRunInputReady(input.request);
|