Initial commit
This commit is contained in:
@@ -0,0 +1,470 @@
|
||||
# Prompt Template Systems
|
||||
|
||||
## Template Architecture
|
||||
|
||||
### Basic Template Structure
|
||||
```python
|
||||
class PromptTemplate:
|
||||
def __init__(self, template_string, variables=None):
|
||||
self.template = template_string
|
||||
self.variables = variables or []
|
||||
|
||||
def render(self, **kwargs):
|
||||
missing = set(self.variables) - set(kwargs.keys())
|
||||
if missing:
|
||||
raise ValueError(f"Missing required variables: {missing}")
|
||||
|
||||
return self.template.format(**kwargs)
|
||||
|
||||
# Usage
|
||||
template = PromptTemplate(
|
||||
template_string="Translate {text} from {source_lang} to {target_lang}",
|
||||
variables=['text', 'source_lang', 'target_lang']
|
||||
)
|
||||
|
||||
prompt = template.render(
|
||||
text="Hello world",
|
||||
source_lang="English",
|
||||
target_lang="Spanish"
|
||||
)
|
||||
```
|
||||
|
||||
### Conditional Templates
|
||||
```python
|
||||
class ConditionalTemplate(PromptTemplate):
|
||||
def render(self, **kwargs):
|
||||
# Process conditional blocks
|
||||
result = self.template
|
||||
|
||||
# Handle if-blocks: {{#if variable}}content{{/if}}
|
||||
import re
|
||||
if_pattern = r'\{\{#if (\w+)\}\}(.*?)\{\{/if\}\}'
|
||||
|
||||
def replace_if(match):
|
||||
var_name = match.group(1)
|
||||
content = match.group(2)
|
||||
return content if kwargs.get(var_name) else ''
|
||||
|
||||
result = re.sub(if_pattern, replace_if, result, flags=re.DOTALL)
|
||||
|
||||
# Handle for-loops: {{#each items}}{{this}}{{/each}}
|
||||
each_pattern = r'\{\{#each (\w+)\}\}(.*?)\{\{/each\}\}'
|
||||
|
||||
def replace_each(match):
|
||||
var_name = match.group(1)
|
||||
content = match.group(2)
|
||||
items = kwargs.get(var_name, [])
|
||||
return '\\n'.join(content.replace('{{this}}', str(item)) for item in items)
|
||||
|
||||
result = re.sub(each_pattern, replace_each, result, flags=re.DOTALL)
|
||||
|
||||
# Finally, render remaining variables
|
||||
return result.format(**kwargs)
|
||||
|
||||
# Usage
|
||||
template = ConditionalTemplate("""
|
||||
Analyze the following text:
|
||||
{text}
|
||||
|
||||
{{#if include_sentiment}}
|
||||
Provide sentiment analysis.
|
||||
{{/if}}
|
||||
|
||||
{{#if include_entities}}
|
||||
Extract named entities.
|
||||
{{/if}}
|
||||
|
||||
{{#if examples}}
|
||||
Reference examples:
|
||||
{{#each examples}}
|
||||
- {{this}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
""")
|
||||
```
|
||||
|
||||
### Modular Template Composition
|
||||
```python
|
||||
class ModularTemplate:
|
||||
def __init__(self):
|
||||
self.components = {}
|
||||
|
||||
def register_component(self, name, template):
|
||||
self.components[name] = template
|
||||
|
||||
def render(self, structure, **kwargs):
|
||||
parts = []
|
||||
for component_name in structure:
|
||||
if component_name in self.components:
|
||||
component = self.components[component_name]
|
||||
parts.append(component.format(**kwargs))
|
||||
|
||||
return '\\n\\n'.join(parts)
|
||||
|
||||
# Usage
|
||||
builder = ModularTemplate()
|
||||
|
||||
builder.register_component('system', "You are a {role}.")
|
||||
builder.register_component('context', "Context: {context}")
|
||||
builder.register_component('instruction', "Task: {task}")
|
||||
builder.register_component('examples', "Examples:\\n{examples}")
|
||||
builder.register_component('input', "Input: {input}")
|
||||
builder.register_component('format', "Output format: {format}")
|
||||
|
||||
# Compose different templates for different scenarios
|
||||
basic_prompt = builder.render(
|
||||
['system', 'instruction', 'input'],
|
||||
role='helpful assistant',
|
||||
instruction='Summarize the text',
|
||||
input='...'
|
||||
)
|
||||
|
||||
advanced_prompt = builder.render(
|
||||
['system', 'context', 'examples', 'instruction', 'input', 'format'],
|
||||
role='expert analyst',
|
||||
context='Financial analysis',
|
||||
examples='...',
|
||||
instruction='Analyze sentiment',
|
||||
input='...',
|
||||
format='JSON'
|
||||
)
|
||||
```
|
||||
|
||||
## Common Template Patterns
|
||||
|
||||
### Classification Template
|
||||
```python
|
||||
CLASSIFICATION_TEMPLATE = """
|
||||
Classify the following {content_type} into one of these categories: {categories}
|
||||
|
||||
{{#if description}}
|
||||
Category descriptions:
|
||||
{description}
|
||||
{{/if}}
|
||||
|
||||
{{#if examples}}
|
||||
Examples:
|
||||
{examples}
|
||||
{{/if}}
|
||||
|
||||
{content_type}: {input}
|
||||
|
||||
Category:"""
|
||||
```
|
||||
|
||||
### Extraction Template
|
||||
```python
|
||||
EXTRACTION_TEMPLATE = """
|
||||
Extract structured information from the {content_type}.
|
||||
|
||||
Required fields:
|
||||
{field_definitions}
|
||||
|
||||
{{#if examples}}
|
||||
Example extraction:
|
||||
{examples}
|
||||
{{/if}}
|
||||
|
||||
{content_type}: {input}
|
||||
|
||||
Extracted information (JSON):"""
|
||||
```
|
||||
|
||||
### Generation Template
|
||||
```python
|
||||
GENERATION_TEMPLATE = """
|
||||
Generate {output_type} based on the following {input_type}.
|
||||
|
||||
Requirements:
|
||||
{requirements}
|
||||
|
||||
{{#if style}}
|
||||
Style: {style}
|
||||
{{/if}}
|
||||
|
||||
{{#if constraints}}
|
||||
Constraints:
|
||||
{constraints}
|
||||
{{/if}}
|
||||
|
||||
{{#if examples}}
|
||||
Examples:
|
||||
{examples}
|
||||
{{/if}}
|
||||
|
||||
{input_type}: {input}
|
||||
|
||||
{output_type}:"""
|
||||
```
|
||||
|
||||
### Transformation Template
|
||||
```python
|
||||
TRANSFORMATION_TEMPLATE = """
|
||||
Transform the input {source_format} to {target_format}.
|
||||
|
||||
Transformation rules:
|
||||
{rules}
|
||||
|
||||
{{#if examples}}
|
||||
Example transformations:
|
||||
{examples}
|
||||
{{/if}}
|
||||
|
||||
Input {source_format}:
|
||||
{input}
|
||||
|
||||
Output {target_format}:"""
|
||||
```
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### Template Inheritance
|
||||
```python
|
||||
class TemplateRegistry:
|
||||
def __init__(self):
|
||||
self.templates = {}
|
||||
|
||||
def register(self, name, template, parent=None):
|
||||
if parent and parent in self.templates:
|
||||
# Inherit from parent
|
||||
base = self.templates[parent]
|
||||
template = self.merge_templates(base, template)
|
||||
|
||||
self.templates[name] = template
|
||||
|
||||
def merge_templates(self, parent, child):
|
||||
# Child overwrites parent sections
|
||||
return {**parent, **child}
|
||||
|
||||
# Usage
|
||||
registry = TemplateRegistry()
|
||||
|
||||
registry.register('base_analysis', {
|
||||
'system': 'You are an expert analyst.',
|
||||
'format': 'Provide analysis in structured format.'
|
||||
})
|
||||
|
||||
registry.register('sentiment_analysis', {
|
||||
'instruction': 'Analyze sentiment',
|
||||
'format': 'Provide sentiment score from -1 to 1.'
|
||||
}, parent='base_analysis')
|
||||
```
|
||||
|
||||
### Variable Validation
|
||||
```python
|
||||
class ValidatedTemplate:
|
||||
def __init__(self, template, schema):
|
||||
self.template = template
|
||||
self.schema = schema
|
||||
|
||||
def validate_vars(self, **kwargs):
|
||||
for var_name, var_schema in self.schema.items():
|
||||
if var_name in kwargs:
|
||||
value = kwargs[var_name]
|
||||
|
||||
# Type validation
|
||||
if 'type' in var_schema:
|
||||
expected_type = var_schema['type']
|
||||
if not isinstance(value, expected_type):
|
||||
raise TypeError(f"{var_name} must be {expected_type}")
|
||||
|
||||
# Range validation
|
||||
if 'min' in var_schema and value < var_schema['min']:
|
||||
raise ValueError(f"{var_name} must be >= {var_schema['min']}")
|
||||
|
||||
if 'max' in var_schema and value > var_schema['max']:
|
||||
raise ValueError(f"{var_name} must be <= {var_schema['max']}")
|
||||
|
||||
# Enum validation
|
||||
if 'choices' in var_schema and value not in var_schema['choices']:
|
||||
raise ValueError(f"{var_name} must be one of {var_schema['choices']}")
|
||||
|
||||
def render(self, **kwargs):
|
||||
self.validate_vars(**kwargs)
|
||||
return self.template.format(**kwargs)
|
||||
|
||||
# Usage
|
||||
template = ValidatedTemplate(
|
||||
template="Summarize in {length} words with {tone} tone",
|
||||
schema={
|
||||
'length': {'type': int, 'min': 10, 'max': 500},
|
||||
'tone': {'type': str, 'choices': ['formal', 'casual', 'technical']}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
### Template Caching
|
||||
```python
|
||||
class CachedTemplate:
|
||||
def __init__(self, template):
|
||||
self.template = template
|
||||
self.cache = {}
|
||||
|
||||
def render(self, use_cache=True, **kwargs):
|
||||
if use_cache:
|
||||
cache_key = self.get_cache_key(kwargs)
|
||||
if cache_key in self.cache:
|
||||
return self.cache[cache_key]
|
||||
|
||||
result = self.template.format(**kwargs)
|
||||
|
||||
if use_cache:
|
||||
self.cache[cache_key] = result
|
||||
|
||||
return result
|
||||
|
||||
def get_cache_key(self, kwargs):
|
||||
return hash(frozenset(kwargs.items()))
|
||||
|
||||
def clear_cache(self):
|
||||
self.cache = {}
|
||||
```
|
||||
|
||||
## Multi-Turn Templates
|
||||
|
||||
### Conversation Template
|
||||
```python
|
||||
class ConversationTemplate:
|
||||
def __init__(self, system_prompt):
|
||||
self.system_prompt = system_prompt
|
||||
self.history = []
|
||||
|
||||
def add_user_message(self, message):
|
||||
self.history.append({'role': 'user', 'content': message})
|
||||
|
||||
def add_assistant_message(self, message):
|
||||
self.history.append({'role': 'assistant', 'content': message})
|
||||
|
||||
def render_for_api(self):
|
||||
messages = [{'role': 'system', 'content': self.system_prompt}]
|
||||
messages.extend(self.history)
|
||||
return messages
|
||||
|
||||
def render_as_text(self):
|
||||
result = f"System: {self.system_prompt}\\n\\n"
|
||||
for msg in self.history:
|
||||
role = msg['role'].capitalize()
|
||||
result += f"{role}: {msg['content']}\\n\\n"
|
||||
return result
|
||||
```
|
||||
|
||||
### State-Based Templates
|
||||
```python
|
||||
class StatefulTemplate:
|
||||
def __init__(self):
|
||||
self.state = {}
|
||||
self.templates = {}
|
||||
|
||||
def set_state(self, **kwargs):
|
||||
self.state.update(kwargs)
|
||||
|
||||
def register_state_template(self, state_name, template):
|
||||
self.templates[state_name] = template
|
||||
|
||||
def render(self):
|
||||
current_state = self.state.get('current_state', 'default')
|
||||
template = self.templates.get(current_state)
|
||||
|
||||
if not template:
|
||||
raise ValueError(f"No template for state: {current_state}")
|
||||
|
||||
return template.format(**self.state)
|
||||
|
||||
# Usage for multi-step workflows
|
||||
workflow = StatefulTemplate()
|
||||
|
||||
workflow.register_state_template('init', """
|
||||
Welcome! Let's {task}.
|
||||
What is your {first_input}?
|
||||
""")
|
||||
|
||||
workflow.register_state_template('processing', """
|
||||
Thanks! Processing {first_input}.
|
||||
Now, what is your {second_input}?
|
||||
""")
|
||||
|
||||
workflow.register_state_template('complete', """
|
||||
Great! Based on:
|
||||
- {first_input}
|
||||
- {second_input}
|
||||
|
||||
Here's the result: {result}
|
||||
""")
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Keep It DRY**: Use templates to avoid repetition
|
||||
2. **Validate Early**: Check variables before rendering
|
||||
3. **Version Templates**: Track changes like code
|
||||
4. **Test Variations**: Ensure templates work with diverse inputs
|
||||
5. **Document Variables**: Clearly specify required/optional variables
|
||||
6. **Use Type Hints**: Make variable types explicit
|
||||
7. **Provide Defaults**: Set sensible default values where appropriate
|
||||
8. **Cache Wisely**: Cache static templates, not dynamic ones
|
||||
|
||||
## Template Libraries
|
||||
|
||||
### Question Answering
|
||||
```python
|
||||
QA_TEMPLATES = {
|
||||
'factual': """Answer the question based on the context.
|
||||
|
||||
Context: {context}
|
||||
Question: {question}
|
||||
Answer:""",
|
||||
|
||||
'multi_hop': """Answer the question by reasoning across multiple facts.
|
||||
|
||||
Facts: {facts}
|
||||
Question: {question}
|
||||
|
||||
Reasoning:""",
|
||||
|
||||
'conversational': """Continue the conversation naturally.
|
||||
|
||||
Previous conversation:
|
||||
{history}
|
||||
|
||||
User: {question}
|
||||
Assistant:"""
|
||||
}
|
||||
```
|
||||
|
||||
### Content Generation
|
||||
```python
|
||||
GENERATION_TEMPLATES = {
|
||||
'blog_post': """Write a blog post about {topic}.
|
||||
|
||||
Requirements:
|
||||
- Length: {word_count} words
|
||||
- Tone: {tone}
|
||||
- Include: {key_points}
|
||||
|
||||
Blog post:""",
|
||||
|
||||
'product_description': """Write a product description for {product}.
|
||||
|
||||
Features: {features}
|
||||
Benefits: {benefits}
|
||||
Target audience: {audience}
|
||||
|
||||
Description:""",
|
||||
|
||||
'email': """Write a {type} email.
|
||||
|
||||
To: {recipient}
|
||||
Context: {context}
|
||||
Key points: {key_points}
|
||||
|
||||
Email:"""
|
||||
}
|
||||
```
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
- Pre-compile templates for repeated use
|
||||
- Cache rendered templates when variables are static
|
||||
- Minimize string concatenation in loops
|
||||
- Use efficient string formatting (f-strings, .format())
|
||||
- Profile template rendering for bottlenecks
|
||||
Reference in New Issue
Block a user