Langroid多代理开发框架
在这个大型语言模型 (LLM) 时代,对创建由这种变革性技术支持的智能应用程序有着前所未有的需求。 开发人员在复杂的应用场景中发挥LLM潜力的最佳方式是什么?
由于各种技术和实践原因(上下文长度限制、LLM 脆弱性、延迟、成本),这并不像向 LLM 系统扔一个任务并期望它完成那么简单。 我们需要的是一个有原则的编程框架,提供正确的抽象和原语集,使开发人员在构建 LLM 应用程序时提高工作效率。
1、Langroid 优雅的多代理范式
Langroid 团队(前卡内基梅隆大学/威斯康辛大学麦迪逊分校研究人员)对此有独特的看法——他们构建了一个开源 Python 框架,使用多代理编程范例来简化 LLM 应用程序开发。 Langroid 的架构建立在代理作为一等公民的基础上:它们是消息转换器,并通过消息协作完成任务。
Langroid 正在成为流行的LLM框架; 开发人员欣赏其简洁的设计和直观、可扩展的架构。 使用 Langroid 进行编程是自然的,甚至是有趣的:你配置代理并为它们配备功能(例如 LLM、矢量数据库和函数调用/工具)、连接它们并让它们通过消息进行协作。 这是一种“对话式编程”范例,适用于本地/开放和远程/专有的LLM。 重要的是,它不使用LangChain或任何其他现有的LLM框架。
代理(Agent)作为一种方便的抽象,封装了 LLM 对话的状态、对向量存储的访问以及各种工具(函数或插件)。 多代理编程框架自然符合复杂的基于 LLM 的应用程序的需求。
2、通过任务连接代理
在 Langroid 中,ChatAgent 有一组“响应者”方法,每个“实体”都有一个:LLM、人类和工具处理程序。 但是,它没有任何方法来迭代这些响应程序。 这就是 Task 类的用武之地:Task 包装了一个 Agent,并赋予它通过 Task.run()
方法循环其响应者的能力。
任务循环围绕简单的规则进行组织,这些规则控制响应者何时有资格响应、什么被视为有效响应以及任务何时完成。 任务循环最简单的示例是与人类用户的交互式聊天。 任务还使代理能够与其他代理交互:其他任务可以作为递归、分层(或 DAG)结构中的子任务添加到任务中。 从任务的角度来看,子任务只是额外的响应者,并提供与代理的“本机”响应者相同的字符串到字符串消息转换接口(函数签名)。 这是 Langroid 中任务可组合性的关键,因为子任务可以以与代理的“本机”响应程序相同的方式运行,并且遵循相同的任务编排规则。 结果是,相同的任务编排机制无缝地支持工具处理、LLM 偏差时的重试以及子任务的委派。 更多详细信息请参阅 Langroid 快速入门指南。
3、Langroid 编码体验
要开始使用 Langroid,只需将其从 pypi 安装到你的虚拟环境中即可:
pip install langroid
要直接与 OpenAI LLM 聊天,定义 LLM 配置,实例化语言模型对象并与其交互:(Langroid 也适用于非 OpenAI 本地/专有 LLM,请参阅相应教程)对于下面的示例,请确保你有 包含 OpenAI API 密钥的文件 .env
,其中包含以下行: OPENAI_API_KEY=sk-....
import langroid as lr
import langroid.language_models as lm
llm_cfg = lm.OpenAIGPTConfig() # default GPT4-Turbo
mdl = lm.OpenAIGPT(llm_cfg)
mdl.chat("What is 3+4?", max_tokens=10)
MDL不维护任何会话状态; 为此,你需要一个 ChatAgent
:
agent_cfg = lr.ChatAgentConfig(llm=llm_cfg)
agent = lr.ChatAgent(agent_cfg)
agent.llm_response("What is the capital of China?")
agent.llm_response("What about France?") # interprets based on previous msg
将 ChatAgent 包装在任务中以创建与用户的基本交互循环:
task = lr.Task(agent, name="Bot")
task.run("Hello")
让教师代理与学生代理交谈:
teacher = lr.ChatAgent(agent_cfg)
teacher_task = lr.Task(
teacher, name="Teacher",
system_message="""
Ask your student simple number-based questions, and give feedback.
Start with a question.
""",
)
student = lr.ChatAgent(agent_cfg)
student_task = lr.Task(
student, name="Student",
system_message="Concisely answer your teacher's questions."
)
teacher_task.add_sub_task(student_task)
teacher_task.run()
4、检索增强生成 (RAG) 和向量数据库
最流行的LLM应用程序之一是通过由矢量数据库支持的检索增强生成(RAG)对文档进行问答。 Langroid 有一个内置的 DocChatAgent,它融合了多种先进的 RAG 技术,布局清晰,因此可以轻松理解和扩展。
对 LanceDB 的内置支持
Langroid 使用 LanceDB 作为其 DocChatAgent 的默认向量存储。
Langroid的DocChatAgent默认使用LanceDB无服务器矢量数据库。 由于LanceDB使用文件存储,因此易于设置和使用(不需要docker或云服务),并且由于其使用Lance列格式,因此具有高性能和可扩展性。 此外,Langroid 有一个专门的 LanceDocChatAgent,它利用了 LanceDB 的独特功能,例如全文搜索、类似 SQL 的过滤和 pandas 数据帧互操作。 设置基本的 RAG 聊天机器人非常简单:
from langroid.agent.special.lance_doc_chat_agent import import (
LanceDocChatAgent, DocChatAgentConfig
)
llm_config = lm.OpenAIGPTConfig()
rag_agent_config = DocChatAgentConfig(
llm=llm_config,
doc_paths=["/path/to/my/docs"], # files, folders, or URLs.
)
rag_agent = LanceDocChatAgent(rag_agent_config)
rag_task = lr.Task(rag_agent, name="RAG")
rag_task.run()📄Chat with IMDB movies dataset
有关在多代理设置中展示工具/函数调用 + RAG 的示例,请参阅他们的快速启动 Colab 笔记本,其中显示了 2 代理系统,其中一个代理的任务是从文档中提取结构化信息并为另一个代理生成问题,代理使用 RAG 进行应答。 在 Langroid-examples 存储库中,有一个具有相同功能的脚本,下面是它的实际效果:
5、检索增强分析
LanceDB 的独特功能之一是其类似 SQL 的过滤和 Pandas 数据帧互操作性。 LLM 非常擅长生成 SQL 查询,以及 Pandas 计算代码,例如 df.groupby("col").mean()
。 这开辟了一种非常有趣的可能性,我们称之为检索增强分析:假设用户有一个包含评级、年份和类型等元数据的电影描述的大型数据集,并且想要询问:
What is the highest-rated Comedy movie about college students made after 2010?
不难想象LLM应该能够生成一个查询计划来回答这个问题,其中包括:
- 类似 SQL 的过滤器:
genre = "Comedy" and year > 2010
- Pandas 计算:
df.loc[df["rating"].idxmax()]
- 给定过滤器的重新表述的查询: `“Movie about college students”
Langroid 的多代理框架正是支持这种类型的应用程序。 LanceRAGTaskCreator 采用 LanceDocChatAgent
并添加两个附加代理:
- QueryPlannerAgent:生成查询计划
- QueryPlanCriticAgent:评价从 RAG 代理收到的查询计划和应答,以便 QueryPlanner 可以在需要时生成更好的计划。
查看 langroid-examples 存储库中的 lance-rag-movies.py 脚本来尝试一下。
原文链接:Langroid: Multi-Agent Programming framework for LLMs
BimAnt翻译整理,转载请标明出处