(no commit message)

This commit is contained in:
2025-11-05 09:58:12 -05:00
parent ec07718eb3
commit 5d1d88364a

369
README.md
View File

@@ -1,10 +1,371 @@
# Prompt To Signature
Transform your ideas and prompts into DSPy signatures using the Prompt To Signature Agent!
Transform your ideas and prompts into executable DSPy signatures using AI! This agent automatically converts natural language descriptions into properly typed, production-ready DSPy signatures with support for complex nested structures, Pydantic models, and more.
## Features
- **Natural Language to DSPy Signature**: Convert ideas like "Translate English to German" or "Count people on the image" into a full `dspy.Signature`.
- **Dynamic Class Factory**: Generate and use `dspy.Signature` classes at runtime.
- **Interactive Refinement**: Iteratively improve generated signatures by providing feedback in a loop.
- **Natural Language to DSPy Signature**: Convert ideas like "Translate English to German" or "Analyze sentiment from product reviews" into full `dspy.Signature` classes
- **Smart Type Inference**: Automatically determines appropriate field types (str, int, list, dict, Pydantic models, Literal types, etc.)
- **Dynamic Class Factory**: Generate and use `dspy.Signature` classes at runtime
- **Interactive Refinement**: Iteratively improve generated signatures by providing feedback in a loop
- **Complex Nested Structures**: Full support for Pydantic models with nested fields for structured outputs
- **Code Generation**: Export signatures as clean, executable Python code
## Quick Start with Modaic AutoAgent
The easiest way to use this agent is by loading it from Modaic Hub:
```python
from modaic import AutoAgent
# Load the precompiled agent from hub
agent = AutoAgent.from_precompiled("fadeleke/prompt-to-signature")
# Use the agent
prompt = "Translate text from English to French"
result = agent(prompt)
# Generate executable code
code = agent.generate_code(result)
print(code)
```
### With Custom Configuration
Override default configuration parameters:
```python
from modaic import AutoAgent
agent = AutoAgent.from_precompiled(
"fadeleke/prompt-to-signature",
config={
"lm": "openrouter/anthropic/claude-sonnet-4.5",
"max_tokens": 32000,
"temperature": 0.7,
}
)
result = agent("Summarize a document and extract key entities")
```
## Manual Installation & Setup
If you prefer to run the agent locally:
### Prerequisites
- Python 3.11+
- [uv](https://docs.astral.sh/uv/) package manager
### Installation
1. Clone the repository:
```bash
git clone <repository-url>
cd vibe-dspy-agent
```
2. Install dependencies:
```bash
uv sync
```
3. Set up environment variables:
```bash
# Create a .env file
echo "OPENROUTER_API_KEY=your_api_key_here" > .env
```
Get your OpenRouter API key from [openrouter.ai](https://openrouter.ai/)
### Usage
```python
from agent import PromptToSignatureAgent, PromptToSignatureConfig
# Initialize the agent
config = PromptToSignatureConfig(
lm="openrouter/anthropic/claude-haiku-4.5",
max_tokens=16000,
temperature=1.0,
)
agent = PromptToSignatureAgent(config)
# Generate a signature from a prompt
prompt = """
Create a signature that takes a customer review and extracts:
- Overall sentiment (positive, negative, neutral)
- Key issues mentioned
- Recommended rating (1-5 stars)
"""
result = agent(prompt)
# Generate executable Python code
code = agent.generate_code(result)
print(code)
```
### Interactive Refinement Mode
Use the refinement loop to iteratively improve signatures:
```python
# Enable refinement with user feedback
result = agent(prompt, refine=True)
# The agent will:
# 1. Generate an initial signature
# 2. Show it to you for review
# 3. Ask if you're satisfied (y/n)
# 4. If not, ask for feedback
# 5. Regenerate with your feedback
# 6. Repeat up to max_attempts_to_refine times
```
## Examples
### Simple Translation Signature
```python
prompt = "Translate text from English to Spanish"
result = agent(prompt)
code = agent.generate_code(result)
```
**Generated Output:**
```python
import dspy
class TranslateEnglishToSpanish(dspy.Signature):
"""Translate English text to Spanish"""
english_text: str = dspy.InputField(desc="The English text to translate")
spanish_translation: str = dspy.OutputField(desc="The translated Spanish text")
```
### Complex Sentiment Analysis
```python
prompt = """
Analyze product reviews and extract:
- Overall sentiment (positive/negative/mixed/neutral)
- Confidence score (0-1)
- Specific issues mentioned
- Specific praise points
- Predicted star rating (1-5)
"""
result = agent(prompt)
code = agent.generate_code(result)
```
**Generated Output:**
```python
import dspy
from typing import List, Literal
from pydantic import BaseModel, Field
class Issue(BaseModel):
"""Represents a specific issue mentioned in the review"""
description: str = Field(description="Description of the issue")
severity: Literal["minor", "moderate", "severe"] = Field(description="Severity level of the issue")
class PraisePoint(BaseModel):
"""Represents a specific praise point mentioned in the review"""
description: str = Field(description="Description of the praise")
class SentimentAnalysis(BaseModel):
"""Complete sentiment analysis result"""
overall_sentiment: Literal["positive", "negative", "mixed", "neutral"] = Field(description="Overall sentiment classification")
confidence_score: float = Field(description="Confidence score between 0 and 1")
issues: List[Issue] = Field(description="List of specific issues mentioned")
praise_points: List[PraisePoint] = Field(description="List of specific praise points")
predicted_rating: int = Field(description="Predicted star rating from 1 to 5")
class AnalyzeProductReview(dspy.Signature):
"""Analyze product reviews to extract sentiment, issues, praise, and rating"""
review_text: str = dspy.InputField(desc="The product review text to analyze")
analysis: SentimentAnalysis = dspy.OutputField(desc="Complete sentiment analysis with structured output")
```
### Multimodal Signatures
```python
prompt = "Count the number of people in an image and describe what they're doing"
result = agent(prompt)
```
**Generated Output:**
```python
import dspy
class CountPeopleInImage(dspy.Signature):
"""Count people in an image and describe their activities"""
image: dspy.Image = dspy.InputField(desc="The image to analyze")
people_count: int = dspy.OutputField(desc="Number of people detected")
activity_description: str = dspy.OutputField(desc="Description of what people are doing")
```
## Architecture
### Core Components
#### 1. SignatureGenerator (`agent/modules.py`)
The heart of the system. This DSPy module:
- Takes natural language prompts as input
- Uses a structured `SignatureGeneration` signature to ensure consistent output
- Generates properly typed field definitions
- Supports complex types: Pydantic models, Literal types, Lists, Dicts, Optional fields
- Creates executable Python code from predictions
**Key Classes:**
- `FieldType`: Enum of all supported Python types
- `GeneratedField`: Represents a single input/output field
- `PydanticModelSchema`: Schema for nested Pydantic models
- `SignatureGenerator`: Main DSPy module for signature generation
#### 2. PromptToSignatureAgent (`agent/index.py`)
The high-level agent wrapper that:
- Extends `modaic.PrecompiledAgent` for hub deployment
- Configures LLM models (defaults to Claude Haiku 4.5 via OpenRouter)
- Implements refinement loop with `dspy.Refine`
- Validates signatures with user feedback
**Configuration Options:**
```python
class PromptToSignatureConfig:
lm: str = "openrouter/anthropic/claude-haiku-4.5"
refine_lm: str = "openrouter/anthropic/claude-haiku-4.5"
max_tokens: int = 16000
temperature: float = 1.0
max_attempts_to_refine: int = 5
```
#### 3. Utilities (`agent/utils.py`)
Helper functions for:
- Converting names to snake_case
- Saving generated signatures to files
- Managing OpenRouter API configuration
### How It Works
1. **Input Processing**: Natural language prompt describing the desired functionality
2. **LLM Generation**: DSPy's structured prediction generates typed field definitions
3. **Schema Construction**: Builds internal representation of the signature with full type info
4. **Code Generation**: Converts the structured representation to executable Python code
5. **Optional Refinement**: User can provide feedback to improve the signature iteratively
### Supported Field Types
- **Basic types**: `str`, `int`, `float`, `bool`
- **Collections**: `list[str]`, `list[int]`, `dict[str, Any]`, etc.
- **Optional types**: `Optional[str]`, `Optional[int]`, etc.
- **Literal types**: For enumerated values like `Literal["positive", "negative", "neutral"]`
- **Multimodal**: `dspy.Image`, `dspy.Audio`
- **Pydantic models**: Complex nested structures with validation
## Advanced Usage
### Pushing to Modaic Hub
To share your agent or update the hub version:
```python
from agent import PromptToSignatureAgent, PromptToSignatureConfig
agent = PromptToSignatureAgent(PromptToSignatureConfig())
agent.push_to_hub("your-username/agent-name", with_code=True)
```
### Dynamic Signature Classes
Create DSPy signature classes at runtime:
```python
result = agent("Translate English to German")
# Create a dynamic signature class
SignatureClass = agent.signature_generator.create_signature_class(result)
# Use it with DSPy modules
predictor = dspy.Predict(SignatureClass)
output = predictor(english_text="Hello, world!")
```
### Custom LLM Backends
Use different LLM providers:
```python
import dspy
from agent import PromptToSignatureAgent, PromptToSignatureConfig
# Configure custom LM
custom_lm = dspy.LM(
model="openai/gpt-4",
api_key="your-key",
max_tokens=8000,
)
# Initialize agent
agent = PromptToSignatureAgent(PromptToSignatureConfig())
agent.signature_generator.set_lm(custom_lm)
```
## Configuration
### Environment Variables
- `OPENROUTER_API_KEY`: Your OpenRouter API key (required for local usage)
### Agent Configuration
```python
PromptToSignatureConfig(
lm="openrouter/anthropic/claude-haiku-4.5", # Main LLM model
refine_lm="openrouter/anthropic/claude-haiku-4.5", # Refinement LLM
max_tokens=16000, # Max tokens per generation
temperature=1.0, # Sampling temperature
max_attempts_to_refine=5, # Max refinement iterations
)
```
## Troubleshooting
### Common Issues
**"Refinement failed"**: This usually means the signature couldn't be improved after max attempts. Try:
- Adjusting your prompt to be more specific
- Increasing `max_attempts_to_refine`
- Providing clearer feedback during refinement
**Missing API Key**: Ensure `OPENROUTER_API_KEY` is set in your `.env` file
**Type Validation Errors**: The agent validates all field types. If generation fails, try:
- Simplifying your prompt
- Being more explicit about expected output structure
## Contributing
Contributions are welcome! Please feel free to submit issues and pull requests.
## License
[Add your license here]
## Acknowledgments
Built with:
- [DSPy](https://github.com/stanfordnlp/dspy) - Framework for programming foundation models
- [Modaic](https://modaic.dev/) - Agent orchestration and hub
- [OpenRouter](https://openrouter.ai/) - Unified LLM API access