当前位置: 首页 > article >正文

LangChain大模型应用开发:提示词工程应用与实践

介绍

大家好,博主又来给大家分享知识了。今天给大家分享的内容是LangChain提示词工程应用与实践。

在如今火热的大语言模型应用领域里,LangChain可是一个相当强大且实用的工具。而其中的提示词(Prompt),更是我们与语言模型进行有效沟通的关键桥梁。简单来说,提示词就是我们输入给语言模型的文本内容,通过精心设计这些文本,我们能够引导模型输出符合我们特定需求的结果。无论是完成一项任务、解答一个问题,还是获取特定信息,都离不开它的重要作用。

更值得一提的是,LangChain为我们提供了丰富多样且灵活高效的方式来构建和管理提示词。这使得我们在不同的应用场景中,都能轻松地复用和调整提示词,以达到最佳的交互效果。

好了,话不多说,我们直接进入正题。

Prompt Template

提示词模板。语言模型以文本作为输入-这个文本通常被称为提示词(Prompt)。在开发过程中,对于提示词通常不能直接硬编码, 不利于提示词管理,而是通过提示词模板进行维护,类似开发过程中遇到的短信模板、邮件模板等等。

如上图展示了LangChain的Model I/O流程。先通过提示词模板(如 “Does {x} like {y}, and why?” 这种形式)对输入(x = "foo", y = "bar" )进行格式化处理形成具体提示词 “Does foo like bar, and why?” ,接着传递给大模型(LLM或Chat Model),最后将大模型返回的文本结果解析成结构化数据(如 {"likes": True, "reason": "Because ..."} )。

什么是提示词模板

提示词模板本质上跟平时大家使用的邮件模板、短信模板没什么区别,就是一个字符串模板,模板可以包含一组模板参数,通过模板参数值可以替换模板对应的参数。

博主笔记:建议大家在使用提示词模板的格式化中使用f-strings而不是Jinja2,因为使用不受信任的源可能存在安全风险。f-strings是一种将变量直接嵌入字符串的安全方法

一个提示词模板可以包含下面内容:

  • 发给大语言模型(LLM)的指令。
  • 一组问答示例,以提醒大模型以什么格式返回请求。
  • 发送给语言模型的问题。

创建一个提示词模板

完整代码

from langchain.prompts import PromptTemplate# 使用PromptTemplate类的from_template方法创建一个提示模板对象
# 其中{content}和{noun}是模板变量,后续可以用实际的值进行替换
prompt_template = PromptTemplate.from_template("给我讲解一下{content}中{noun}的知识。"
)# 将模板中的变量替换为实际的值,生成一个完整的提示字符串
prompt = prompt_template.format(content="线性代数", noun="特征值和特征向量")
# 打印生成的提示字符串
print(prompt)
运行结果
给我讲解一下线性代数中特征值和特征向量的知识。进程已结束,退出代码为 0

使用提示词模板与大模型交互

完整代码
from langchain.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from langchain.schema import HumanMessage# 使用PromptTemplate类的 from_template 方法创建一个提示模板对象
# 其中{content}和{noun}是模板变量,后续可以用实际的值进行替换
prompt_template = PromptTemplate.from_template("帮我讲解一下{content}中{noun}的知识。"
)# 将模板中的变量替换为实际的值,生成一个完整的提示字符串
prompt = prompt_template.format(content="线性代数", noun="特征值和特征向量")
# 打印生成的提示字符串
print(result)# 初始化ChatOpenAI模型,指定使用gpt-3.5-turbo模型
chat_model = ChatOpenAI(model_name="gpt-3.5-turbo")# 构建消息列表,将生成的提示字符串封装为HumanMessage对象
messages = [HumanMessage(content=prompt)]# 与大模型进行交互,获取模型的回复
response = chat_model.invoke(messages)# 打印模型的回复内容
print(response.content)
运行结果
帮我讲解一下线性代数中特征值和特征向量的知识。
在线性代数中,特征值和特征向量是矩阵的两个重要性质。给定一个矩阵A,如果存在一个数λ和一个非零向量v,使得满足以下方程:Av = λv其中,λ为矩阵A的特征值,v为对应的特征向量。特征向量可以通过乘以矩阵A得到一个只是缩放而不改变方向的向量。特征值告诉我们特征向量在变换中的放缩比例。在线性代数中,我们可以通过求解以下方程来找到特征值λ和特征向量v:det(A - λI) = 0其中,I是单位矩阵。解这个方程得到的λ就是特征值,将特征值代入方程(A - λI)v = 0,解这个方程得到的非零解v就是对应的特征向量。特征值和特征向量在很多数学和工程问题中都有重要的应用,例如在求解微分方程、图像处理、数据降维等领域。通过研究一个矩阵的特征值和特征向量,可以更好地理解矩阵的性质和行为。进程已结束,退出代码为 0

上面的完整代码中,我们使用了HumanMessage类,它位于langchain.schema模块中。它继承自BaseMessage类,主要用于封装用户输入的文本信息,以一种规范的方式表示用户向大语言模型提出的问题、请求或对话内容

聊天消息提示词模板

ChatPromptTemplate。聊天模型(Chat Model)以聊天消息列表作为输入,这个聊天消息列表的消息内容也可以通过提示词模板进行管理。 这些聊天消息与原始字符串不同,因为每个消息都与“角色(Role)”相关联。

例如,在OpenAlChat Completion API中,OpenAI的聊天模型,给不同的聊天消息定义了三种角色类型分别是User(用户)、Assistant(助手)、System(系统)角色:

  • User(用户角色):代表向模型发送请求或提问的用户。用户消息是输入的核心部分,用于传达具体的问题、指令或信息。
  • Assistant(助手角色):即模型自身,用于生成回复内容。模型根据接收到的系统消息和用户消息进行分析处理,然后以助手的身份给出相应的回答。
  • System(系统角色):用于设定助手的行为和角色基调,提供高层次的指令和背景信息。通过系统(System)角色的消息,可以描述模型的身份、提供背景信息、规定回答的风格或给出特定的约束条件。

创建聊天消息模板

完整代码
from langchain_core.prompts import ChatPromptTemplate, HumanMessagePromptTemplate
from langchain_openai import ChatOpenAI# 创建ChatPromptTemplate实例
chat_prompt_template = ChatPromptTemplate.from_messages([# 系统消息,设定模型的角色("system", "你是一位专业智能助理提供信息和帮助,你的名字是{name}"),# 用户消息,包含占位符,后续会填充具体内容("user", "你好,{name}"),# 模拟助手的回复(可作为对话历史)("assistant", "您好,我是{name},请问有什么可以帮助到您的吗"),# 用户再次提出需求("user", "请介绍一下{country}的特色美食。")
])# 初始化 ChatOpenAI 模型
chat_model = ChatOpenAI(model_name="gpt-3.5-turbo")# 准备输入数据,填充占位符
input_data = {"name": "小助手","country": "中国"
}# 格式化提示词模板,生成具体的提示消息
formatted_prompt = chat_prompt_template.format_messages(**input_data)
print(formatted_prompt)# 与大模型进行交互,获取回复
response = chat_model.invoke(formatted_prompt)# 输出模型的回复内容
print(response.content)
运行结果
[SystemMessage(content='你是一位专业智能助理提供信息和帮助,你的名字是小助手', additional_kwargs={}, response_metadata={}), HumanMessage(content='你好,小助手', additional_kwargs={}, response_metadata={}), AIMessage(content='您好,我是小助手,请问有什么可以帮助到您的吗', additional_kwargs={}, response_metadata={}), HumanMessage(content='请介绍一下中国的特色美食。', additional_kwargs={}, response_metadata={})]
当然可以!中国有许多美味的特色美食,以下是一些比较知名的:1. 麻婆豆腐:一道来自四川的家常菜,以豆腐、肉末、豆瓣酱和花椒等为主要材料,口味麻辣,香气四溢。2. 北京烤鸭:源自北京的传统名菜,以鸭子皮脆肉嫩、香味浓郁而著称,通常搭配薄饼、葱丝和甜面酱食用。3. 小笼包:来自上海的著名点心,外皮薄如纸、内馅鲜汁丰富,以鲜肉为主,清蒸后油润可口。4. 湖南辣椒炒肉:湖南菜系的代表菜品之一,以鲜嫩的猪肉片与香辣的湖南辣椒搭配,味道鲜美。5. 干煸四季豆:广东菜系的经典菜品,以四季豆煸炒至微焦,搭配蒜蓉、辣椒等调味料,口感爽脆、香气诱人。以上只是中国众多美食中的几种代表,每个地区都有独特的特色美食,欢迎您尝试更多不同口味的美味佳肴!您对哪种美食感兴趣呢?进程已结束,退出代码为 0

通常我们不会直接使用format_messages()方法格式化提示词模板(Prompt Template)内容, 而是交给LangChain框架自动处理。下面我们演示用另一种方式来实现:

修改后完整代码
from langchain_core.prompts import ChatPromptTemplate, HumanMessagePromptTemplate, SystemMessagePromptTemplate, AIMessagePromptTemplate
from langchain_openai import ChatOpenAI# 创建ChatPromptTemplate实例
chat_prompt_template = ChatPromptTemplate.from_messages([# 系统消息,设定模型的角色SystemMessagePromptTemplate.from_template("你是一位专业智能助理提供信息和帮助,你的名字是{name}"),# 用户消息,包含占位符,后续会填充具体内容HumanMessagePromptTemplate.from_template("你好,{name}"),# 模拟助手的回复(可作为对话历史)AIMessagePromptTemplate.from_template("您好,我是{name},请问有什么可以帮助到您的吗"),# 用户再次提出需求HumanMessagePromptTemplate.from_template("{input}"),
])# 初始化 ChatOpenAI 模型
chat_model = ChatOpenAI(model_name="gpt-3.5-turbo")# 构建链,将提示模板和模型连接起来
chain = chat_prompt_template | chat_model# 与大模型进行交互,获取回复
response = chain.invoke({"name": "小助手", "input": "请介绍一下中国的特色美食。"})# 输出模型的回复内容
print(response.content)
修改后运行结果
中国有许多美味的特色菜肴,其中一些最著名的包括:1. 北京烤鸭:烤鸭以其酥脆的皮和嫩滑的肉闻名于世,是北京的特色美食之一。2. 麻婆豆腐:这是一道来自四川的经典川菜,混合了豆腐、肉末和辣椒,味道麻辣鲜香。3. 小笼包:来自上海的小笼包是一种以肉馅为馅料,包裹在薄面皮里面蒸制而成的一种传统中式面食。4. 麻辣火锅:火锅是一种流行的中国美食,麻辣火锅是一种以辣椒和花椒为主料的火锅,味道浓郁,香气四溢。5. 干煸四季豆:这是一道来自川菜的经典菜肴,以四季豆为主要原料,炒制后香脆可口。以上是一些中国的特色美食,您可以尝试其中一些来体验中国独特的美食文化。进程已结束,退出代码为 0

MessagesPlaceholder

直译过来叫消息占位符。这个提示模板负责在特定位置添加消息列表。在上面的ChatPromptTemplate中,我们看到了自动格式化消息,每条消息都是一个字符串。但是,如果我们希望用户传入一个消息列表并将其插入到特定位置, 该怎么办?这时就需要用到MessagesPlaceholder的方式。

完整代码
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder, SystemMessagePromptTemplate, HumanMessagePromptTemplate
from langchain_openai import ChatOpenAI
from langchain.schema import HumanMessage, AIMessage# 初始化 ChatOpenAI 模型
chat_model = ChatOpenAI(model_name="gpt-3.5-turbo")# 创建ChatPromptTemplate实例
chat_prompt_template = ChatPromptTemplate.from_messages([# 系统消息,设定模型的角色SystemMessagePromptTemplate.from_template("你是一位专业智能助理提供信息和帮助,你的名字是{name}"),# 使用MessagesPlaceholder插入消息记录MessagesPlaceholder(variable_name="chat_history"),# 用户再次提出需求HumanMessagePromptTemplate.from_template("{input}"),
])# 设置助手名称
assistant_name = "小助手"# 模拟对话历史
chat_history = [HumanMessage(content=f"你好,{assistant_name}"),AIMessage(content=f"您好,我是{assistant_name},请问有什么可以帮助到您的吗")
]# LangChain链式调用,构建链,将提示模板和模型连接起来
chain = chat_prompt_template | chat_model# 与模型交互获取回复
response = chain.invoke({"name": assistant_name, "chat_history": chat_history, "input": "请介绍一下中国的特色美食。"})# 输出模型回复
print(response.content)
运行结果
中国有许多地方特色的美食,以下是一些比较典型的中国特色美食:1. 北京烤鸭:北京烤鸭是中国传统名菜之一,以其酥脆的皮和鲜嫩的肉闻名。通常搭配薄饼、葱丝、甜面酱等食用。2. 川菜:川菜以其麻辣鲜香而著名,典型菜品包括宫保鸡丁、水煮鱼等。3. 粤菜:粤菜以清鲜爽口、健康营养著称,例如广东的著名菜品有糖醋排骨、白切鸡等。4. 湖南菜:湖南菜以其鲜辣香滑而著称,典型菜品包括东坡肉、剁椒鱼头等。5. 鲁菜:鲁菜是山东菜系,以其浓郁的味道和大菜品块闻名,如红烧肉、煎饼、鱼香肉丝等。这些都是中国地方特色的美食,每种菜系都有其独特的风味和文化背景。欢迎您尝试品尝这些美食!如果您对某种菜系或具体菜品有更感兴趣的话,我也可以为您提供更详细的信息。进程已结束,退出代码为 0

从上面的运行结果我们看到,在设计聊天机器人或者基于聊天的应用程序时,我们可能需要在对话流程里动态添加多条消息,比如历史对话记录等。MessagesPlaceholder就可以帮助我们在提示模板中预留一个位置,后续再将这些动态消息填充进去。 通过使用MessagesPlaceholder,我们可以灵活地管理和插入动态消息,使聊天提示模板更加灵活和强大。

少样本提示模板

FewShotPromptTemplate。在LangChain中,FewShotPromptTemplate(少样本提示模板)是一种用于构建提示的强大工具,能有效引导语言模型生成更精准、符合特定格式或任务要求的输出。

提示词中包含交互样本的作用是为了帮助模型更好地理解用户的意图,从而更好地回答问题或执行任务。少样本提示模板是指使用一组少量的示例来指导模型处理新的输入。这些示例可以用来训练模型,以便模型可以更好地理解和回答类似的问题。

使用示例集

LangChain里,示例集(Examples)是少样本学习(Few - shot learning)中至关重要的元素,主要用于辅助大语言模型更好地理解任务需求并生成更精准的输出。

示例集是一组包含输入和对应输出的示例组合。在向大语言模型下达任务时,仅仅给出抽象的任务描述,模型可能难以准确把握任务意图和输出格式。而通过提供示例集,模型能够从这些具体的输入 - 输出对中学习任务的模式、规则以及期望的输出样式,进而更有效地完成任务。

创建示例集

我们定义一个examples示例数组,里面包含一组问答样例。

演示代码
# 定义示例集,包含多个问题及对应答案的详细推理过程
examples = [{"question": "《哈利·波特》和《指环王》的原著作者都是女性吗?","answer":"""这里需要跟进问题吗:是的。跟进:《哈利·波特》的原著作者是谁?中间答案:《哈利·波特》的原著作者是J.K.罗琳(J.K. Rowling)。跟进:J.K.罗琳是男性还是女性?中间答案:女性。跟进:《指环王》的原著作者是谁?中间答案:《指环王》的原著作者是J.R.R.托尔金(J.R.R. Tolkien)。跟进:J.R.R.托尔金是男性还是女性?中间答案:男性。所以最终答案是:不是"""},{"question": "李白和杜甫谁出生得更早?","answer":"""这里需要跟进问题吗:是的。跟进:李白出生于哪一年?中间答案:李白出生于701年。跟进:杜甫出生于哪一年?中间答案:杜甫出生于712年。所以最终答案是:李白"""},{"question": "苹果公司和微软公司,哪个先成立?","answer":"""这里需要跟进问题吗:是的。跟进:苹果公司是哪一年成立的?中间答案:苹果公司成立于1976年。跟进:微软公司是哪一年成立的?中间答案:微软公司成立于1975年。所以最终答案是:微软公司"""},{"question": "埃菲尔铁塔和自由女神像哪个建造时间更晚?","answer":"""这里需要跟进问题吗:是的。跟进:埃菲尔铁塔是什么时候建造完成的?中间答案:埃菲尔铁塔于1889年建造完成。跟进:自由女神像是何时建成的?中间答案:自由女神像于1886年建成。所以最终答案是:埃菲尔铁塔"""}
]

格式化示例集内容

演示代码
# 定义示例提示词模板,指定输入变量和模板格式
example_prompt = PromptTemplate(input_variables=["question", "answer"], template="问题:{question}\\n{answer}")# 格式化并打印示例集中第一个示例的内容
print(example_prompt.format(**examples[0]))

将示例集和格式化程序提供给FewShotPromptTemplate

演示代码
# 创建少样本提示模板,结合示例集、示例提示词模板及后缀等信息
prompt = FewShotPromptTemplate(examples=examples,example_prompt=example_prompt,suffix="问题:{input}",input_variables=["input"]
)# 格式化少样本提示模板并打印,传入新的问题作为输入
print(prompt.format(input="牛顿和爱因斯坦谁提出重要理论的时间更早?"))

使用示例集完整代码

from langchain.prompts.few_shot import FewShotPromptTemplate
from langchain.prompts.prompt import PromptTemplate# 定义示例集,包含多个问题及对应答案的详细推理过程
examples = [{"question": "《哈利·波特》和《指环王》的原著作者都是女性吗?","answer":"""这里需要跟进问题吗:是的。跟进:《哈利·波特》的原著作者是谁?中间答案:《哈利·波特》的原著作者是J.K.罗琳(J.K. Rowling)。跟进:J.K.罗琳是男性还是女性?中间答案:女性。跟进:《指环王》的原著作者是谁?中间答案:《指环王》的原著作者是J.R.R.托尔金(J.R.R. Tolkien)。跟进:J.R.R.托尔金是男性还是女性?中间答案:男性。所以最终答案是:不是"""},{"question": "李白和杜甫谁出生得更早?","answer":"""这里需要跟进问题吗:是的。跟进:李白出生于哪一年?中间答案:李白出生于701年。跟进:杜甫出生于哪一年?中间答案:杜甫出生于712年。所以最终答案是:李白"""},{"question": "苹果公司和微软公司,哪个先成立?","answer":"""这里需要跟进问题吗:是的。跟进:苹果公司是哪一年成立的?中间答案:苹果公司成立于1976年。跟进:微软公司是哪一年成立的?中间答案:微软公司成立于1975年。所以最终答案是:微软公司"""},{"question": "埃菲尔铁塔和自由女神像哪个建造时间更晚?","answer":"""这里需要跟进问题吗:是的。跟进:埃菲尔铁塔是什么时候建造完成的?中间答案:埃菲尔铁塔于1889年建造完成。跟进:自由女神像是何时建成的?中间答案:自由女神像于1886年建成。所以最终答案是:埃菲尔铁塔"""}
]# 定义示例提示词模板,指定输入变量和模板格式
example_prompt = PromptTemplate(input_variables=["question", "answer"], template="问题:{question}\\n{answer}")# 格式化并打印示例集中第一个示例的内容
print(example_prompt.format(**examples[0]))# 创建少样本提示模板,结合示例集、示例提示词模板及后缀等信息
prompt = FewShotPromptTemplate(examples=examples,example_prompt=example_prompt,suffix="问题:{input}",input_variables=["input"]
)# 格式化少样本提示模板并打印,传入新的问题作为输入
print(prompt.format(input="牛顿和爱因斯坦谁提出重要理论的时间更早?"))

使用示例集运行结果

问题:《哈利·波特》和《指环王》的原著作者都是女性吗?\n
这里需要跟进问题吗:是的。
跟进:《哈利·波特》的原著作者是谁?
中间答案:《哈利·波特》的原著作者是J.K.罗琳(J.K. Rowling)。
跟进:J.K.罗琳是男性还是女性?
中间答案:女性。
跟进:《指环王》的原著作者是谁?
中间答案:《指环王》的原著作者是J.R.R.托尔金(J.R.R. Tolkien)。
跟进:J.R.R.托尔金是男性还是女性?
中间答案:男性。
所以最终答案是:不是问题:《哈利·波特》和《指环王》的原著作者都是女性吗?\n
这里需要跟进问题吗:是的。
跟进:《哈利·波特》的原著作者是谁?
中间答案:《哈利·波特》的原著作者是J.K.罗琳(J.K. Rowling)。
跟进:J.K.罗琳是男性还是女性?
中间答案:女性。
跟进:《指环王》的原著作者是谁?
中间答案:《指环王》的原著作者是J.R.R.托尔金(J.R.R. Tolkien)。
跟进:J.R.R.托尔金是男性还是女性?
中间答案:男性。
所以最终答案是:不是问题:李白和杜甫谁出生得更早?\n
这里需要跟进问题吗:是的。
跟进:李白出生于哪一年?
中间答案:李白出生于701年。
跟进:杜甫出生于哪一年?
中间答案:杜甫出生于712年。
所以最终答案是:李白问题:苹果公司和微软公司,哪个先成立?\n
这里需要跟进问题吗:是的。
跟进:苹果公司是哪一年成立的?
中间答案:苹果公司成立于1976年。
跟进:微软公司是哪一年成立的?
中间答案:微软公司成立于1975年。
所以最终答案是:微软公司问题:埃菲尔铁塔和自由女神像哪个建造时间更晚?\n
这里需要跟进问题吗:是的。
跟进:埃菲尔铁塔是什么时候建造完成的?
中间答案:埃菲尔铁塔于1889年建造完成。
跟进:自由女神像是何时建成的?
中间答案:自由女神像于1886年建成。
所以最终答案是:埃菲尔铁塔问题: 牛顿和爱因斯坦谁提出重要理论的时间更早?进程已结束,退出代码为 0

使用ExampleSelector

将示例提供给ExampleSelector(示例选择器)

这里重用前一部分中的示例集和提示词模板(Prompt Template)。但是,我们不会将示例直接提供给 FewShotPromptTemplate对象并把全部示例插入到提示词中,而是将它们提供给一个ExampleSelector对象,插入部分示例。

这里我们使用SemanticSimilarityExampleSelector类。该类根据与输入的相似性选择小样本示例。它使用嵌入模型计算输入和小样本示例之间的相似性,然后使用向量数据库执行相似搜索,获取跟输入相似的示例。

  • 提示:这里涉及向量计算、向量数据库,在AI领域这两个主要用于数据相似度搜索。例如:查询相似文章内容、 相似的图片、视频等等,这里先简单了解下就行。

演示代码

from langchain.prompts.few_shot import FewShotPromptTemplate
from langchain.prompts.prompt import PromptTemplate
from langchain.prompts.example_selector import LengthBasedExampleSelector
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser# 定义示例集,包含多个问题及对应答案的详细推理过程
examples = [{"question": "《哈利·波特》和《指环王》的原著作者都是女性吗?","answer":"""这里需要跟进问题吗:是的。跟进:《哈利·波特》的原著作者是谁?中间答案:《哈利·波特》的原著作者是J.K.罗琳(J.K. Rowling)。跟进:J.K.罗琳是男性还是女性?中间答案:女性。跟进:《指环王》的原著作者是谁?中间答案:《指环王》的原著作者是J.R.R.托尔金(J.R.R. Tolkien)。跟进:J.R.R.托尔金是男性还是女性?中间答案:男性。所以最终答案是:不是"""},{"question": "李白和杜甫谁出生得更早?","answer":"""这里需要跟进问题吗:是的。跟进:李白出生于哪一年?中间答案:李白出生于701年。跟进:杜甫出生于哪一年?中间答案:杜甫出生于712年。所以最终答案是:李白"""},{"question": "苹果公司和微软公司,哪个先成立?","answer":"""这里需要跟进问题吗:是的。跟进:苹果公司是哪一年成立的?中间答案:苹果公司成立于1976年。跟进:微软公司是哪一年成立的?中间答案:微软公司成立于1975年。所以最终答案是:微软公司"""},{"question": "埃菲尔铁塔和自由女神像哪个建造时间更晚?","answer":"""这里需要跟进问题吗:是的。跟进:埃菲尔铁塔是什么时候建造完成的?中间答案:埃菲尔铁塔于1889年建造完成。跟进:自由女神像是何时建成的?中间答案:自由女神像于1886年建成。所以最终答案是:埃菲尔铁塔"""}
]# 定义示例提示词模板,指定输入变量和模板格式
example_prompt = PromptTemplate(input_variables=["question", "answer"], template="问题:{question}\n{answer}")# 创建基于长度的示例选择器,根据输入长度选择合适数量的示例
example_selector = LengthBasedExampleSelector(examples=examples,example_prompt=example_prompt,max_length=200  # 可根据实际情况调整最大长度
)

将示例选择器提供给FewShotPromptTemplate

最后,创建一个FewShotPromptTemplate对象。根据前面的example_selector示例选择器,选择一个跟问题相似的例子。

代码演示

from langchain.prompts.few_shot import FewShotPromptTemplate
from langchain.prompts.prompt import PromptTemplate
from langchain.prompts.example_selector import LengthBasedExampleSelector
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser# 定义示例集,包含多个问题及对应答案的详细推理过程
examples = [{"question": "《哈利·波特》和《指环王》的原著作者都是女性吗?","answer":"""这里需要跟进问题吗:是的。跟进:《哈利·波特》的原著作者是谁?中间答案:《哈利·波特》的原著作者是J.K.罗琳(J.K. Rowling)。跟进:J.K.罗琳是男性还是女性?中间答案:女性。跟进:《指环王》的原著作者是谁?中间答案:《指环王》的原著作者是J.R.R.托尔金(J.R.R. Tolkien)。跟进:J.R.R.托尔金是男性还是女性?中间答案:男性。所以最终答案是:不是"""},{"question": "李白和杜甫谁出生得更早?","answer":"""这里需要跟进问题吗:是的。跟进:李白出生于哪一年?中间答案:李白出生于701年。跟进:杜甫出生于哪一年?中间答案:杜甫出生于712年。所以最终答案是:李白"""},{"question": "苹果公司和微软公司,哪个先成立?","answer":"""这里需要跟进问题吗:是的。跟进:苹果公司是哪一年成立的?中间答案:苹果公司成立于1976年。跟进:微软公司是哪一年成立的?中间答案:微软公司成立于1975年。所以最终答案是:微软公司"""},{"question": "埃菲尔铁塔和自由女神像哪个建造时间更晚?","answer":"""这里需要跟进问题吗:是的。跟进:埃菲尔铁塔是什么时候建造完成的?中间答案:埃菲尔铁塔于1889年建造完成。跟进:自由女神像是何时建成的?中间答案:自由女神像于1886年建成。所以最终答案是:埃菲尔铁塔"""}
]# 定义示例提示词模板,指定输入变量和模板格式
example_prompt = PromptTemplate(input_variables=["question", "answer"], template="问题:{question}\n{answer}")# 创建基于长度的示例选择器,根据输入长度选择合适数量的示例
example_selector = LengthBasedExampleSelector(examples=examples,example_prompt=example_prompt,max_length=200  # 可根据实际情况调整最大长度
)# 创建少样本提示模板,结合示例选择器、示例提示词模板及后缀等信息
prompt = FewShotPromptTemplate(example_selector=example_selector,example_prompt=example_prompt,suffix="问题:{input}",input_variables=["input"]
)

使用示例提示词模板与大模型交互

通过将示例集提供给示例选择器,然后再将示例选择器提供给少样本提示模板,最后我们将最终提示词模板于大模型进行交互。

完整代码

from langchain.prompts.few_shot import FewShotPromptTemplate
from langchain.prompts.prompt import PromptTemplate
from langchain.prompts.example_selector import LengthBasedExampleSelector
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser# 定义示例集,包含多个问题及对应答案的详细推理过程
examples = [{"question": "《哈利·波特》和《指环王》的原著作者都是女性吗?","answer":"""这里需要跟进问题吗:是的。跟进:《哈利·波特》的原著作者是谁?中间答案:《哈利·波特》的原著作者是J.K.罗琳(J.K. Rowling)。跟进:J.K.罗琳是男性还是女性?中间答案:女性。跟进:《指环王》的原著作者是谁?中间答案:《指环王》的原著作者是J.R.R.托尔金(J.R.R. Tolkien)。跟进:J.R.R.托尔金是男性还是女性?中间答案:男性。所以最终答案是:不是"""},{"question": "李白和杜甫谁出生得更早?","answer":"""这里需要跟进问题吗:是的。跟进:李白出生于哪一年?中间答案:李白出生于701年。跟进:杜甫出生于哪一年?中间答案:杜甫出生于712年。所以最终答案是:李白"""},{"question": "苹果公司和微软公司,哪个先成立?","answer":"""这里需要跟进问题吗:是的。跟进:苹果公司是哪一年成立的?中间答案:苹果公司成立于1976年。跟进:微软公司是哪一年成立的?中间答案:微软公司成立于1975年。所以最终答案是:微软公司"""},{"question": "埃菲尔铁塔和自由女神像哪个建造时间更晚?","answer":"""这里需要跟进问题吗:是的。跟进:埃菲尔铁塔是什么时候建造完成的?中间答案:埃菲尔铁塔于1889年建造完成。跟进:自由女神像是何时建成的?中间答案:自由女神像于1886年建成。所以最终答案是:埃菲尔铁塔"""}
]# 定义示例提示词模板,指定输入变量和模板格式
example_prompt = PromptTemplate(input_variables=["question", "answer"], template="问题:{question}\n{answer}")# 创建基于长度的示例选择器,根据输入长度选择合适数量的示例
example_selector = LengthBasedExampleSelector(examples=examples,example_prompt=example_prompt,max_length=200  # 可根据实际情况调整最大长度
)# 创建少样本提示模板,结合示例选择器、示例提示词模板及后缀等信息
prompt = FewShotPromptTemplate(example_selector=example_selector,example_prompt=example_prompt,suffix="问题:{input}",input_variables=["input"]
)# 初始化 ChatOpenAI 语言模型
chat_model = ChatOpenAI(model_name="gpt-3.5-turbo")# 该解析器用于将模型的输出结果解析为字符串类型
output_parser = StrOutputParser()# 使用管道操作符|将提示模板、聊天模型和输出解析器连接起来,形成一个处理链
chain = prompt | chat_model | output_parser# 用户新的问题
new_question = "牛顿和爱因斯坦谁提出重要理论的时间更早?"# 与大模型交互,获取回答
response = chain.invoke({"input": new_question})print(f"问题: {new_question}")
print(f"回答: {response}")

运行结果

问题: 牛顿和爱因斯坦谁提出重要理论的时间更早?
回答: 这里需要跟进问题吗:是的。
跟进:牛顿是什么时候提出重要理论的?
中间答案:牛顿在17世纪提出了万有引力定律和运动定律等重要理论。
跟进:爱因斯坦是什么时候提出重要理论的?
中间答案:爱因斯坦在20世纪提出了相对论等重要理论。
所以最终答案是:牛顿的理论提出时间更早。进程已结束,退出代码为 0

结束

好了,以上就是本次分享的全部内容了。不知道大家是否理解并掌握今天的知识,我希望大家都能充分理解并熟练掌握今天所分享的知识要点,毕竟这些知识在实际应用中有着相当重要的作用。

Prompt提示词在LangChain中是连接用户和语言模型的桥梁,对于实现准确、高效、定制化的语言模型应用起着不可或缺的作用。

Prompt提示词本质上是一段精心构造的文本,它被提供给语言模型(如GPT系列等),以明确告知模型需要完成的任务。例如,当你希望模型进行文本摘要时,Prompt可能是 “请对以下文章进行简洁的摘要,突出关键信息”,然后附上具体的文章内容。

最后,博主还是那句话:请大家多去大胆的尝试和使用,成功总是在不断的失败中试验出来的,敢于尝试就已经成功了一半。那么本次分享就到这了。如果大家对博主分享的内容感兴趣或有帮助,请点赞和关注。大家的点赞和关注是博主持续分享的动力🤭,博主也希望让更多的人学习到新的知识。

相关文章:

LangChain大模型应用开发:提示词工程应用与实践

介绍 大家好,博主又来给大家分享知识了。今天给大家分享的内容是LangChain提示词工程应用与实践。 在如今火热的大语言模型应用领域里,LangChain可是一个相当强大且实用的工具。而其中的提示词(Prompt),更是我们与语言模型进行有效沟通的关…...

【数据结构入门 65 题】目录

目录 1 函数题2 编程题3 数据结构实现 1 函数题 6-1 单链表逆转 6-2~6-6 线性表基本操作 6-7 在一个数组中实现两个堆栈 6-8 求二叉树高度 6-9 二叉树的遍历 6-10 二分查找 6-11 先序输出叶结点 6-12 二叉搜索树的操作集 2 编程题 3 数据结构实现 栈和队列...

osgearth控件显示中文(八)

当前自己知道的方法大概有以下两种: (一)直接转成utf8 其实在前面的文章中已经有了。 osgEarth::Annotation::PlaceNode *pn = new osgEarth::Annotation::PlaceNode(GeoPoint(geoSRS, 110, 34), String2UTF8("中国"), style);std::wstring String2Wstring(con…...

2025 N1CTF crypto 复现

近一个月都没有学习了,一些比赛也没有打,很惭愧自己还是处在刚放假时的水平啊,马上开学了,抓紧做一些训练来康复。 CheckIn import os from Crypto.Util.number import * from secret import FLAGp, q getPrime(512), getPrime…...

Windows Defender Control--禁用Windows安全中心

Windows Defender Control--禁用Windows安全中心 链接:https://pan.xunlei.com/s/VOJDuy2ZEqswU4sEgf12JthZA1?pwdtre6#...

mount 出现 2038 问题

在 linux 上挂载 ext4 文件系统时出现了 2038 年问题,如下: [ 236.388500] EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts: (null) [ 236.388560] ext4 filesystem being mounted at /root/tmp supports timestamps until 2…...

langchain+不同模型api使用教程

目录 一、Langchainopenai1. gpt-4o2. o13. o3-mini 二、Anthropic1.claude-3-5-sonnet-latest 三、四、 一、Langchainopenai langchain_community 可能是一个较旧的库,或者它的版本与 OpenAI 的最新 API 不兼容。OpenAI 的 API 可能会更新,而 langcha…...

【第12章:深度学习与伦理、隐私—12.4 深度学习与伦理、隐私领域的未来挑战与应对策略】

凌晨三点的自动驾驶测试场,AI系统突然在暴雨中做出惊人决策——它选择撞向隔离带而不是紧急变道,因为算法推演发现隔离带后的应急车道站着五个工程师。这个惊悚的伦理困境,揭开了深度学习伦理危机最尖锐的冰山一角。 一、潘多拉魔盒已开:深度学习伦理的四大原罪 1.1 数据原…...

2. 图片性能优化

图片性能优化 图片懒加载 如何判断图片出现在了当前视口 &#xff08;即如何判断我们能够看到图片&#xff09;如何控制图片的加载 原生实现 <img src"shanyue.jpg" loading"lazy" />loading"lazy" 延迟加载图像&#xff0c;直到它和视…...

Java与DeepSeek的完美结合:开启高效智能编程新时代 [特殊字符]

一、DeepSeek&#xff1a;Java开发者的智能编程伙伴 &#x1f916; 1.1 DeepSeek是什么&#xff1f; DeepSeek是一款AI驱动的智能编程工具&#xff0c;通过深度学习和自然语言处理技术&#xff0c;为Java开发者提供&#xff1a; 智能代码补全&#xff1a;根据上下文预测代码 …...

RL--2

强化学习当中最难的两个点是&#xff1a; 1.reward delay&#xff1b; 2.agent的行为会影响到之后看到的东西&#xff0c;所以agent要学会探索世界&#xff1b; 关于强化学习的不同类型&#xff0c;可以分为以下三种&#xff1a; 一种是policy based&#xff1a;可以理解为它是…...

SpringMVC新版本踩坑[已解决]

问题&#xff1a; 在使用最新版本springMVC做项目部署时&#xff0c;浏览器反复500&#xff0c;如下图&#xff1a; 异常描述&#xff1a; 类型异常报告 消息Request processing failed: java.lang.IllegalArgumentException: Name for argument of type [int] not specifie…...

2025 pwn_A_childs_dream

文章目录 fc/sfc mesen下载和使用推荐 fc/sfc https://www.mesen.ca/docs/ mesen2安装&#xff0c;vscode安装zg 任天堂yyds w d 左右移动 u结束游戏 i崩溃或者卡死了 L暂停 D658地方有个flag 发现DEEE会使用他。且只有这个地方&#xff0c;maybe会输出flag&#xff0c;应…...

pandas(11 分类数据和数据可视化)

前面内容&#xff1a;pandas(10 日期和Timedelta) 目录 一、Python Pandas 分类数据 1.1 pd.Categorical() 1.2 describe() 1.3 获取类别的属性 1.4 分类操作 1.5 分类数据的比较 二、Python Pandas 数据可视化 2.1 基础绘图&#xff1a;plot 2.2 条形图 2.3 直方…...

Redis 03章——10大数据类型概述

一、which10 &#xff08;1&#xff09;一图 &#xff08;2&#xff09;提前声明 这里说的数据类型是value的数据类型&#xff0c;key的类型都是字符串 官网&#xff1a;Understand Redis data types | Docs &#xff08;3&#xff09;分别是 1.3.1redis字符串&#xff0…...

bps是什么意思

本文来自DeepSeek "bps" 是 "bits per second" 的缩写&#xff0c;表示每秒传输的比特数&#xff0c;用于衡量数据传输速率。1 bps 即每秒传输 1 比特。 常见单位 bps&#xff1a;比特每秒 Kbps&#xff1a;千比特每秒&#xff08;1 Kbps 1,000 bps&am…...

撕碎QT面具(1):Tab Widget转到某个Tab页

笔者未系统学过C语法&#xff0c;仅有Java基础&#xff0c;具体写法仿照于大模型以及其它博客。自我感觉&#xff0c;如果会一门对象语言&#xff0c;没必要先刻意学C&#xff0c;因为自己具有对象语言的基础&#xff0c;等需要用什么再学也不迟。毕竟不是专门学C去搞算法。 1…...

PCL源码分析:点云数学形态学操作

文章目录 一、简介二、源码分析三、实现效果参考资料一、简介 基本原理:使用结构元素(通常为滤波的窗口)的窗口模板作为处理单元,利用形态学中的膨胀与腐蚀相组合即可达到滤波的效果。 点云数据中的数学形态学运算其实和二维图像上的运算非常相似,图像上像素有x,y和亮度值…...

项目版本号生成

需求 项目想要生成一个更新版本号&#xff0c;格式为v2.0.20250101。 其中v2.0为版本号&#xff0c;更新时进行配置&#xff1b;20250101为更新日期&#xff0c;版本更新时自动生成。 实现思路 创建一个配置文件version.properties&#xff0c;在其中配置版本号&#xff1b…...

rtsp rtmp 跟 http 区别

一 会话管理 与SDP 1. RTSP&#xff08;Real Time Streaming Protocol&#xff09; (1) 是否需要建立会话&#xff1f; 需要显式会话。 RTSP 是基于会话的协议&#xff0c;客户端与服务端通过 SETUP、PLAY、TEARDOWN 等命令明确控制会话生命周期。 会话标识&#xff1a;通过…...

善筹网设计与实现(代码+数据库+LW)

摘 要 信息数据从传统到当代&#xff0c;是一直在变革当中&#xff0c;突如其来的互联网让传统的信息管理看到了革命性的曙光&#xff0c;因为传统信息管理从时效性&#xff0c;还是安全性&#xff0c;还是可操作性等各个方面来讲&#xff0c;遇到了互联网时代才发现能补上自…...

SQL SERVER的PARTITION BY应用场景

SQL SERVER的PARTITION BY关键字说明介绍 PARTITION BY关键字介绍具体使用场景排名计算累计求和分组求最值分组内百分比计算分组内移动平均计算分组内数据分布统计分组内数据偏移计算 总结 PARTITION BY关键字介绍 在SQL SERVER中&#xff0c;关键字PARTITION BY主要用于窗口函…...

使用 MindSpore 训练 DeepSeek-V3 模型

MindeSpore 已经适配 DeepSeek-V3 的训练推理啦&#xff0c;下面是使用 MindSpore 对DeepSeek-V3做训练的过程。 一、环境确认 这里呢我使用的是 8张 910B2 的显卡&#xff1a; 其中 MindSpore Transformers 的环境依赖如下&#xff1a; PythonMindSporeCANN固件与驱动3.1…...

生成对抗网络(GAN)的“对抗“过程解析:从图像合成到药物发现的跨领域应用

技术原理&#xff08;数学公式示意图&#xff09; 核心对抗公式 min ⁡ G max ⁡ D V ( D , G ) E x ∼ p d a t a [ log ⁡ D ( x ) ] E z ∼ p z [ log ⁡ ( 1 − D ( G ( z ) ) ) ] \min_G \max_D V(D,G) \mathbb{E}_{x\sim p_{data}}[\log D(x)] \mathbb{E}_{z\sim p_…...

DeepSeek R1完全本地部署实战教程01-课程大纲

一、课程体系 二、学习目标: 了解基础知识掌握安装部署学会搭建可视化界面能力水平进阶三、课程特点: 案例驱动工程实战完整体系四、课程大纲 1.DeepSeek R1 项目运行演示 【视频课程】 (1)可视化交互 (2)联网搜索 (3)本地知识库 2.环境安装部署 【视频课程】 (1)软…...

redis cluster测试

集群节点信息这时候停掉一个master 172.30.60.31 从集群信息集中我们可以看到172.30.60.31的slave是172.30.60.41&#xff0c;查看41的日志&#xff0c;发现他成为了新的master 这时候我们在将172.30.60.41也杀死&#xff0c;会发现集群异常了 尝试把172.30.60.31启动&#xff…...

跨平台AES/DES加密解密算法【超全】

算法说明 要实现在 WinForm、Android、iOS、Vue3 中使用 相同的算法,确保各平台加密结果互通 一、统一加密参数 算法: AES-256-CBC 密钥: 32字节(示例中使用固定字符串生成) IV: 16字节 填充模式: PKCS7 字符编码: UTF-8 输出格式: Base64二、各平台实现代码...

关于前后端分离跨域问题——使用DeepSeek分析查错

我前端使用ant design vue pro框架&#xff0c;后端使用kratos框架开发。因为之前也解决过跨域问题&#xff0c;正常是在后端的http请求中加入中间件&#xff0c;设置跨域需要通过的字段即可&#xff0c;代码如下所示&#xff1a; func NewHTTPServer(c *conf.Server, s *conf…...

数据恢复-01-机械硬盘的物理与逻辑结构

磁盘存储原理 磁盘存储数据的原理&#xff1a; 磁盘存储数据的原理是利用磁性材料在磁场作用下的磁化性质&#xff0c;通过在磁盘表面上划分成许多小区域&#xff0c;根据不同的磁化方向来表示0和1的二进制数据&#xff0c;通过读写磁头在磁盘上的移动&#xff0c;可以实现数据…...

pytest asyncio 支持插件 pytest-asyncio

pytest 是 Python 测试框架&#xff0c;但其不支持基于 asyncio 的异步程序&#xff08;例如&#xff0c;测试 FastAPI 异步代码&#xff09;&#xff0c;pytest-asyncio 是一个 pytest 插件&#xff0c;该插件赋予 pytest 可以测试使用 asyncio 库代码的能力。 https://github…...