Skip to content

Bidirectional interop with Google Cloud AlphaEvolve (run AE examples on OE, and export OE programs to the AE service) #468

Description

@codelion

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 .envcreate_experiment({run_settings, generation_settings}); AlphaEvolveClientAlphaEvolveExperimentrun_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|EVALUATEDiterations / max programs; run_settings.max_programs.
  • CONCURRENCY / WORKER_CONCURRENCY / PARALLEL_EVALUATIONevaluation.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

  • The three local-eval examples (circle_packing, tsp, signal_processing) from the AE repo run end-to-end on OpenEvolve with no changes to program.py or evaluate.py, and only a config/import swap (ideally zero, via the alpha_evolve shim) in run_evolution.py.
  • No GCP project, gcloud auth, or Gemini Enterprise required for Direction A; models come from the OE Config (local/OpenRouter/OpenAI).
  • export_to_alphaevolve(...) produces a bundle that runs on the real AlphaEvolve service after the user fills PROJECT_ID/GE_APP_ID, with clear warnings for every dropped OE-only setting.
  • Round-trip test: OE example → export_to_alphaevolveConfig.from_alphaevolve reproduces an equivalent OE run (modulo the documented lossy fields).
  • Compat layer is isolated under 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), new openevolve/compat/alpha_evolve/ (A2) and openevolve/compat/export.py (B1), docs + an examples/alphaevolve_interop/ walkthrough.

Links

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions