openpond-sdk 0.12.1 → 0.12.3
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/LEARNING.md +16 -0
- package/dist/advanced-refiner-evaluations.js +5 -5
- package/dist/candidate-evaluations.js +4 -4
- package/dist/{chunk-VSRTJDVB.js → chunk-36WJTS5V.js} +3 -3
- package/dist/{chunk-O5ARJVT5.js → chunk-77N3QEIL.js} +2 -2
- package/dist/{chunk-WNH4DOEC.js → chunk-BFR3VC25.js} +16 -285
- package/dist/chunk-BFR3VC25.js.map +7 -0
- package/dist/{chunk-DBRRQASP.js → chunk-BSK3VLM3.js} +2 -2
- package/dist/{chunk-B7VYE7YQ.js → chunk-CTVKI3BV.js} +2 -2
- package/dist/{chunk-7AZDNZP6.js → chunk-CWXM57QR.js} +350 -87
- package/dist/chunk-CWXM57QR.js.map +7 -0
- package/dist/chunk-FY7NHCEH.js +255 -0
- package/dist/chunk-FY7NHCEH.js.map +7 -0
- package/dist/{chunk-YSKUXQ2N.js → chunk-G53MA5XX.js} +3 -3
- package/dist/{chunk-AV5JV26B.js → chunk-G6Y6CQYV.js} +2 -2
- package/dist/{chunk-ENLQCKY6.js → chunk-K5WRVSOL.js} +5 -5
- package/dist/{chunk-OEPYLZXK.js → chunk-MLPPSCDQ.js} +2 -2
- package/dist/{chunk-7GYXC2AI.js → chunk-QEIT5VXJ.js} +2 -2
- package/dist/{chunk-L5PQPAU6.js → chunk-QTJQIHDZ.js} +5 -2
- package/dist/{chunk-L5PQPAU6.js.map → chunk-QTJQIHDZ.js.map} +2 -2
- package/dist/{chunk-YVFERCUC.js → chunk-TMUAKJWX.js} +71 -2
- package/dist/chunk-TMUAKJWX.js.map +7 -0
- package/dist/{chunk-D4WTE6ZA.js → chunk-TSMGMA6R.js} +2 -2
- package/dist/{chunk-VOL3WES2.js → chunk-UPS52OPZ.js} +10 -165
- package/dist/chunk-UPS52OPZ.js.map +7 -0
- package/dist/{chunk-MLFKQ7E7.js → chunk-VY5AFE7A.js} +2 -2
- package/dist/{chunk-WVISXXIL.js → chunk-XYQD4LDI.js} +2 -2
- package/dist/{chunk-DG5CRENU.js → chunk-YUKV7RCD.js} +2 -2
- package/dist/{chunk-7WUJBFCH.js → chunk-ZJ3H3VS7.js} +18 -1
- package/dist/chunk-ZJ3H3VS7.js.map +7 -0
- package/dist/connected-evidence.js +10 -10
- package/dist/dataset-workspaces.js +51 -14
- package/dist/dataset-workspaces.js.map +3 -3
- package/dist/experiment-evaluation-schedules.js +13 -13
- package/dist/experiment-improvements.js +5 -5
- package/dist/experiments.js +17 -13
- package/dist/index.js +19 -19
- package/dist/model-starter-catalog.js +5 -5
- package/dist/model-starters.js +5 -5
- package/dist/model-taskset-runs.js +1 -1
- package/dist/post-training.js +4 -4
- package/dist/taskset-drafts.js +16 -16
- package/dist/taskset-packages.js +14 -14
- package/dist/training-bundle.js +161 -25
- package/dist/training-bundle.js.map +4 -4
- package/dist/training.js +11 -5
- package/dist/types/packages/sdk/src/candidate-evaluation-client.d.ts +9 -0
- package/dist/types/packages/sdk/src/candidate-evaluation-client.d.ts.map +1 -1
- package/dist/types/packages/sdk/src/candidate-evaluations.d.ts +6 -0
- package/dist/types/packages/sdk/src/candidate-evaluations.d.ts.map +1 -1
- package/dist/types/packages/sdk/src/dataset-preparation-client.d.ts +45 -0
- package/dist/types/packages/sdk/src/dataset-preparation-client.d.ts.map +1 -1
- package/dist/types/packages/sdk/src/dataset-preparation-contracts.d.ts +56 -0
- package/dist/types/packages/sdk/src/dataset-preparation-contracts.d.ts.map +1 -1
- package/dist/types/packages/sdk/src/dataset-preparation-source-coverage.d.ts +31 -0
- package/dist/types/packages/sdk/src/dataset-preparation-source-coverage.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/dataset-workspaces.d.ts +1 -0
- package/dist/types/packages/sdk/src/dataset-workspaces.d.ts.map +1 -1
- package/dist/types/packages/sdk/src/experiment-client.d.ts +33 -0
- package/dist/types/packages/sdk/src/experiment-client.d.ts.map +1 -1
- package/dist/types/packages/sdk/src/experiment-contracts.d.ts +12 -0
- package/dist/types/packages/sdk/src/experiment-contracts.d.ts.map +1 -1
- package/dist/types/packages/sdk/src/experiment-evaluation-schedules.d.ts +21 -0
- package/dist/types/packages/sdk/src/experiment-evaluation-schedules.d.ts.map +1 -1
- package/dist/types/packages/sdk/src/experiment-run-contracts.d.ts +3 -0
- package/dist/types/packages/sdk/src/experiment-run-contracts.d.ts.map +1 -1
- package/dist/types/packages/sdk/src/experiment-run-details.d.ts +15 -0
- package/dist/types/packages/sdk/src/experiment-run-details.d.ts.map +1 -1
- package/dist/types/packages/sdk/src/harness-experiment-policy.d.ts +17 -0
- package/dist/types/packages/sdk/src/harness-experiment-policy.d.ts.map +1 -1
- package/dist/types/packages/sdk/src/managed-training-preparation.d.ts +3 -1
- package/dist/types/packages/sdk/src/managed-training-preparation.d.ts.map +1 -1
- package/dist/types/packages/sdk/src/model-taskset-runs-contracts.d.ts +12 -0
- package/dist/types/packages/sdk/src/model-taskset-runs-contracts.d.ts.map +1 -1
- package/dist/types/packages/sdk/src/model-taskset-runs.d.ts +12 -0
- package/dist/types/packages/sdk/src/model-taskset-runs.d.ts.map +1 -1
- package/dist/types/packages/sdk/src/post-training.d.ts +15 -0
- package/dist/types/packages/sdk/src/post-training.d.ts.map +1 -1
- package/dist/types/packages/sdk/src/training-bundle-contracts.d.ts +4 -0
- package/dist/types/packages/sdk/src/training-bundle-contracts.d.ts.map +1 -1
- package/dist/types/packages/sdk/src/training-bundle.d.ts +4 -0
- package/dist/types/packages/sdk/src/training-bundle.d.ts.map +1 -1
- package/dist/types/packages/sdk/src/training-qualification-preparation.d.ts +364 -0
- package/dist/types/packages/sdk/src/training-qualification-preparation.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/training.d.ts +161 -0
- package/dist/types/packages/sdk/src/training.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-7AZDNZP6.js.map +0 -7
- package/dist/chunk-7WUJBFCH.js.map +0 -7
- package/dist/chunk-PGBFI5HC.js +0 -98
- package/dist/chunk-PGBFI5HC.js.map +0 -7
- package/dist/chunk-VOL3WES2.js.map +0 -7
- package/dist/chunk-WNH4DOEC.js.map +0 -7
- package/dist/chunk-YVFERCUC.js.map +0 -7
- /package/dist/{chunk-VSRTJDVB.js.map → chunk-36WJTS5V.js.map} +0 -0
- /package/dist/{chunk-O5ARJVT5.js.map → chunk-77N3QEIL.js.map} +0 -0
- /package/dist/{chunk-DBRRQASP.js.map → chunk-BSK3VLM3.js.map} +0 -0
- /package/dist/{chunk-B7VYE7YQ.js.map → chunk-CTVKI3BV.js.map} +0 -0
- /package/dist/{chunk-YSKUXQ2N.js.map → chunk-G53MA5XX.js.map} +0 -0
- /package/dist/{chunk-AV5JV26B.js.map → chunk-G6Y6CQYV.js.map} +0 -0
- /package/dist/{chunk-ENLQCKY6.js.map → chunk-K5WRVSOL.js.map} +0 -0
- /package/dist/{chunk-OEPYLZXK.js.map → chunk-MLPPSCDQ.js.map} +0 -0
- /package/dist/{chunk-7GYXC2AI.js.map → chunk-QEIT5VXJ.js.map} +0 -0
- /package/dist/{chunk-D4WTE6ZA.js.map → chunk-TSMGMA6R.js.map} +0 -0
- /package/dist/{chunk-MLFKQ7E7.js.map → chunk-VY5AFE7A.js.map} +0 -0
- /package/dist/{chunk-WVISXXIL.js.map → chunk-XYQD4LDI.js.map} +0 -0
- /package/dist/{chunk-DG5CRENU.js.map → chunk-YUKV7RCD.js.map} +0 -0
package/dist/training-bundle.js
CHANGED
|
@@ -1,32 +1,37 @@
|
|
|
1
1
|
import {
|
|
2
|
+
prepareImportedTasksetPackage,
|
|
2
3
|
projectLearningBatchGraders
|
|
3
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-FY7NHCEH.js";
|
|
4
5
|
import {
|
|
6
|
+
projectPortableTaskRecord,
|
|
5
7
|
resolvePortableTasksetRewardExecution
|
|
6
8
|
} from "./chunk-ROBAX5TN.js";
|
|
7
9
|
import {
|
|
8
10
|
TasksetSchema,
|
|
9
11
|
computeTasksetHash
|
|
10
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-CWXM57QR.js";
|
|
11
13
|
import {
|
|
12
14
|
LearningBatchDatasetSourceRefSchema,
|
|
13
|
-
MAX_TASKSET_PACKAGE_BYTES
|
|
15
|
+
MAX_TASKSET_PACKAGE_BYTES,
|
|
16
|
+
decodeTasksetPackageFile,
|
|
17
|
+
validateTasksetPackage
|
|
14
18
|
} from "./chunk-FHCSDXIA.js";
|
|
15
19
|
import "./chunk-2U54EOXJ.js";
|
|
16
20
|
import {
|
|
17
21
|
TRAINING_EVALUATION_SOURCE_PATH,
|
|
18
22
|
TrainingEvaluationSourceSchema,
|
|
19
23
|
assertTrainingEvaluationIsolation,
|
|
24
|
+
deterministicTrainingRewardSource,
|
|
20
25
|
parseAndVerifyTrainingInputArtifactUpload,
|
|
21
26
|
parseAndVerifyTrainingJobSubmission,
|
|
22
27
|
trainingEvaluationSourceRef,
|
|
23
28
|
trainingInputArtifactUploadHash,
|
|
24
29
|
trainingJobSubmissionHash
|
|
25
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-TMUAKJWX.js";
|
|
26
31
|
import {
|
|
27
32
|
TrainingHandoffOriginSchema
|
|
28
|
-
} from "./chunk-
|
|
29
|
-
import "./chunk-
|
|
33
|
+
} from "./chunk-MLPPSCDQ.js";
|
|
34
|
+
import "./chunk-G53MA5XX.js";
|
|
30
35
|
import {
|
|
31
36
|
HarnessSourceSelectionSchema,
|
|
32
37
|
createAgentSnapshot,
|
|
@@ -35,8 +40,8 @@ import {
|
|
|
35
40
|
validateHarnessSourcePackage
|
|
36
41
|
} from "./chunk-DUKW3R7O.js";
|
|
37
42
|
import "./chunk-KAE7AMYE.js";
|
|
38
|
-
import "./chunk-
|
|
39
|
-
import "./chunk-
|
|
43
|
+
import "./chunk-QTJQIHDZ.js";
|
|
44
|
+
import "./chunk-ZJ3H3VS7.js";
|
|
40
45
|
import "./chunk-CK3ONRRC.js";
|
|
41
46
|
import "./chunk-TCHAWJMB.js";
|
|
42
47
|
import "./chunk-3KXDH6OB.js";
|
|
@@ -51,7 +56,7 @@ import {
|
|
|
51
56
|
} from "./chunk-COPVBJPL.js";
|
|
52
57
|
|
|
53
58
|
// src/training-bundle.ts
|
|
54
|
-
import { compileBoundGraders } from "@openpond/evals/rewards";
|
|
59
|
+
import { compileBoundGraders as compileBoundGraders2 } from "@openpond/evals/rewards";
|
|
55
60
|
import { verifyLearningTextAsset as verifyLearningTextAsset3 } from "@openpond/evals/learning";
|
|
56
61
|
|
|
57
62
|
// src/training-bundle-contracts.ts
|
|
@@ -106,6 +111,7 @@ var TrainingEngineBindingSchema = z.object({
|
|
|
106
111
|
}).strict();
|
|
107
112
|
var HarnessRunManifestContentSchema = z.object({
|
|
108
113
|
schemaVersion: z.literal("openpond.harnessRunManifest.v1"),
|
|
114
|
+
executionMode: z.literal("qualification").optional(),
|
|
109
115
|
id: ReleaseIdSchema,
|
|
110
116
|
harnessRelease: ImmutableReleaseRefSchema,
|
|
111
117
|
datasetRelease: ImmutableReleaseRefSchema,
|
|
@@ -139,6 +145,7 @@ var HarnessRunManifestSchema = HarnessRunManifestContentSchema.extend({
|
|
|
139
145
|
}).strict();
|
|
140
146
|
var ResolvedTrainingBundleContentSchema = z.object({
|
|
141
147
|
schemaVersion: z.literal("openpond.resolvedTrainingBundle.v1"),
|
|
148
|
+
executionMode: z.literal("qualification").optional(),
|
|
142
149
|
projection: z.literal("trainer"),
|
|
143
150
|
harnessRelease: ImmutableReleaseRefSchema,
|
|
144
151
|
datasetRelease: ImmutableReleaseRefSchema,
|
|
@@ -354,6 +361,13 @@ async function prepareManagedTrainingSubmission(raw) {
|
|
|
354
361
|
const { project, recipe, taskset, approval } = input;
|
|
355
362
|
const manifest = HarnessRunManifestSchema.parse(input.manifest);
|
|
356
363
|
const bundle = ResolvedTrainingBundleManifestSchema.parse(input.bundleManifest);
|
|
364
|
+
const qualification = input.executionMode === "qualification";
|
|
365
|
+
if (manifest.executionMode !== input.executionMode || bundle.executionMode !== input.executionMode) {
|
|
366
|
+
throw new Error("Managed submission execution mode differs from its immutable bundle.");
|
|
367
|
+
}
|
|
368
|
+
if (qualification && (input.evaluationSource || input.resumeFrom || input.rewardSource.kind !== "deterministic")) {
|
|
369
|
+
throw new Error("Qualification requires the original learner, deterministic rewards, and no evaluation source.");
|
|
370
|
+
}
|
|
357
371
|
const { contentHash: manifestHash, ...manifestContent } = manifest;
|
|
358
372
|
const { contentHash: bundleHash, ...bundleContent } = bundle;
|
|
359
373
|
if (contentHash(manifestContent) !== manifestHash || contentHash(bundleContent) !== bundleHash || manifest.resolvedBundleHash !== bundleHash || contentHash(manifest.harnessRelease) !== contentHash(bundle.harnessRelease) || contentHash(manifest.datasetRelease) !== contentHash(bundle.datasetRelease) || contentHash(manifest.evidenceSets) !== contentHash(bundle.evidenceSetRelease ? [bundle.evidenceSetRelease] : [])) {
|
|
@@ -372,14 +386,21 @@ async function prepareManagedTrainingSubmission(raw) {
|
|
|
372
386
|
if (input.idempotencyKey !== void 0)
|
|
373
387
|
z2.string().trim().min(16).max(191).parse(input.idempotencyKey);
|
|
374
388
|
const files = verifyFiles(bundle, input.files);
|
|
375
|
-
const evaluationSource = TrainingEvaluationSourceSchema.parse(input.evaluationSource);
|
|
389
|
+
const evaluationSource = qualification ? null : TrainingEvaluationSourceSchema.parse(input.evaluationSource);
|
|
376
390
|
const evaluationFile = files.find((file) => file.path === TRAINING_EVALUATION_SOURCE_PATH);
|
|
377
|
-
if (!evaluationFile || contentHash(JSON.parse(Buffer.from(evaluationFile.content, "base64").toString("utf8"))) !== contentHash(evaluationSource)) {
|
|
391
|
+
if (evaluationSource && (!evaluationFile || contentHash(JSON.parse(Buffer.from(evaluationFile.content, "base64").toString("utf8"))) !== contentHash(evaluationSource))) {
|
|
378
392
|
throw new Error("The evaluation source differs from the immutable training bundle.");
|
|
379
393
|
}
|
|
380
|
-
|
|
394
|
+
if (qualification && (evaluationFile || files.some((file) => file.path === "dataset/train.json") || !files.some((file) => file.path === "dataset/qualification.json") || !files.some((file) => file.path === "qualification-source.json"))) {
|
|
395
|
+
throw new Error("Qualification requires its dedicated dataset and no training/evaluation datasets.");
|
|
396
|
+
}
|
|
397
|
+
if (!qualification && files.some((file) => file.path === "dataset/qualification.json" || file.path === "qualification-source.json")) {
|
|
398
|
+
throw new Error("Qualification datasets cannot be prepared as training.");
|
|
399
|
+
}
|
|
400
|
+
const evaluation = evaluationSource ? await trainingEvaluationSourceRef(evaluationSource) : null;
|
|
381
401
|
const payload = {
|
|
382
402
|
schemaVersion: "openpond.managedRlPortableSubmission.v1",
|
|
403
|
+
...qualification ? { executionMode: "qualification" } : {},
|
|
383
404
|
...input.origin ? { origin: TrainingHandoffOriginSchema.parse(input.origin) } : {},
|
|
384
405
|
sourceRunRef: `openpond:model-run:${manifest.id}`,
|
|
385
406
|
name: `OpenPond Managed \xB7 ${project.id}`.slice(0, 191),
|
|
@@ -393,8 +414,8 @@ async function prepareManagedTrainingSubmission(raw) {
|
|
|
393
414
|
modelImprovementQualification: input.modelImprovementQualification ?? null,
|
|
394
415
|
recipe,
|
|
395
416
|
resolvedBundle: { manifest: bundle, files },
|
|
396
|
-
validationTasks: evaluationSource
|
|
397
|
-
validationAssets: evaluationSource
|
|
417
|
+
validationTasks: evaluationSource?.tasks ?? [],
|
|
418
|
+
validationAssets: evaluationSource?.assets ?? []
|
|
398
419
|
};
|
|
399
420
|
const artifactContent = {
|
|
400
421
|
schemaVersion: "openpond.trainingInputArtifactUpload.v2",
|
|
@@ -424,18 +445,19 @@ async function prepareManagedTrainingSubmission(raw) {
|
|
|
424
445
|
taskset,
|
|
425
446
|
tasksetRelease: { id: taskset.id, contentHash: taskset.contentHash },
|
|
426
447
|
dataset: bundle.datasetRelease,
|
|
427
|
-
evaluation,
|
|
448
|
+
...evaluation ? { evaluation } : {},
|
|
428
449
|
evidenceSets: bundle.evidenceSetRelease ? [bundle.evidenceSetRelease] : []
|
|
429
450
|
},
|
|
430
451
|
job: {
|
|
431
452
|
kind: "policy_optimize",
|
|
453
|
+
...qualification ? { executionMode: "qualification" } : {},
|
|
432
454
|
baseModel,
|
|
433
455
|
recipe,
|
|
434
456
|
rewardSource: input.rewardSource,
|
|
435
457
|
resumeFrom: input.resumeFrom
|
|
436
458
|
},
|
|
437
459
|
requestedCapabilities: [
|
|
438
|
-
{ id: "managed_rl.policy.grpo", version: "1", required: true },
|
|
460
|
+
{ id: qualification ? "managed_rl.policy.qualification" : "managed_rl.policy.grpo", version: "1", required: true },
|
|
439
461
|
{
|
|
440
462
|
id: `managed_rl.rollouts.${manifest.runtimeTarget.placement}`,
|
|
441
463
|
version: "1",
|
|
@@ -734,10 +756,114 @@ function asset(input) {
|
|
|
734
756
|
};
|
|
735
757
|
}
|
|
736
758
|
|
|
759
|
+
// src/training-qualification-preparation.ts
|
|
760
|
+
import { createRewardBinding, createRewardRelease, compileBoundGraders } from "@openpond/evals/rewards";
|
|
761
|
+
import { LearningTextAssetSchema, sealLearningContent } from "@openpond/evals/learning";
|
|
762
|
+
async function prepareOrdinaryTasksetQualification(input) {
|
|
763
|
+
const source = validateTasksetPackage(input.package);
|
|
764
|
+
if (source.modelResources || source.learningResources || !source.taskset.tasks.length) {
|
|
765
|
+
throw new Error("Qualification requires a nonempty ordinary Taskset package.");
|
|
766
|
+
}
|
|
767
|
+
if (source.taskset.tasks.some((task) => task.privilegedContextRef !== null || task.artifactRefs.some((asset2) => asset2.visibility !== "policy"))) {
|
|
768
|
+
throw new Error("Qualification runtime requires private targets in expectedOutput and policy-only task assets.");
|
|
769
|
+
}
|
|
770
|
+
const rewards = source.taskset.graders.map((grader) => {
|
|
771
|
+
const { id, version, weight: _weight, hardGate: _gate, rewardEligible: _eligible, privileged: _private, taskIds: _tasks, ...implementation } = grader;
|
|
772
|
+
const revision = Number(version);
|
|
773
|
+
if (!Number.isSafeInteger(revision) || revision < 1 || String(revision) !== version || implementation.kind === "model_judge" || implementation.kind === "human") {
|
|
774
|
+
throw new Error("Qualification requires deterministic graders with canonical integer versions.");
|
|
775
|
+
}
|
|
776
|
+
return createRewardRelease({
|
|
777
|
+
schemaVersion: "openpond.rewardRelease.v1",
|
|
778
|
+
id: `qualification-${contentHash({ source: source.contentHash, id }).slice(0, 40)}`,
|
|
779
|
+
revision,
|
|
780
|
+
name: id,
|
|
781
|
+
description: "Exact ordinary package grader for no-update qualification.",
|
|
782
|
+
implementation,
|
|
783
|
+
rawScore: { minimum: 0, maximum: 1 },
|
|
784
|
+
assets: implementation.kind === "custom_verifier" ? [implementation.verifierRef] : []
|
|
785
|
+
});
|
|
786
|
+
});
|
|
787
|
+
const binding = createRewardBinding({
|
|
788
|
+
schemaVersion: "openpond.rewardBinding.v1",
|
|
789
|
+
id: `qualification-${source.contentHash.slice(0, 40)}`,
|
|
790
|
+
revision: 1,
|
|
791
|
+
sources: source.taskset.graders.map((grader, index) => ({
|
|
792
|
+
graderId: grader.id,
|
|
793
|
+
...grader.taskIds ? { taskIds: grader.taskIds } : {},
|
|
794
|
+
reward: { id: rewards[index].id, revision: rewards[index].revision, contentHash: rewards[index].contentHash },
|
|
795
|
+
role: grader.rewardEligible ? "training" : "evaluation",
|
|
796
|
+
normalization: { kind: "identity" },
|
|
797
|
+
weight: grader.weight,
|
|
798
|
+
required: true,
|
|
799
|
+
hardGate: grader.hardGate,
|
|
800
|
+
privileged: grader.privileged,
|
|
801
|
+
fixtureRefs: []
|
|
802
|
+
})),
|
|
803
|
+
aggregation: "weighted_mean",
|
|
804
|
+
unscorable: "exclude_optional_require_all_required"
|
|
805
|
+
}, rewards);
|
|
806
|
+
if (!binding.sources.some((item) => item.role === "training" && item.weight > 0) || contentHash(compileBoundGraders(binding, rewards)) !== contentHash(source.taskset.graders)) {
|
|
807
|
+
throw new Error("Qualification must preserve an executable positively weighted source grader set.");
|
|
808
|
+
}
|
|
809
|
+
const verifierIds = new Set(rewards.flatMap((reward) => reward.assets.map((asset2) => asset2.id)));
|
|
810
|
+
const verifierAssets = source.files.filter((file) => verifierIds.has(file.asset.id)).map((file) => LearningTextAssetSchema.parse(sealLearningContent({
|
|
811
|
+
schemaVersion: "openpond.learningTextAsset.v1",
|
|
812
|
+
id: file.asset.id,
|
|
813
|
+
revision: 1,
|
|
814
|
+
asset: file.asset,
|
|
815
|
+
text: new TextDecoder("utf-8", { fatal: true }).decode(decodeTasksetPackageFile(file))
|
|
816
|
+
})));
|
|
817
|
+
const { taskset } = prepareImportedTasksetPackage({
|
|
818
|
+
package: source,
|
|
819
|
+
profileId: input.modelProject.id,
|
|
820
|
+
name: source.taskset.id,
|
|
821
|
+
createdAt: input.modelProject.updatedAt
|
|
822
|
+
});
|
|
823
|
+
const taskAssets = new Set(taskset.tasks.flatMap((task) => (task.assets ?? []).map((asset2) => asset2.artifactRef)));
|
|
824
|
+
const tasksetAssetBytes = new Map(source.files.filter((file) => taskAssets.has(file.asset.path)).map((file) => [file.asset.path, decodeTasksetPackageFile(file)]));
|
|
825
|
+
const tasksetRef = { id: source.taskset.id, revision: source.taskset.revision, contentHash: source.taskset.contentHash };
|
|
826
|
+
const rewardExecution = { binding, rewards };
|
|
827
|
+
const bundle = buildTasksetTrainingBundle({
|
|
828
|
+
...input,
|
|
829
|
+
taskset,
|
|
830
|
+
executionMode: "qualification",
|
|
831
|
+
qualificationSource: source,
|
|
832
|
+
tasksetRelease: { id: tasksetRef.id, contentHash: tasksetRef.contentHash },
|
|
833
|
+
rewardExecution,
|
|
834
|
+
verifierAssets,
|
|
835
|
+
tasksetAssetBytes,
|
|
836
|
+
approval: { approvalHash: input.approval.approvalHash, approvedAt: input.approval.approvedAt, maximumSpendUsd: input.approval.maximumSpendUsd }
|
|
837
|
+
});
|
|
838
|
+
const recipe = input.modelProject.trainingSetup.recipe;
|
|
839
|
+
if (!recipe || recipe.method !== "grpo") throw new Error("Qualification requires a pinned GRPO rollout recipe.");
|
|
840
|
+
const prepared = await prepareManagedTrainingSubmission({
|
|
841
|
+
executionMode: "qualification",
|
|
842
|
+
project: input.modelProject,
|
|
843
|
+
manifest: bundle.manifest,
|
|
844
|
+
bundleManifest: bundle.resolvedBundleManifest,
|
|
845
|
+
taskset: tasksetRef,
|
|
846
|
+
recipe,
|
|
847
|
+
files: [...bundle.assets].map(([path, bytes2]) => ({ ...bundle.resolvedBundleManifest.files.find((file) => file.path === path), encoding: "base64", content: Buffer.from(bytes2).toString("base64") })),
|
|
848
|
+
rewardSource: await deterministicTrainingRewardSource({ graders: source.taskset.graders, rewardExecution }),
|
|
849
|
+
resumeFrom: null,
|
|
850
|
+
approval: { approvalHash: input.approval.approvalHash, maximumSpendUsd: input.approval.maximumSpendUsd, retentionDays: input.approval.retentionDays, region: input.approval.region },
|
|
851
|
+
...input.idempotencyKey ? { idempotencyKey: input.idempotencyKey } : {}
|
|
852
|
+
});
|
|
853
|
+
return { ...prepared, bundle };
|
|
854
|
+
}
|
|
855
|
+
|
|
737
856
|
// src/training-bundle.ts
|
|
738
857
|
function buildTasksetTrainingBundle(input) {
|
|
739
858
|
const { taskset, modelProject, harnessRelease, tasksetRelease } = input;
|
|
740
859
|
const setup = modelProject.trainingSetup;
|
|
860
|
+
const qualification = input.executionMode === "qualification";
|
|
861
|
+
if (qualification && input.evaluationSource) throw new Error("Qualification does not consume an independent evaluation source.");
|
|
862
|
+
const qualificationSource = qualification ? validateTasksetPackage(input.qualificationSource) : null;
|
|
863
|
+
if (!qualification && input.qualificationSource) throw new Error("Qualification sources cannot be used for training.");
|
|
864
|
+
if (qualificationSource && (qualificationSource.modelResources || qualificationSource.learningResources || contentHash(taskset.tasks.map(projectPortableTaskRecord)) !== contentHash(qualificationSource.taskset.tasks) || releasedRefHash(input.tasksetRelease) !== releasedRefHash(qualificationSource.taskset))) {
|
|
865
|
+
throw new Error("Qualification must preserve its ordinary source release and complete task population.");
|
|
866
|
+
}
|
|
741
867
|
const releasedHarness = ImmutableReleaseRefSchema.parse(harnessRelease);
|
|
742
868
|
const releasedTaskset = ImmutableReleaseRefSchema.parse(tasksetRelease);
|
|
743
869
|
void input.openpondRelease;
|
|
@@ -748,7 +874,7 @@ function buildTasksetTrainingBundle(input) {
|
|
|
748
874
|
"Taskset authoring state changed after its release was selected."
|
|
749
875
|
);
|
|
750
876
|
}
|
|
751
|
-
if (!setup.baseModel?.revision || !setup.baseModel.tokenizerRevision || !setup.baseModel.chatTemplateHash || !setup.recipe || !setup.tasksetRef || setup.tasksetRef.id !== taskset.id || setup.tasksetRef.contentHash !== taskset.contentHash) {
|
|
877
|
+
if (!setup.baseModel?.revision || !setup.baseModel.tokenizerRevision || !setup.baseModel.chatTemplateHash || !setup.recipe || !setup.tasksetRef || setup.tasksetRef.id !== (qualification ? tasksetRelease.id : taskset.id) || setup.tasksetRef.contentHash !== (qualification ? tasksetRelease.contentHash : taskset.contentHash)) {
|
|
752
878
|
throw new Error(
|
|
753
879
|
"Model Run must bind an exact Taskset, Model revision, tokenizer, chat template, and Recipe."
|
|
754
880
|
);
|
|
@@ -763,6 +889,7 @@ function buildTasksetTrainingBundle(input) {
|
|
|
763
889
|
})
|
|
764
890
|
};
|
|
765
891
|
const assets = /* @__PURE__ */ new Map();
|
|
892
|
+
if (qualificationSource) addJsonAsset(assets, "qualification-source.json", qualificationSource);
|
|
766
893
|
if (input.evaluationSource) {
|
|
767
894
|
const evaluation = TrainingEvaluationSourceSchema.parse(input.evaluationSource);
|
|
768
895
|
if (contentHash(evaluation.taskset) !== contentHash(setup.evaluationTasksetRef)) {
|
|
@@ -770,7 +897,7 @@ function buildTasksetTrainingBundle(input) {
|
|
|
770
897
|
}
|
|
771
898
|
assertTrainingEvaluationIsolation(taskset.tasks.filter((task) => task.split === "train"), evaluation.tasks);
|
|
772
899
|
assets.set(TRAINING_EVALUATION_SOURCE_PATH, new TextEncoder().encode(canonicalJson(evaluation)));
|
|
773
|
-
} else if (setup.evaluationTasksetRef) {
|
|
900
|
+
} else if (!qualification && setup.evaluationTasksetRef) {
|
|
774
901
|
throw new Error("The prepared Model requires its pinned evaluation source bytes.");
|
|
775
902
|
}
|
|
776
903
|
const harnessSource = input.harnessSource ? input.harnessSource.schemaVersion === "openpond.harnessPolicySourcePackage.v1" ? validateHarnessPolicySourcePackage(input.harnessSource, releasedHarness) : validateHarnessSourcePackage(input.harnessSource, releasedHarness) : null;
|
|
@@ -794,11 +921,14 @@ function buildTasksetTrainingBundle(input) {
|
|
|
794
921
|
sourcePackageHash: harnessSource?.contentHash ?? null
|
|
795
922
|
}));
|
|
796
923
|
const rewardExecution = resolvePortableTasksetRewardExecution(taskset, input.rewardExecution);
|
|
924
|
+
if (qualificationSource && (!rewardExecution || contentHash(compileBoundGraders2(rewardExecution.binding, rewardExecution.rewards)) !== contentHash(qualificationSource.taskset.graders) || qualificationSource.taskset.graders.some((grader) => grader.kind === "model_judge" || grader.kind === "human"))) {
|
|
925
|
+
throw new Error("Qualification requires the source package's exact deterministic graders.");
|
|
926
|
+
}
|
|
797
927
|
if (rewardExecution) {
|
|
798
928
|
const verifierAssets = input.verifierAssets ?? [];
|
|
799
929
|
const references = [
|
|
800
930
|
...rewardExecution.rewards.flatMap((reward) => reward.assets),
|
|
801
|
-
...
|
|
931
|
+
...compileBoundGraders2(rewardExecution.binding, rewardExecution.rewards).flatMap((grader) => grader.kind === "custom_verifier" ? [grader.verifierRef] : grader.kind === "model_judge" ? [grader.rubricRef] : [])
|
|
802
932
|
];
|
|
803
933
|
const expected = new Set(references.map((reference) => reference.id));
|
|
804
934
|
if (new Set(verifierAssets.map((asset2) => asset2.id)).size !== verifierAssets.length || new Set(verifierAssets.map((asset2) => asset2.asset.path)).size !== verifierAssets.length || verifierAssets.some((asset2) => !expected.has(asset2.id))) throw new Error("Unexpected or duplicate private verifier asset.");
|
|
@@ -813,7 +943,7 @@ function buildTasksetTrainingBundle(input) {
|
|
|
813
943
|
}
|
|
814
944
|
addJsonAsset(assets, "environment.json", {
|
|
815
945
|
schemaVersion: "openpond.harnessEnvironment.v1",
|
|
816
|
-
environment: taskset.environment,
|
|
946
|
+
environment: qualification ? { ...taskset.environment, metadata: { ...taskset.environment.metadata, policySystemPrompt: taskset.objective } } : taskset.environment,
|
|
817
947
|
capabilities: taskset.capabilities,
|
|
818
948
|
policy: taskset.policy,
|
|
819
949
|
outputContract: taskset.metadata.tasksetOutputContract?.mode === "text" ? null : taskset.metadata.tasksetOutputContract ?? null
|
|
@@ -830,11 +960,11 @@ function buildTasksetTrainingBundle(input) {
|
|
|
830
960
|
capabilities: taskset.capabilities,
|
|
831
961
|
connectedAppScopes: taskset.policy.connectedAppScopes
|
|
832
962
|
});
|
|
833
|
-
const trainTasks = taskset.tasks.filter((task) => task.split === "train");
|
|
963
|
+
const trainTasks = qualification ? taskset.tasks : taskset.tasks.filter((task) => task.split === "train");
|
|
834
964
|
if (trainTasks.length > 0) {
|
|
835
|
-
addJsonAsset(assets, "dataset/train.json", {
|
|
836
|
-
schemaVersion: "openpond.datasetSplit.v1",
|
|
837
|
-
split: "train",
|
|
965
|
+
addJsonAsset(assets, qualification ? "dataset/qualification.json" : "dataset/train.json", {
|
|
966
|
+
schemaVersion: qualification ? "openpond.qualificationDataset.v1" : "openpond.datasetSplit.v1",
|
|
967
|
+
...qualification ? {} : { split: "train" },
|
|
838
968
|
tasks: trainTasks
|
|
839
969
|
});
|
|
840
970
|
addTasksetAssets({
|
|
@@ -858,7 +988,7 @@ function buildTasksetTrainingBundle(input) {
|
|
|
858
988
|
taskset: releasedTaskset,
|
|
859
989
|
sourceRefs: taskset.sourceRefs,
|
|
860
990
|
datasetArtifact: taskset.datasetArtifact ?? null,
|
|
861
|
-
trainTasks
|
|
991
|
+
...qualification ? { executionMode: "qualification", tasks: trainTasks } : { trainTasks }
|
|
862
992
|
})
|
|
863
993
|
};
|
|
864
994
|
const evidenceSetRelease = approvedSignals.length > 0 ? {
|
|
@@ -873,6 +1003,7 @@ function buildTasksetTrainingBundle(input) {
|
|
|
873
1003
|
} : null;
|
|
874
1004
|
const bundleContent = ResolvedTrainingBundleContentSchema.parse({
|
|
875
1005
|
schemaVersion: "openpond.resolvedTrainingBundle.v1",
|
|
1006
|
+
...qualification ? { executionMode: "qualification" } : {},
|
|
876
1007
|
projection: "trainer",
|
|
877
1008
|
harnessRelease: releasedHarness,
|
|
878
1009
|
datasetRelease,
|
|
@@ -889,6 +1020,7 @@ function buildTasksetTrainingBundle(input) {
|
|
|
889
1020
|
});
|
|
890
1021
|
const manifestContent = HarnessRunManifestContentSchema.parse({
|
|
891
1022
|
schemaVersion: "openpond.harnessRunManifest.v1",
|
|
1023
|
+
...qualification ? { executionMode: "qualification" } : {},
|
|
892
1024
|
id: `manifest_${input.modelRunId}_${input.approval.approvalHash.slice(0, 16)}`,
|
|
893
1025
|
harnessRelease,
|
|
894
1026
|
datasetRelease,
|
|
@@ -961,6 +1093,9 @@ function addJsonAsset(assets, assetPath, value) {
|
|
|
961
1093
|
function bytes(value) {
|
|
962
1094
|
return Buffer.from(canonicalJson(value), "utf8");
|
|
963
1095
|
}
|
|
1096
|
+
function releasedRefHash(value) {
|
|
1097
|
+
return contentHash({ id: value.id, contentHash: value.contentHash });
|
|
1098
|
+
}
|
|
964
1099
|
export {
|
|
965
1100
|
AdamwOptimizerConfigSchema,
|
|
966
1101
|
ComputeTargetBindingSchema,
|
|
@@ -976,6 +1111,7 @@ export {
|
|
|
976
1111
|
createPolicyHarnessContext,
|
|
977
1112
|
materializeLearningBatchTaskset,
|
|
978
1113
|
prepareManagedTrainingSubmission,
|
|
1114
|
+
prepareOrdinaryTasksetQualification,
|
|
979
1115
|
prepareReviewedLearningBatch,
|
|
980
1116
|
scanAndRedactEvidence,
|
|
981
1117
|
withAuthoritativeRecipeHashes
|