像LangChain、CrewAI和AutoGen这样的框架通过提供构建人工智能系统的高级抽象而广受欢迎。然而,包括我在内的许多开发人员都发现,这些工具弊大于利,常常给开发过程带来不必要的复杂性和挫折感。
进入Atomic Agents--一个模块化的精简框架,旨在消除与现有人工智能开发工具相关的麻烦。Atomic Agents 基于可靠的编程范式,如 Input–Process–Output(IPO)模型和原子性概念,提供了一种以简单性、灵活性和开发者控制为优先考虑的全新方法。
在本文中,我们将深入探讨 Atomic Agents 的创建原因、它所采用的编程范式以及它如何在众多产品中脱颖而出。结合代码示例和实际示例,一起深入了解 Atomic Agents。如果你也一度觉得 LangChain 太复杂了,下面我们一起看一看吧~
当我第一次开始尝试使用LangChain时,我对它简化人工智能代理开发非常感兴趣。然而,实际上并非如此简单。
除了各种错中复杂的类和方法,LangChain的开发者似乎并不了解人工智能开发所面临的实际挑战,或许他们更看重的是理论上的优雅而非现实世界中的可用性。过度的抽象不仅增加了开发难度,还让开发变得不透明。
同样,CrewAI和AutoGen等框架也试图通过自动化复杂任务来提供 “神奇 ”的解决方案。部署成群的人工智能代理来自主处理一切事务的想法很诱人,但在实践中,这些工具往往一半的时间都无法正常工作。它们的承诺过高,而实际效果却不尽如人意,让开发人员疲于应对不可预测的行为和缺乏控制的问题。
这些框架模糊了底层流程,使得调试或定制功能变得困难。结果就是,这些工具更像是一个黑盒子,而不是一个有用的框架--在开发需要可靠和可维护性的应用程序时,这种情况并不理想。
这些框架经常出现的一个问题是倾向于过度承诺功能。一些公司和工具声称可以提供接近AGI(人工通用智能)的解决方案,但如果你有长时间从事人工智能领域相关工作,你就会发现,我们还没有达到那个水平。炒作往往会导致不切实际的期望,而当这些工具不可避免地出现不足时,开发人员就不得不面对后果。
在与这些挫折搏斗之后,我们清楚地认识到,我们需要一个这样的框架:消除不必要的复杂性和抽象层:
这种认识促成了Atomic Agents的诞生。
Atomic Agents是一个开源框架,旨在尽可能做到轻量级、模块化和可组合。它遵循输入-处理-输出(IPO)模型和原子性的原则,确保每个组件都是单一用途、可重用和可互换的。
Atomic Agents 的诞生是为了弥补现有框架的不足。它的目标是
通过坚持这些原则,Atomic Agents 让开发人员能够构建既强大又易于管理的人工智能代理和应用程序。
Atomic Agents的核心是Input–Process–Output(IPO)模型,这是一种基本的编程范式,它将程序结构分为三个不同的阶段:
这种模型清晰简洁,更容易理解和管理应用程序中的数据流。
在Atomic Agents中,这可以转化为
原子性的概念是将复杂的系统分解成最小的功能部分或 “原子”。每个原子
通过专注于原子组件,Atomic Agents 促进了模块化架构,提高了灵活性和可扩展性。
在Atomic Agents中,人工智能代理由几个关键部分组成:
每个组件的设计都是模块化和可互换的,并遵循关注点分离和单一责任的原则。
模块化是Atomic Agents的核心。通过将组件设计成自成一体并专注于单一任务,开发人员可以
这种模块化方法不仅使开发更易于管理,还增强了人工智能应用程序的可维护性和可扩展性。
上下文提供程序允许代理在系统提示中包含动态数据,并根据最新信息加强响应。
示例:
from atomic_agents.lib.components.system_prompt_generator import SystemPromptContextProviderBase
class SearchResultsProvider(SystemPromptContextProviderBase):
def __init__(self, title: str, search_results: List[str]):
super().__init__(title=title)
self.search_results = search_results
def get_info(self) -> str:
return "\n".join(self.search_results)
# 向代理注册上下文提供程序
agent.register_context_provider("search_results", search_results_provider)
通过将实时数据注入代理的上下文,您可以创建更动态、反应更灵敏的人工智能应用。
Atomic Agents 通过调整输入和输出模式,简化了代理和工具的链式连接过程。
示例: 假设你有一个查询生成代理和一个网络搜索工具。通过设置查询代理的输出模式,使其与搜索工具的输入模式相匹配,就可以直接将它们串联起来。
from web_search_agent.tools.searxng_search import SearxNGSearchTool
# Initialize the query agent
query_agent = BaseAgent(
BaseAgentConfig(
# ... other configurations ...
output_schema=SearxNGSearchTool.input_schema, # Align output schema
)
)
这种设计提高了可重用性和灵活性,可以轻松更换组件或扩展功能。
与引入多层抽象的框架不同,Atomic Agents 保持了简单明了。每个组件都有明确的目的,没有隐藏的魔法需要破解。
Atomic Agents 的设计考虑到了现实世界中的开发挑战。它采用久经考验的编程范式,并优先考虑开发人员的经验。
Atomic Agents 的每个部分都可以独立运行,从而促进了可重用性和模块化。
我们将构建一个人工智能代理,它能响应用户询问并提出后续问题。
from pydantic import BaseModel, Field
from typing import List
from atomic_agents.agents.base_agent import BaseIOSchema
class CustomInputSchema(BaseIOSchema):
chat_message: str = Field(..., description="The user's input message.")
class CustomOutputSchema(BaseIOSchema):
chat_message: str = Field(..., description="The agent's response message.")
suggested_questions: List[str] = Field(..., description="Suggested follow-up questions.")
from atomic_agents.lib.components.system_prompt_generator import SystemPromptGenerator
system_prompt_generator = SystemPromptGenerator(
background=[
"You are a knowledgeable assistant that provides helpful information and suggests follow-up questions."
],
steps=[
"Analyze the user's input to understand the context and intent.",
"Provide a relevant and informative response.",
"Generate 3 suggested follow-up questions."
],
output_instructions=[
"Ensure clarity and conciseness in your response.",
"Conclude with 3 relevant suggested questions."
]
)
from atomic_agents.agents.base_agent import BaseAgent, BaseAgentConfig
import instructor
import openai
# Initialize the agent
agent = BaseAgent(
config=BaseAgentConfig(
client=instructor.from_openai(openai.OpenAI(api_key='YOUR_OPENAI_API_KEY')),
model="gpt-4",
system_prompt_generator=system_prompt_generator,
input_schema=CustomInputSchema,
output_schema=CustomOutputSchema
)
)
user_input = "Can you explain the benefits of using Atomic Agents?"
input_data = CustomInputSchema(chat_message=user_input)
response = agent.run(input_data)
print(f"Agent: {response.chat_message}")
print("Suggested questions:")
for question in response.suggested_questions:
print(f"- {question}")
Agent: Atomic Agents simplifies AI development by providing modular, reusable components based on solid programming paradigms like the IPO model and atomicity.
Suggested questions:
- How does Atomic Agents compare to other AI frameworks?
- Can you provide an example of building an agent with Atomic Agents?
- What are the key features of Atomic Agents that enhance productivity?
假设我们想让代理根据用户查询执行网络搜索。
使用 Atomic Assembler CLI,我们可以下载搜索工具:
atomic
从菜单中选择 SearxNGSearchTool,然后按照说明安装依赖项。
from web_search_agent.tools.searxng_search import SearxNGSearchTool, SearxNGSearchToolConfig
# 初始化搜索工具
search_tool = SearxNGSearchTool(config=SearxNGSearchToolConfig(base_url="http://localhost:8080"))
我们可以修改代理,以便根据用户的输入决定何时使用搜索工具。
from typing import Union
class OrchestratorOutputSchema(BaseModel):
tool: str = Field(..., description="The tool to use: 'search' or 'chat'")
parameters: Union[SearxNGSearchTool.input_schema, CustomInputSchema] = Field(..., description="Parameters for the selected tool.")
# 修改代理逻辑以输出 OrchestratorOutputSchema
# ...
# 执行选定的工具
if response.tool == "search":
search_results = search_tool.run(response.parameters)
# 处理检索结果
else:
# 使用之前的聊天代理
pass
class SearchResultsProvider(SystemPromptContextProviderBase):
def __init__(self, search_results):
super().__init__(title="Search Results")
self.search_results = search_results
def get_info(self) -> str:
return "\n".join(self.search_results)
# After obtaining search results
context_provider = SearchResultsProvider(search_results)
agent.register_context_provider("search_results", context_provider)
通过这种集成,代理可以根据实时网络搜索数据提供响应。
Atomic Agents的一个突出特点是Atomic Assembler CLI,这是一个简化工具和代理管理的命令行工具。
受一些现代尾风库(如shadcn)的启发,在这些库中,你不需要将组件作为依赖项安装,而是在自己的源代码中对它们拥有所有权。
这意味着我们不会使用 pip 将工具作为依赖项安装,而是将其复制到我们的项目中。有两种方法可以做到这一点:
atomic-forge
文件夹中。Atomic Agents 将简洁性、模块化和开发者控制放在首位,为人工智能开发领域带来了亟需的转变。通过采用输入-进程-输出模型和原子性等可靠的编程范式,它解决了许多开发人员在使用 LangChain、CrewAI 和 AutoGen 等现有框架时遇到的挫折。