fastevolve 0.3.2__tar.gz → 0.3.3__tar.gz
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.
- {fastevolve-0.3.2 → fastevolve-0.3.3}/PKG-INFO +10 -13
- {fastevolve-0.3.2 → fastevolve-0.3.3}/README.md +9 -12
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/llm_ensemble/__init__.py +2 -2
- fastevolve-0.3.3/fastevolve/llm_ensemble/ollama.py +100 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/pyproject.toml +1 -1
- {fastevolve-0.3.2 → fastevolve-0.3.3}/uv.lock +1 -1
- fastevolve-0.3.2/fastevolve/llm_ensemble/ollama.py +0 -45
- {fastevolve-0.3.2 → fastevolve-0.3.3}/.claude/settings.local.json +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/.gitignore +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/.python-version +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/__init__.py +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/checkpoint.py +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/config.py +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/controller.py +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/evaluator/__init__.py +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/evaluator/config.py +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/evaluator/evaluator.py +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/evaluator/result.py +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/llm_ensemble/anthropic_llm.py +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/llm_ensemble/base.py +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/llm_ensemble/config.py +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/llm_ensemble/ensemble.py +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/llm_ensemble/openai_llm.py +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/program_database/__init__.py +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/program_database/config.py +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/program_database/database.py +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/program_database/embedder.py +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/program_database/program.py +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/prompt_sampler/__init__.py +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/prompt_sampler/config.py +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/prompt_sampler/sampler.py +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/prompt_sampler/template_library.py +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/fastevolve/telemetry.py +0 -0
- {fastevolve-0.3.2 → fastevolve-0.3.3}/main.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastevolve
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: Minimal open-source AlphaEvolve: LLM-driven program evolution with MAP-Elites islands, cascade evaluation, and a local Ollama ensemble.
|
|
5
5
|
Project-URL: Homepage, https://github.com/tiagomonteiro0715/fastevolve
|
|
6
6
|
Project-URL: Repository, https://github.com/tiagomonteiro0715/fastevolve
|
|
@@ -179,22 +179,19 @@ print(result.best.code)
|
|
|
179
179
|
|
|
180
180
|
### Google Colab (with Ollama)
|
|
181
181
|
|
|
182
|
-
Ollama can run on Colab if you install it, start the daemon in the background, and pull a
|
|
182
|
+
Ollama can run on Colab if you install it, start the daemon in the background, and pull a model. Tested working on the free CPU runtime with a tiny model (`qwen2.5:0.5b`).
|
|
183
|
+
|
|
184
|
+
**On Colab Pro / Pro+**: switch to an A100 or L4 GPU runtime (`Runtime → Change runtime type → A100 GPU`) and swap the model for something bigger — `qwen2.5-coder:7b`, `llama3.1:8b`, or `gemma2:9b` all fit comfortably and produce dramatically better evolution candidates than `0.5b`. Pro+'s longer sessions (24 h) and background execution also mean you can leave a 1000-iteration run going overnight without keeping the tab open.
|
|
183
185
|
|
|
184
186
|
```python
|
|
185
|
-
# 1. Install ollama and fastevolve
|
|
187
|
+
# 1. Install ollama (zstd is required by the install script) and fastevolve via uv
|
|
188
|
+
!apt-get -qq install -y zstd
|
|
186
189
|
!curl -fsSL https://ollama.com/install.sh | sh
|
|
187
|
-
!pip install
|
|
188
|
-
|
|
189
|
-
# 2. Start the ollama daemon in the background
|
|
190
|
-
import subprocess, time
|
|
191
|
-
subprocess.Popen(["ollama", "serve"])
|
|
192
|
-
time.sleep(5) # give it a moment to bind to port 11434
|
|
193
|
-
|
|
194
|
-
# 3. Pull a small model (qwen2.5:0.5b is ~400 MB and fits the free CPU runtime)
|
|
195
|
-
!ollama pull qwen2.5:0.5b
|
|
190
|
+
!pip install uv
|
|
191
|
+
!uv pip install -q fastevolve
|
|
196
192
|
|
|
197
|
-
#
|
|
193
|
+
# 2. Run fastevolve — it starts the ollama daemon automatically with GPU-aware
|
|
194
|
+
# optimizations (flash attention, q8_0 KV cache, parallel decoding) when a GPU is detected.
|
|
198
195
|
from fastevolve import Config, Controller
|
|
199
196
|
from fastevolve.llm_ensemble import ModelConfig
|
|
200
197
|
|
|
@@ -149,22 +149,19 @@ print(result.best.code)
|
|
|
149
149
|
|
|
150
150
|
### Google Colab (with Ollama)
|
|
151
151
|
|
|
152
|
-
Ollama can run on Colab if you install it, start the daemon in the background, and pull a
|
|
152
|
+
Ollama can run on Colab if you install it, start the daemon in the background, and pull a model. Tested working on the free CPU runtime with a tiny model (`qwen2.5:0.5b`).
|
|
153
|
+
|
|
154
|
+
**On Colab Pro / Pro+**: switch to an A100 or L4 GPU runtime (`Runtime → Change runtime type → A100 GPU`) and swap the model for something bigger — `qwen2.5-coder:7b`, `llama3.1:8b`, or `gemma2:9b` all fit comfortably and produce dramatically better evolution candidates than `0.5b`. Pro+'s longer sessions (24 h) and background execution also mean you can leave a 1000-iteration run going overnight without keeping the tab open.
|
|
153
155
|
|
|
154
156
|
```python
|
|
155
|
-
# 1. Install ollama and fastevolve
|
|
157
|
+
# 1. Install ollama (zstd is required by the install script) and fastevolve via uv
|
|
158
|
+
!apt-get -qq install -y zstd
|
|
156
159
|
!curl -fsSL https://ollama.com/install.sh | sh
|
|
157
|
-
!pip install
|
|
158
|
-
|
|
159
|
-
# 2. Start the ollama daemon in the background
|
|
160
|
-
import subprocess, time
|
|
161
|
-
subprocess.Popen(["ollama", "serve"])
|
|
162
|
-
time.sleep(5) # give it a moment to bind to port 11434
|
|
163
|
-
|
|
164
|
-
# 3. Pull a small model (qwen2.5:0.5b is ~400 MB and fits the free CPU runtime)
|
|
165
|
-
!ollama pull qwen2.5:0.5b
|
|
160
|
+
!pip install uv
|
|
161
|
+
!uv pip install -q fastevolve
|
|
166
162
|
|
|
167
|
-
#
|
|
163
|
+
# 2. Run fastevolve — it starts the ollama daemon automatically with GPU-aware
|
|
164
|
+
# optimizations (flash attention, q8_0 KV cache, parallel decoding) when a GPU is detected.
|
|
168
165
|
from fastevolve import Config, Controller
|
|
169
166
|
from fastevolve.llm_ensemble import ModelConfig
|
|
170
167
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from .config import ModelConfig, EnsembleConfig
|
|
2
2
|
from .base import BaseLLM
|
|
3
|
-
from .ollama import OllamaLLM
|
|
3
|
+
from .ollama import OllamaLLM, start_ollama
|
|
4
4
|
from .ensemble import LLMEnsemble
|
|
5
5
|
|
|
6
|
-
__all__ = ["ModelConfig", "EnsembleConfig", "BaseLLM", "OllamaLLM", "LLMEnsemble"]
|
|
6
|
+
__all__ = ["ModelConfig", "EnsembleConfig", "BaseLLM", "OllamaLLM", "LLMEnsemble", "start_ollama"]
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
import subprocess
|
|
4
|
+
import time
|
|
5
|
+
from functools import cache
|
|
6
|
+
|
|
7
|
+
from ollama import Client, ResponseError
|
|
8
|
+
|
|
9
|
+
from ..telemetry import log
|
|
10
|
+
from .base import BaseLLM
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@cache
|
|
14
|
+
def _gpu_available() -> bool:
|
|
15
|
+
if not shutil.which("nvidia-smi"):
|
|
16
|
+
return False
|
|
17
|
+
try:
|
|
18
|
+
return subprocess.run(["nvidia-smi"], capture_output=True, timeout=2).returncode == 0
|
|
19
|
+
except Exception:
|
|
20
|
+
return False
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def start_ollama(host: str = "127.0.0.1:11434", *, wait: float = 5.0) -> None:
|
|
24
|
+
"""Start an ollama daemon with GPU-aware optimizations. No-op if one is already running."""
|
|
25
|
+
for prefix in ("http://", "https://"):
|
|
26
|
+
if host.startswith(prefix):
|
|
27
|
+
host = host[len(prefix):]
|
|
28
|
+
try:
|
|
29
|
+
Client(host=f"http://{host}").list()
|
|
30
|
+
log.info("[ollama] server already running on %s", host)
|
|
31
|
+
return
|
|
32
|
+
except Exception:
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
env = os.environ.copy()
|
|
36
|
+
env["OLLAMA_HOST"] = host
|
|
37
|
+
if _gpu_available():
|
|
38
|
+
env.setdefault("OLLAMA_FLASH_ATTENTION", "1")
|
|
39
|
+
env.setdefault("OLLAMA_KV_CACHE_TYPE", "q8_0")
|
|
40
|
+
env.setdefault("OLLAMA_NUM_PARALLEL", "4")
|
|
41
|
+
env.setdefault("OLLAMA_MAX_LOADED_MODELS", "2")
|
|
42
|
+
log.info("[ollama] starting server in [bold]GPU[/] mode (flash_attn, q8_0 kv-cache, parallel=4, max_loaded=2)")
|
|
43
|
+
else:
|
|
44
|
+
log.info("[ollama] starting server in [bold]CPU[/] mode")
|
|
45
|
+
|
|
46
|
+
path = shutil.which("ollama") or "/usr/local/bin/ollama"
|
|
47
|
+
subprocess.Popen([path, "serve"], env=env,
|
|
48
|
+
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
49
|
+
time.sleep(wait)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class OllamaLLM(BaseLLM):
|
|
53
|
+
def __init__(self, model_config, *, host: str = "http://localhost:11434", timeout: float = 600.0, system_prompt: str | None = None):
|
|
54
|
+
self.cfg = model_config
|
|
55
|
+
self.system_prompt = system_prompt
|
|
56
|
+
self.client = Client(host=host, timeout=timeout)
|
|
57
|
+
self._gpu = _gpu_available()
|
|
58
|
+
try:
|
|
59
|
+
self.client.list()
|
|
60
|
+
except Exception:
|
|
61
|
+
start_ollama(host=host)
|
|
62
|
+
self.client = Client(host=host, timeout=timeout)
|
|
63
|
+
log.info("[ollama] %s → [bold]%s[/] mode", self.cfg.name, "GPU" if self._gpu else "CPU")
|
|
64
|
+
self._ensure_model()
|
|
65
|
+
|
|
66
|
+
def _ensure_model(self):
|
|
67
|
+
try:
|
|
68
|
+
self.client.show(self.cfg.name)
|
|
69
|
+
except ResponseError:
|
|
70
|
+
log.info("[ollama] pulling [bold]%s[/]...", self.cfg.name)
|
|
71
|
+
self.client.pull(self.cfg.name)
|
|
72
|
+
|
|
73
|
+
def generate(self, prompt: str) -> str:
|
|
74
|
+
try:
|
|
75
|
+
return self._generate(prompt)
|
|
76
|
+
except Exception:
|
|
77
|
+
log.exception("ollama generate failed for model=%s", self.cfg.name)
|
|
78
|
+
raise
|
|
79
|
+
|
|
80
|
+
def _options(self) -> dict:
|
|
81
|
+
opts = {
|
|
82
|
+
"temperature": self.cfg.temperature,
|
|
83
|
+
"num_ctx": self.cfg.num_ctx,
|
|
84
|
+
"flash_attn": self.cfg.flash_attention and self._gpu,
|
|
85
|
+
"num_gpu": -1 if self._gpu else 0,
|
|
86
|
+
"num_thread": 0 if self._gpu else (os.cpu_count() or 4),
|
|
87
|
+
}
|
|
88
|
+
opts.update(self.cfg.options)
|
|
89
|
+
return opts
|
|
90
|
+
|
|
91
|
+
def _generate(self, prompt: str) -> str:
|
|
92
|
+
resp = self.client.generate(
|
|
93
|
+
model=self.cfg.name,
|
|
94
|
+
prompt=prompt,
|
|
95
|
+
system=self.system_prompt,
|
|
96
|
+
options=self._options(),
|
|
97
|
+
keep_alive="1h",
|
|
98
|
+
stream=False,
|
|
99
|
+
)
|
|
100
|
+
return resp.response
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "fastevolve"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.3"
|
|
4
4
|
description = "Minimal open-source AlphaEvolve: LLM-driven program evolution with MAP-Elites islands, cascade evaluation, and a local Ollama ensemble."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12"
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
from ollama import Client, ResponseError
|
|
2
|
-
|
|
3
|
-
from ..telemetry import log
|
|
4
|
-
from .base import BaseLLM
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class OllamaLLM(BaseLLM):
|
|
8
|
-
def __init__(self, model_config, *, host: str = "http://localhost:11434", timeout: float = 600.0, system_prompt: str | None = None):
|
|
9
|
-
self.cfg = model_config
|
|
10
|
-
self.system_prompt = system_prompt
|
|
11
|
-
self.client = Client(host=host, timeout=timeout)
|
|
12
|
-
self._ensure_model()
|
|
13
|
-
|
|
14
|
-
def _ensure_model(self):
|
|
15
|
-
try:
|
|
16
|
-
self.client.show(self.cfg.name)
|
|
17
|
-
except ResponseError:
|
|
18
|
-
log.info("[ollama] pulling [bold]%s[/]...", self.cfg.name)
|
|
19
|
-
self.client.pull(self.cfg.name)
|
|
20
|
-
|
|
21
|
-
def generate(self, prompt: str) -> str:
|
|
22
|
-
try:
|
|
23
|
-
return self._generate(prompt)
|
|
24
|
-
except Exception:
|
|
25
|
-
log.exception("ollama generate failed for model=%s", self.cfg.name)
|
|
26
|
-
raise
|
|
27
|
-
|
|
28
|
-
def _options(self) -> dict:
|
|
29
|
-
opts = {
|
|
30
|
-
"temperature": self.cfg.temperature,
|
|
31
|
-
"num_ctx": self.cfg.num_ctx,
|
|
32
|
-
"flash_attn": self.cfg.flash_attention,
|
|
33
|
-
}
|
|
34
|
-
opts.update(self.cfg.options)
|
|
35
|
-
return opts
|
|
36
|
-
|
|
37
|
-
def _generate(self, prompt: str) -> str:
|
|
38
|
-
resp = self.client.generate(
|
|
39
|
-
model=self.cfg.name,
|
|
40
|
-
prompt=prompt,
|
|
41
|
-
system=self.system_prompt,
|
|
42
|
-
options=self._options(),
|
|
43
|
-
stream=False,
|
|
44
|
-
)
|
|
45
|
-
return resp.response
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|