😅 Prompts Aligned to Guidelines and Normalization System - Optimize prompts for OpenAI, Anthropic, xAI, and Google models
Project description
PAGANS - Prompt Optimization Framework 😅
PAGANS (Prompts Aligned to Guidelines and Normalization System) is a powerful prompt optimization framework that works exclusively with OpenRouter to optimize prompts across different LLM model families. By leveraging model-specific optimization strategies, PAGANS ensures your prompts are perfectly aligned with each model family's unique characteristics and best practices.
✨ Features
- 🚀 Fast Optimization: Optimize prompts in under 10 seconds
- 🎯 Model Family Optimization: Specialized optimization strategies for OpenAI, Anthropic, xAI Grok, and Google model families
- 🔗 OpenRouter Integration: Seamless integration with OpenRouter for access to all major model families
- 🔄 Async Support: Full asynchronous API for high-throughput optimization
- 📊 Performance Metrics: Track optimization time and token usage
- 🔧 Easy Integration: Simple API that integrates seamlessly into existing workflows
- 🧠 Smart Caching: Built-in caching to avoid redundant optimizations
- ⚡ Batch Processing: Optimize multiple prompts concurrently
- 📈 Model Comparison: Compare optimization results across different model families
- 🎨 Family-Aware Prompts: Automatically adapts prompts to each model family's unique characteristics
🎯 Model Family Optimization
PAGANS excels at understanding the unique characteristics of different LLM model families and optimizing prompts accordingly:
OpenAI Models (GPT Series)
- Emphasizes clear structure and explicit instructions
- Benefits from chain-of-thought prompting techniques
- Optimized for conversational and creative tasks
Anthropic Models (Claude Series)
- Focuses on safety and helpfulness guidelines
- Works best with detailed context and examples
- Excels at analysis and reasoning tasks
Google Models (Gemini Series)
- Leverages multimodal capabilities when available
- Optimized for factual accuracy and research
- Performs well with structured data and technical content
xAI Models (Grok Series)
- Responds best to explicit goals, constraints, and concrete context
- Strong performance for reasoning-heavy and agentic coding tasks
- Benefits from structured prompt sections and iterative refinement
The optimization process automatically detects the target model family and applies the most effective strategies for that specific family, ensuring optimal performance across all supported models.
📦 Installation
From PyPI (Recommended)
pip install pagans
From Source
git clone https://github.com/abubakarsiddik31/pagans.git
cd pagans
uv sync
Development Installation
git clone https://github.com/abubakarsiddik31/pagans.git
cd pagans
uv sync --dev
🔧 Quick Start
Basic Usage
import asyncio
from pagans import PAGANSOptimizer
async def main():
# Initialize PAGANS optimizer with your OpenRouter API key
optimizer = PAGANSOptimizer(api_key="your-openrouter-api-key")
# Your original prompt
prompt = "Write a Python function to calculate fibonacci numbers"
# Optimize for a specific model family
result = await optimizer.optimize(
prompt=prompt,
target_model="claude-sonnet-4" # Short model name
)
print(f"Original: {result.original}")
print(f"Optimized: {result.optimized}")
print(f"Target Model: {result.target_model}")
print(f"Model Family: {result.target_family.value}")
print(f"Optimization Time: {result.optimization_time:.2f}s")
await optimizer.close()
asyncio.run(main())
How It Works
PAGANS separates the target model (what you're optimizing for) from the optimizer model (what does the work):
# The optimizer model (from environment) does the actual optimization work
# The target model is what you're optimizing FOR
result = await optimizer.optimize(
prompt="Explain quantum computing",
target_model="claude-sonnet-4" # What you're optimizing FOR
)
# PAGANS automatically detects the model family and applies the right optimization strategy
result2 = await optimizer.optimize(
prompt="Explain quantum computing",
target_model="gpt-4o" # Different model family, different optimization strategy
)
Environment Configuration
export OPENROUTER_API_KEY="your-api-key-here"
export PAGANS_OPTIMIZER_MODEL="openai/gpt-4o-mini" # Model that does the optimization work
Using Environment Variables
import asyncio
from pagans import PAGANSOptimizer
async def main():
# Configuration loaded from environment variables
optimizer = PAGANSOptimizer()
result = await optimizer.optimize(
prompt="Explain quantum computing",
target_model="claude-3.5-sonnet" # What you're optimizing FOR
)
print(f"Optimized for: {result.target_model}")
print(f"Optimization: {result.optimized}")
await optimizer.close()
asyncio.run(main())
Context Manager (Recommended)
import asyncio
from pagans import PAGANSOptimizer
async def main():
async with PAGANSOptimizer() as optimizer:
result = await optimizer.optimize(
prompt="Create a REST API in Node.js",
target_model="gemini-2.5-pro"
)
print(result.optimized)
🎯 Supported Models
Short Model Names (Recommended)
Use these convenient short names with PAGANS:
| Family | Short Names | Available via OpenRouter |
|---|---|---|
| OpenAI | gpt-5.4, gpt-5.4-pro, gpt-5-mini, gpt-5-nano, gpt-4.1, gpt-4o |
✅ |
| Anthropic | claude-opus-4.6, claude-sonnet-4.6, claude-haiku-4.5, claude-opus-4.1, claude-sonnet-4 |
✅ |
| xAI | grok-4.20-beta, grok-4, grok-4-fast, grok-code-fast-1 |
✅ |
gemini-3.1-pro-preview, gemini-3-flash-preview, gemini-3.1-flash-lite-preview, gemini-2.5-pro, gemini-2.5-flash |
✅ |
Full Model Names
You can also use full OpenRouter model names:
| Family | Full Model Names |
|---|---|
| OpenAI | openai/gpt-5.4, openai/gpt-5.4-pro, openai/gpt-5.4-mini, openai/gpt-5.4-nano, openai/gpt-4.1, openai/gpt-4o |
| Anthropic | anthropic/claude-opus-4.6, anthropic/claude-sonnet-4.6, anthropic/claude-haiku-4.5, anthropic/claude-opus-4.1 |
| xAI | x-ai/grok-4.20-beta, x-ai/grok-4, x-ai/grok-4-fast, x-ai/grok-code-fast-1 |
google/gemini-3.1-pro-preview, google/gemini-3-flash-preview, google/gemini-3.1-flash-lite-preview, google/gemini-2.5-pro, google/gemini-2.5-flash |
✨ Key Feature: PAGANS automatically detects the model family and applies the appropriate optimization strategy for optimal results!
📚 Examples
See the examples/ directory for complete working examples:
Basic PAGANS Example
# Set your OpenRouter API key (get one at https://openrouter.ai/)
export OPENROUTER_API_KEY="your-openrouter-api-key-here"
# Run the basic example
uv run examples/openai_example.py
Model Family Examples
# Set your OpenRouter API key (get one at https://openrouter.ai/)
export OPENROUTER_API_KEY="your-openrouter-api-key-here"
# Run examples for different model families
uv run examples/anthropic_example.py # Claude models
uv run examples/google_example.py # Gemini models
Advanced Examples
# Provider factory example (legacy)
uv run examples/provider_factory_example.py
Notebook Example
# Launch Jupyter and open the quickstart notebook
uv sync --dev
uv run jupyter lab
Open: notebooks/pagans_quickstart.ipynb
🛠️ CLI Usage
PAGANS includes a CLI installed as pagans.
Optimize One Prompt
pagans optimize \
--prompt "Write a robust retry policy for external API calls" \
--target-model gpt-5.4
Compare Across Models
pagans compare \
--prompt "Design an event-driven architecture for order processing" \
--models "gpt-5.4,claude-sonnet-4-20250514,gemini-3.1-pro-preview,grok-4-1-fast-reasoning"
Batch From File
pagans batch \
--prompts-file ./prompts.txt \
--target-model gemini-3.1-pro-preview \
--max-concurrent 5
JSON Output
pagans optimize \
--prompt "Summarize this technical RFC" \
--target-model claude-opus-4-20250514 \
--json
For full CLI docs, see docs/CLI.md.
🔧 Advanced Usage
Batch Processing
import asyncio
from pagans import PAGANSOptimizer
async def batch_optimize():
prompts = [
"Write a Python function",
"Explain machine learning",
"Create a React component"
]
async with PAGANSOptimizer() as optimizer:
results = await optimizer.optimize_multiple(
prompts=prompts,
target_model="gpt-4o",
max_concurrent=3
)
for result in results:
print(f"Optimized: {result.optimized}")
Compare Across Model Families
import asyncio
from pagans import PAGANSOptimizer
async def compare_models():
prompt = "Write a function to reverse a string"
async with PAGANSOptimizer() as optimizer:
results = await optimizer.compare_optimizations(
prompt=prompt,
target_models=[
"gpt-4o", # OpenAI family
"claude-3.5-sonnet", # Anthropic family
"gemini-2.5-pro" # Google family
]
)
for model, result in results.items():
print(f"{model}: {result.optimized[:50]}...")
Custom Configuration
import asyncio
from pagans import PAGANSOptimizer
async def custom_config():
optimizer = PAGANSOptimizer(
api_key="your-api-key",
base_url="https://custom.openrouter.url",
timeout=30.0,
max_retries=5,
retry_delay=2.0
)
result = await optimizer.optimize(
prompt="Your prompt here",
target_model="gpt-4o"
)
await optimizer.close()
🏗️ API Reference
PAGANSOptimizer
__init__(api_key=None, base_url=None, optimizer_model=None, timeout=30.0, max_retries=3, retry_delay=1.0)
Initialize the PAGANSOptimizer.
Parameters:
api_key(str, optional): OpenRouter API keybase_url(str, optional): OpenRouter base URLoptimizer_model(str, optional): Model that does the optimization worktimeout(float): Request timeout in secondsmax_retries(int): Maximum number of retry attemptsretry_delay(float): Delay between retry attempts
async optimize(prompt, target_model=None, optimization_notes=None, use_cache=True)
Optimize a prompt for a specific target model.
Parameters:
prompt(str): The original prompt to optimizetarget_model(str, optional): Target model nameoptimization_notes(str, optional): Additional optimization notesuse_cache(bool): Whether to use caching
Returns: OptimizationResult
async optimize_multiple(prompts, target_model=None, optimization_notes=None, use_cache=True, max_concurrent=3)
Optimize multiple prompts concurrently.
Parameters:
prompts(list[str]): List of prompts to optimizetarget_model(str, optional): Target model nameoptimization_notes(str, optional): Additional optimization notesuse_cache(bool): Whether to use cachingmax_concurrent(int): Maximum concurrent optimizations
Returns: list[OptimizationResult]
OptimizationResult
Attributes:
original(str): Original promptoptimized(str): Optimized prompttarget_model(str): Target model nametarget_family(ModelFamily): Model family enumprovider(str, optional): Provider used (always OpenRouter)optimization_notes(str, optional): Optimization notestokens_used(int, optional): Tokens used in optimizationoptimization_time(float, optional): Time taken in seconds
⚙️ Configuration
Environment Variables
OPENROUTER_API_KEY: Your OpenRouter API key (required)PAGANS_OPTIMIZER_MODEL: The model that does the optimization work (optional)OPENROUTER_BASE_URL: Custom OpenRouter base URL (optional)
.env File Support
Create a .env file in your project root:
OPENROUTER_API_KEY=your-api-key-here
OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
PAGANS_OPTIMIZER_MODEL=openai/gpt-4o-mini
Important Environment Variables:
OPENROUTER_API_KEY: Your OpenRouter API key (required)PAGANS_OPTIMIZER_MODEL: The model that does the optimization work (optional, defaults toopenai/gpt-4o-mini)OPENROUTER_BASE_URL: Custom OpenRouter base URL (optional)
🧪 Testing
This project uses uv for dependency management and running commands.
Run the test suite:
uv run pytest
Run with coverage:
uv run pytest --cov=pagans --cov-report=html
🚀 What's Coming Next
We're actively working on exciting new features! Here's what's on our roadmap:
🔥 Coming Soon
- 🤖 Extended Model Families - Support for Meta Llama, Mistral, Cohere, and Perplexity models via OpenRouter
- ⚡ Advanced Caching - Redis-based distributed caching with semantic similarity matching
- 🎨 Custom Optimization Strategies - Allow users to define their own optimization approaches
🎯 Planned Features
- 🔄 A/B Testing Framework - Compare optimization strategies and automatically select the best approach
- 📊 Performance Analytics - Track optimization success rates, cost savings, and performance metrics
- 🛠️ CLI Tool - Command-line interface for batch processing and automation
- 🌐 Web Dashboard - Simple web UI for testing and managing optimizations
- 🔌 Framework Integrations - Native support for LangChain, LlamaIndex, and Haystack
- 📱 IDE Extensions - VS Code extension for in-editor prompt optimization
Want to contribute to any of these features? Check out our agents.md for developer guidelines!
🤝 Contributing
Contributions are welcome.
- Contribution guide:
CONTRIBUTING.md - Code of Conduct:
CODE_OF_CONDUCT.md - Security policy:
SECURITY.md - Support:
SUPPORT.md - Developer architecture notes:
agents.md
Quick flow:
- Fork and clone the repository.
- Create a feature branch.
- Run tests and lint locally.
- Open a pull request with context and tests.
📦 Publishing
PyPI publishing guide is available at:
Automated publishing workflow:
📝 License
This project is licensed under the MIT License - see the LICENSE file for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pagans-0.1.2.tar.gz.
File metadata
- Download URL: pagans-0.1.2.tar.gz
- Upload date:
- Size: 343.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fda7d92f8a68c20be955899b64795b31b313ab1c86b6e318aa52140dc291c4f9
|
|
| MD5 |
9f9bc76e59368b022221087bdae833d3
|
|
| BLAKE2b-256 |
1f7d8c38e7172a4297062c6d42f2dfecad4beb9c59d57d9d45f755d0e03d5ece
|
File details
Details for the file pagans-0.1.2-py3-none-any.whl.
File metadata
- Download URL: pagans-0.1.2-py3-none-any.whl
- Upload date:
- Size: 44.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a93a549dc4d7355ea4597755b8ebedb646e35c213e38bd222f94c6934f8761fc
|
|
| MD5 |
53ebebc0d10077d3371f69a78c334ac3
|
|
| BLAKE2b-256 |
9634b22ea7e2a99c05d4af8c22af2ee5fadab3c5b16edf79cd2066641546c83a
|