构建你的第一个AI Agent(它实际上会提升你作为AI工程师的能力)

​编辑

AI agent 可以干什么:

  • 执行操作并从其环境中获取反馈
  • 思考并基于反馈改进其行动
  • 努力完成目标,而不是等待进一步的提示(除非有明确要求)
  • 与其他代理合作工作

一个Agent可以建立在大型语言模型(LLM)或其他神经网络之上,并且可以使用强化学习(RL)或基于规则的系统等。

我们用什么构建Agent

我们开始使用CrewAI构建我们的AI代理。它是一个开源的Python框架,帮助我们使用单个或多个代理构建AI系统,这些代理可以协同工作以解决复杂任务。

你可能已经看过很多关于构建代理的LangChain教程,但我们在这个教程中使用CrewAI,因为LangChain的语法非常特殊,,很快就会变得难以理解。​

CrewAI 使用起来更加简单,发展迅速,拥有一个活跃且乐于助人的社区,并且拥有令人惊叹的文档(令人惊讶的是,这些文档是由基于 CrewAI 构建的代理编写的)。

首先,我们需要了解以下六个术语:

1. Crew

这是管理AI代理并帮助他们协作以产生预期输出的顶级组织。

  1. Agents

这些是基于LLM的自主实体,具有特定的角色。它们可以做出自主决策,使用工具,并与其他代理一起解决问题。

  1. Tasks

这些是人工智能代理正在工作的子目标。

  1. Tools

这些是使代理能够执行各种任务的组件,例如网络搜索、网络抓取、文件管理等等。

  1. Memory

这是一个系统,它让AI代理记住他们的短期和长期过去互动,以改善他们的解决问题的能力。

  1. Process

这是工作流管理系统,它定义了代理如何互动和协作以高效工作。

​编辑

让我们开始第一个Agent

基于"做中学"的理念,以ArXiv为例构建一个研究团队

你将拥有一个多代理系统,该系统将致力于实现以下目标:

  1. 在给定日期搜索 ArXiv 上所有关于人工智能的研究论文。
  2. 从这些论文中选出最重要的 10 篇。
  3. 以格式良好的 HTML 文件返回结果。
  4. 在步骤之间请向我们反馈,以便其功能能够得到良好的监控,并在需要时进行调整。

步骤1:安装软件包

复制代码
pip install crewai crewai_tools arxiv

步骤2:设置环境变量

创建一个OpenAI API密钥,并将其设置为环境变量,如下所示,与openai api使用方式兼容的方式也是可以的。

CrewAI 默认使用 gpt-4o-mini 来构建代理。我在下面的代码中明确展示了这一点,如果你愿意,可以使用比它更小、更便宜或更强大的模型。

lua 复制代码
# Set up environment variables
import os

openai_api_key = "YOUR_API_KEY"
os.environ["OPENAI_API_BASE"] = 'https://api.openai.com/v1' 
os.environ["OPENAI_API_KEY"] = openai_api_key
os.environ["OPENAI_MODEL_NAME"] = "gpt-4o-mini"

步骤3:构建自定义ArXiv搜索工具

CrewAI 附带 多种工具,您可以直接使用。这些工具可以轻松地从我们之前安装的crewai_tools包中导入和使用,如下所示。

ini 复制代码
# Importing crewAI tools
from crewai_tools import (
    DirectoryReadTool,
    FileReadTool,
    SerperDevTool,
    WebsiteSearchTool
)

# Set up API keys for Serper
os.environ["SERPER_API_KEY"] = "Your Key" # serper.dev API key

# Instantiate tools
docs_tool = DirectoryReadTool(directory='./your-directory') # Tool for reading documents from a specified directory
file_tool = FileReadTool() # Tool for reading individual files
search_tool = SerperDevTool() # Tool for performing web searches using the Serper API
web_rag_tool = WebsiteSearchTool() # Tool for searching and extracting information from websites

您还可以轻松地将LangChain的工具CrewAI集成并使用

要创建自定义工具,我们需要继承自BaseTool类,并定义必要的属性,包括用于输入验证的args_schema_run方法。

Pydantic 用于定义我们工具的输入模式。

python 复制代码
from typing import Type, List
from pydantic import BaseModel, Field 
from crewai.tools import BaseTool 

import arxiv
import time
import datetime

class FetchArxivPapersInput(BaseModel):
    """Input schema for FetchArxivPapersTool."""
    target_date: datetime.date = Field(..., description="Target date to fetch papers for.")

class FetchArxivPapersTool(BaseTool):
    name: str = "fetch_arxiv_papers"
    description: str = "Fetches all ArXiv papers from selected categories submitted on the target date."
    args_schema: Type[BaseModel] = FetchArxivPapersInput

    def _run(self, target_date: datetime.date) -> List[dict]:
        # List of AI-related categories. 
        # You can also include ["cs.AI", "cs.LG", "cs.CV", "cs.MA", "cs.RO"]
        AI_CATEGORIES = ["cs.CL"]

        # Define the date range for the target date
        start_date = target_date.strftime('%Y%m%d%H%M')
        end_date = (target_date + datetime.timedelta(days=1)).strftime('%Y%m%d%H%M')

        # Initialize the ArXiv client
        client = arxiv.Client(
            page_size=100,  # Fetch 100 results per page
            delay_seconds=3  # Delay between requests to respect rate limits
        )

        all_papers = []

        for category in AI_CATEGORIES:
            print(f"Fetching papers for category: {category}")

            search_query = f"cat:{category} AND submittedDate:[{start_date} TO {end_date}]"

            search = arxiv.Search(
                query=search_query,
                sort_by=arxiv.SortCriterion.SubmittedDate,
                max_results=None  # Fetch all results
            )

            # Collect results for the category
            category_papers = []
            for result in client.results(search):
                category_papers.append({
                    'title': result.title,
                    'authors': [author.name for author in result.authors],
                    'summary': result.summary,
                    'published': result.published,
                    'url': result.entry_id
                })

                # Delay between requests to respect rate limits
                time.sleep(3)

            print(f"Fetched {len(category_papers)} papers from {category}")
            all_papers.extend(category_papers)

        return all_papers

我们初始化此工具如下:

ini 复制代码
arxiv_search_tool = FetchArxivPapersTool()

步骤4:创建代理

当要求代理人扮演一个角色时,他们工作得更好。基于这一事实,每个代理都初始化为:

  • Role
  • Goal
  • Backstory

我们定义了两个代理来工作于我们的目标:

1. ArXiv Researcher

ini 复制代码
# Agent 1: ArXiv Researcher

researcher = Agent(
    role = "Senior Researcher",
    goal = "Find the top 10 papers from the search results from ArXiv on {date}."
            "Rank them appropirately.",
    backstory = "You are a senior researcher with a deep understanding of all topics in AI and AI research."
                "You are able to identify the best research papers based on the title and abstract.",
    verbose = True,
    tools = [arxiv_search_tool],
)

参数 verbose 设置为 True,以查看有关代理执行的详细日志。参数 tools 指定了人工智能代理在执行过程中可以使用哪些工具。

  1. Frontend Engineer
ini 复制代码
# Agent 2: Frontend Engineer

frontend_engineer = Agent(
    role = "Senior Frontend & AI Engineer",
    goal = "Compile the results into a HTML file.",
    backstory = "You are a competent frontend engineer writing HTML and CSS with decades of experience."
                "You have also been working with AI for decades and understand it well.",
    verbose = True,
)

Agent 类还包含一个可选参数 llm,如果您愿意,可以为此类不同的代理选择不同的 LLM。

步骤5:创建任务

你一定在想,为什么我们不使用一个单一的LLM作为代理,并给它所有完成目标所需的工具。原因在于,将一个目标分解为子目标或任务 ,并让每个AI代理专注于一个任务,能够带来更好的结果。每个任务都指定了一个描述和一个预期输出。参数 agent 指定了执行特定任务所需的代理。

我们将目标分解为两个任务,如下所示:

  1. 'ArXiv Researcher' 代理的研究任务
ini 复制代码
# Task for ArXiv Researcher

research_task = Task(
    description = (" Find the top 10 research papers from the search results from ArXiv on {date}."),
    expected_output = (
        "A list of top 10 research papers with the following information in the following format:"
        "- Title"
        "- Authors"
        "- Abstract"
        "- Link to the paper"
    ),
    agent = researcher,
    human_input = True,
)

参数 human_input 被设置为 True,以确保代理在完成任务后能够接收我们对结果的反馈。

'Frontend Engineer' 代理的报告任务

ini 复制代码
# Task for Frontend Engineer

reporting_task = Task(
    description = ("Compile the results into a detailed report in a HTML file."),
    expected_output = (
        "An HTML file with the results in the following format:"
        "Top 10 AI Research Papers published on {date}"
        "- Title (which on clicking opens the paper in a new tab)"
        "- Authors"
        "- Short summary of the abstract (2-4 sentences)"
    ),
    agent = frontend_engineer,
    context = [research_task],
    output_file = "./ai_research_report.html",
    human_input = True,
)

参数 context 确保此任务依赖于 research_task 的输出,并将其用作上下文。参数 output_file 指定了任务结果必须保存的位置(输出文件的名称和位置)。

步骤6:创建Crew

在这一步中,我们使用初始化的代理和任务创建一个团队。

ini 复制代码
arxiv_research_crew = Crew(
    agents = [researcher, frontend_engineer],
    tasks = [research_task, reporting_task],
    verbose = True,
)

请注意,Crew 有一个名为 Process 的可选参数,其默认值为 sequential

这确保每个代理依次运行。但是我们可以将其值设置为分层,并定义另一个代理,该代理充当管理者,根据其他代理的能力、审查输出并评估任务完成情况来监督和分配任务。

以下是我们的团队Crew整体情况:

​编辑

步骤7:运行团队并对其结果进行反馈

在定义代理和任务时,我们使用了占位符"date"。我们可以通过使用kickoff方法运行crew时传递此占位符的值,如下所示。

ini 复制代码
crew_inputs = {
    "date" : "2025-03-12"
}

result = arxiv_research_crew.kickoff(inputs = crew_inputs)

And there we go!

​编辑

步骤8:改进crew

您应该意识到,由于在过程中使用了大量标记,使用 LLM 作为代理可能会很昂贵。

以下是一些关于如何改进这一多代理系统的建议:

  • 使用开源模型替代 GPT-4o-mini:可以使用 Ollama 等开源模型来替代 GPT-4o-mini,从而降低成本。
  • 不同角色使用不同 LLM:可以根据不同角色的需求,使用不同大小的 LLM。例如,使用更大的模型进行研究,使用更小的模型进行结果报告。
  • 建立分层团队:可以建立一个分层团队,其中不同角色负责搜索不同的 ArXiv 发表类别。
  • 改进搜索和检索工具:可以改进搜索和检索工具,以从研究论文中提取最相关的数据字段,从而节省 LLM 令牌。
  • 标准化输出文件布局:可以标准化输出文件的布局,例如统一标题格式、段落间距等。

关注公众号:智汇说 学习交流

相关推荐
win4r1 小时前
🚀多维度测评OpenAI最新GPT-4.1模型!百万token上下文窗口!编程能力和指令遵循能力大幅提升!Cline+GPT-4.1十分钟零代码开发macOS
chatgpt·openai·ai编程
十分钟空间3 小时前
MCP(Model Context Protocol)技术与项目集成指南
ai编程·mcp
vil du4 小时前
c# AI编程助手 — Fitten Code
开发语言·c#·ai编程
黑心萝卜三条杠8 小时前
单目3D目标检测新突破:MonoTAKD如何用助教模型解决深度模糊难题
ai编程
玲小珑8 小时前
5分钟学会LLM开发系列教程(五)Agent的最终形态LangGraph
langchain·node.js·ai编程
知了一笑10 小时前
DeepSeekV3:写代码很强了
大模型·ai编程·deepseek
Goboy10 小时前
Java版的深度学习 · 手撕 DeepLearning4J实现手写数字识别 (附UI效果展示)
llm·aigc·ai编程
Goboy10 小时前
用AI从零理解推荐系统
llm·aigc·ai编程
谦行10 小时前
AI 基础知识从 -1 到 0.1
机器学习·aigc·ai编程