命令行代码执行器
命令行代码执行是最简单的代码执行形式。 通常来说,它会将每个代码块保存到一个文件中,然后执行该文件。 这意味着每个代码块都在一个新的进程中执行。这种执行器有两种形式:
- Docker
(
DockerCommandLineCodeExecutor
) - 这是所有命令在Docker容器中执行的地方 - 本地
(
LocalCommandLineCodeExecutor
) - 这是所有命令在主机上执行的地方
此执行器类型与AutoGen中的旧版代码执行类似。
Docker
DockerCommandLineCodeExecutor
将创建一个Docker容器,并在该容器内运行所有命令。默认使用的镜像是 python:3-slim
,可以通过向构造函数传递 image
参数来自定义。如果本地找不到镜像,该类将尝试拉取它。因此,在本地构建镜像就足够了。该镜像与执行器兼容的唯一要求是安装 sh
和 python
。因此,创建自定义镜像是确保所需系统依赖项可用的简单且有效的方式。
您可以将执行器用作上下文管理器,以确保在使用后清理容器。否则,当程序退出时,将使用atexit
模块来停止容器。
检查容器
如果您希望在AutoGen使用完容器后保留它(例如用于检查容器),那么在创建执行器时可以将auto_remove
参数设置为False
。也可以将stop_container
设置为False
,以防止在执行结束时停止容器。
示例
from pathlib import Path
from autogen.coding import CodeBlock, DockerCommandLineCodeExecutor
work_dir = Path("coding")
work_dir.mkdir(exist_ok=True)
with DockerCommandLineCodeExecutor(work_dir=work_dir) as executor:
print(
executor.execute_code_blocks(
code_blocks=[
CodeBlock(language="python", code="print('Hello, World!')"),
]
)
)
exit_code=0 output='Hello, World!\n' code_file='coding/tmp_code_07da107bb575cc4e02b0e1d6d99cc204.py'
在Docker中将AutoGen与基于Docker的executor结合使用
将您的AutoGen应用程序打包到Docker镜像中是很有意义的。但是,如何让您的容器化应用程序在不同的容器中执行代码呢?
推荐的方法称为“Docker out of Docker”,其中将Docker套接字挂载到主AutoGen容器,以便它可以在主机上生成和控制“兄弟”容器。这比所谓的“Docker in Docker”更好,其中主容器运行一个Docker守护进程并在自身内部生成容器。您可以在此这里阅读更多相关信息。
要实现这一点,你需要将Docker socket挂载到AutoGen容器中。这可以通过将以下内容添加到docker run
命令中来完成:
-v /var/run/docker.sock:/var/run/docker.sock
这将允许AutoGen容器在主
如果您需要将工作目录绑定到AutoGen容器,但该目录属于您的宿主机,请使用bind_dir
参数。这将允许主AutoGen容器将宿主机目录绑定到新生成的容器,并使其能够访问该目录中的文件。如果未指定bind_dir
,它将回退到work_dir
。
本地
本地版本将在您的本地系统上运行代码。使用时请小心。
要在主机上执行代码,即在运行AutoGen的机器上,可以使用LocalCommandLineCodeExecutor
。
示例
from pathlib import Path
from autogen.coding import CodeBlock, LocalCommandLineCodeExecutor
work_dir = Path("coding")
work_dir.mkdir(exist_ok=True)
executor = LocalCommandLineCodeExecutor(work_dir=work_dir)
print(
executor.execute_code_blocks(
code_blocks=[
CodeBlock(language="python", code="print('Hello, World!')"),
]
)
)
exit_code=0 output='\nHello, World!\n' code_file='coding/065b51a16ee54f3298847518f9e999d7.py'
使用Python虚拟环境
默认情况下,LocalCommandLineCodeExecutor在与AutoGen代码相同的Python环境中执行代码并安装依赖项。您可以选择指定一个Python虚拟环境,以防止污染基础Python环境。
示例
from autogen.code_utils import create_virtual_env
from autogen.coding import CodeBlock, LocalCommandLineCodeExecutor
venv_dir = ".venv"
venv_context = create_virtual_env(venv_dir)
executor = LocalCommandLineCodeExecutor(virtual_env_context=venv_context)
print(
executor.execute_code_blocks(code_blocks=[CodeBlock(language="python", code="import sys; print(sys.executable)")])
)
分配给一个代理
这些执行器可以用于促进代理编写代码的执行。
from pathlib import Path
from autogen import ConversableAgent
from autogen.coding import DockerCommandLineCodeExecutor
work_dir = Path("coding")
work_dir.mkdir(exist_ok=True)
executor = DockerCommandLineCodeExecutor(work_dir=work_dir)
code_executor_agent = ConversableAgent(
name="code_executor_agent",
llm_config=False,
code_execution_config={
"executor": executor,
},
human_input_mode="NEVER",
)
在使用代码执行时,关键是你需要更新你期望编写代码的代理的系统提示,以便能够使用执行器。例如,对于DockerCommandLineCodeExecutor
,你可以这样设置一个代码编写代理:
# The code writer agent's system message is to instruct the LLM on how to
# use the Jupyter code executor with IPython kernel.
code_writer_system_message = """
You have been given coding capability to solve tasks using Python code.
In the following cases, suggest python code (in a python coding block) or shell script (in a sh coding block) for the user to execute.
1. When you need to collect info, use the code to output the info you need, for example, browse or search the web, download/read a file, print the content of a webpage or a file, get the current date/time, check the operating system. After sufficient info is printed and the task is ready to be solved based on your language skill, you can solve the task by yourself.
2. When you need to perform some task with code, use the code to perform the task and output the result. Finish the task smartly.
Solve the task step by step if you need to. If a plan is not provided, explain your plan first. Be clear which step uses code, and which step uses your language skill.
When using code, you must indicate the script type in the code block. The user cannot provide any other feedback or perform any other action beyond executing the code you suggest. The user can't modify your code. So do not suggest incomplete code which requires users to modify. Don't use a code block if it's not intended to be executed by the user.
If you want the user to save the code in a file before executing it, put # filename: <filename> inside the code block as the first line. Don't include multiple code blocks in one response. Do not ask users to copy and paste the result. Instead, use 'print' function for the output when relevant. Check the execution result returned by the user.
"""
import os
code_writer_agent = ConversableAgent(
"code_writer",
system_message=code_writer_system_message,
llm_config={"config_list": [{"model": "gpt-4", "api_key": os.environ["OPENAI_API_KEY"]}]},
code_execution_config=False, # Turn off code execution for this agent.
max_consecutive_auto_reply=2,
human_input_mode="NEVER",
)
然后我们可以使用这两个代理来解决问题:
import pprint
chat_result = code_executor_agent.initiate_chat(
code_writer_agent, message="Write Python code to calculate the 14th Fibonacci number."
)
pprint.pprint(chat_result)
Write Python code to calculate the 14th Fibonacci number.
--------------------------------------------------------------------------------
Sure, we can calculate the Fibonacci series using a few different methods such as recursion, iterative, by using Binet's formula, or by using matrix exponentiation.
But, since we only need to calculate the 14th number, we will simply use the iterative method as it's the most efficient for this case.
Here is the Python code that solves the task:
```python
def fibonacci(n):
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
return a
print(fibonacci(14))
```
In this script, `fibonacci(n)` is a function that calculates the nth Fibonacci number. Inside the function, two variables `a` and `b` are initialised to `0` and `1` which are the first two numbers in the Fibonacci series. Then, a loop runs `n` times (14 times in your case), and in each iteration `a` is replaced with `b` and `b` is replaced with `a + b`, which generates the next number in the series.
The function returns `a`, which is the nth Fibonacci number. The result is then printed to the console.
--------------------------------------------------------------------------------
>>>>>>>> EXECUTING 1 CODE BLOCKS (inferred languages are [python])...
exitcode: 0 (execution succeeded)
Code output: 377
--------------------------------------------------------------------------------
Great! The script has successfully computed the 14th Fibonacci number as 377. If you need to compute other Fibonacci numbers, you can simply change the argument in the `fibonacci()` function call. Please let me know if you need help with anything else.
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
ChatResult(chat_id=None,
chat_history=[{'content': 'Write Python code to calculate the 14th '
'Fibonacci number.',
'role': 'assistant'},
{'content': 'Sure, we can calculate the Fibonacci '
'series using a few different methods '
'such as recursion, iterative, by using '
"Binet's formula, or by using matrix "
'exponentiation.\n'
'\n'
'But, since we only need to calculate the '
'14th number, we will simply use the '
"iterative method as it's the most "
'efficient for this case.\n'
'\n'
'Here is the Python code that solves the '
'task:\n'
'\n'
'```python\n'
'def fibonacci(n):\n'
' a, b = 0, 1\n'
' for _ in range(n):\n'
' a, b = b, a + b\n'
' return a\n'
'\n'
'print(fibonacci(14))\n'
'```\n'
'\n'
'In this script, `fibonacci(n)` is a '
'function that calculates the nth '
'Fibonacci number. Inside the function, '
'two variables `a` and `b` are '
'initialised to `0` and `1` which are the '
'first two numbers in the Fibonacci '
'series. Then, a loop runs `n` times (14 '
'times in your case), and in each '
'iteration `a` is replaced with `b` and '
'`b` is replaced with `a + b`, which '
'generates the next number in the '
'series. \n'
'\n'
'The function returns `a`, which is the '
'nth Fibonacci number. The result is then '
'printed to the console.',
'role': 'user'},
{'content': 'exitcode: 0 (execution succeeded)\n'
'Code output: 377\n',
'role': 'assistant'},
{'content': 'Great! The script has successfully '
'computed the 14th Fibonacci number as '
'377. If you need to compute other '
'Fibonacci numbers, you can simply change '
'the argument in the `fibonacci()` '
'function call. Please let me know if you '
'need help with anything else.',
'role': 'user'},
{'content': '', 'role': 'assistant'}],
summary='',
cost=({'gpt-4-0613': {'completion_tokens': 302,
'cost': 0.04842,
'prompt_tokens': 1010,
'total_tokens': 1312},
'total_cost': 0.04842},
{'gpt-4-0613': {'completion_tokens': 302,
'cost': 0.04842,
'prompt_tokens': 1010,
'total_tokens': 1312},
'total_cost': 0.04842}),
human_input=[])
最后,停止容器。或者更好的是使用上下文管理器来自动停止它。
executor.stop()