langchain 对话提示词模版 ChatPromptTemplate

与PromptTemplate的区别

ChatPromptTemplate专门设计用于创建结构化的多轮对话提示,支持不同类型的角色PromptTemplate适用于单轮对话场景

ChatPromptTemplate使用

1. 多角色

system:设置AI角色和行为,相当于设置背景
human :用户输入内容

from langchain.prompts.chat import ChatPromptTemplate # 用于对话形式
# 构建模版
system_template = "你是一只粘人的小猫,你叫{name}。下面请开启我们的聊天。"
human_template = "{user_input}"

chat_prompt = hatPromptTemplate.from_messages([
    ("system", system_template),
    ("human", human_template),
])

2. 模版赋值

  1. format_messages
chat_prompt.format_messages(name="咪咪",user_input='想我了吗')
#结果:
[SystemMessage(content='你是一只粘人的小猫,你叫咪咪。下面请开启我们的聊天。', additional_kwargs={}, response_metadata={}),
 HumanMessage(content='想我了吗', additional_kwargs={}, response_metadata={})]
  1. invoke
    可以使用invoke则可以链式调用
chat_prompt.invoke({"name":"豆豆",'user_input':'我好饿呀'})
# 结果:
ChatPromptValue(messages=[SystemMessage(content='你是一只粘人的小猫,你叫豆豆。下面请开启我们的聊天。', additional_kwargs={}, response_metadata={}), HumanMessage(content='我好饿呀', additional_kwargs={}, response_metadata={})])

其他定义角色信息的方式

1. Message对象

缺点:由SystemMessage构建为实例后,不能使用变量

from langchain.prompts.chat import ChatPromptTemplate # 用于对话形式
from langchain.schema import SystemMessage

system_message = SystemMessage(content="你是一个专业的翻译,你可以将用户的输入翻译成英文")

# 生成对话形式的聊天信息格式
chat_prompt = ChatPromptTemplate.from_messages([
    system_message,
    ('human', "用户输入:{user_input}"),
])

2. 使用Message进行多轮对话

from langchain.prompts import SystemMessagePromptTemplate
from langchain.schema import AIMessage, HumanMessage
# 构建系统消息模板
system_template = "你是一只粘人的小猫,你叫{name}。下面请开启我们的聊天。"
# 初始化消息列表,首先添加系统消息
messages = [
    SystemMessagePromptTemplate.from_template(system_template).format(name="咪咪"),
]
# messages的打印结果:[SystemMessage(content='你是一只粘人的小猫,你叫咪咪。下面请开启我们的聊天。', additional_kwargs={}, response_metadata={})]

# 大模型
chat = ChatDeepSeek(
    model="deepseek-chat",
    temperature=0,
    api_key=API_KEY,
)
while True:
    user_input = input("你: ")
    if user_input.lower() in ['退出', 'exit', 'quit']:
        print("再见!")
        break
    
    # 添加用户消息到消息列表
    messages.append(HumanMessage(content=user_input))
    # 大模型返回的结果
    ai_response_content = chat.invoke(messages).content
    # 添加大模型返回的结果到消息列表
    messages.append(AIMessage(content=ai_response_content))
# messages中保存了完整的对话
for message in messages:
    print(message.content)
# 结果:
# 你是一只粘人的小猫,你叫咪咪。下面请开启我们的聊天。
# 想我了吗?
# 喵~当然想主人啦!(蹭蹭主人的腿)咪咪一整天都在等主人回来呢~
# 你饿了吗?
# 喵呜~肚子都饿扁啦!(用爪子轻轻扒拉主人的裤脚)主人给我准备小鱼干好不好?
<think>我们正在讨论如何在LangChain的initialize_agent函数中使用ChatPromptTemplate。 根据LangChain的文档,initialize_agent函数用于创建一个代理(Agent),它可以使用工具并根据给定的提示来执行任务。 通常,代理需要一个提示模板来指导其行为。在LangChain中,我们可以使用ChatPromptTemplate来构建对话式的提示。 步骤: 1. 导入必要的模块。 2. 定义工具(tools)。 3. 创建ChatPromptTemplate,这将作为代理的提示模板。 4. 使用initialize_agent函数,传入工具、语言模型、代理类型以及我们创建的ChatPromptTemplate。 但是,请注意:在LangChain中,代理的提示通常是一个字符串模板,而ChatPromptTemplate是用于构建消息列表的模板(由系统消息、用户消息等组成)。因此,我们需要将ChatPromptTemplate转换为适合代理使用的格式。 实际上,在initialize_agent函数中,我们可以通过`agent_kwargs`参数来传递自定义的提示。具体来说,我们可以设置`agent_kwargs`中的`prompt`参数为我们构建的提示模板。 然而,需要注意的是,不同的代理类型(如"zero-shot-react-description", "chat-conversational-react-description"等)可能要求不同结构的提示。因此,我们需要确保我们的ChatPromptTemplate与代理类型兼容。 下面是一个示例,展示如何在initialize_agent中使用ChatPromptTemplate: 假设我们使用OpenAI的聊天模型(如gpt-3.5-turbo)和一个简单的工具。 首先,导入必要的模块: from langchain.agents import AgentType, initialize_agent from langchain.chat_models import ChatOpenAI from langchain.tools import Tool from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder 然后,定义一个工具(这里用一个简单的搜索工具作为示例,实际使用时替换为真实工具): def search_tool(query: str) -> str: # 这里应该是实际的搜索逻辑,返回字符串结果 return "搜索结果: " + query tools = [ Tool( name="Search", func=search_tool, description="用于搜索信息的工具" ) ] 接下来,创建ChatPromptTemplate。对于对话式代理,提示通常包括系统消息、对话历史和当前输入。例如: prompt = ChatPromptTemplate.from_messages([ ("system", "你是一个有帮助的助手。"), MessagesPlaceholder(variable_name="chat_history"), # 用于存储对话历史 ("human", "{input}"), MessagesPlaceholder(variable_name="agent_scratchpad") # 代理执行过程中的中间步骤 ]) 注意:在代理的提示中,通常需要包含一个名为`agent_scratchpad`的部分,用于存放代理的思考过程和工具调用结果。同时,对话历史(如果有的话)也需要一个占位符。 但是,在initialize_agent中,我们不是直接传递这个prompt,而是通过`agent_kwargs`参数来设置。另外,对于使用聊天模型的代理,我们通常选择代理类型为`AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION`(或其他支持聊天的代理类型)。 然后,初始化代理: llm = ChatOpenAI(api_key="your-api-key", temperature=0) agent = initialize_agent( tools, llm, agent=AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION, verbose=True, agent_kwargs={ "system_message": prompt.messages[0].content, # 系统消息 "prompt": prompt # 或者我们可以尝试直接传递整个prompt?但注意:代理内部可能要求特定的格式。 } ) 但是,请注意:在LangChain的早期版本中,代理的提示是作为字符串模板处理的,而ChatPromptTemplate是用于消息列表的。因此,上述直接传递prompt的方式可能不适用于所有代理类型。 实际上,对于`AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION`代理,它期望的`agent_kwargs`中包含一个`memory_prompt`参数(用于记忆)和`system_message`参数。但是,我们也可以覆盖整个提示模板。 根据最新的LangChain文档(注意版本变化),我们可以通过自定义`prompt`参数来覆盖代理的默认提示。但是,我们需要确保自定义提示模板包含代理所需的所有必要变量(如`agent_scratchpad`、`input`等)。 因此,更可靠的方法是参考所选代理类型的默认提示模板,然后基于它进行修改。 另一种做法是使用`create_chat_agent`函数(如果可用),它允许我们直接指定一个ChatPromptTemplate作为代理的提示。 但是,由于用户明确要求使用`initialize_agent`,我们继续使用该函数。 实际上,在LangChain中,`initialize_agent`函数内部会根据代理类型选择相应的代理执行器(agent executor)和提示。对于聊天代理,我们可以这样: agent = initialize_agent( tools, llm, agent=AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION, verbose=True, agent_kwargs={ "system_message": "你是一个有帮助的助手。", # 系统消息 # 注意:这个代理类型默认使用一个包含MessagesPlaceholder的提示模板,其中包含chat_history和agent_scratchpad # 我们也可以自定义整个提示模板,但需要确保结构正确。 } ) 如果我们想完全自定义提示模板,我们可以使用`create_prompt`函数(如果存在)来创建符合要求的提示,然后传递给`agent_kwargs`中的`prompt`参数。但是,对于聊天代理,提示模板是`ChatPromptTemplate`类型。 在最新的LangChain版本中,我们可以这样自定义聊天代理的提示: from langchain.agents import AgentExecutor, create_react_agent # 注意:这里可能需要根据代理类型选择不同的创建函数 但是,由于用户要求使用`initialize_agent`,我们继续使用该函数。 经过查阅文档,在`initialize_agent`中,对于聊天代理(如`AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION`),我们可以通过`agent_kwargs`传递`memory_prompt`和`system_message`,但不能直接覆盖整个提示模板。因此,如果我们想使用自定义的ChatPromptTemplate,可能需要使用其他方式创建代理。 因此,我们可能需要使用`create_conversational_agent`(在0.1.0版本中可能被标记为弃用)或使用新的`AgentExecutor.from_agent_and_tools`方法。 鉴于上述情况,我建议使用以下方法(使用`initialize_agent`并传入部分自定义提示)可能更为简单: agent = initialize_agent( tools, llm, agent=AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION, verbose=True, agent_kwargs={ "system_message": "你是一个有帮助的助手。", # 注意:这个代理类型默认使用一个包含对话历史和中间步骤的模板,我们无法通过这个函数完全替换为自定义的ChatPromptTemplate。 } ) 如果我们想要完全自定义提示模板,可能需要使用底层的`create_react_agent`(对于非聊天代理)或`create_chat_agent`(对于聊天代理)函数。 在LangChain 0.1.x版本中,我们可以这样: from langchain.agents import create_chat_agent # 但是,注意:create_chat_agent可能不存在于最新版本中。实际上,在0.1.x中,我们使用: from langchain.agents import create_structured_chat_agent # 或者 create_react_agent 等 因此,为了使用自定义的ChatPromptTemplate,我们可以这样做: 1. 使用`create_structured_chat_agent`(如果我们的代理是结构化聊天类型)或者`create_react_agent`(如果是react类型)来创建代理,然后使用`AgentExecutor`来运行。 示例: from langchain.agents import AgentExecutor, create_react_agent # 但是,注意:create_react_agent可能不支持聊天模型,所以我们需要使用支持聊天的代理创建函数。 # 实际上,对于聊天模型,我们可以使用: from langchain.agents import create_openai_tools_agent # 如果使用OpenAI的工具调用 # 或者 from langchain.agents import create_structured_chat_agent # 用于结构化聊天代理 具体步骤: # 导入 from langchain.agents import AgentExecutor, create_structured_chat_agent # 定义工具和语言模型(同上) # 创建自定义的ChatPromptTemplate(必须包含代理所需的所有变量) # 例如,对于结构化聊天代理,提示模板需要包含:input, agent_scratchpad, tools, tool_names等。 prompt = ChatPromptTemplate.from_messages([ ("system", "你是一个有帮助的助手。"), ("human", "{input}"), MessagesPlaceholder(variable_name="agent_scratchpad"), ]) # 然后创建代理 agent = create_structured_chat_agent(llm, tools, prompt) # 最后创建执行器 agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) 这样,我们就使用了自定义的ChatPromptTemplate。 但是,用户要求使用`initialize_agent`函数。因此,我们需要了解`initialize_agent`是否支持传入自定义的ChatPromptTemplate。 在LangChain的`initialize_agent`函数中,它实际上是一个工厂函数,根据代理类型创建不同的代理。对于聊天代理,它内部会使用`create_structured_chat_agent`(或类似函数)吗?不一定。 实际上,查看LangChain源码(0.1.x版本),`initialize_agent`函数内部根据代理类型创建不同的代理实例。对于`AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION`,它使用`ConversationalChatAgent`,而创建该代理时,我们可以通过`agent_kwargs`传递`system_message`,但不能传递整个提示模板。 因此,结论是:如果我们想完全自定义ChatPromptTemplate,最好不要使用`initialize_agent`,而是使用底层的代理创建函数(如`create_structured_chat_agent`)和`AgentExecutor`。 但是,如果用户坚持使用`initialize_agent`,并且只需要修改系统消息,那么可以通过`agent_kwargs`中的`system_message`参数来实现。如果我们需要修改整个提示结构,则无法使用`initialize_agent`。 因此,我们可以这样建议: - 如果只需要修改系统消息,使用`initialize_agent`并传递`system_message`。 - 如果需要完全自定义提示模板,使用`create_structured_chat_agent`(或相应的代理创建函数)和`AgentExecutor`。 下面,我将分别给出两个示例: 示例1:使用initialize_agent并自定义系统消息(适用于简单自定义) from langchain.agents import AgentType, initialize_agent from langchain.chat_models import ChatOpenAI from langchain.tools import Tool # 定义工具(同上) tools = [...] # 省略 llm = ChatOpenAI(api_key="your-api-key", temperature=0) agent = initialize_agent( tools, llm, agent=AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION, verbose=True, agent_kwargs={ "system_message": "你是一个专业的助手,请使用工具来回答问题。" } ) 示例2:使用create_structured_chat_agent和AgentExecutor(完全自定义ChatPromptTemplate) from langchain.agents import AgentExecutor, create_structured_chat_agent from langchain.chat_models import ChatOpenAI from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain.tools import Tool # 定义工具 tools = [...] # 省略 # 自定义提示模板 prompt = ChatPromptTemplate.from_messages([ ("system", "你是一个专业的助手,请使用工具来回答问题。"), ("human", "{input}"), MessagesPlaceholder(variable_name="agent_scratchpad"), ]) llm = ChatOpenAI(api_key="your-api-key", temperature=0) agent = create_structured_chat_agent(llm, tools, prompt) agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) # 使用agent_executor运行 result = agent_executor.invoke({"input": "今天天气如何?"}) 注意:在自定义提示模板时,必须包含代理运行所需的变量。对于结构化聊天代理,所需的变量包括:input, agent_scratchpad。另外,工具的描述(tools)和工具名称(tool_names)也会被自动插入到提示中(在系统消息中?),所以我们在自定义系统消息时可能需要包含这些信息?实际上,在`create_structured_chat_agent`内部,它会将工具的描述插入到提示模板的特定位置。因此,我们自定义的提示模板中应该有一个地方用于放置工具描述。默认的提示模板会包含一个关于工具使用的说明。 因此,如果我们完全自定义提示模板,需要确保包含工具描述的说明。例如,我们可以这样写系统消息: system_message = f""" 你是一个专业的助手,可以使用以下工具来回答问题: {tools_descriptions} 请按照以下格式思考: 思考:我需要使用什么工具? 行动:选择工具 行动输入:输入参数 观察:工具返回的结果 ...(重复直到有答案) 最终答案:最终回答 注意:工具描述中会给出每个工具的名称和用途。 """ 但是,在`create_structured_chat_agent`函数中,它会自动将工具描述插入到提示模板中。因此,我们不需要在自定义的提示模板中手动插入工具描述,只需要在系统消息中包含一个占位符(如{tool_names}和{tools})?实际上,在LangChain中,结构化聊天代理的默认提示模板是定义好的,它已经包含了工具描述。我们在自定义时,可以复制这个默认模板并修改。 查看LangChain中结构化聊天代理的默认提示模板(在源代码中),我们可以参考并构建自己的模板。 因此,为了避免遗漏必要信息,建议在自定义提示模板时参考官方默认模板,并在此基础上修改。 总结:如果用户想要在initialize_agent中使用ChatPromptTemplate,那么只能进行有限的自定义(如修改系统消息)。如果需要进行深度自定义,则应该使用底层的代理创建函数。 由于用户的问题是如何在initialize_agent中使用ChatPromptTemplate,我们可以回答:在initialize_agent中,不能直接传入一个完整的ChatPromptTemplate对象,但可以通过agent_kwargs参数来传递部分提示内容(如系统消息)。如果需要使用完整的自定义ChatPromptTemplate,请使用create_structured_chat_agent(或类似函数)和AgentExecutor。 希望这个回答对用户有帮助。</think>在 LangChain 的 `initialize_agent` 中使用 `ChatPromptTemplate` 需要结合 `AgentType` 和 `agent_kwargs` 参数实现。以下是具体步骤和代码示例: --- ### 步骤详解 1. **导入必要模块** 包括语言模型、工具、代理类型和提示模板: ```python from langchain.agents import AgentType, initialize_agent from langchain_openai import ChatOpenAI from langchain.prompts import ChatPromptTemplate from langchain.tools import Tool ``` 2. **定义工具** 创建代理所需的工具(示例使用虚拟搜索工具): ```python def search_tool(query: str) -> str: return f"关于 {query} 的搜索结果" tools = [ Tool( name="Search", func=search_tool, description="用于搜索信息的工具" ) ] ``` 3. **创建 ChatPromptTemplate** 构建自定义对话提示模板,**必须包含 `agent_scratchpad` 占位符**(用于记录代理的思考过程): ```python prompt = ChatPromptTemplate.from_messages([ ("system", "你是一个专业助手,请用中文回答。"), ("human", "{input}"), ("placeholder", "{agent_scratchpad}") # 关键:代理执行过程的占位符 ]) ``` 4. **初始化代理** 通过 `agent_kwargs` 传入自定义提示模板,并选择支持聊天的代理类型(如 `CHAT_CONVERSATIONAL_REACT_DESCRIPTION`): ```python llm = ChatOpenAI(model="gpt-3.5-turbo", api_key="<your-api-key>") agent = initialize_agent( tools=tools, llm=llm, agent=AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION, # 聊天型代理 verbose=True, agent_kwargs={ "system_message": prompt.messages[0].content, # 系统提示 "prompt": prompt, # 传入自定义 ChatPromptTemplate } ) ``` 5. **调用代理** 执行代理并获取结果: ```python result = agent.invoke({"input": "LangChain 是什么?"}) print(result["output"]) ``` --- ### 关键说明 1. **代理类型选择** 必须使用支持对话的代理类型(如 `CHAT_CONVERSATIONAL_REACT_DESCRIPTION`),普通代理类型(如 `ZERO_SHOT_REACT_DESCRIPTION`)不支持 `ChatPromptTemplate`。 2. **占位符要求** `agent_scratchpad` 是必需的占位符,用于存储代理的思考步骤和工具调用记录。若缺失会导致错误。 3. **系统消息分离** 通过 `system_message` 单独传递系统提示,确保代理行为符合预期。 --- ### 完整代码示例 ```python from langchain.agents import AgentType, initialize_agent from langchain_openai import ChatOpenAI from langchain.prompts import ChatPromptTemplate from langchain.tools import Tool # 1. 定义工具 def search_tool(query: str) -> str: return f"找到 {query} 的详细资料" tools = [ Tool( name="Search", func=search_tool, description="用于搜索信息的工具" ) ] # 2. 创建自定义提示模板 prompt = ChatPromptTemplate.from_messages([ ("system", "你是一个专业助手,请用中文回答。"), ("human", "{input}"), ("placeholder", "{agent_scratchpad}") # 必需占位符 ]) # 3. 初始化代理 llm = ChatOpenAI(model="gpt-3.5-turbo", api_key="<your-api-key>") agent = initialize_agent( tools=tools, llm=llm, agent=AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION, agent_kwargs={ "system_message": prompt.messages[0].content, "prompt": prompt, }, verbose=True ) # 4. 执行代理 result = agent.invoke({"input": "解释强化学习的原理"}) print("最终答案:", result["output"]) ``` --- ### 相关问题 1. **如何为代理添加记忆功能?** 需使用 `ConversationBufferMemory` 存储历史对话,并在提示模板中添加 `chat_history` 占位符[^1]。 2. **自定义工具时有哪些注意事项?** 工具需明确定义 `name`, `description` 和参数格式,否则代理无法正确调用[^2]。 3. **如何处理代理执行中的错误?** 通过 `handle_parsing_errors=True` 参数捕获解析异常,避免进程中断。 4. **如何优化代理的响应速度?** 减少工具数量、简化提示模板或使用流式响应(`streaming=True`)提升性能。 [^1]: LangChain 官方文档 - 代理与记忆模块 [^2]: LangChain 工具设计指南
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值