LLaMEA Minimal Example¶
This notebook shows a simple usage of LLaMEA to automatically generate and refine a Python-based optimization algorithm for a toy evaluation.
[ ]:
#this dependency is sometimes missed by poetry
!pip install swig
!pip install llamea==1.0.5
[1]:
# Cell 1: Imports
import os
import numpy as np
from llamea import LLaMEA, Gemini_LLM
Cell 1: Set up the LLM¶
If you haven’t already, set your OpenAI or other API key in your environment variables, e.g., export OPENAI_API_KEY="..."
or export GEMINI_API_KEY="...."
You can also use Gemini in most countries for free.
[2]:
from google.colab import userdata
api_key = userdata.get('GOOGLE_API_KEY_1') # <--- Make sure you add your Google API key via the Colab secrets panel
#api_key = os.getenv("GEMINI_API_KEY")
llm = Gemini_LLM(api_key, "gemini-2.0-flash")
Cell 2: Define an evaluation function for LLaMEA¶
The function must accept a “solution” argument, which contains code, a name, etc.
You parse solution.solution (the raw code), dynamically load it, and run it on your problem(s).
You then set_scores() to record how well it did.
We’ll define a simple example with a 1D quadratic function: f(x) = (x - 2)^2 We’ll ask the solution code to search for the minimum x in [-5, 5]. We’ll then return a score based on how close x is to 2. The closer, the higher the score.
[3]:
import re
import textwrap
import math
# We implement an exception to stop algorithms that try a too large budget (to prevent infinite loops).
class OverBudgetException(Exception):
"""The algorithm tried to do more evaluations than allowed."""
pass
def evaluate_simple(solution, explogger=None):
code_str = solution.code # The Python code the LLM generated
alg_name = solution.name
# We define our 1D search space: x in [-5, 5], budget=100
# We'll create a small function that the generated code should optimize.
def f(x):
# We only allow so many function calls
if f.call_count >= 100:
raise OverBudgetException("Budget exceeded.")
f.call_count += 1
return (x - 2.0)**2
f.call_count = 0
# Dynamically run the generated code
# The code is expected to define a class named alg_name, with __init__(budget, dim) and __call__(f).
# We'll create a safe execution context to run it.
safe_globals = {
"OverBudgetException": OverBudgetException,
"math": math,
"np": np,
}
local_env = {}
try:
exec(code_str, safe_globals, local_env)
except Exception as e:
# If there's an error in code, set the score to 0
solution.set_scores(0, feedback=f"Runtime/Syntax error: {e}")
return solution
# Instantiate the class with budget=100, dim=1
try:
AlgorithmClass = local_env[alg_name]
algo = AlgorithmClass(budget=100, dim=1)
except Exception as e:
solution.set_scores(0, feedback=f"Instantiation error: {e}")
return solution
# Now run the algorithm
best_f = math.inf
try:
best_f, best_x = algo(f)
except OverBudgetException:
# If over budget, we penalize heavily
best_f = 9999
# We'll convert it to a "score" where smaller f is better => we do `score = 1/(1 + best_f)`
# so that 0 => 1/1 => 1, big f => near 0
# Note: LLaMEA is optimizing by default! (bigger is better)
score = 1.0 / (1.0 + best_f)
# Provide feedback
feedback_str = f"Algorithm {alg_name} got score={score:.4f} (bigger is better)."
# Save the score to the solution object
solution.set_scores(score, feedback_str)
return solution
Cell 3: Create and run the LLaMEA search¶
We define a small prompt. The LLM will see how we want it to write code (like a class, with call). Then we let LLaMEA iterate a few times, generating and refining solutions.
[4]:
role_prompt = "You are an AI that generates Python optimization code."
task_prompt = textwrap.dedent("""\
Create a Python class named Optimize, with __init__(self, budget, dim),
and a __call__(self, func) method that tries to find x in [-5, 5] that minimizes func(x).
The function should return the tuple best_f, best_x (value best found and the location).
Implement an efficient algorithm for this task.
""")
# We'll use a small number of iterations for demonstration
es = LLaMEA(
f=evaluate_simple,
llm=llm,
n_parents=1,
n_offspring=1,
role_prompt=role_prompt,
task_prompt=task_prompt,
experiment_name="my-llamea-example",
elitism=True,
budget=3 # Try 3 iterations for a quick demo
)
best_solution = es.run()
print(f"Best found solution: {best_solution.name}, Score={best_solution.fitness:.4f}")
print(f"Generated code:\n{best_solution.code}")
print(f"Additional feedback: {best_solution.feedback}")
/usr/local/lib/python3.11/dist-packages/joblib/parallel.py:1383: UserWarning: The backend class 'SequentialBackend' does not support timeout. You have set 'timeout=3615' in Parallel but the 'timeout' parameter will not be used.
warnings.warn(
ERROR:tornado.access:503 POST /v1beta/models/gemini-2.0-flash:generateContent?%24alt=json%3Benum-encoding%3Dint (127.0.0.1) 404.79ms
Best found solution: Optimize, Score=0.0001
Generated code:
import numpy as np
class Optimize:
def __init__(self, budget=10000, dim=10):
self.budget = budget
self.dim = dim
self.f_opt = np.Inf
self.x_opt = None
def __call__(self, func):
# Initial guess
x = np.random.uniform(-5, 5, size=self.dim)
f = func(x)
self.f_opt = f
self.x_opt = x
for i in range(self.budget):
# Generate a neighbor by adding a small random perturbation
x_new = x + np.random.normal(0, 0.1, size=self.dim)
# Clip to stay within bounds
x_new = np.clip(x_new, -5, 5)
f_new = func(x_new)
# Accept if better
if f_new < f:
f = f_new
x = x_new
# Update best seen
if f < self.f_opt:
self.f_opt = f
self.x_opt = x
else:
# Random Restart to escape local optima
if np.random.rand() < 0.01:
x = np.random.uniform(-5, 5, size=self.dim)
f = func(x)
if f < self.f_opt:
self.f_opt = f
self.x_opt = x
return self.f_opt, self.x_opt
Additional feedback: Algorithm Optimize got score=0.0001 (bigger is better).