1. Prompt基本使用
from langchain_core.prompts import PromptTemplate from langchain_core.prompts import ChatPromptTemplate
这里有两种prompt,其对应两种形式:PromptTemplate 和 ChatPromptTemplate
从某种意义来说,前者是一个通用形式,后者是在chat领域的一个特殊表达。
from langchain_core.prompts import PromptTemplate prompt_template = PromptTemplate.from_template( "Tell me a {adjective} joke about {content}." ) prompt_template.format(adjective="funny", content="chickens") # 'Tell me a funny joke about chickens.'
PromptTemplate做的操作很简单,相当于把 f'Tell me a {adjective} joke about {content}.'
从变量带入字符串中分离开了,Template都可以使用format函数转化为字符串,但是这里要注意的是,参数是变量
了并不是字典。
ChatPromptTemplate相当于在PromptTemplate做了一个对话的快捷方式,一般来说对话是这样的:
System: You are a helpful AI bot. Your name is Bob. Human: Hello, how are you doing? AI: I'm doing well, thanks! Human: What is your name?
但是ChatPromptTemplate将其分解得具体了,其有两种表达形式,一种使用列表,一种使用更具体的ChatMessagePromptTemplate,AIMessagePromptTemplate,HumanMessagePromptTemplate
# 使用列表 from langchain_core.prompts import ChatPromptTemplate chat_template = ChatPromptTemplate.from_messages( [ ("system", "You are a helpful AI bot. Your name is {name}."), ("human", "Hello, how are you doing?"), ("ai", "I'm doing well, thanks!"), ("human", "{user_input}"), ] ) # 转化为字符串 messages = chat_template.format(name="Bob", user_input="What is your name?") # 转化为列表 可以具体看看是 SystemMessage HumanMessage AIMessage 还是其他的 Message messages = chat_template.format_messages(name="Bob", user_input="What is your name?") # 使用细分的方式 from langchain_core.prompts import ChatPromptTemplate, SystemMessagePromptTemplate, AIMessagePromptTemplate, HumanMessagePromptTemplate c1 = SystemMessagePromptTemplate.from_template("You are a helpful AI bot. Your name is {name}.") c2 = HumanMessagePromptTemplate.from_template("You are a helpful AI bot. Your name is {name}.") c3 = AIMessagePromptTemplate.from_template("You are a helpful AI bot. Your name is {name}.") c4 = HumanMessagePromptTemplate.from_template("You are a helpful AI bot. Your name is {name}.") chat_template = ChatPromptTemplate.from_messages([c1, c2, c3, c4]) # 效果如上 messages = chat_template.format(name="Bob", user_input="What is your name?") messages = chat_template.format_messages(name="Bob", user_input="What is your name?")
在这里要注意的是,使用列表的话元组前面一个字符串只能是 one of 'human', 'user', 'ai', 'assistant', or 'system'.
,不然会报错。其中还有一个ChatMessagePromptTemplate
,其from_template参数中还有一个role
参数,可以自定义对话实体,不需要必须满足'human', 'user', 'ai', 'assistant', or 'system'
其中的一个。
在定义好template之后,就可以搭配模型使用chain了
from langchain_community.llms import Ollama from langchain_core.prompts import ChatPromptTemplate llm = Ollama(model='llama3', temperature=0.0) chat_template = ChatPromptTemplate.from_messages( [ ("system", "You are a helpful AI bot. Your name is {name}."), ("human", "Hello, how are you doing?"), ("ai", "I'm doing well, thanks!"), ("human", "{user_input}"), ] ) chain = chat_template | llm chain.invoke({'name': 'Bob', 'user_input': 'What is your name?'}) # "Nice to meet you! My name is Bob, and I'm here to help answer any questions or provide assistance you may need. How can I help you today?"
2. 进阶Prompt
2.1 MessagesPlaceholder
MessagesPlaceholder
: 当暂时不确定使用什么角色需要占位时
from langchain_core.prompts import ChatPromptTemplate, HumanMessagePromptTemplate, MessagesPlaceholder from langchain_core.messages import AIMessage, HumanMessage # 这里与AIMessagePromptTemplate的区别在与前者是不能使用input_variables的 human_prompt = "Summarize our conversation so far in {word_count} words." human_message_template = HumanMessagePromptTemplate.from_template(human_prompt) # 在这里使用MessagesPlaceholder进行占位 chat_prompt = ChatPromptTemplate.from_messages( [MessagesPlaceholder(variable_name="conversation"), human_message_template] ) # 在这里添加,添加参数为占位时设置的variable_name human_message = HumanMessage(content="What is the best way to learn programming?") ai_message = AIMessage( content="""1.Choose a programming language: Decide on a programming language that you want to learn. 2. Start with the basics: Familiarize yourself with the basic programming concepts such as variables, data types and control structures. 3. Practice, practice, practice: The best way to learn programming is through hands-on experience""" ) # 这里的 word_count 对应 chat_prompt 中的 input_variables chat_prompt.format_prompt( conversation=[human_message, ai_message], word_count="10" ).to_messages()
利用示例让LLM模仿输出进而获得一个更好的效果在prompt工程中很常见,但是大量的实例会造成一个问题,那就是模型的输入长度是由限制的,大量的实例可能会导致在input_variables输入时出现长度过长模型无法输入的问题。这里就需要引入selectors
2.2 selectors
selectors
:通过对示例进行选择的方式来减少示例,进而减少文本长度。要注意的是使用selectors
后并不会立刻就删除示例,示例是在FewShotPromptTemplate中被删除的。
from langchain_core.prompts import PromptTemplate examples = [ {"input": "happy", "output": "sad"}, {"input": "tall", "output": "short"}, {"input": "energetic", "output": "lethargic"}, {"input": "sunny", "output": "gloomy"}, {"input": "windy", "output": "calm"}, ] example_prompt = PromptTemplate( input_variables=["input", "output"], template="Input: {input}\nOutput: {output}", ) # 要注意的是format_prompt是不可以使用列表的,只能一个参数参数输入 example_prompt.format_prompt(**examples[0])
2.2.1 LengthBasedExampleSelector
LengthBasedExampleSelector
: 根据文本长度来选择
from langchain_core.example_selectors import LengthBasedExampleSelector from langchain_core.prompts import FewShotPromptTemplate # 定义example_selector example_selector = LengthBasedExampleSelector( examples=examples, example_prompt=example_prompt, # 这里max_length是针对 one example 的 max_length=25, # get_text_length 是用来计算 example_prompt 的长度的 # get_text_length: Callable[[str], int] = lambda x: len(re.split("\n| ", x)) ) FewShotPromptTemplate( example_selector=example_selector, example_prompt=example_prompt, prefix="Give the antonym of every input", suffix="Input: {adjective}\nOutput:", # 这里的input_variables与suffix中的adjective对应 input_variables=["adjective"], )
2.2.2 NGramOverlapExampleSelector
NGramOverlapExampleSelector
: 根据 ngram 重叠分数,根据与输入最相似的示例 NGramOverlapExampleSelector
来选择和排序示例。ngram 重叠分数是介于 0.0 和 1.0 之间的浮点数,包括 0.0(含)。ngram 重叠分数小于或等于阈值的示例被排除在外。默认情况下,阈值设置为 -1.0,因此不会排除任何示例,只会对它们重新排序。将阈值设置为 0.0 将排除与输入没有 ngram 重叠的示例。
from langchain_community.example_selector.ngram_overlap import NGramOverlapExampleSelector example_selector = NGramOverlapExampleSelector( examples=examples, example_prompt=example_prompt, # threshold 阈值默认设置为 -1.0 threshold=-1.0, # 阈值小于 0.0:选择器按 ngram 重叠分数对示例进行排序,不排除任何示例。 # 阈值大于 1.0: Selector 排除所有示例,返回一个空列表。 # 阈值等于 0.0: 选择器按 ngram 重叠分数对示例进行排序, 并排除那些与输入没有 ngram 重叠的词。 ) dynamic_prompt = FewShotPromptTemplate( # We provide an ExampleSelector instead of examples. example_selector=example_selector, example_prompt=example_prompt, prefix="Give the Spanish translation of every input", suffix="Input: {sentence}\nOutput:", input_variables=["sentence"], )
2.2.3 SemanticSimilarityExampleSelector
SemanticSimilarityExampleSelector
:此对象根据与输入的相似性选择示例。它通过查找具有与输入具有最大余弦相似度的嵌入的示例来实现此目的。
from langchain_chroma import Chroma from langchain_core.example_selectors import SemanticSimilarityExampleSelector from langchain_core.prompts import FewShotPromptTemplate from langchain_openai import OpenAIEmbeddings example_selector = SemanticSimilarityExampleSelector.from_examples( examples, # 使用 embedding 层来判断文本相似性 OpenAIEmbeddings(), # Chroma用于生成嵌入的嵌入类,用于度量语义相似度。 Chroma, # k表示要生成的示例数量 k=1, ) similar_prompt = FewShotPromptTemplate( example_selector=example_selector, example_prompt=example_prompt, prefix="Give the antonym of every input", suffix="Input: {adjective}\nOutput:", input_variables=["adjective"], )
2.2.4 MaxMarginalRelevanceExampleSelector
MaxMarginalRelevanceExampleSelector
:与输入最相似的示例组合来选择示例,同时还针对多样性进行了优化。为此,它找到具有与输入具有最大余弦相似度的嵌入的示例,然后迭代添加它们,同时惩罚它们与已选定示例的接近程度。
example_selector = MaxMarginalRelevanceExampleSelector.from_examples( examples, OpenAIEmbeddings(), # FAISS 和 Chroma 一样用于生成嵌入的嵌入类,用于度量语义相似度。 FAISS, k=2, ) mmr_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"], )