Tony20100/langchain_full huggingface dataset:
Source code for langchain_core.prompts.string
"""BasePrompt schema definition."""
from __future__ import annotations
import warnings
from abc import ABC
from string import Formatter
from typing import Any, Callable, Dict, List, Set, Tuple, Type
import langchain_core.utils.mustache as mustache
from langchain_core.prompt_values import PromptValue, StringPromptValue
from langchain_core.prompts.base import BasePromptTemplate
from langchain_core.pydantic_v1 import BaseModel, create_model
from langchain_core.utils import get_colored_text
from langchain_core.utils.formatting import formatter
from langchain_core.utils.interactive_env import is_interactive_env
[docs]def jinja2_formatter(template: str, **kwargs: Any) -> str:
    """Format a template using jinja2.
    *Security warning*: As of LangChain 0.0.329, this method uses Jinja2's
        SandboxedEnvironment by default. However, this sand-boxing should
        be treated as a best-effort approach rather than a guarantee of security.
        Do not accept jinja2 templates from untrusted sources as they may lead
        to arbitrary Python code execution.
        https://jinja.palletsprojects.com/en/3.1.x/sandbox/
    """
    try:
        from jinja2.sandbox import SandboxedEnvironment
    except ImportError:
        raise ImportError(
            "jinja2 not installed, which is needed to use the jinja2_formatter. "
            "Please install it with `pip install jinja2`."
            "Please be cautious when using jinja2 templates. "
            "Do not expand jinja2 templates using unverified or user-controlled "
            "inputs as that can result in arbitrary Python code execution."
        )
"inputs as that can result in arbitrary Python code execution."
        )
    # This uses a sandboxed environment to prevent arbitrary code execution.
    # Jinja2 uses an opt-out rather than opt-in approach for sand-boxing.
    # Please treat this sand-boxing as a best-effort approach rather than
    # a guarantee of security.
    # We recommend to never use jinja2 templates with untrusted inputs.
    # https://jinja.palletsprojects.com/en/3.1.x/sandbox/
    # approach not a guarantee of security.
    return SandboxedEnvironment().from_string(template).render(**kwargs)
[docs]def validate_jinja2(template: str, input_variables: List[str]) -> None:
    """
    Validate that the input variables are valid for the template.
    Issues a warning if missing or extra variables are found.
    Args:
        template: The template string.
        input_variables: The input variables.
    """
    input_variables_set = set(input_variables)
    valid_variables = _get_jinja2_variables_from_template(template)
    missing_variables = valid_variables - input_variables_set
    extra_variables = input_variables_set - valid_variables
    warning_message = ""
    if missing_variables:
        warning_message += f"Missing variables: {missing_variables} "
    if extra_variables:
        warning_message += f"Extra variables: {extra_variables}"
    if warning_message:
        warnings.warn(warning_message.strip())
def _get_jinja2_variables_from_template(template: str) -> Set[str]:
    try:
        from jinja2 import Environment, meta
    except ImportError:
        raise ImportError(
            "jinja2 not installed, which is needed to use the jinja2_formatter. "
"Please install it with `pip install jinja2`."
        )
    env = Environment()
    ast = env.parse(template)
    variables = meta.find_undeclared_variables(ast)
    return variables
[docs]def mustache_formatter(template: str, **kwargs: Any) -> str:
    """Format a template using mustache."""
    return mustache.render(template, kwargs)
[docs]def mustache_template_vars(
    template: str,
) -> Set[str]:
    """Get the variables from a mustache template."""
    vars: Set[str] = set()
    in_section = False
    for type, key in mustache.tokenize(template):
        if type == "end":
            in_section = False
        elif in_section:
            continue
        elif type in ("variable", "section") and key != ".":
            vars.add(key.split(".")[0])
            if type == "section":
                in_section = True
    return vars
Defs = Dict[str, "Defs"]
[docs]def mustache_schema(
    template: str,
) -> Type[BaseModel]:
    """Get the variables from a mustache template."""
    fields = set()
    prefix: Tuple[str, ...] = ()
    for type, key in mustache.tokenize(template):
        if key == ".":
            continue
        if type == "end":
            prefix = prefix[: -key.count(".")]
        elif type == "section":
            prefix = prefix + tuple(key.split("."))
        elif type == "variable":
            fields.add(prefix + tuple(key.split(".")))
    defs: Defs = {}  # None means leaf node
    while fields:
        field = fields.pop()
        current = defs
        for part in field[:-1]:
current = defs
        for part in field[:-1]:
            current = current.setdefault(part, {})
        current[field[-1]] = {}
    return _create_model_recursive("PromptInput", defs)
def _create_model_recursive(name: str, defs: Defs) -> Type:
    return create_model(  # type: ignore[call-overload]
        name,
        **{
            k: (_create_model_recursive(k, v), None) if v else (str, None)
            for k, v in defs.items()
        },
    )
DEFAULT_FORMATTER_MAPPING: Dict[str, Callable] = {
    "f-string": formatter.format,
    "mustache": mustache_formatter,
    "jinja2": jinja2_formatter,
}
DEFAULT_VALIDATOR_MAPPING: Dict[str, Callable] = {
    "f-string": formatter.validate_input_variables,
    "jinja2": validate_jinja2,
}
[docs]def check_valid_template(
    template: str, template_format: str, input_variables: List[str]
) -> None:
    """Check that template string is valid.
    Args:
        template: The template string.
        template_format: The template format. Should be one of "f-string" or "jinja2".
        input_variables: The input variables.
    Raises:
        ValueError: If the template format is not supported.
    """
    try:
        validator_func = DEFAULT_VALIDATOR_MAPPING[template_format]
    except KeyError as exc:
        raise ValueError(
            f"Invalid template format {template_format!r}, should be one of"
            f" {list(DEFAULT_FORMATTER_MAPPING)}."
        ) from exc
    try:
        validator_func(template, input_variables)
) from exc
    try:
        validator_func(template, input_variables)
    except (KeyError, IndexError) as exc:
        raise ValueError(
            "Invalid prompt schema; check for mismatched or missing input parameters"
            f" from {input_variables}."
        ) from exc
[docs]def get_template_variables(template: str, template_format: str) -> List[str]:
    """Get the variables from the template.
    Args:
        template: The template string.
        template_format: The template format. Should be one of "f-string" or "jinja2".
    Returns:
        The variables from the template.
    Raises:
        ValueError: If the template format is not supported.
    """
    if template_format == "jinja2":
        # Get the variables for the template
        input_variables = _get_jinja2_variables_from_template(template)
    elif template_format == "f-string":
        input_variables = {
            v for _, v, _, _ in Formatter().parse(template) if v is not None
        }
    elif template_format == "mustache":
        input_variables = mustache_template_vars(template)
    else:
        raise ValueError(f"Unsupported template format: {template_format}")
    return sorted(input_variables)
[docs]class StringPromptTemplate(BasePromptTemplate, ABC):
    """String prompt that exposes the format method, returning a prompt."""
[docs]    @classmethod
    def get_lc_namespace(cls) -> List[str]:
        """Get the namespace of the langchain object."""
        return ["langchain", "prompts", "base"]
[docs]    def format_prompt(self, **kwargs: Any) -> PromptValue:
        return StringPromptValue(text=self.format(**kwargs))
return StringPromptValue(text=self.format(**kwargs))
[docs]    async def aformat_prompt(self, **kwargs: Any) -> PromptValue:
        return StringPromptValue(text=await self.aformat(**kwargs))
[docs]    def pretty_repr(self, html: bool = False) -> str:
        # TODO: handle partials
        dummy_vars = {
            input_var: "{" + f"{input_var}" + "}" for input_var in self.input_variables
        }
        if html:
            dummy_vars = {
                k: get_colored_text(v, "yellow") for k, v in dummy_vars.items()
            }
        return self.format(**dummy_vars)
[docs]    def pretty_print(self) -> None:
        print(self.pretty_repr(html=is_interactive_env()))  # noqa: T201
Source code for langchain_core.prompts.structured
from typing import (
    Any,
    Callable,
    Dict,
    Iterator,
    List,
    Mapping,
    Optional,
    Sequence,
    Set,
    Type,
    Union,
)
from langchain_core._api.beta_decorator import beta
from langchain_core.language_models.base import BaseLanguageModel
from langchain_core.prompts.chat import (
    BaseChatPromptTemplate,
    BaseMessagePromptTemplate,
    ChatPromptTemplate,
    MessageLikeRepresentation,
    MessagesPlaceholder,
    _convert_to_message,
)
from langchain_core.pydantic_v1 import BaseModel
from langchain_core.runnables.base import (
    Other,
    Runnable,
    RunnableSequence,
    RunnableSerializable,
)
[docs]@beta()
class StructuredPrompt(ChatPromptTemplate):
    """Structured prompt template for a language model."""
    schema_: Union[Dict, Type[BaseModel]]
    """Schema for the structured prompt."""
[docs]    @classmethod
    def get_lc_namespace(cls) -> List[str]:
        """Get the namespace of the langchain object.
        For example, if the class is `langchain.llms.openai.OpenAI`, then the
        namespace is ["langchain", "llms", "openai"]
        """
        return cls.__module__.split(".")
[docs]    @classmethod
    def from_messages_and_schema(
        cls,
        messages: Sequence[MessageLikeRepresentation],
        schema: Union[Dict, Type[BaseModel]],
    ) -> ChatPromptTemplate:
        """Create a chat prompt template from a variety of message formats.
        Examples:
            Instantiation from a list of message templates:
            .. code-block:: python
Instantiation from a list of message templates:
            .. code-block:: python
                class OutputSchema(BaseModel):
                    name: str
                    value: int
                template = ChatPromptTemplate.from_messages(
                    [
                        ("human", "Hello, how are you?"),
                        ("ai", "I'm doing well, thanks!"),
                        ("human", "That's good to hear."),
                    ],
                    OutputSchema,
                )
        Args:
            messages: sequence of message representations.
                  A message can be represented using the following formats:
                  (1) BaseMessagePromptTemplate, (2) BaseMessage, (3) 2-tuple of
                  (message type, template); e.g., ("human", "{user_input}"),
                  (4) 2-tuple of (message class, template), (4) a string which is
                  shorthand for ("human", template); e.g., "{user_input}"
            schema: a dictionary representation of function call, or a Pydantic model.
        Returns:
            a structured prompt template
        """
        _messages = [_convert_to_message(message) for message in messages]
        # Automatically infer input variables from messages
        input_vars: Set[str] = set()
        partial_vars: Dict[str, Any] = {}
        for _message in _messages:
            if isinstance(_message, MessagesPlaceholder) and _message.optional:
                partial_vars[_message.variable_name] = []
            elif isinstance(
                _message, (BaseChatPromptTemplate, BaseMessagePromptTemplate)
            ):
                input_vars.update(_message.input_variables)
        return cls(
            input_variables=sorted(input_vars),
            messages=_messages,
            partial_variables=partial_vars,
            schema_=schema,
        )
    def __or__(
schema_=schema,
        )
    def __or__(
        self,
        other: Union[
            Runnable[Any, Other],
            Callable[[Any], Other],
            Callable[[Iterator[Any]], Iterator[Other]],
            Mapping[str, Union[Runnable[Any, Other], Callable[[Any], Other], Any]],
        ],
    ) -> RunnableSerializable[Dict, Other]:
        if isinstance(other, BaseLanguageModel) or hasattr(
            other, "with_structured_output"
        ):
            try:
                return RunnableSequence(
                    self, other.with_structured_output(self.schema_)
                )
            except NotImplementedError as e:
                raise NotImplementedError(
                    "Structured prompts must be piped to a language model that "
                    "implements with_structured_output."
                ) from e
        else:
            raise NotImplementedError(
                "Structured prompts must be piped to a language model that "
                "implements with_structured_output."
            )
[docs]    def pipe(
        self,
        *others: Union[Runnable[Any, Other], Callable[[Any], Other]],
        name: Optional[str] = None,
    ) -> RunnableSerializable[Dict, Other]:
        if (
            others
            and isinstance(others[0], BaseLanguageModel)
            or hasattr(others[0], "with_structured_output")
        ):
            return RunnableSequence(
                self,
                others[0].with_structured_output(self.schema_),
                *others[1:],
                name=name,
            )
        else:
            raise NotImplementedError(
                "Structured prompts need to be piped to a language model."
            )
Source code for langchain_core.prompts.pipeline
from typing import Any, Dict, List, Tuple
from langchain_core.prompt_values import PromptValue
from langchain_core.prompts.base import BasePromptTemplate
from langchain_core.prompts.chat import BaseChatPromptTemplate
from langchain_core.pydantic_v1 import root_validator
def _get_inputs(inputs: dict, input_variables: List[str]) -> dict:
    return {k: inputs[k] for k in input_variables}
[docs]class PipelinePromptTemplate(BasePromptTemplate):
    """Prompt template for composing multiple prompt templates together.
    This can be useful when you want to reuse parts of prompts.
    A PipelinePrompt consists of two main parts:
        - final_prompt: This is the final prompt that is returned
        - pipeline_prompts: This is a list of tuples, consisting
            of a string (`name`) and a Prompt Template.
            Each PromptTemplate will be formatted and then passed
            to future prompt templates as a variable with
            the same name as `name`
    """
    final_prompt: BasePromptTemplate
    """The final prompt that is returned."""
    pipeline_prompts: List[Tuple[str, BasePromptTemplate]]
    """A list of tuples, consisting of a string (`name`) and a Prompt Template."""
[docs]    @classmethod
    def get_lc_namespace(cls) -> List[str]:
        """Get the namespace of the langchain object."""
        return ["langchain", "prompts", "pipeline"]
    @root_validator(pre=True)
    def get_input_variables(cls, values: Dict) -> Dict:
        """Get input variables."""
        created_variables = set()
        all_variables = set()
        for k, prompt in values["pipeline_prompts"]:
            created_variables.add(k)
            all_variables.update(prompt.input_variables)
created_variables.add(k)
            all_variables.update(prompt.input_variables)
        values["input_variables"] = list(all_variables.difference(created_variables))
        return values
[docs]    def format_prompt(self, **kwargs: Any) -> PromptValue:
        for k, prompt in self.pipeline_prompts:
            _inputs = _get_inputs(kwargs, prompt.input_variables)
            if isinstance(prompt, BaseChatPromptTemplate):
                kwargs[k] = prompt.format_messages(**_inputs)
            else:
                kwargs[k] = prompt.format(**_inputs)
        _inputs = _get_inputs(kwargs, self.final_prompt.input_variables)
        return self.final_prompt.format_prompt(**_inputs)
[docs]    async def aformat_prompt(self, **kwargs: Any) -> PromptValue:
        for k, prompt in self.pipeline_prompts:
            _inputs = _get_inputs(kwargs, prompt.input_variables)
            if isinstance(prompt, BaseChatPromptTemplate):
                kwargs[k] = await prompt.aformat_messages(**_inputs)
            else:
                kwargs[k] = await prompt.aformat(**_inputs)
        _inputs = _get_inputs(kwargs, self.final_prompt.input_variables)
        return await self.final_prompt.aformat_prompt(**_inputs)
[docs]    def format(self, **kwargs: Any) -> str:
        return self.format_prompt(**kwargs).to_string()
[docs]    async def aformat(self, **kwargs: Any) -> str:
        return (await self.aformat_prompt(**kwargs)).to_string()
    @property
    def _prompt_type(self) -> str:
        raise ValueError
Source code for langchain_core.prompts.chat
"""Chat prompt template."""
from __future__ import annotations
from abc import ABC, abstractmethod
from pathlib import Path
from typing import (
    Any,
    Dict,
    List,
    Literal,
    Optional,
    Sequence,
    Set,
    Tuple,
    Type,
    TypedDict,
    TypeVar,
    Union,
    cast,
    overload,
)
from langchain_core._api import deprecated
from langchain_core.load import Serializable
from langchain_core.messages import (
    AIMessage,
    AnyMessage,
    BaseMessage,
    ChatMessage,
    HumanMessage,
    SystemMessage,
    convert_to_messages,
)
from langchain_core.messages.base import get_msg_title_repr
from langchain_core.prompt_values import ChatPromptValue, ImageURL, PromptValue
from langchain_core.prompts.base import BasePromptTemplate
from langchain_core.prompts.image import ImagePromptTemplate
from langchain_core.prompts.prompt import PromptTemplate
from langchain_core.prompts.string import StringPromptTemplate, get_template_variables
from langchain_core.pydantic_v1 import Field, root_validator
from langchain_core.utils import get_colored_text
from langchain_core.utils.interactive_env import is_interactive_env
[docs]class BaseMessagePromptTemplate(Serializable, ABC):
    """Base class for message prompt templates."""
[docs]    @classmethod
    def is_lc_serializable(cls) -> bool:
        """Return whether or not the class is serializable."""
        return True
[docs]    @classmethod
    def get_lc_namespace(cls) -> List[str]:
        """Get the namespace of the langchain object."""
        return ["langchain", "prompts", "chat"]
[docs]    @abstractmethod
[docs]    @abstractmethod
    def format_messages(self, **kwargs: Any) -> List[BaseMessage]:
        """Format messages from kwargs. Should return a list of BaseMessages.
        Args:
            **kwargs: Keyword arguments to use for formatting.
        Returns:
            List of BaseMessages.
        """
[docs]    async def aformat_messages(self, **kwargs: Any) -> List[BaseMessage]:
        """Format messages from kwargs. Should return a list of BaseMessages.
        Args:
            **kwargs: Keyword arguments to use for formatting.
        Returns:
            List of BaseMessages.
        """
        return self.format_messages(**kwargs)
    @property
    @abstractmethod
    def input_variables(self) -> List[str]:
        """Input variables for this prompt template.
        Returns:
            List of input variables.
        """
[docs]    def pretty_repr(self, html: bool = False) -> str:
        """Human-readable representation."""
        raise NotImplementedError
[docs]    def pretty_print(self) -> None:
        print(self.pretty_repr(html=is_interactive_env()))  # noqa: T201
    def __add__(self, other: Any) -> ChatPromptTemplate:
        """Combine two prompt templates.
        Args:
            other: Another prompt template.
        Returns:
            Combined prompt template.
        """
        prompt = ChatPromptTemplate(messages=[self])  # type: ignore[call-arg]
        return prompt + other
[docs]class MessagesPlaceholder(BaseMessagePromptTemplate):
    """Prompt template that assumes variable is already list of messages.
    A placeholder which can be used to pass in a list of messages.
    Direct usage:
        .. code-block:: python
            from langchain_core.prompts import MessagesPlaceholder
.. code-block:: python
            from langchain_core.prompts import MessagesPlaceholder
            prompt = MessagesPlaceholder("history")
            prompt.format_messages() # raises KeyError
            prompt = MessagesPlaceholder("history", optional=True)
            prompt.format_messages() # returns empty list []
            prompt.format_messages(
                history=[
                    ("system", "You are an AI assistant."),
                    ("human", "Hello!"),
                ]
            )
            # -> [
            #     SystemMessage(content="You are an AI assistant."),
            #     HumanMessage(content="Hello!"),
            # ]
    Building a prompt with chat history:
        .. code-block:: python
            from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
            prompt = ChatPromptTemplate.from_messages(
                [
                    ("system", "You are a helpful assistant."),
                    MessagesPlaceholder("history"),
                    ("human", "{question}")
                ]
            )
            prompt.invoke(
               {
                   "history": [("human", "what's 5 + 2"), ("ai", "5 + 2 is 7")],
                   "question": "now multiply that by 4"
               }
            )
            # -> ChatPromptValue(messages=[
            #     SystemMessage(content="You are a helpful assistant."),
            #     HumanMessage(content="what's 5 + 2"),
            #     AIMessage(content="5 + 2 is 7"),
            #     HumanMessage(content="now multiply that by 4"),
            # ])
    """
    variable_name: str
    """Name of variable to use as messages."""
    optional: bool = False
    """If True format_messages can be called with no arguments and will return an empty
"""If True format_messages can be called with no arguments and will return an empty 
        list. If False then a named argument with name `variable_name` must be passed 
        in, even if the value is an empty list."""
[docs]    @classmethod
    def get_lc_namespace(cls) -> List[str]:
        """Get the namespace of the langchain object."""
        return ["langchain", "prompts", "chat"]
    def __init__(self, variable_name: str, *, optional: bool = False, **kwargs: Any):
        super().__init__(variable_name=variable_name, optional=optional, **kwargs)
[docs]    def format_messages(self, **kwargs: Any) -> List[BaseMessage]:
        """Format messages from kwargs.
        Args:
            **kwargs: Keyword arguments to use for formatting.
        Returns:
            List of BaseMessage.
        """
        value = (
            kwargs.get(self.variable_name, [])
            if self.optional
            else kwargs[self.variable_name]
        )
        if not isinstance(value, list):
            raise ValueError(
                f"variable {self.variable_name} should be a list of base messages, "
                f"got {value}"
            )
        return convert_to_messages(value)
    @property
    def input_variables(self) -> List[str]:
        """Input variables for this prompt template.
        Returns:
            List of input variable names.
        """
        return [self.variable_name] if not self.optional else []
[docs]    def pretty_repr(self, html: bool = False) -> str:
        var = "{" + self.variable_name + "}"
        if html:
            title = get_msg_title_repr("Messages Placeholder", bold=True)
            var = get_colored_text(var, "yellow")