
机器学习算法有哪些
随着LLM的涌现,以LLM为中枢构建的Agent系统在近期受到了广泛的关注。Agent系统旨在利用LLM的归纳推理能力,通过为不同的Agent分配角色与任务信息,并配备相应的工具插件,从而完成复杂的任务。
目前更常见的框架大多聚焦于single-agent的场景。single-agent的核心在于LLM与工具的配合。LLM通过理解用户的任务,推理出需要调用的工具,并基于调用结果给用户反馈。在完成任务的过程中,Agent可能与用户有多轮交互。下图即展示了一个主流的Agent执行流程。
与此同时,也有越来越多的Agent框架开始聚焦于multi-agent场景。为了完成任务,multi-agent会为不同的Agent赋予不同的角色定位,通过Agent之间的协同合作来完成复杂的任务。而在完成任务的过程中,相比于single-agent来说,与用户的交互会更少一些。
为了构建一个multi-agent框架,我们需要思考相比于single-agent,框架中多了哪些组件。
multi-agent框架的核心交互流程可以概括如下:
下面的部分我们将简单介绍现有的三个multi-agent框架,并对它们进行简单的比较。
相关资料
代码repo:https://github.com/geekan/MetaGPT
论文:https://arxiv.org/pdf/2308.00352.pdf
核心模块
MetaGPT论文中给出的架构图如上所示。
class Role:
"""Role/Agent"""
def __init__(self, name="", profile="", goal="", constraints="", desc=""):
self._llm = LLM() #llm
self._setting = RoleSetting(name=name, profile=profile, goal=goal, constraints=constraints, desc=desc)
self._states = []
self._actions = [] # 对应的action/ stage
self._role_id = str(self._setting)
self._rc = RoleContext()
在Role中,又有两个主要组件:RoleSetting和RoleContext。其中RoleSetting存储了角色的名字、目标等信息。RoleContext则包含了运行中的状态信息,如记忆,需要执行的动作等。
class RoleSetting(BaseModel):
"""Role Settings"""
name: str
profile: str
goal: str
constraints: str
desc: str
class RoleContext(BaseModel):
"""Role Runtime Context"""
# 维护运行过程中的一些状态信息
env: 'Environment' = Field(default=None) # environment,所有角色共享
memory: Memory = Field(default_factory=Memory) # 记忆信息
state: int = Field(default=0) # 下一时刻要执行的动作
todo: Action = Field(default=None)
watch: set[Type[Action]] = Field(default_factory=set) # 关注/订阅的信息
news: list[Type[Message]] = Field(default=[]) # 本轮新增的信息
下面简单介绍一下MetaGPT的流程。
首先,在environment.run()函数中,会依次调用每个角色的role.run()
async def run(self, k=1):
"""处理一次所有信息的运行
Process all Role runs at once
"""
for _ in range(k):
futures = []
# 执行
for role in self.roles.values():
future = role.run()
futures.append(future)
await asyncio.gather(*futures)
在role.run()函数中,与前面所述流程类似分为三步:a) _observe()函数观察环境、更新memory。b) _react()函数思考并执行动作。c) _publish_message()函数将执行结果更新到环境中。
async def run(self, message=None):
"""Observe, and think and act based on the results of the observation"""
if message:
...
# 观察环境、更新memory
elif not await self._observe():
# If there is no new information, suspend and wait
return
# 执行动作
rsp = await self._react()
# 把结果传给environment
self._publish_message(rsp)
return rsp
_react()函数可以进一步分为_think()和_act()两个阶段。_think()负责决定SOP的状态转移,_act()通过调用action.run()完成具体执行。两个阶段可能都需要调用LLM。
自定义扩展
最后在作者给出的examples中,用户如果想要实现一个自定义场景,一般情况下只需要实现自己的Action和Role类及对应的关键函数即可。
相关资料
代码repo:https://github.com/OpenBMB/AgentVerse
论文:https://arxiv.org/pdf/2308.10848.pdf
除此之外,清华大学的开源框架AgentVerse也提供了一个基于LLMs来搭建多智能体交互的框架。
核心模块
论文中,提供了如上图所示的流程图,它的设计流程模拟了人类的决策过程,包含了四个阶段,分别是:专家招聘、协作决策、行动执行和评估。
根据包括软件开发,咨询和游戏的几个不同领域的案例表明,这种多智能体合作的方式优于单一智能体,并且优势明显。
AgentVerse 在代码实现上,包含了两个基础元素agent和environment, agent不用过多介绍,他的工作行为依赖特定的prompt以及配合大模型llm进行结果生成。
这里的environment就是代表着任务,在environment中通过定义agents以及rules等信息,来确保多智能体的交互流程能够按照上述进行。
值得注意的是,environment 的rules中包含了5个组建,这些组件分别是: 描述器,顺序,选择器,更新器,以及可见性。他们的作用具体如下,(参考https://mp.weixin.qq.com/s/jkW2JRnbfsK81ClhwsCxqA)
具体Environment定义的代码如下:
@EnvironmentRegistry.register("basic")
class BasicEnvironment(BaseEnvironment):
"""
A basic environment implementing the logic of conversation.
Args:
agents: List of agents
rule: Rule for the environment
max_turns: Maximum number of turns
cnt_turn: Current turn number
last_messages: Messages from last turn
rule_params: Variables set by the rule
"""
agents: List[BaseAgent]
rule: Rule
max_turns: int = 10
cnt_turn: int = 0
last_messages: List[Message] = []
rule_params: Dict = {}
def __init__(self, rule, **kwargs):
rule_config = rule
order_config = rule_config.get("order", {"type": "sequential"})
visibility_config = rule_config.get("visibility", {"type": "all"})
selector_config = rule_config.get("selector", {"type": "basic"})
updater_config = rule_config.get("updater", {"type": "basic"})
describer_config = rule_config.get("describer", {"type": "basic"})
rule = Rule(
order_config,
visibility_config,
selector_config,
updater_config,
describer_config,
)
super().__init__(rule=rule, **kwargs)
对应Agent的定义如下:
class BaseAgent(BaseModel):
name: str # 名字
llm: BaseLLM # llm
output_parser: OutputParser # 输出解析
prompt_template: str # 模板
role_description: str = Field(default="") # 角色信息
memory: BaseMemory = Field(default_factory=ChatHistoryMemory) # 记忆
max_retry: int = Field(default=3)
receiver: Set[str] = Field(default=set({"all"})) # 信息的接收方
async_mode: bool = Field(default=True)
核心流程
用户初始化,并调用 agentVerse.run()作为程序入口
class AgentVerse:
def __init__(self, agents: List[BaseAgent], environment: BaseEnvironment):
self.agents = agents
self.environment = environment
def run(self):
"""Run the environment from scratch until it is done."""
self.environment.reset()
# 循环执行
while not self.environment.is_done():
asyncio.run(self.environment.step())
相关environment流程逻辑如下:
async def step(self) -> List[Message]:
"""Run one step of the environment"""
# 选择下一时刻的行动的agent(s)
agent_ids = self.rule.get_next_agent_idx(self)
# 环境描述信息(每个agents不一定一样)
env_descriptions = self.rule.get_env_description(self)
# agent行动,返回结果
messages = await asyncio.gather(
*[self.agents[i].astep(env_descriptions[i]) for i in agent_ids]
)
# 选择过滤message信息
selected_messages = self.rule.select_message(self, messages)
# 更新mmory
self.rule.update_memory(self)
# 更新agent之间的可见性
self.rule.update_visible_agents(self)
self.cnt_turn += 1
return selected_messages
相关 agent 流程逻辑如下:
def step(self, env_description: str = "") -> Message:
parsed_response = None
tool_observation = [self.tool_memory.to_string()]
while True:
# 拼接prompt
prompt = self._fill_prompt_template(env_description, tool_observation)
try:
# 调用LLM
response = self.llm.generate_response(prompt)
# 解析结果
parsed_response = self.output_parser.parse(response)
if isinstance(parsed_response, AgentAction):
# 调用工具
observation = self._call_tool(parsed_response)
tool_observation.append(
parsed_response.log.strip()
+ f"\nObservation: {observation.strip()}"
)
break
except BaseException as e:
logging.error(e)
logging.warning("Retrying...")
continue
if parsed_response is None or isinstance(parsed_response, AgentFinish):
break
self._update_tool_memory(tool_observation)
message = Message(
content=""
if parsed_response is None
else parsed_response.return_values["output"],
sender=self.name,
receiver=self.get_receiver(),
)
return message
拿软件开发的任务举例子,用户需要提供一个json配置文件,包含environment信息所需的信息,并且定义若干个不同的agent,如code_writer,code_reviwer,unit_test_generator,以及他们之间沟通时候的rule,最终初始化environment, agents以及agentverse入口方法,并调用 agentVerse.run()即可。
相关资料
代码repo:https://github.com/aiwaves-cn/agents
论文:https://arxiv.org/pdf/2309.07870.pdf
最后,波形智能联合浙大和苏黎世联邦理工大学,提供了另外一种支持mutli-agent的设计方案。
核心模块
该方案围绕SOP模块来确定agent之间交互的推进方式,通过SOP来管理状态的变换,并将相关状态信息变换记录到环境中,以便不同的agent进行各自任务的推进。 整体流程如下图所示:
Agents有三个核心模块,除了上述SOP,还有Agent以及Environment。
(参考:https://mp.weixin.qq.com/s/toblMJJkpFKtv0dfJFfHKA)
核心流程
入口代码如下所示,用户通过配置文件来初始化agent,environment以及sop,并通过如下入口程序开始agent交互流程。
def run(agents,sop,environment):
while True:
# 更新状态,决定下一个行动的agent
current_state,current_agent= sop.next(environment,agents)
if sop.finished:
os.environ.clear()
break
# agent执行
action = current_agent.step(current_state)
# 更新memory
memory = process(action)
environment.update_memory(memory,current_state)
sop的流程方法如下,通过调用transit方法进行状态转移的操作,以及用route进行agent的选择。
def next(self, environment, agents):
"""
Determine the next state and the agent that needs action based on the current situation
"""
# 一些初始化流程:获取记忆、相关信息等
...
# 下一时刻的状态
next_state = self.transit(
chat_history=environment.shared_memory["long_term_memory"][
environment.current_chat_history_idx :
],
relevant_history=relevant_history,
environment=environment,
)
# 如果进入终止节点,则直接终止
if next_state.name == self.finish_state_name:
self.finished = True
return None, None
# 更新状态
self.current_state = next_state
# 决定下一时刻要行动的agent
next_agent = self.route(
chat_history=environment.shared_memory["long_term_memory"][
environment.current_chat_history_idx :
],
agents = agents,
relevant_history=relevant_history,
)
return self.current_state, next_agent
agent的执行方法如下,主要是根据当前环境信息,来进行prompt生成,并调用llm进行生成
def step(self, current_state,input=""):
"""
return actions by current state and environment
Return: action(Action)
"""
current_state.chat_nums +=1
state_begin = current_state.is_begin
agent_begin = self.begins[current_state.name]["is_begin"]
self.begins[current_state.name]["is_begin"] = False
current_state.is_begin = False
environment = self.environment
self.current_state = current_state
# 先根据当前环境更新信息
if len(environment.shared_memory["long_term_memory"])>0:
current_history = self.observe()
self.long_term_memory.append(current_history)
response,res_dict = self.act()
action_dict = {
"response": response,
"res_dict": res_dict,
"role": self.state_roles[current_state.name],
"name": self.name,
"state_begin" : state_begin,
"agent_begin" : agent_begin,
"is_user" : self.is_user
}
return Action(**action_dict)
def act(self):
"""
return actions by the current state
"""
current_state = self.current_state
chat_history = self.long_term_memory
current_LLM = self.LLMs[current_state.name]
# 拼接prompt
system_prompt, last_prompt, res_dict = self.compile()
# 调用LLM
response = current_LLM.get_response(
chat_history, system_prompt, last_prompt, stream=True
)
return response,res_dict
最后,agent执行结束后,environment会更新本轮环境信息用于下一轮
class Memory:
def __init__(self,role,name,content) -> None:
self.send_role = role
self.send_name = name
self.content = content
def update_memory(self, memory, current_state):
"""
更新环境的memory信息
"""
MAX_CHAT_HISTORY = eval(os.environ["MAX_CHAT_HISTORY"])
self.shared_memory["long_term_memory"].append(memory)
current_embedding = get_embedding(memory.content)
# 对过去几轮信息作summary
if len(self.shared_memory["long_term_memory"]) % MAX_CHAT_HISTORY == 0:
summary = self.summary(current_state)
self.shared_memory["short_term_memory"] = summary
self.agents[memory.send_name].update_memory(memory)
目前,Agents 除了独特的SOP系统以外,相对于其他框架不同的点还有一个重要功能是支持人类使用者扮演multi-agent系统中的一个或多个智能体的功能,可以方便地支持各种人 – 智能体交互的应用场景,如人和智能体一起玩游戏、辩论等。
最后,我们针对上述几个市面上比较主流的agents框架进行简单的总结与比较。部分相关特性如下所示:
框架名称 | MetaGPT | AgentVerse | Agents |
Config的详细性 | 少 | 中 | 多 |
状态的切换 | 基于LLM与SOP | 无/迭代达到最大轮数 | 基于LLM与SOP |
Agent执行顺序 | 顺序 | 基于规则 | 顺序/LLM决定/随机 |
长短期记忆 | 有 | 有 | 有/做了额外处理 |
工具调用 | 少 | 少/单个 | 少/不是由LLM决定的 |
Agent差异性体现(即对当前Agent,其他Agent是否有区别) | 有 | 有 | 无 |
综上,multi-agent框架的核心还是在agent之间的交互与状态的转移。而LLM对工具的调用往往只是作为其中一个子模块,且大部分agent都只调用单个tool。因此,在multi-agent的场景中,使用多个单tool的agent还是一个多tool的agent,也是一个值得考虑的问题。
本文章转载微信公众号@青稞AI