之前我们对AI的使用方式中,大抵都可以概括为让一个AI根据用户的需求,去引导对话的生成。
那么是否可以让多个AI彼此对话,从而去根据用户的一个模糊需求,实现一个具体方案呢?
这就涉及到今天要提及的框架,CAMEL框架,让AI扮演不同角色,从而进行彼此交流,最后完成任务。
那么我们先介绍一下CAMEL这个框架,来自中东的神秘力量。
其中的重要概念为,交流式代理,可以让代理和代理进行交流
角色扮演,可以让代理扮演不同的角色,更好的和人类进行交流,这说明代理可以模仿人类行为,理解人类的意图,做出对应的反应。
启示式提示,指导代理完成任务的方式,给代理提供一系列的提示,从而更好的理解如何行动,最终去通过和代理的多轮交互,完成制定的任务。
那么我们看下这个框架的具体构成
首先是人类用户,这个很好理解,就是提供一个需求,比如为股票市场开发一个交易机器人。但是其并不知道如何实现
其次是一个任务代理,这个代理不参与操作,但是会给不同的AI助手设定角色,确定任务。比如设定一个程序员AI和一个项目经理AI,之后便是下发任务给AI,让其进行多轮对话,最终得到结果。
在整个执行链路之中,需要给出的提示分为两类,分为了Prompt Engineering,用于明确任务和分配角色 和Inception Prompting,用于互相给出提示,直到对话结束。
而在Inception Prompting之中,分为了三类提示,AI助手提示,AI用户提示,任务提示。
而针对普通任务和代码开发任务,还提供不同的提示模板,AI Society和AI Code
这里我们以AI Society为例,看下如何进行的提示
首先明确了扮演的角色,其次是告知了AI角色不要忘记,不要改变
之后是确保AI不会自己编造回答,以及明确了回答的一致性
和鼓励AI进行多轮对话
而AI 用户,则是尽可能的和AI 助手保持对称,除了角色分配。
那么从上面看出,利用一个明确的框架,我们可以保证AI的对话是多轮的,有序的。利用一套复杂但合理的交互规范,提高了AI之间的自主合作能力。
那么我们就可以看下在LangChain之中,如何利用上面的CAMEL框架
1. 首先定义对应的agent类
# 定义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 |
设定一些预设值的角色和任务提示
assistant_role_name = “花店营销专员”
user_role_name = “花店老板” task = “整理出一个夏季玫瑰之夜的营销活动的策略” word_limit = 50 # 每次讨论的字数限制 |
之后是首先让一个CAMELAgent根据用户的模糊需求生成一个具体的需求。
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 |
在此之后,我们从用户的模糊需求之中得到了详细需求
Original task prompt:整理出一个夏季玫瑰之夜营销活动的策略。
Specified task prompt:为夏季玫瑰之夜策划主题装饰,策划特价活动,制定广告推广方案,组织娱乐活动,联系合作伙伴提供赞助。
然后我们为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>。””” |
利用SystemMessagePromptTemplate进行模板的生成
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= specified_task,
)[0]
最后进行多轮交流
# 初始化对话互动
assistant_msg = HumanMessage( content=( f”{user_sys_msg.content}。” “现在开始逐一给我介绍。” “只回复指令和输入。” ) ) user_msg = HumanMessage(content=f”{assistant_sys_msg.content}”) user_msg = assistant_agent.step(user_msg) print(f”Original task prompt:\n{task}\n”) print(f”Specified task prompt:\n{specified_task}\n”) # 模拟对话交互,直到达到对话轮次上限或任务完成 chat_turn_limit, n = 30, 0 while n < chat_turn_limit: n += 1 user_ai_msg = user_agent.step(assistant_msg) user_msg = HumanMessage(content=user_ai_msg.content) print(f”AI User ({user_role_name}):\n\n{user_msg.content}\n\n”) assistant_ai_msg = assistant_agent.step(user_msg) assistant_msg = HumanMessage(content=assistant_ai_msg.content) print(f”AI Assistant ({assistant_role_name}):\n\n{assistant_msg.content}\n\n”) if “<CAMEL_TASK_DONE>” in user_msg.content: break |
最终我们得到了多轮这样的对话。
那么总结一下
我们利用了CAMEL框架
这个框架中存在三个概念,AI用户 AI助手,任务代理
在实际操作,我们分别初始化了两个操作,一个是助手角色的提示,一个是用户角色的提示,分别描述了各自角色的行为准则和任务细节。
并且在描述中利用了合理的规定来保证了对话方案的清晰性和高效性。