将大型语言模型(LLMs)与专用工具集成,为智能自动化系统提供了新的机会。然而,由于协调困难、资源利用效率低下和信息流不一致,组织多个由LLM驱动的代理来处理复杂任务仍然具有挑战性。我们提出了OmniNova,这是一个模块化的多代理自动化框架,将语言模型与专用工具(如网络搜索、爬虫和代码执行能力)相结合。OmniNova引入了三项关键创新:(1)具有不同协调员、规划者、监督者和专家代理的分层多代理架构;(2)根据任务复杂度优化代理部署的动态任务路由机制;以及(3)分配适当模型以满足不同认知需求的多层次LLM集成系统。我们在研究、数据分析和网络交互领域的50个复杂任务上的评估表明,OmniNova在任务完成率(87% vs 基准62%)、效率(减少41%的令牌使用量)和结果质量(人类评分4.2/5 vs 基准3.1/5)方面优于现有框架。我们贡献了一个用于多代理系统设计的理论框架和一个开源实现,推动了基于LLM的自动化系统的最先进水平。
随着大型语言模型(LLMs)在自然语言理解和生成方面表现出越来越强的能力 (Brown 等 2020; Touvron 等 2023; Anthropic 2023) ,通过与专用工具集成来扩展其功能引起了越来越多的兴趣 (Schick 等 2023; Qin 等 2023) 。这些增强型LLMs可以执行超出文本生成的动作,例如执行代码 (M. Chen 等 2021) ,检索信息 (Lewis 等 2020) ,以及与外部系统交互 (Nakano 等 2021) 。
尽管单独使用时令人印象深刻,但使用单一LLM实例处理需要多样化能力的复杂任务存在显著限制。例如,研究任务通常涉及信息搜索、数据分析和综合发现——这些活动受益于专门方法。这促使开发了多代理系统,在该系统中,多个具有特定角色和能力的LLM实例协作解决复杂问题 (Wu 等 2023; Qian 等 2023; Hong 等 2023) 。
尽管该领域取得了进展,现有的多代理框架仍面临几个挑战:
- 协调开销 :管理多个代理之间的互动引入了显著的复杂性和潜在的沟通失误 (Zhao 等 2023) 。
- 资源低效 :使用高能力模型处理所有任务浪费计算资源 (Zhou 等 2023) 。
- 规划限制 :许多系统难以进行有效的任务分解和策略制定 (Hao 等 2023) 。
- 工具集成 :无缝结合外部工具仍然具有挑战性 (Qin 等 2023) 。
为了解决这些限制,我们介绍了OmniNova,这是一个模块化的多代理自动化框架,能够实现具有不同能力的LLM代理之间的有效协作。OmniNova实现了一种分层架构,其中专业代理由监督代理协调,这些监督代理管理整体工作流程。这种方法允许有效的任务分解、适当的委派和结果的有效整合。
我们的贡献包括:
- 一种分层多代理架构,包含不同的协调员、规划者、监督者和专家代理,使任务分解和委派更加有效。
- 一种动态任务路由机制,根据任务复杂度优化代理部署,降低计算成本的同时保持性能。
- 一种多层次的LLM集成系统,根据不同的认知需求分配具有适当能力的模型,平衡性能和效率。
- 一项全面评估,证明OmniNova在多个指标和任务类型上优于现有框架。
- 一个开源实现,既作为实用工具,也为未来多代理系统的研究奠定了基础。
在接下来的部分中,我们将详细介绍OmniNova的架构、实现和评估。我们首先回顾相关工作(第 2 节),然后描述OmniNova的系统架构(第 3 节)。随后详细说明我们的实现(第 4 节)和评估方法及结果(第 5 节)。最后,我们讨论工作的意义和局限性(第 6 节),并以未来方向总结(第 7 节)。
2 相关工作
2.1 大型语言模型和工具使用
大型语言模型已从基本的文本生成模型发展为能够进行复杂推理和问题解决的复杂系统 (Brown 等 2020; Ouyang 等 2022; OpenAI 2023) 。近期的工作集中在增强LLMs使用外部工具的能力,从而扩展其超越训练数据的功能,并使其能够与世界互动 (Schick 等 2023; Qin 等 2023; Paranjape 等 2023) 。
Toolformer (Schick 等 2023) 首次通过此方法微调语言模型,使用嵌入在文本中的API调用来使用外部工具。ToolLLM (Qin 等 2023) 通过开发工具使用的基准和提出改进的训练方法扩展了这一概念。ReAct (Yao 等 2023) 引入了一个框架,将推理和行动交织在一起,使LLMs能够以集成的方式制定计划并执行动作。Voyager (Wang 等 2023) 展示了一个通过工具使用在Minecraft中自主探索和技能获取的LLM驱动代理。
尽管这些系统展示了有希望的能力,但它们通常依赖于单一的LLM实例,这限制了它们处理需要多样化专业知识的复杂任务的能力,并在使用高能力模型处理所有任务时引入了效率挑战。
2.2 多代理系统
基于LLM的代理组成的多代理系统代表了一个不断增长的研究领域,旨在解决单代理方法的局限性 (Hong 等 2023; Qian 等 2023; Wu 等 2023) 。这些系统将复杂任务分布在多个专业代理之间,通过协作实现更有效的解决问题。
MetaGPT (Hong 等 2023) 实现了一个用于软件开发的多代理框架,其中不同的代理承担产品管理、架构师和程序员等角色。AutoGen (Wu 等 2023) 提出了一种构建可以共同完成任务的多个对话代理的应用程序框架。ChatDev (Qian 等 2023) 展示了一个由LLM代理组成的虚拟软件开发团队,这些代理协作构建软件应用程序。
这些系统展示了多代理方法的潜力,但在有效协调、高效资源利用和外部工具的无缝集成方面往往面临挑战。
2.3 代理编排和工作流
协调多个代理以有效地处理复杂任务需要复杂的流程管理。LangGraph (Harrison Chase 2023) 和 CrewAI (Creati.ai 2023) 已经作为定义和管理代理工作流的框架出现,使创建复杂的交互模式和决策过程成为可能。
CAMEL (G. Li 等 2023) 探索了人工智能代理之间的通信和协作,通过实施角色扮演场景的框架。CHATGPT-TEAM-GEN (J. Li 等 2023) 展示了多个ChatGPT实例如何作为一个团队合作解决复杂任务。特定任务的框架如AgentVerse (W. Chen 等 2023) 用于模拟环境和 Ghost (Ghosn, Gupta, 和 Alokik 2020) 用于分布式任务执行进一步推动了该领域的发展。
我们的工作建立在这些基础上,同时解决了协调效率、资源利用和适应不同任务复杂度的关键限制。
2.4 分层规划与执行
分层规划与执行的概念,即将复杂任务分解为子任务并分配给专业代理,在各种背景下得到了探索 (Yang, Parr, 和 Caruana 2018; Illanes 等 2020; Wen 等 2021) 。
CLAIRIFY (Kalyan 等 2023) 展示了语言模型代理如何将复杂的信息寻求任务分解为分层步骤。ReAct-Plan-Solve (Liu 等 2023) 提出了一个结合规划、行动和对话的任务规划和执行框架。ViperGPT (Surís, Menon, 和 Torralba 2023) 实现了一个生成和执行视觉推理任务程序的系统。
OmniNova通过更全面的分层系统扩展了这些方法,该系统包含了动态路由、多层次模型分配和无缝工具集成。
3 系统架构
OmniNova实现了模块化、分层架构,旨在通过专业代理协作高效处理复杂任务。该系统包括六个核心组件:多代理系统、工作流引擎、语言模型集成层、工具集成层、配置管理和提示模板系统。图 1 说明了这一架构。
OmniNova的分层多代理架构
3.1 多代理系统
OmniNova的核心是一个由七个专业化代理组成的协作生态系统,每个代理负责任务执行的不同方面:
3.1.1 协调员代理
协调员作为入口点,接收用户查询并进行初步分析。它评估任务复杂度并确定是直接响应还是升级到规划代理以处理更复杂的任务。这种初始路由机制防止了简单查询的不必要的处理,提高了效率。
3.1.2 规划代理
对于复杂任务,规划员进行详细分析并制定全面的执行策略。它可以选择进行初步研究以收集背景信息然后再规划。规划员产生任务计划的结构化JSON表示,包括步骤、依赖关系和资源要求。此代理使用高性能推理模型确保有效的任务分解。
3.1.3 监督代理
监督员管理工作流执行,解释计划并将任务分配给专业代理。它根据当前状态和代理能力动态分配任务,监控进度,并做出路由决策以确保计划的有效执行。像规划员一样,它使用高性能推理模型进行复杂决策。
3.1.4 专家代理
三个专家代理处理特定的任务领域:
- 研究代理 :使用搜索工具和网络爬虫收集和分析信息,生成关于发现的结构化报告。
- 代码代理 :使用Python和bash环境执行编程任务,处理数据分析、计算和自动化任务。
- 浏览器代理 :执行网页交互,包括导航、内容提取和表单提交,使能在基于Web的系统上进行复杂操作。
3.1.5 报告代理
报告员将所有专家代理的输出整合成一份连贯的最终报告,确保格式一致并对所有任务方面进行全面覆盖。
这种多代理结构使任务分解和专业化有效,同时保持协调执行,解决了单代理方法的关键限制。
3.2 工作流引擎
OmniNova的工作流引擎基于LangGraph (Harrison Chase 2023) ,管理代理交互和状态转换。引擎实现:
- 状态管理 :使用TypedDict进行类型安全的状态表示,确保代理间的数据传递一致性。
- 节点系统 :每个代理作为一个独立的节点运行,具有明确定义的输入和输出。
- 动态路由 :条件逻辑根据代理输出和任务需求确定工作流路径。
- 工作流控制 :命令如 goto 和 update 允许灵活地在网络中导航。
该组件为代理协作提供了结构性基础,使复杂工作流成为可能,同时保持系统完整性。
3.3 语言模型集成层
OmniNova的一个关键创新是其多层次的LLM架构,根据认知需求分配不同的模型能力:
- 推理层 :高性能模型被分配到需要复杂推理的规划和监督任务。
- 基本层 :标准模型处理诸如研究、编码和报告等常规任务。
- 视觉层 :专门用于涉及图像理解任务的模型(可扩展设计)。
这种分层方法通过仅在必要时部署昂贵的高性能模型,同时使用更高效的模型处理常规任务,优化了计算资源的利用。集成通过统一的模型接口LiteLLM (BerriAI 2023) 实现,支持多个提供商、灵活配置、流式输出和结构化响应。
3.4 工具集成层
OmniNova通过统一的工具集成框架扩展代理能力:
- 搜索工具 :Tavily API用于网络搜索和Jina用于神经搜索,实现信息检索。
- 代码执行 :Python REPL和Bash环境用于执行代码和系统命令。
- 浏览器自动化 :基于Playwright的浏览器控制进行网页交互。
- 文件操作 :安全的文件读写能力。
所有工具都实现了统一的接口模式,便于扩展并确保可靠的错误处理。这种全面的工具集成解决了现有系统常常难以有效使用外部工具的常见限制。
3.5 配置系统
OmniNova实现了一个多层次的配置管理系统:
- YAML配置 :定义模型提供商、参数和系统行为的核心设置。
- 环境变量 :支持敏感信息和部署特定设置。
- 运行时覆盖 :执行期间的动态参数调整。
- 验证 :配置完整性检查以防止运行时错误。
这个灵活的配置系统无需代码修改即可适应不同的环境和用例。
3.6 提示模板系统
代理行为通过模板驱动设计定义:
- 基于文件的模板 :易于修改和优化提示。
- 上下文注入 :自动将状态信息纳入模板。
- 历史管理 :处理对话历史和上下文窗口。
- 多模式支持 :与聊天和完成模型兼容。
这种方法无需代码更改即可快速迭代代理行为,促进实验和优化。
4 实现
4.1 系统组件
4.1.1 状态管理
OmniNova的状态管理使用TypedDict实现类型安全和LangGraph的MessagesState进行消息处理:
class State(MessagesState):
"""代理系统的状态,
扩展MessagesState添加next字段。"""
# 常量
TEAM_MEMBERS: list[str]
TEAM_MEMBER_CONFIGRATIONS: dict[str, dict]
# 运行时变量
next: str
full_plan: str
"> deep_thinking_mode: bool
search_before_planning: bool
这种类型化的方法确保了代理之间一致的数据传递,并防止由于状态操作不一致而导致的运行时错误。该状态扩展了LangGraph的MessagesState,利用其内置的消息处理能力,同时为OmniNova的具体需求添加自定义字段。
4.1.2 工作流构建
工作流使用LangGraph的StateGraph构建,定义节点和边以表示代理交互模式:
def build_graph():
"""构建并返回代理工作流图。"""
builder = StateGraph(State)
builder.add_edge(START, "coordinator")
builder.add_node("coordinator", coordinator_node)
builder.add_node("planner", planner_node)
builder.add_node("supervisor", supervisor_node)
builder.add_node("researcher", research_node)
builder.add_node("coder", code_node)
builder.add_node("browser", browser_node)
builder.add_node("reporter", reporter_node)
return builder.compile()
该图结构遵循分层模式,协调员作为入口点,然后是规划员和监督节点,再委托给专业代理。此设计实现了清晰的任务流程和高效的状态管理。
4.1.3 代理实现
代理使用LangGraph的React代理模式实现,结合推理和行动能力:
def create_agent(agent_type: str, tools: list, prompt_template: str):
"""工厂函数用于创建具有统一配置的代理。"""
return create_react_agent(
get_llm_by_type(AGENT_LLM_MAP[agent_type]),
tools=tools,
prompt=lambda state: apply_prompt_template(prompt_template,
state)
)
这种工厂方法使具有适当模型分配和工具分配的代理创建保持一致。每个代理根据其在系统中的角色配置特定的工具和提示。
4.1.4 LLM集成
OmniNova的多层次LLM架构通过支持不同类型和配置的模型工厂函数实现:
def get_llm_by_type(
llm_type: Union[LLMType, str],
model_kwargs: Optional[Dict[str, Any]] = None
) -> BaseLanguageModel:
"""通过类型获取语言模型实例。"""
model_kwargs = model_kwargs or {}
if llm_type == "reasoning":
model_config = REASONING_MODEL
elif llm_type == "basic":
model_config = BASIC_MODEL
elif llm_type == "vision":
model_config = VL_MODEL
else:
# 针对特定类型的代理
from src.config.agents import AGENT_LLM_MAP
if llm_type in AGENT_LLM_MAP:
return get_llm_by_type(
AGENT_LLM_MAP[llm_type],
model_kwargs)
# 通过litellm创建LLM
final_kwargs = {**model_config, **model_kwargs}
return ChatLiteLLM(**final_kwargs)
LLM集成层提供了一个灵活的接口进行模型选择和配置,支持不同类型的模型(推理、基础、视觉),并允许运行时参数覆盖。这种设计通过部署适当的模型来满足不同的认知需求,从而实现高效的资源利用。
4.2 代理行为专业化
4.2.1 协调员逻辑
协调员实施了一种分流机制,根据任务复杂性路由任务:
def coordinator_node(state: State) -> Command:
"""与用户沟通的协调员节点。"""
messages = apply_prompt_template("coordinator", state)
response = get_llm_by_type(
AGENT_LLM_MAP["coordinator"]).invoke(messages)
goto = "__end__"
if "handoff_to_planner" in response.content:
goto = "planner"
return Command(goto=goto)
这种实现能够有效处理简单查询,同时将复杂任务路由到规划系统。协调员使用基本LLM模型进行快速决策,优化资源使用。
4.2.2 规划逻辑
规划员采用一种复杂的任务分解和策略制定方法:
def planner_node(state: State) ->
Command[Literal["supervisor", "__end__"]]:
"""生成完整计划的规划员节点。"""
messages = apply_prompt_template("planner", state)
# 根据任务复杂度动态选择模型
llm = get_llm_by_type("basic")
if state.get("deep_thinking_mode"):
llm = get_llm_by_type("reasoning")
# 可选搜索背景信息
if state.get("search_before_planning"):
searched_content = tavily_tool.invoke(
{"query": state["messages"][-1].content})
if isinstance(searched_content, list):
messages = deepcopy(messages)
messages[-1].content += f"\n\n
# 搜索结果\n\n{json.dumps([...])}"
# 流式响应提高效率
stream = llm.stream(messages)
full_response = ""
for chunk in stream:
full_response += chunk.content
# 确保有效的JSON格式
try:
repaired_response =
json_repair.loads(full_response)
full_response = json.dumps(repaired_response)
goto = "supervisor"
except json.JSONDecodeError:
goto = "__end__"
return Command(
update={
"messages": [HumanMessage(
content=full_response,
name="planner")],
"full_plan": full_response,
},
goto=goto,
)
此实现展示了几项创新,包括根据任务复杂度动态选择模型、可选搜索集成以获得更好的上下文、流式传输以提高效率以及对JSON响应的健壮错误处理。
4.2.3 监督逻辑
监督员根据计划和当前状态动态地将任务分配给专家代理:
def supervisor_node(state: State) ->
Command[Literal[*TEAM_MEMBERS, "__end__"]]:
"""决定哪个代理应该执行下一步的监督员节点。"""
messages = apply_prompt_template("supervisor", state)
# 增强消息格式以更好地执行
messages = deepcopy(messages)
for message in messages:
if isinstance(message, BaseMessage)
and message.name in TEAM_MEMBERS:
message.content = RESPONSE_FORMAT.format(
message.name, message.content)
# 获取结构化的路由决策
response = (
get_llm_by_type(AGENT_LLM_MAP["supervisor"])
.with_structured_output(
schema=Router, method="json_mode")
.invoke(messages)
)
goto = response["next"]
# 处理完成情况
if goto == "FINISH":
goto = "__end__"
return Command(goto=goto, update={"next": goto})
此实现实现了系统的动态路由功能、结构化输出处理和与工作流引擎的无缝集成。监督员使用基本LLM模型进行高效决策,同时保持结构化输出以确保可靠的路由。
4.3 工具集成
OmniNova通过一致的接口模式实现多样化的工具,包括日志记录和错误处理:
@log_io
def tavily_search(query: str,
max_results: \
int = TAVILY_MAX_RESULTS) -> List[Dict]:
"""使用Tavily搜索网络信息。"""
client = TavilyClient(api_key=os.getenv("TAVILY_API_KEY"))
response =
client.search(query=query, max_results=max_results)
return response["results"]
工具集成层包括一个日志装饰器,跟踪输入参数和输出结果,便于调试和监控。所有工具均实现一致的错误处理和输入验证,确保系统可靠运行。