Motivation
Google published Google-Cloud-AI/alphaevolve-on-googlecloud — a client SDK + examples for the managed AlphaEvolve service on Gemini Enterprise / Discovery Engine. It implements the same core loop as OpenEvolve (EVOLVE-BLOCK seed + metric-returning evaluator + weighted model ensemble), but generation and the program database run server-side on Google infra, behind gcloud auth + a Gemini Enterprise Engine ID, and it's Gemini-only.
OpenEvolve implements the same algorithm fully self-hosted (any OpenAI-compatible model, local vLLM, MAP-Elites diversity knobs). The two are conceptually identical but incompatible at three seams: the evaluator contract, the config schema, and the client/experiment entrypoint.
Goal: first-class, bidirectional interoperability, so a user can:
- (A) Run any AlphaEvolve example on OpenEvolve unchanged — no GCP project, no
gcloud auth, no Gemini lock-in.
- (B) Export an existing OpenEvolve program + config to the AlphaEvolve service and run it there directly.
We (the requesters) will own and maintain the compat layer and track upstream schema changes, so coupling to Google's SDK surface is an accepted, maintained cost.
The three incompatibilities (verified against the repo)
| Seam |
Google AlphaEvolve |
OpenEvolve |
| Evaluator input |
a candidate object: program_candidate["content"]["files"][0]["content"] → source string |
a file path (evaluate(program_path)) |
| Evaluator output |
AlphaEvolveProgramEvaluation wrapping AlphaEvolveEvaluationScore(metric=..., score=...); failure sentinel -1e12 |
a flat dict[str, float] |
| Config + entrypoint |
.env → create_experiment({run_settings, generation_settings}); AlphaEvolveClient → AlphaEvolveExperiment → run_controller_loop |
Config(llm/database/evaluation) → run_evolution(initial_program, evaluator, config) → EvolutionResult |
The seed program is already 100% compatible (identical # EVOLVE-BLOCK-START/END markers).
Refs: evaluator examples/circle_packing/src/evaluate.py, entrypoint examples/circle_packing/src/run_evolution.py, SDK src/alpha_evolve/ (client.py, experiment.py, controller.py, models.py, visualization.py).
Direction A — run AlphaEvolve examples on OpenEvolve
A1. Evaluator-contract adapter — openevolve/evaluator.py
Support the AE evaluator signature in addition to the current path→dict one. Detect the contract (by declared flag or by duck-typing the return), then:
- On input: wrap the candidate as
{"content": {"files": [{"content": code}]}} and pass that instead of a path.
- On output: flatten
AlphaEvolveProgramEvaluation/AlphaEvolveEvaluationScore → OE's {metric: score} dict (duck-type on .metric/.score, so Google's package need not be installed). Map every returned score into the metrics dict (so MAP-Elites feature_dimensions still work).
- Map the
-1e12 sentinel to OE's failure handling.
A2. Compat SDK shim — new openevolve/compat/alpha_evolve/
Provide drop-in classes with the AE signatures that run OE locally:
AlphaEvolveClient(project_id, location, collection, engine, assistant, base_url, ...) — accept-and-ignore GCP args (warn once); no auth.
AlphaEvolveExperiment(client, evaluator, max_programs_evaluated, parallel_evaluation=...) with .create_experiment(dict), .create_initial_program(src), .start_experiment(), .list_programs(params={"order_by": "<metric> desc"}) — internally build an OE Config and call run_evolution.
run_controller_loop(experiment) — async no-op wrapper (OE runs generation+eval in-process; there is no remote candidate queue to poll). list_programs reads from the OE archive/best.
- Provide compatible
AlphaEvolveProgramEvaluation / AlphaEvolveEvaluationScore types.
- Ship an importable
alpha_evolve alias package so from alpha_evolve.client import AlphaEvolveClient resolves to OE → examples run with only an import/config swap (or zero changes if alpha_evolve resolves to the shim).
A3. Config translation (inbound) — openevolve/config.py
Config.from_alphaevolve(env_path=None, experiment_dict=None):
MODEL / MODEL_1..N + _WEIGHT and generation_settings.models[{name,weight}] → Config.llm.models (name/weight); api_base/api_key come from OE side (local vLLM / OpenRouter) — this is the point of removing Google infra.
MAX_PROGRAMS_GENERATED|EVALUATED → iterations / max programs; run_settings.max_programs.
CONCURRENCY / WORKER_CONCURRENCY / PARALLEL_EVALUATION → evaluation.parallel_evaluations.
problem_description / instructions.md → OE prompt/system message.
A4. Scope
- In scope (v1): local-eval examples —
circle_packing, tsp, signal_processing.
- Out of scope (v1): remote/cloud evaluators —
adaptive_sort (Cloud Run), adaptive_sort_cpp, llm_fine_tuning (GKE + Ray GPU). Their evaluators shell out to Google-hosted infra; they run on OE only if the user provides equivalent local execution. Track as follow-ups.
Direction B — export an OpenEvolve program to the AlphaEvolve service
B1. Exporter — new openevolve/compat/export.py + Config.to_alphaevolve()
export_to_alphaevolve(initial_program, evaluator, config, out_dir) emits a ready-to-run AE example bundle mirroring the repo layout:
src/program.py — the OE seed, EVOLVE-BLOCK unchanged.
src/evaluate.py — the OE evaluator wrapped in the AE contract: read program_candidate["content"]["files"][0]["content"], run the OE scoring, return AlphaEvolveProgramEvaluation([AlphaEvolveEvaluationScore(metric, score), ...]), -1e12 on failure.
src/run_evolution.py — the AlphaEvolveClient/AlphaEvolveExperiment/run_controller_loop boilerplate.
example.env — from Config.to_alphaevolve(): MODEL_i/_WEIGHT from llm.models, MAX_PROGRAMS_*, CONCURRENCY/PARALLEL_EVALUATION; GCP fields (PROJECT_ID, GE_APP_ID, …) left as TODO placeholders for the user.
instructions.md — from the OE prompt/problem description.
B2. Documented lossy mappings (warn on export)
- OE MAP-Elites knobs (
num_islands, feature_dimensions, feature_bins, migration_*) have no AE equivalent — dropped with a warning (AE hides its search internals; only max_programs/concurrency/model weights are exposed).
- Non-Gemini models in
llm.models can't run on the AE service → warn/remap to a Gemini default.
- OE-only hooks (
evaluator_models, UCB bandit, guided-JSON, data_dump, preamble_source) are OE-side only → dropped on export.
Config mapping (both directions)
| OpenEvolve |
AlphaEvolve |
llm.models[{name, weight}] |
generation_settings.models[{name, weight}] / MODEL_i + _WEIGHT |
iterations / max programs |
run_settings.max_programs / MAX_PROGRAMS_EVALUATED |
evaluation.parallel_evaluations |
run_settings.concurrency / PARALLEL_EVALUATION / WORKER_CONCURRENCY |
| prompt / problem description |
problem_description / instructions.md |
database.{num_islands, feature_dimensions, feature_bins, migration_*} |
no equivalent (dropped on export) |
llm.models[].{api_base, api_key} |
no equivalent (AE = Gemini via service) |
Acceptance criteria
Files likely touched
openevolve/evaluator.py (A1), openevolve/config.py (A3, B1), openevolve/api.py (export entrypoint), new openevolve/compat/alpha_evolve/ (A2) and openevolve/compat/export.py (B1), docs + an examples/alphaevolve_interop/ walkthrough.
Links
Motivation
Google published
Google-Cloud-AI/alphaevolve-on-googlecloud— a client SDK + examples for the managed AlphaEvolve service on Gemini Enterprise / Discovery Engine. It implements the same core loop as OpenEvolve (EVOLVE-BLOCK seed + metric-returning evaluator + weighted model ensemble), but generation and the program database run server-side on Google infra, behindgcloudauth + a Gemini Enterprise Engine ID, and it's Gemini-only.OpenEvolve implements the same algorithm fully self-hosted (any OpenAI-compatible model, local vLLM, MAP-Elites diversity knobs). The two are conceptually identical but incompatible at three seams: the evaluator contract, the config schema, and the client/experiment entrypoint.
Goal: first-class, bidirectional interoperability, so a user can:
gcloud auth, no Gemini lock-in.We (the requesters) will own and maintain the compat layer and track upstream schema changes, so coupling to Google's SDK surface is an accepted, maintained cost.
The three incompatibilities (verified against the repo)
program_candidate["content"]["files"][0]["content"]→ source stringevaluate(program_path))AlphaEvolveProgramEvaluationwrappingAlphaEvolveEvaluationScore(metric=..., score=...); failure sentinel-1e12dict[str, float].env→create_experiment({run_settings, generation_settings});AlphaEvolveClient→AlphaEvolveExperiment→run_controller_loopConfig(llm/database/evaluation)→run_evolution(initial_program, evaluator, config)→EvolutionResultThe seed program is already 100% compatible (identical
# EVOLVE-BLOCK-START/ENDmarkers).Refs: evaluator
examples/circle_packing/src/evaluate.py, entrypointexamples/circle_packing/src/run_evolution.py, SDKsrc/alpha_evolve/(client.py,experiment.py,controller.py,models.py,visualization.py).Direction A — run AlphaEvolve examples on OpenEvolve
A1. Evaluator-contract adapter —
openevolve/evaluator.pySupport the AE evaluator signature in addition to the current path→dict one. Detect the contract (by declared flag or by duck-typing the return), then:
{"content": {"files": [{"content": code}]}}and pass that instead of a path.AlphaEvolveProgramEvaluation/AlphaEvolveEvaluationScore→ OE's{metric: score}dict (duck-type on.metric/.score, so Google's package need not be installed). Map every returned score into the metrics dict (so MAP-Elitesfeature_dimensionsstill work).-1e12sentinel to OE's failure handling.A2. Compat SDK shim — new
openevolve/compat/alpha_evolve/Provide drop-in classes with the AE signatures that run OE locally:
AlphaEvolveClient(project_id, location, collection, engine, assistant, base_url, ...)— accept-and-ignore GCP args (warn once); no auth.AlphaEvolveExperiment(client, evaluator, max_programs_evaluated, parallel_evaluation=...)with.create_experiment(dict),.create_initial_program(src),.start_experiment(),.list_programs(params={"order_by": "<metric> desc"})— internally build an OEConfigand callrun_evolution.run_controller_loop(experiment)— async no-op wrapper (OE runs generation+eval in-process; there is no remote candidate queue to poll).list_programsreads from the OE archive/best.AlphaEvolveProgramEvaluation/AlphaEvolveEvaluationScoretypes.alpha_evolvealias package sofrom alpha_evolve.client import AlphaEvolveClientresolves to OE → examples run with only an import/config swap (or zero changes ifalpha_evolveresolves to the shim).A3. Config translation (inbound) —
openevolve/config.pyConfig.from_alphaevolve(env_path=None, experiment_dict=None):MODEL/MODEL_1..N+_WEIGHTandgeneration_settings.models[{name,weight}]→Config.llm.models(name/weight);api_base/api_keycome from OE side (local vLLM / OpenRouter) — this is the point of removing Google infra.MAX_PROGRAMS_GENERATED|EVALUATED→iterations/ max programs;run_settings.max_programs.CONCURRENCY/WORKER_CONCURRENCY/PARALLEL_EVALUATION→evaluation.parallel_evaluations.problem_description/instructions.md→ OE prompt/system message.A4. Scope
circle_packing,tsp,signal_processing.adaptive_sort(Cloud Run),adaptive_sort_cpp,llm_fine_tuning(GKE + Ray GPU). Their evaluators shell out to Google-hosted infra; they run on OE only if the user provides equivalent local execution. Track as follow-ups.Direction B — export an OpenEvolve program to the AlphaEvolve service
B1. Exporter — new
openevolve/compat/export.py+Config.to_alphaevolve()export_to_alphaevolve(initial_program, evaluator, config, out_dir)emits a ready-to-run AE example bundle mirroring the repo layout:src/program.py— the OE seed, EVOLVE-BLOCK unchanged.src/evaluate.py— the OE evaluator wrapped in the AE contract: readprogram_candidate["content"]["files"][0]["content"], run the OE scoring, returnAlphaEvolveProgramEvaluation([AlphaEvolveEvaluationScore(metric, score), ...]),-1e12on failure.src/run_evolution.py— theAlphaEvolveClient/AlphaEvolveExperiment/run_controller_loopboilerplate.example.env— fromConfig.to_alphaevolve():MODEL_i/_WEIGHTfromllm.models,MAX_PROGRAMS_*,CONCURRENCY/PARALLEL_EVALUATION; GCP fields (PROJECT_ID,GE_APP_ID, …) left asTODOplaceholders for the user.instructions.md— from the OE prompt/problem description.B2. Documented lossy mappings (warn on export)
num_islands,feature_dimensions,feature_bins,migration_*) have no AE equivalent — dropped with a warning (AE hides its search internals; onlymax_programs/concurrency/model weights are exposed).llm.modelscan't run on the AE service → warn/remap to a Gemini default.evaluator_models, UCB bandit, guided-JSON,data_dump,preamble_source) are OE-side only → dropped on export.Config mapping (both directions)
llm.models[{name, weight}]generation_settings.models[{name, weight}]/MODEL_i+_WEIGHTiterations/ max programsrun_settings.max_programs/MAX_PROGRAMS_EVALUATEDevaluation.parallel_evaluationsrun_settings.concurrency/PARALLEL_EVALUATION/WORKER_CONCURRENCYproblem_description/instructions.mddatabase.{num_islands, feature_dimensions, feature_bins, migration_*}llm.models[].{api_base, api_key}Acceptance criteria
circle_packing,tsp,signal_processing) from the AE repo run end-to-end on OpenEvolve with no changes toprogram.pyorevaluate.py, and only a config/import swap (ideally zero, via thealpha_evolveshim) inrun_evolution.py.gcloud auth, or Gemini Enterprise required for Direction A; models come from the OEConfig(local/OpenRouter/OpenAI).export_to_alphaevolve(...)produces a bundle that runs on the real AlphaEvolve service after the user fillsPROJECT_ID/GE_APP_ID, with clear warnings for every dropped OE-only setting.export_to_alphaevolve→Config.from_alphaevolvereproduces an equivalent OE run (modulo the documented lossy fields).openevolve/compat/and does not change the default OE evaluator/config contract.Files likely touched
openevolve/evaluator.py(A1),openevolve/config.py(A3, B1),openevolve/api.py(export entrypoint), newopenevolve/compat/alpha_evolve/(A2) andopenevolve/compat/export.py(B1), docs + anexamples/alphaevolve_interop/walkthrough.Links