1,290
社区成员
这篇文章最初发表在 NVIDIA 技术博客上。有关此类的更多内容,请参阅最新的 生成式人工智能 新闻和教程。
在构建 大型语言模型 (LLM) 智能体应用时,您需要四个关键组件:智能体核心、内存模块、智能体工具和规划模块。无论您是设计问答智能体、多模态智能体还是智能体群,您都可以考虑许多实现框架 — 从开源到生产就绪。有关更多信息,请参阅 LLM 代理简介。
对于首次尝试开发 LLM 代理的用户,本文提供了以下内容:
你们大多数人可能已经阅读过有关 LangChain 或 LLaMa-Index 代理的文章。以下是目前可用的一些实现框架:
那么,我推荐哪一种?答案是,“这取决于”。
单代理框架
社区构建了多个框架来推进 LLM 应用开发生态系统,为您提供了开发代理的简单路径。热门框架的一些示例包括 LangChain、LlamaIndex 和 Haystack.这些框架提供通用代理类、连接器和内存模组功能、第三方工具的访问权限,以及数据检索和提取机制。
选择哪种框架在很大程度上取决于您的工作流的细节和要求。在必须构建具有有向无环图 (DAG) (如逻辑流)或具有独特属性的复杂代理的情况下,这些框架为您自己的自定义实现提供了一个很好的提示参考点和通用架构。
多智能体框架
您可能会问:“多智能体框架有何不同?”简短回答是“世界”类。要管理多个智能体,您必须构建世界,或者说构建环境中它们彼此交互的环境、用户和环境中的工具。
这里的挑战在于,对于每个应用程序,所面对的世界都将是不同的。您需要一个定制的工具包来构建模拟环境,以及一个能够管理世界状态并具备代理通用类的工具包。您还需要一个用于管理代理之间流量的通信协议。 OSS 框架的选择取决于您所构建的应用程序类型以及所需的自定义程度。
您可以使用大量资源和材料来激发您对智能体的可能性的思考,但以下资源是涵盖智能体整体精神的良好起点:
如果您正在寻找更多阅读材料,由 LLM 提供支持的优秀智能体 列出了许多有用信息。如果您有特定的查询,请在此帖子下发表评论。
在本教程中,您构建了一个问答 (QA) 代理,可帮助您处理数据。
为了证明即使是一个简单的坐席也能应对复杂的挑战,您可以构建一个能够从财报电话会议中提取信息的坐席。您可以参考通话记录。图 1 展示了财报电话会议的一般结构,这将帮助您理解本教程中使用的文件。
图 1.收益通知的概念分解
在本文结束时,您构建的智能体将回答如下复杂的分层问题:
图 2.您正在构建的智能体的问答示例
正如本系列的第 1 部分所介绍的,智能体包含四个组件:
要构建 LLM 代理,您需要以下工具:
通过此 LLM 代理,您将能够回答以下问题:“在 2024 年第一季度到 2024 年第二季度期间,收入增长了多少?”基本上,我们将以下三个问题合二为一:
答案是,您必须构建一个问题分解模块:
decomp_template = """GENERAL INSTRUCTIONS You are a domain expert. Your task is to break down a complex question into simpler sub-parts. USER QUESTION {{user_question}} ANSWER FORMAT {"sub-questions":["<FILL>"]}""
如您所见,分解模块促使 LLM 将问题分解为不太复杂的部分。图 3 展示了答案。
图 3.规划模块和原型设计分解
接下来,您必须构建一个内存模块,以跟踪被问到的所有问题,或者仅保留所有子问题和上述问题答案的列表。
class Ledger: def __init__(self): self.question_trace = [] self.answer_trace = []
您可以使用由两个列表组成的简单分类帐来执行此操作:一个用于跟踪所有问题,另一个用于跟踪所有答案。这有助于代理记住其已回答但尚未回答的问题。
评估心理模型
在构建智能体核心之前,请评估您目前拥有的核心:
此时,您可以将它们连接在一起,看看它是否可以用作心理模型(图 4)。
template = """GENERAL INSTRUCTIONS Your task is to answer questions. If you cannot answer the question, request a helper or use a tool. Fill with Nil where no tool or helper is required. AVAILABLE TOOLS - Search Tool - Math Tool AVAILABLE HELPERS - Decomposition: Breaks Complex Questions down into simpler subparts CONTEXTUAL INFORMATION <No previous questions asked> QUESTION How much did the revenue grow between Q1 of 2024 and Q2 of 2024? ANSWER FORMAT {"Tool_Request": "<Fill>", "Helper_Request "<Fill>"}"""
图 4 显示了收到的 LLM 答案。
图 4.将所有模块组合在一起
您可以看到,LLM 请求使用搜索工具,这是一个合乎逻辑的步骤,因为答案很可能在语料库中。也就是说,您知道所有转录都不包含答案。在下一步(图 5)中,您提供来自 RAG 管道的输入,以确定答案不可用,因此代理随后决定将问题分解为更简单的子部分。
图 5.为子上下文问题添加答案
通过本练习,您确认逻辑的核心机制是可靠的。LLM 会根据需要选择工具和辅助工具。
现在,只需将其整齐地包装在 Python 函数中,该函数看起来类似于以下代码示例:
def agent_core(question): answer_dict = prompt_core_llm(question, memory) update_memory() if answer_dict[tools]: execute_tool() update_memory() if answer_dict[planner]: questions = execute_planner() update_memory() if no_new_questions and no tool request: return generate_final_answer(memory)
您刚刚看到了智能体核心的示例,还剩下什么?智能体核心不仅仅是将所有组件拼接在一起。您必须定义智能体执行流的机制。本质上有三个主要选择:
线性求解器
这就是我之前讨论过的执行类型。有一个线性解决方案链,代理可以在其中使用工具并进行一级规划。虽然这是一个简单的设置,但真正的复杂和微妙的问题通常需要分层思考。
单线程递归求解器
您还可以构建一个递归求解器,该求解器构建一个问题和答案树,直到原始问题得到解答。此树在深度优先遍历中求解。以下代码示例展示了逻辑:
def Agent_Core(Question, Context): Action = LLM(Context + Question) if Action == "Decomposition": Sub Questions = LLM(Question) Agent_Core(Sub Question, Context) if Action == "Search Tool": Answer = RAG_Pipeline(Question) Context = Context + Answer Agent_Core(Question, Context) if Action == "Gen Final Answer”: return LLM(Context) if Action == "<Another Tool>": <Execute Another Tool>
多线程递归求解器
您可以为树上的每个节点分离并行执行线程,而不是以迭代方式求解树。此方法增加了执行复杂性,但由于可以并行处理 LLM 调用,因此会产生巨大的延迟优势。
恭喜!您现在已经掌握了构建相当复杂的智能体的知识!下一步是根据您的问题调整前面讨论的原则。
要为 LLM 代理开发更多工具,请参阅 NVIDIA 深度学习培训中心 (DLI)。如需为您的用例构建、自定义和部署 LLM,请参阅 NVIDIA NeMo 框架。