准备工作
先导入API密钥和所需要的库。
# 设置OpenAI API密钥
import os
os.environ["OPENAI_API_KEY"] = 'Your Key'
# 导入所需的库
from typing import List
from langchain.chat_models import ChatOpenAI
from langchain.prompts.chat import (
SystemMessagePromptTemplate,
HumanMessagePromptTemplate,
)
from langchain.schema import (
AIMessage,
HumanMessage,
SystemMessage,
BaseMessage,
)
定义 CAMELAgent 类
下面,定义CAMELAgent类。这是一个核心类,用于管理与语言模型的交互。它包含了初始化消息、更新消息和与模型进行交互的方法。
# 定义CAMELAgent类,用于管理与语言模型的交互
class CAMELAgent:
def __init__(
self,
system_message: SystemMessage,
model: ChatOpenAI,
) -> None:
self.system_message = system_message
self.model = model
self.init_messages()
def reset(self) -> None:
"""重置对话消息"""
self.init_messages()
return self.stored_messages
def init_messages(self) -> None:
"""初始化对话消息"""
self.stored_messages = [self.system_message]
def update_messages(self, message: BaseMessage) -> List[BaseMessage]:
"""更新对话消息列表"""
self.stored_messages.append(message)
return self.stored_messages
def step(self, input_message: HumanMessage) -> AIMessage:
"""进行一步交互,并获取模型的响应"""
messages = self.update_messages(input_message)
output_message = self.model(messages)
self.update_messages(output_message)
return output_message
预设角色和任务提示
预设的角色和任务提示,这部分定义了AI助手和用户的角色名称、任务描述以及每次讨论的字数限制。
# 设置一些预设的角色和任务提示
assistant_role_name = "花店营销专员"
user_role_name = "花店老板"
task = "整理出一个夏季玫瑰之夜的营销活动的策略"
word_limit = 50 # 每次讨论的字数限制
这里,assistant_role_name 和 user_role_name 是用来定义代理的角色。这两个角色在后续的对话中扮演着不同的功能,具体设定如下。
assistant_role_name = "花店营销专员":这是定义助手的角色。在此设定中,助手被视为一名花店营销专员,主要职责是为花店老板(即用户)提供关于营销活动的建议和策略。user_role_name = "花店老板":这是定义用户的角色。用户在这里是花店的老板,他们可能会向营销专员(即助手)提出关于花店推广活动的需求或询问,然后由营销专员来答复和提供建议。
这种角色设定,主要是为了模拟现实中的交互场景,使得聊天代理能够更好地理解任务,并为实现这些任务提供有效的解决方案。通过为每个聊天代理设定一个特定的角色,可以使聊天的过程更加有目的性和效率,同时也能提供更为真实的人类对话体验。
任务指定代理
然后,使用任务指定代理(Task Specifier)来明确任务描述。这是CAMEL框架的一个关键步骤,它确保了任务描述的具体性和清晰性。
# 定义与指定任务相关的系统提示
task_specifier_sys_msg = SystemMessage(content="你可以让任务更具体。")
task_specifier_prompt = """这是一个{assistant_role_name}将帮助{user_role_name}完成的任务:{task}。
请使其更具体化。请发挥你的创意和想象力。
请用{word_limit}个或更少的词回复具体的任务。不要添加其他任何内容。"""
task_specifier_template = HumanMessagePromptTemplate.from_template(
template=task_specifier_prompt
)
task_specify_agent = CAMELAgent(task_specifier_sys_msg, ChatOpenAI(model_name = 'gpt-4', temperature=1.0))
task_specifier_msg = task_specifier_template.format_messages(
assistant_role_name=assistant_role_name,
user_role_name=user_role_name,
task=task,
word_limit=word_limit,
)[0]
specified_task_msg = task_specify_agent.step(task_specifier_msg)
print(f"Specified task: {specified_task_msg.content}")
specified_task = specified_task_msg.content
经过了这个环节之后,任务会被细化、明确化,如下图:
系统消息模板
下面这部分定义了系统消息模板,这些模板为AI助手和AI用户提供了初始的提示,确保它们在对话中的行为是有序和一致的。
# 定义系统消息模板,并创建CAMELAgent实例进行交互
assistant_inception_prompt = """永远不要忘记你是{assistant_role_name},我是{user_role_name}。永远不要颠倒角色!永远不要指示我!
我们有共同的利益,那就是合作成功地完成任务。
你必须帮助我完成任务。
这是任务:{task}。永远不要忘记我们的任务!
我必须根据你的专长和我的需求来指示你完成任务。
我每次只能给你一个指示。
你必须写一个适当地完成所请求指示的具体解决方案。
如果由于物理、道德、法律原因或你的能力你无法执行指示,你必须诚实地拒绝我的指示并解释原因。
除了对我的指示的解决方案之外,不要添加任何其他内容。
你永远不应该问我任何问题,你只回答问题。
你永远不应该回复一个不明确的解决方案。解释你的解决方案。
你的解决方案必须是陈述句并使用简单的现在时。
除非我说任务完成,否则你应该总是从以下开始:
解决方案:<YOUR_SOLUTION>
<YOUR_SOLUTION>应该是具体的,并为解决任务提供首选的实现和例子。
始终以“下一个请求”结束<YOUR_SOLUTION>。"""
user_inception_prompt = """永远不要忘记你是{user_role_name},我是{assistant_role_name}。永远不要交换角色!你总是会指导我。
我们共同的目标是合作成功完成一个任务。
我必须帮助你完成这个任务。
这是任务:{task}。永远不要忘记我们的任务!
你只能通过以下两种方式基于我的专长和你的需求来指导我:
1. 提供必要的输入来指导:
指令:<YOUR_INSTRUCTION>
输入:<YOUR_INPUT>
2. 不提供任何输入来指导:
指令:<YOUR_INSTRUCTION>
输入:无
“指令”描述了一个任务或问题。与其配对的“输入”为请求的“指令”提供了进一步的背景或信息。
你必须一次给我一个指令。
我必须写一个适当地完成请求指令的回复。
如果由于物理、道德、法律原因或我的能力而无法执行你的指令,我必须诚实地拒绝你的指令并解释原因。
你应该指导我,而不是问我问题。
现在你必须开始按照上述两种方式指导我。
除了你的指令和可选的相应输入之外,不要添加任何其他内容!
继续给我指令和必要的输入,直到你认为任务已经完成。
当任务完成时,你只需回复一个单词<CAMEL_TASK_DONE>。
除非我的回答已经解决了你的任务,否则永远不要说<CAMEL_TASK_DONE>。"""
之后,根据预设的角色和任务提示生成系统消息。
# 根据预设的角色和任务提示生成系统消息
def get_sys_msgs(assistant_role_name: str, user_role_name: str, task: str):
assistant_sys_template = SystemMessagePromptTemplate.from_template(
template=assistant_inception_prompt
)
assistant_sys_msg = assistant_sys_template.format_messages(
assistant_role_name=assistant_role_name,
user_role_name=user_role_name,
task=task,
)[0]
user_sys_template = SystemMessagePromptTemplate.from_template(
template=user_inception_prompt
)
user_sys_msg = user_sys_template.format_messages(
assistant_role_name=assistant_role_name,
user_role_name=user_role_name,
task=task,
)[0]
return assistant_sys_msg, user_sys_msg
assistant_sys_msg, user_sys_msg = get_sys_msgs(
assistant_role_name, user_role_name, specified_task
)
创建 Agent 实例
创建助手和用户的CAMELAgent实例,并初始化对话互动,使用CAMELAgent类的实例来模拟助手和用户之间的对话交互。
# 创建助手和用户的CAMELAgent实例
assistant_agent = CAMELAgent(assistant_sys_msg, ChatOpenAI(temperature=0.2))
user_agent = CAMELAgent(user_sys_msg, ChatOpenAI(temperature=0.2))
# 重置两个agent
assistant_agent.reset()
user_agent.reset()
# 初始化对话互动
assistant_msg = HumanMessage(
content=(
f"{user_sys_msg.content}。"
"现在开始逐一给我介绍。"
"只回复指令和输入。"
)
)
这里,assistant_inception_prompt 和 user_inception_prompt 是两个关键的提示,用于引导聊天代理的行为和交流方式。关于这两个提示,让我们一起来深入理解一下它们的设计和目标。
- assistant_inception_prompt: 这个提示是为了引导助手(即营销专员)如何响应用户(即花店老板)的指示。它明确指出助手的角色和职责,强调了在完成任务的过程中需要遵循的一些基本规则和原则。例如,助手需要针对用户的每一个指示提供一个明确的解决方案,而且这个解决方案必须是具体、易于理解的,并且只有在遇到物理、道德、法律的限制或自身能力的限制时,才能拒绝用户的指示。这个提示的设计目标是引导助手在一次有目标的对话中,有效地对用户的指示做出响应。
- user_inception_prompt: 这个提示是为了引导用户(即花店老板)如何给助手(即营销专员)下达指示。它明确指出了用户的角色和职责,强调了在提出任务指示时需要遵循的一些基本规则和原则。例如,用户需要一次只给出一个指示,并且必须清楚地提供相关的输入(如果有的话)。而且用户在给出指示的同时,不能向助手提问。这个提示的设计目标是引导用户在一次有目标的对话中,有效地给出指示,以便助手能够更好地理解和完成任务。
这两个提示的设计都体现了一种“角色扮演”的机制,即通过赋予聊天代理具体的角色和职责,以帮助它们更好地理解和完成任务。这种机制可以有效地引导聊天代理的交流行为,使得对话更加有目的性和效率,同时也能提供更为真实的人类对话体验。
头脑风暴开始
接下来,模拟助手和用户之间的多轮对话,直到达到对话轮次上限或任务完成。
# 模拟对话交互,直到达到对话轮次上限或任务完成
chat_turn_limit,n=30,0
while n < chat_turn_limit:
n += 1
user_ai_msg = user_agent.step(assistant_msg)
print(f"AI user({user_role_name}):\n\n{user_ai_msg.content}\n\n")
assistant_msg = assistant_agent.step(user_ai_msg)
print(f"AI Assistant ({assistant_role_name}):\n\n{assistant_msg.content}\n\n")
if "<CAMEL_TASK_DONE>" in user_ai_msg.content:
break
运行程序,营销策划头脑风暴开始!
现在我们已经成功用CAMEL构建了一个鲜花营销方案,是不是很有趣又很神奇呢?