第二章 提示工程(2)

2.3Example Selectors

如果您有大量的示例,您可能需要選擇包含在提示中的示例。ExampleSelector是負(fù)責(zé)執(zhí)行此操作的類(lèi)。

基本接口定義如下:

class BaseExampleSelector(ABC):

"""Interface for selecting examples to include in prompts."""

? ? @abstractmethod

? ? def select_examples(self, input_variables: Dict[str, str]) -> List[dict]:

"""Select which examples to use based on the inputs."""

ExampleSelector唯一需要公開(kāi)的方法是select_examples。該方法接受輸入變量,然后返回一個(gè)示例列表。如何選擇這些示例取決于每個(gè)具體實(shí)現(xiàn)。以下是一些示例。

from langchain.prompts.example_selector import LengthBasedExampleSelector

# These are a lot of examples of a pretend task of creating antonyms.

examples = [

? ? {"word": "happy", "antonym": "sad"},

? ? {"word": "tall", "antonym": "short"},

? ? {"word": "energetic", "antonym": "lethargic"},

? ? {"word": "sunny", "antonym": "gloomy"},

? ? {"word": "windy", "antonym": "calm"},

]

# Next, we specify the template to format the examples we have provided.

# We use the `PromptTemplate` class for this.

example_formatter_template = """

Word: {word}

Antonym: {antonym}\n

"""

example_prompt = PromptTemplate(

? ? input_variables=["word", "antonym"],

? ? template=example_formatter_template,

)

2.3.1根據(jù)長(zhǎng)度選擇要使用的示例

如果你有大量的示例,可以使用 ExampleSelector 來(lái)選擇一組最具信息量的示例,以幫助語(yǔ)言模型生成更好的響應(yīng)。這將幫助你生成更可能生成良好響應(yīng)的提示。

在下面的示例中,我們將使用基于輸入長(zhǎng)度選擇示例的 LengthBasedExampleSelector。當(dāng)你擔(dān)心構(gòu)建的提示會(huì)超過(guò)上下文窗口的長(zhǎng)度時(shí),這很有用。對(duì)于較長(zhǎng)的輸入,它將選擇較少的示例進(jìn)行包含,而對(duì)于較短的輸入,它將選擇更多的示例。

在這個(gè)例子中,我們將創(chuàng)建一個(gè)提示來(lái)生成單詞的反義詞。我們將使用 LengthBasedExampleSelector 來(lái)選擇示例

example_selector = LengthBasedExampleSelector(

? ? examples=examples,

? ? example_prompt=example_prompt,

? ? # 下面是格式樣例最大長(zhǎng)度.

? ? # 長(zhǎng)度是指 get_text_length 函數(shù)返回值.

? ? max_length=25,

)

# 使用`example_selector` 創(chuàng)建 `FewShotPromptTemplate`.

dynamic_prompt = FewShotPromptTemplate(

? ? # 使用 ExampleSelector 替代 examples.

? ? example_selector=example_selector,

? ? example_prompt=example_prompt,

? ? prefix="根據(jù)輸入給出中文反義詞",

? ? suffix="詞語(yǔ): {input}\n反義詞:",

? ? input_variables=["input"],

? ? example_separator="? ",

)

# 使用 `format` 方法生成提示.

print(dynamic_prompt.format(input="big"))

llm_chain=LLMChain(

? ? prompt=dynamic_prompt,

? ? llm=llm

)

llm_chain.run("高尚")

輸出:

根據(jù)輸入給出中文反義詞 Word: happyAntonym: sad Word: tallAntonym: short Word: energeticAntonym: lethargic 詞語(yǔ): big反義詞:

低俗

前面是print(dynamic_prompt.format(input="big"))的輸出結(jié)果,后面是llm_chain.run("高尚")輸出結(jié)果。

相比之下,如果我們提供一個(gè)非常長(zhǎng)的輸入,LengthBasedExampleSelector將選擇較少的示例包含在提示中。因?yàn)橐WC最大長(zhǎng)度不能超過(guò)25,就犧牲了示例數(shù)量。

long_string = "big and huge and massive and large and gigantic and tall and much bigger than everything else"

print(dynamic_prompt.format(input=long_string))

輸出:

根據(jù)輸入給出中文反義詞?

?Word: happy

Antonym: sad?

?詞語(yǔ): big and huge and massive and large and gigantic and tall and much bigger than everything else反義詞:


2.3.2 相似度

SemanticSimilarityExampleSelector根據(jù)示例與輸入的相似度選擇示例。它通過(guò)查找嵌入與輸入的余弦相似度最大的示例來(lái)實(shí)現(xiàn)此目的。

from langchain.prompts.example_selector import SemanticSimilarityExampleSelector

from langchain.vectorstores import Chroma

example_selector = SemanticSimilarityExampleSelector.from_examples(

? ? # This is the list of examples available to select from.

? ? examples,

? ? # This is the embedding class used to produce embeddings which are used to measure semantic similarity.

? ? HuggingFaceEmbeddings(),

? ? # This is the VectorStore class that is used to store the embeddings and do a similarity search over.

? ? Chroma,

? ? # This is the number of examples to produce.

? ? k=1

)

similar_prompt = FewShotPromptTemplate(

? ? # We provide an ExampleSelector instead of examples.

? ? example_selector=example_selector,

? ? example_prompt=example_prompt,

? ? prefix="Give the antonym of every input",

? ? suffix="Input: {adjective}\nOutput:",

? ? input_variables=["adjective"],

)


print(similar_prompt.format(adjective="worried"))

輸出:

Give the antonym of every input

詞語(yǔ): happy

反義詞: sad

Input: worried

Output:

給變量adjective賦值worried,屬于情緒類(lèi),根據(jù)相似度選擇器選擇了同樣是情緒類(lèi)示例:happy/sad。

print(similar_prompt.format(adjective="fat"))

輸出:

Give the antonym of every input

Word: tall

Antonym: short

Input: fat

Output:

給變量adjective賦值fat,屬于體型特征類(lèi),根據(jù)相似度選擇器選擇了同樣是體型特征類(lèi)示例:tall/short。還可以增加示例,如下:

similar_prompt.example_selector.add_example({"input": "enthusiastic", "output": "apathetic"})

還有其他選擇器,如ngram重疊。NGramOverlapExampleSelector根據(jù)ngram重疊得分選擇和排序示例,該得分表示示例與輸入的相似程度。 ngram重疊得分是一個(gè)介于0.0和1.0之間的浮點(diǎn)數(shù)。選擇器允許設(shè)置閾值得分。 ngram重疊得分小于或等于閾值的示例將被排除。默認(rèn)情況下,閾值設(shè)置為-1.0,因此不會(huì)排除任何示例,只會(huì)對(duì)它們進(jìn)行重新排序。將閾值設(shè)置為0.0將排除具有與輸入無(wú)ngram重疊的示例。具體參考官方文檔。

2.4輸出解析器

語(yǔ)言模型輸出文本。但是很多時(shí)候,你可能想要獲得比文本更結(jié)構(gòu)化的信息。這就是輸出解析器的作用。

輸出解析器是幫助結(jié)構(gòu)化語(yǔ)言模型響應(yīng)的類(lèi)。有兩種主要的方法,一個(gè)輸出解析器必須實(shí)現(xiàn):

get_format_instructions() -> str:一個(gè)方法,返回一個(gè)包含有關(guān)如何格式化語(yǔ)言模型輸出的字符串。

parse(str) -> Any:一個(gè)方法,接受一個(gè)字符串(假定為語(yǔ)言模型的響應(yīng))并將其解析為某個(gè)結(jié)構(gòu)。

然后是一個(gè)可選的:

parse_with_prompt(str) -> Any:一個(gè)方法,它接受一個(gè)字符串(假設(shè)是語(yǔ)言模型的響應(yīng))和一個(gè)提示(假設(shè)是生成這樣的響應(yīng)的提示),并將其解析為某種結(jié)構(gòu)。提示在此大多數(shù)情況下是為了提供信息以便OutputParser重新嘗試或以某種方式修復(fù)輸出。

2.4.1?逗號(hào)分隔列表輸出解析器

輸出內(nèi)容,用逗號(hào)分隔列表

from langchain.output_parsers import CommaSeparatedListOutputParser

from langchain.prompts import PromptTemplate

output_parser = CommaSeparatedListOutputParser()

format_instructions = output_parser.get_format_instructions()

prompt = PromptTemplate(

? ? template="使用中文列出7個(gè) {subject}.\n{format_instructions}",

? ? input_variables=["subject"],

? ? partial_variables={"format_instructions": format_instructions}

)

_input = prompt.format(subject="世界七大洲")

#llm.temperature=0.0

output = llm(_input)

output_parser.parse(output)

輸出:

['世界七大洲如下:\n\n非洲大陸,亞洲大陸,北美洲,南美洲,歐洲大陸,大洋洲,南極洲。']

2.4.2?PydanticOutputParser

from langchain.output_parsers import PydanticOutputParser

from pydantic import BaseModel, Field, validator

# Define your desired data structure.

class Joke(BaseModel):

? ? setup: str = Field(description="question to set up a joke")

? ? punchline: str = Field(description="answer to resolve the joke")

? ? # You can add custom validation logic easily with Pydantic.

? ? @validator('setup')

? ? def question_ends_with_question_mark(cls, field):

? ? ? ? if field[-1] != '?':

? ? ? ? ? ? raise ValueError("Badly formed question!")

? ? ? ? return field

# Set up a parser + inject instructions into the prompt template.

parser = PydanticOutputParser(pydantic_object=Joke)

prompt = PromptTemplate(

? ? template="Answer the user query.\n{format_instructions}\n{query}\n",

? ? input_variables=["query"],

? ? partial_variables={"format_instructions": parser.get_format_instructions()}

)

# And a query intented to prompt a language model to populate the data structure.

joke_query = "Tell me a joke."

_input = prompt.format_prompt(query=joke_query)

output=llm(_input.to_string())

from langchain.output_parsers import OutputFixingParser

new_parser = OutputFixingParser.from_llm(parser=parser, llm=llm)

new_parser.parse(output)

輸出:

Joke(setup="What do you call a cow that can't jump over the fence?", punchline='A dairy product!')

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容