104 lines
3.3 KiB
Python
104 lines
3.3 KiB
Python
"""
|
|
Template utilities for Jinja2 template rendering with LangChain
|
|
"""
|
|
import logging
|
|
from typing import Dict, Any
|
|
from jinja2 import Environment, BaseLoader, TemplateError
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class TemplateRenderer:
|
|
"""Jinja2 template renderer for LLM prompts"""
|
|
|
|
def __init__(self):
|
|
self.env = Environment(
|
|
loader=BaseLoader(),
|
|
# Enable safe variable substitution
|
|
autoescape=False,
|
|
# Custom delimiters to avoid conflicts with common markdown syntax
|
|
variable_start_string='{{',
|
|
variable_end_string='}}',
|
|
block_start_string='{%',
|
|
block_end_string='%}',
|
|
comment_start_string='{#',
|
|
comment_end_string='#}',
|
|
# Keep linebreaks
|
|
keep_trailing_newline=True,
|
|
# Remove unnecessary whitespace
|
|
trim_blocks=True,
|
|
lstrip_blocks=True
|
|
)
|
|
|
|
def render_template(self, template_string: str, variables: Dict[str, Any]) -> str:
|
|
"""
|
|
Render a Jinja2 template string with provided variables
|
|
|
|
Args:
|
|
template_string: The template string with Jinja2 syntax
|
|
variables: Dictionary of variables to substitute
|
|
|
|
Returns:
|
|
Rendered template string
|
|
|
|
Raises:
|
|
TemplateError: If template rendering fails
|
|
"""
|
|
try:
|
|
template = self.env.from_string(template_string)
|
|
rendered = template.render(**variables)
|
|
logger.debug(f"Template rendered successfully with variables: {list(variables.keys())}")
|
|
return rendered
|
|
except TemplateError as e:
|
|
logger.error(f"Template rendering failed: {e}")
|
|
logger.error(f"Template: {template_string[:200]}...")
|
|
logger.error(f"Variables: {variables}")
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"Unexpected error during template rendering: {e}")
|
|
raise TemplateError(f"Template rendering failed: {e}")
|
|
|
|
def render_system_prompt(self, template_string: str, variables: Dict[str, Any]) -> str:
|
|
"""
|
|
Render system prompt template
|
|
|
|
Args:
|
|
template_string: System prompt template
|
|
variables: Variables for substitution
|
|
|
|
Returns:
|
|
Rendered system prompt
|
|
"""
|
|
return self.render_template(template_string, variables)
|
|
|
|
def render_user_prompt(self, template_string: str, variables: Dict[str, Any]) -> str:
|
|
"""
|
|
Render user prompt template
|
|
|
|
Args:
|
|
template_string: User prompt template
|
|
variables: Variables for substitution
|
|
|
|
Returns:
|
|
Rendered user prompt
|
|
"""
|
|
return self.render_template(template_string, variables)
|
|
|
|
|
|
# Global template renderer instance
|
|
template_renderer = TemplateRenderer()
|
|
|
|
|
|
def render_prompt_template(template_string: str, variables: Dict[str, Any]) -> str:
|
|
"""
|
|
Convenience function to render prompt templates
|
|
|
|
Args:
|
|
template_string: Template string with Jinja2 syntax
|
|
variables: Dictionary of variables to substitute
|
|
|
|
Returns:
|
|
Rendered template string
|
|
"""
|
|
return template_renderer.render_template(template_string, variables)
|