PromptEngine
A powerful Rails engine for managing AI prompts with version control, A/B testing, and seamless LLM integration. PromptEngine provides a centralized admin interface where teams can create, version, test, and optimize their AI prompts without deploying code changes.
Why PromptEngine?
- Version Control: Track every change to your prompts with automatic versioning
- A/B Testing: Test different prompt variations with built-in evaluation tools
- No Deploy Required: Update prompts through the admin UI without code changes
- LLM Agnostic: Works with OpenAI, Anthropic, and other providers
- Type Safety: Automatic parameter detection and validation
- Team Collaboration: Centralized prompt management for your entire team
- Production Ready: Battle-tested with secure API key storage
Features
- ๐ฏ Smart Prompt Management: Create and organize prompts with slug-based identification
- ๐ Version Control: Automatic versioning with one-click rollback
- ๐ Variable Detection: Auto-detects
{{variables}}
and creates typed parameters - ๐งช Playground: Test prompts with real AI providers before deploying
- ๐ Evaluation Suite: Create test cases and measure prompt performance
- ๐ Secure: Encrypted API key storage using Rails encryption
- ๐ Modern API: Object-oriented design with direct LLM integration
Installation
Add this line to your application's Gemfile:
gem "prompt_engine"
And then execute:
$ bundle
$ rails prompt_engine:install:migrations
$ rails db:migrate
$ rails prompt_engine:seed # Optional: adds sample prompts
Setup
1. Configure Encryption
PromptEngine uses Rails encryption to secure API keys. Add to your environment files:
# config/environments/development.rb
config.active_record.encryption.primary_key = 'development' * 4
config.active_record.encryption.deterministic_key = 'development' * 4
config.active_record.encryption.key_derivation_salt = 'development' * 4
For production, use rails db:encryption:init
to generate secure keys.
2. Configure API Keys
Add your AI provider API keys to Rails credentials:
rails credentials:edit
openai:
api_key: sk-your-openai-api-key
anthropic:
api_key: sk-ant-your-anthropic-api-key
3. Mount the Engine
In your config/routes.rb
:
Rails.application.routes.draw do
mount PromptEngine::Engine => "/prompt_engine"
# your other routes...
end
4. Authentication (Optional but Recommended)
PromptEngine provides flexible authentication options to secure your admin interface. By default, authentication is enabled but not configured, allowing full access. We strongly recommend configuring authentication for production environments.
Quick Start
The simplest way to secure PromptEngine is with HTTP Basic authentication:
# config/initializers/prompt_engine.rb
PromptEngine.configure do |config|
config.http_basic_auth_enabled = true
config.http_basic_auth_name = "admin"
config.http_basic_auth_password = "secure_password_here"
end
For production, use Rails credentials:
rails credentials:edit
# Add to credentials file
prompt_engine:
username: your_secure_username
password: your_secure_password
# config/initializers/prompt_engine.rb
PromptEngine.configure do |config|
config.http_basic_auth_enabled = true
config.http_basic_auth_name = Rails.application.credentials.dig(:prompt_engine, :username)
config.http_basic_auth_password = Rails.application.credentials.dig(:prompt_engine, :password)
end
Authentication Strategies
1. HTTP Basic Authentication
Built-in support with secure credential comparison:
# config/initializers/prompt_engine.rb
PromptEngine.configure do |config|
config.authentication_enabled = true # Default: true
config.http_basic_auth_enabled = true
config.http_basic_auth_name = ENV['PROMPT_ENGINE_USERNAME']
config.http_basic_auth_password = ENV['PROMPT_ENGINE_PASSWORD']
end
Security Notes:
- Uses
ActiveSupport::SecurityUtils.secure_compare
to prevent timing attacks - Credentials are never logged or exposed in errors
- Empty credentials are treated as invalid
2. Devise Integration
For Devise authentication, mount the engine within an authenticated route:
# config/routes.rb
Rails.application.routes.draw do
authenticate :user, ->(user) { user.admin? } do
mount PromptEngine::Engine => "/prompt_engine"
end
end
3. Custom Authentication
Integrate with your existing authentication system using the ActiveSupport hook:
# config/initializers/prompt_engine.rb
ActiveSupport.on_load(:prompt_engine_application_controller) do
before_action do
raise ActionController::RoutingError.new('Not Found') unless current_user&.admin?
end
def current_user
# Your authentication logic here
@current_user ||= User.find_by(id: session[:user_id])
end
end
4. Rack Middleware Authentication
For advanced scenarios, add custom middleware directly to the engine:
# config/initializers/prompt_engine.rb
PromptEngine::Engine.middleware.use(Rack::Auth::Basic) do |username, password|
ActiveSupport::SecurityUtils.secure_compare(
Rails.application.credentials.prompt_engine_username, username
) & ActiveSupport::SecurityUtils.secure_compare(
Rails.application.credentials.prompt_engine_password, password
)
end
5. Disable Authentication (Development Only)
โ ๏ธ Warning: Only disable authentication in development environments:
# config/initializers/prompt_engine.rb
if Rails.env.development?
PromptEngine.configure do |config|
config.authentication_enabled = false
end
end
Configuration Reference
Setting | Default | Description |
---|---|---|
authentication_enabled |
true |
Master switch for all authentication |
http_basic_auth_enabled |
false |
Enable HTTP Basic authentication |
http_basic_auth_name |
nil |
Username for HTTP Basic auth |
http_basic_auth_password |
nil |
Password for HTTP Basic auth |
Testing with Authentication
When writing tests, you can disable authentication:
# spec/rails_helper.rb or test/test_helper.rb
RSpec.configure do |config|
config.before(:each) do
PromptEngine.authentication_enabled = false
end
end
Or provide credentials in your tests:
get prompt_engine.prompts_path, headers: {
"Authorization" => ActionController::HttpAuthentication::Basic.encode_credentials("admin", "password")
}
Security Best Practices
- Always enable authentication in production
- Use strong, unique passwords
- Store credentials securely (Rails credentials, environment variables, or secrets management)
- Use HTTPS to encrypt authentication credentials in transit
- Implement rate limiting on your application server
- Monitor access logs for suspicious activity
For more authentication examples and advanced configurations, see AUTHENTICATION.md
Usage
Admin Interface
Visit /prompt_engine
in your browser to access the admin interface where you can:
- Create and manage prompts
- Test prompts in the playground
- View version history
- Create evaluation sets
- Monitor prompt performance
In Your Application
# Render a prompt with variables
rendered = PromptEngine.render("customer-support",
customer_name: "John",
issue: "Can't login to my account"
)
# Access rendered content
rendered.content # => "Hello John, I understand you're having trouble..."
rendered.system_message # => "You are a helpful customer support agent..."
rendered.model # => "gpt-4"
rendered.temperature # => 0.7
# Direct integration with OpenAI
client = OpenAI::Client.new(access_token: ENV["OPENAI_API_KEY"])
response = rendered.execute_with(client)
# Or with Anthropic
client = Anthropic::Client.new(access_token: ENV["ANTHROPIC_API_KEY"])
response = rendered.execute_with(client)
# Override model settings at runtime
rendered = PromptEngine.render("email-writer",
subject: "Welcome to our platform",
model: "gpt-4-turbo",
temperature: 0.9
)
# Load a specific version
rendered = PromptEngine.render("onboarding-email",
user_name: "Sarah",
version: 3
)
How It Works
-
Create Prompts: Use the admin UI to create prompts with
{{variables}}
- Auto-Detection: PromptEngine automatically detects variables and creates parameters
- Version Control: Every save creates a new version automatically
- Test & Deploy: Test in the playground, then use in your application
- Monitor: Track usage and performance through the dashboard
API Documentation
PromptEngine.render(slug, **options)
Renders a prompt template with the given variables.
Parameters:
-
slug
(String): The unique identifier for the prompt -
**options
(Hash): Variables and optional overrides- Variables: Any key-value pairs matching prompt variables
-
model
: Override the default model -
temperature
: Override the default temperature -
max_tokens
: Override the default max tokens -
version
: Load a specific version number
Returns: PromptEngine::RenderedPrompt
instance
RenderedPrompt Methods
-
content
: The rendered prompt content -
system_message
: The system message (if any) -
model
: The AI model to use -
temperature
: The temperature setting -
max_tokens
: The max tokens setting -
to_openai_params
: Convert to OpenAI API format -
to_ruby_llm_params
: Convert to RubyLLM/Anthropic format -
execute_with(client)
: Execute with an LLM client
Contributing
We welcome contributions! Here's how you can help:
Development Setup
-
Fork the repository
-
Clone your fork:
git clone https://github.com/YOUR_USERNAME/prompt_engine.git cd prompt_engine
-
Install dependencies:
bundle install
-
Set up the test database:
cd spec/dummy rails db:create db:migrate db:seed cd ../..
-
Run the tests:
bundle exec rspec
-
Start the development server:
cd spec/dummy && rails server
Making Changes
-
Create a feature branch:
git checkout -b feature/your-feature-name
-
Make your changes and ensure tests pass:
bundle exec rspec bundle exec rubocop
-
Commit your changes:
git commit -m "Add your feature"
-
Push to your fork:
git push origin feature/your-feature-name
-
Create a Pull Request
Guidelines
- Write tests for new features
- Follow Rails best practices
- Use conventional commit messages
- Update documentation as needed
- Be respectful in discussions
Architecture
PromptEngine follows Rails engine conventions with a modular architecture:
- Models: Prompt, PromptVersion, Parameter, EvalSet, TestCase
- Services: VariableDetector, PlaygroundExecutor, PromptRenderer
- Admin UI: Built with Hotwire, Stimulus, and Turbo
- API: Object-oriented design with RenderedPrompt instances
See docs/ARCHITECTURE.md for detailed technical documentation.
Roadmap
- Multi-language prompt support
- Prompt templates marketplace
- Advanced A/B testing analytics
- Webhook integrations
- Prompt chaining
- Cost tracking and optimization
- Team collaboration features
Sponsors
- Innovent Capital - Pioneering AI innovation in financial services
License
The gem is available as open source under the terms of the MIT License.
Support
- ๐ Documentation
- ๐ Issue Tracker
- ๐ฌ Discussions
- ๐ง Email Support
Built with โค๏ธ by Avi.nyc