orizu 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +56 -9
- package/package.json +12 -2
- package/scripts/vendor-gepa-python.mjs +54 -0
- package/src/index.ts +6 -2
- package/vendor/orizu-gepa-python/manifest.json +9 -0
- package/vendor/orizu-gepa-python/pyproject.toml +16 -0
- package/vendor/orizu-gepa-python/src/orizu_gepa/__init__.py +19 -0
- package/vendor/orizu-gepa-python/src/orizu_gepa/cli.py +173 -0
- package/vendor/orizu-gepa-python/src/orizu_gepa/client.py +314 -0
- package/vendor/orizu-gepa-python/src/orizu_gepa/optimizer.py +1231 -0
- package/vendor/orizu-gepa-python/src/orizu_gepa/reflection.py +177 -0
- package/vendor/orizu-gepa-python/src/orizu_gepa/runner.py +207 -0
package/dist/index.js
CHANGED
|
@@ -1485,8 +1485,11 @@ function removeFlagWithValue(args, flag) {
|
|
|
1485
1485
|
return filtered;
|
|
1486
1486
|
}
|
|
1487
1487
|
function bundledOrizuGepaPythonPath() {
|
|
1488
|
-
const
|
|
1489
|
-
|
|
1488
|
+
const candidates = [
|
|
1489
|
+
fileURLToPath(new URL('../vendor/orizu-gepa-python/src', import.meta.url)),
|
|
1490
|
+
fileURLToPath(new URL('../../orizu-gepa-python/src', import.meta.url)),
|
|
1491
|
+
];
|
|
1492
|
+
return candidates.find(candidate => existsSync(candidate)) ?? null;
|
|
1490
1493
|
}
|
|
1491
1494
|
async function runGepaOptimization() {
|
|
1492
1495
|
const project = getArg('--project') || await resolveProjectSlug(null);
|
|
@@ -2664,6 +2667,47 @@ function readRunnerManifest(runnerDir) {
|
|
|
2664
2667
|
supports_body_kind: supportedBodyKinds,
|
|
2665
2668
|
};
|
|
2666
2669
|
}
|
|
2670
|
+
const RUNNER_TIMEOUT_MS = 120_000;
|
|
2671
|
+
const RUNNER_OUTPUT_MAX_BYTES = 2 * 1024 * 1024;
|
|
2672
|
+
const RUNNER_ARTIFACT_MAX_BYTES = 25 * 1024 * 1024;
|
|
2673
|
+
const RUNNER_ENV_ALLOWLIST = new Set([
|
|
2674
|
+
'PATH',
|
|
2675
|
+
'SystemRoot',
|
|
2676
|
+
'WINDIR',
|
|
2677
|
+
'HOME',
|
|
2678
|
+
'TMPDIR',
|
|
2679
|
+
'TEMP',
|
|
2680
|
+
'TMP',
|
|
2681
|
+
'LANG',
|
|
2682
|
+
'LC_ALL',
|
|
2683
|
+
'PYTHONPATH',
|
|
2684
|
+
'NODE_PATH',
|
|
2685
|
+
'ANTHROPIC_API_KEY',
|
|
2686
|
+
'OPENAI_API_KEY',
|
|
2687
|
+
'GEMINI_API_KEY',
|
|
2688
|
+
'GOOGLE_API_KEY',
|
|
2689
|
+
]);
|
|
2690
|
+
function runnerSubprocessEnv(inputPath, outputPath) {
|
|
2691
|
+
const env = {};
|
|
2692
|
+
for (const key of RUNNER_ENV_ALLOWLIST) {
|
|
2693
|
+
const value = process.env[key];
|
|
2694
|
+
if (value !== undefined) {
|
|
2695
|
+
env[key] = value;
|
|
2696
|
+
}
|
|
2697
|
+
}
|
|
2698
|
+
env.ORIZU_RUNNER_INPUT_PATH = inputPath;
|
|
2699
|
+
env.ORIZU_RUNNER_OUTPUT_PATH = outputPath;
|
|
2700
|
+
return env;
|
|
2701
|
+
}
|
|
2702
|
+
function boundedRunnerOutput(value) {
|
|
2703
|
+
if (!value)
|
|
2704
|
+
return '';
|
|
2705
|
+
const buffer = Buffer.isBuffer(value) ? value : Buffer.from(value);
|
|
2706
|
+
if (buffer.byteLength <= RUNNER_OUTPUT_MAX_BYTES) {
|
|
2707
|
+
return buffer.toString('utf8');
|
|
2708
|
+
}
|
|
2709
|
+
return `${buffer.subarray(0, RUNNER_OUTPUT_MAX_BYTES).toString('utf8')}\n[truncated]`;
|
|
2710
|
+
}
|
|
2667
2711
|
async function materializeRunnerVersion(runnerVersionId) {
|
|
2668
2712
|
const response = await authedFetch(`/api/cli/runner-versions/${encodeURIComponent(runnerVersionId)}/download`);
|
|
2669
2713
|
if (!response.ok) {
|
|
@@ -2672,7 +2716,12 @@ async function materializeRunnerVersion(runnerVersionId) {
|
|
|
2672
2716
|
const tempDir = mkdtempSync(join(tmpdir(), 'orizu-runner-version-'));
|
|
2673
2717
|
const zipPath = join(tempDir, 'runner.zip');
|
|
2674
2718
|
const runnerDir = join(tempDir, 'runner');
|
|
2675
|
-
|
|
2719
|
+
const zipBytes = new Uint8Array(await response.arrayBuffer());
|
|
2720
|
+
if (zipBytes.byteLength > RUNNER_ARTIFACT_MAX_BYTES) {
|
|
2721
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
2722
|
+
throw new Error(`Runner artifact exceeds ${RUNNER_ARTIFACT_MAX_BYTES} bytes`);
|
|
2723
|
+
}
|
|
2724
|
+
writeFileSync(zipPath, zipBytes);
|
|
2676
2725
|
const result = spawnSync('unzip', ['-q', zipPath, '-d', runnerDir], {
|
|
2677
2726
|
encoding: 'utf8',
|
|
2678
2727
|
});
|
|
@@ -2778,18 +2827,16 @@ async function runnersExec() {
|
|
|
2778
2827
|
}));
|
|
2779
2828
|
const result = spawnSync(manifest.command[0], manifest.command.slice(1), {
|
|
2780
2829
|
cwd: runnerDir,
|
|
2781
|
-
env:
|
|
2782
|
-
...process.env,
|
|
2783
|
-
ORIZU_RUNNER_INPUT_PATH: inputPath,
|
|
2784
|
-
ORIZU_RUNNER_OUTPUT_PATH: outputPath,
|
|
2785
|
-
},
|
|
2830
|
+
env: runnerSubprocessEnv(inputPath, outputPath),
|
|
2786
2831
|
encoding: 'utf8',
|
|
2832
|
+
maxBuffer: RUNNER_OUTPUT_MAX_BYTES,
|
|
2833
|
+
timeout: RUNNER_TIMEOUT_MS,
|
|
2787
2834
|
});
|
|
2788
2835
|
if (result.error) {
|
|
2789
2836
|
throw result.error;
|
|
2790
2837
|
}
|
|
2791
2838
|
if (result.status !== 0) {
|
|
2792
|
-
throw new Error(`Runner failed for row ${row.id} with exit code ${result.status}: ${sanitizeTerminalText(result.stderr || result.stdout
|
|
2839
|
+
throw new Error(`Runner failed for row ${row.id} with exit code ${result.status}: ${sanitizeTerminalText(boundedRunnerOutput(result.stderr || result.stdout))}`);
|
|
2793
2840
|
}
|
|
2794
2841
|
const runnerOutput = JSON.parse(readFileSync(outputPath, 'utf8'));
|
|
2795
2842
|
resultLines.push(JSON.stringify({
|
package/package.json
CHANGED
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orizu",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"orizu": "dist/index.js"
|
|
8
8
|
},
|
|
9
|
+
"files": [
|
|
10
|
+
"README.md",
|
|
11
|
+
"dist",
|
|
12
|
+
"scripts",
|
|
13
|
+
"src",
|
|
14
|
+
"tsconfig.json",
|
|
15
|
+
"vendor"
|
|
16
|
+
],
|
|
9
17
|
"scripts": {
|
|
10
|
-
"build": "tsc -p tsconfig.json"
|
|
18
|
+
"build": "tsc -p tsconfig.json",
|
|
19
|
+
"prepack": "node scripts/vendor-gepa-python.mjs",
|
|
20
|
+
"postpack": "node scripts/vendor-gepa-python.mjs --clean"
|
|
11
21
|
}
|
|
12
22
|
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { cpSync, existsSync, mkdirSync, rmSync } from 'node:fs'
|
|
2
|
+
import { dirname, resolve } from 'node:path'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
|
|
5
|
+
const scriptDir = dirname(fileURLToPath(import.meta.url))
|
|
6
|
+
const cliRoot = resolve(scriptDir, '..')
|
|
7
|
+
const repoRoot = resolve(cliRoot, '..', '..')
|
|
8
|
+
const sourceRoot = resolve(repoRoot, 'packages', 'orizu-gepa-python')
|
|
9
|
+
const vendorRoot = resolve(cliRoot, 'vendor', 'orizu-gepa-python')
|
|
10
|
+
const shouldClean = process.argv.includes('--clean')
|
|
11
|
+
const sourceSrc = resolve(sourceRoot, 'src')
|
|
12
|
+
const sourcePyproject = resolve(sourceRoot, 'pyproject.toml')
|
|
13
|
+
const sourceManifest = resolve(sourceRoot, 'manifest.json')
|
|
14
|
+
const vendoredSrc = resolve(vendorRoot, 'src')
|
|
15
|
+
const vendoredPyproject = resolve(vendorRoot, 'pyproject.toml')
|
|
16
|
+
const vendoredManifest = resolve(vendorRoot, 'manifest.json')
|
|
17
|
+
const hasSourcePackage = existsSync(sourceSrc)
|
|
18
|
+
&& existsSync(sourcePyproject)
|
|
19
|
+
&& existsSync(sourceManifest)
|
|
20
|
+
const hasVendoredPackage = existsSync(vendoredSrc)
|
|
21
|
+
&& existsSync(vendoredPyproject)
|
|
22
|
+
&& existsSync(vendoredManifest)
|
|
23
|
+
|
|
24
|
+
if (shouldClean) {
|
|
25
|
+
if (hasSourcePackage) {
|
|
26
|
+
rmSync(vendorRoot, { recursive: true, force: true })
|
|
27
|
+
}
|
|
28
|
+
process.exit(0)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!hasSourcePackage) {
|
|
32
|
+
if (hasVendoredPackage) {
|
|
33
|
+
process.exit(0)
|
|
34
|
+
}
|
|
35
|
+
throw new Error(`Unable to vendor orizu-gepa-python: source package not found at ${sourceRoot}`)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
rmSync(vendorRoot, { recursive: true, force: true })
|
|
39
|
+
mkdirSync(vendorRoot, { recursive: true })
|
|
40
|
+
cpSync(sourcePyproject, resolve(vendorRoot, 'pyproject.toml'))
|
|
41
|
+
cpSync(sourceManifest, resolve(vendorRoot, 'manifest.json'))
|
|
42
|
+
cpSync(sourceSrc, resolve(vendorRoot, 'src'), {
|
|
43
|
+
recursive: true,
|
|
44
|
+
filter: sourcePath => {
|
|
45
|
+
const normalizedPath = sourcePath.replace(/\\/g, '/')
|
|
46
|
+
return !normalizedPath.endsWith('/__pycache__')
|
|
47
|
+
&& !normalizedPath.includes('/__pycache__/')
|
|
48
|
+
&& !normalizedPath.endsWith('.pyc')
|
|
49
|
+
&& !normalizedPath.endsWith('.pyo')
|
|
50
|
+
&& !normalizedPath.endsWith('/.pytest_cache')
|
|
51
|
+
&& !normalizedPath.includes('/.pytest_cache/')
|
|
52
|
+
&& !normalizedPath.endsWith('/.DS_Store')
|
|
53
|
+
},
|
|
54
|
+
})
|
package/src/index.ts
CHANGED
|
@@ -2083,8 +2083,12 @@ function removeFlagWithValue(args: string[], flag: string): string[] {
|
|
|
2083
2083
|
}
|
|
2084
2084
|
|
|
2085
2085
|
function bundledOrizuGepaPythonPath(): string | null {
|
|
2086
|
-
const
|
|
2087
|
-
|
|
2086
|
+
const candidates = [
|
|
2087
|
+
fileURLToPath(new URL('../vendor/orizu-gepa-python/src', import.meta.url)),
|
|
2088
|
+
fileURLToPath(new URL('../../orizu-gepa-python/src', import.meta.url)),
|
|
2089
|
+
]
|
|
2090
|
+
|
|
2091
|
+
return candidates.find(candidate => existsSync(candidate)) ?? null
|
|
2088
2092
|
}
|
|
2089
2093
|
|
|
2090
2094
|
async function runGepaOptimization() {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "orizu.optimizer.v1",
|
|
3
|
+
"name": "orizu-gepa-text",
|
|
4
|
+
"description": "Orizu-owned text candidate optimizer with GEPA-style reflection and mandatory live event logging.",
|
|
5
|
+
"language": "python",
|
|
6
|
+
"command": ["python3", "-m", "orizu_gepa.cli"],
|
|
7
|
+
"optimizer_family": "gepa",
|
|
8
|
+
"candidate_kind": "text"
|
|
9
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "orizu-gepa"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Orizu-owned text prompt optimizer with GEPA-style reflection and mandatory live logging."
|
|
9
|
+
requires-python = ">=3.10"
|
|
10
|
+
dependencies = []
|
|
11
|
+
|
|
12
|
+
[project.scripts]
|
|
13
|
+
orizu-gepa = "orizu_gepa.cli:main"
|
|
14
|
+
|
|
15
|
+
[tool.setuptools.packages.find]
|
|
16
|
+
where = ["src"]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from .optimizer import (
|
|
2
|
+
Budget,
|
|
3
|
+
DatasetRow,
|
|
4
|
+
PromptContext,
|
|
5
|
+
RowEvaluation,
|
|
6
|
+
TextGepaConfig,
|
|
7
|
+
TextGepaResult,
|
|
8
|
+
optimize_text_candidate,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"Budget",
|
|
13
|
+
"DatasetRow",
|
|
14
|
+
"PromptContext",
|
|
15
|
+
"RowEvaluation",
|
|
16
|
+
"TextGepaConfig",
|
|
17
|
+
"TextGepaResult",
|
|
18
|
+
"optimize_text_candidate",
|
|
19
|
+
]
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import json
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from .client import OrizuClient, OrizuEventSink
|
|
9
|
+
from .optimizer import TextGepaConfig, optimize_loaded_text_candidate
|
|
10
|
+
from .reflection import reflect_with_provider
|
|
11
|
+
from .runner import make_candidate_runner, make_scorer_runner
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def positive_int(value: str) -> int:
|
|
15
|
+
parsed = int(value)
|
|
16
|
+
if parsed <= 0:
|
|
17
|
+
raise argparse.ArgumentTypeError("must be positive")
|
|
18
|
+
return parsed
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def read_text_arg(value: str | None) -> str | None:
|
|
22
|
+
if value is None:
|
|
23
|
+
return None
|
|
24
|
+
if value.startswith("@"):
|
|
25
|
+
return Path(value[1:]).read_text()
|
|
26
|
+
path = Path(value)
|
|
27
|
+
if path.exists():
|
|
28
|
+
return path.read_text()
|
|
29
|
+
return value
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def read_json_object_arg(value: str | None, flag_name: str) -> dict[str, Any] | None:
|
|
33
|
+
text = read_text_arg(value)
|
|
34
|
+
if text is None:
|
|
35
|
+
return None
|
|
36
|
+
parsed = json.loads(text)
|
|
37
|
+
if not isinstance(parsed, dict):
|
|
38
|
+
raise RuntimeError(f"{flag_name} must be a JSON object")
|
|
39
|
+
return parsed
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def main() -> None:
|
|
43
|
+
parser = argparse.ArgumentParser(prog="orizu-gepa")
|
|
44
|
+
parser.add_argument("--project", required=True)
|
|
45
|
+
parser.add_argument("--optimizer-version-id", required=True)
|
|
46
|
+
parser.add_argument("--candidate-version-id", required=True)
|
|
47
|
+
parser.add_argument("--runner-version-id", required=True)
|
|
48
|
+
parser.add_argument("--candidate-runner-dir", required=True)
|
|
49
|
+
parser.add_argument("--scorer-version-id", required=True)
|
|
50
|
+
parser.add_argument("--scorer-runner-version-id", required=True)
|
|
51
|
+
parser.add_argument("--scorer-runner-dir", required=True)
|
|
52
|
+
parser.add_argument("--dataset-version-id", required=True)
|
|
53
|
+
parser.add_argument("--split-set-id", required=True)
|
|
54
|
+
parser.add_argument("--train-split", default="train")
|
|
55
|
+
parser.add_argument("--val-split", default="validation")
|
|
56
|
+
parser.add_argument("--budget", default="light", choices=["auto", "light", "medium", "high"])
|
|
57
|
+
parser.add_argument("--max-iterations", type=positive_int, default=3)
|
|
58
|
+
parser.add_argument("--minibatch-size", type=positive_int, default=3)
|
|
59
|
+
parser.add_argument(
|
|
60
|
+
"--candidate-selection-strategy",
|
|
61
|
+
default=TextGepaConfig.candidate_selection_strategy,
|
|
62
|
+
choices=["pareto", "current_best", "epsilon_greedy"],
|
|
63
|
+
)
|
|
64
|
+
parser.add_argument("--epsilon", type=float, default=TextGepaConfig.epsilon)
|
|
65
|
+
parser.add_argument("--disable-evaluation-cache", action="store_true")
|
|
66
|
+
parser.add_argument("--max-metric-calls", type=positive_int)
|
|
67
|
+
parser.add_argument("--max-full-evals", type=positive_int)
|
|
68
|
+
parser.add_argument("--reflection-model", default=TextGepaConfig.reflection_model)
|
|
69
|
+
parser.add_argument("--reflection-temperature", type=float)
|
|
70
|
+
parser.add_argument("--reflection-prompt-template")
|
|
71
|
+
parser.add_argument("--reflection-provider-settings")
|
|
72
|
+
parser.add_argument("--objective", default=TextGepaConfig.objective)
|
|
73
|
+
parser.add_argument("--seed", type=int, default=0)
|
|
74
|
+
parser.add_argument("--auto-promote", action="store_true")
|
|
75
|
+
parser.add_argument("--promotion-label")
|
|
76
|
+
parser.add_argument("--log-row-snapshots", action="store_true")
|
|
77
|
+
parser.add_argument("--metadata", default="{}")
|
|
78
|
+
args = parser.parse_args()
|
|
79
|
+
|
|
80
|
+
metadata = json.loads(args.metadata)
|
|
81
|
+
if not isinstance(metadata, dict):
|
|
82
|
+
raise RuntimeError("--metadata must be a JSON object")
|
|
83
|
+
|
|
84
|
+
config = TextGepaConfig(
|
|
85
|
+
budget=args.budget,
|
|
86
|
+
max_iterations=args.max_iterations,
|
|
87
|
+
minibatch_size=args.minibatch_size,
|
|
88
|
+
candidate_selection_strategy=args.candidate_selection_strategy,
|
|
89
|
+
epsilon=args.epsilon,
|
|
90
|
+
max_metric_calls=args.max_metric_calls,
|
|
91
|
+
max_full_evals=args.max_full_evals,
|
|
92
|
+
reflection_model=args.reflection_model,
|
|
93
|
+
reflection_temperature=args.reflection_temperature,
|
|
94
|
+
reflection_prompt_template=read_text_arg(args.reflection_prompt_template),
|
|
95
|
+
reflection_provider_settings=read_json_object_arg(args.reflection_provider_settings, "--reflection-provider-settings") or {},
|
|
96
|
+
objective=args.objective,
|
|
97
|
+
seed=args.seed,
|
|
98
|
+
auto_promote=args.auto_promote,
|
|
99
|
+
promotion_label=args.promotion_label,
|
|
100
|
+
cache_evaluations=not args.disable_evaluation_cache,
|
|
101
|
+
log_row_snapshots=args.log_row_snapshots,
|
|
102
|
+
)
|
|
103
|
+
client = OrizuClient.from_env()
|
|
104
|
+
prompt_context, trainset = client.fetch_exec_context(
|
|
105
|
+
prompt_version_id=args.candidate_version_id,
|
|
106
|
+
runner_version_id=args.runner_version_id,
|
|
107
|
+
dataset_version_id=args.dataset_version_id,
|
|
108
|
+
split_set_id=args.split_set_id,
|
|
109
|
+
split=args.train_split,
|
|
110
|
+
)
|
|
111
|
+
_, valset = client.fetch_exec_context(
|
|
112
|
+
prompt_version_id=args.candidate_version_id,
|
|
113
|
+
runner_version_id=args.runner_version_id,
|
|
114
|
+
dataset_version_id=args.dataset_version_id,
|
|
115
|
+
split_set_id=args.split_set_id,
|
|
116
|
+
split=args.val_split,
|
|
117
|
+
)
|
|
118
|
+
scorer_context, _ = client.fetch_scorer_exec_context(
|
|
119
|
+
scorer_version_id=args.scorer_version_id,
|
|
120
|
+
runner_version_id=args.scorer_runner_version_id,
|
|
121
|
+
dataset_version_id=args.dataset_version_id,
|
|
122
|
+
split_set_id=args.split_set_id,
|
|
123
|
+
split=args.val_split,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
run_id = client.start_run(
|
|
127
|
+
project=args.project,
|
|
128
|
+
optimizer_version_id=args.optimizer_version_id,
|
|
129
|
+
prompt_version_id=args.candidate_version_id,
|
|
130
|
+
scorer_version_id=args.scorer_version_id,
|
|
131
|
+
dataset_version_id=args.dataset_version_id,
|
|
132
|
+
split_set_id=args.split_set_id,
|
|
133
|
+
train_split=args.train_split,
|
|
134
|
+
validation_split=args.val_split,
|
|
135
|
+
metadata={
|
|
136
|
+
**metadata,
|
|
137
|
+
"optimizer_package": "orizu-gepa-python",
|
|
138
|
+
"optimizer_family": "gepa",
|
|
139
|
+
"mode": "text-candidate",
|
|
140
|
+
"inference_lm": prompt_context.provider_settings.get("model"),
|
|
141
|
+
"reflection_lm": config.reflection_model,
|
|
142
|
+
"scorer_lm": scorer_context.provider_settings.get("model"),
|
|
143
|
+
"dataset_size": len(trainset) + len(valset),
|
|
144
|
+
"train_count": len(trainset),
|
|
145
|
+
"validation_count": len(valset),
|
|
146
|
+
},
|
|
147
|
+
)
|
|
148
|
+
print(f"[orizu-gepa] started optimization run {run_id}", flush=True)
|
|
149
|
+
|
|
150
|
+
result = optimize_loaded_text_candidate(
|
|
151
|
+
run_id=run_id,
|
|
152
|
+
prompt_context=prompt_context,
|
|
153
|
+
scorer_context=scorer_context,
|
|
154
|
+
trainset=trainset,
|
|
155
|
+
valset=valset,
|
|
156
|
+
candidate_runner=make_candidate_runner(Path(args.candidate_runner_dir), run_id),
|
|
157
|
+
scorer_runner=make_scorer_runner(Path(args.scorer_runner_dir), run_id),
|
|
158
|
+
reflector=reflect_with_provider,
|
|
159
|
+
event_sink=OrizuEventSink(client, run_id, fail_on_log_error=config.fail_on_log_error),
|
|
160
|
+
config=config,
|
|
161
|
+
)
|
|
162
|
+
print(json.dumps({
|
|
163
|
+
"optimization_run_id": result.run_id,
|
|
164
|
+
"best_candidate_id": result.best_candidate_id,
|
|
165
|
+
"best_score": result.best_score,
|
|
166
|
+
"seed_score": result.seed_score,
|
|
167
|
+
"promoted_prompt_version_id": result.promoted_prompt_version_id,
|
|
168
|
+
"budget": result.budget.to_payload(),
|
|
169
|
+
}))
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
if __name__ == "__main__":
|
|
173
|
+
main()
|