Source code for langchain_core.prompts.few_shot

"""包含少量示例的提示模板。"""

from __future__ import annotations

from pathlib import Path
from typing import Any, Dict, List, Literal, Optional, Union

from langchain_core.example_selectors import BaseExampleSelector
from langchain_core.messages import BaseMessage, get_buffer_string
from langchain_core.prompts.chat import (
    BaseChatPromptTemplate,
    BaseMessagePromptTemplate,
)
from langchain_core.prompts.prompt import PromptTemplate
from langchain_core.prompts.string import (
    DEFAULT_FORMATTER_MAPPING,
    StringPromptTemplate,
    check_valid_template,
    get_template_variables,
)
from langchain_core.pydantic_v1 import BaseModel, Extra, Field, root_validator


class _FewShotPromptTemplateMixin(BaseModel):
    """包含少量示例的提示模板。"""

    examples: Optional[List[dict]] = None
    """需要格式化到提示符中的示例。
    应提供这个或者example_selector中的一个。"""

    example_selector: Optional[BaseExampleSelector] = None
    """选择要格式化为提示符的示例的ExampleSelector。
应提供此项或示例。"""

    class Config:
        """这个pydantic对象的配置。"""

        extra = Extra.forbid
        arbitrary_types_allowed = True

    @root_validator(pre=True)
    def check_examples_and_selector(cls, values: Dict) -> Dict:
        """检查是否提供了一个且仅一个 examples/example_selector。"""
        examples = values.get("examples", None)
        example_selector = values.get("example_selector", None)
        if examples and example_selector:
            raise ValueError(
                "Only one of 'examples' and 'example_selector' should be provided"
            )

        if examples is None and example_selector is None:
            raise ValueError(
                "One of 'examples' and 'example_selector' should be provided"
            )

        return values

    def _get_examples(self, **kwargs: Any) -> List[dict]:
        """获取用于格式化提示的示例。

参数:
    **kwargs: 要传递给示例选择器的关键字参数。

返回:
    示例列表。
"""
        if self.examples is not None:
            return self.examples
        elif self.example_selector is not None:
            return self.example_selector.select_examples(kwargs)
        else:
            raise ValueError(
                "One of 'examples' and 'example_selector' should be provided"
            )

    async def _aget_examples(self, **kwargs: Any) -> List[dict]:
        """获取用于格式化提示的示例。

参数:
    **kwargs: 要传递给示例选择器的关键字参数。

返回:
    示例列表。
"""
        if self.examples is not None:
            return self.examples
        elif self.example_selector is not None:
            return await self.example_selector.aselect_examples(kwargs)
        else:
            raise ValueError(
                "One of 'examples' and 'example_selector' should be provided"
            )


[docs]class FewShotPromptTemplate(_FewShotPromptTemplateMixin, StringPromptTemplate): """包含少量示例的提示模板。"""
[docs] @classmethod def is_lc_serializable(cls) -> bool: """返回类是否可序列化。""" return False
validate_template: bool = False """是否尝试验证模板。""" input_variables: List[str] """提示模板期望的变量名称列表。""" example_prompt: PromptTemplate """用于格式化单个示例的PromptTemplate。""" suffix: str """一个用于放置示例后的提示模板字符串。""" example_separator: str = "\n\n" """用于连接前缀、示例和后缀的字符串分隔符。""" prefix: str = "" """一个放在示例之前的提示模板字符串。""" template_format: Literal["f-string", "jinja2"] = "f-string" """提示模板的格式。选项包括:'f-string','jinja2'。""" @root_validator() def template_is_valid(cls, values: Dict) -> Dict: """检查前缀、后缀和输入变量是否一致。""" if values["validate_template"]: check_valid_template( values["prefix"] + values["suffix"], values["template_format"], values["input_variables"] + list(values["partial_variables"]), ) elif values.get("template_format"): values["input_variables"] = [ var for var in get_template_variables( values["prefix"] + values["suffix"], values["template_format"] ) if var not in values["partial_variables"] ] return values class Config: """这个pydantic对象的配置。""" extra = Extra.forbid arbitrary_types_allowed = True
[docs] def format(self, **kwargs: Any) -> str: kwargs = self._merge_partial_and_user_variables(**kwargs) # Get the examples to use. examples = self._get_examples(**kwargs) examples = [ {k: e[k] for k in self.example_prompt.input_variables} for e in examples ] # Format the examples. example_strings = [ self.example_prompt.format(**example) for example in examples ] # Create the overall template. pieces = [self.prefix, *example_strings, self.suffix] template = self.example_separator.join([piece for piece in pieces if piece]) # Format the template with the input variables. return DEFAULT_FORMATTER_MAPPING[self.template_format](template, **kwargs)
[docs] async def aformat(self, **kwargs: Any) -> str: kwargs = self._merge_partial_and_user_variables(**kwargs) # Get the examples to use. examples = await self._aget_examples(**kwargs) examples = [ {k: e[k] for k in self.example_prompt.input_variables} for e in examples ] # Format the examples. example_strings = [ await self.example_prompt.aformat(**example) for example in examples ] # Create the overall template. pieces = [self.prefix, *example_strings, self.suffix] template = self.example_separator.join([piece for piece in pieces if piece]) # Format the template with the input variables. return DEFAULT_FORMATTER_MAPPING[self.template_format](template, **kwargs)
@property def _prompt_type(self) -> str: """返回提示类型键。""" return "few_shot"
[docs] def save(self, file_path: Union[Path, str]) -> None: if self.example_selector: raise ValueError("Saving an example selector is not currently supported") return super().save(file_path)
[docs]class FewShotChatMessagePromptTemplate( BaseChatPromptTemplate, _FewShotPromptTemplateMixin ): """聊天提示模板,支持少量示例。 此提示模板生成的高级结构是消息列表,包括前缀消息、示例消息和后缀消息。 该结构使得创建具有中间示例的对话成为可能,例如: 系统:您是一个乐于助人的AI助手 人类:2+2等于多少? AI:4 人类:2+3等于多少? AI:5 人类:4+4等于多少? 此提示模板可用于生成固定的示例列表,也可以根据输入动态选择示例。 示例: 带有固定示例列表的提示模板(与上述示例对话匹配): .. code-block:: python from langchain_core.prompts import ( FewShotChatMessagePromptTemplate, ChatPromptTemplate ) examples = [ {"input": "2+2", "output": "4"}, {"input": "2+3", "output": "5"}, ] example_prompt = ChatPromptTemplate.from_messages( [('human', '{input}'), ('ai', '{output}')] ) few_shot_prompt = FewShotChatMessagePromptTemplate( examples=examples, # 这是用于格式化每个单独示例的提示模板。 example_prompt=example_prompt, ) final_prompt = ChatPromptTemplate.from_messages( [ ('system', 'You are a helpful AI Assistant'), few_shot_prompt, ('human', '{input}'), ] ) final_prompt.format(input="4+4等于多少?") 带有动态选择示例的提示模板: .. code-block:: python from langchain_core.prompts import SemanticSimilarityExampleSelector from langchain_core.embeddings import OpenAIEmbeddings from langchain_core.vectorstores import Chroma examples = [ {"input": "2+2", "output": "4"}, {"input": "2+3", "output": "5"}, {"input": "2+4", "output": "6"}, # ... ] to_vectorize = [ " ".join(example.values()) for example in examples ] embeddings = OpenAIEmbeddings() vectorstore = Chroma.from_texts( to_vectorize, embeddings, metadatas=examples ) example_selector = SemanticSimilarityExampleSelector( vectorstore=vectorstore ) from langchain_core import SystemMessage from langchain_core.prompts import HumanMessagePromptTemplate from langchain_core.prompts.few_shot import FewShotChatMessagePromptTemplate few_shot_prompt = FewShotChatMessagePromptTemplate( # 将传递给示例选择器的变量。 input_variables=["input"], example_selector=example_selector, # 定义每个示例的格式。 # 在这种情况下,每个示例将变为2条消息: # 1条人类消息和1条AI消息 example_prompt=( HumanMessagePromptTemplate.from_template("{input}") + AIMessagePromptTemplate.from_template("{output}") ), ) # 定义整体提示。 final_prompt = ( SystemMessagePromptTemplate.from_template( "You are a helpful AI Assistant" ) + few_shot_prompt + HumanMessagePromptTemplate.from_template("{input}") ) # 显示提示 print(final_prompt.format_messages(input="3+3等于多少?")) # noqa: T201 # 在LLM中使用 from langchain_core.chat_models import ChatAnthropic chain = final_prompt | ChatAnthropic(model="claude-3-haiku-20240307") chain.invoke({"input": "3+3等于多少?"}) """
[docs] @classmethod def is_lc_serializable(cls) -> bool: """返回类是否可序列化。""" return False
input_variables: List[str] = Field(default_factory=list) """用于传递给示例选择器的提示模板将使用的变量名称列表。""" example_prompt: Union[BaseMessagePromptTemplate, BaseChatPromptTemplate] """每个示例的格式化类。""" class Config: """这个pydantic对象的配置。""" extra = Extra.forbid arbitrary_types_allowed = True
[docs] def format_messages(self, **kwargs: Any) -> List[BaseMessage]: """将kwargs格式化为消息列表。 参数: **kwargs:用于填充消息模板的关键字参数。 返回: 包含所有模板变量填充的格式化消息列表。 """ # Get the examples to use. examples = self._get_examples(**kwargs) examples = [ {k: e[k] for k in self.example_prompt.input_variables} for e in examples ] # Format the examples. messages = [ message for example in examples for message in self.example_prompt.format_messages(**example) ] return messages
[docs] async def aformat_messages(self, **kwargs: Any) -> List[BaseMessage]: """将kwargs格式化为消息列表。 参数: **kwargs:用于填充消息模板的关键字参数。 返回: 包含所有模板变量填充的格式化消息列表。 """ # Get the examples to use. examples = await self._aget_examples(**kwargs) examples = [ {k: e[k] for k in self.example_prompt.input_variables} for e in examples ] # Format the examples. messages = [ message for example in examples for message in await self.example_prompt.aformat_messages(**example) ] return messages
[docs] def format(self, **kwargs: Any) -> str: """使用输入生成字符串格式的提示。 使用此方法生成由聊天消息组成的提示的字符串表示形式。 适用于输入到基于字符串的完成语言模型或调试中。 参数: **kwargs:用于格式化的关键字参数。 返回: 提示的字符串表示形式。 """ messages = self.format_messages(**kwargs) return get_buffer_string(messages)
[docs] async def aformat(self, **kwargs: Any) -> str: messages = await self.aformat_messages(**kwargs) return get_buffer_string(messages)
[docs] def pretty_repr(self, html: bool = False) -> str: raise NotImplementedError()