fastevolve 0.2.1__tar.gz → 0.3.1__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.2.1 → fastevolve-0.3.1}/.claude/settings.local.json +2 -1
- {fastevolve-0.2.1 → fastevolve-0.3.1}/.gitignore +1 -0
- fastevolve-0.3.1/PKG-INFO +237 -0
- fastevolve-0.3.1/README.md +207 -0
- fastevolve-0.3.1/fastevolve/checkpoint.py +62 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/fastevolve/config.py +1 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/fastevolve/controller.py +23 -4
- fastevolve-0.3.1/fastevolve/llm_ensemble/anthropic_llm.py +25 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/fastevolve/llm_ensemble/config.py +1 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/fastevolve/llm_ensemble/ensemble.py +15 -3
- fastevolve-0.3.1/fastevolve/llm_ensemble/openai_llm.py +28 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/pyproject.toml +4 -1
- {fastevolve-0.2.1 → fastevolve-0.3.1}/uv.lock +165 -2
- fastevolve-0.2.1/PKG-INFO +0 -47
- fastevolve-0.2.1/README.md +0 -24
- {fastevolve-0.2.1 → fastevolve-0.3.1}/.python-version +0 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/fastevolve/__init__.py +0 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/fastevolve/evaluator/__init__.py +0 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/fastevolve/evaluator/config.py +0 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/fastevolve/evaluator/evaluator.py +0 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/fastevolve/evaluator/result.py +0 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/fastevolve/llm_ensemble/__init__.py +0 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/fastevolve/llm_ensemble/base.py +0 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/fastevolve/llm_ensemble/ollama.py +0 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/fastevolve/program_database/__init__.py +0 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/fastevolve/program_database/config.py +0 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/fastevolve/program_database/database.py +0 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/fastevolve/program_database/embedder.py +0 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/fastevolve/program_database/program.py +0 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/fastevolve/prompt_sampler/__init__.py +0 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/fastevolve/prompt_sampler/config.py +0 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/fastevolve/prompt_sampler/sampler.py +0 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/fastevolve/prompt_sampler/template_library.py +0 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/fastevolve/telemetry.py +0 -0
- {fastevolve-0.2.1 → fastevolve-0.3.1}/main.py +0 -0
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"Bash(uv run *)",
|
|
10
10
|
"Bash(.venv/Scripts/python.exe -m pip install \"rich>=13.7\" -q)",
|
|
11
11
|
"Bash(uv add *)",
|
|
12
|
-
"Bash(.venv/Scripts/python.exe -c 'from fastevolve.controller import Controller; from fastevolve.telemetry import setup, span, log; setup\\(\\); log.info\\('\\\\''telemetry [bold green]ok[/]'\\\\''\\); *)"
|
|
12
|
+
"Bash(.venv/Scripts/python.exe -c 'from fastevolve.controller import Controller; from fastevolve.telemetry import setup, span, log; setup\\(\\); log.info\\('\\\\''telemetry [bold green]ok[/]'\\\\''\\); *)",
|
|
13
|
+
"Bash(.venv/Scripts/python.exe -c ' *)"
|
|
13
14
|
]
|
|
14
15
|
}
|
|
15
16
|
}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fastevolve
|
|
3
|
+
Version: 0.3.1
|
|
4
|
+
Summary: Minimal open-source AlphaEvolve: LLM-driven program evolution with MAP-Elites islands, cascade evaluation, and a local Ollama ensemble.
|
|
5
|
+
Project-URL: Homepage, https://github.com/tiagomonteiro0715/fastevolve
|
|
6
|
+
Project-URL: Repository, https://github.com/tiagomonteiro0715/fastevolve
|
|
7
|
+
Project-URL: Issues, https://github.com/tiagomonteiro0715/fastevolve/issues
|
|
8
|
+
Author-email: Tiago Monteiro <monteiro.t@northeastern.edu>
|
|
9
|
+
License: MIT
|
|
10
|
+
Keywords: alphaevolve,evolutionary-search,llm,map-elites,ollama,program-synthesis
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
16
|
+
Requires-Python: >=3.12
|
|
17
|
+
Requires-Dist: ollama>=0.4.0
|
|
18
|
+
Requires-Dist: rich>=13.7
|
|
19
|
+
Provides-Extra: all
|
|
20
|
+
Requires-Dist: anthropic>=0.30; extra == 'all'
|
|
21
|
+
Requires-Dist: openai>=1.0; extra == 'all'
|
|
22
|
+
Provides-Extra: anthropic
|
|
23
|
+
Requires-Dist: anthropic>=0.30; extra == 'anthropic'
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
26
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
27
|
+
Provides-Extra: openai
|
|
28
|
+
Requires-Dist: openai>=1.0; extra == 'openai'
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# fastevolve
|
|
32
|
+
|
|
33
|
+
Minimal open-source AlphaEvolve: LLM-driven program evolution with MAP-Elites islands, cascade evaluation, and a local Ollama ensemble.
|
|
34
|
+
|
|
35
|
+
## Install
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
uv sync
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The core install ships with Ollama support only. OpenAI and Anthropic SDKs are optional extras — install whichever you need:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
uv sync --extra openai # adds the OpenAI SDK
|
|
45
|
+
uv sync --extra anthropic # adds the Anthropic SDK
|
|
46
|
+
uv sync --extra all # both
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
If you only use Ollama, skip the extras — neither SDK will be imported.
|
|
50
|
+
|
|
51
|
+
## Quick start in code
|
|
52
|
+
|
|
53
|
+
### Local (with Ollama)
|
|
54
|
+
|
|
55
|
+
Assumes `ollama serve` is running and you've pulled the model.
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from fastevolve import Config, Controller
|
|
59
|
+
from fastevolve.llm_ensemble import ModelConfig
|
|
60
|
+
|
|
61
|
+
INITIAL = "def solve(x):\n return x\n"
|
|
62
|
+
|
|
63
|
+
def correctness(p):
|
|
64
|
+
ns = {}
|
|
65
|
+
try: exec(p.code, ns)
|
|
66
|
+
except Exception: return 0.0
|
|
67
|
+
fn = ns.get("solve")
|
|
68
|
+
cases = [(2, 4), (3, 9), (4, 16), (5, 25)]
|
|
69
|
+
return sum(1 for x, y in cases if fn and fn(x) == y) / len(cases)
|
|
70
|
+
|
|
71
|
+
cfg = Config()
|
|
72
|
+
cfg.iterations = 20
|
|
73
|
+
cfg.checkpoint_path = "run.log" # optional — resume if killed mid-run
|
|
74
|
+
cfg.ensemble.models = [
|
|
75
|
+
ModelConfig(name="gemma3:e4b", provider="ollama", temperature=0.7, weight=1.0, role="fast"),
|
|
76
|
+
]
|
|
77
|
+
cfg.evaluator.cascade = [(correctness, 0.0)]
|
|
78
|
+
|
|
79
|
+
result = Controller(cfg, initial_program=INITIAL).run()
|
|
80
|
+
print(result.best.code)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Google Colab (with OpenAI or Anthropic)
|
|
84
|
+
|
|
85
|
+
Ollama isn't practical on Colab — use an API provider instead. Paste this into a Colab cell:
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
!pip install -q "fastevolve[openai]"
|
|
89
|
+
|
|
90
|
+
import os
|
|
91
|
+
from google.colab import userdata
|
|
92
|
+
os.environ["OPENAI_API_KEY"] = userdata.get("OPENAI_API_KEY") # store in Colab Secrets first
|
|
93
|
+
|
|
94
|
+
from fastevolve import Config, Controller
|
|
95
|
+
from fastevolve.llm_ensemble import ModelConfig
|
|
96
|
+
|
|
97
|
+
INITIAL = "def solve(x):\n return x\n"
|
|
98
|
+
|
|
99
|
+
def correctness(p):
|
|
100
|
+
ns = {}
|
|
101
|
+
try: exec(p.code, ns)
|
|
102
|
+
except Exception: return 0.0
|
|
103
|
+
fn = ns.get("solve")
|
|
104
|
+
cases = [(2, 4), (3, 9), (4, 16), (5, 25)]
|
|
105
|
+
return sum(1 for x, y in cases if fn and fn(x) == y) / len(cases)
|
|
106
|
+
|
|
107
|
+
cfg = Config()
|
|
108
|
+
cfg.iterations = 20
|
|
109
|
+
cfg.ensemble.models = [
|
|
110
|
+
ModelConfig(name="gpt-4o-mini", provider="openai", temperature=0.7, weight=1.0, role="fast"),
|
|
111
|
+
]
|
|
112
|
+
cfg.evaluator.cascade = [(correctness, 0.0)]
|
|
113
|
+
|
|
114
|
+
result = Controller(cfg, initial_program=INITIAL).run()
|
|
115
|
+
print(result.best.code)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Google Colab (with Claude)
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
!pip install -q "fastevolve[anthropic]"
|
|
122
|
+
|
|
123
|
+
import os
|
|
124
|
+
from google.colab import userdata
|
|
125
|
+
os.environ["ANTHROPIC_API_KEY"] = userdata.get("ANTHROPIC_API_KEY") # store in Colab Secrets first
|
|
126
|
+
|
|
127
|
+
from fastevolve import Config, Controller
|
|
128
|
+
from fastevolve.llm_ensemble import ModelConfig
|
|
129
|
+
|
|
130
|
+
INITIAL = "def solve(x):\n return x\n"
|
|
131
|
+
|
|
132
|
+
def correctness(p):
|
|
133
|
+
ns = {}
|
|
134
|
+
try: exec(p.code, ns)
|
|
135
|
+
except Exception: return 0.0
|
|
136
|
+
fn = ns.get("solve")
|
|
137
|
+
cases = [(2, 4), (3, 9), (4, 16), (5, 25)]
|
|
138
|
+
return sum(1 for x, y in cases if fn and fn(x) == y) / len(cases)
|
|
139
|
+
|
|
140
|
+
cfg = Config()
|
|
141
|
+
cfg.iterations = 20
|
|
142
|
+
cfg.ensemble.models = [
|
|
143
|
+
ModelConfig(name="claude-haiku-4-5-20251001", provider="anthropic",
|
|
144
|
+
temperature=0.7, weight=1.0, role="fast",
|
|
145
|
+
options={"max_tokens": 4096}),
|
|
146
|
+
]
|
|
147
|
+
cfg.evaluator.cascade = [(correctness, 0.0)]
|
|
148
|
+
|
|
149
|
+
result = Controller(cfg, initial_program=INITIAL).run()
|
|
150
|
+
print(result.best.code)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Google Colab (with Ollama)
|
|
154
|
+
|
|
155
|
+
Ollama can run on Colab if you install it, start the daemon in the background, and pull a small model. Use a GPU runtime (`Runtime → Change runtime type → T4 GPU`) for any model bigger than ~1B parameters.
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
# 1. Install ollama and fastevolve
|
|
159
|
+
!curl -fsSL https://ollama.com/install.sh | sh
|
|
160
|
+
!pip install -q fastevolve
|
|
161
|
+
|
|
162
|
+
# 2. Start the ollama daemon in the background
|
|
163
|
+
import subprocess, time
|
|
164
|
+
subprocess.Popen(["ollama", "serve"])
|
|
165
|
+
time.sleep(5) # give it a moment to bind to port 11434
|
|
166
|
+
|
|
167
|
+
# 3. Pull a small model (qwen2.5:0.5b is ~400 MB and fits the free CPU runtime)
|
|
168
|
+
!ollama pull qwen2.5:0.5b
|
|
169
|
+
|
|
170
|
+
# 4. Run fastevolve as usual
|
|
171
|
+
from fastevolve import Config, Controller
|
|
172
|
+
from fastevolve.llm_ensemble import ModelConfig
|
|
173
|
+
|
|
174
|
+
INITIAL = "def solve(x):\n return x\n"
|
|
175
|
+
|
|
176
|
+
def correctness(p):
|
|
177
|
+
ns = {}
|
|
178
|
+
try: exec(p.code, ns)
|
|
179
|
+
except Exception: return 0.0
|
|
180
|
+
fn = ns.get("solve")
|
|
181
|
+
cases = [(2, 4), (3, 9), (4, 16), (5, 25)]
|
|
182
|
+
return sum(1 for x, y in cases if fn and fn(x) == y) / len(cases)
|
|
183
|
+
|
|
184
|
+
cfg = Config()
|
|
185
|
+
cfg.iterations = 20
|
|
186
|
+
cfg.ensemble.models = [
|
|
187
|
+
ModelConfig(name="qwen2.5:0.5b", provider="ollama",
|
|
188
|
+
temperature=0.7, weight=1.0, role="fast"),
|
|
189
|
+
]
|
|
190
|
+
cfg.evaluator.cascade = [(correctness, 0.0)]
|
|
191
|
+
|
|
192
|
+
result = Controller(cfg, initial_program=INITIAL).run()
|
|
193
|
+
print(result.best.code)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Colab sessions are disconnected after ~90 min idle and the VM is wiped — set `cfg.checkpoint_path = "/content/drive/MyDrive/run.log"` after mounting Drive if you want resume across sessions.
|
|
197
|
+
|
|
198
|
+
## Run the demo
|
|
199
|
+
|
|
200
|
+
Start Ollama and pull the model first:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
ollama serve
|
|
204
|
+
ollama pull gemma3:e4b
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Then:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
uv run python main.py
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Using OpenAI or Claude in the ensemble
|
|
214
|
+
|
|
215
|
+
Set the API key for whichever provider(s) you plan to use:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
export OPENAI_API_KEY=sk-...
|
|
219
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
On Windows (cmd.exe): `set OPENAI_API_KEY=sk-...`
|
|
223
|
+
|
|
224
|
+
Then pick a `provider` per model in your config. You can freely mix providers in one ensemble:
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
from fastevolve.llm_ensemble import ModelConfig
|
|
228
|
+
|
|
229
|
+
cfg.ensemble.models = [
|
|
230
|
+
ModelConfig(name="gemma3:e4b", provider="ollama", temperature=0.6, weight=1.0, role="fast"),
|
|
231
|
+
ModelConfig(name="gpt-4o-mini", provider="openai", temperature=0.6, weight=1.0, role="fast"),
|
|
232
|
+
ModelConfig(name="claude-opus-4-7", provider="anthropic", temperature=0.7, weight=1.0,
|
|
233
|
+
role="deep", options={"max_tokens": 4096}),
|
|
234
|
+
]
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
`provider` defaults to `"ollama"`, so existing configs keep working unchanged.
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# fastevolve
|
|
2
|
+
|
|
3
|
+
Minimal open-source AlphaEvolve: LLM-driven program evolution with MAP-Elites islands, cascade evaluation, and a local Ollama ensemble.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
uv sync
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
The core install ships with Ollama support only. OpenAI and Anthropic SDKs are optional extras — install whichever you need:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
uv sync --extra openai # adds the OpenAI SDK
|
|
15
|
+
uv sync --extra anthropic # adds the Anthropic SDK
|
|
16
|
+
uv sync --extra all # both
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
If you only use Ollama, skip the extras — neither SDK will be imported.
|
|
20
|
+
|
|
21
|
+
## Quick start in code
|
|
22
|
+
|
|
23
|
+
### Local (with Ollama)
|
|
24
|
+
|
|
25
|
+
Assumes `ollama serve` is running and you've pulled the model.
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from fastevolve import Config, Controller
|
|
29
|
+
from fastevolve.llm_ensemble import ModelConfig
|
|
30
|
+
|
|
31
|
+
INITIAL = "def solve(x):\n return x\n"
|
|
32
|
+
|
|
33
|
+
def correctness(p):
|
|
34
|
+
ns = {}
|
|
35
|
+
try: exec(p.code, ns)
|
|
36
|
+
except Exception: return 0.0
|
|
37
|
+
fn = ns.get("solve")
|
|
38
|
+
cases = [(2, 4), (3, 9), (4, 16), (5, 25)]
|
|
39
|
+
return sum(1 for x, y in cases if fn and fn(x) == y) / len(cases)
|
|
40
|
+
|
|
41
|
+
cfg = Config()
|
|
42
|
+
cfg.iterations = 20
|
|
43
|
+
cfg.checkpoint_path = "run.log" # optional — resume if killed mid-run
|
|
44
|
+
cfg.ensemble.models = [
|
|
45
|
+
ModelConfig(name="gemma3:e4b", provider="ollama", temperature=0.7, weight=1.0, role="fast"),
|
|
46
|
+
]
|
|
47
|
+
cfg.evaluator.cascade = [(correctness, 0.0)]
|
|
48
|
+
|
|
49
|
+
result = Controller(cfg, initial_program=INITIAL).run()
|
|
50
|
+
print(result.best.code)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Google Colab (with OpenAI or Anthropic)
|
|
54
|
+
|
|
55
|
+
Ollama isn't practical on Colab — use an API provider instead. Paste this into a Colab cell:
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
!pip install -q "fastevolve[openai]"
|
|
59
|
+
|
|
60
|
+
import os
|
|
61
|
+
from google.colab import userdata
|
|
62
|
+
os.environ["OPENAI_API_KEY"] = userdata.get("OPENAI_API_KEY") # store in Colab Secrets first
|
|
63
|
+
|
|
64
|
+
from fastevolve import Config, Controller
|
|
65
|
+
from fastevolve.llm_ensemble import ModelConfig
|
|
66
|
+
|
|
67
|
+
INITIAL = "def solve(x):\n return x\n"
|
|
68
|
+
|
|
69
|
+
def correctness(p):
|
|
70
|
+
ns = {}
|
|
71
|
+
try: exec(p.code, ns)
|
|
72
|
+
except Exception: return 0.0
|
|
73
|
+
fn = ns.get("solve")
|
|
74
|
+
cases = [(2, 4), (3, 9), (4, 16), (5, 25)]
|
|
75
|
+
return sum(1 for x, y in cases if fn and fn(x) == y) / len(cases)
|
|
76
|
+
|
|
77
|
+
cfg = Config()
|
|
78
|
+
cfg.iterations = 20
|
|
79
|
+
cfg.ensemble.models = [
|
|
80
|
+
ModelConfig(name="gpt-4o-mini", provider="openai", temperature=0.7, weight=1.0, role="fast"),
|
|
81
|
+
]
|
|
82
|
+
cfg.evaluator.cascade = [(correctness, 0.0)]
|
|
83
|
+
|
|
84
|
+
result = Controller(cfg, initial_program=INITIAL).run()
|
|
85
|
+
print(result.best.code)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Google Colab (with Claude)
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
!pip install -q "fastevolve[anthropic]"
|
|
92
|
+
|
|
93
|
+
import os
|
|
94
|
+
from google.colab import userdata
|
|
95
|
+
os.environ["ANTHROPIC_API_KEY"] = userdata.get("ANTHROPIC_API_KEY") # store in Colab Secrets first
|
|
96
|
+
|
|
97
|
+
from fastevolve import Config, Controller
|
|
98
|
+
from fastevolve.llm_ensemble import ModelConfig
|
|
99
|
+
|
|
100
|
+
INITIAL = "def solve(x):\n return x\n"
|
|
101
|
+
|
|
102
|
+
def correctness(p):
|
|
103
|
+
ns = {}
|
|
104
|
+
try: exec(p.code, ns)
|
|
105
|
+
except Exception: return 0.0
|
|
106
|
+
fn = ns.get("solve")
|
|
107
|
+
cases = [(2, 4), (3, 9), (4, 16), (5, 25)]
|
|
108
|
+
return sum(1 for x, y in cases if fn and fn(x) == y) / len(cases)
|
|
109
|
+
|
|
110
|
+
cfg = Config()
|
|
111
|
+
cfg.iterations = 20
|
|
112
|
+
cfg.ensemble.models = [
|
|
113
|
+
ModelConfig(name="claude-haiku-4-5-20251001", provider="anthropic",
|
|
114
|
+
temperature=0.7, weight=1.0, role="fast",
|
|
115
|
+
options={"max_tokens": 4096}),
|
|
116
|
+
]
|
|
117
|
+
cfg.evaluator.cascade = [(correctness, 0.0)]
|
|
118
|
+
|
|
119
|
+
result = Controller(cfg, initial_program=INITIAL).run()
|
|
120
|
+
print(result.best.code)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Google Colab (with Ollama)
|
|
124
|
+
|
|
125
|
+
Ollama can run on Colab if you install it, start the daemon in the background, and pull a small model. Use a GPU runtime (`Runtime → Change runtime type → T4 GPU`) for any model bigger than ~1B parameters.
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
# 1. Install ollama and fastevolve
|
|
129
|
+
!curl -fsSL https://ollama.com/install.sh | sh
|
|
130
|
+
!pip install -q fastevolve
|
|
131
|
+
|
|
132
|
+
# 2. Start the ollama daemon in the background
|
|
133
|
+
import subprocess, time
|
|
134
|
+
subprocess.Popen(["ollama", "serve"])
|
|
135
|
+
time.sleep(5) # give it a moment to bind to port 11434
|
|
136
|
+
|
|
137
|
+
# 3. Pull a small model (qwen2.5:0.5b is ~400 MB and fits the free CPU runtime)
|
|
138
|
+
!ollama pull qwen2.5:0.5b
|
|
139
|
+
|
|
140
|
+
# 4. Run fastevolve as usual
|
|
141
|
+
from fastevolve import Config, Controller
|
|
142
|
+
from fastevolve.llm_ensemble import ModelConfig
|
|
143
|
+
|
|
144
|
+
INITIAL = "def solve(x):\n return x\n"
|
|
145
|
+
|
|
146
|
+
def correctness(p):
|
|
147
|
+
ns = {}
|
|
148
|
+
try: exec(p.code, ns)
|
|
149
|
+
except Exception: return 0.0
|
|
150
|
+
fn = ns.get("solve")
|
|
151
|
+
cases = [(2, 4), (3, 9), (4, 16), (5, 25)]
|
|
152
|
+
return sum(1 for x, y in cases if fn and fn(x) == y) / len(cases)
|
|
153
|
+
|
|
154
|
+
cfg = Config()
|
|
155
|
+
cfg.iterations = 20
|
|
156
|
+
cfg.ensemble.models = [
|
|
157
|
+
ModelConfig(name="qwen2.5:0.5b", provider="ollama",
|
|
158
|
+
temperature=0.7, weight=1.0, role="fast"),
|
|
159
|
+
]
|
|
160
|
+
cfg.evaluator.cascade = [(correctness, 0.0)]
|
|
161
|
+
|
|
162
|
+
result = Controller(cfg, initial_program=INITIAL).run()
|
|
163
|
+
print(result.best.code)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Colab sessions are disconnected after ~90 min idle and the VM is wiped — set `cfg.checkpoint_path = "/content/drive/MyDrive/run.log"` after mounting Drive if you want resume across sessions.
|
|
167
|
+
|
|
168
|
+
## Run the demo
|
|
169
|
+
|
|
170
|
+
Start Ollama and pull the model first:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
ollama serve
|
|
174
|
+
ollama pull gemma3:e4b
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Then:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
uv run python main.py
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Using OpenAI or Claude in the ensemble
|
|
184
|
+
|
|
185
|
+
Set the API key for whichever provider(s) you plan to use:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
export OPENAI_API_KEY=sk-...
|
|
189
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
On Windows (cmd.exe): `set OPENAI_API_KEY=sk-...`
|
|
193
|
+
|
|
194
|
+
Then pick a `provider` per model in your config. You can freely mix providers in one ensemble:
|
|
195
|
+
|
|
196
|
+
```python
|
|
197
|
+
from fastevolve.llm_ensemble import ModelConfig
|
|
198
|
+
|
|
199
|
+
cfg.ensemble.models = [
|
|
200
|
+
ModelConfig(name="gemma3:e4b", provider="ollama", temperature=0.6, weight=1.0, role="fast"),
|
|
201
|
+
ModelConfig(name="gpt-4o-mini", provider="openai", temperature=0.6, weight=1.0, role="fast"),
|
|
202
|
+
ModelConfig(name="claude-opus-4-7", provider="anthropic", temperature=0.7, weight=1.0,
|
|
203
|
+
role="deep", options={"max_tokens": 4096}),
|
|
204
|
+
]
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
`provider` defaults to `"ollama"`, so existing configs keep working unchanged.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import pickle
|
|
3
|
+
import struct
|
|
4
|
+
import threading
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from queue import Queue
|
|
7
|
+
|
|
8
|
+
from .telemetry import log
|
|
9
|
+
|
|
10
|
+
_SENTINEL = object()
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Checkpointer:
|
|
14
|
+
"""Append-only background log: O(1) main-thread cost per iteration."""
|
|
15
|
+
|
|
16
|
+
def __init__(self, path: str | None):
|
|
17
|
+
self.path = Path(path) if path else None
|
|
18
|
+
self._q: Queue = Queue()
|
|
19
|
+
self._thread: threading.Thread | None = None
|
|
20
|
+
if self.path:
|
|
21
|
+
self._thread = threading.Thread(target=self._worker, daemon=True)
|
|
22
|
+
self._thread.start()
|
|
23
|
+
|
|
24
|
+
def append(self, record) -> None:
|
|
25
|
+
if self.path:
|
|
26
|
+
self._q.put(record)
|
|
27
|
+
|
|
28
|
+
def close(self) -> None:
|
|
29
|
+
if self._thread:
|
|
30
|
+
self._q.put(_SENTINEL)
|
|
31
|
+
self._thread.join(timeout=5)
|
|
32
|
+
|
|
33
|
+
def load(self) -> list:
|
|
34
|
+
records: list = []
|
|
35
|
+
if not (self.path and self.path.exists()):
|
|
36
|
+
return records
|
|
37
|
+
try:
|
|
38
|
+
with open(self.path, "rb") as f:
|
|
39
|
+
while True:
|
|
40
|
+
hdr = f.read(4)
|
|
41
|
+
if len(hdr) < 4:
|
|
42
|
+
break
|
|
43
|
+
(n,) = struct.unpack("!I", hdr)
|
|
44
|
+
records.append(pickle.loads(f.read(n)))
|
|
45
|
+
except Exception:
|
|
46
|
+
log.exception("checkpoint load failed: %s", self.path)
|
|
47
|
+
return records
|
|
48
|
+
|
|
49
|
+
def _worker(self) -> None:
|
|
50
|
+
try:
|
|
51
|
+
with open(self.path, "ab") as f:
|
|
52
|
+
while True:
|
|
53
|
+
rec = self._q.get()
|
|
54
|
+
if rec is _SENTINEL:
|
|
55
|
+
return
|
|
56
|
+
data = pickle.dumps(rec, protocol=pickle.HIGHEST_PROTOCOL)
|
|
57
|
+
f.write(struct.pack("!I", len(data)))
|
|
58
|
+
f.write(data)
|
|
59
|
+
f.flush()
|
|
60
|
+
os.fsync(f.fileno())
|
|
61
|
+
except Exception:
|
|
62
|
+
log.exception("checkpoint worker died")
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import itertools
|
|
1
2
|
import re
|
|
2
3
|
from dataclasses import dataclass, field
|
|
3
4
|
from typing import Optional
|
|
@@ -7,11 +8,13 @@ from rich.progress import (
|
|
|
7
8
|
TimeElapsedColumn, TimeRemainingColumn,
|
|
8
9
|
)
|
|
9
10
|
|
|
11
|
+
from .checkpoint import Checkpointer
|
|
10
12
|
from .config import Config
|
|
11
13
|
from .prompt_sampler import PromptSampler, TemplateLibrary
|
|
12
14
|
from .llm_ensemble import LLMEnsemble
|
|
13
15
|
from .evaluator import Evaluator
|
|
14
16
|
from .program_database import ProgramDatabase, Program
|
|
17
|
+
from .program_database import program as _program
|
|
15
18
|
from .telemetry import setup, span, timings, log
|
|
16
19
|
|
|
17
20
|
|
|
@@ -39,9 +42,22 @@ class Controller:
|
|
|
39
42
|
self.sampler = PromptSampler(config.prompt, library=lib)
|
|
40
43
|
self.ensemble = LLMEnsemble(config.ensemble, system_prompts=lib.system_prompts)
|
|
41
44
|
self.evaluator = Evaluator(config.evaluator)
|
|
45
|
+
self.checkpoint = Checkpointer(config.checkpoint_path)
|
|
46
|
+
records = self.checkpoint.load()
|
|
42
47
|
self.database = ProgramDatabase(config.database)
|
|
43
|
-
|
|
44
|
-
|
|
48
|
+
if records:
|
|
49
|
+
for prog, res in records:
|
|
50
|
+
self.database.add(prog, res)
|
|
51
|
+
_program._ids = itertools.count(max(self.database.by_id, default=-1) + 1)
|
|
52
|
+
self._start = max(0, len(records) - 1)
|
|
53
|
+
log.info("resumed: [bold]%d[/] records replayed (population=%d)",
|
|
54
|
+
len(records), len(self.database.by_id))
|
|
55
|
+
else:
|
|
56
|
+
seed = self.database.seed(initial_program)
|
|
57
|
+
seed_result = self.evaluator.execute(seed)
|
|
58
|
+
self.database.add(seed, seed_result)
|
|
59
|
+
self.checkpoint.append((seed, seed_result))
|
|
60
|
+
self._start = 0
|
|
45
61
|
|
|
46
62
|
def run(self) -> RunResult:
|
|
47
63
|
best: Optional[Program] = None
|
|
@@ -54,8 +70,9 @@ class Controller:
|
|
|
54
70
|
TimeElapsedColumn(), TimeRemainingColumn(),
|
|
55
71
|
]
|
|
56
72
|
with Progress(*cols, transient=False) as prog:
|
|
57
|
-
task = prog.add_task("run", total=self.config.iterations,
|
|
58
|
-
|
|
73
|
+
task = prog.add_task("run", total=self.config.iterations, completed=self._start,
|
|
74
|
+
stage="init", fit=0.0, best=0.0)
|
|
75
|
+
for step in range(self._start, self.config.iterations):
|
|
59
76
|
prog.update(task, stage="sample")
|
|
60
77
|
with span("sample"):
|
|
61
78
|
parent, insp = self.database.sample()
|
|
@@ -76,6 +93,8 @@ class Controller:
|
|
|
76
93
|
best = child
|
|
77
94
|
prog.update(task, advance=1, fit=child.fitness,
|
|
78
95
|
best=best.fitness if best else 0.0)
|
|
96
|
+
self.checkpoint.append((child, result))
|
|
97
|
+
self.checkpoint.close()
|
|
79
98
|
t = timings()
|
|
80
99
|
log.info("done. population=%d best=%.3f", len(self.database.by_id),
|
|
81
100
|
best.fitness if best else 0.0)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from anthropic import Anthropic
|
|
2
|
+
|
|
3
|
+
from ..telemetry import log
|
|
4
|
+
from .base import BaseLLM
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ClaudeLLM(BaseLLM):
|
|
8
|
+
def __init__(self, model_config, *, system_prompt: str | None = None, **_):
|
|
9
|
+
self.cfg = model_config
|
|
10
|
+
self.system_prompt = system_prompt
|
|
11
|
+
self.client = Anthropic() # reads ANTHROPIC_API_KEY
|
|
12
|
+
|
|
13
|
+
def generate(self, prompt: str) -> str:
|
|
14
|
+
try:
|
|
15
|
+
resp = self.client.messages.create(
|
|
16
|
+
model=self.cfg.name,
|
|
17
|
+
max_tokens=self.cfg.options.get("max_tokens", 4096),
|
|
18
|
+
temperature=self.cfg.temperature,
|
|
19
|
+
system=self.system_prompt or "",
|
|
20
|
+
messages=[{"role": "user", "content": prompt}],
|
|
21
|
+
)
|
|
22
|
+
return resp.content[0].text
|
|
23
|
+
except Exception:
|
|
24
|
+
log.exception("anthropic generate failed for model=%s", self.cfg.name)
|
|
25
|
+
raise
|
|
@@ -1,17 +1,29 @@
|
|
|
1
1
|
import random
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def _make_llm(mcfg, **kw):
|
|
5
|
+
if mcfg.provider == "ollama":
|
|
6
|
+
from .ollama import OllamaLLM
|
|
7
|
+
return OllamaLLM(mcfg, **kw)
|
|
8
|
+
if mcfg.provider == "openai":
|
|
9
|
+
from .openai_llm import OpenAILLM
|
|
10
|
+
return OpenAILLM(mcfg, **kw)
|
|
11
|
+
if mcfg.provider == "anthropic":
|
|
12
|
+
from .anthropic_llm import ClaudeLLM
|
|
13
|
+
return ClaudeLLM(mcfg, **kw)
|
|
14
|
+
raise ValueError(f"unknown provider: {mcfg.provider}")
|
|
3
15
|
|
|
4
16
|
|
|
5
17
|
class LLMEnsemble:
|
|
6
18
|
def __init__(self, config, *, system_prompts: dict | None = None):
|
|
7
19
|
self.config = config
|
|
8
20
|
sp = system_prompts or {}
|
|
9
|
-
self.llms = [
|
|
21
|
+
self.llms = [_make_llm(m, host=config.host, timeout=config.timeout,
|
|
10
22
|
system_prompt=sp.get(m.name)) for m in config.models]
|
|
11
23
|
if not self.llms:
|
|
12
24
|
raise ValueError("EnsembleConfig.models is empty")
|
|
13
25
|
|
|
14
|
-
def select_model(self)
|
|
26
|
+
def select_model(self):
|
|
15
27
|
return random.choices(self.llms, weights=[m.cfg.weight for m in self.llms], k=1)[0]
|
|
16
28
|
|
|
17
29
|
def generate(self, prompt: str) -> str:
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from openai import OpenAI
|
|
2
|
+
|
|
3
|
+
from ..telemetry import log
|
|
4
|
+
from .base import BaseLLM
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class OpenAILLM(BaseLLM):
|
|
8
|
+
def __init__(self, model_config, *, system_prompt: str | None = None, **_):
|
|
9
|
+
self.cfg = model_config
|
|
10
|
+
self.system_prompt = system_prompt
|
|
11
|
+
self.client = OpenAI() # reads OPENAI_API_KEY
|
|
12
|
+
|
|
13
|
+
def generate(self, prompt: str) -> str:
|
|
14
|
+
try:
|
|
15
|
+
msgs = []
|
|
16
|
+
if self.system_prompt:
|
|
17
|
+
msgs.append({"role": "system", "content": self.system_prompt})
|
|
18
|
+
msgs.append({"role": "user", "content": prompt})
|
|
19
|
+
resp = self.client.chat.completions.create(
|
|
20
|
+
model=self.cfg.name,
|
|
21
|
+
messages=msgs,
|
|
22
|
+
temperature=self.cfg.temperature,
|
|
23
|
+
**self.cfg.options,
|
|
24
|
+
)
|
|
25
|
+
return resp.choices[0].message.content or ""
|
|
26
|
+
except Exception:
|
|
27
|
+
log.exception("openai generate failed for model=%s", self.cfg.name)
|
|
28
|
+
raise
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "fastevolve"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.3.1"
|
|
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"
|
|
@@ -21,6 +21,9 @@ dependencies = [
|
|
|
21
21
|
|
|
22
22
|
[project.optional-dependencies]
|
|
23
23
|
dev = ["pytest>=8", "ruff>=0.6"]
|
|
24
|
+
openai = ["openai>=1.0"]
|
|
25
|
+
anthropic = ["anthropic>=0.30"]
|
|
26
|
+
all = ["openai>=1.0", "anthropic>=0.30"]
|
|
24
27
|
|
|
25
28
|
[project.scripts]
|
|
26
29
|
fastevolve-demo = "main:main"
|
|
@@ -11,6 +11,25 @@ wheels = [
|
|
|
11
11
|
{ url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" },
|
|
12
12
|
]
|
|
13
13
|
|
|
14
|
+
[[package]]
|
|
15
|
+
name = "anthropic"
|
|
16
|
+
version = "0.112.0"
|
|
17
|
+
source = { registry = "https://pypi.org/simple" }
|
|
18
|
+
dependencies = [
|
|
19
|
+
{ name = "anyio" },
|
|
20
|
+
{ name = "distro" },
|
|
21
|
+
{ name = "docstring-parser" },
|
|
22
|
+
{ name = "httpx" },
|
|
23
|
+
{ name = "jiter" },
|
|
24
|
+
{ name = "pydantic" },
|
|
25
|
+
{ name = "sniffio" },
|
|
26
|
+
{ name = "typing-extensions" },
|
|
27
|
+
]
|
|
28
|
+
sdist = { url = "https://files.pythonhosted.org/packages/7b/dd/808c144d4a883fcfd12fe0d7689b1d86bbbea6666c1cc957ad19f1017c22/anthropic-0.112.0.tar.gz", hash = "sha256:e180cd91aa5b9b32e4007fe69892ab128d8a86b9f90825103b1903fbc977d0af", size = 937460, upload-time = "2026-06-24T18:45:56.844Z" }
|
|
29
|
+
wheels = [
|
|
30
|
+
{ url = "https://files.pythonhosted.org/packages/a9/26/ea71185027956325be1903d4fcaf7461d5ef40ca8f0e64f992e24ea9db0e/anthropic-0.112.0-py3-none-any.whl", hash = "sha256:bcc6268612c716dbb77133dd60fc41d26016d1b81dee9a52314d210193638751", size = 931954, upload-time = "2026-06-24T18:45:58.205Z" },
|
|
31
|
+
]
|
|
32
|
+
|
|
14
33
|
[[package]]
|
|
15
34
|
name = "anyio"
|
|
16
35
|
version = "4.14.1"
|
|
@@ -42,9 +61,27 @@ wheels = [
|
|
|
42
61
|
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
|
|
43
62
|
]
|
|
44
63
|
|
|
64
|
+
[[package]]
|
|
65
|
+
name = "distro"
|
|
66
|
+
version = "1.9.0"
|
|
67
|
+
source = { registry = "https://pypi.org/simple" }
|
|
68
|
+
sdist = { url = "https://files.pythonhosted.org/packages/fc/f8/98eea607f65de6527f8a2e8885fc8015d3e6f5775df186e443e0964a11c3/distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed", size = 60722, upload-time = "2023-12-24T09:54:32.31Z" }
|
|
69
|
+
wheels = [
|
|
70
|
+
{ url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" },
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
[[package]]
|
|
74
|
+
name = "docstring-parser"
|
|
75
|
+
version = "0.18.0"
|
|
76
|
+
source = { registry = "https://pypi.org/simple" }
|
|
77
|
+
sdist = { url = "https://files.pythonhosted.org/packages/e0/4d/f332313098c1de1b2d2ff91cf2674415cc7cddab2ca1b01ae29774bd5fdf/docstring_parser-0.18.0.tar.gz", hash = "sha256:292510982205c12b1248696f44959db3cdd1740237a968ea1e2e7a900eeb2015", size = 29341, upload-time = "2026-04-14T04:09:19.867Z" }
|
|
78
|
+
wheels = [
|
|
79
|
+
{ url = "https://files.pythonhosted.org/packages/a7/5f/ed01f9a3cdffbd5a008556fc7b2a08ddb1cc6ace7effa7340604b1d16699/docstring_parser-0.18.0-py3-none-any.whl", hash = "sha256:b3fcbed555c47d8479be0796ef7e19c2670d428d72e96da63f3a40122860374b", size = 22484, upload-time = "2026-04-14T04:09:18.638Z" },
|
|
80
|
+
]
|
|
81
|
+
|
|
45
82
|
[[package]]
|
|
46
83
|
name = "fastevolve"
|
|
47
|
-
version = "0.
|
|
84
|
+
version = "0.3.1"
|
|
48
85
|
source = { editable = "." }
|
|
49
86
|
dependencies = [
|
|
50
87
|
{ name = "ollama" },
|
|
@@ -52,19 +89,33 @@ dependencies = [
|
|
|
52
89
|
]
|
|
53
90
|
|
|
54
91
|
[package.optional-dependencies]
|
|
92
|
+
all = [
|
|
93
|
+
{ name = "anthropic" },
|
|
94
|
+
{ name = "openai" },
|
|
95
|
+
]
|
|
96
|
+
anthropic = [
|
|
97
|
+
{ name = "anthropic" },
|
|
98
|
+
]
|
|
55
99
|
dev = [
|
|
56
100
|
{ name = "pytest" },
|
|
57
101
|
{ name = "ruff" },
|
|
58
102
|
]
|
|
103
|
+
openai = [
|
|
104
|
+
{ name = "openai" },
|
|
105
|
+
]
|
|
59
106
|
|
|
60
107
|
[package.metadata]
|
|
61
108
|
requires-dist = [
|
|
109
|
+
{ name = "anthropic", marker = "extra == 'all'", specifier = ">=0.30" },
|
|
110
|
+
{ name = "anthropic", marker = "extra == 'anthropic'", specifier = ">=0.30" },
|
|
62
111
|
{ name = "ollama", specifier = ">=0.4.0" },
|
|
112
|
+
{ name = "openai", marker = "extra == 'all'", specifier = ">=1.0" },
|
|
113
|
+
{ name = "openai", marker = "extra == 'openai'", specifier = ">=1.0" },
|
|
63
114
|
{ name = "pytest", marker = "extra == 'dev'", specifier = ">=8" },
|
|
64
115
|
{ name = "rich", specifier = ">=13.7" },
|
|
65
116
|
{ name = "ruff", marker = "extra == 'dev'", specifier = ">=0.6" },
|
|
66
117
|
]
|
|
67
|
-
provides-extras = ["dev"]
|
|
118
|
+
provides-extras = ["dev", "openai", "anthropic", "all"]
|
|
68
119
|
|
|
69
120
|
[[package]]
|
|
70
121
|
name = "h11"
|
|
@@ -121,6 +172,78 @@ wheels = [
|
|
|
121
172
|
{ url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
|
|
122
173
|
]
|
|
123
174
|
|
|
175
|
+
[[package]]
|
|
176
|
+
name = "jiter"
|
|
177
|
+
version = "0.15.0"
|
|
178
|
+
source = { registry = "https://pypi.org/simple" }
|
|
179
|
+
sdist = { url = "https://files.pythonhosted.org/packages/66/b5/55f06bb281d92fb3cc86d14e1def2bd908bb77693183e7cb1f5a3c388b0c/jiter-0.15.0.tar.gz", hash = "sha256:4251acc80e2b7c9b7b8823456ea0fceeb0734dac2df7636d3c711b38476b5a76", size = 166640, upload-time = "2026-05-19T10:09:48.361Z" }
|
|
180
|
+
wheels = [
|
|
181
|
+
{ url = "https://files.pythonhosted.org/packages/44/53/4f6bddbcde3c71e56d0aa1337ec95950f3d27dd4153e25aadf0feac71751/jiter-0.15.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0e90a1c315a0226ec822d973817967f9223b7701546c8c2a7913e7ab0926294d", size = 308793, upload-time = "2026-05-19T10:07:35.25Z" },
|
|
182
|
+
{ url = "https://files.pythonhosted.org/packages/01/84/c01099b59a285a1ebba64ae93f62bfa036675340fd1b0045ae65890a0442/jiter-0.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8c9004af7c8d67cce7f1aae1026fb55607f4aa600710d08ede3a3ce4aeefe7e0", size = 309570, upload-time = "2026-05-19T10:07:36.919Z" },
|
|
183
|
+
{ url = "https://files.pythonhosted.org/packages/58/64/8fb7f9d45bb98190355454cd04dad8d8f27223d6bd52f83af07f637168a6/jiter-0.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c210f8b35dc6f30aafd4b4365ca89b9d1189f21ab49b8e68fa6322a847aef138", size = 336783, upload-time = "2026-05-19T10:07:38.694Z" },
|
|
184
|
+
{ url = "https://files.pythonhosted.org/packages/c3/b6/f5739011d009b3a30f6a53c5240979030ba29ae46a8c67e3a15759f7c37d/jiter-0.15.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f30bae8bc1c2d613e28e5af3e8cceb09b742f1c8a8a5f839fb67afaffc03b61", size = 363555, upload-time = "2026-05-19T10:07:40.832Z" },
|
|
185
|
+
{ url = "https://files.pythonhosted.org/packages/e5/12/98a9d9f766665e8a3b6252454e17cb0c464606a28cf2fa09399b003345fa/jiter-0.15.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c60e71b6d10cfc284c9bf36bd885e8d44c46f688ce50aa91b5edd90181dea687", size = 452255, upload-time = "2026-05-19T10:07:42.62Z" },
|
|
186
|
+
{ url = "https://files.pythonhosted.org/packages/e8/d5/60f972840f79c5e7544fce567c56f1e4e50468f996baba3e78d823dd62a6/jiter-0.15.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ab068bce62a45aa3e7367eceaffb5dde60b7eb853be8dece45132e3d0ff4879", size = 373559, upload-time = "2026-05-19T10:07:44.201Z" },
|
|
187
|
+
{ url = "https://files.pythonhosted.org/packages/ee/cf/d46ef1234ba335aabc2f013210db8e0821a22f5e644a2e9449df199ecc23/jiter-0.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa248c9eb220197d363f688818dac2fd4b2f0cd7d843ca7105d652034823427d", size = 346055, upload-time = "2026-05-19T10:07:46.005Z" },
|
|
188
|
+
{ url = "https://files.pythonhosted.org/packages/f0/63/4d2749d8d54d230bad9b3a6b0d00cc28c6ff6b2fdffc26a8ccf76cc5a974/jiter-0.15.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:2a77aadd57cac1682e4401a72724d2796d89a4ba129b1a5812aa94ee480826eb", size = 351406, upload-time = "2026-05-19T10:07:47.855Z" },
|
|
189
|
+
{ url = "https://files.pythonhosted.org/packages/d9/b9/9965b990035d8773328e0a8c8b457a87bf2b19f6c4126d9d99296be5d16a/jiter-0.15.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2ae901f3a55bfafdde31d289590fa25e3245735a2b1e8c7cc15871710a002871", size = 389357, upload-time = "2026-05-19T10:07:49.665Z" },
|
|
190
|
+
{ url = "https://files.pythonhosted.org/packages/2d/55/9ddf903deda1413e87fed792f416b7123daee5b8efbad6a202a7421c36a5/jiter-0.15.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f0b271b462769543716f92d3a4f90527df6ef5ed05ee95ec4137f513e21e1b77", size = 517263, upload-time = "2026-05-19T10:07:51.537Z" },
|
|
191
|
+
{ url = "https://files.pythonhosted.org/packages/e8/76/a0c40ad064d3a20a4fde231e35d56e9a01ce82164278180e82d5daf85469/jiter-0.15.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2fb6a5d26af81fc0f00f9360a891e05cf755e149bba391c4d563adc54812973d", size = 548646, upload-time = "2026-05-19T10:07:53.196Z" },
|
|
192
|
+
{ url = "https://files.pythonhosted.org/packages/23/4f/eca9b954942916ba2f453891b8593ab444cd872396fe66a3936616f236f3/jiter-0.15.0-cp312-cp312-win32.whl", hash = "sha256:c2f6bb8b5216ab9e7873bc08b5d7bef2b8abbb578a3069bf1cd14a45d71d771d", size = 206427, upload-time = "2026-05-19T10:07:55.307Z" },
|
|
193
|
+
{ url = "https://files.pythonhosted.org/packages/95/bf/8ead82a87495149542748e828d153fd232a512a22c83b02c4815c1a9c7d8/jiter-0.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:40b2c7e92c44a84d748d21706c68dc6ff8161d80b59c99d774721a0d2317d7c7", size = 197300, upload-time = "2026-05-19T10:07:56.651Z" },
|
|
194
|
+
{ url = "https://files.pythonhosted.org/packages/f4/e4/9b8a78fb2d894471bc344e37f1949bdd784bd914d031dba0ba3a40c71dd7/jiter-0.15.0-cp312-cp312-win_arm64.whl", hash = "sha256:cc0bc345cf2df9d1c00ac443f50d543c1ccfa8b0422cb85b1ab70d681c0b255b", size = 192702, upload-time = "2026-05-19T10:07:58.307Z" },
|
|
195
|
+
{ url = "https://files.pythonhosted.org/packages/e5/f4/f708c900ecee41b2025ef8413d5351e5649eb2125c506f6720cc69b06f5c/jiter-0.15.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1c11465f97e2abf45a014b83b730222f8f1c5335e802c7055a67d50de6f1f4e3", size = 307829, upload-time = "2026-05-19T10:07:59.704Z" },
|
|
196
|
+
{ url = "https://files.pythonhosted.org/packages/86/59/db537c0949e83668c38481d426b9f2fd5ab758c4ee53a811dd0a510626a0/jiter-0.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d1e7b1776f0797956c509e123d0952d10d293a9492dea9f288ab9570ec01d1a5", size = 308445, upload-time = "2026-05-19T10:08:01.184Z" },
|
|
197
|
+
{ url = "https://files.pythonhosted.org/packages/37/38/ea0e13b18c30ef951da0d47d39e7fa9edb82a93a62990ffbd7cea9b622d4/jiter-0.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:351a341c2105aa430b7047e30f1bf7975f6313b00165d3fc07be2edaf741f279", size = 336181, upload-time = "2026-05-19T10:08:02.688Z" },
|
|
198
|
+
{ url = "https://files.pythonhosted.org/packages/58/fc/2303901b16c4ba05865588990a420c0b4156270b44379c20931544a1d962/jiter-0.15.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4ab395feec8d249ec4044e228e98a7033f043426a265df439dc3698823f0a4e4", size = 362985, upload-time = "2026-05-19T10:08:04.394Z" },
|
|
199
|
+
{ url = "https://files.pythonhosted.org/packages/5b/6f/11bace093c52e7d4d26c8e606ccd7ae8c972189622469ec0d9e28161e28b/jiter-0.15.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2a438005b6f22d0273413484d6094d7c2c5d10ec1b3a3bf128e0d1d3ba53258", size = 453292, upload-time = "2026-05-19T10:08:05.967Z" },
|
|
200
|
+
{ url = "https://files.pythonhosted.org/packages/22/db/987f2f086ca4d7a6582eb4ccd513f9b26b42d9e4243a087609a3137a8fc7/jiter-0.15.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f18f85e4218d1b40f000f42a92239a7a61a902cd42c65e6c360dbd17dcb20894", size = 373501, upload-time = "2026-05-19T10:08:07.857Z" },
|
|
201
|
+
{ url = "https://files.pythonhosted.org/packages/8f/7c/89fbcabb2739b7a5b8dc959a1b6c5761f6484f5fed3486854b3c789bb1de/jiter-0.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1aa62e277fc1cbd80e6deacae6f4d983b41b3d7728e0645c5d741a6149bba45", size = 344683, upload-time = "2026-05-19T10:08:09.431Z" },
|
|
202
|
+
{ url = "https://files.pythonhosted.org/packages/30/6f/6cca7692e7dddfec6d8d76c54dc97f2af2a41df4ac0674b999df1f09a5f3/jiter-0.15.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:6550fa135c7deb8ead6af49ed7ff648532ea8334a1447fe34a36315ef79c5c29", size = 350892, upload-time = "2026-05-19T10:08:11.352Z" },
|
|
203
|
+
{ url = "https://files.pythonhosted.org/packages/39/14/0338d6190cb8e6d22e677ab1d4eabd4117f67cca70c54cd04b82ff64e068/jiter-0.15.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:066f8f33f18b2419cd8213b2436fa7fbc9c499f315971cfa3ce1f9820c001b1b", size = 388723, upload-time = "2026-05-19T10:08:12.912Z" },
|
|
204
|
+
{ url = "https://files.pythonhosted.org/packages/90/31/cc19f4a1bdb6afb09ce6a2f2615aa8d44d994eba0d8e6105ed1af920e736/jiter-0.15.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:75e8a04e91432dde9f1838373cf93d23726c79d3e908d319acf0e796f85592e7", size = 516648, upload-time = "2026-05-19T10:08:14.808Z" },
|
|
205
|
+
{ url = "https://files.pythonhosted.org/packages/49/9f/833c541512cd091b63c10c0381973dfe11bc7a503a818c16384417e0c81e/jiter-0.15.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:a97261f1fccb8e50ecd2890a96e46efdc3f57c80a197324c6777827231eca712", size = 547382, upload-time = "2026-05-19T10:08:16.927Z" },
|
|
206
|
+
{ url = "https://files.pythonhosted.org/packages/d2/11/e7b70e91f90bc4477e8eee9e8a5f7cf3cb41b4525d6394dc98a714eb8f7f/jiter-0.15.0-cp313-cp313-win32.whl", hash = "sha256:c77496cb10bd7549690fbbab3e5ec05857b83e49276f4a9423a766ddd2afcd4c", size = 205845, upload-time = "2026-05-19T10:08:18.401Z" },
|
|
207
|
+
{ url = "https://files.pythonhosted.org/packages/4b/23/5c20d9ad6f02c493e4023e5d2d09e1c1f15fe2753c9102c544aff068a88e/jiter-0.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b15741f501469009ae0ae90b7147958a664a7dede40aa7ff174a8a4645f546d0", size = 196842, upload-time = "2026-05-19T10:08:20.131Z" },
|
|
208
|
+
{ url = "https://files.pythonhosted.org/packages/6b/11/1eb400ef248e8c925fd883fbe325daf5e42cd1b0d308539dd332bd4f7ffc/jiter-0.15.0-cp313-cp313-win_arm64.whl", hash = "sha256:5d6a60072b44c3c2b797a7ddcbcbbf2b34ea3cfd4721580fbfd2a09d9d9b84ba", size = 192212, upload-time = "2026-05-19T10:08:21.807Z" },
|
|
209
|
+
{ url = "https://files.pythonhosted.org/packages/8a/60/2fd8d7c79da8acf9b7b277c7616847773779356b92acfc9bb158452174da/jiter-0.15.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ef1fd24d9413f6209e00d3d5a453e67acfe004a25cc6c8e8484faed4311ab9e8", size = 315065, upload-time = "2026-05-19T10:08:23.218Z" },
|
|
210
|
+
{ url = "https://files.pythonhosted.org/packages/46/f4/008fb7d65e8ac2abf00811651a661e025c4ba80bbc6f378450384ddd3aed/jiter-0.15.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:144f8e72cb53dab146347b91cceac01f5481237f2b93b4a339a1ee8f8878b67c", size = 339444, upload-time = "2026-05-19T10:08:24.701Z" },
|
|
211
|
+
{ url = "https://files.pythonhosted.org/packages/00/55/90b0c7b9c6896c0f2a591dd36d36b71d22e09674bfef178fa03ba3f81499/jiter-0.15.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:553fcac2ef2cb990877f9fc0833b8b629a3e6a5670b6b5fd58219b41a653ddc4", size = 347779, upload-time = "2026-05-19T10:08:26.408Z" },
|
|
212
|
+
{ url = "https://files.pythonhosted.org/packages/51/6b/69666cec5000fd57734c118437394516c749ae8dbeea9fb66d6fef9c4775/jiter-0.15.0-cp313-cp313t-win_amd64.whl", hash = "sha256:774f93f65031856bf14ad9f59bdcab8b8cad501e5ceabd51ba3525f76937a25b", size = 200395, upload-time = "2026-05-19T10:08:28.055Z" },
|
|
213
|
+
{ url = "https://files.pythonhosted.org/packages/39/04/a6aa62cd27e8149b0d28df5561f10f6cceaf7935a9ccf3f1c5a05f9a0cd8/jiter-0.15.0-cp313-cp313t-win_arm64.whl", hash = "sha256:f1e1754960f38ec40613a07e5e372df67acb3b890fb383b6fb3de3e49ddbf3c7", size = 190516, upload-time = "2026-05-19T10:08:29.35Z" },
|
|
214
|
+
{ url = "https://files.pythonhosted.org/packages/eb/d2/079f350ebf7859d081de30aa890f9e3be68516f754f3ba32366ffff4dcee/jiter-0.15.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:ac0d9ddea4350974be7a221fc25895f251a8fee748c889bdced2141c0fec1a49", size = 308884, upload-time = "2026-05-19T10:08:31.667Z" },
|
|
215
|
+
{ url = "https://files.pythonhosted.org/packages/04/4e/a2c30a7f69b48c03b20935d647479106fe932f6e63f75faf53937197e05d/jiter-0.15.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:01a8222cf05ab1128e239421156c207949808acaaea2bdfd33130ae666786e86", size = 310028, upload-time = "2026-05-19T10:08:33.304Z" },
|
|
216
|
+
{ url = "https://files.pythonhosted.org/packages/40/90/2e7cdfd3cf8ca967be38c48f5cf474d79f089efaf559a40f15984a77ae69/jiter-0.15.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:182226cbc930c9fab81bc2e41a4da672f89539906dadb05e75670ac07b94f71f", size = 337485, upload-time = "2026-05-19T10:08:35.259Z" },
|
|
217
|
+
{ url = "https://files.pythonhosted.org/packages/9b/11/15a1aa28b120b8ee5b4f1fb894c125046225f09847738bd64233d3b84883/jiter-0.15.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:71683c38c825452999b5717fcae07ea708e8c93003e808be4319c1b02e3d176e", size = 364223, upload-time = "2026-05-19T10:08:36.694Z" },
|
|
218
|
+
{ url = "https://files.pythonhosted.org/packages/b7/25/f442e8af5f3d0dcf47b39e83a0efd9ee45ea946aa6d04625dc3181eae3b6/jiter-0.15.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30f2218e6a9e5c18bc10fe6d41ac189c442c88eacf11bad9f28ef95a9bef00e6", size = 456387, upload-time = "2026-05-19T10:08:38.143Z" },
|
|
219
|
+
{ url = "https://files.pythonhosted.org/packages/da/f4/37f2d2c9f64f49af7da652ed7532bb5a2372e588e6927c3fdd76f911db65/jiter-0.15.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5157de9f76eb4bc5ea74a1219366a25f945ad305641d74e04f59c54087091aa9", size = 374461, upload-time = "2026-05-19T10:08:39.869Z" },
|
|
220
|
+
{ url = "https://files.pythonhosted.org/packages/60/28/edcfbbbf0cb15436f36664a8908a0df47ab9006298d4cd937dc08ea932d6/jiter-0.15.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90c5db5527c221249a876160663ab891ace358c17f7b9c93ec1478b7f0550e5c", size = 345924, upload-time = "2026-05-19T10:08:41.668Z" },
|
|
221
|
+
{ url = "https://files.pythonhosted.org/packages/47/13/89fba6398dab7f202b7278c4b4aac122399d2c0183971c4a57a3b7088df5/jiter-0.15.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:3e4540b8e74e4268811ac05db226a6a128ff572e7e0ce3f1163b693cadb184cd", size = 352283, upload-time = "2026-05-19T10:08:43.091Z" },
|
|
222
|
+
{ url = "https://files.pythonhosted.org/packages/1b/da/0f6af8cef2c565a1ab44d970f268c43ccaa72707386ea6388e6fe2b6cd26/jiter-0.15.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:62ebd14e47e9aed9df4472afcb2663668ce4d74891cd54f86bf6e44029d6dc89", size = 389985, upload-time = "2026-05-19T10:08:44.915Z" },
|
|
223
|
+
{ url = "https://files.pythonhosted.org/packages/a1/ec/b9cb7d6d29e24ee14910266157d2a279d7a8f60ee0df7fa840882976ba64/jiter-0.15.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0be6f5ad41a809f303f416d17cec92a7a725902fb9b4f3de3d19362ac0ef8554", size = 517695, upload-time = "2026-05-19T10:08:46.486Z" },
|
|
224
|
+
{ url = "https://files.pythonhosted.org/packages/64/5e/6d1bda880723aae0ad86b4b763f044362448efe31e3e819635d41cb03451/jiter-0.15.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:813dfbb17d65328bf86e5f0905dd277ba2265d3ca20556e86c0c7035b7182e5a", size = 548868, upload-time = "2026-05-19T10:08:48.026Z" },
|
|
225
|
+
{ url = "https://files.pythonhosted.org/packages/0c/72/7de501cf38dcacaf35098796f3a50e0f2e338baba18a58946c618544b809/jiter-0.15.0-cp314-cp314-win32.whl", hash = "sha256:50e51156192722a9c58db112837d3f8ef96fb3c5ecc14e95f409134b08b158ec", size = 206380, upload-time = "2026-05-19T10:08:49.738Z" },
|
|
226
|
+
{ url = "https://files.pythonhosted.org/packages/1e/a9/e19addf4b0c1bdce52c6da12351e6bc42c340c45e7c09e2158e46d293ccc/jiter-0.15.0-cp314-cp314-win_amd64.whl", hash = "sha256:30ce1a5d16b5641dc935d50ef775af6a0871e3d14ab05d6fc54dff371b78e558", size = 197687, upload-time = "2026-05-19T10:08:51.088Z" },
|
|
227
|
+
{ url = "https://files.pythonhosted.org/packages/f2/c9/776b1db01db25fc6c1d58d1979a37b0a9fe787e5f5b1d062d2eaacb77923/jiter-0.15.0-cp314-cp314-win_arm64.whl", hash = "sha256:510c8b3c17a0ed9ac69850c0438dada3c9b82d9c4d589fcb62002a5a9cf3a866", size = 192571, upload-time = "2026-05-19T10:08:52.451Z" },
|
|
228
|
+
{ url = "https://files.pythonhosted.org/packages/a0/f6/45bb4670bacf300fd2c7abadbfb3af376e5f1b6ae75fd9bc069891d15870/jiter-0.15.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7553333dd0930c104a5a0db8df72bf7219fe663d731383b576bb6ed6351c984d", size = 317151, upload-time = "2026-05-19T10:08:53.867Z" },
|
|
229
|
+
{ url = "https://files.pythonhosted.org/packages/d7/68/ed635ad5acd7b73e454283083bbb7c8205ad10e88b0d9d7d793b09fe8226/jiter-0.15.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2143ab06181d2b029eedcb6af3cebe95f11bbac62441781860f98ee9330a6a6", size = 341243, upload-time = "2026-05-19T10:08:55.383Z" },
|
|
230
|
+
{ url = "https://files.pythonhosted.org/packages/5d/db/3ff4176b817b8ea33879e71e13d8bc2b0d481a7ed3fe9e080f333d415c16/jiter-0.15.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6eac374c5c975709b69c10f09afd199df74150172156ad10c8d4fd785b7da995", size = 363629, upload-time = "2026-05-19T10:08:56.928Z" },
|
|
231
|
+
{ url = "https://files.pythonhosted.org/packages/ab/24/5f8270e0ba9c883582f96f722f8a0b58015c7ce1f8c6d4571cf394e99b6b/jiter-0.15.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b3b3b775e33d3bfaec9899edc526ae97b0da0bf9d071a46124ba419149a414f8", size = 456198, upload-time = "2026-05-19T10:08:58.618Z" },
|
|
232
|
+
{ url = "https://files.pythonhosted.org/packages/45/5b/76fc02b0b5c54c3d18c60653156e2f76fde1816f9b4722db68d6ee2c897e/jiter-0.15.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3071db3346334beae1360b46da4606da57bf3528c167b3c38533afaf9f2c5", size = 373710, upload-time = "2026-05-19T10:09:00.151Z" },
|
|
233
|
+
{ url = "https://files.pythonhosted.org/packages/c4/52/4310821b0ea9277994d3e1f49fc6a4b34e4800caebacb2c0af81da59a454/jiter-0.15.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6694a173ecabc12eb60efbc0b474464ead1951ff65cd8b1e72100715c64512b", size = 349901, upload-time = "2026-05-19T10:09:01.621Z" },
|
|
234
|
+
{ url = "https://files.pythonhosted.org/packages/93/fe/67648c35b3594fba8854ac64cc8a826d8bcd18324bbdb53d77697c60b6ef/jiter-0.15.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:a254e10b593624d230c365b6d616b22ca0ad65e63a16e6631c2b3466022e6ba8", size = 352438, upload-time = "2026-05-19T10:09:03.216Z" },
|
|
235
|
+
{ url = "https://files.pythonhosted.org/packages/cb/28/0a1879d07ad6b3e025a2750027363452ced93c2d16d1c9d4b153ffd51c91/jiter-0.15.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d8d2955167274e15d79a7a020afdd9b39c990eb80b2d89fca695d92dcfdd38ec", size = 388152, upload-time = "2026-05-19T10:09:04.741Z" },
|
|
236
|
+
{ url = "https://files.pythonhosted.org/packages/c1/78/46c6f6b56ba85c90021f4afd72ed42f691f8f84daacb5fe27277070e3858/jiter-0.15.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:acf4ee4d1fc55917239fe72972fb292dd773055d05eb040d36f4326e02cc2c0e", size = 517707, upload-time = "2026-05-19T10:09:06.231Z" },
|
|
237
|
+
{ url = "https://files.pythonhosted.org/packages/ca/cb/720662d4c88fcad606e826fef5424365527ba43ce4868a479aed8f8c507e/jiter-0.15.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:e7196e56f1cd69af1dbb07dff02dcfb260a50b45a82d409d92a06fedb32473b5", size = 548241, upload-time = "2026-05-19T10:09:08.093Z" },
|
|
238
|
+
{ url = "https://files.pythonhosted.org/packages/60/e3/935b8034fd143f21125c87d51404a9e0e1449186a494405721ff5d1d695e/jiter-0.15.0-cp314-cp314t-win32.whl", hash = "sha256:7f6163c0f10b055245f814dcc59f4818da60dfe72f3e72ab89fc24b6bd5e9c52", size = 207950, upload-time = "2026-05-19T10:09:09.616Z" },
|
|
239
|
+
{ url = "https://files.pythonhosted.org/packages/93/59/984fd9ece895953dad3e0880a650e766f5a2da2c5514f0eafdaaabbeb5f9/jiter-0.15.0-cp314-cp314t-win_amd64.whl", hash = "sha256:980c256edb05b78a111b99c4de3b1d32e31634b867fd1fc2cf726e7b7bba9854", size = 200055, upload-time = "2026-05-19T10:09:11.367Z" },
|
|
240
|
+
{ url = "https://files.pythonhosted.org/packages/0e/a4/cf8d779feb133a27a2e3bc833bccb9e13aa332cdf820497ebf72c10ce8c3/jiter-0.15.0-cp314-cp314t-win_arm64.whl", hash = "sha256:66b1880df2d01e206e8339769d1c7c1753bcb653efd6289e203f6f24ebada0c0", size = 191244, upload-time = "2026-05-19T10:09:12.74Z" },
|
|
241
|
+
{ url = "https://files.pythonhosted.org/packages/73/38/505941b2b092fd5bbbd60a52a880db1173f1690ae6751bed3af1c9ddcb4e/jiter-0.15.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:631f13a3d04e97d4e083993b10f4b99530e3a10d953e2eb5e196b7dc7f812ce0", size = 303769, upload-time = "2026-05-19T10:09:42.203Z" },
|
|
242
|
+
{ url = "https://files.pythonhosted.org/packages/e7/95/a06692b29e77473f286e1ec1f426d3ca44d7b5843be8ad21d7a5f3fcdcc0/jiter-0.15.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:b6c0ffae686c39bf3737be60793783267628783ea42545632c10b291105aee45", size = 305128, upload-time = "2026-05-19T10:09:43.657Z" },
|
|
243
|
+
{ url = "https://files.pythonhosted.org/packages/23/85/7270d7ad41d6061a25b950c6bf91d638bd9aacb113200a8c8d57a055fd67/jiter-0.15.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d54fb5b31dea401a41af3f8a7d2512e9b6a6a005491e6166c7e4ffab9639a9c", size = 340459, upload-time = "2026-05-19T10:09:45.452Z" },
|
|
244
|
+
{ url = "https://files.pythonhosted.org/packages/c8/8d/302cb2057b7513327b4d575cff6b1d066ee6431a5357fc3f8867cd684406/jiter-0.15.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54d5d6090cdc1b7c9e780dfb04949a990adb1e301a2fc0bbcee7de4638d33f9a", size = 344469, upload-time = "2026-05-19T10:09:46.864Z" },
|
|
245
|
+
]
|
|
246
|
+
|
|
124
247
|
[[package]]
|
|
125
248
|
name = "markdown-it-py"
|
|
126
249
|
version = "4.2.0"
|
|
@@ -155,6 +278,25 @@ wheels = [
|
|
|
155
278
|
{ url = "https://files.pythonhosted.org/packages/c4/ab/d6722beeb2d10f7a3b9ff49375708904fde18f82b5609a0bc4aeb5996a4d/ollama-0.6.2-py3-none-any.whl", hash = "sha256:3ad7daab28e5a973445c36a73882a3ef698c2ebb00e21e308652741577509f7d", size = 15115, upload-time = "2026-04-29T21:21:13.794Z" },
|
|
156
279
|
]
|
|
157
280
|
|
|
281
|
+
[[package]]
|
|
282
|
+
name = "openai"
|
|
283
|
+
version = "2.44.0"
|
|
284
|
+
source = { registry = "https://pypi.org/simple" }
|
|
285
|
+
dependencies = [
|
|
286
|
+
{ name = "anyio" },
|
|
287
|
+
{ name = "distro" },
|
|
288
|
+
{ name = "httpx" },
|
|
289
|
+
{ name = "jiter" },
|
|
290
|
+
{ name = "pydantic" },
|
|
291
|
+
{ name = "sniffio" },
|
|
292
|
+
{ name = "tqdm" },
|
|
293
|
+
{ name = "typing-extensions" },
|
|
294
|
+
]
|
|
295
|
+
sdist = { url = "https://files.pythonhosted.org/packages/49/f5/7c7cb955305cb41f7f3c5fd7e0e38bf6bbf2658468863d4b7b868a5cb8df/openai-2.44.0.tar.gz", hash = "sha256:68a5a5ffad82b8ff7d451c437529fb64f7c3b8123aaf0c021966a882d9e3947d", size = 988753, upload-time = "2026-06-24T20:56:02.293Z" }
|
|
296
|
+
wheels = [
|
|
297
|
+
{ url = "https://files.pythonhosted.org/packages/ae/f4/561ed79fd94876160018a5e75254cfcb9b0e62d4dded9dcb20072e86d623/openai-2.44.0-py3-none-any.whl", hash = "sha256:0a2a3ab2e29aeda368700f662ff9ba0f9df17ba4c54577a64e08b8115a3cc0ad", size = 1366216, upload-time = "2026-06-24T20:55:58.882Z" },
|
|
298
|
+
]
|
|
299
|
+
|
|
158
300
|
[[package]]
|
|
159
301
|
name = "packaging"
|
|
160
302
|
version = "26.2"
|
|
@@ -326,6 +468,27 @@ wheels = [
|
|
|
326
468
|
{ url = "https://files.pythonhosted.org/packages/30/66/9a73695e31eaee04f35d8475998bf8ab354465f9c638936d76111603dcc5/ruff-0.15.19-py3-none-win_arm64.whl", hash = "sha256:6c6b607466e47349332eb1d9be52fb1467423fc07c217341af41cd0f3f0573be", size = 11376779, upload-time = "2026-06-24T01:10:34.465Z" },
|
|
327
469
|
]
|
|
328
470
|
|
|
471
|
+
[[package]]
|
|
472
|
+
name = "sniffio"
|
|
473
|
+
version = "1.3.1"
|
|
474
|
+
source = { registry = "https://pypi.org/simple" }
|
|
475
|
+
sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" }
|
|
476
|
+
wheels = [
|
|
477
|
+
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" },
|
|
478
|
+
]
|
|
479
|
+
|
|
480
|
+
[[package]]
|
|
481
|
+
name = "tqdm"
|
|
482
|
+
version = "4.68.3"
|
|
483
|
+
source = { registry = "https://pypi.org/simple" }
|
|
484
|
+
dependencies = [
|
|
485
|
+
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
|
486
|
+
]
|
|
487
|
+
sdist = { url = "https://files.pythonhosted.org/packages/87/d7/0535a28b1f5f24f6612fb3ff1e89fb1a8d160fee0f976e0aa6803862134b/tqdm-4.68.3.tar.gz", hash = "sha256:00dfa48452b6b6cfae3dd9885636c23d3422d1ec97c66d96818cbd5e0821d482", size = 170596, upload-time = "2026-06-17T07:36:52.105Z" }
|
|
488
|
+
wheels = [
|
|
489
|
+
{ url = "https://files.pythonhosted.org/packages/d8/8e/bb97bb0c71802080bfc8952937d174e49cfc50de5c951dd47b2496f0dcdb/tqdm-4.68.3-py3-none-any.whl", hash = "sha256:39832cc2def2789a6f29df83f172db7416cea70052c0907a57801c5f2fdccb03", size = 78337, upload-time = "2026-06-17T07:36:50.132Z" },
|
|
490
|
+
]
|
|
491
|
+
|
|
329
492
|
[[package]]
|
|
330
493
|
name = "typing-extensions"
|
|
331
494
|
version = "4.15.0"
|
fastevolve-0.2.1/PKG-INFO
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: fastevolve
|
|
3
|
-
Version: 0.2.1
|
|
4
|
-
Summary: Minimal open-source AlphaEvolve: LLM-driven program evolution with MAP-Elites islands, cascade evaluation, and a local Ollama ensemble.
|
|
5
|
-
Project-URL: Homepage, https://github.com/tiagomonteiro0715/fastevolve
|
|
6
|
-
Project-URL: Repository, https://github.com/tiagomonteiro0715/fastevolve
|
|
7
|
-
Project-URL: Issues, https://github.com/tiagomonteiro0715/fastevolve/issues
|
|
8
|
-
Author-email: Tiago Monteiro <monteiro.t@northeastern.edu>
|
|
9
|
-
License: MIT
|
|
10
|
-
Keywords: alphaevolve,evolutionary-search,llm,map-elites,ollama,program-synthesis
|
|
11
|
-
Classifier: Development Status :: 3 - Alpha
|
|
12
|
-
Classifier: Intended Audience :: Science/Research
|
|
13
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
-
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
16
|
-
Requires-Python: >=3.12
|
|
17
|
-
Requires-Dist: ollama>=0.4.0
|
|
18
|
-
Requires-Dist: rich>=13.7
|
|
19
|
-
Provides-Extra: dev
|
|
20
|
-
Requires-Dist: pytest>=8; extra == 'dev'
|
|
21
|
-
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
22
|
-
Description-Content-Type: text/markdown
|
|
23
|
-
|
|
24
|
-
# fastevolve
|
|
25
|
-
|
|
26
|
-
Minimal open-source AlphaEvolve: LLM-driven program evolution with MAP-Elites islands, cascade evaluation, and a local Ollama ensemble.
|
|
27
|
-
|
|
28
|
-
## Install
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
uv sync
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## Run the demo
|
|
35
|
-
|
|
36
|
-
Start Ollama and pull the model first:
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
ollama serve
|
|
40
|
-
ollama pull gemma3:e4b
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
Then:
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
uv run python main.py
|
|
47
|
-
```
|
fastevolve-0.2.1/README.md
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# fastevolve
|
|
2
|
-
|
|
3
|
-
Minimal open-source AlphaEvolve: LLM-driven program evolution with MAP-Elites islands, cascade evaluation, and a local Ollama ensemble.
|
|
4
|
-
|
|
5
|
-
## Install
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
uv sync
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Run the demo
|
|
12
|
-
|
|
13
|
-
Start Ollama and pull the model first:
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
ollama serve
|
|
17
|
-
ollama pull gemma3:e4b
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
Then:
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
uv run python main.py
|
|
24
|
-
```
|
|
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
|