Skip to main content

Evolvable AI programs: define a function + criteria, let an LLM iteratively improve it

Project description

evolvers

PyPI CI License: Apache-2.0 Python Downloads

Evolvable AI programs: define a Python function + criteria of success, the bound LLM iteratively rewrites the function body to maximize the criteria score.

Status: early PoC. APIs will change.

Idea

A program is a Python function with an injected llm. Criteria are either natural-language LLM judges or plain code, each scoring outputs in [-1, 1]. An LLM-driven optimizer proposes mutations to the function body; mutations that improve the weighted score are accepted, the rest are reverted. Trained programs save to disk and reload by URI.

Quick look

evolvers is async-primary — train, evaluate, and calling an Evolvable are coroutines.

End-to-end runnable example: fetch a small dataset with lurkers, then train a TLDR program against it.

uv add evolvers lurkers
import asyncio
import evolvers as ev
import lurkers

def tldr(input_text: str, llm) -> str:
    return input_text[:130] + "..."  # naive baseline; the optimizer rewrites this

async def main():
    # Bring your own data — here, three arXiv abstracts.
    docs = await asyncio.gather(
        lurkers.afetch("https://arxiv.org/abs/1706.03762"),  # Attention Is All You Need
        lurkers.afetch("https://arxiv.org/abs/2005.14165"),  # GPT-3
        lurkers.afetch("https://arxiv.org/abs/2310.06825"),  # Mistral 7B
    )
    dataset = [d.content for d in docs]

    llm = ev.LLM(model="claude-opus-4-7")  # or any OpenAI-compatible endpoint

    evo = ev.Evolvable(
        tldr,
        criteria=[
            ev.judge("Does it directly summarize the main points as a TLDR?"),
            ev.code(lambda output_text:
                max(-1.0, 1 - 2 * max(0, (len(output_text) - 140) / 140))),
        ],
        llm=llm,
    )

    await evo.train(dataset, num_train_epochs=10)
    print(evo.source)  # the function body the optimizer settled on
    evo.save("you/tldr-v1:claude-opus-4-7")

    reloaded = ev.Evolvable.load("you/tldr-v1:claude-opus-4-7")
    print(await reloaded(dataset[0]))

asyncio.run(main())

Sync wrappers (evo.train_sync, evo.evaluate_sync, evo.call_sync) exist for non-async codebases. See examples/with_lurkers.py for the full version.

Install (from source)

git clone https://github.com/tiramisu-sh/evolvers
cd evolvers
uv sync

What works today

  • ev.LLM against Anthropic and OpenAI-compatible endpoints (vLLM, Ollama, OpenAI, Azure)
  • Structured output via pydantic schemas (schema=)
  • ev.judge(question) + ev.code(callable) criteria; lambdas captured as def for round-tripping
  • await evo.train(dataset, num_train_epochs=N) — propose-test-accept-or-revert loop driven by the bound LLM
  • Evolvable.save("owner/name:variant") / Evolvable.load(...) for sharing trained programs
  • Evolvable.clone().set_llm(other) for variants

Validated end-to-end against a local Qwen3.5-27B reasoning model: naive truncation baseline → optimized LLM-using TLDR in one mutation attempt.

License

Apache-2.0.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

evolvers-0.2.0.tar.gz (54.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

evolvers-0.2.0-py3-none-any.whl (22.8 kB view details)

Uploaded Python 3

File details

Details for the file evolvers-0.2.0.tar.gz.

File metadata

  • Download URL: evolvers-0.2.0.tar.gz
  • Upload date:
  • Size: 54.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for evolvers-0.2.0.tar.gz
Algorithm Hash digest
SHA256 9955567dbf42af9c8f74aa751f753831058be008329f10977ec30cd9baaf3785
MD5 16031b1e984616d29db7d0b58fdad173
BLAKE2b-256 622708292852de390caea2bf70e833bd51516444ffe9efe01b289893321be825

See more details on using hashes here.

File details

Details for the file evolvers-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: evolvers-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 22.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for evolvers-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c5a1737220d2e429ee84a039fa3dab0f2585838635ab187c4f5a3ca60b07792a
MD5 223d2cdb00b7246a8b716d92ff625679
BLAKE2b-256 541ab3b5a99143aec5d07d07f9eca48a5186ea76513f5406ea7540b07ce3a6fe

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page