mirror of
https://github.com/csunny/DB-GPT.git
synced 2025-07-27 05:47:47 +00:00
794 lines
26 KiB
Python
794 lines
26 KiB
Python
"""The prompt template interface."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import dataclasses
|
|
import json
|
|
from abc import ABC, abstractmethod
|
|
from string import Formatter
|
|
from typing import Any, Callable, Dict, List, Optional, Set, Type, TypeVar, Union
|
|
|
|
from dbgpt._private.pydantic import BaseModel, ConfigDict, model_validator
|
|
from dbgpt.core.interface.message import BaseMessage, HumanMessage, SystemMessage
|
|
from dbgpt.core.interface.storage import (
|
|
InMemoryStorage,
|
|
QuerySpec,
|
|
ResourceIdentifier,
|
|
StorageInterface,
|
|
StorageItem,
|
|
)
|
|
from dbgpt.util.formatting import formatter, no_strict_formatter
|
|
|
|
T = TypeVar("T", bound="BasePromptTemplate")
|
|
|
|
|
|
def _jinja2_formatter(template: str, **kwargs: Any) -> str:
|
|
"""Format a template using jinja2."""
|
|
try:
|
|
from jinja2 import Template
|
|
except ImportError:
|
|
raise ImportError(
|
|
"jinja2 not installed, which is needed to use the jinja2_formatter. "
|
|
"Please install it with `pip install jinja2`."
|
|
)
|
|
|
|
return Template(template).render(**kwargs)
|
|
|
|
|
|
_DEFAULT_FORMATTER_MAPPING: Dict[str, Callable] = {
|
|
"f-string": lambda is_strict: (
|
|
formatter.format if is_strict else no_strict_formatter.format
|
|
),
|
|
"jinja2": lambda is_strict: _jinja2_formatter,
|
|
}
|
|
|
|
|
|
class BasePromptTemplate(BaseModel):
|
|
"""Base class for all prompt templates, returning a prompt."""
|
|
|
|
input_variables: List[str]
|
|
"""A list of the names of the variables the prompt template expects."""
|
|
|
|
|
|
class PromptTemplate(BasePromptTemplate):
|
|
"""Prompt template."""
|
|
|
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
|
|
template: str
|
|
"""The prompt template."""
|
|
|
|
template_format: str = "f-string"
|
|
"""The format of the prompt template. Options are: 'f-string', 'jinja2'."""
|
|
|
|
response_key: str = "response"
|
|
|
|
template_is_strict: bool = True
|
|
"""strict template will check template args"""
|
|
|
|
response_format: Optional[str] = None
|
|
|
|
template_scene: Optional[str] = None
|
|
|
|
template_define: Optional[str] = None
|
|
"""this template define"""
|
|
|
|
@property
|
|
def _prompt_type(self) -> str:
|
|
"""Return the prompt type key."""
|
|
return "prompt"
|
|
|
|
def format(self, **kwargs: Any) -> str:
|
|
"""Format the prompt with the inputs."""
|
|
if self.response_format:
|
|
kwargs[self.response_key] = json.dumps(
|
|
self.response_format, ensure_ascii=False, indent=4
|
|
)
|
|
return _DEFAULT_FORMATTER_MAPPING[self.template_format](
|
|
self.template_is_strict
|
|
)(self.template, **kwargs)
|
|
|
|
@classmethod
|
|
def from_template(
|
|
cls: Type[T], template: str, template_format: str = "f-string", **kwargs: Any
|
|
) -> T:
|
|
"""Create a prompt template from a template string."""
|
|
input_variables = get_template_vars(template, template_format)
|
|
return cls(
|
|
template=template,
|
|
input_variables=input_variables,
|
|
template_format=template_format,
|
|
**kwargs,
|
|
)
|
|
|
|
|
|
class BaseChatPromptTemplate(BaseModel, ABC):
|
|
"""The base chat prompt template."""
|
|
|
|
prompt: BasePromptTemplate
|
|
|
|
@property
|
|
def input_variables(self) -> List[str]:
|
|
"""Return a list of the names of the variables the prompt template expects."""
|
|
return self.prompt.input_variables
|
|
|
|
@abstractmethod
|
|
def format_messages(self, **kwargs: Any) -> List[BaseMessage]:
|
|
"""Format the prompt with the inputs."""
|
|
|
|
@classmethod
|
|
def from_template(
|
|
cls: Type[T],
|
|
template: str,
|
|
template_format: str = "f-string",
|
|
response_format: Optional[str] = None,
|
|
response_key: str = "response",
|
|
template_is_strict: bool = True,
|
|
**kwargs: Any,
|
|
) -> T:
|
|
"""Create a prompt template from a template string."""
|
|
prompt = PromptTemplate.from_template(
|
|
template,
|
|
template_format,
|
|
response_format=response_format,
|
|
response_key=response_key,
|
|
template_is_strict=template_is_strict,
|
|
)
|
|
return cls(prompt=prompt, **kwargs)
|
|
|
|
|
|
class SystemPromptTemplate(BaseChatPromptTemplate):
|
|
"""The system prompt template."""
|
|
|
|
def format_messages(self, **kwargs: Any) -> List[BaseMessage]:
|
|
"""Format the prompt with the inputs.
|
|
|
|
Returns:
|
|
List[BaseMessage]: The formatted messages.
|
|
"""
|
|
content = self.prompt.format(**kwargs)
|
|
return [SystemMessage(content=content)]
|
|
|
|
|
|
class HumanPromptTemplate(BaseChatPromptTemplate):
|
|
"""The human prompt template."""
|
|
|
|
def format_messages(self, **kwargs: Any) -> List[BaseMessage]:
|
|
"""Format the prompt with the inputs.
|
|
|
|
Returns:
|
|
List[BaseMessage]: The formatted messages.
|
|
"""
|
|
content = self.prompt.format(**kwargs)
|
|
return [HumanMessage(content=content)]
|
|
|
|
|
|
class MessagesPlaceholder(BaseModel):
|
|
"""The messages placeholder template.
|
|
|
|
Mostly used for the chat history.
|
|
"""
|
|
|
|
variable_name: str
|
|
|
|
def format_messages(self, **kwargs: Any) -> List[BaseMessage]:
|
|
"""Format the prompt with the inputs.
|
|
|
|
Just return the messages from the kwargs with the variable name.
|
|
|
|
Returns:
|
|
List[BaseMessage]: The messages.
|
|
"""
|
|
messages = kwargs.get(self.variable_name, [])
|
|
if not isinstance(messages, list):
|
|
raise ValueError(
|
|
f"Unsupported messages type: {type(messages)}, should be list."
|
|
)
|
|
for message in messages:
|
|
if not isinstance(message, BaseMessage):
|
|
raise ValueError(
|
|
f"Unsupported message type: {type(message)}, should be BaseMessage."
|
|
)
|
|
return messages
|
|
|
|
@property
|
|
def input_variables(self) -> List[str]:
|
|
"""Return a list of the names of the variables the prompt template expects.
|
|
|
|
Returns:
|
|
List[str]: The input variables.
|
|
"""
|
|
return [self.variable_name]
|
|
|
|
|
|
MessageType = Union[BaseChatPromptTemplate, MessagesPlaceholder, BaseMessage]
|
|
|
|
|
|
class ChatPromptTemplate(BasePromptTemplate):
|
|
"""The chat prompt template.
|
|
|
|
Examples:
|
|
.. code-block:: python
|
|
|
|
prompt_template = ChatPromptTemplate(
|
|
messages=[
|
|
SystemPromptTemplate.from_template(
|
|
"You are a helpful AI assistant."
|
|
),
|
|
MessagesPlaceholder(variable_name="chat_history"),
|
|
HumanPromptTemplate.from_template("{question}"),
|
|
]
|
|
)
|
|
"""
|
|
|
|
messages: List[MessageType]
|
|
|
|
def format_messages(self, **kwargs: Any) -> List[BaseMessage]:
|
|
"""Format the prompt with the inputs."""
|
|
result_messages = []
|
|
for message in self.messages:
|
|
if isinstance(message, BaseMessage):
|
|
result_messages.append(message)
|
|
elif isinstance(message, (BaseChatPromptTemplate, MessagesPlaceholder)):
|
|
pass_kwargs = {
|
|
k: v for k, v in kwargs.items() if k in message.input_variables
|
|
}
|
|
result_messages.extend(message.format_messages(**pass_kwargs))
|
|
else:
|
|
raise ValueError(f"Unsupported message type: {type(message)}")
|
|
return result_messages
|
|
|
|
@model_validator(mode="before")
|
|
@classmethod
|
|
def base_pre_fill(cls, values: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Pre-fill the messages."""
|
|
if not isinstance(values, dict):
|
|
return values
|
|
input_variables = values.get("input_variables", {})
|
|
messages = values.get("messages", [])
|
|
if not input_variables:
|
|
input_variables = set()
|
|
for message in messages:
|
|
if isinstance(message, (BaseChatPromptTemplate, MessagesPlaceholder)):
|
|
input_variables.update(message.input_variables)
|
|
values["input_variables"] = sorted(input_variables)
|
|
return values
|
|
|
|
def get_placeholders(self) -> List[str]:
|
|
"""Get all placeholders in the prompt template.
|
|
|
|
Returns:
|
|
List[str]: The placeholders.
|
|
"""
|
|
placeholders = set()
|
|
for message in self.messages:
|
|
if isinstance(message, MessagesPlaceholder):
|
|
placeholders.add(message.variable_name)
|
|
return sorted(placeholders)
|
|
|
|
|
|
@dataclasses.dataclass
|
|
class PromptTemplateIdentifier(ResourceIdentifier):
|
|
"""The identifier of a prompt template."""
|
|
|
|
identifier_split: str = dataclasses.field(default="___$$$$___", init=False)
|
|
prompt_name: str
|
|
prompt_language: Optional[str] = None
|
|
sys_code: Optional[str] = None
|
|
model: Optional[str] = None
|
|
|
|
def __post_init__(self):
|
|
"""Post init method."""
|
|
if self.prompt_name is None:
|
|
raise ValueError("prompt_name cannot be None")
|
|
|
|
if any(
|
|
self.identifier_split in key
|
|
for key in [
|
|
self.prompt_name,
|
|
self.prompt_language,
|
|
self.sys_code,
|
|
self.model,
|
|
]
|
|
if key is not None
|
|
):
|
|
raise ValueError(
|
|
f"identifier_split {self.identifier_split} is not allowed in "
|
|
f"prompt_name, prompt_language, sys_code, model"
|
|
)
|
|
|
|
@property
|
|
def str_identifier(self) -> str:
|
|
"""Return the string identifier of the identifier."""
|
|
return self.identifier_split.join(
|
|
key
|
|
for key in [
|
|
self.prompt_name,
|
|
self.prompt_language,
|
|
self.sys_code,
|
|
self.model,
|
|
]
|
|
if key is not None
|
|
)
|
|
|
|
def to_dict(self) -> Dict:
|
|
"""Convert the identifier to a dict.
|
|
|
|
Returns:
|
|
Dict: The dict of the identifier.
|
|
"""
|
|
return {
|
|
"prompt_name": self.prompt_name,
|
|
"prompt_language": self.prompt_language,
|
|
"sys_code": self.sys_code,
|
|
"model": self.model,
|
|
}
|
|
|
|
|
|
@dataclasses.dataclass
|
|
class StoragePromptTemplate(StorageItem):
|
|
"""The storage prompt template."""
|
|
|
|
prompt_name: str
|
|
content: Optional[str] = None
|
|
prompt_language: Optional[str] = None
|
|
prompt_format: Optional[str] = None
|
|
input_variables: Optional[str] = None
|
|
model: Optional[str] = None
|
|
chat_scene: Optional[str] = None
|
|
sub_chat_scene: Optional[str] = None
|
|
prompt_type: Optional[str] = None
|
|
user_name: Optional[str] = None
|
|
sys_code: Optional[str] = None
|
|
_identifier: PromptTemplateIdentifier = dataclasses.field(init=False)
|
|
|
|
def __post_init__(self):
|
|
"""Post init method."""
|
|
self._identifier = PromptTemplateIdentifier(
|
|
prompt_name=self.prompt_name,
|
|
prompt_language=self.prompt_language,
|
|
sys_code=self.sys_code,
|
|
model=self.model,
|
|
)
|
|
# Assuming _check() is a method you need to call after initialization
|
|
self._check()
|
|
|
|
def to_prompt_template(self) -> PromptTemplate:
|
|
"""Convert the storage prompt template to a prompt template."""
|
|
input_variables = (
|
|
[] if not self.input_variables else self.input_variables.strip().split(",")
|
|
)
|
|
template_format = self.prompt_format or "f-string"
|
|
return PromptTemplate(
|
|
input_variables=input_variables,
|
|
template=self.content,
|
|
template_scene=self.chat_scene,
|
|
# prompt_name=self.prompt_name,
|
|
template_format=template_format,
|
|
)
|
|
|
|
@staticmethod
|
|
def from_prompt_template(
|
|
prompt_template: PromptTemplate,
|
|
prompt_name: str,
|
|
prompt_language: Optional[str] = None,
|
|
prompt_type: Optional[str] = None,
|
|
sys_code: Optional[str] = None,
|
|
user_name: Optional[str] = None,
|
|
sub_chat_scene: Optional[str] = None,
|
|
model: Optional[str] = None,
|
|
**kwargs,
|
|
) -> "StoragePromptTemplate":
|
|
"""Convert a prompt template to a storage prompt template.
|
|
|
|
Args:
|
|
prompt_template (PromptTemplate): The prompt template to convert from.
|
|
prompt_name (str): The name of the prompt.
|
|
prompt_language (Optional[str], optional): The language of the prompt.
|
|
Defaults to None. e.g. zh-cn, en.
|
|
prompt_type (Optional[str], optional): The type of the prompt.
|
|
Defaults to None. e.g. common, private.
|
|
sys_code (Optional[str], optional): The system code of the prompt.
|
|
Defaults to None.
|
|
user_name (Optional[str], optional): The username of the prompt.
|
|
Defaults to None.
|
|
sub_chat_scene (Optional[str], optional): The sub chat scene of the prompt.
|
|
Defaults to None.
|
|
model (Optional[str], optional): The model name of the prompt.
|
|
Defaults to None.
|
|
kwargs (Dict): Other params to build the storage prompt template.
|
|
"""
|
|
input_variables = prompt_template.input_variables or kwargs.get(
|
|
"input_variables"
|
|
)
|
|
if input_variables and isinstance(input_variables, list):
|
|
input_variables = ",".join(input_variables)
|
|
return StoragePromptTemplate(
|
|
prompt_name=prompt_name,
|
|
sys_code=sys_code,
|
|
user_name=user_name,
|
|
input_variables=input_variables,
|
|
model=model,
|
|
content=prompt_template.template or kwargs.get("content"),
|
|
prompt_language=prompt_language,
|
|
prompt_format=prompt_template.template_format
|
|
or kwargs.get("prompt_format"),
|
|
chat_scene=prompt_template.template_scene or kwargs.get("chat_scene"),
|
|
sub_chat_scene=sub_chat_scene,
|
|
prompt_type=prompt_type,
|
|
)
|
|
|
|
@property
|
|
def identifier(self) -> PromptTemplateIdentifier:
|
|
"""Return the identifier of the storage prompt template."""
|
|
return self._identifier
|
|
|
|
def merge(self, other: "StorageItem") -> None:
|
|
"""Merge the other item into the current item.
|
|
|
|
Args:
|
|
other (StorageItem): The other item to merge
|
|
"""
|
|
if not isinstance(other, StoragePromptTemplate):
|
|
raise ValueError(
|
|
f"Cannot merge {type(other)} into {type(self)} because they are not "
|
|
f"the same type."
|
|
)
|
|
self.from_object(other)
|
|
|
|
def to_dict(self) -> Dict:
|
|
"""Convert the storage prompt template to a dict.
|
|
|
|
Returns:
|
|
Dict: The dict of the storage prompt template.
|
|
"""
|
|
return {
|
|
"prompt_name": self.prompt_name,
|
|
"content": self.content,
|
|
"prompt_language": self.prompt_language,
|
|
"prompt_format": self.prompt_format,
|
|
"input_variables": self.input_variables,
|
|
"model": self.model,
|
|
"chat_scene": self.chat_scene,
|
|
"sub_chat_scene": self.sub_chat_scene,
|
|
"prompt_type": self.prompt_type,
|
|
"user_name": self.user_name,
|
|
"sys_code": self.sys_code,
|
|
}
|
|
|
|
def _check(self):
|
|
if self.prompt_name is None:
|
|
raise ValueError("prompt_name cannot be None")
|
|
if self.content is None:
|
|
raise ValueError("content cannot be None")
|
|
|
|
def from_object(self, template: "StoragePromptTemplate") -> None:
|
|
"""Load the prompt template from an existing prompt template object.
|
|
|
|
Args:
|
|
template (PromptTemplate): The prompt template to load from.
|
|
"""
|
|
self.content = template.content
|
|
self.prompt_format = template.prompt_format
|
|
self.input_variables = template.input_variables
|
|
self.model = template.model
|
|
self.chat_scene = template.chat_scene
|
|
self.sub_chat_scene = template.sub_chat_scene
|
|
self.prompt_type = template.prompt_type
|
|
self.user_name = template.user_name
|
|
|
|
|
|
class PromptManager:
|
|
"""The manager class for prompt templates.
|
|
|
|
Simple wrapper for the storage interface.
|
|
|
|
Examples:
|
|
.. code-block:: python
|
|
|
|
# Default use InMemoryStorage
|
|
prompt_manager = PromptManager()
|
|
prompt_template = PromptTemplate(
|
|
template="hello {input}",
|
|
input_variables=["input"],
|
|
template_scene="chat_normal",
|
|
)
|
|
prompt_manager.save(prompt_template, prompt_name="hello")
|
|
prompt_template_list = prompt_manager.list()
|
|
prompt_template_list = prompt_manager.prefer_query("hello")
|
|
|
|
With a custom storage interface.
|
|
|
|
.. code-block:: python
|
|
|
|
from dbgpt.core.interface.storage import InMemoryStorage
|
|
|
|
prompt_manager = PromptManager(InMemoryStorage())
|
|
prompt_template = PromptTemplate(
|
|
template="hello {input}",
|
|
input_variables=["input"],
|
|
template_scene="chat_normal",
|
|
)
|
|
prompt_manager.save(prompt_template, prompt_name="hello")
|
|
prompt_template_list = prompt_manager.list()
|
|
prompt_template_list = prompt_manager.prefer_query("hello")
|
|
|
|
|
|
"""
|
|
|
|
def __init__(
|
|
self, storage: Optional[StorageInterface[StoragePromptTemplate, Any]] = None
|
|
):
|
|
"""Create a new prompt manager."""
|
|
if storage is None:
|
|
storage = InMemoryStorage()
|
|
self._storage = storage
|
|
|
|
@property
|
|
def storage(self) -> StorageInterface[StoragePromptTemplate, Any]:
|
|
"""Return the storage interface for prompt templates."""
|
|
return self._storage
|
|
|
|
def prefer_query(
|
|
self,
|
|
prompt_name: str,
|
|
sys_code: Optional[str] = None,
|
|
prefer_prompt_language: Optional[str] = None,
|
|
prefer_model: Optional[str] = None,
|
|
**kwargs,
|
|
) -> List[StoragePromptTemplate]:
|
|
"""Query prompt templates from storage with prefer params.
|
|
|
|
Sometimes, we want to query prompt templates with prefer params(e.g. some
|
|
language or some model).
|
|
This method will query prompt templates with prefer params first, if not found,
|
|
will query all prompt templates.
|
|
|
|
Examples:
|
|
Query a prompt template.
|
|
.. code-block:: python
|
|
|
|
prompt_template_list = prompt_manager.prefer_query("hello")
|
|
|
|
Query with sys_code and username.
|
|
|
|
.. code-block:: python
|
|
|
|
prompt_template_list = prompt_manager.prefer_query(
|
|
"hello", sys_code="sys_code", user_name="user_name"
|
|
)
|
|
|
|
Query with prefer prompt language.
|
|
|
|
.. code-block:: python
|
|
|
|
# First query with prompt name "hello" exactly.
|
|
# Second filter with prompt language "zh-cn", if not found, will return
|
|
# all prompt templates.
|
|
prompt_template_list = prompt_manager.prefer_query(
|
|
"hello", prefer_prompt_language="zh-cn"
|
|
)
|
|
|
|
Query with prefer model.
|
|
|
|
.. code-block:: python
|
|
|
|
# First query with prompt name "hello" exactly.
|
|
# Second filter with model "vicuna-13b-v1.5", if not found, will return
|
|
# all prompt templates.
|
|
prompt_template_list = prompt_manager.prefer_query(
|
|
"hello", prefer_model="vicuna-13b-v1.5"
|
|
)
|
|
|
|
Args:
|
|
prompt_name (str): The name of the prompt template.
|
|
sys_code (Optional[str], optional): The system code of the prompt template.
|
|
Defaults to None.
|
|
prefer_prompt_language (Optional[str], optional): The language of the
|
|
prompt template. Defaults to None.
|
|
prefer_model (Optional[str], optional): The model of the prompt template.
|
|
Defaults to None.
|
|
kwargs (Dict): Other query params(If some key and value not None, wo we
|
|
query it exactly).
|
|
"""
|
|
query_spec = QuerySpec(
|
|
conditions={
|
|
"prompt_name": prompt_name,
|
|
"sys_code": sys_code,
|
|
**kwargs,
|
|
}
|
|
)
|
|
queries: List[StoragePromptTemplate] = self.storage.query(
|
|
query_spec, StoragePromptTemplate
|
|
)
|
|
if not queries:
|
|
return []
|
|
if prefer_prompt_language:
|
|
prefer_prompt_language = prefer_prompt_language.lower()
|
|
temp_queries = [
|
|
query
|
|
for query in queries
|
|
if query.prompt_language
|
|
and query.prompt_language.lower() == prefer_prompt_language
|
|
]
|
|
if temp_queries:
|
|
queries = temp_queries
|
|
if prefer_model:
|
|
prefer_model = prefer_model.lower()
|
|
temp_queries = [
|
|
query
|
|
for query in queries
|
|
if query.model and query.model.lower() == prefer_model
|
|
]
|
|
if temp_queries:
|
|
queries = temp_queries
|
|
return queries
|
|
|
|
def save(self, prompt_template: PromptTemplate, prompt_name: str, **kwargs) -> None:
|
|
"""Save a prompt template to storage.
|
|
|
|
Examples:
|
|
.. code-block:: python
|
|
|
|
prompt_template = PromptTemplate(
|
|
template="hello {input}",
|
|
input_variables=["input"],
|
|
template_scene="chat_normal",
|
|
prompt_name="hello",
|
|
)
|
|
prompt_manager.save(prompt_template)
|
|
|
|
Save with sys_code and username.
|
|
|
|
.. code-block:: python
|
|
|
|
prompt_template = PromptTemplate(
|
|
template="hello {input}",
|
|
input_variables=["input"],
|
|
template_scene="chat_normal",
|
|
prompt_name="hello",
|
|
)
|
|
prompt_manager.save(
|
|
prompt_template, sys_code="sys_code", user_name="user_name"
|
|
)
|
|
|
|
Args:
|
|
prompt_template (PromptTemplate): The prompt template to save.
|
|
prompt_name (str): The name of the prompt template.
|
|
kwargs (Dict): Other params to build the storage prompt template.
|
|
More details in :meth:`~StoragePromptTemplate.from_prompt_template`.
|
|
"""
|
|
storage_prompt_template = StoragePromptTemplate.from_prompt_template(
|
|
prompt_template, prompt_name, **kwargs
|
|
)
|
|
self.storage.save(storage_prompt_template)
|
|
|
|
def query_or_save(
|
|
self, prompt_template: PromptTemplate, prompt_name: str, **kwargs
|
|
) -> StoragePromptTemplate:
|
|
"""Query a prompt template from storage, if not found, save it.
|
|
|
|
Args:
|
|
prompt_template (PromptTemplate): The prompt template to save.
|
|
prompt_name (str): The name of the prompt template.
|
|
kwargs (Dict): Other params to build the storage prompt template.
|
|
More details in :meth:`~StoragePromptTemplate.from_prompt_template`.
|
|
|
|
Returns:
|
|
StoragePromptTemplate: The storage prompt template.
|
|
"""
|
|
storage_prompt_template = StoragePromptTemplate.from_prompt_template(
|
|
prompt_template, prompt_name, **kwargs
|
|
)
|
|
exist_prompt_template = self.storage.load(
|
|
storage_prompt_template.identifier, StoragePromptTemplate
|
|
)
|
|
if exist_prompt_template:
|
|
return exist_prompt_template
|
|
self.save(prompt_template, prompt_name, **kwargs)
|
|
prompt = self.storage.load(
|
|
storage_prompt_template.identifier, StoragePromptTemplate
|
|
)
|
|
if not prompt:
|
|
raise ValueError("Can't read prompt from storage")
|
|
return prompt
|
|
|
|
def list(self, **kwargs) -> List[StoragePromptTemplate]:
|
|
"""List prompt templates from storage.
|
|
|
|
Examples:
|
|
List all prompt templates.
|
|
.. code-block:: python
|
|
|
|
all_prompt_templates = prompt_manager.list()
|
|
|
|
List with sys_code and username.
|
|
|
|
.. code-block:: python
|
|
|
|
templates = prompt_manager.list(
|
|
sys_code="sys_code", user_name="user_name"
|
|
)
|
|
|
|
Args:
|
|
kwargs (Dict): Other query params.
|
|
"""
|
|
query_spec = QuerySpec(conditions=kwargs)
|
|
return self.storage.query(query_spec, StoragePromptTemplate)
|
|
|
|
def delete(
|
|
self,
|
|
prompt_name: str,
|
|
prompt_language: Optional[str] = None,
|
|
sys_code: Optional[str] = None,
|
|
model: Optional[str] = None,
|
|
) -> None:
|
|
"""Delete a prompt template from storage.
|
|
|
|
Examples:
|
|
Delete a prompt template.
|
|
|
|
.. code-block:: python
|
|
|
|
prompt_manager.delete("hello")
|
|
|
|
Delete with sys_code and username.
|
|
|
|
.. code-block:: python
|
|
|
|
prompt_manager.delete(
|
|
"hello", sys_code="sys_code", user_name="user_name"
|
|
)
|
|
|
|
Args:
|
|
prompt_name (str): The name of the prompt template.
|
|
prompt_language (Optional[str], optional): The language of the prompt
|
|
template. Defaults to None.
|
|
sys_code (Optional[str], optional): The system code of the prompt template.
|
|
Defaults to None.
|
|
model (Optional[str], optional): The model of the prompt template.
|
|
Defaults to None.
|
|
"""
|
|
identifier = PromptTemplateIdentifier(
|
|
prompt_name=prompt_name,
|
|
prompt_language=prompt_language,
|
|
sys_code=sys_code,
|
|
model=model,
|
|
)
|
|
self.storage.delete(identifier)
|
|
|
|
|
|
def _get_string_template_vars(template_str: str) -> Set[str]:
|
|
"""Get template variables from a template string."""
|
|
variables = set()
|
|
formatter = Formatter()
|
|
|
|
for _, variable_name, _, _ in formatter.parse(template_str):
|
|
if variable_name:
|
|
variables.add(variable_name)
|
|
|
|
return variables
|
|
|
|
|
|
def _get_jinja2_template_vars(template_str: str) -> Set[str]:
|
|
"""Get template variables from a template string."""
|
|
from jinja2 import Environment, meta
|
|
|
|
env = Environment()
|
|
ast = env.parse(template_str)
|
|
variables = meta.find_undeclared_variables(ast)
|
|
return variables
|
|
|
|
|
|
def get_template_vars(
|
|
template_str: str, template_format: str = "f-string"
|
|
) -> List[str]:
|
|
"""Get template variables from a template string."""
|
|
if template_format == "f-string":
|
|
result = _get_string_template_vars(template_str)
|
|
elif template_format == "jinja2":
|
|
result = _get_jinja2_template_vars(template_str)
|
|
else:
|
|
raise ValueError(f"Unsupported template format: {template_format}")
|
|
return sorted(result)
|