Files
microsoft--semantic-kernel/python/semantic_kernel/prompt_template/prompt_template_config.py
T
wehub-resource-sync b957a53def
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 13:21:23 +08:00

139 lines
6.0 KiB
Python

# Copyright (c) Microsoft. All rights reserved.
import logging
from collections.abc import MutableMapping, MutableSequence, Sequence
from typing import TypeVar
from pydantic import Field, field_validator, model_validator
from semantic_kernel.connectors.ai.prompt_execution_settings import PromptExecutionSettings
from semantic_kernel.const import DEFAULT_SERVICE_NAME
from semantic_kernel.functions.kernel_parameter_metadata import KernelParameterMetadata
from semantic_kernel.kernel_pydantic import KernelBaseModel
from semantic_kernel.prompt_template.const import KERNEL_TEMPLATE_FORMAT_NAME, TEMPLATE_FORMAT_TYPES
from semantic_kernel.prompt_template.input_variable import InputVariable
PromptExecutionSettingsT = TypeVar("PromptExecutionSettingsT", bound=PromptExecutionSettings)
logger: logging.Logger = logging.getLogger(__name__)
_T = TypeVar("_T", bound="PromptTemplateConfig")
class PromptTemplateConfig(KernelBaseModel):
"""Configuration for a prompt template.
Args:
name: The name of the prompt template.
description: The description of the prompt template.
template: The template for the prompt.
template_format: The format of the template, should be 'semantic-kernel', 'jinja2' or 'handlebars'.
input_variables: The input variables for the prompt.
allow_dangerously_set_content (bool = False): Allow content without encoding throughout, this overrides
the same settings in the prompt template config and input variables.
This reverts the behavior to unencoded input.
execution_settings: The execution settings for the prompt.
"""
name: str = ""
description: str | None = ""
template: str | None = None
template_format: TEMPLATE_FORMAT_TYPES = KERNEL_TEMPLATE_FORMAT_NAME
input_variables: MutableSequence[InputVariable] = Field(default_factory=list)
allow_dangerously_set_content: bool = False
execution_settings: MutableMapping[str, PromptExecutionSettings] = Field(default_factory=dict)
@model_validator(mode="after")
def check_input_variables(self):
"""Verify that input variable default values are string only."""
for variable in self.input_variables:
if variable.default and not isinstance(variable.default, str):
raise TypeError(f"Default value for input variable {variable.name} must be a string.")
return self
@field_validator("execution_settings", mode="before")
@classmethod
def rewrite_execution_settings(
cls: type[_T],
settings: PromptExecutionSettings
| Sequence[PromptExecutionSettings]
| MutableMapping[str, PromptExecutionSettings]
| None,
) -> MutableMapping[str, PromptExecutionSettings]:
"""Rewrite execution settings to a dictionary."""
if not settings:
return {}
if isinstance(settings, PromptExecutionSettings):
return {settings.service_id or DEFAULT_SERVICE_NAME: settings}
if isinstance(settings, Sequence):
return {s.service_id or DEFAULT_SERVICE_NAME: s for s in settings}
return settings
def add_execution_settings(self, settings: PromptExecutionSettings, overwrite: bool = True) -> None:
"""Add execution settings to the prompt template."""
if settings.service_id in self.execution_settings and not overwrite:
return
self.execution_settings[settings.service_id or DEFAULT_SERVICE_NAME] = settings
logger.warning("Execution settings already exist and overwrite is set to False")
def get_kernel_parameter_metadata(self) -> Sequence[KernelParameterMetadata]:
"""Get the kernel parameter metadata for the input variables."""
return [
KernelParameterMetadata(
name=variable.name,
description=variable.description,
default_value=variable.default,
type_=variable.json_schema, # TODO (moonbox3): update to handle complex JSON schemas # type: ignore
is_required=variable.is_required,
)
for variable in self.input_variables
]
@classmethod
def from_json(cls: type[_T], json_str: str) -> _T:
"""Create a PromptTemplateConfig instance from a JSON string."""
if not json_str:
raise ValueError("json_str is empty")
try:
return cls.model_validate_json(json_str)
except Exception as exc:
raise ValueError(
"Unable to deserialize PromptTemplateConfig from the "
f"specified JSON string: {json_str} with exception: {exc}"
) from exc
@classmethod
def restore(
cls: type[_T],
name: str,
description: str,
template: str,
template_format: TEMPLATE_FORMAT_TYPES = KERNEL_TEMPLATE_FORMAT_NAME,
input_variables: MutableSequence[InputVariable] | None = None,
execution_settings: MutableMapping[str, PromptExecutionSettings] | None = None,
allow_dangerously_set_content: bool = False,
) -> _T:
"""Restore a PromptTemplateConfig instance from the specified parameters.
Args:
name: The name of the prompt template.
description: The description of the prompt template.
template: The template for the prompt.
template_format: The format of the template, should be 'semantic-kernel', 'jinja2' or 'handlebars'.
input_variables: The input variables for the prompt.
execution_settings: The execution settings for the prompt.
allow_dangerously_set_content: Allow content without encoding.
Returns:
A new PromptTemplateConfig instance.
"""
return cls(
name=name,
description=description,
template=template,
template_format=template_format,
input_variables=input_variables or [],
execution_settings=execution_settings or {},
allow_dangerously_set_content=allow_dangerously_set_content,
)