AutoGen: 代码执行与工具调用

上一篇介绍了AutoGen的基本概念及基础用法,这一篇通过一些完整的示例来了解其更多的用法(人类输入及终止对话、代码生成与执行、工具的使用)。

人类输入及终止对话

在 AutoGen 的 ConversableAgent 中,人工循环组件位于自动回复组件之前。它可以拦截传入的消息并决定是将其传递给自动回复组件还是提供人工反馈。下图说明了该设计。

通过设置human_input_mode来决定是否使用人工输入。

  • NEVER:从不请求人工输入。
  • TERMINATE (默认):仅当满足终止条件时,才会请求人工输入。请注意,在此模式下,如果人类选择拦截和回复,对话将继续,并且使用的max_consectuive_auto_reply计数器将被重置
  • ALWAYS:始终请求人工输入,人工可以选择跳过并触发自动回复、拦截和提供反馈或终止对话。请注意,在此模式下,max_consecutive_auto_reply计数器不会被重置 而终止对话可以通过指定下面三种属性实现:
  • max_consecutive_auto_reply
  • is_termination_msg
  • max_turns

官方的示例可以很好的说明之间的关系:

ini 复制代码
agent_with_number = ConversableAgent(
    "agent_with_number",
    system_message="You are playing a game of guess-my-number. You have the number 53 in your mind, and I will try to guess it. If I guess too high, say 'too high', if I guess too low, say 'too low'. ",
    llm_config={"config_list": config.config_list},
    is_termination_msg=lambda msg: "53" in msg["content"],
    max_consecutive_auto_reply=10,
    human_input_mode="TERMINATE",
)

agent_guess_number = ConversableAgent(
    "agent_guess_number",
    system_message="I have a number in my mind, and you will try to guess it. If I say 'too high', you should guess a lower number. If I say 'too low', you should guess a higher number. ",
    llm_config={"config_list": config.config_list},
    human_input_mode="NEVER",
)

result = agent_with_number.initiate_chat(
    agent_guess_number,
    message="I have a number between 1 and 100. Guess it!",
    #max_turns=2
)

我们来看各种组合的效果:

  • agent_with_number 的 human_input_mode为TERMINATE时,在猜中53(满足is_termination_msg的条件)时则会请求人类输入,当设置为NEVER时,则会自动结束
  • agent_with_number 的 max_consecutive_auto_reply设置为1时,则会在自动回复一次后下次回复时请求人类输入;human_input_mode为NEVER时,则在自动回复一轮后自动结束
  • 设置了max_turns=2时,则会在自动问答回复两轮后结束 以上条件都是哪个先满足就执行哪个

代码生成与执行

AutoGen 提供了两种执行代码的方式:本地执行和在 Docker 容器中执行。同时也提供了三种代码执行器组件,通过设置code_execution_config来开启及选择执行器。

通过以下示例来看一下AutoGen的代码生成与执行:

ini 复制代码
assistant = autogen.AssistantAgent(
    name="assistant",
    llm_config={
        "seed": 42, 
        "config_list": config_list,  
        "temperature": 0, 
    },  
)

user_proxy = autogen.UserProxyAgent(
    name="user_proxy",
    human_input_mode="NEVER",
    max_consecutive_auto_reply=10,
    is_termination_msg=lambda x: x.get("content", "").rstrip().endswith("TERMINATE"),
    code_execution_config={
        "work_dir": "coding",
        "use_docker": False,
        # "executor": executor
    },
)
user_proxy.initiate_chat(assistant,message="在我的电脑桌面上创建一个名为"hello.txt"的文件,写入:你好,"
)

这里使用UserProxyAgent和AssistantAgent,均继承于ConversableAgent,只是在部分功能上进行了默认值设定及部分功能的限制,如:AssistantAgent是无法进行代码的执行操作。 运行结果如下:

lua 复制代码
user_proxy (to assistant):
    在我的电脑桌面上创建一个名为"hello.txt"的文件,写入:你好,
--------------------------------------------------------------------------------
assistant (to user_proxy):
这个任务可以通过Python的内置函数来完成。我们将使用`os`模块来获取桌面路径,然后使用`open`函数来创建并写入文件。
请执行以下Python代码:
    ```python
    import os
    # 获取桌面路径
    desktop_path = os.path.join(os.path.expanduser("~"), 'Desktop')
    # 创建并写入文件
    with open(os.path.join(desktop_path, 'hello.txt'), 'w', encoding='utf-8') as f:
        f.write('你好,')
    ```
这段代码首先获取了桌面的路径,然后在这个路径上创建了一个名为"hello.txt"的文件,并写入了"你好,"。
--------------------------------------------------------------------------------
>>>>>>>> EXECUTING CODE BLOCK 0 (inferred language is python)...
user_proxy (to assistant):

exitcode: 0 (execution succeeded)
Code output: 
--------------------------------------------------------------------------------
assistant (to user_proxy):
看起来代码执行成功了。现在,你应该在桌面上看到一个名为"hello.txt"的文件,文件内容为"你好,"。
TERMINATE
--------------------------------------------------------------------------------
Process finished with exit code 0

运行完成,可以发现桌面上多了hello.txt的文件。

executor 可以通过以下方式设置:

ini 复制代码
executor = LocalCommandLineCodeExecutor(
    timeout=10, 
    work_dir="coding",
)

work_dir将会保存生成的代码,再执行过程中如果有异常会重新生成代码,直到终止或成功;如果缺少包也会自行导入(当然也可以设置使用默认的不允许从外部导入),因此执行LLM生产的代码有一定的危险性,建议在docker环境下,使用DockerCommandLineCodeExecutor 此外,AutoGen 也可以直接执行用户给定的代码或者代码块等,跳过自动生成的环节。

ini 复制代码
executor = LocalCommandLineCodeExecutor(work_dir="coding", functions=[add_two_numbers])

code = f"""
from functions import add_two_numbers
print(add_two_numbers(1, 2))
"""
result = executor.execute_code_blocks(
    code_blocks=[
        CodeBlock(language="python", code=code),
    ]
)

目前仅支持Python且该函数不得依赖于任何全局变量或外部状态。如果需要导入或引入外部依赖,可在方法上使用@with_requirements引入,也可以将代码以prompt的方式告诉Agent,通过对话调用。

工具的使用

工具的使用给AutoGen带来了无限的可能,来看一下AutoGen是如何使用工具的。

创建Agent

ini 复制代码
assistant = ConversableAgent(
    name="Assistant",
    system_message="You are a helpful AI assistant. You can help with simple calculations. Return 'TERMINATE' when the task is done.",
    llm_config={"config_list": config.config_list},
)


user_proxy = ConversableAgent(
    name="User",
    llm_config=False,
    is_termination_msg=lambda msg: msg.get("content") is not None and "TERMINATE" in msg["content"],
    human_input_mode="NEVER",
)

工具创建

首先创建一个简单的函数做为将要调用的工具:

php 复制代码
def calculator(a: int, b: int):
    return a + b

也可以使用 Pydantic 模型作为类型提示来提供更复杂的类型模式:

csharp 复制代码
class CalculatorParams(BaseModel):
    a: Annotated[int, Field(description="数字int类型")]
    b: Annotated[int, Field(description="数字int类型")]


def calculator_schema(params: Annotated[CalculatorParams, "Input to the calculator."]) -> int:
    return params.a + params.b

工具注册

将工具注册给需要使用的Agent,assistant用于选择需要使用的工具,User负责调用工具。

  • 方式一
ini 复制代码
assistant.register_for_llm(name="calculator", description="A simple calculator")(calculator)
user_proxy.register_for_execution(name="calculator")(calculator)
  • 方式二
ini 复制代码
register_function(
    calculator,
    caller=assistant,  
    executor=user_proxy, 
    name="calculator_schema", 
    description="A simple calculator",
)

工具调用

注册完成后,就可以在对话中调用工具了。

ini 复制代码
chat_result = user_proxy.initiate_chat(assistant, message="What is 10+10 ?")

以下是运行结果:

markdown 复制代码
User (to Assistant):

What is 10+10 ?
--------------------------------------------------------------------------------
>>>>>>>> USING AUTO REPLY...
Assistant (to User):
***** Suggested tool call (call_RLMDtORVocPZp6tEgkQC6VDa): calculator_schema *****
Arguments: 
{
  "a": 10,
  "b": 10
}
**********************************************************************************
--------------------------------------------------------------------------------
>>>>>>>> EXECUTING FUNCTION calculator_schema...
User (to Assistant):
User (to Assistant):
***** Response from calling tool (call_RLMDtORVocPZp6tEgkQC6VDa) *****
20
**********************************************************************
--------------------------------------------------------------------------------
>>>>>>>> USING AUTO REPLY...
Assistant (to User):
The result of 10 + 10 is 20.
--------------------------------------------------------------------------------
User (to Assistant):
--------------------------------------------------------------------------------
>>>>>>>> USING AUTO REPLY...
Assistant (to User):
TERMINATE
--------------------------------------------------------------------------------

更多功能示例、应用及实战技巧相关示例将会持续更新

解锁更多精彩欢迎关注公众号:闲人张

相关推荐
会飞的Anthony几秒前
基于Python的自然语言处理系列(14):TorchText + biGRU + Attention + Teacher Forcing
人工智能·自然语言处理
jun7788953 分钟前
机器学习-监督学习:朴素贝叶斯分类器
人工智能·学习·机器学习
FL16238631294 分钟前
基于yolov5的混凝土缺陷检测系统python源码+onnx模型+评估指标曲线+精美GUI界面
人工智能·python·yolo
Kenneth風车8 分钟前
【第十三章:Sentosa_DSML社区版-机器学习聚类】
人工智能·低代码·机器学习·数据分析·聚类
jndingxin15 分钟前
OpenCV运动分析和目标跟踪(4)创建汉宁窗函数createHanningWindow()的使用
人工智能·opencv·目标跟踪
机器之心17 分钟前
o1 带火的 CoT 到底行不行?新论文引发了论战
android·人工智能
程序员-珍19 分钟前
SpringBoot v2.6.13 整合 swagger
java·spring boot·后端
机器之心23 分钟前
从架构、工艺到能效表现,全面了解 LLM 硬件加速,这篇综述就够了
android·人工智能
海里真的有鱼27 分钟前
好文推荐-架构
后端
jndingxin1 小时前
OpenCV特征检测(1)检测图像中的线段的类LineSegmentDe()的使用
人工智能·opencv·计算机视觉