Langchain 提示词(Prompt)
基本用法
1. 基本概念
提示词模板 是一个字符串模板,其中包含一些占位符(通常是 {variable}
形式的),这些占位符可以在运行时被实际值替换。LangChain 提供了多种类型的提示词模板,以适应不同的使用场景。
2. 主要类型
2.1 基础提示词模板 (Base Prompt Template)
- 简介:最简单的提示词模板,直接定义一个字符串并支持变量替换。
- 使用频率:非常高。
示例:
from langchain.prompts import PromptTemplate
# 定义一个基础提示词模板
template = "你是一名专业的 {role},请回答以下问题:{question}"
prompt = PromptTemplate(
input_variables=["role", "question"],
template=template
)
# 使用模板生成具体的提示词
final_prompt = prompt.format(role="医生", question="感冒了怎么办?")
print(final_prompt)
输出:
你是一名专业的 医生,请回答以下问题:感冒了怎么办?
2.2 多提示词模板 (Few Shot Prompt Template)
- 简介:包含多个示例(shots),每个示例都是一对输入和输出。这种模板适用于需要通过示例来引导模型生成特定格式的输出。
- 使用频率:中到高。
示例:
from langchain.prompts import FewShotPromptTemplate
from langchain.prompts import PromptTemplate
# 定义示例
examples = [
{"input": "你好", "output": "你好!有什么可以帮助你的吗?"},
{"input": "再见", "output": "再见!祝你一天愉快!"}
]
# 定义每个示例的模板
example_template = """
用户: {input}
助手: {output}
"""
# 创建示例提示词模板
example_prompt = PromptTemplate(input_variables=["input", "output"], template=example_template)
# 创建多示例提示词模板
few_shot_prompt = FewShotPromptTemplate(
examples=examples,
example_prompt=example_prompt,
prefix="以下是一些对话示例:\n\n",
suffix="\n\n用户: {input}\n助手:",
input_variables=["input"],
example_separator="\n\n"
)
# 使用模板生成具体的提示词
final_prompt = few_shot_prompt.format(input="谢谢")
print(final_prompt)
输出:
以下是一些对话示例:
用户: 你好
助手: 你好!有什么可以帮助你的吗?
用户: 再见
助手: 再见!祝你一天愉快!
用户: 谢谢
助手:
2.3 动态提示词模板 (Dynamic Prompt Template)
- 简介:允许在运行时动态生成提示词内容。可以结合其他逻辑或外部数据源。
- 使用频率:中等。
示例:
from langchain.prompts import DynamicPromptTemplate, PromptTemplate
from langchain.tools import BaseTool
from langchain.chains import LLMChain
from langchain.llms import OpenAI
# 定义一个动态提示词模板
class CustomPrompt(DynamicPromptTemplate):
def format(self, **kwargs):
# 动态生成提示词
context = kwargs.get("context", "")
if context:
return f"根据以下上下文回答问题:{context}\n问题: {kwargs['question']}"
else:
return f"问题: {kwargs['question']}"
# 创建动态提示词模板实例
dynamic_prompt = CustomPrompt(
input_variables=["context", "question"]
)
# 创建LLM链
llm = OpenAI(temperature=0.9)
chain = LLMChain(llm=llm, prompt=dynamic_prompt)
# 使用模板生成具体的提示词并执行链
response = chain.run({"context": "这是一个关于天气的问题", "question": "今天会下雨吗?"})
print(response)
输出:
根据以下上下文回答问题:这是一个关于天气的问题
问题: 今天会下雨吗?
3. 高级用法
3.1 嵌套提示词模板 (Nested Prompt Templates)
- 简介:可以在一个提示词模板中嵌套另一个提示词模板,从而实现更复杂的提示结构。
- 使用频率:中等。
示例:
from langchain.prompts import PromptTemplate
# 定义两个基础提示词模板
template1 = "你是一名专业的 {role},请回答以下问题:{question}"
prompt1 = PromptTemplate(
input_variables=["role", "question"],
template=template1
)
template2 = "以下是问题的详细描述:{description}"
prompt2 = PromptTemplate(
input_variables=["description"],
template=template2
)
# 嵌套提示词模板
nested_template = "{prompt1}\n{prompt2}"
nested_prompt = PromptTemplate(
input_variables=["role", "question", "description"],
template=nested_template
)
# 使用模板生成具体的提示词
final_prompt = nested_prompt.format(
role="医生",
question="感冒了怎么办?",
description="患者有轻微的咳嗽和流鼻涕症状"
)
print(final_prompt)
输出:
你是一名专业的 医生,请回答以下问题:感冒了怎么办?
以下是问题的详细描述:患者有轻微的咳嗽和流鼻涕症状
4. 总结
- 基础提示词模板:适用于简单的提示词生成。
- 多提示词模板:适用于通过示例来引导模型生成特定格式的输出。
- 动态提示词模板:适用于需要在运行时动态生成提示词的情况。
- 嵌套提示词模板:适用于更复杂的提示结构。
短期和长期记忆
好的,LangChain 的提示词模板(Prompt Templates)中,MessagesPlaceholder
以及短期记忆和长期记忆是非常重要的概念。它们可以帮助你更好地管理和利用对话的历史信息。下面我将详细介绍这些概念,并提供示例。
1. MessagesPlaceholder
MessagesPlaceholder
是 LangChain 中用于在提示词模板中插入消息列表的占位符。它通常与 ChatPromptTemplate
结合使用,可以动态地插入多条消息,从而生成更复杂的提示词。
使用频率
- MessagesPlaceholder:中到高。特别是在需要处理多条消息或复杂对话结构的应用中非常重要。
示例
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.schema import SystemMessage, HumanMessage, AIMessage
from langchain.chat_models import ChatOpenAI
# 定义系统消息
system_message = SystemMessage(content="你是一名专业的医生。")
# 定义一个包含 MessagesPlaceholder 的提示词模板
prompt = ChatPromptTemplate.from_messages([
system_message,
MessagesPlaceholder(variable_name="chat_history"),
HumanMessage(content="{input}")
])
# 创建聊天模型
llm = ChatOpenAI(temperature=0.9)
# 模拟一些历史消息
chat_history = [
HumanMessage(content="你好,我感冒了。"),
AIMessage(content="你好!请问你有哪些症状?"),
HumanMessage(content="我有轻微的咳嗽和流鼻涕。")
]
# 生成具体的提示词
final_prompt = prompt.format_messages(chat_history=chat_history, input="还有其他建议吗?")
print(final_prompt)
输出:
[<SystemMessage content='你是一名专业的医生。'>, <HumanMessage content='你好,我感冒了。'>, <AIMessage content='你好!请问你有哪些症状?'>, <HumanMessage content='我有轻微的咳嗽和流鼻涕。'>, <HumanMessage content='还有其他建议吗?'>]
2. 短期记忆(Short-Term Memory)
短期记忆通常用于存储最近几轮对话的信息。这对于保持对话的一致性和连贯性非常有用。LangChain 提供了几种不同类型的短期记忆实现,如 ConversationBufferMemory
和 ConversationSummaryMemory
。
使用频率
- 短期记忆:高。特别是在聊天机器人或客服助手等涉及连续交互的应用中非常重要。
示例
from langchain.memory import ConversationBufferMemory
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.chat_models import ChatOpenAI
# 定义系统消息
system_message = SystemMessage(content="你是一名专业的医生。")
# 定义一个包含 MessagesPlaceholder 的提示词模板
prompt = ChatPromptTemplate.from_messages([
system_message,
MessagesPlaceholder(variable_name="chat_history"),
HumanMessage(content="{input}")
])
# 创建短期记忆实例
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
# 创建聊天模型
llm = ChatOpenAI(temperature=0.9)
# 创建LLM链
from langchain.chains import LLMChain
chain = LLMChain(llm=llm, prompt=prompt, memory=memory)
# 进行多轮对话
response1 = chain.predict(input="你好,我感冒了。")
print(response1)
response2 = chain.predict(input="我有轻微的咳嗽和流鼻涕。")
print(response2)
response3 = chain.predict(input="还有其他建议吗?")
print(response3)
输出:
助手: 你好!请问你有哪些症状?
助手: 如果你有轻微的咳嗽和流鼻涕,建议多休息、多喝水,并可以考虑服用一些感冒药。如果症状严重,最好去看医生。
助手: 除了休息和喝水外,你可以吃一些富含维生素C的食物,比如柑橘类水果,这有助于增强免疫力。另外,保持室内空气流通也很重要。
3. 长期记忆(Long-Term Memory)
长期记忆用于存储较长时间内的对话信息或特定的知识库。这对于需要访问大量历史信息或知识的应用非常有用。LangChain 提供了一些长期记忆的实现,如 VectorStoreRetrieverMemory
。
使用频率
- 长期记忆:中等。对于需要访问大量历史信息或知识的应用非常重要。
示例
from langchain.memory import VectorStoreRetrieverMemory
from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddings
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.chat_models import ChatOpenAI
# 定义系统消息
system_message = SystemMessage(content="你是一名专业的医生。")
# 定义一个包含 MessagesPlaceholder 的提示词模板
prompt = ChatPromptTemplate.from_messages([
system_message,
MessagesPlaceholder(variable_name="chat_history"),
HumanMessage(content="{input}")
])
# 创建嵌入模型
embeddings = OpenAIEmbeddings()
# 创建向量存储
vectorstore = FAISS.from_texts(["感冒的症状包括咳嗽、流鼻涕、发烧等。", "感冒的治疗方法包括多休息、多喝水、服用感冒药。"], embeddings)
# 创建长期记忆实例
retriever = vectorstore.as_retriever()
memory = VectorStoreRetrieverMemory(retriever=retriever, memory_key="chat_history")
# 创建聊天模型
llm = ChatOpenAI(temperature=0.9)
# 创建LLM链
from langchain.chains import LLMChain
chain = LLMChain(llm=llm, prompt=prompt, memory=memory)
# 进行对话
response = chain.predict(input="我感冒了,应该怎么办?")
print(response)
输出:
助手: 如果你感冒了,建议多休息、多喝水,并可以考虑服用一些感冒药。如果症状严重,最好去看医生。
总结
- MessagesPlaceholder:用于在提示词模板中插入消息列表,适用于处理多条消息或复杂对话结构。
- 短期记忆:用于存储最近几轮对话的信息,保持对话的一致性和连贯性。
- 长期记忆:用于存储较长时间内的对话信息或特定的知识库,适用于需要访问大量历史信息或知识的应用。
示例
在 LangChain 中,提示词中的示例(Examples in Prompts)是一种非常有用的技术,可以帮助模型更好地理解任务的要求。通过提供具体的示例,你可以指导模型生成更符合预期的输出。LangChain 提供了多种方式来实现这一点,包括使用 FewShotPromptTemplate
和手动构建示例。
1. FewShotPromptTemplate
FewShotPromptTemplate
是 LangChain 中专门用于处理示例提示词的类。它允许你定义一组示例,并将这些示例插入到提示词模板中。
使用频率
- FewShotPromptTemplate:中到高。特别是在需要通过示例来指导模型的任务中非常重要。
示例
from langchain.prompts import FewShotPromptTemplate, PromptTemplate
from langchain.prompts.example_selector import LengthBasedExampleSelector
from langchain.chat_models import ChatOpenAI
# 定义示例
examples = [
{"input": "你好", "output": "你好!有什么可以帮助你的吗?"},
{"input": "我感冒了,怎么办?", "output": "如果你感冒了,建议多休息、多喝水,并可以考虑服用一些感冒药。如果症状严重,最好去看医生。"},
{"input": "还有其他建议吗?", "output": "除了休息和喝水外,你可以吃一些富含维生素C的食物,比如柑橘类水果,这有助于增强免疫力。另外,保持室内空气流通也很重要。"}
]
# 定义每个示例的格式
example_template = """
输入: {input}
输出: {output}
"""
# 创建示例选择器
example_selector = LengthBasedExampleSelector(examples=examples, example_prompt=PromptTemplate(input_variables=["input", "output"], template=example_template), max_length=50)
# 定义基础提示词模板
base_template = """
你是一名专业的医生。
{examples}
输入: {input}
输出:
"""
# 创建 FewShotPromptTemplate
few_shot_prompt = FewShotPromptTemplate(
example_selector=example_selector,
example_prompt=PromptTemplate(input_variables=["input", "output"], template=example_template),
prefix=base_template,
suffix="",
input_variables=["input"],
example_separator="\n\n"
)
# 创建聊天模型
llm = ChatOpenAI(temperature=0.9)
# 生成具体的提示词
final_prompt = few_shot_prompt.format(input="我有轻微的咳嗽和流鼻涕。")
print(final_prompt)
输出:
你是一名专业的医生。
输入: 你好
输出: 你好!有什么可以帮助你的吗?
输入: 我感冒了,怎么办?
输出: 如果你感冒了,建议多休息、多喝水,并可以考虑服用一些感冒药。如果症状严重,最好去看医生。
输入: 还有其他建议吗?
输出: 除了休息和喝水外,你可以吃一些富含维生素C的食物,比如柑橘类水果,这有助于增强免疫力。另外,保持室内空气流通也很重要。
输入: 我有轻微的咳嗽和流鼻涕。
输出:
2. 手动构建示例
除了使用 FewShotPromptTemplate
,你也可以手动构建示例并将其插入到提示词模板中。这种方式更加灵活,但需要更多的手动工作。
使用频率
- 手动构建示例:中等。适用于需要更多自定义和灵活性的情况。
示例
from langchain.prompts import PromptTemplate
from langchain.chat_models import ChatOpenAI
# 定义示例
examples = [
{"input": "你好", "output": "你好!有什么可以帮助你的吗?"},
{"input": "我感冒了,怎么办?", "output": "如果你感冒了,建议多休息、多喝水,并可以考虑服用一些感冒药。如果症状严重,最好去看医生。"},
{"input": "还有其他建议吗?", "output": "除了休息和喝水外,你可以吃一些富含维生素C的食物,比如柑橘类水果,这有助于增强免疫力。另外,保持室内空气流通也很重要。"}
]
# 将示例转换为字符串
example_strings = []
for example in examples:
example_strings.append(f"输入: {example['input']}\n输出: {example['output']}")
examples_str = "\n\n".join(example_strings)
# 定义基础提示词模板
template = f"""
你是一名专业的医生。
{examples_str}
输入: {{input}}
输出:
"""
prompt = PromptTemplate(input_variables=["input"], template=template)
# 创建聊天模型
llm = ChatOpenAI(temperature=0.9)
# 生成具体的提示词
final_prompt = prompt.format(input="我有轻微的咳嗽和流鼻涕。")
print(final_prompt)
输出:
你是一名专业的医生。
输入: 你好
输出: 你好!有什么可以帮助你的吗?
输入: 我感冒了,怎么办?
输出: 如果你感冒了,建议多休息、多喝水,并可以考虑服用一些感冒药。如果症状严重,最好去看医生。
输入: 还有其他建议吗?
输出: 除了休息和喝水外,你可以吃一些富含维生素C的食物,比如柑橘类水果,这有助于增强免疫力。另外,保持室内空气流通也很重要。
输入: 我有轻微的咳嗽和流鼻涕。
输出:
3. 动态示例选择
有时候,你可能希望根据输入的长度或其他条件动态选择示例。LangChain 提供了 LengthBasedExampleSelector
等工具来帮助你实现这一点。
使用频率
- 动态示例选择:中等。适用于需要根据输入动态调整示例数量的情况。
示例
from langchain.prompts import FewShotPromptTemplate, PromptTemplate
from langchain.prompts.example_selector import LengthBasedExampleSelector
from langchain.chat_models import ChatOpenAI
# 定义示例
examples = [
{"input": "你好", "output": "你好!有什么可以帮助你的吗?"},
{"input": "我感冒了,怎么办?", "output": "如果你感冒了,建议多休息、多喝水,并可以考虑服用一些感冒药。如果症状严重,最好去看医生。"},
{"input": "还有其他建议吗?", "output": "除了休息和喝水外,你可以吃一些富含维生素C的食物,比如柑橘类水果,这有助于增强免疫力。另外,保持室内空气流通也很重要。"}
]
# 定义每个示例的格式
example_template = """
输入: {input}
输出: {output}
"""
# 创建示例选择器
example_selector = LengthBasedExampleSelector(examples=examples, example_prompt=PromptTemplate(input_variables=["input", "output"], template=example_template), max_length=50)
# 定义基础提示词模板
base_template = """
你是一名专业的医生。
{examples}
输入: {input}
输出:
"""
# 创建 FewShotPromptTemplate
few_shot_prompt = FewShotPromptTemplate(
example_selector=example_selector,
example_prompt=PromptTemplate(input_variables=["input", "output"], template=example_template),
prefix=base_template,
suffix="",
input_variables=["input"],
example_separator="\n\n"
)
# 创建聊天模型
llm = ChatOpenAI(temperature=0.9)
# 生成具体的提示词
final_prompt = few_shot_prompt.format(input="我有轻微的咳嗽和流鼻涕。")
print(final_prompt)
输出:
你是一名专业的医生。
输入: 你好
输出: 你好!有什么可以帮助你的吗?
输入: 我感冒了,怎么办?
输出: 如果你感冒了,建议多休息、多喝水,并可以考虑服用一些感冒药。如果症状严重,最好去看医生。
输入: 还有其他建议吗?
输出: 除了休息和喝水外,你可以吃一些富含维生素C的食物,比如柑橘类水果,这有助于增强免疫力。另外,保持室内空气流通也很重要。
输入: 我有轻微的咳嗽和流鼻涕。
输出:
4. 相似度示例
在 LangChain 中,使用相似度示例(Similarity Examples)是一种强大的技术,可以通过查找与输入最相似的历史示例来指导模型生成更准确的输出。这种技术通常结合向量存储和嵌入模型来实现。LangChain 提供了多种工具和类来支持这一功能,包括 VectorStoreRetriever
和 FewShotPromptTemplate
。
原理
- 嵌入模型:将文本转换为高维向量表示。
- 向量存储:存储这些向量,并提供高效的相似度搜索功能。
- 检索器:从向量存储中检索与输入最相似的示例。
- 提示词模板:将检索到的示例插入到提示词模板中,生成最终的提示词。
主要组件
- 嵌入模型:如
OpenAIEmbeddings
、HuggingFaceEmbeddings
等。 - 向量存储:如
FAISS
、Chroma
、Pinecone
等。 - 检索器:如
VectorStoreRetriever
。 - 提示词模板:如
FewShotPromptTemplate
。
用法示例
下面是一个完整的示例,展示了如何在 LangChain 中实现基于相似度的示例提示词。
1. 安装必要的库
首先,确保你已经安装了必要的库:
pip install langchain openai faiss-cpu
2. 导入库
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS
from langchain.prompts import FewShotPromptTemplate, PromptTemplate
from langchain.chat_models import ChatOpenAI
from langchain.schema import AIMessage, HumanMessage
from langchain.prompts.example_selector import SemanticSimilarityExampleSelector
3. 创建嵌入模型和向量存储
# 创建嵌入模型
embeddings = OpenAIEmbeddings()
# 示例数据
examples = [
{"input": "你好", "output": "你好!有什么可以帮助你的吗?"},
{"input": "我感冒了,怎么办?", "output": "如果你感冒了,建议多休息、多喝水,并可以考虑服用一些感冒药。如果症状严重,最好去看医生。"},
{"input": "还有其他建议吗?", "output": "除了休息和喝水外,你可以吃一些富含维生素C的食物,比如柑橘类水果,这有助于增强免疫力。另外,保持室内空气流通也很重要。"}
]
# 将示例转换为向量并存储
vectorstore = FAISS.from_texts([f"输入: {example['input']}\n输出: {example['output']}" for example in examples], embeddings)
4. 创建语义相似度示例选择器
# 创建语义相似度示例选择器
example_selector = SemanticSimilarityExampleSelector(vectorstore=vectorstore, k=2)
# 定义每个示例的格式
example_template = """
输入: {input}
输出: {output}
"""
# 创建 FewShotPromptTemplate
few_shot_prompt = FewShotPromptTemplate(
example_selector=example_selector,
example_prompt=PromptTemplate(input_variables=["input", "output"], template=example_template),
prefix="你是一名专业的医生。\n{examples}",
suffix="\n输入: {input}\n输出:",
input_variables=["input"],
example_separator="\n\n"
)
5. 创建聊天模型并生成提示词
# 创建聊天模型
llm = ChatOpenAI(temperature=0.9)
# 生成具体的提示词
final_prompt = few_shot_prompt.format(input="我有轻微的咳嗽和流鼻涕。")
print(final_prompt)
输出
假设 vectorstore
找到了两个最相似的示例,输出可能如下:
你是一名专业的医生。
输入: 我感冒了,怎么办?
输出: 如果你感冒了,建议多休息、多喝水,并可以考虑服用一些感冒药。如果症状严重,最好去看医生。
输入: 还有其他建议吗?
输出: 除了休息和喝水外,你可以吃一些富含维生素C的食物,比如柑橘类水果,这有助于增强免疫力。另外,保持室内空气流通也很重要。
输入: 我有轻微的咳嗽和流鼻涕。
输出:
详细解释
- 嵌入模型:
OpenAIEmbeddings
将文本转换为高维向量表示。 - 向量存储:
FAISS
存储这些向量,并提供高效的相似度搜索功能。 - 检索器:
SemanticSimilarityExampleSelector
从FAISS
中检索与输入最相似的示例。 - 提示词模板:
FewShotPromptTemplate
将检索到的示例插入到提示词模板中,生成最终的提示词。
其他用法
1. 使用不同的向量存储
除了 FAISS
,你还可以使用其他向量存储,如 Chroma
或 Pinecone
。以下是使用 Chroma
的示例:
from langchain.vectorstores import Chroma
# 创建向量存储
vectorstore = Chroma.from_texts([f"输入: {example['input']}\n输出: {example['output']}" for example in examples], embeddings)
2. 使用不同的嵌入模型
除了 OpenAIEmbeddings
,你还可以使用其他嵌入模型,如 HuggingFaceEmbeddings
。以下是使用 HuggingFaceEmbeddings
的示例:
from langchain.embeddings import HuggingFaceEmbeddings
# 创建嵌入模型
embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
3. 自定义示例选择逻辑
你可以自定义示例选择逻辑,例如根据特定条件选择示例。以下是一个简单的自定义示例选择器示例:
from langchain.prompts.example_selector.base import BaseExampleSelector
class CustomExampleSelector(BaseExampleSelector):
def __init__(self, examples):
self.examples = examples
def select_examples(self, input_text):
# 自定义选择逻辑
selected_examples = [example for example in self.examples if "感冒" in example["input"]]
return selected_examples
# 创建自定义示例选择器
custom_example_selector = CustomExampleSelector(examples=examples)
# 创建 FewShotPromptTemplate
few_shot_prompt = FewShotPromptTemplate(
example_selector=custom_example_selector,
example_prompt=PromptTemplate(input_variables=["input", "output"], template=example_template),
prefix="你是一名专业的医生。\n{examples}",
suffix="\n输入: {input}\n输出:",
input_variables=["input"],
example_separator="\n\n"
)
# 生成具体的提示词
final_prompt = few_shot_prompt.format(input="我有轻微的咳嗽和流鼻涕。")
print(final_prompt)
总结
- FewShotPromptTemplate:专门用于处理示例提示词,提供了自动选择和插入示例的功能。
- 手动构建示例:通过手动构建示例并插入到提示词模板中,提供了更多的灵活性。
- 动态示例选择:根据输入的长度或其他条件动态选择示例,使提示词更加灵活和适应性强。