UNPKG

promptly-ai

Version:

A universal template-based prompt management system for LLM applications

459 lines (340 loc) 10.3 kB
# Promptly AI A universal template-based prompt management system for LLM applications. Promptly AI separates prompts from business logic, making them easier to maintain, version, and modify across different projects. ## Features - 🎯 **Template-based prompts** - Separate prompts from code - 🔄 **Multi-turn conversations** - Support for dialogue flows - **Conditional prompts** - Include/exclude prompts based on context - 🧠 **Extended thinking** - Support for reasoning tokens - 🔌 **Extensible adapters** - Easy integration with different LLM providers - 📝 **Handlebars templating** - Powerful variable interpolation and logic - **Type-safe** - Full TypeScript support - **Performance** - Built-in caching for templates - �🛡️ **Validation** - Context validation with custom rules ## Installation ```bash npm install promptly-ai ``` ### Peer Dependencies Install the LLM SDKs you plan to use: ```bash # For OpenAI npm install openai # For Anthropic npm install @anthropic-ai/sdk ``` ## Quick Start ### 1. Setup ```typescript import { createPromptly, OpenAIAdapter, AnthropicAdapter } from 'promptly-ai'; const promptly = createPromptly({ templatesPath: './prompts', defaultModel: 'gpt-4-turbo', adapters: [ new OpenAIAdapter(), // Uses OPENAI_API_KEY env var new AnthropicAdapter(), // Uses ANTHROPIC_API_KEY env var ], }); ``` ### 2. Create a Template Create `./prompts/greeting.md`: ```markdown --- name: "greeting" description: "Generate personalized greetings" model: "gpt-4-turbo" temperature: 0.7 maxTokens: 100 --- # System Prompt You are a friendly assistant that creates personalized greetings. # User Prompt Create a {{style}} greeting for {{name}}. {{#if occasion}} The occasion is: {{occasion}} {{/if}} # User Prompt 2 [if includeWeather] Also mention that it's a {{weather}} day. ``` ### 3. Use the Template ```typescript const result = await promptly.generate('greeting', { name: 'Alice', style: 'warm', occasion: 'birthday', includeWeather: true, weather: 'sunny' }); console.log(result.content); // Output: A warm birthday greeting for Alice mentioning the sunny weather ``` ## Template Format Templates use Markdown with YAML frontmatter: ```markdown --- name: "template-name" description: "Template description" model: "gpt-4-turbo" temperature: 0.8 maxTokens: 500 maxThinkingTokens: 2000 version: "1.0.0" --- # System Prompt Your system instructions here... # User Prompt Your user message with {{variables}} # Assistant Prompt [if needsResponse] Assistant response (conditional) # User Prompt 2 Follow-up user message ``` ## Conditional Prompts Control which prompts are included using conditions: ```markdown # User Prompt [if hasContext] Additional context: {{context}} # Assistant Prompt [if (eq mode "detailed")] I'll provide a detailed response. # User Prompt 2 [if (and hasExamples (ne format "simple"))] Here are examples: {{examples}} ``` ### Supported Conditions - Simple variables: `[if variableName]` - Equality: `[if (eq value "expected")]` - Inequality: `[if (ne value "unwanted")]` - Logical AND: `[if (and condition1 condition2)]` - Logical OR: `[if (or condition1 condition2)]` - Negation: `[if (not condition)]` - Comparisons: `[if (gt number 5)]`, `[if (lte score 100)]` ## API Reference ### Core Classes #### Promptly Main class for managing templates and generating content. ```typescript const promptly = new Promptly({ templatesPath: './prompts', adapters: [new OpenAIAdapter()], defaultModel: 'gpt-4-turbo', cache: true }); // Generate content const result = await promptly.generate('template-name', context); // Just render template (without LLM call) const rendered = await promptly.renderTemplate('template-name', context); // Utility methods const templates = await promptly.getAvailableTemplates(); const exists = await promptly.templateExists('template-name'); promptly.clearCache(); ``` #### LLM Adapters ##### OpenAIAdapter ```typescript import { OpenAIAdapter } from 'promptly-ai'; // With environment variable OPENAI_API_KEY const adapter = new OpenAIAdapter(); // With explicit API key const adapter = new OpenAIAdapter('your-api-key'); // Supports models matching patterns: /^gpt-/i, /^o\d+/i // Examples: gpt-4, gpt-4-turbo, gpt-3.5-turbo, o1, o3, etc. ``` ##### AnthropicAdapter ```typescript import { AnthropicAdapter } from 'promptly-ai'; // With environment variable ANTHROPIC_API_KEY const adapter = new AnthropicAdapter(); // With explicit API key const adapter = new AnthropicAdapter('your-api-key'); // Supports models matching pattern: /^claude-/i // Examples: claude-3-5-sonnet, claude-opus, etc. ``` ### Custom Adapters Create custom adapters for other LLM providers: ```typescript import { LLMAdapter, LLMConfig, LLMUsageResult } from 'promptly-ai'; class CustomAdapter implements LLMAdapter { name = 'custom'; supportsModel(model: string): boolean { return model.startsWith('custom-'); } async generate(config: LLMConfig): Promise<LLMUsageResult> { // Your implementation here return { content: 'Generated content', provider: this.name, model: config.model, inputTokens: 100, outputTokens: 50, costUsd: 0.001 }; } } promptly.addAdapter(new CustomAdapter()); ``` ### Validation Add validation rules for template contexts: ```typescript promptly.setValidationSchema({ 'greeting': [ { field: 'name', required: true, type: 'string' }, { field: 'style', required: true, type: 'string' }, { field: 'age', type: 'number', validator: (age) => age > 0 } ] }); ``` ### Handlebars Helpers Built-in helpers for templates: ```handlebars {{! Comparison }} {{#if (eq status "active")}}Active user{{/if}} {{#if (gt score 80)}}High score!{{/if}} {{! Logic }} {{#if (and isLoggedIn hasPermission)}}Welcome{{/if}} {{#if (or isAdmin isModerator)}}Admin panel{{/if}} {{! String manipulation }} {{uppercase name}} {{capitalize title}} {{lowercase email}} {{! Arrays and loops }} {{#if (gt (length items) 0)}} Items: {{join items ", "}} {{/if}} {{#each items}} Item {{@index}}: {{this}} Item {{add @index 1}}: {{this}} {{! 1-based numbering }} {{/each}} {{! Math operations }} {{add 5 3}} {{! Returns 8 }} {{subtract 10 4}} {{! Returns 6 }} {{multiply 3 7}} {{! Returns 21 }} {{divide 15 3}} {{! Returns 5 }} {{! Type checking }} {{#if (isString value)}}String value{{/if}} {{#if (isArray items)}}Array of items{{/if}} {{! Utilities }} {{default value "fallback"}} ``` #### Advanced Loop Examples ```handlebars {{! Loop with 1-based indexing }} {{#each sections}} Section {{add @index 1}}: {{this.title}} Content: {{this.content}} {{/each}} {{! Nested object access in loops }} {{#each sectionContext.previousSections}} [Previous Section {{add @index 1}}]: {{this}} {{/each}} {{! Conditional content in loops }} {{#each users}} {{#if (eq @index 0)}}First user: {{/if}} {{name}} ({{add @index 1}} of {{length ../users}}) {{/each}} ``` ## Project Integration ### Directory Structure ``` your-project/ ├── prompts/ ├── greeting.md ├── summarization.md └── analysis.md ├── src/ └── llm-service.ts └── package.json ``` ### Service Integration ```typescript // src/llm-service.ts import { createPromptly, OpenAIAdapter } from 'promptly-ai'; import path from 'path'; export class LLMService { private promptly; constructor() { this.promptly = createPromptly({ templatesPath: path.join(process.cwd(), 'prompts'), defaultModel: 'gpt-4-turbo', adapters: [new OpenAIAdapter()], }); } async generateGreeting(name: string, style: string) { return this.promptly.generate('greeting', { name, style }); } async summarizeText(text: string, maxLength: number) { return this.promptly.generate('summarization', { text, maxLength }); } } ``` ## Environment Variables Set up your API keys: ```bash # .env OPENAI_API_KEY=your-openai-key ANTHROPIC_API_KEY=your-anthropic-key ``` ## Best Practices 1. **Organize Templates**: Group related templates in subdirectories 2. **Version Templates**: Use the `version` field in frontmatter 3. **Validate Context**: Define validation schemas for important templates 4. **Cache Management**: Clear cache during development, enable in production 5. **Error Handling**: Wrap LLM calls in try-catch blocks 6. **Model Selection**: Specify models in templates for consistency 7. **Testing**: Test templates with various context combinations ## Examples ### Multi-turn Conversation ```markdown --- name: "interview" model: "gpt-4-turbo" --- # System Prompt You are conducting a job interview. # User Prompt I'm interviewing for a {{position}} role. # Assistant Prompt [if needsIntroduction] Welcome! Let's start with some basic questions. # User Prompt 2 Tell me about your experience with {{technology}}. # Assistant Prompt 2 [if (eq difficulty "advanced")] Let's dive into some advanced topics. # User Prompt 3 [if hasAdvancedQuestions] {{advancedQuestion}} ``` ### Content Generation Pipeline ```typescript class ContentPipeline { constructor(private promptly: Promptly) {} async generateArticle(topic: string) { // Step 1: Generate outline const outline = await this.promptly.generate('outline', { topic }); // Step 2: Generate introduction const intro = await this.promptly.generate('introduction', { topic, outline: outline.content }); // Step 3: Generate sections const sections = await this.promptly.generate('sections', { topic, outline: outline.content, introduction: intro.content }); return { outline: outline.content, introduction: intro.content, sections: sections.content }; } } ``` ## Contributing 1. Fork the repository 2. Create a feature branch 3. Make your changes 4. Add tests 5. Run linting: `npm run lint` 6. Submit a pull request ## License MIT License - see LICENSE file for details. ## Support - 📖 [Documentation](https://github.com/your-org/promptly-ai) - 🐛 [Issues](https://github.com/your-org/promptly-ai/issues) - 💬 [Discussions](https://github.com/your-org/promptly-ai/discussions)