NSDT工具推荐Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - AI模型在线查看 - Three.js虚拟轴心开发包 - 3D模型在线减面 - STL模型在线切割 - 3D道路快速建模

最近,关于 AI 智能体或AI代理(AI Agent)的讨论很多。受这种炒作的影响,我阅读了一些资料,偶然发现了 AutoGen,这是一个构建 AI 代理的很棒的库。但 AI 代理到底是什么?为什么它们很重要?让我们深入研究一下。

LLM 已经存在了几年,它们正在迅速向 AI 代理和 Agentic 工作流程发展。别误会我的意思,LLM 很棒,但它们在自行实现自动化方面仍然效率不高。通过消耗大量语言数据,LLM 与其他工具相结合是一种非常有效的方式,可以充分利用 LLM 所拥有的通用智能。AI 代理是可以自主执行任务的软件实体,可以与环境交互以做出决策。它们正在彻底改变我们解决问题的方式,从客户服务聊天机器人到复杂的数据分析。今天,我很高兴向你展示如何使用 AutoGen 构建一个简单的 AI 代理。

准备好了吗?让我们开始吧!

1、为什么 AI 代理很重要

AI 代理带来了几个好处:

  • 自动化:它们无需人工干预即可处理重复性任务。
  • 效率:它们处理数据和执行任务的速度比人类更快。
  • 可扩展性:它们可以全天候运行,提供服务而无需停机。
  • 智能:它们从交互中学习和改进,随着时间的推移变得越来越好。

鉴于这些优势,AI 代理正在被从医疗保健到金融等各个行业采用。

2、使用 AutoGen 构建一个简单的 AI 代理

让我们动手使用 AutoGen 构建一个基本的 AI 代理。为了进行演示,我们将解决 LeetCode 中的“在二叉树中分配硬币”问题。这个问题是编码面试中的经典问题,你需要在数组中找到两个相加等于目标的数字。Colab 链接请点击这里

2.1 安装 AutoGen

首先,我们需要安装 AutoGen 库。在你的环境中运行以下命令:

!pip install pyautogen -q --progress-bar off

2.2 设置你的环境

我使用 Google Colab 进行此演示。以下是如何设置你的环境并安全地加载你的 OpenAI API 密钥:

import os
import autogen
from google.colab import userdata

# Load your OpenAI API key
userdata.get('OPENAI_API_KEY')

llm_config = {
    "config_list": [{"model": "gpt-3.5-turbo", "api_key": userdata.get('OPENAI_API_KEY')}],
    "cache_seed": 0,
    "temperature": 0,
}

2.3 定义问题

我们将使用 LeetCode 中的 LC Medium“在二叉树中分配硬币”问题:

LEETCODE_QUESTION = """
Title : Distribute Coins in a binary tree

You are given the root of a binary tree with n nodes where each node in the tree has node.val coins. There are n coins in total throughout the whole tree.

In one move, we may choose two adjacent nodes and move one coin from one node to another. A move may be from parent to child, or from child to parent.

Return the minimum number of moves required to make every node have exactly one coin.

 

Example 1:


Input: root = [3,0,0]
Output: 2
Explanation: From the root of the tree, we move one coin to its left child, and one coin to its right child.
Example 2:


Input: root = [0,3,0]
Output: 3
Explanation: From the left child of the root, we move two coins to the root [taking two moves]. Then, we move one coin from the root of the tree to the right child.

Follow-up: Can you come up with an algorithm that has a better time complexity?
"""

4、设置代理

AutoGen 使用两种类型的代理: AssistantAgentUserProxyAgent

AssistantAgent 建议代码解决方案,而 UserProxyAgent 执行代码并检查其是否正常工作:

SYSTEM_MESSAGE = """You are a helpful AI assistant. Solve tasks using your coding and language skills..."""

assistant = autogen.AssistantAgent(
    name="assistant",
    llm_config=llm_config,
    system_message=SYSTEM_MESSAGE
)

user_proxy = autogen.UserProxyAgent(
    name="user_proxy",
    human_input_mode="NEVER",
    max_consecutive_auto_reply=4,
    is_termination_msg=lambda x: x.get("content", "").rstrip().endswith("TERMINATE"),
    code_execution_config={
        "work_dir": "coding",
        "use_docker": False,
    },
)

human_input_mode 设置为“NEVER”,因为我们不打算自己提供任何输入,而 max_consecutive_auto_reply 限制了对话轮次。

5、发起对话

我们将通过从 UserProxyAgent 向我们的助手发送消息来开始对话。

with autogen.Cache.disk(cache_seed=7) as cache:
  chat_res = user_proxy.initiate_chat(
      assistant,
      message="""Solve the following LeetCode problem and also comment on its time and space complexity:\n\n""" + LEETCODE_QUESTION
  )

以下是输出对话的片段:

user_proxy (to assistant):

Solve the following LeetCode problem and also comment on its time and space complexity:


Title : Distribute Coins in a binary tree

You are given the root of a binary tree with n nodes where each node in the tree has node.val coins. There are n coins in total throughout the whole tree.

In one move, we may choose two adjacent nodes and move one coin from one node to another. A move may be from parent to child, or from child to parent.

Return the minimum number of moves required to make every node have exactly one coin.

 

Example 1:


Input: root = [3,0,0]
Output: 2
Explanation: From the root of the tree, we move one coin to its left child, and one coin to its right child.
Example 2:


Input: root = [0,3,0]
Output: 3
Explanation: From the left child of the root, we move two coins to the root [taking two moves]. Then, we move one coin from the root of the tree to the right child.

Follow-up: Can you come up with an algorithm that has a better time complexity?


--------------------------------------------------------------------------------
assistant (to user_proxy):

To solve this problem, we can perform a depth-first search (DFS) traversal of the binary tree and calculate the excess coins at each node. The excess coins at a node can be calculated as the sum of coins at the node and the excess coins from its left and right children, minus 1 (since the node itself should have 1 coin).

Here is the Python code to solve the problem:

```python
class Solution:
    def distributeCoins(self, root: TreeNode) -> int:
        self.moves = 0
        
        def dfs(node):
            if not node:
                return 0
            
            left_excess = dfs(node.left)
            right_excess = dfs(node.right)
            
            self.moves += abs(left_excess) + abs(right_excess)
            
            return node.val + left_excess + right_excess - 1
        
        dfs(root)
        
        return self.moves
```

Time complexity analysis:
- The DFS traversal visits each node once, so the time complexity is O(n), where n is the number of nodes in the binary tree.

Space complexity analysis:
- The space complexity is O(h), where h is the height of the binary tree. This is due to the recursive calls in the DFS traversal. In the worst case, the space complexity can be O(n) for a skewed tree.

To improve the time complexity, we can modify the algorithm to avoid redundant calculations and achieve a linear time complexity. This can be done by returning both the excess coins and the number of moves from the DFS function. This way, we can eliminate the need to traverse the tree twice.

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

>>>>>>>> EXECUTING CODE BLOCK 0 (inferred language is python)...
user_proxy (to assistant):

exitcode: 1 (execution failed)
Code output: 
Traceback (most recent call last):
  File "", line 1, in <module>
    class Solution:
  File "", line 2, in Solution
    def distributeCoins(self, root: TreeNode) -> int:
NameError: name 'TreeNode' is not defined

注意 UserProxyAgent 是如何出错的。它会回调另一个代理来获取解决方案:

--------------------------------------------------------------------------------
assistant (to user_proxy):

It seems like the code snippet I provided is missing the definition of the `TreeNode` class. Here is an updated version of the code that includes the definition of the `TreeNode` class:

```python
# Definition for a binary tree node.
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def distributeCoins(self, root: TreeNode) -> int:
        self.moves = 0
        
        def dfs(node):
            if not node:
                return 0
            
            left_excess = dfs(node.left)
            right_excess = dfs(node.right)
            
            self.moves += abs(left_excess) + abs(right_excess)
            
            return node.val + left_excess + right_excess - 1
        
        dfs(root)
        
        return self.moves
```

You can now use this updated code to solve the LeetCode problem "Distribute Coins in a binary tree".

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

>>>>>>>> EXECUTING CODE BLOCK 0 (inferred language is python)...
user_proxy (to assistant):

exitcode: 0 (execution succeeded)
Code output: 


--------------------------------------------------------------------------------
assistant (to user_proxy):

Great! I'm glad to hear that the code executed successfully. If you have any more questions or need further assistance, feel free to ask!

--------------------------------------------------------------------------------
user_proxy (to assistant):



--------------------------------------------------------------------------------
assistant (to user_proxy):

If you have any more questions or need help with anything else, feel free to ask. I'm here to help!

--------------------------------------------------------------------------------
user_proxy (to assistant):



--------------------------------------------------------------------------------
assistant (to user_proxy):

If you have any questions in the future or need assistance, don't hesitate to ask. Have a great day!

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

6、结束语

通过使用 AutoGen 的可对话代理,我们自动验证了 LLM 建议的 Python 代码是否有效,并创建了一个框架,LLM 可以通过读取控制台输出来响应语法或逻辑错误。


原文链接:AI Agents Are All You Need ? Hands-on guide to creating a better code-solving AI Agent with AutoGen

BimAnt翻译整理,转载请标明出处