Skip to main content

· 9 min read
Shaokun Zhang
Jieyu Zhang

AgentOptimizer 的整体结构

TL;DR: 介绍一种新的类 AgentOptimizer,用于在 LLM 作为服务的时代训练 LLM agents。 AgentOptimizer 能够根据历史对话和表现,提示 LLMs 迭代优化 AutoGen agents 的功能/技能。

更多信息请参考:

论文: https://arxiv.org/abs/2402.11359.

Notebook: https://github.com/microsoft/autogen/blob/main/notebook/agentchat_agentoptimizer.ipynb.

引言

在传统的机器学习流程中,我们通过更新模型在训练集上的损失来训练模型,而在 LLM agents 时代,我们应该如何训练一个 agent 呢? 在这里,我们迈出了训练 agent 的第一步。受到 OpenAI 提供的 function calling 功能的启发, 我们将模型的权重与 agent 的功能/技能进行类比,并根据 agent 在训练集上的历史表现来更新其功能/技能。 具体来说,我们提出使用 function calling 功能来将优化 agent 功能的操作表示为一组函数调用,以支持迭代地添加、修改和删除现有的函数。 我们还包括了回滚和提前停止两种策略,以简化训练过程,克服训练时性能下降的问题。 作为一种主动训练 agent 的方式,我们的方法有助于增强 agent 的能力,而无需访问 LLM 的权重。

AgentOptimizer

AgentOptimizer 是一个用于优化 agent 的类,通过改进其函数调用来提升其性能。 它包含三个主要方法:

  1. record_one_conversation:

该方法记录 agent 在解决一个问题时的对话历史和表现。 它包括两个输入参数:conversation_history (List[Dict]) 和 is_satisfied (bool)。 conversation_history 是一个字典列表,可以从 AgentChat 类的 chat_messages_for_summary 方法中获取。 is_satisfied 是一个布尔值,表示用户是否对解决方案感到满意。如果为 None,则会要求用户输入满意度。

示例:

optimizer = AgentOptimizer(max_actions_per_step=3, llm_config = llm_config)
# ------------ 解决一个问题的代码 ------------
# ......
# -------------------------------------------------
history = assistant.chat_messages_for_summary(UserProxy)
optimizer.record_one_conversation(history, is_satisfied=result)
  1. step():

step() 是 AgentOptimizer 的核心方法。 在每次优化迭代中,它将返回两个字段register_for_llm和register_for_executor,随后用于更新assistant和UserProxy代理。

register_for_llm, register_for_exector = optimizer.step()
for item in register_for_llm:
assistant.update_function_signature(**item)
if len(register_for_exector.keys()) > 0:
user_proxy.register_function(function_map=register_for_exector)
  1. reset_optimizer:

这个方法将优化器重置为初始状态,当你想从头开始训练代理时非常有用。

AgentOptimizer包括在返回register_for_llm和register_for_exector之前检查(1)函数的有效性和(2)代码实现的机制。 此外,它还包括检查每个更新是否可行的机制,例如避免由于幻觉而删除当前函数中不存在的函数。

优化过程的伪代码

优化过程如下所示:

optimizer = AgentOptimizer(max_actions_per_step=3, llm_config = llm_config)
for i in range(EPOCH):
is_correct = user_proxy.initiate_chat(assistant, message = problem)
history = assistant.chat_messages_for_summary(user_proxy)
optimizer.record_one_conversation(history, is_satisfied=is_correct)
register_for_llm, register_for_exector = optimizer.step()
for item in register_for_llm:
assistant.update_function_signature(**item)
if len(register_for_exector.keys()) > 0:
user_proxy.register_function(function_map=register_for_exector)

给定一个准备好的训练数据集,代理们迭代地解决训练集中的问题,以获取对话历史和统计信息。 然后使用AgentOptimizer改进函数。每次迭代可以看作是一次训练步骤,类似于传统的机器学习,其中优化元素是代理所拥有的函数。 经过EPOCH次迭代,代理预计将获得更好的函数,这些函数可能在未来的任务中使用。

AgentOptimizer背后的实现技术

为了从AgentOptimizer中获得稳定和结构化的函数签名和代码实现, 我们利用OpenAI提供的函数调用能力,将操作函数的动作表示为一组函数调用。 具体而言,我们引入了三个函数调用来在每个步骤中操作当前函数:add_functionremove_functionrevise_function。 这些调用分别在现有函数列表中添加、删除和修改函数。 这种做法可以充分利用GPT-4的函数调用能力,并输出具有更稳定签名和代码实现的结构化函数。 下面是这些函数调用的JSON模式:

  1. add_function:添加一个可能在未来任务中使用的新函数。
ADD_FUNC = {
"type": "function",
"function": {
"name": "add_function",
"description": "在对话的上下文中添加一个函数。必须声明所需的 Python 包。函数的名称必须与您生成的代码中的函数名称相同。",
"parameters": {
"type": "object",
"properties": {
"name": {"type": "string", "description": "代码实现中函数的名称。"},
"description": {"type": "string", "description": "函数的简短描述。"},
"arguments": {
"type": "string",
"description": '以字符串形式编码的参数的 JSON 模式。请注意,JSON 模式仅支持特定类型,包括字符串、整数、对象、数组、布尔值(不支持浮点数类型)。例如:{ "url": { "type": "string", "description": "URL" }}。在使用数组类型时,请避免出现错误 "array schema missing items"。',
},
"packages": {
"type": "string",
"description": "函数导入的包名称列表,需要在调用函数之前使用 pip 安装。这解决了 ModuleNotFoundError。它应该是字符串,而不是列表。",
},
"code": {
"type": "string",
"description": "Python 中的实现。不要包含函数声明。",
},
},
"required": ["name", "description", "arguments", "packages", "code"],
},
},
}
  1. revise_function: 根据对话历史和性能,修改当前函数列表中的一个现有函数(代码实现,函数签名)。
REVISE_FUNC = {
"type": "function",
"function": {
"name": "revise_function",
"description": "在对话的上下文中修改函数。必须声明必要的Python包。函数的名称必须与您生成的代码中的函数名称相同。",
"parameters": {
"type": "object",
"properties": {
"name": {"type": "string", "description": "代码实现中函数的名称。"},
"description": {"type": "string", "description": "函数的简短描述。"},
"arguments": {
"type": "string",
"description": '以字符串形式编码的参数的JSON模式。请注意,JSON模式仅支持特定类型,包括字符串、整数、对象、数组、布尔值(不支持浮点类型)。例如:{ "url": { "type": "string", "description": "URL" }}。在使用数组类型时,请避免出现错误\'array schema missing items\'。',
},
"packages": {
"type": "string",
"description": "函数导入的包名称列表,需要在调用函数之前使用pip安装。这解决了ModuleNotFoundError。它应该是字符串,而不是列表。",
},
"code": {
"type": "string",
"description": "Python中的实现。不要包含函数声明。",
},
},
"required": ["name", "description", "arguments", "packages", "code"],
},
},
}
  1. remove_function: 从当前函数列表中删除一个现有函数。用于删除未来任务中不需要的函数(冗余函数)。
REMOVE_FUNC = {
"type": "function",
"function": {
"name": "remove_function",
"description": "在对话的上下文中删除一个函数。一旦删除一个函数,助手将不会在未来的对话中使用该函数。",
"parameters": {
"type": "object",
"properties": {
"name": {"type": "string", "description": "代码实现中函数的名称。"}
},
"required": ["name"],
},
},
}

限制和未来工作

  1. 目前,它仅支持优化一个典型的用户代理和助手代理对。我们将在未来的工作中使此功能更通用,以支持其他代理类型。
  2. AgentOptimizer的当前实现仅对OpenAI GPT-4模型有效。将此功能/概念扩展到其他LLM是下一步。

· 16 min read
Victor Dibia
Gagan Bansal
Saleema Amershi

AutoGen Studio Playground View: 使用多智能体解决生成带有图像的 PDF 文档的任务。

AutoGen Studio:使用多智能体解决生成带有图像的 PDF 文档的任务。

TL;DR

为了帮助您快速原型化多智能体解决方案,我们推出了 AutoGen Studio,这是一个由 AutoGen 提供支持的界面。它可以让您:

  • 通过点选和拖放界面(例如,您可以选择两个智能体的参数,它们将进行通信以解决您的任务)来声明性地定义和修改智能体和多智能体工作流程。
  • 使用我们的用户界面与指定的智能体创建聊天会话并查看结果(例如,查看聊天历史记录、生成的文件和所需时间)。
  • 明确地为您的智能体添加技能并完成更多任务。
  • 将您的会话发布到本地画廊。

有关更多详细信息,请参阅官方 AutoGen Studio 文档此处

AutoGen Studio 是开源的,代码在这里,可以通过 pip 安装。试试看吧!

pip install autogenstudio

简介

技术的加速发展使我们进入了一个数字助手(或智能体)成为我们生活中不可或缺的一部分的时代。AutoGen 已经成为一个领先的框架,用于协调智能体的力量。为了扩展这个领域并使这种能力民主化,我们非常高兴地推出了一个新的用户友好界面:AutoGen Studio

使用 AutoGen Studio,用户可以快速创建、管理和与可以学习、适应和协作的智能体进行交互。在将这个界面发布到开源社区时,我们的目标不仅是提高生产力,还要激发人与智能体之间个性化互动的水平。

注意:AutoGen Studio 旨在帮助您快速原型化多智能体工作流程,并演示使用 AutoGen 构建的最终用户界面的示例。它不是一个可用于生产的应用程序。

使用 AutoGen Studio 入门

以下指南将帮助您在系统上启动和运行 AutoGen Studio。

配置 LLM 提供程序

要开始使用,您需要访问一个语言模型。您可以按照 AutoGen 文档此处的步骤进行设置。使用 OPENAI_API_KEYAZURE_OPENAI_API_KEY 配置您的环境。

例如,在终端中,您可以像这样设置 API 密钥:

设置 OPENAI_API_KEY=<你的 API 密钥>

您还可以在以下示例中直接在代理配置中指定模型。

llm_config = LLMConfig(
config_list=[{
"model": "gpt-4",
"api_key": "<azure_api_key>",
"base_url": "<azure api base url>",
"api_type": "azure",
"api_version": "2024-02-01"
}],
temperature=0,
)

安装

有两种安装 AutoGen Studio 的方法 - 从 PyPi 或从源代码安装。我们建议从 PyPi 安装,除非您计划修改源代码。

  1. 从 PyPi 安装

    我们建议使用虚拟环境(例如 conda)以避免与现有 Python 包的冲突。在您的虚拟环境中激活 Python 3.10 或更新版本后,使用 pip 安装 AutoGen Studio:

    pip install autogenstudio
  2. 从源代码安装

    注意:这种方法需要对 React 中的构建界面有一定的了解。

    如果您希望从源代码安装,请确保已安装 Python 3.10+ 和 Node.js(版本大于 14.15.0)。以下是开始的方法:

    • 克隆 AutoGen Studio 仓库并安装其 Python 依赖项:

      pip install -e .
    • 导航到 samples/apps/autogen-studio/frontend 目录,安装依赖项并构建 UI:

      npm install -g gatsby-cli
      npm install --global yarn
      yarn install
      yarn build

    对于 Windows 用户,要构建前端,您可能需要使用 autogen studio readme 中提供的替代命令。

运行应用程序

安装完成后,在终端中输入以下命令运行 Web UI:

autogenstudio ui --port 8081

这将在指定的端口上启动应用程序。打开您的 Web 浏览器并转到 http://localhost:8081/,开始使用 AutoGen Studio。

现在,您已经安装并运行了 AutoGen Studio,可以开始探索其功能,包括定义和修改代理工作流、与代理和会话交互以及扩展代理技能。

AutoGen Studio 能做什么?

AutoGen Studio UI 分为 3 个高级部分 - 构建PlaygroundGallery

构建

指定代理。

该部分专注于定义代理和代理工作流的属性。它包括以下概念:

技能:技能是描述如何解决任务的函数(例如 Python 函数)。通常,一个好的技能具有描述性的名称(例如 generate_images),详细的文档字符串和良好的默认值(例如,将文件写入磁盘以进行持久化和重用)。您可以通过提供的 UI 向 AutoGen Studio 添加新的技能。在推理时,这些技能将作为辅助代理的可用技能,以解决您的任务。

查看和添加技能。

AutoGen Studio 构建视图:查看、添加或编辑代理人在处理任务时可以利用的技能。

代理人:这提供了一个界面,用于声明性地指定 AutoGen 代理人的属性(与基本的 AutoGen 可对话代理人 类的大部分成员相同)。

代理人工作流:代理人工作流是指一组可以共同完成任务的代理人的规范。最简单的版本是设置两个代理人 - 一个用户代理人(代表用户,即编译代码并打印结果)和一个助手,可以处理任务请求(例如生成计划、编写代码、评估响应、提出错误恢复步骤等)。更复杂的流程可以是一个群聊,其中更多的代理人共同努力解决问题。

游乐场

AutoGen Studio 游乐场视图:使用多个可以生成带有图片的 PDF 文档的代理人解决任务。

AutoGen Studio 游乐场视图:代理人协作,利用可用技能(生成图片的能力)来处理用户任务(生成 PDF)。

游乐场部分专注于与前面构建部分中定义的代理人工作流进行交互。它包括以下概念:

会话:会话指的是与代理人工作流的连续交互或参与期,通常通过一系列旨在实现特定目标的活动或操作来描述。它包括代理人工作流配置以及用户和代理人之间的交互。会话可以“发布”到“画廊”。

聊天视图:聊天是用户和代理人之间的一系列交互的序列。它是会话的一部分。

画廊

这一部分专注于共享和重用工件(例如工作流配置、会话等)。

AutoGen Studio 自带了 3 个示例技能:fetch_profilefind_papersgenerate_images。请随意查看存储库以了解它们的工作原理。

AutoGen Studio API

虽然 AutoGen Studio 是一个 Web 界面,但它由一个可重用和模块化的底层 Python API 提供支持。重要的是,我们实现了一个 API,可以以声明性的方式指定代理人工作流(以 JSON 格式),加载和运行。下面是当前 API 的示例。请参阅AutoGen Studio 存储库以获取更多详细信息。

import json
from autogenstudio import AutoGenWorkFlowManager, AgentWorkFlowConfig

# 加载一个以 JSON 格式存储的 agent 规范
agent_spec = json.load(open('agent_spec.json'))

# 从 agent 规范创建一个 AutoGen 工作流配置
agent_work_flow_config = FlowConfig(**agent_spec)

# 从配置创建一个工作流
agent_work_flow = AutoGenWorkFlowManager(agent_work_flow_config)

# 在一个任务上运行工作流
task_query = "巴黎铁塔的高度是多少?"
agent_work_flow.run(message=task_query)

路线图和下一步计划

在我们继续开发和完善 AutoGen Studio 的过程中,下面的路线图概述了未来版本中计划的一系列增强和新功能。以下是用户可以期待的内容:

  • 复杂的代理工作流程:我们正在努力集成对更复杂的代理工作流程的支持,例如 GroupChat,允许多个代理之间或动态拓扑之间进行更丰富的交互。
  • 改进的用户体验:这包括诸如实时反馈中间模型输出、更好地总结代理响应、每次交互的成本信息等功能。我们还将致力于改进组合和重用代理的工作流程。我们还将探索对代理提供更多交互式人工反馈的支持。
  • 扩展代理技能:我们将努力改进代理技能的创作、组合和重用工作流程。
  • 社区功能:在 AutoGen Studio 用户社区内进行共享和协作是一个重要目标。我们正在探索更方便地在用户之间共享会话和结果的选项,并为技能、代理和代理工作流程建立一个共享的存储库。

贡献指南

我们欢迎对 AutoGen Studio 的贡献。我们建议按照以下一般步骤来为项目做出贡献:

  • 查看整体的 AutoGen 项目贡献指南
  • 请查看 AutoGen Studio 的路线图,了解当前项目的优先事项。特别需要帮助的是带有 help-wanted 标签的 Studio 问题。
  • 请在路线图问题或新问题上发起讨论,讨论您提出的贡献。
  • 请查看此处的 autogenstudio dev 分支 [dev branch].(https://github.com/microsoft/autogen/tree/autogenstudio),并将其用作贡献的基础。这样,您的贡献将与 AutoGen Studio 项目的最新更改保持一致。
  • 提交一个拉取请求,贡献您的代码!
  • 如果您在 vscode 中修改 AutoGen Studio,它有自己的 devcontainer 来简化开发工作。请参阅 .devcontainer/README.md 中的说明。
  • 请在与 Studio 相关的任何问题、疑问和拉取请求中使用标签 studio

常见问题

问:我在哪里可以调整默认的技能、代理和工作流配置? 答:您可以直接从用户界面修改代理配置,或者编辑 autogentstudio/utils/dbdefaults.json 文件来初始化数据库。

问:如果我想重置与代理的整个对话,我该怎么做? 答:要重置您的对话历史记录,您可以删除 database.sqlite 文件。如果您需要清除特定用户的数据,请删除相关的 autogenstudio/web/files/user/<user_id_md5hash> 文件夹。 问:在交互过程中,是否可以查看代理生成的输出和消息? 答:是的,您可以在Web UI的调试控制台中查看生成的消息,从而了解代理之间的交互情况。另外,您还可以检查database.sqlite文件,以获取完整的消息记录。

问:我在哪里可以找到AutoGen Studio的文档和支持? 答:我们不断努力改进AutoGen Studio。有关最新更新,请参阅AutoGen Studio自述文件。如果需要额外的支持,请在GitHub上提出问题或在Discord上提问。

问:我可以在AutoGen Studio中使用其他模型吗? 答:可以。AutoGen采用了openai模型API格式的标准化,您可以使用任何提供openai兼容端点的API服务器。在AutoGen Studio的UI中,每个代理都有一个llm_config字段,您可以在其中输入模型端点的详细信息,包括模型名称API密钥基本URL模型类型API版本。对于Azure OpenAI模型,您可以在Azure门户中找到这些详细信息。请注意,对于Azure OpenAI,模型名称是部署ID或引擎,而模型类型是"azure"。对于其他开源模型,我们建议使用类似vllm的服务器来实例化一个openai兼容的端点。

问:服务器已启动,但无法访问UI界面 答:如果您在远程机器上运行服务器(或本地机器无法正确解析localhost),您可能需要指定主机地址。默认情况下,主机地址设置为localhost。您可以使用--host <host>参数指定主机地址。例如,要在端口8081上启动服务器,并使用本地地址,以便从网络上的其他机器访问,可以运行以下命令:

autogenstudio ui --port 8081 --host 0.0.0.0

· 11 min read
Linxin Song
Jieyu Zhang

AutoBuild的整体结构

TL;DR: 介绍 AutoBuild,它可以自动、快速、轻松地构建用于复杂任务的多智能体系统,只需最少的用户提示,由新设计的 AgentBuilder 类提供支持。AgentBuilder 还通过利用 vLLMFastChat 支持开源的LLM。请查看示例笔记本和源代码以供参考:

简介

在本文中,我们介绍了一种名为 AutoBuild 的流水线,可以自动构建用于复杂任务的多智能体系统。具体来说,我们设计了一个名为 AgentBuilder 的新类,它将在用户提供建筑任务和执行任务的描述后,自动完成参与者专家智能体的生成和群组聊天的构建。

AgentBuilder 支持由 vLLMFastChat 提供支持的开源模型。一旦用户选择使用开源的LLM,AgentBuilder 将自动设置一个端点服务器,无需用户参与。

安装

  • AutoGen:
pip install pyautogen[autobuild]
  • (可选:如果您想使用开源的LLM)vLLM 和 FastChat
pip install vllm fastchat

基本示例

在本节中,我们提供了一个逐步示例,介绍如何使用 AgentBuilder 构建特定任务的多智能体系统。

步骤1:准备配置

首先,我们需要准备智能体的配置。 具体来说,需要一个包含模型名称和API密钥的配置文件路径,以及每个智能体的默认配置。

config_file_or_env = '/home/elpis_ubuntu/LLM/autogen/OAI_CONFIG_LIST'  # 修改路径
default_llm_config = {
'temperature': 0
}

步骤2:创建 AgentBuilder 实例

然后,我们使用配置文件路径和默认配置创建一个 AgentBuilder 实例。 您还可以指定构建器模型和智能体模型,它们是用于构建和智能体的LLM。

from autogen.agentchat.contrib.agent_builder import AgentBuilder

builder = AgentBuilder(config_file_or_env=config_file_or_env, builder_model='gpt-4-1106-preview', agent_model='gpt-4-1106-preview')

步骤3:指定建筑任务

使用一般描述指定一个建筑任务。建筑任务将帮助建筑经理(一个LLM)决定应该构建哪些智能体。 请注意,您的建筑任务应该有一个关于任务的一般描述。添加一些具体的示例会更好。

building_task = "在 arxiv 上找一篇与编程相关的论文,并分析其在某个领域的应用。例如,在 arxiv 上找一篇关于 GPT-4 的最新论文,并找出它在软件领域的潜在应用。"

第四步:构建群聊代理

使用 build() 方法,让构建管理器(使用 builder_model 作为主干)完成群聊代理的生成。

如果你认为在任务中需要编码,你可以使用 coding=True 将一个用户代理(本地代码解释器)添加到代理列表中,如下所示:

agent_list, agent_configs = builder.build(building_task, default_llm_config, coding=True)

如果没有指定 coding 参数,AgentBuilder 将根据任务自行决定是否添加用户代理。

生成的 agent_list 是一个 AssistantAgent 实例的列表。如果 codingTrue,将会在 agent_list 的第一个元素位置添加一个用户代理(UserProxyAssistant 实例)。

agent_configs 是一个代理配置的列表,包括代理名称、主干 LLM 模型和系统消息。

例如:

// 一个 agent_configs 的示例。AgentBuilder 将生成具有以下配置的代理。
[
{
"name": "ArXiv_Data_Scraper_Developer",
"model": "gpt-4-1106-preview",
"system_message": "您现在在一个群聊中。您需要与其他参与者一起完成一个任务。作为 ArXiv_Data_Scraper_Developer,您的重点是创建和改进能够智能搜索和从 arXiv 提取数据的工具,专注于计算机科学和医学科学领域的主题。利用您在 Python 编程方面的熟练程度,设计脚本来浏览、查询和解析平台上的信息,生成有价值的见解和数据集进行分析。\n\n在您的任务中,不仅仅是制定查询;您的角色还包括优化和精确数据检索过程,确保提取的信息的相关性和准确性。如果您在脚本中遇到问题或预期输出有差异,鼓励您在群聊中进行故障排除并提供修订的代码。\n\n当您达到现有代码库无法满足任务要求的程度,或者对提供的代码的操作不清楚时,您应该向群聊管理员寻求帮助。他们将通过提供指导或指派其他参与者来促进您的进展。根据同行的反馈能力来调整和改进脚本至关重要,因为数据爬取的动态性要求不断完善技术和方法。\n\n通过确认您提供的数据爬取解决方案是否满足用户的需求来结束您的参与。在群聊中回复“TERMINATE”来指示您任务的完成。",
"description": "ArXiv_Data_Scraper_Developer 是一个专门的软件开发角色,需要精通 Python,包括熟悉 BeautifulSoup 或 Scrapy 等网络爬虫库,并对 API 和数据解析有扎实的理解。他们必须具备在现有脚本中识别和纠正错误的能力,并自信地参与技术讨论,以改进数据检索过程。该角色还需要具备疑难解答和优化代码的敏锐眼光,以确保从 ArXiv 平台高效地提取研究和分析所需的数据。"
},
...
]

第五步:执行任务

让在 build() 中生成的代理在群聊中协作完成任务。

import autogen

def start_task(execution_task: str, agent_list: list, llm_config: dict):
config_list = autogen.config_list_from_json(config_file_or_env, filter_dict={"model": ["gpt-4-1106-preview"]})

group_chat = autogen.GroupChat(agents=agent_list, messages=[], max_round=12)
manager = autogen.GroupChatManager(
groupchat=group_chat, llm_config={"config_list": config_list, **llm_config}
)
agent_list[0].initiate_chat(manager, message=execution_task)

start_task(
execution_task="在 arxiv 上找一篇关于 gpt-4 的最新论文,并找出它在软件领域的潜在应用。",
agent_list=agent_list,
llm_config=default_llm_config
)

第六步(可选):清除所有代理并准备下一个任务

如果任务已完成或下一个任务与当前任务差异较大,您可以使用以下代码清除在此任务中生成的所有代理。

builder.clear_all_agents(recycle_endpoint=True)

如果代理的骨干是开源的 LLM,则此过程还将关闭端点服务器。更多细节请参见下一节。 如果需要,您可以使用 recycle_endpoint=False 保留先前开源 LLM 的端点服务器。

保存和加载

您可以通过以下代码保存构建的群聊代理的所有必要信息:

saved_path = builder.save()

配置将以 JSON 格式保存,内容如下:

// 文件名:save_config_TASK_MD5.json
{
"building_task": "在 arxiv 上找一篇关于 gpt-4 的论文,并分析其在某个领域的应用。例如,在 arxiv 上找一篇关于 gpt-4 的最新论文,并找出它在软件领域的潜在应用。",
"agent_configs": [
{
"name": "...",
"model": "...",
"system_message": "...",
"description": "..."
},
...
],
"manager_system_message": "...",
"code_execution_config": {...},
"default_llm_config": {...}
}

您可以提供特定的文件名,否则 AgentBuilder 将使用生成的文件名 save_config_TASK_MD5.json 将配置保存到当前路径。

您可以加载保存的配置并跳过构建过程。AgentBuilder 将使用这些信息创建代理,而无需提示构建管理器。

new_builder = AgentBuilder(config_file_or_env=config_file_or_env)
agent_list, agent_config = new_builder.load(saved_path)
start_task(...) # 跳过 build()

使用 OpenAI Assistant

Assistants API 允许您在自己的应用程序中构建 AI 助手。 助手具有指令,并可以利用模型、工具和知识来回应用户的查询。 AutoBuild 通过在 build() 中添加 use_oai_assistant=True 来支持助手 API。

# 转换为 OpenAI Assistant API。
agent_list, agent_config = new_builder.build(building_task, default_llm_config, use_oai_assistant=True)
...

(实验性)使用开源LLM

AutoBuild支持通过vLLMFastChat使用开源LLM。 请在这里查看支持的模型列表。 满足要求后,您可以将开源LLM的huggingface仓库添加到配置文件中,

// 将LLM的huggingface仓库添加到您的配置文件中,并将api_key设置为EMPTY。
[
...
{
"model": "meta-llama/Llama-2-13b-chat-hf",
"api_key": "EMPTY"
}
]

并在初始化AgentBuilder时指定它。 AgentBuilder将自动设置一个用于开源LLM的端点服务器。请确保您有足够的GPU资源。

未来工作/路线图

  • 让构建器从给定的库/数据库中选择最佳的代理来解决任务。

概述

我们提出了AutoBuild,其中包含一个新的类AgentBuilder。 AutoBuild可以帮助用户使用自动构建的多代理系统解决复杂任务。 AutoBuild支持开源LLM和GPTs API,使用户能够更灵活地选择他们喜欢的模型。 更多高级功能即将推出。

· 15 min read
Julia Kiseleva
Negar Arabzadeh

图1:验证框架

图1展示了AgentEval的一般流程

TL;DR:

  • 作为一个LLM应用的开发者,你如何评估它对最终用户的实用性,同时又能帮助他们完成任务?
  • 为了回答上述问题,我们介绍了AgentEval——一个用于评估任何LLM应用实用性的框架的第一个版本。AgentEval旨在简化评估过程,通过自动提出一组与应用的独特目的相适应的标准,实现全面评估,并量化应用相对于建议标准的实用性。
  • 我们使用数学问题数据集作为示例,在以下笔记本中演示了AgentEval的工作原理。对于未来的发展,任何反馈都将非常有用。请通过我们的Discord与我们联系。

引言

AutoGen旨在简化开发LLM驱动的多Agent系统,以应用于各种应用程序,最终通过协助用户完成任务来简化用户的生活。接下来,我们都渴望了解我们开发的系统的性能,对用户的实用性以及最重要的是如何改进它们。直接评估多Agent系统存在挑战,因为当前的方法主要依赖于成功度量标准,即Agent是否完成任务。然而,理解用户与系统的交互远不止于仅仅成功。以数学问题为例,重要的不仅仅是Agent解决问题,同样重要的是它能够根据各种标准传达解决方案,包括完整性、简洁性和提供的解释的清晰度。此外,并非每个任务的成功都有明确定义。

LLM和多Agent系统的快速发展带来了许多新兴的能力,我们渴望将其转化为对最终用户有实际用途的工具。我们介绍了AgentEval框架的第一个版本——一个旨在帮助开发者快速评估LLM应用实用性的工具,以帮助最终用户完成所需任务。

图2:任务分类的概览

图2提供了任务分类的概览

让我们首先了解一个多Agent系统可以设计的任务分类的概览。一般来说,任务可以分为两类,即:

  • 成功没有明确定义 - 指的是用户以辅助方式使用系统的情况,寻求建议而不是期望系统解决任务。例如,用户可能要求系统生成一封电子邮件。在许多情况下,生成的内容作为用户稍后将编辑的模板。然而,对于这种任务来说,准确定义成功相对复杂。
  • 成功有明确定义 - 指的是我们可以明确定义系统是否解决了任务的情况。考虑到协助完成家务任务的代理程序,成功的定义是明确且可衡量的。这个类别可以进一步分为两个子类别:
    • 存在最优解 - 这些是只有一个解决方案可能的任务。例如,如果你要求你的助手打开灯,这个任务的成功是明确定义的,而且只有一种方法可以完成它。
    • 存在多个解决方案 - 越来越多的情况下,我们观察到多个代理行为轨迹可以导致成功或失败。在这种情况下,区分各种成功和失败的轨迹非常重要。例如,当你要求代理程序给你建议一个食谱或者讲个笑话时。

在我们的AgentEval框架中,我们目前专注于_成功有明确定义_的任务。接下来,我们将介绍建议的框架。

AgentEval框架

我们之前在Minecraft中的辅助代理研究中发现,获取人类判断的最佳方式是将两个代理程序并排呈现给人类,并询问他们的偏好。在这种成对比较的设置中,人类可以制定标准来解释为什么他们更喜欢一个代理程序的行为而不是另一个。例如,“第一个代理程序执行速度更快”,或者“第二个代理程序移动更自然”。因此,比较的性质使人类能够提出一系列标准,有助于推断任务的效用。基于这个想法,我们设计了AgentEval(如图1所示),其中我们使用LLMs来帮助我们理解、验证和评估多代理系统的任务效用。具体来说:

  • CriticAgent的目标是提供一份可以用来评估任务效用的标准列表(图1)。这是使用Autogen定义CriticAgent的一个示例:
critic = autogen.AssistantAgent(
name="critic",
llm_config={"config_list": config_list},
system_message="""你是一个乐于助人的助理。你会为评估不同任务提供评价标准。这些标准应该是可区分的、可量化的,并且不重复。
将评估标准转化为一个字典,其中键是标准的名称。
每个键的值是一个字典,格式如下:{"description": 标准描述, "accepted_values": 该键的可接受输入}
确保键是用于评估给定任务的标准。"accepted_values" 包括每个键的可接受输入,这些输入应该是细粒度的,最好是多级别的。"description" 包括标准的描述。
只返回字典。"""
)

接下来,评论家将获得任务执行的成功和失败示例;然后,它能够返回一系列的标准(图1)。请参考以下笔记本

  • QuantifierAgent 的目标是量化每个建议的标准(图1),从而让我们了解该系统在给定任务中的效用。以下是如何定义它的示例:
quantifier = autogen.AssistantAgent(
name="quantifier",
llm_config={"config_list": config_list},
system_message = """You are a helpful assistant. You quantify the output of different tasks based on the given criteria.
The criterion is given in a dictionary format where each key is a distinct criteria.
The value of each key is a dictionary as follows {"description": criteria description , "accepted_values": possible accepted inputs for this key}
You are going to quantify each of the criteria for a given task based on the task description.
Return a dictionary where the keys are the criteria and the values are the assessed performance based on accepted values for each criteria.
Return only the dictionary."""

)

基于数学问题数据集的 AgentEval 结果

例如,运行 CriticAgent 后,我们获得了以下标准来验证数学问题数据集的结果:

标准描述可接受的值
问题解释正确解释问题的能力["完全错误", "稍微相关", "相关", "大部分准确", "完全准确"]
数学方法选择的数学或算法方法对于问题的适当性["不适当", "勉强合适", "合适", "大部分有效", "完全有效"]
计算正确性计算的准确性和给出的解决方案["完全不正确", "大部分不正确", "无法确定", "大部分正确", "完全正确"]
解释清晰度解释的清晰度和可理解性,包括语言使用和结构["完全不清晰", "稍微清晰", "中等清晰", "非常清晰", "完全清晰"]
代码效率代码的质量,包括效率和优雅程度["完全不高效", "稍微高效", "中等高效", "非常高效", "极其高效"]
代码正确性提供的代码的正确性["完全不正确", "大部分不正确", "部分正确", "大部分正确", "完全正确"]

然后,运行 QuantifierAgent 后,我们获得了图3中呈现的结果,其中您可以看到三个模型:

  • AgentChat
  • ReAct
  • GPT-4 Vanilla Solver

较浅的颜色表示失败案例的估计,较亮的颜色显示了发现的标准是如何被量化的。 图3:基于整体数学问题数据集的结果,_s代表成功案例,_f代表失败案例

图3显示了基于整体数学问题数据集的结果,_s代表成功案例,_f代表失败案例

我们注意到,在应用AgentEval到数学问题时,该代理并没有接触到任何关于问题的真实信息。因此,这个图表展示了三个不同代理(Autogen(蓝色)、Gpt-4(红色)和ReAct(绿色))的估计性能。通过比较任何一个代理在成功案例(任何颜色的深色条形)和失败案例(同一条形的浅色版本)中的表现,我们可以观察到AgentEval能够给成功案例分配比失败案例更高的量化值。这个观察结果验证了AgentEval在任务效用预测方面的能力。此外,AgentEval还允许我们超越对成功的二元定义,实现对成功和失败案例的更深入比较。

重要的是,不仅要识别出不起作用的原因,还要认识到什么以及为什么实际上做得好。

限制和未来工作

目前的AgentEval实现存在一些限制,我们计划在未来克服这些限制:

  • 根据每次运行的不同,评估标准的列表也会有所变化(除非您存储了一个种子)。我们建议至少运行CriticAgent两次,并选择您认为对您的领域重要的标准。
  • QuantifierAgent的结果可能会随每次运行而变化,因此我们建议进行多次运行以观察结果变化的程度。

为了缓解上述限制,我们正在开发VerifierAgent,其目标是稳定结果并提供额外的解释。

总结

CriticAgentQuantifierAgent可以应用于任何类型应用的日志,为您提供对您的解决方案在给定任务中为用户带来的效用的深入理解。

我们很想听听AgentEval在您的应用中的表现如何。任何反馈对未来的发展都将非常有用。请通过我们的Discord与我们联系。

先前的研究

@InProceedings{pmlr-v176-kiseleva22a,
title = "在协作环境中的交互式基于场景的语言理解:IGLU 2021",
author = "Kiseleva, Julia and Li, Ziming and Aliannejadi, Mohammad and Mohanty, Shrestha and ter Hoeve, Maartje and Burtsev, Mikhail and Skrynnik, Alexey and Zholus, Artem and Panov, Aleksandr and Srinet, Kavya and Szlam, Arthur and Sun, Yuxuan and Hofmann, Katja and C{\^o}t{\'e}, Marc-Alexandre and Awadallah, Ahmed and Abdrazakov, Linar and Churin, Igor and Manggala, Putra and Naszadi, Kata and van der Meer, Michiel and Kim, Taewoon",
booktitle = "NeurIPS 2021竞赛和演示论文集",
pages = "146--161",
year = 2022,
editor = "Kiela, Douwe and Ciccone, Marco and Caputo, Barbara",
volume = 176,
series = "机器学习研究论文集",
month = "12月6日至14日",
publisher = "PMLR",
pdf = {https://proceedings.mlr.press/v176/kiseleva22a/kiseleva22a.pdf},
url = {https://proceedings.mlr.press/v176/kiseleva22a.html}.
}
@InProceedings{pmlr-v220-kiseleva22a,
title = "在协作环境中的交互式基于场景的语言理解:Iglu 2022竞赛回顾",
author = "Kiseleva, Julia and Skrynnik, Alexey and Zholus, Artem and Mohanty, Shrestha and Arabzadeh, Negar and C\^{o}t\'e, Marc-Alexandre and Aliannejadi, Mohammad and Teruel, Milagro and Li, Ziming and Burtsev, Mikhail and ter Hoeve, Maartje and Volovikova, Zoya and Panov, Aleksandr and Sun, Yuxuan and Srinet, Kavya and Szlam, Arthur and Awadallah, Ahmed and Rho, Seungeun and Kwon, Taehwan and Wontae Nam, Daniel and Bivort Haiek, Felipe and Zhang, Edwin and Abdrazakov, Linar and Qingyam, Guo and Zhang, Jason and Guo, Zhibin",
booktitle = "NeurIPS 2022竞赛论文集",
pages = "204--216",
year = 2022,
editor = "Ciccone, Marco and Stolovitzky, Gustavo and Albrecht, Jacob",
volume = 220,
series = "机器学习研究论文集",
month = "11月28日--12月9日",
publisher = "PMLR",
pdf = "https://proceedings.mlr.press/v220/kiseleva22a/kiseleva22a.pdf",
url = "https://proceedings.mlr.press/v220/kiseleva22a.html".
}

· 4 min read
Gagan Bansal

OpenAI助手

AutoGen通过GPTAssistantAgent实现了多个ChatGPT之间的协作,用于处理复杂任务。

TL;DR

现在,通过GPTAssistantAgent,OpenAI助手已经集成到AutoGen中。 这使得多个OpenAI助手(作为现在流行的GPT的后端)能够协作处理复杂任务。 可以参考以下示例笔记本:

简介

上周,OpenAI推出了GPT,使用户能够创建适合自己的定制ChatGPT。 但是,如果这些个体GPT能够合作做更多事情呢? 幸运的是,由于AutoGen,这已经成为现实! AutoGen从今年年初开始就一直在开创代理人并支持多代理人工作流,现在(从版本0.2.0b5开始)我们引入了与助手API的兼容性,该API目前处于beta预览阶段。

为了实现这一点,我们添加了一个新的(实验性的)代理人,称为GPTAssistantAgent,它可以无缝地将这些新的OpenAI助手添加到基于AutoGen的多代理人工作流中。 这种集成显示出巨大的潜力和协同效应,我们计划继续增强它。

安装

pip install pyautogen==0.2.0b5

基本示例

下面是一个基本示例,使用UserProxyAgent允许与GPTAssistantAgent进行交互。

首先,导入新的代理人并设置config_list

from autogen import config_list_from_json
from autogen.agentchat.contrib.gpt_assistant_agent import GPTAssistantAgent
from autogen import UserProxyAgent

config_list = config_list_from_json("OAI_CONFIG_LIST")

然后简单地定义OpenAI助手代理人并给它任务!

# 使用助手API创建新助手
gpt_assistant = GPTAssistantAgent(
name="assistant",
llm_config={
"config_list": config_list,
"assistant_id": None
})

user_proxy = UserProxyAgent(name="user_proxy",
code_execution_config={
"work_dir": "coding"
},
human_input_mode="NEVER")

user_proxy.initiate_chat(gpt_assistant, message="打印Hello World")

GPTAssistantAgent支持创建新的OpenAI助手或重用现有助手 (例如,通过提供assistant_id)。

代码解释器示例

GPTAssistantAgent允许您指定一个OpenAI工具, (例如,函数调用,代码解释器等)。下面的示例演示了如何使用 OpenAI 代码解释器创建一个能够解决任务的助手。

# 使用 Assistant API 创建新的助手
gpt_assistant = GPTAssistantAgent(
name="assistant",
llm_config={
"config_list": config_list,
"assistant_id": None,
"tools": [
{
"type": "code_interpreter"
}
],
})

user_proxy = UserProxyAgent(name="user_proxy",
code_execution_config={
"work_dir": "coding"
},
human_input_mode="NEVER")

user_proxy.initiate_chat(gpt_assistant, message="Print hello world")

这里查看更多示例。

限制和未来工作

  • 使用 GPT 助手的群聊管理器尚未完成。
  • 具备多模态能力的 GPT 助手尚未发布,但我们致力于支持它们。

致谢

GPTAssistantAgent 是与 @IANTHEREALJiale LiuYiran WuQingyun WuChi Wang 和其他 AutoGen 维护者合作完成的。

· 8 min read
Jieyu Zhang

system

TL;DR:

  • 我们介绍了EcoAssistant,旨在更准确、更经济地解决用户的问题。
  • 我们展示了如何让LLM助手代理利用外部API来解决用户的问题。
  • 我们展示了如何通过助手层次结构降低使用GPT模型的成本。
  • 我们展示了如何利用检索增强生成(RAG)的思想通过解决方案演示来提高成功率。

EcoAssistant

在本文中,我们介绍了EcoAssistant,这是一个建立在AutoGen之上的系统,旨在更准确、更经济地解决用户的问题。

问题设定

最近,用户们使用对话式LLM(如ChatGPT)进行各种查询。 报告显示,23%的ChatGPT用户查询是为了进行知识提取。 其中许多查询需要的知识是超出任何预训练的大型语言模型(LLM)内部存储的信息的。 这些任务只能通过生成代码来获取所需信息,而这些信息存储在包含所请求信息的外部API中。 在下表中,我们展示了我们在这项工作中要解决的三种类型的用户查询。

数据集API示例查询
地点Google Places我在蒙特利尔找一个24小时的药店,你能帮我找一个吗?
天气Weather API孟买,印度的当前云覆盖率是多少?
股票Alpha Vantage Stock API你能给我2023年1月份微软的开盘价吗?

利用外部API

为了解决这些查询,我们首先构建了一个基于AutoGen的双代理系统, 其中第一个代理是一个LLM助手代理(AutoGen中的AssistantAgent),负责提出和优化代码, 第二个代理是一个代码执行代理(AutoGen中的UserProxyAgent),负责提取生成的代码并执行它,将输出转发回LLM助手代理。 下图显示了这个双代理系统的可视化。

chat

为了指示助手代理利用外部API,我们只需要在初始消息的开头添加API名称/密钥字典。 模板如下所示,其中红色部分是API的信息,黑色部分是用户查询。

template

重要的是,出于安全考虑,我们不想向助手代理透露真实的API密钥。 因此,我们使用一个虚假的API密钥来替换初始消息中的真实API密钥。 具体来说,我们为每个API密钥生成一个随机令牌(例如181dbb37),并将真实API密钥替换为初始消息中的令牌。 然后,当代码执行器执行代码时,假的 API 密钥会自动被真实的 API 密钥替换。

解决方案演示

在大多数实际场景中,用户的查询通常是按时间顺序逐个出现的。 我们的 EcoAssistant 利用过去的成功经验,通过 解决方案演示 来帮助 LLM 助手解决未来的查询。 具体来说,每当一个查询被用户反馈认为成功解决时,我们会捕获并存储查询和最终生成的代码片段。 这些查询-代码对被保存在一个专门的向量数据库中。当出现新的查询时,EcoAssistant 从数据库中检索出最相似的查询,然后将其与相关的代码附加到新查询的初始提示中,作为演示。 下面是初始消息的新模板,其中蓝色部分对应解决方案演示。

template

我们发现,利用过去成功的查询-代码对可以减少迭代次数,提高系统性能,从而改进查询解决过程。

助手层次结构

LLM 助手通常具有不同的价格和性能,例如,GPT-3.5-turbo比GPT-4便宜得多,但准确性也较低。 因此,我们提出了 助手层次结构 来降低使用LLM的成本。 核心思想是我们首先使用更便宜的LLM,只有在必要时才使用更昂贵的LLM。 通过这种方式,我们能够减少对昂贵LLM的依赖,从而降低成本。 具体来说,给定多个LLM,我们为每个LLM初始化一个助手代理,并与最具成本效益的LLM助手开始对话。 如果当前LLM助手与代码执行器之间的对话在未成功解决查询的情况下结束,EcoAssistant 将重新与层次结构中的下一个更昂贵的LLM助手开始对话。 我们发现,这种策略显著降低了成本,同时仍然有效地解决了查询。

协同效应

我们发现 EcoAssistant助手层次结构解决方案演示 具有协同效应。 因为查询-代码数据库是所有LLM助手共享的,即使没有专门的设计, 更强大的LLM助手(例如GPT-4)的解决方案也可以后续检索,以指导较弱的LLM助手(例如GPT-3.5-turbo)。 这种协同效应进一步提高了 EcoAssistant 的性能并降低了成本。

实验结果

我们在三个数据集(Places、Weather和Stock)上评估了 EcoAssistant。与单个GPT-4助手相比,我们发现 EcoAssistant 在成功率更高的同时成本更低,如下图所示。 有关实验结果和其他实验的更多详细信息,请参阅我们的论文

exp

进一步阅读

更多关于EcoAssistant的详细信息,请参考我们的论文代码库

如果您觉得本博客有用,请考虑引用以下内容:

@article{zhang2023ecoassistant,
title={EcoAssistant: 使用LLM助手更经济高效},
author={Zhang, Jieyu and Krishna, Ranjay and Awadallah, Ahmed H and Wang, Chi},
journal={arXiv preprint arXiv:2310.03046},
year={2023}
}

· 4 min read
Beibin Li

多模态预览

简介:

  • 引入多模态对话代理LLaVA代理以增强LMM的功能。
  • 用户可以使用<img img_path>标签同时输入文本和图像,以指定图像加载。
  • 通过GPT-4V笔记本进行演示。
  • 通过LLaVA笔记本进行演示。

引言

大型多模态模型(LMM)通过处理多感官数据来增强大型语言模型(LLM)的能力。

本博文和最新的AutoGen更新专注于视觉理解。用户可以输入图像,提出关于图像的问题,并从这些LMM中获得基于文本的回答。 我们现在支持来自OpenAI的gpt-4-vision-preview模型和来自Microsoft的LLaVA模型。

在这里,我们强调多模态对话代理LLaVA代理,因为它们越来越受欢迎。 GPT-4V代表图像理解的前沿,而LLaVA是一个高效的模型,从LLama-2进行了精细调整。

安装

在AutoGen安装过程中加入lmm功能:

pip install "pyautogen[lmm]"

然后,从AutoGen中导入多模态对话代理LLaVA代理

from autogen.agentchat.contrib.multimodal_conversable_agent import MultimodalConversableAgent  # 用于GPT-4V
from autogen.agentchat.contrib.llava_agent import LLaVAAgent # 用于LLaVA

使用方法

已定义了一个简单的语法,可以在单个字符串中同时包含消息和图像。

示例中的上下文学习提示:

prompt = """您现在是一个面部表情分类器。这里有一些例子。

<img happy.jpg> 描述了一个快乐的表情。
<img http://some_location.com/sad.jpg> 代表了一个悲伤的表情。
<img obama.jpg> 描绘了一个中性的表情。

现在,请识别这个人的面部表情:<img unknown.png>
"""

agent = MultimodalConversableAgent()
user = UserProxyAgent()
user.initiate_chat(agent, message=prompt)

MultimodalConversableAgent会解释输入提示,并从本地或互联网源提取图像。

高级用法

与其他AutoGen代理类似,多模态代理支持与其他代理的多轮对话、代码生成、事实查询和通过GroupChat接口进行管理。

例如,在我们的GPT-4V笔记本LLaVA笔记本中,FigureCreator集成了两个代理:一个编码器(AssistantAgent)和评论家(多模态代理)。 编码者为可视化草图编写Python代码,而评论家则提供改进的见解。这些代理人共同努力,旨在改进可视化输出。 通过设置 human_input_mode=ALWAYS,您还可以为更好的可视化提供建议。

参考资料

未来的改进

如有进一步的疑问或建议,请在AutoGen存储库中提出问题,或直接与我联系,我的邮箱是beibin.li@microsoft.com

AutoGen将继续发展,融入更多的多模态功能,如DALLE模型集成、音频交互和视频理解。敬请期待这些令人兴奋的发展。

· 26 min read
Ricky Loynd

可教授代理架构

TL;DR:

  • 我们引入了可教授代理,使用户能够教授他们基于LLM的助手新的事实、偏好和技能。
  • 我们展示了可教授代理学习并在后续对话中回忆事实、偏好和技能的示例。

引言

基于LLM的对话助手可以记住与用户的当前对话,并且在对话过程中可以展示用户教授的上下文学习。但是助手的记忆和学习在对话结束时或者当单个对话变得过长以至于LLM无法有效处理时会丢失。然后在后续的对话中,用户被迫一遍又一遍地重复任何必要的指令。

可教授性通过将用户教授跨越对话边界存储在作为向量数据库实现的长期记忆中来解决这些限制。而不是将所有记忆复制到上下文窗口中,这将占用宝贵的空间,单个记忆(称为备忘录)会根据需要检索到上下文中。这使得用户只需将常用的事实和技能教给可教授代理一次,并在后续对话中回忆起来。

任何继承自ConversableAgent的实例化agent都可以通过实例化Teachability对象并调用其add_to_agent(agent)方法来使其可教授。 为了对备忘录的存储和检索做出有效的决策,Teachability对象调用TextAnalyzerAgent的一个实例(另一个AutoGen代理)来识别和重组文本,以便记住事实、偏好和技能。请注意,这会增加涉及相对较少数量的令牌的额外LLM调用,这可能会使用户等待每个响应的时间延长几秒钟。

自己运行

AutoGen包含四个使用可教授性的代码示例。

  1. 运行chat_with_teachable_agent.py与可教授代理进行对话。

  2. 运行test_teachable_agent.py对可教授代理进行快速单元测试。

  3. 使用Jupyter笔记本agentchat_teachability.ipynb逐步执行下面讨论的示例。

  4. 使用Jupyter笔记本agentchat_teachable_oai_assistants.ipynb通过GPTAssistantAgent使任意OpenAI助手可教授。

可教授性的基本用法

  1. 安装依赖项

在使用可教授性之前,请先安装带有[teachable]选项的pyautogen。

pip install "pyautogen[teachable]"
  1. 导入代理
from autogen import UserProxyAgent, config_list_from_json
from autogen.agentchat.contrib.capabilities.teachability import Teachability
from autogen import ConversableAgent # 作为示例
  1. 创建 llm_config
# 从环境变量或文件中加载 LLM 推理端点
# 参见 https://microsoft.github.io/autogen/docs/FAQ#set-your-api-endpoints
# 和 OAI_CONFIG_LIST_sample
filter_dict = {"model": ["gpt-4"]} # GPT-3.5 在从用户反馈中学习方面比 GPT-4 不可靠。
config_list = config_list_from_json(env_or_file="OAI_CONFIG_LIST", filter_dict=filter_dict)
llm_config={"config_list": config_list, "timeout": 120}
  1. 创建代理

# 首先实例化任何继承自 ConversableAgent 的代理,这里我们直接使用它来简化操作。
teachable_agent = ConversableAgent(
name="teachable_agent", # 名称可以是任意的。
llm_config=llm_config
)

# 实例化一个 Teachability 对象,其参数都是可选的。
teachability = Teachability(
reset_db=False, # 使用 True 强制重置记忆数据库,使用 False 使用现有数据库。
path_to_db_dir="./tmp/interactive/teachability_db" # 可以是任何路径,但在群聊中的可教授代理需要唯一的路径。
)

# 现在将 teachability 添加到代理中。
teachability.add_to_agent(teachable_agent)

# 对于这个测试,像往常一样创建一个用户代理。
user = UserProxyAgent("user", human_input_mode="ALWAYS")
  1. 与可教授代理进行对话
# 当用户输入 'exit' 时,该函数将返回。
teachable_agent.initiate_chat(user, message="嗨,我是一个可教授的用户助手!有什么问题吗?")

示例 1 - 学习用户信息

用户可以教导代理关于自己的事实。 (请注意,由于微调的原因,LLM 可能不愿意承认它们知道个人信息。)

从磁盘加载以前的记忆(如果有)。
teachable_agent(对用户):

你好,我是一个可教授的用户助手!你今天有什么问题?

--------------------------------------------------------------------------------
向 teachable_agent 提供反馈。按回车跳过并使用自动回复,或输入 'exit' 结束对话:我的名字是 Ricky
user(对 teachable_agent):

我的名字是 Ricky

--------------------------------------------------------------------------------

>>>>>>>> 使用自动回复...
teachable_agent(对用户):

你好 Ricky!今天我能帮你什么?

--------------------------------------------------------------------------------
向 teachable_agent 提供反馈。按回车跳过并使用自动回复,或输入 'exit' 结束对话:exit

在以后的对话中,用户可以检查可教授代理是否记得他们的名字。(为了易读起见,下面不再重复用户提示和一些已记录的通知。)

--------------------------------------------------------------------------------
user(对 teachable_agent):

我的名字是什么?

--------------------------------------------------------------------------------
teachable_agent(对用户):

嗨 Ricky!今天我能帮你什么?

--------------------------------------------------------------------------------

示例2 - 学习新事实

用户可以教会代理程序更复杂、相关的事实。

--------------------------------------------------------------------------------
用户 (向可教授的代理提问):

什么是Vicuna模型?

--------------------------------------------------------------------------------
可教授的代理 (回复用户):

很抱歉,但是我在当前数据库中没有关于"Vicuna模型"的信息。您能提供一些关于该模型的背景、描述或详细信息吗?这样我可以更好地帮助您。

--------------------------------------------------------------------------------
用户 (向可教授的代理提问):

Vicuna是由Meta发布的一个拥有130亿参数的语言模型。

--------------------------------------------------------------------------------
可教授的代理 (回复用户):

感谢您提供的信息。Vicuna模型是由Meta开发的一个大规模语言模型。它包含1300亿个参数,这使得它能够理解和生成各种主题的类似人类的文本。神经网络中的参数是分配给每个神经元之间连接的权重和偏差,拥有更多的参数使得模型能够学习和捕捉更复杂的数据模式和关系。作为一个AI语言模型,Vicuna可以在各种与语言相关的任务中使用,例如文本补全、翻译、摘要等。

--------------------------------------------------------------------------------
用户 (向可教授的代理提问):

什么是Orca模型?

--------------------------------------------------------------------------------
可教授的代理 (回复用户):

Orca模型是Meta即将发布的一个语言模型,指的是Meta先进语言模型的研究预览API版本。虽然我目前没有关于Orca模型的具体细节,但预计该模型将比其前身Vicuna拥有更多的参数,以进一步增强其功能。

随着AI语言模型的发展,它们通常在理解和生成类似人类文本方面变得更加高效。这使得它们在完成各种任务,包括文本补全、翻译、摘要、问答以及在各种应用中提供更准确、连贯的结果方面更加有效。

--------------------------------------------------------------------------------
用户 (向可教授的代理提问):

Orca是由Microsoft发布的一个拥有130亿参数的语言模型。它在大多数任务上都优于Vicuna。

--------------------------------------------------------------------------------
可教授的代理 (回复用户):

感谢您的澄清。Orca是由Microsoft开发的一个拥有1300亿参数的语言模型。它旨在超越Meta发布的语言模型Vicuna。拥有大量参数使得Orca能够理解和生成各种主题的类似人类的文本,使其在各种应用中非常有用。

Orca的先进功能使其在文本补全、翻译、摘要、问答等任务中表现出色。它相对于Vicuna的性能提升突显了自然语言处理(NLP)研究的快速进展和越来越强大的AI语言模型的发展。

然后在后续的对话中,可教学的代理可以回答关于它所学到的事实的问题。 (记得先通过输入 'exit' 来关闭之前的对话。)

--------------------------------------------------------------------------------
user (to teachable_agent):

维库纳模型和逆戟鲸模型有什么区别?

--------------------------------------------------------------------------------
teachable_agent (to user):

维库纳模型和逆戟鲸模型都是由 Meta 和 Microsoft 分别发布的具有 1300 亿参数的语言模型。在性能方面,据报道逆戟鲸在大多数任务上优于维库纳。然而,如果没有关于具体任务和基准的详细信息,很难提供更全面的比较。总的来说,这两个模型都是先进的语言模型,旨在提供高质量的自然语言理解和生成,但逆戟鲸在整体性能方面似乎更具优势。

--------------------------------------------------------------------------------

示例 3 - 学习用户偏好

用户可以教导代理人他们更喜欢如何完成任务。

请注意,像下面这样的消息不能作为单个消息通过命令行输入,因为它包含换行符。 这样的消息可以在 Jupyter notebook 中输入,或者通过像 ChatGPT 这样的 UI 层输入。

--------------------------------------------------------------------------------
用户(对teachable_agent):

请给这个摘要做个总结。

AutoGen: 通过多智能体对话实现下一代LLM应用
Qingyun Wu, Gagan Bansal, Jieyu Zhang, Yiran Wu, Beibin Li, Erkang Zhu, Li Jiang, Xiaoyun Zhang, Shaokun Zhang, Jiale Liu, Ahmed Hassan Awadallah, Ryen W White, Doug Burger, Chi Wang
AutoGen是一个开源框架,允许开发人员通过多个智能体进行对话来构建LLM应用。AutoGen智能体具有可定制性、可对话性,并且可以在使用LLM、人工输入和工具的各种模式下运行。使用AutoGen,开发人员还可以灵活定义智能体的交互行为。可以使用自然语言和计算机代码来编程不同应用的灵活对话模式。AutoGen作为一个通用基础设施,用于构建各种复杂度和LLM能力的多样化应用。经验研究证明了该框架在许多示例应用中的有效性,领域涵盖数学、编码、问题回答、运筹学、在线决策、娱乐等。

--------------------------------------------------------------------------------
teachable_agent (to user):

AutoGen是一个开源框架,旨在帮助开发人员创建具有多个可定制智能体的LLM应用,这些智能体可以相互对话以完成任务。这些智能体可以使用LLM、人工输入和工具的不同组合进行操作,使开发人员能够灵活定义智能体的交互行为。AutoGen支持使用自然语言和代码编程灵活的对话模式,适用于构建具有不同复杂度和LLM能力的多样化应用。通过经验研究,在数学、编码、运筹学、决策和娱乐等各个领域证明了该框架的有效性。

--------------------------------------------------------------------------------
请给这个摘要做个总结。当我总结一个摘要时,我会尽量让摘要包含三个简短的要点:标题、创新点和关键的经验结果。

AutoGen: 通过多智能体对话实现下一代LLM应用
Qingyun Wu, Gagan Bansal, Jieyu Zhang, Yiran Wu, Beibin Li, Erkang Zhu, Li Jiang, Xiaoyun Zhang, Shaokun Zhang, Jiale Liu, Ahmed Hassan Awadallah, Ryen W White, Doug Burger, Chi Wang
AutoGen是一个开源框架,允许开发人员通过多个智能体进行对话来构建LLM应用。AutoGen智能体具有可定制性、可对话性,并且可以在使用LLM、人工输入和工具的各种模式下运行。使用AutoGen,开发人员还可以灵活定义智能体的交互行为。可以使用自然语言和计算机代码来编程不同应用的灵活对话模式。AutoGen作为一个通用基础设施,用于构建各种复杂度和LLM能力的多样化应用。经验研究证明了该框架在许多示例应用中的有效性,领域涵盖数学、编码、问题回答、运筹学、在线决策、娱乐等。

--------------------------------------------------------------------------------
teachable_agent (to user):

- 标题:AutoGen: 通过多智能体对话实现下一代LLM应用
- 创新点:通过智能体对话构建可定制的LLM应用的开源框架,支持多种模式和交互行为。
- 关键的经验结果:在数学、编码、问题回答等多个领域证明了该框架的有效性。

--------------------------------------------------------------------------------

然后在后续的聊天中,教师不需要重复详细说明他们的偏好。

--------------------------------------------------------------------------------
user (to teachable_agent):

请总结一下这篇摘要。

《人工通用智能的火花:GPT-4的早期实验》
Sébastien Bubeck, Varun Chandrasekaran, Ronen Eldan, Johannes Gehrke, Eric Horvitz, Ece Kamar, Peter Lee, Yin Tat Lee, Yuanzhi Li, Scott Lundberg, Harsha Nori, Hamid Palangi, Marco Tulio Ribeiro, Yi Zhang
人工智能(AI)研究人员一直在开发和改进大型语言模型(LLMs),这些模型在各种领域和任务中展现出了令人瞩目的能力,挑战了我们对学习和认知的理解。OpenAI最新开发的模型GPT-4使用了前所未有的计算和数据规模进行训练。在本文中,我们报告了我们对GPT-4早期版本的调查,当时它还在OpenAI的积极开发中。我们认为(这个早期版本的)GPT-4是一批新的LLMs(例如ChatGPT和Google的PaLM)的一部分,这些模型展现出比以前的AI模型更具普遍智能。我们讨论了这些模型的不断增强的能力和影响。我们证明了除了掌握语言之外,GPT-4还可以解决涉及数学、编码、视觉、医学、法律、心理学等新颖且困难的任务,而无需任何特殊提示。此外,在所有这些任务中,GPT-4的表现与人类水平的表现非常接近,通常远远超过了ChatGPT等先前的模型。鉴于GPT-4的广度和深度能力,我们认为它可以合理地被视为人工通用智能(AGI)系统的早期(但仍不完整)版本。在我们对GPT-4的探索中,我们特别强调发现其局限性,并讨论了朝着更深入和更全面的AGI版本前进的挑战,包括可能需要追求超越下一个单词预测的新范式。最后,我们对最近技术飞跃的社会影响和未来研究方向进行了反思。

--------------------------------------------------------------------------------
teachable_agent (to user):

- 标题:《人工通用智能的火花:GPT-4的早期实验》
- 创新点:GPT-4是一个具有令人瞩目能力的LLM,展现出在数学、编码、视觉、医学、法律和心理学等各个领域的人类水平表现。
- 主要结果:GPT-4显著超越了先前的模型,表明它可能是AGI的早期版本;同时讨论了深入研究AGI所面临的局限性和挑战。

--------------------------------------------------------------------------------

示例4 - 学习新技能

用户可以通过教授可教授代理新的技能来扩展其能力,以完成具有挑战性的任务。通常最好先描述任务,然后(在同一轮中)提供一些提示或建议来解决任务。

AGI的火花论文对GPT-4在以下数学问题上进行了评估,它只能解决32%的问题。我们首先展示一个失败案例,然后教授代理一种策略,将GPT-4的成功率提高到95%以上。

用户(对可教授的代理):

考虑等式: 9 * 4 + 6 * 6 = 72 你能否修改等式左边的一个整数(不多于一个!),使得右边变成99?

  • 让我们一步一步来,先制定一个计划,然后写下你的解答,格式为:“解答是:A * B + C * D”。

步骤1:确定当前等式和右边的目标值。 当前等式:9 * 4 + 6 * 6 = 72 目标值:99

步骤2:确定可以在左边改变的数字。 可改变的数字:9、4、6(第一次出现)和6(第二次出现)

步骤3:评估左边每个数字的改变是否能得到目标值。 9 -> 如果改变,会得到更大的乘积。 4 -> 如果改变,乘积会增加或减少超过达到99所需的量。 6(第一次出现)-> 如果增加到7,则等式变为9 * 4 + 7 * 6 = 94,仍然不是99。 6(第二次出现)-> 如果增加到7,则等式变为9 * 4 + 6 * 7 = 99。

步骤4:写下解答。 解答是:9 * 4 + 6 * 7


用户(对可教授的代理):

考虑等式: 9 * 4 + 6 * 6 = 72 你能否修改等式左边的一个整数(不多于一个!),使得右边变成99?

  • 让我们一步一步来,先制定一个计划,然后写下你的解答,格式为:“解答是:A * B + C * D”。

以下是一些建议,可能会有所帮助:

  1. 用 E 表示右边的原始数字。
  2. 用 F 表示右边的最终数字。
  3. 计算两者之间的差值,G = F - E。
  4. 逐个检查左边的数字,直到找到一个能整除 G 的数字,允许使用负整数。
  5. 计算 J = G / H。这是 H 整除 G 的次数。
  6. 验证 J 是否为整数,以及 H * J 是否等于 G。
  7. 找到左边与 H 相乘的数字,并称其为 K。
  8. 将 K 改为 K + J。
  9. 重新计算左边的值,并验证是否等于 F。 最后,将解答写下来,格式为:“解答是:A * B + C * D”。

可教授的代理(对用户):

步骤1:确定右边的原始数字(E)和最终数字(F)。 E = 72 F = 99

步骤2:计算两者之间的差值,G = F - E。 G = 99 - 72 = 27

步骤3:逐个检查左边的数字,直到找到一个能整除 G 的数字,允许使用负整数。 9(能整除27) 4(不能) 6(第一次出现,不能) 6(第二次出现,不能)

步骤4:计算 J = G / H。这是 H 整除 G 的次数。 H = 9(因为9能整除27) J = 27 / 9 = 3

步骤5:验证 J 是否为整数,以及 H * J 是否等于 G。 H * J = 9 * 3 = 27 J = 3(是整数)

步骤6:找到左边与 H 相乘的数字,并称其为 K。 等式左边与9相乘的数字是4 因此,K = 4

步骤7:将 K 改为 K + J。 K + J = 4 + 3 = 7

步骤8:重新计算左边的值,并验证是否等于 F。 9 * 7 + 6 * 6 = 63 + 36 = 99(与 F 相等)

步骤9:写下解答。 解答是:9 * 7 + 6 * 6


在之后的对话中,用户不需要重复详细的建议。

--------------------------------------------------------------------------------
用户(对 teachable_agent):

考虑以下等式:
8 * 3 + 7 * 9 = 87
你能否修改等式左边的一个整数(不多于一个!),使得右边变成59?
- 让我们一步一步思考,制定一个计划,然后将你的解决方案写成:“解决方案是:A * B + C * D”。

--------------------------------------------------------------------------------
teachable_agent(对用户):

让我们按照建议来修改等式左边的一个整数,使得右边变成59:

1. 用 E 表示原来右边的数字:E = 87。
2. 用 F 表示最终右边的数字:F = 59。
3. 计算两者之间的差值,G = F - E:G = 59 - 87 = -28。
4. 逐个检查左边的数字,找到一个能整除 G 的数字:8、3、7、9。由于7能整除-28,我们将使用7(H = 7)。
5. 计算 J = G / H:J = -28 / 7 = -4。
6. 验证 J 是否为整数,并且 H * J = G:J 是整数,而且 7 * (-4) = -28。
7. 找到左边与 H(7)相乘的数字,并将其称为 K:K = 9。
8. 将 K 改为 K + J:K_new = 9 + (-4) = 5。
9. 重新计算左边的值,并验证其是否等于 F:(8 * 3) + (7 * 5) = 24 + 35 = 59。

解决方案是:8 * 3 + 7 * 5

--------------------------------------------------------------------------------

计划改进

  • 理解分布在多个回合中的用户指令。
  • 从代理的经验中学习,减少对明确的用户教学的依赖。
  • 在之前学到的技能基础上构建学习技能。

结论

“可教性”仍在积极研究和开发中。如果您发现任何问题或有改进的想法,请加入我们在该存储库中的讨论以及我们的 Discord 频道。我们期待看到您和社区的其他成员如何使用和改进 AutoGen 中的可教授代理!

· 14 min read
Li Jiang

最后更新:2024年4月4日;AutoGen 版本:v0.2.21

RAG 架构

TL;DR:

  • 我们介绍了 AutoGen 的 RAG 代理(RetrieveUserProxyAgent 和 RetrieveAssistantAgent),它们实现了检索增强生成,并介绍了其基本用法。
  • 我们展示了 RAG 代理的自定义,例如自定义嵌入函数、文本分割函数和向量数据库。
  • 我们还展示了 RAG 代理的两种高级用法,即与群聊集成和构建使用 Gradio 的聊天应用程序。

简介

检索增强已经成为一种实用且有效的方法,通过引入外部文档来缓解 LLM 的固有限制。在本博文中,我们介绍了 AutoGen 的 RAG 代理,它实现了检索增强生成。该系统由两个代理组成:检索增强用户代理(RetrieveUserProxyAgent)和检索增强助理代理(RetrieveAssistantAgent),它们都是基于 AutoGen 的内置代理进行扩展的。RAG 代理的整体架构如上图所示。

要使用检索增强聊天功能,需要初始化两个代理,包括检索增强用户代理和检索增强助理代理。初始化检索增强用户代理需要指定文档集合的路径。随后,检索增强用户代理可以下载文档,将其分割成特定大小的块,计算嵌入并将其存储在向量数据库中。一旦启动聊天,代理将根据以下步骤进行代码生成或问答:

  1. 检索增强用户代理根据嵌入相似性检索文档块,并将其与问题一起发送给检索增强助理。
  2. 检索增强助理使用 LLM 根据提供的问题和上下文生成代码或文本作为答案。如果 LLM 无法生成令人满意的响应,则指示其回复“更新上下文”给检索增强用户代理。
  3. 如果响应中包含代码块,检索增强用户代理将执行代码并将输出作为反馈发送。如果没有代码块或更新上下文的指令,则会终止对话。否则,它会更新上下文,并将问题与新上下文转发给检索增强助理。请注意,如果启用了人工输入请求,个人可以主动向检索增强助理发送任何反馈,包括“更新上下文”。
  4. 如果检索增强助理收到“更新上下文”,它会从检索增强用户代理请求与上下文最相似的下一个文档块作为新上下文。否则,它将继续生成答案。 根据反馈和聊天历史生成新的代码或文本。如果LLM无法生成答案,则会再次回复“Update Context”。这个过程可以重复多次。如果没有更多的文档可用于上下文,则对话终止。

RAG代理的基本用法

  1. 安装依赖项

在使用RAG代理之前,请使用[retrievechat]选项安装pyautogen。

pip install "pyautogen[retrievechat]"

RetrieveChat可以处理各种类型的文档。默认情况下,它可以处理纯文本和PDF文件,包括'txt'、'json'、'csv'、'tsv'、'md'、'html'、'htm'、'rtf'、'rst'、'jsonl'、'log'、'xml'、'yaml'、'yml'和'pdf'等格式。如果安装了unstructured,还可以支持其他文档类型,如'docx'、'doc'、'odt'、'pptx'、'ppt'、'xlsx'、'eml'、'msg'、'epub'等。

  • 在Ubuntu上安装unstructured
sudo apt-get update
sudo apt-get install -y tesseract-ocr poppler-utils
pip install unstructured[all-docs]

您可以使用autogen.retrieve_utils.TEXT_FORMATS找到所有支持的文档类型列表。

  1. 导入代理
import autogen
from autogen.agentchat.contrib.retrieve_assistant_agent import RetrieveAssistantAgent
from autogen.agentchat.contrib.retrieve_user_proxy_agent import RetrieveUserProxyAgent
  1. 创建一个名为“assistant”的'RetrieveAssistantAgent'实例和一个名为“ragproxyagent”的'RetrieveUserProxyAgent'实例
assistant = RetrieveAssistantAgent(
name="assistant",
system_message="You are a helpful assistant.",
llm_config=llm_config,
)

ragproxyagent = RetrieveUserProxyAgent(
name="ragproxyagent",
retrieve_config={
"task": "qa",
"docs_path": "https://raw.githubusercontent.com/microsoft/autogen/main/README.md",
},
)
  1. 初始化聊天并提问问题
assistant.reset()
ragproxyagent.initiate_chat(assistant, message=ragproxyagent.message_generator, problem="What is autogen?")

输出如下:

--------------------------------------------------------------------------------
assistant (to ragproxyagent):

AutoGen是一个框架,它使用可以相互对话以解决任务的多个代理来开发大型语言模型(LLM)应用程序。这些代理是可定制的、可对话的,并允许人类参与。它们可以在使用LLM、人类输入和工具的各种模式下运行。

--------------------------------------------------------------------------------
  1. 创建一个UserProxyAgent并提出同样的问题
assistant.reset()
userproxyagent = autogen.UserProxyAgent(name="userproxyagent")
userproxyagent.initiate_chat(assistant, message="What is autogen?")

输出如下:

助手(给 userproxyagent):

在计算机软件中,自动生成(autogen)是一种无需手动编码即可自动生成程序代码的工具。它通常用于软件工程、游戏开发和网页开发等领域,以加快开发过程并减少错误。自动生成工具通常使用预先编程的规则、模板和数据来为重复性任务生成代码,例如生成用户界面、数据库模式和数据模型。一些常用的自动生成工具包括 Visual Studio 的代码生成器和 Unity 的资源商店。


你可以看到 UserProxyAgent 的输出与我们的 autogen 不相关,因为 autogen 的最新信息不在 ChatGPT 的训练数据中。而 RetrieveUserProxyAgent 的输出是正确的,因为它可以根据给定的文档文件执行检索增强生成。

自定义 RAG 代理

RetrieveUserProxyAgent 可以通过 retrieve_config 进行自定义。根据不同的用例,有几个参数可以配置。在本节中,我们将展示如何自定义嵌入函数、文本分割函数和向量数据库。

自定义嵌入函数

默认情况下,我们将使用 Sentence Transformers 及其预训练模型来计算嵌入。但你可能希望使用 OpenAI、Cohere、HuggingFace 或其他嵌入函数。

  • OpenAI
from chromadb.utils import embedding_functions

openai_ef = embedding_functions.OpenAIEmbeddingFunction(
api_key="YOUR_API_KEY",
model_name="text-embedding-ada-002"
)

ragproxyagent = RetrieveUserProxyAgent(
name="ragproxyagent",
retrieve_config={
"task": "qa",
"docs_path": "https://raw.githubusercontent.com/microsoft/autogen/main/README.md",
"embedding_function": openai_ef,
},
)
  • HuggingFace
huggingface_ef = embedding_functions.HuggingFaceEmbeddingFunction(
api_key="YOUR_API_KEY",
model_name="sentence-transformers/all-MiniLM-L6-v2"
)

更多示例可以在这里找到。

自定义文本分割函数

在将文档存储到向量数据库之前,我们需要将文本分割成块。虽然我们在 autogen 中实现了一个灵活的文本分割器,但你可能仍然想使用不同的文本分割器。也有一些现有的文本分割工具可以重用。

例如,你可以使用 langchain 中的所有文本分割器。

from langchain.text_splitter import RecursiveCharacterTextSplitter

recur_spliter = RecursiveCharacterTextSplitter(separators=["\n", "\r", "\t"])

ragproxyagent = RetrieveUserProxyAgent(
name="ragproxyagent",
retrieve_config={
"task": "qa",
"docs_path": "https://raw.githubusercontent.com/microsoft/autogen/main/README.md",
"custom_text_split_function": recur_spliter.split_text,
},
)

自定义向量数据库

我们使用 chromadb 作为默认的向量数据库,你也可以通过简单地覆盖 RetrieveUserProxyAgentretrieve_docs 函数来替换为任何其他向量数据库。

例如,你可以使用 Qdrant,如下所示:

# 创建 qdrant 客户端
from qdrant_client import QdrantClient

client = QdrantClient(url="***", api_key="***")

# 包装 RetrieveUserProxyAgent
from litellm import embedding as test_embedding
from autogen.agentchat.contrib.retrieve_user_proxy_agent import RetrieveUserProxyAgent
from qdrant_client.models import SearchRequest, Filter, FieldCondition, MatchText

class QdrantRetrieveUserProxyAgent(RetrieveUserProxyAgent):
def query_vector_db(
self,
query_texts: List[str],
n_results: int = 10,
search_string: str = "",
**kwargs,
) -> Dict[str, Union[List[str], List[List[str]]]]:
# 在这里定义你自己的查询函数
embed_response = test_embedding('text-embedding-ada-002', input=query_texts)

all_embeddings: List[List[float]] = []

for item in embed_response['data']:
all_embeddings.append(item['embedding'])

search_queries: List[SearchRequest] = []

for embedding in all_embeddings:
search_queries.append(
SearchRequest(
vector=embedding,
filter=Filter(
must=[
FieldCondition(
key="page_content",
match=MatchText(
text=search_string,
)
)
]
),
limit=n_results,
with_payload=True,
)
)

search_response = client.search_batch(
collection_name="{你的集合名称}",
requests=search_queries,
)

return {
"ids": [[scored_point.id for scored_point in batch] for batch in search_response],
"documents": [[scored_point.payload.get('page_content', '') for scored_point in batch] for batch in search_response],
"metadatas": [[scored_point.payload.get('metadata', {}) for scored_point in batch] for batch in search_response]
}

def retrieve_docs(self, problem: str, n_results: int = 20, search_string: str = "", **kwargs):
results = self.query_vector_db(
query_texts=[problem],
n_results=n_results,
search_string=search_string,
**kwargs,
)

self._results = results


# 使用 QdrantRetrieveUserProxyAgent
qdrantragagent = QdrantRetrieveUserProxyAgent(
name="ragproxyagent",
human_input_mode="NEVER",
max_consecutive_auto_reply=2,
retrieve_config={
"task": "qa",
},
)

qdrantragagent.retrieve_docs("什么是 Autogen?", n_results=10, search_string="autogen")

RAG 代理的高级用法

与其他代理在群聊中集成

在群聊中使用 RetrieveUserProxyAgent 和在两个代理之间的聊天中使用几乎是一样的。唯一的区别是你需要使用 RetrieveUserProxyAgent 初始化聊天。在群聊中不需要使用 RetrieveAssistantAgent

然而,在某些情况下,你可能希望使用另一个代理来初始化聊天。为了充分利用 RetrieveUserProxyAgent 的优势,你需要从一个函数中调用它。

boss = autogen.UserProxyAgent(
name="Boss",
is_termination_msg=termination_msg,
human_input_mode="TERMINATE",
system_message="提问问题和分配任务的老板。",
)

boss_aid = RetrieveUserProxyAgent(
name="Boss_Assistant",
is_termination_msg=termination_msg,
system_message="拥有额外内容检索能力,用于解决困难问题的助手。",
human_input_mode="NEVER",
max_consecutive_auto_reply=3,
retrieve_config={
"task": "qa",
},
code_execution_config=False, # 在这种情况下,我们不想执行代码。
)

coder = autogen.AssistantAgent(
name="Senior_Python_Engineer",
is_termination_msg=termination_msg,
system_message="你是一名高级 Python 工程师。在完成所有工作后回复“TERMINATE”。",
llm_config={"config_list": config_list, "timeout": 60, "temperature": 0},
)

pm = autogen.AssistantAgent(
name="Product_Manager",
is_termination_msg=termination_msg,
system_message="你是一名产品经理。在完成所有工作后回复“TERMINATE”。",
llm_config={"config_list": config_list, "timeout": 60, "temperature": 0},
)

reviewer = autogen.AssistantAgent(
name="Code_Reviewer",
is_termination_msg=termination_msg,
system_message="你是一名代码审查员。在完成所有工作后回复“TERMINATE”。",
llm_config={"config_list": config_list, "timeout": 60, "temperature": 0},
)

def retrieve_content(
message: Annotated[
str,
"经过优化的消息,保留原始含义,可用于检索内容以进行代码生成和问题回答。",
],
n_results: Annotated[int, "结果数量"] = 3,
) -> str:
boss_aid.n_results = n_results # 设置要检索的结果数量。
# 检查是否需要更新上下文。
update_context_case1, update_context_case2 = boss_aid._check_update_context(message)
if (update_context_case1 or update_context_case2) and boss_aid.update_context:
boss_aid.problem = message if not hasattr(boss_aid, "problem") else boss_aid.problem
_, ret_msg = boss_aid._generate_retrieve_user_reply(message)
else:
_context = {"problem": message, "n_results": n_results}
ret_msg = boss_aid.message_generator(boss_aid, None, _context)
return ret_msg if ret_msg else message

for caller in [pm, coder, reviewer]:
d_retrieve_content = caller.register_for_llm(
description="检索内容以进行代码生成和问题回答。",
api_style="function"
)(retrieve_content)

for executor in [boss, pm]:
executor.register_for_execution()(d_retrieve_content)

groupchat = autogen.GroupChat(
agents=[boss, pm, coder, reviewer],
messages=[],
max_round=12,
speaker_selection_method="round_robin",
allow_repeat_speaker=False,
)

llm_config = {"config_list": config_list, "timeout": 60, "temperature": 0}
manager = autogen.GroupChatManager(groupchat=groupchat, llm_config=llm_config)

# 作为用户代理代理开始与老板聊天。
boss.initiate_chat(
manager,
message="如何在 FLAML 中使用 Spark 进行并行训练?给我一个示例代码。",
)

使用 Gradio 构建聊天应用程序

现在,让我们用 AutoGen 和 Gradio 来封装它,创建一个聊天应用程序。

使用 AutoGen 的 RAG ChatBot

# 初始化代理
def initialize_agents(config_list, docs_path=None):
...
return assistant, ragproxyagent

# 初始化聊天
def initiate_chat(config_list, problem, queue, n_results=3):
...
assistant.reset()
try:
ragproxyagent.a_initiate_chat(
assistant, problem=problem, silent=False, n_results=n_results
)
messages = ragproxyagent.chat_messages
messages = [messages[k] for k in messages.keys()][0]
messages = [m["content"] for m in messages if m["role"] == "user"]
print("messages: ", messages)
except Exception as e:
messages = [str(e)]
queue.put(messages)

# 将 AutoGen 部分封装成一个函数
def chatbot_reply(input_text):
"""通过终端与代理进行聊天。"""
queue = mp.Queue()
process = mp.Process(
target=initiate_chat,
args=(config_list, input_text, queue),
)
process.start()
try:
messages = queue.get(timeout=TIMEOUT)
except Exception as e:
messages = [str(e) if len(str(e)) > 0 else "无效的 OpenAI 请求,请检查您的 API 密钥。"]
finally:
try:
process.terminate()
except:
pass
return messages

...

# 使用 Gradio 设置用户界面
with gr.Blocks() as demo:
...
assistant, ragproxyagent = initialize_agents(config_list)

chatbot = gr.Chatbot(
[],
elem_id="chatbot",
bubble_full_width=False,
avatar_images=(None, (os.path.join(os.path.dirname(__file__), "autogen.png"))),
# height=600,
)

txt_input = gr.Textbox(
scale=4,
show_label=False,
placeholder="输入文本并按回车键",
container=False,
)

with gr.Row():
txt_model = gr.Dropdown(
label="模型",
choices=[
"gpt-4",
"gpt-35-turbo",
"gpt-3.5-turbo",
],
allow_custom_value=True,
value="gpt-35-turbo",
container=True,
)
txt_oai_key = gr.Textbox(
label="OpenAI API 密钥",
placeholder="输入密钥并按回车键",
max_lines=1,
show_label=True,
value=os.environ.get("OPENAI_API_KEY", ""),
container=True,
type="password",
)
...

clear = gr.ClearButton([txt_input, chatbot])

...

if __name__ == "__main__":
demo.launch(share=True)

在线应用程序和源代码托管在 HuggingFace 上。随时试用一下吧!

阅读更多

您可以查看更多 RAG 使用案例的示例笔记本:

· 3 min read
Jiale Liu

TL;DR: 我们演示了如何使用 AutoGen 进行本地 LLM 应用。以 FastChat 为例,我们将使用 ChatGLMv2-6b 进行端点初始化和推理。

准备工作

克隆 FastChat

FastChat 提供了与 OpenAI 兼容的 API,因此您可以将 FastChat 用作本地的 OpenAI API 替代品。但是,为了使其正常工作,需要对其代码进行轻微修改。

git clone https://github.com/lm-sys/FastChat.git
cd FastChat

下载检查点

ChatGLM-6B 是基于通用语言模型 (GLM) 框架的开放式双语语言模型,具有 62 亿个参数。ChatGLM2-6B 是其第二代版本。

在从 HuggingFace Hub 下载之前,您需要安装 Git LFS (安装说明)

git clone https://huggingface.co/THUDM/chatglm2-6b

启动服务器

首先,启动控制器

python -m fastchat.serve.controller

然后,启动模型工作进程

python -m fastchat.serve.model_worker --model-path chatglm2-6b

最后,启动 RESTful API 服务器

python -m fastchat.serve.openai_api_server --host localhost --port 8000

通常情况下,这将正常工作。但是,如果遇到像 这样的 错误,可以通过在 fastchat/protocol/api_protocol.pyfastchat/protocol/openai_api_protocol.py 中注释掉所有包含 finish_reason 的行来解决问题。修改后的代码如下所示:

class CompletionResponseChoice(BaseModel):
index: int
text: str
logprobs: Optional[int] = None
# finish_reason: Optional[Literal["stop", "length"]]

class CompletionResponseStreamChoice(BaseModel):
index: int
text: str
logprobs: Optional[float] = None
# finish_reason: Optional[Literal["stop", "length"]] = None

使用 oai.Completion 与模型交互(需要 openai<1)

现在,可以通过 openai-python 库以及 autogen.oai.Completionautogen.oai.ChatCompletion 直接访问模型。

from autogen import oai

# 创建一个文本补全请求
response = oai.Completion.create(
config_list=[
{
"model": "chatglm2-6b",
"base_url": "http://localhost:8000/v1",
"api_type": "openai",
"api_key": "NULL", # 只是一个占位符
}
],
prompt="你好",
)
print(response)

# 创建一个对话补全请求
response = oai.ChatCompletion.create(
config_list=[
{
"model": "chatglm2-6b",
"base_url": "http://localhost:8000/v1",
"api_type": "openai",
"api_key": "NULL",
}
],
messages=[{"role": "user", "content": "你好"}]
)
print(response)

如果您想切换到不同的模型,请下载它们的检查点,并在启动模型工作器时指定模型路径。

与多个本地 LLM 进行交互

如果您想与本地机器上的多个 LLM 进行交互,请将上面的 model_worker 步骤替换为多模型变体:

python -m fastchat.serve.multi_model_worker \
--model-path lmsys/vicuna-7b-v1.3 \
--model-names vicuna-7b-v1.3 \
--model-path chatglm2-6b \
--model-names chatglm2-6b

推理代码如下:

from autogen import oai

# 创建一个聊天完成请求
response = oai.ChatCompletion.create(
config_list=[
{
"model": "chatglm2-6b",
"base_url": "http://localhost:8000/v1",
"api_type": "openai",
"api_key": "NULL",
},
{
"model": "vicuna-7b-v1.3",
"base_url": "http://localhost:8000/v1",
"api_type": "openai",
"api_key": "NULL",
}
],
messages=[{"role": "user", "content": "Hi"}]
)
print(response)

进一步阅读