原文towardsdatascience.com/the-anatomy-of-an-autonomous-agent-499b42b73124本文与 Rafael Guedes 共同撰写。简介生成式 AI 的兴起是数字时代的新平台变革。它解决了从大型企业自动化到各种类型的研发和创造力的问题。预计到 2024 年全球市场将超过 650 亿美元86%的 IT 领导者预计将出现大规模的组织变革[1]。迄今为止最大的回报来自聊天机器人更通用和丰富的用例、代码协同飞行员和企业搜索。投资持续流入 AI2024 年投资了 138 亿美元比 2023 年增长了六倍[1]。此外企业正在将 AI 嵌入到其核心战略和系统中。检索增强生成RAG、微调和针对垂直应用例如医疗保健、法律的专用模型等技术正在成为主流。大型语言模型LLMs在多个方面引起了人们对 AI 的关注并开启了以新方式解决旧问题的途径。这种新方式是通过代理式 AI——一个自主智能体协作执行复杂、多步骤工作流程的框架。我们的演示展示了您如何工作和发展一个多智能体系统。它集成了三个专用智能体一个网络研究员智能体它摄取并分析互联网数据。一个转录和摘要智能体它检索并浓缩视频或文本数据为可操作的摘要。一个博客撰写智能体它将这些信息综合成一个连贯的结构。这些智能体在结构化的工作流程中运行。它们利用基础 LLMs 和日常企业堆栈中的现有工具。我们展示了组织如何简化任务减少人力并提高输出质量——同时保持对复杂场景的适应性。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/bfb5f9f6f59e097f7d2348a52ccd780a.png图 1多智能体系统作者与 DALL-E 共同创作如往常一样代码可在我们的GitHub上找到。AI 代理它们是什么AI 代理通常由 LLM 驱动是设计为自主行动以实现特定目标的系统。它们接收一个输入提示并有权访问完成某些任务所需的一组工具。输入提示可以采取多种形式。它可以是一个人类给出的简单文本提示包含要遵循的指令例如“写一篇关于 AI 代理的博客文章。”在一个多智能体系统MAS中它可以是前一个智能体的输出这也可以是文本或更结构化的数据如 JSON。代理可以访问以执行任务的工具对于其成功至关重要类似于人类。例如如果厨师没有正常工作的烤箱他们就无法烹饪美味的烤肉。在 AI 代理的情况下这些工具通常是 API允许它们连接到其他系统以执行任务。例如连接到搜索引擎以查找信息或数据库以运行查询。当构建这类代理时需要定义两个主要类 [2]代理包含四个主要组件代理使用的LLM可以是闭源如 GPT-4 或 Claude Sonnet或开源如 LLaMA 3.3 或 Mixtral 8×22。LLM 接收我们应相应设置的参数例如温度或产生的最大令牌数。LLM 的选择将取决于代理必须执行的任务。例如虽然 GPT-4 具有良好的推理能力但 Claude Sonnet 在编码方面表现更好而 GPT-4o-mini 是最快的。另一方面如果处理关键信息可能会选择开源模型以避免与第三方公司共享信息。代理的角色定义了其责任提供目的并指导代理通过其期望的任务和行为。例如代理的角色可以是处理和分析信息从数据库中检索数据或协调其他代理之间的交互。背景故事定义了代理对其环境、责任以及与其他代理或工具的交互的当前知识。它还定义了代理的当前意图即代理根据其对环境的了解和目标计划做什么。目标是代理预期要实现的内容通常转化为代理的输出。例如如果代理负责从数据库中检索数据并回答用户的问题其目标是得到答案输出就是答案。任务包含三个主要组件描述提供了对任务性质和结果的详细解释通过明确定义任务的性质和结果。它还提供了代理可能面临的特定指令和约束。例如如果任务是检索数据库中的数据则描述必须指定检索参数和任何格式要求。输出描述了任务结果应该如何呈现通过设定对输出的明确期望。它可以指示结果应该是文本、JSON、列表、HTML、SQL 或 API 的响应。最后代理负责执行任务。虽然一个 AI 智能体可以有效地执行特定任务但我们只能通过利用一组智能体来提取其全部潜力。通过相互交互和协作它们提供了可扩展性和专业化来解决复杂问题。下一节将讨论这些 MAS。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/bd22f5391cf5a47c3dbcfd6bb7e7c0da.png图 2智能体和任务定义作者提供多智能体协作系统MASMAS 由一组智能体定义也称为 Crew。每个智能体都拥有独特的技能和专门的能力。这些智能体合作解决简单任务以实现更大、更复杂的共同目标 [3]。在 Crew 中每个智能体都是一个具有独特特征、角色和特定工具的独立 LLM。类似于人类这些智能体通过将任务输出发送给后续智能体以构建在它们之上来相互沟通。根据智能体之间的交互Crew 的结构可以根据三种主要类型进行分类顺序型智能体以链的形式工作一个智能体的输出是下一个智能体的输入。通过解决较小的任务它们可以解决 Crew 被设计来解决的更大、更复杂的任务。分层型通常由一个经理和多个下属组成领导者的角色是委派、计划和管理工作完成。下属执行领导者的指令。在这种情况下我们可以有智能体同时执行任务因为并非每个智能体都有顺序依赖性。混合型这种结构在同一 Crew 中包含顺序和分层环境。通常发生在一些智能体手头有复杂任务时将它们分解成更小的任务并组建一个新的子 Crew新的智能体成为该子 Crew 的领导者同时又是原始 Crew 的下属。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/f42f195c5c8dc5f2f227c1c4cc93fc67.png图 3多智能体系统/Crew 可能的结构作者提供CrewAI创建一个 MAS 来撰写博客文章在本节中我们将创建一个多智能体系统MAS来撰写一篇关于 AI 智能体的博客文章我们知道 AI 智能体撰写关于 AI 智能体的内容可能听起来有些令人困惑但请耐心等待使用这个领域中最受欢迎的包之一CrewAI。图 4 展示了我们方法的完整架构https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/201301ca12b539b87050e68bfc2b0bbe.png图 4智能体架构作者提供我们的 Crew 由三个具有不同任务的智能体组成它们协作生成 HTML 格式的博客文章。这些智能体包括Web Researcher Agent负责连接到一个名为SearXNG的搜索引擎并检索关于AI Agents的有用且最新的 YouTube 网址。该代理及其任务定义如下researcher:role:{topic}Senior Data Researcher goal:Uncover cutting-edge developmentsin{topic}backstory:Youre a seasoned researcherwitha knackforuncovering the latest developmentsin{topic}.Knownforyour ability to find the most relevant informationandpresent itina clearandconcise manner.research_task:description:Conduct a thorough research about{topic}Make sure you findanyinterestingandrelevant youtube links given the current yearis2024.expected_output:Alistwithyoutube URLs that cover{topic}andthe respective descriptionwiththe most relevant information about{topic}.Ignoreanylinks that dont startwithhttps://www.youtube.com.agent:researcherTranscriptor Summarizer Agent连接到YouTube API从Web Search Agent提供的 URL 中检索转录。它总结转录提取主要见解和参考文献并根据视频内容提出建议。如下所示该代理及其任务定义如下summarizer:role:{topic}Summarizer goal:Summarizeandextract knowledgeandother insightfulandinteresting informationfrom{topic}backstory:Youre an expert on analyzing informationandextracting the most importantandinsightful informationina concise manner.Youre knownforyour ability to summarizeandretrive facts,references,quotesandrecommend the most useful surprising information about the{topic}.summarize_task:description:Analyse the information about the{topic}thoroughly to extract the most valuable insights,facts,andrecommendations.Adhere strictly to the provided schema when extracting informationfromtheinputcontent.Ensure that the output matches the field descriptions,typesandconstraints exactly.Ignoreanylinks that dont startwithhttps://www.youtube.com.expected_output:A jsonwitha summary of the{topic}andthe most valuable insights,facts,andrecommendations.Also add the youtube linksasreferences.agent:summarizerBlog Writer Agent是我们团队的第三个也是最后一个代理。它利用Transcriptor Summarizer生成的摘要以 HTML 格式创建关于主题的博客文章。这个 HTML 必须具有专业的外观包括一个导航栏以帮助读者浏览文章。该代理及其任务定义如下blog_writer:role:{topic}Blog Writer goal:Create detailed blog posts based on{topic}research findings backstory:Youre a meticulous writerwitha keen eyefordetail.Youre knownforyour ability to turncomplextopics into clearandconcise blog posts,making it easyforothers to understandandact on the information you provide.write_task:description:Review the context you gotandexpand each topic into a full sectionfora blog post.Make sure the blog postisdetailedandcontainsanyandallrelevant information.The blog post must contain an introduction,a body,a code exampleanda conclusion section.expected_output:A fully-fledged blog postwiththe main topics,each presentedasa complete section of information.Format itasHTML without using.使其看起来像专业的技术博客网站 包括一个导航栏、菜单和样式。将 YouTube 链接作为可点击的参考包含在内 文本并在最后。 agent:blog_writer py The definitions above must be definedintwo different YAML files,oneforagents(*agents.yaml*)andanotherfortasks(*taks.yaml*).Once this process has been done,itistime to create the tools agents use to perform their tasks.In ourcase,only the**Blog Writer**doesnotneedanytool,the**Researcher**needs the search engine,whilethe**TranscriptorandSummarizer**needs the connection to the YouTube API.**Search Engine([SearXNG](https://search.zaai.ai))***Itisgood practice to define theinputschema when defining the tools.As showninthe code snippet below,our search engine tool expects to receive the search queryandthe number of results to retrieve.*Then,we must define the tool itself.The**__init__**function sets the search engine to use,whilethe _run function specifies how the agent will use the tool.It basically searches YouTube videos about the topic the user requested,inthiscase,*AI Agents*.from crewai.tools import BaseToolfrom typing import Type, Optional, List, Dictfrom pydantic import BaseModel, Field, PrivateAttrfrom langchain_community.utilities import SearxSearchWrapperclass SearxSearchToolInput(BaseModel):SearxSearchTool 的输入模式。” query: str Field(..., description搜索查询。) num_results: int Field(10, description要检索的结果数量。)class SearxSearchTool(BaseTool):name: str searx_search_tool description: str ( 一个使用 Searx 元搜索引擎进行搜索的工具。 指定一个查询并可选择通过引擎、类别或结果数量进行限制。 ) args_schema: Type[BaseModel] SearxSearchToolInput _searx_wrapper: SearxSearchWrapper PrivateAttr() def __init__(self, searx_host: str, unsecure: bool False): 使用 SearxSearchWrapper 初始化 SearxSearchTool。” super().__init__() self._searx_wrapper SearxSearchWrapper( searx_hostsearx_host, unsecureunsecure ) def _run( self, query: str, num_results: int 10, ) - List[Dict]: 使用 Searx API 进行搜索。” try: results self._searx_wrapper.results( queryquery :youtube, num_resultsnum_results, ) return results except Exception as e: return [{Error: str(e)}]**YouTube API***This tool follows the same principle by first defining theinputschema,which consists of the YouTube URLandthe language we want the transcription to bein.*We also define an output schema wherenotonly the transcriptionisreturned but also the duration of the video.*Finally,the tool itself consists of extracting the video IDfromthe URLandconnecting to the Youtube API to retrieve the transcription,asseeninthe _run function.from typing import Type, Optionalfrom pydantic import Field, BaseModelfrom youtube_transcript_api import (NoTranscriptFound, TranscriptsDisabled, YouTubeTranscriptApi,)from crewai.tools import BaseToolclass YouTubeTranscriptToolInputSchema(BaseModel): 使用 YouTube 转录 API 获取 YouTube 视频转录的工具。 返回包含文本、开始时间和持续时间的转录。 video_url: str Field( ..., description要获取转录的 YouTube 视频的 URL。 ) language: Optional[str] Field( None, description转录的语言代码例如en表示英语。 )class YouTubeTranscriptToolOutputSchema(BaseModel): YouTubeTranscriptTool 的输出模式。包含转录文本、持续时间、评论和元数据。 transcript: str Field(..., descriptionYouTube 视频的转录文本。) duration: float Field( ..., descriptionYouTube 视频的持续时间秒。 )class YouTubeTranscriptTool(BaseTool): 工具用于使用 YouTube 转录 API 获取 YouTube 视频的转录文本。 Attributes: input_schema (YouTubeTranscriptToolInputSchema): 输入数据的模式。 output_schema (YouTubeTranscriptToolOutputSchema): 输出数据的模式。 name: str youtube_transcript_tool description: str ( 一个用于执行 YouTube 转录提取的工具。 指定 YouTube 视频的 URL 和可选的语言代码。 ) args_schema: Type[BaseModel] YouTubeTranscriptToolInputSchema def __init__(self): 初始化 YouTubeTranscriptTool。 super().__init__() def _run( self, video_url: str, language: Optional[str] None ) - YouTubeTranscriptToolOutputSchema: 使用给定的参数运行 YouTubeTranscriptTool。 Args: video_url (list[str]): 要获取转录文本的 YouTube 视频 URL 列表。 language (Optional[str]): 转录的语言代码例如en表示英语。 Returns: YouTubeTranscriptToolOutputSchema: 工具的输出遵循输出模式。 Raises: Exception: 如果获取转录文本失败。 video_id self.extract_video_id(video_url) try: if language: transcripts YouTubeTranscriptApi.get_transcript( video_id, languages[language] ) else: transcripts YouTubeTranscriptApi.get_transcript(video_id) except (NoTranscriptFound, TranscriptsDisabled) as e: raise Exception( f无法获取视频{video_id}的转录文本{str(e)} ) transcript_text .join([transcript[text] for transcript in transcripts]) total_duration sum([transcript[duration] for transcript in transcripts]) return YouTubeTranscriptToolOutputSchema( transcripttranscript_text, durationtotal_duration, ) staticmethod def extract_video_id(url: str) - str: 从 YouTube URL 中提取视频 ID。 Args: url (str): YouTube 视频的 URL。 Returns: str: 提取的视频 ID。 return url.split(v)[-1].split(amp;)[0]With agents,tasks,andtools defined,we can now build our Crewandsettheir dependencies.As shown below,we declare the agents by using the agent decorator,togetherwiththe respective toolsandtheir components(role,goalandbackstory).For tasks,we use the task decoratoranddefine their components(description,outputandagent).Finally,we define how they should collaborate,i.e.,they workina sequential manner Process.sequential.import osfrom crewai import Agent, Crew, Process, Taskfrom crewai.project import CrewBase, agent, crew, taskfrom crew_zaai.src.crew_zaai.tools.searx import SearxSearchToolfrom crew_zaai.src.crew_zaai.tools.youtube import YouTubeTranscriptToolCrewBaseclass CrewZaai:CrewZaai crew agents_config config/agents.yaml tasks_config config/tasks.yaml agent def researcher(self) - Agent: search_tool SearxSearchTool( searx_hostos.getenv(SEARXNG_BASE_URL), unsecureFalse ) return Agent( configself.agents_config[researcher], tools[search_tool], verboseTrue ) agent def summarizer(self) - Agent: youtube_tool YouTubeTranscriptTool() return Agent( configself.agents_config[summarizer], tools[youtube_tool], verboseTrue ) agent def blog_writer(self) - Agent: return Agent(configself.agents_config[blog_writer], verboseTrue) task def research_task(self) - Task: return Task( configself.tasks_config[research_task], ) task def summarizer_task(self) - Task: return Task( configself.tasks_config[summarize_task], ) task def write_task(self) - Task: return Task( configself.tasks_config[write_task], output_fileassets/report.html ) crew def crew(self) - Crew: 创建 CrewZaai 团队 return Crew( agentsself.agents, tasksself.tasks, processProcess.sequential, verboseTrue, )CrewBaseclass CrewZaai:CrewZaai 团队The last stepisto make our agents work together to write the blog post by kicking off our Crew.import sysimport warningsfrom crew_zaai.src.crew_zaai.crew import CrewZaaifrom dotenv import load_dotenvwarnings.filterwarnings(“ignore”, categorySyntaxWarning, module“pysbd”)load_dotenv()inputs {“topic”: “AI Agents”}CrewZaai().crew().kickoff(inputsinputs)By default,the LLM usedisGPT-4o-minifromOpenAI;therefore,the OpenAI API key must besetasan environment variable.We also need tosetthe API keyforYouTube(check this[link](https://developers.google.com/youtube/v3/getting-started)to create your key)andthe URLforthe search engine.Our .envfilemust contain the following variables:YOUTUBE_API_KEYOPENAI_API_KEYSEARXNG_BASE_URLhttps://search.zaai.ai在运行脚本后我们团队的输出存储在一个名为 assets/ 的文件夹中其截图如下 https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/64b2be1f6cb64066ef34ae464a8fd301.png 图 5关于 AI 代理的博客文章图片由作者提供 ## 结论 在这篇文章中我们探讨了当前的热门话题代理式人工智能。 代理式人工智能是行业向更自主和协作的工作流程转变无需人工干预。它承诺将人类从无聊和简单的任务中解放出来让他们能够专注于更有价值的任务。 我们展示了一个简单的用例其中 MAS 在没有人工干预的情况下生成了一篇博客文章。代理在网络上搜索内容从最近的 YouTube 视频中获取转录构建想法并生成一个包含输出的 HTML 页面。我们现在可以使用这些代理来处理新的和更复杂的应用场景。例如我们可以帮助客户使用文本和图像在网站上搜索产品利用多模态能力。我们还可以为课程教育创建个性化的课程表或审查文件并评估其合规性法律。 在正确的投资和策略下人工智能将继续设定生产力和创造力的新标准。可能性是无限的探索它们的时间就在现在。 ## 关于我 连续创业者和 AI 领域的领导者。我为商业开发 AI 产品并对专注于 AI 的初创企业进行投资。 [ZAAI 创始人](http://zaai.ai/) | [LinkedIn](https://www.linkedin.com/in/luisbrasroque/) | [X/Twitter](https://x.com/luisbrasroque) ## 参考文献 [1] Menlo Ventures. (2024). *企业中生成式 AI 的现状*. 从 [menlovc.com/2024-the-state-of-generative-ai-in-the-enterprise/](https://menlovc.com/2024-the-state-of-generative-ai-in-the-enterprise/) 获取. [2] Talebirad, Y., Nadiri, A. (2023). *多智能体协作利用智能 LLM 代理的力量*. arXiv:2306.03314. [3] 汉斯张琪姚毅金伟徐振和陈晨. (2024). *LLM 多智能体系统挑战与开放问题*. arXiv:2402.03578.