@tuned-tensor/local 0.2.9 → 0.3.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.
Files changed (82) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/README.md +84 -210
  3. package/dist/artifacts.d.ts +3 -4
  4. package/dist/artifacts.js +55 -33
  5. package/dist/artifacts.js.map +1 -1
  6. package/dist/compare.d.ts +1 -8
  7. package/dist/compare.js +1 -23
  8. package/dist/compare.js.map +1 -1
  9. package/dist/contracts.d.ts +59 -366
  10. package/dist/contracts.js +73 -224
  11. package/dist/contracts.js.map +1 -1
  12. package/dist/dataset.d.ts +2 -4
  13. package/dist/dataset.js +31 -125
  14. package/dist/dataset.js.map +1 -1
  15. package/dist/doctor.d.ts +2 -3
  16. package/dist/doctor.js +23 -161
  17. package/dist/doctor.js.map +1 -1
  18. package/dist/evaluation.d.ts +11 -71
  19. package/dist/evaluation.js +212 -572
  20. package/dist/evaluation.js.map +1 -1
  21. package/dist/huggingface-cache.d.ts +8 -7
  22. package/dist/huggingface-cache.js +16 -8
  23. package/dist/huggingface-cache.js.map +1 -1
  24. package/dist/index.d.ts +0 -10
  25. package/dist/index.js +203 -626
  26. package/dist/index.js.map +1 -1
  27. package/dist/local-project.d.ts +1 -11
  28. package/dist/local-project.js +33 -61
  29. package/dist/local-project.js.map +1 -1
  30. package/dist/model-registry.d.ts +3 -16
  31. package/dist/model-registry.js +76 -292
  32. package/dist/model-registry.js.map +1 -1
  33. package/dist/model-server.d.ts +1 -2
  34. package/dist/model-server.js +9 -18
  35. package/dist/model-server.js.map +1 -1
  36. package/dist/orchestrator.d.ts +11 -25
  37. package/dist/orchestrator.js +246 -566
  38. package/dist/orchestrator.js.map +1 -1
  39. package/dist/prefetch.d.ts +1 -5
  40. package/dist/prefetch.js +14 -19
  41. package/dist/prefetch.js.map +1 -1
  42. package/dist/process-runner.d.ts +10 -29
  43. package/dist/process-runner.js +63 -169
  44. package/dist/process-runner.js.map +1 -1
  45. package/dist/process-training.d.ts +0 -1
  46. package/dist/process-training.js +10 -87
  47. package/dist/process-training.js.map +1 -1
  48. package/dist/store.d.ts +1 -3
  49. package/dist/store.js +92 -290
  50. package/dist/store.js.map +1 -1
  51. package/docs/architecture.md +87 -152
  52. package/docs/spark.md +66 -97
  53. package/examples/dry-runner.json +14 -0
  54. package/examples/local-runner.json +8 -6
  55. package/examples/smoke-spec.json +41 -0
  56. package/package.json +6 -6
  57. package/training/local-runner/pyproject.toml +0 -5
  58. package/training/local-runner/src/evaluate.py +89 -234
  59. package/training/local-runner/src/model_contract.py +47 -0
  60. package/training/local-runner/src/prefetch.py +18 -4
  61. package/training/local-runner/src/serve.py +54 -115
  62. package/training/local-runner/src/sft_data.py +97 -0
  63. package/training/local-runner/src/train.py +146 -346
  64. package/training/local-runner/uv.lock +0 -1197
  65. package/dist/labeling-sanitize.d.ts +0 -31
  66. package/dist/labeling-sanitize.js +0 -158
  67. package/dist/labeling-sanitize.js.map +0 -1
  68. package/dist/labeling.d.ts +0 -155
  69. package/dist/labeling.js +0 -496
  70. package/dist/labeling.js.map +0 -1
  71. package/dist/openrouter.d.ts +0 -29
  72. package/dist/openrouter.js +0 -66
  73. package/dist/openrouter.js.map +0 -1
  74. package/dist/server.d.ts +0 -9
  75. package/dist/server.js +0 -211
  76. package/dist/server.js.map +0 -1
  77. package/docs/local-workflow-remediation-2026-07-13.md +0 -130
  78. package/docs/local-workflow-ux-review-2026-07-13.md +0 -458
  79. package/examples/dpo-preferences.jsonl +0 -2
  80. package/examples/dpo-run-request.json +0 -34
  81. package/examples/smoke-run-request.json +0 -34
  82. package/training/local-runner/src/train_dpo.py +0 -286
@@ -1,31 +0,0 @@
1
- /**
2
- * Secret/PII sanitization for labeling rows, ported from tuned-tensor-runs.
3
- * Even though tt-local runs on hardware the user controls, labeling sends row
4
- * content to OpenRouter — so secret-like content blocks the row and PII is
5
- * redacted before anything leaves the machine.
6
- */
7
- export type SanitizationStatus = "clean" | "redacted" | "blocked";
8
- export type SanitizationKind = "api_key" | "bearer_token" | "connection_string" | "credit_card" | "email" | "password" | "phone" | "private_key" | "ssn";
9
- export interface SanitizationFinding {
10
- kind: SanitizationKind;
11
- action: "redact" | "block";
12
- count: number;
13
- }
14
- export interface SanitizedText {
15
- text: string;
16
- status: SanitizationStatus;
17
- findings: SanitizationFinding[];
18
- }
19
- export interface SanitizedLabelingRow {
20
- input: string;
21
- output?: string;
22
- sanitizationStatus: SanitizationStatus;
23
- sanitizationFindings: SanitizationFinding[];
24
- sanitizationError?: string;
25
- }
26
- export declare function sanitizeText(text: string): SanitizedText;
27
- export declare function mergeSanitizationFindings(findings: readonly SanitizationFinding[]): SanitizationFinding[];
28
- export declare function sanitizeLabelingRow(row: {
29
- input: string;
30
- output?: string;
31
- }): SanitizedLabelingRow;
@@ -1,158 +0,0 @@
1
- /**
2
- * Secret/PII sanitization for labeling rows, ported from tuned-tensor-runs.
3
- * Even though tt-local runs on hardware the user controls, labeling sends row
4
- * content to OpenRouter — so secret-like content blocks the row and PII is
5
- * redacted before anything leaves the machine.
6
- */
7
- const BLOCK_PATTERNS = [
8
- {
9
- kind: "private_key",
10
- replacement: "[REDACTED_PRIVATE_KEY]",
11
- regex: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g,
12
- },
13
- {
14
- kind: "connection_string",
15
- replacement: "[REDACTED_CONNECTION_STRING]",
16
- regex: /\b(?:postgres(?:ql)?|mysql|mongodb(?:\+srv)?|redis):\/\/[^\s:/@]+:[^\s@]+@[^\s]+/gi,
17
- },
18
- {
19
- kind: "bearer_token",
20
- replacement: "Bearer [REDACTED_TOKEN]",
21
- regex: /\bBearer\s+[A-Za-z0-9._~+/=-]{20,}\b/g,
22
- },
23
- {
24
- kind: "api_key",
25
- replacement: "[REDACTED_API_KEY]",
26
- regex: /\b(?:sk-[A-Za-z0-9]{20,}|(?:tt|ghp|gho|github_pat|xox[baprs])_[A-Za-z0-9_=-]{20,}|(?:AKIA|ASIA)[A-Z0-9]{16}|AIza[0-9A-Za-z_-]{20,})\b/g,
27
- },
28
- {
29
- kind: "password",
30
- replacement: "$1 [REDACTED_SECRET]",
31
- regex: /\b((?:password|passwd|pwd|api[_-]?key|secret|token|access[_-]?token|refresh[_-]?token|client[_-]?secret)\s*[:=])\s*["']?[^"'\s,;]{8,}/gi,
32
- },
33
- ];
34
- const REDACT_PATTERNS = [
35
- {
36
- kind: "email",
37
- replacement: "[REDACTED_EMAIL]",
38
- regex: /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi,
39
- },
40
- {
41
- kind: "ssn",
42
- replacement: "[REDACTED_SSN]",
43
- regex: /\b\d{3}-\d{2}-\d{4}\b/g,
44
- },
45
- {
46
- kind: "phone",
47
- replacement: "[REDACTED_PHONE]",
48
- regex: /\b(?:\+?1[\s.-]?)?(?:\(?\d{3}\)?[\s.-]?)\d{3}[\s.-]?\d{4}\b/g,
49
- },
50
- ];
51
- function addFinding(findings, kind, action, count) {
52
- if (count <= 0)
53
- return;
54
- const key = `${kind}:${action}`;
55
- const existing = findings.get(key);
56
- findings.set(key, {
57
- kind,
58
- action,
59
- count: (existing?.count ?? 0) + count,
60
- });
61
- }
62
- function replacePattern(text, pattern, action, findings) {
63
- let count = 0;
64
- const next = text.replace(pattern.regex, (...args) => {
65
- count += 1;
66
- if (pattern.replacement.includes("$1") && typeof args[1] === "string") {
67
- return pattern.replacement.replace("$1", args[1]);
68
- }
69
- return pattern.replacement;
70
- });
71
- addFinding(findings, pattern.kind, action, count);
72
- return next;
73
- }
74
- function digitsOnly(value) {
75
- return value.replace(/\D/g, "");
76
- }
77
- function passesLuhn(value) {
78
- let sum = 0;
79
- let doubleDigit = false;
80
- for (let i = value.length - 1; i >= 0; i -= 1) {
81
- let digit = Number(value[i]);
82
- if (Number.isNaN(digit))
83
- return false;
84
- if (doubleDigit) {
85
- digit *= 2;
86
- if (digit > 9)
87
- digit -= 9;
88
- }
89
- sum += digit;
90
- doubleDigit = !doubleDigit;
91
- }
92
- return sum > 0 && sum % 10 === 0;
93
- }
94
- function redactCreditCards(text, findings) {
95
- let count = 0;
96
- const next = text.replace(/\b(?:\d[ -]*?){13,19}\b/g, (match) => {
97
- const digits = digitsOnly(match);
98
- if (digits.length < 13 || digits.length > 19 || !passesLuhn(digits)) {
99
- return match;
100
- }
101
- count += 1;
102
- return "[REDACTED_CARD]";
103
- });
104
- addFinding(findings, "credit_card", "redact", count);
105
- return next;
106
- }
107
- export function sanitizeText(text) {
108
- const findings = new Map();
109
- let sanitized = text;
110
- for (const pattern of BLOCK_PATTERNS) {
111
- sanitized = replacePattern(sanitized, pattern, "block", findings);
112
- }
113
- sanitized = redactCreditCards(sanitized, findings);
114
- for (const pattern of REDACT_PATTERNS) {
115
- sanitized = replacePattern(sanitized, pattern, "redact", findings);
116
- }
117
- const allFindings = Array.from(findings.values());
118
- const hasBlock = allFindings.some((finding) => finding.action === "block");
119
- return {
120
- text: sanitized,
121
- status: hasBlock
122
- ? "blocked"
123
- : allFindings.length > 0
124
- ? "redacted"
125
- : "clean",
126
- findings: allFindings,
127
- };
128
- }
129
- export function mergeSanitizationFindings(findings) {
130
- const merged = new Map();
131
- for (const finding of findings) {
132
- addFinding(merged, finding.kind, finding.action, finding.count);
133
- }
134
- return Array.from(merged.values());
135
- }
136
- export function sanitizeLabelingRow(row) {
137
- const input = sanitizeText(row.input);
138
- const output = row.output === undefined ? undefined : sanitizeText(row.output);
139
- const findings = mergeSanitizationFindings([
140
- ...input.findings,
141
- ...(output?.findings ?? []),
142
- ]);
143
- const status = input.status === "blocked" || output?.status === "blocked"
144
- ? "blocked"
145
- : input.status === "redacted" || output?.status === "redacted"
146
- ? "redacted"
147
- : "clean";
148
- return {
149
- input: input.text,
150
- ...(output !== undefined ? { output: output.text } : {}),
151
- sanitizationStatus: status,
152
- sanitizationFindings: findings,
153
- ...(status === "blocked"
154
- ? { sanitizationError: "Sensitive secret-like content was blocked" }
155
- : {}),
156
- };
157
- }
158
- //# sourceMappingURL=labeling-sanitize.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"labeling-sanitize.js","sourceRoot":"","sources":["../src/labeling-sanitize.ts"],"names":[],"mappings":"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"}
@@ -1,155 +0,0 @@
1
- /**
2
- * Local teacher-labeling job, ported from the tuned-tensor-runs labeling
3
- * workflow. Reads an unlabeled JSONL or CSV source, sanitizes each row, sends
4
- * pending rows to an OpenRouter teacher model under the spec's system message
5
- * (the same message the fine-tuned model will see at inference), and writes a
6
- * labeled {"input","output"} JSONL plus a job report under the artifact root.
7
- *
8
- * Unlike the eval judge there is no JSON output schema (the teacher's output
9
- * IS the training label, free text) and no heuristic fallback — a failed call
10
- * must surface as a failed row, never a fabricated label.
11
- */
12
- import type { LocalRunnerConfig } from "./contracts.js";
13
- import { type SanitizationFinding, type SanitizationStatus } from "./labeling-sanitize.js";
14
- import type { LocalRunReporter } from "./run-reporter.js";
15
- /** Per-row input cap; larger documents should be chunked upstream. */
16
- export declare const MAX_INPUT_CHARS = 32000;
17
- export declare const MAX_PARSE_ERRORS = 50;
18
- export interface UnlabeledRow {
19
- rowIndex: number;
20
- input: string;
21
- /** Present when the source row was already labeled (JSONL only). */
22
- output?: string;
23
- }
24
- export interface FailedUnlabeledRow {
25
- rowIndex: number;
26
- input: string;
27
- error: string;
28
- }
29
- export interface ParseResult {
30
- rows: UnlabeledRow[];
31
- failedRows: FailedUnlabeledRow[];
32
- errors: string[];
33
- }
34
- /**
35
- * Parse a JSONL source of {"input": string, "output"?: string} rows. Rows
36
- * that already carry an "output" skip the teacher and land directly as
37
- * labeled. Collects errors instead of throwing; callers reject the job when
38
- * `errors` is non-empty.
39
- */
40
- export declare function parseUnlabeledJsonl(text: string, maxRows: number): ParseResult;
41
- /**
42
- * Minimal RFC 4180 CSV reader (quoted fields, escaped quotes, CR/LF inside
43
- * quotes). tt-local deliberately avoids a CSV dependency; this covers the
44
- * upload formats the hosted labeling dialog accepts.
45
- */
46
- export declare function parseCsvRecords(text: string): {
47
- fields: string[];
48
- records: string[][];
49
- errors: string[];
50
- };
51
- /**
52
- * Parse a CSV source, taking `inputColumn` as the input text of each row.
53
- * The header row is required.
54
- */
55
- export declare function parseUnlabeledCsv(text: string, inputColumn: string, maxRows: number): ParseResult;
56
- /**
57
- * Defensive removal of `<think>` reasoning blocks so the training label is
58
- * only the teacher's final answer. Truncated output can leave a dangling
59
- * close tag; keep only what follows the last close tag in that case.
60
- */
61
- export declare function stripModelThinking(raw: string): string;
62
- /**
63
- * Map over items with bounded concurrency and optional minimum spacing
64
- * between call starts (global across workers).
65
- */
66
- export declare function mapWithPacing<T, R>(items: readonly T[], pacing: {
67
- concurrency: number;
68
- minIntervalMs: number;
69
- }, mapper: (item: T, index: number) => Promise<R>): Promise<R[]>;
70
- export interface TeacherOptions {
71
- model: string;
72
- apiKeyEnv: string;
73
- appName?: string;
74
- siteUrl?: string;
75
- maxTokens: number;
76
- temperature: number;
77
- maxAttempts: number;
78
- timeoutMs: number;
79
- }
80
- export interface TeacherLabelResult {
81
- output: string;
82
- promptTokens: number;
83
- completionTokens: number;
84
- latencyMs: number;
85
- }
86
- export declare function resolveTeacherOptions(config: LocalRunnerConfig, overrides?: {
87
- model?: string;
88
- }): TeacherOptions;
89
- export declare function labelRow(args: {
90
- systemMessage: string;
91
- input: string;
92
- teacher: TeacherOptions;
93
- }): Promise<TeacherLabelResult>;
94
- export type LabelingRowStatus = "labeled" | "failed" | "pending";
95
- export interface LabelingRowResult {
96
- row_index: number;
97
- input: string;
98
- output?: string;
99
- status: LabelingRowStatus;
100
- label_source?: "teacher" | "upload";
101
- error?: string;
102
- sanitization_status: SanitizationStatus;
103
- sanitization_findings: SanitizationFinding[];
104
- prompt_tokens: number;
105
- completion_tokens: number;
106
- }
107
- export interface LocalLabelingReport {
108
- job_id: string;
109
- status: "completed" | "failed" | "dry_run";
110
- source_path: string;
111
- source_format: "jsonl" | "csv";
112
- input_column?: string;
113
- teacher_model_id: string;
114
- row_count: number;
115
- labeled_count: number;
116
- prelabeled_count: number;
117
- failed_count: number;
118
- redacted_count: number;
119
- blocked_count: number;
120
- pending_count: number;
121
- prompt_tokens_total: number;
122
- completion_tokens_total: number;
123
- error?: string;
124
- artifact_uris: {
125
- labeled: string;
126
- rows: string;
127
- report: string;
128
- };
129
- created_at: string;
130
- completed_at: string;
131
- }
132
- export interface LocalLabelingResult {
133
- report: LocalLabelingReport;
134
- reportPath: string;
135
- artifactDir: string;
136
- labeledPath: string;
137
- rowsPath: string;
138
- }
139
- export interface RunLocalLabelingJobArgs {
140
- sourcePath: string;
141
- /** Inferred from the file extension when omitted. */
142
- format?: "jsonl" | "csv";
143
- /** Required for CSV sources. */
144
- inputColumn?: string;
145
- systemMessage: string;
146
- config: LocalRunnerConfig;
147
- /** Optional extra copy of the labeled JSONL (artifact copy is always written). */
148
- outputPath?: string;
149
- /** Teacher model override; falls back to labeling.model then llm.model. */
150
- model?: string;
151
- /** Parse and sanitize only; no teacher calls, no labeled.jsonl. */
152
- dryRun?: boolean;
153
- reporter?: LocalRunReporter;
154
- }
155
- export declare function runLocalLabelingJob(args: RunLocalLabelingJobArgs): Promise<LocalLabelingResult>;