A generic, generate framework for AI agents to learn from their experiences and improve over time by extracting reusable patterns from sessions.
This framework implements the self-evolution pattern from OpenAI's cookbook, adapted as a general-purpose solution rather than a domain-specific implementation. It enables AI agents to:
- Evaluate their outputs using multiple independent scorers
- Identify weaknesses based on feedback
- Generate improved prompts automatically
- Track and version all prompt changes
- Select optimal prompts based on aggregate performance
The framework consists of four main components:
- Evaluator - Runs multiple scorers to evaluate agent outputs
- PromptVersioner - Manages prompt versions and history
- MetaPromptAgent - Optimizes prompts based on feedback
- SelfEvolvingAgent - Orchestrates the evolution loop
pip install openaiimport asyncio
from openai import OpenAI
from openai_selfevo import (
SelfEvolvingAgent,
Evaluator,
PromptVersioner,
MetaPromptAgent,
create_default_scorers,
)
async def main():
client = OpenAI(api_key="your-api-key")
# Create base agent
def basic_agent(input_text: str) -> str:
response = client.chat.completions.create(
model="gpt-4.1",
messages=[{"role": "user", "content": input_text}]
)
return response.choices[0].message.content
# Create evaluator
evaluator = Evaluator(scorers=create_default_scorers())
# Create prompt versioner
prompter = PromptVersioner(
initial_prompt="You are a helpful assistant."
)
# Create self-evolving agent
agent = SelfEvolvingAgent(
base_agent=basic_agent,
evaluator=evaluator,
prompter=prompter,
max_retries=3
)
# Dataset for optimization
dataset = [
{"section_number": "1", "content": "What is Python?"},
{"section_number": "2", "content": "Explain lists vs tuples"},
]
# Run evolution
best_prompt = await agent.evolve(dataset, verbose=True)
print(f"Optimized prompt:\n{best_prompt.prompt}")
asyncio.run(main())The framework supports multiple scorer types:
| Scorer | Description |
|---|---|
PythonScorer |
Custom Python functions for deterministic evaluation |
TextSimilarityScorer |
Cosine similarity on embeddings |
LLMAsJudgeScorer |
LLM-based quality assessment |
You can create custom scorers by implementing the Scorer interface or using PythonScorer:
from openai_selfevo import PythonScorer
keyword_scorer = PythonScorer(
name="keyword_coverage",
pass_threshold=0.8,
source=r"""
def grade(sample: dict, item: dict) -> float:
output = item.get("output_text", "").lower()
required_keywords = ["important", "key", "essential"]
found = sum(1 for kw in required_keywords if kw in output)
return found / len(required_keywords)
"""
)The PromptVersioner tracks all prompt changes:
prompter = PromptVersioner(initial_prompt="...")
# Get current prompt
current = prompter.current
# Update to new prompt
new_version = prompter.update(new_prompt="...")
# Revert to previous version
prompter.revert_to(version=1)
# Get history
history = prompter.history()# Run the example script
python example.py
# Or use the framework in your own code
python -c "from openai_selfevo import *; # your code here"| Parameter | Default | Description |
|---|---|---|
max_retries |
3 | Maximum attempts per sample |
lenient_pass_ratio |
0.75 | Ratio of scorers that must pass |
lenient_avg_threshold |
0.85 | Average score threshold |
self_evo/
├── openai_selfevo.py # Main framework implementation
├── example.py # Example usage script
├── plans/
│ └── architecture.md # Architecture documentation
└── README.md # This file
MIT License - See LICENSE file for details.