We use cookies on our website.
Docs
API Reference
Tools
PythonInterpreterTool

PythonInterpreterTool

The PythonInterpreterTool class is a subclass of Tool. It is used to run commands on the current Python Interpreter in a subprocess with a timeout.

The code you provide as the input to this tool is executed in two parts:

  1. Everything but last line:
  • All the lines of the code, except the last one are parsed using python's ast module and run using python's exec function
  • The import statements are parsed separately and passed as global variables to the above mentioned exec function
  • The python dict passed as the vars parameter to the tool is passed as local variables to the above mentioned exec function
  1. Last line:
  • The last line of the code is run using python's eval function. If eval returns something, the tool returns it with an exit code of 0. Otherwise anything eval printed in stdout is returned by the tool with an exit code of 0.
  • If the above mentioned eval function raises an exception, the last line is run again using python's exec function everything that is printed to stdout is returned by the tool with an exit code of 1.
ℹ️

The entire code execution happens in a subprocess (with a timeout) that communicates with the main process using a queue from the multiprocessing module

Parameters

  1. code (str): The python code to run in the interpreter.
  2. vars (dict): Python variables that need to be inserted into the local scope of the interpreter.
  3. timeout (int): The maximum amount of time (in seconds) to wait for the command to finish. Defaults to 60.

Returns

The return value is of the type: ToolReturn (Learn more about: ToolReturn) with the following output and exit_code:

  • output (str): Result of running the last line of your code.
  • exit_code (int): 0 if success, 1 if failure.

Usage

Running it directly

You can run the tool directly like so:

import asyncio
from embedia.tools import PythonInterpreterTool
 
python_interpreter = PythonInterpreterTool()
resp = asyncio.run(python_interpreter(code='print("Hello World")'))

Running the above code prints the following on the terminal:

[time: 2023-10-02T07:26:36.153412+00:00] [id: 139757053245712] [event: Tool Start]
Tool: PythonInterpreterTool
Args: ()
Kwargs: {'code': 'print("Hello World")'}
 
[time: 2023-10-02T07:26:36.225196+00:00] [id: 139757053245712] [event: Tool End]
Tool: PythonInterpreterTool
ExitCode: 0
Output:
Hello World

Using with ToolUserAgent

Let us use the ToolUserAgent to write some code and run it using the PythonInterpreterTool (Learn more about: ToolUserAgent)

main.py
import asyncio
import os
 
import openai
import tiktoken
from embedia import ChatLLM, Tokenizer
from embedia.agents import ToolUserAgent
from embedia.tools import PythonInterpreterTool
 
 
class OpenAITokenizer(Tokenizer):
 
    def __init__(self):
        super().__init__()
 
    async def _tokenize(self, text):
        return tiktoken.encoding_for_model("gpt-3.5-turbo").encode(text)
 
 
class OpenAIChatLLM(ChatLLM):
 
    def __init__(self):
        super().__init__(tokenizer=OpenAITokenizer())
        openai.api_key = os.environ['OPENAI_API_KEY']
 
    async def _reply(self, prompt):
        completion = await openai.ChatCompletion.acreate(
            model="gpt-3.5-turbo",
            temperature=0.1,
            messages=[{
                'role': msg.role,
                'content': msg.content
            } for msg in self.chat_history],
        )
        return completion.choices[0].message.content
 
 
if __name__ == '__main__':
    tool_user_agent = ToolUserAgent(chatllm=OpenAIChatLLM(),
                                    tools=[PythonInterpreterTool()])
    resp = asyncio.run(
        tool_user_agent("Count the number of lines in main.py"))

Running the above code prints the following on the terminal:

[time: 2023-10-02T07:34:46.633286+00:00] [id: 140137853475168] [event: Tool Start]
Tool: ToolUserAgent
Args: ('Count the number of lines in main.py',)
Kwargs: {}
 
[time: 2023-10-02T07:34:46.640763+00:00] [id: 140137853475168] [event: Agent Start]
Main Question:
Count the number of lines in main.py
 
[time: 2023-10-02T07:34:47.636894+00:00] [id: 140137853521584] [event: ChatLLM Init]
system (81 tokens):
You're an expert in choosing the function arguments based on the user's question. The question, the function description, the list of parameters and their descriptions will be provided to you. Reply with all arguments in the following json format:
{
    <parameter name>: <argument value>,
    <parameter name>: <argument value>,
    <parameter name>: <argument value>,
}
Do not reply with anything else
 
[time: 2023-10-02T07:34:47.638714+00:00] [id: 140137853521584] [event: ChatLLM Start]
user (66 tokens):
Question: Count the number of lines in main.py
Function: Runs the provided python code in the current interpreter
Parameters:
code: Python code to be run (type: str)
vars: A python dictionary containing variables to be passed to the code
timeout: Timeout in seconds (type: int). Defaults to 60.
 
 
[time: 2023-10-02T07:34:49.484452+00:00] [id: 140137853521584] [event: ChatLLM End]
assistant (42 tokens):
{
    "code": "with open('main.py', 'r') as file:\n    lines = file.readlines()\nlen(lines)",
    "vars": {},
    "timeout": 60
}
 
Tool: ToolUserAgent
Details: {'tool': 'Python Interpreter', 'args': {'code': "with open('main.py', 'r') as file:\n    lines = file.readlines()\nlen(lines)", 'vars': {}, 'timeout': 60}} Confirm (y/n): y
 
[time: 2023-10-02T07:34:55.124291+00:00] [id: 140137867148688] [event: Tool Start]
Tool: PythonInterpreterTool
Args: ()
Kwargs: {'code': "with open('main.py', 'r') as file:\n    lines = file.readlines()\nlen(lines)", 'vars': {}, 'timeout': 60}
 
[time: 2023-10-02T07:34:55.177002+00:00] [id: 140137867148688] [event: Tool End]
Tool: PythonInterpreterTool
ExitCode: 0
Output:
42
 
[time: 2023-10-02T07:34:55.177935+00:00] [id: 140137853475168] [event: Agent Step]
Question: Count the number of lines in main.py
ToolChoice: Python Interpreter
ToolArgs: {'code': "with open('main.py', 'r') as file:\n    lines = file.readlines()\nlen(lines)", 'vars': {}, 'timeout': 60}
ToolExitCode: 0
ToolOutput: 42
 
[time: 2023-10-02T07:34:55.179037+00:00] [id: 140137853521296] [event: ChatLLM Init]
system (113 tokens):
You're an expert in deciding what next question should be asked (if any) to reach the final answer. Your question will be acted upon and its result will be provided to you. This will repeat until we reach the final answer. The main question, actions taken till now and their results will be provided to you.
If we've reached the final answer, reply with the answer in the following format:
Final Answer: <final answer>
If not, reply with the next question in the following format:
Question: <next question>
Do not reply with anything else 
 
[time: 2023-10-02T07:34:55.194171+00:00] [id: 140137853521296] [event: ChatLLM Start]
user (28 tokens):
Main question: Count the number of lines in main.py
 
Question: Count the number of lines in main.py
 Output: 42
 
 
[time: 2023-10-02T07:34:56.501344+00:00] [id: 140137853521296] [event: ChatLLM End]
assistant (5 tokens):
Final Answer: 42
 
[time: 2023-10-02T07:34:56.517049+00:00] [id: 140137853475168] [event: Agent End]
Final Answer:
 42
 
[time: 2023-10-02T07:34:56.517882+00:00] [id: 140137853475168] [event: Tool End]
Tool: ToolUserAgent
ExitCode: 0
Output:
 42

Try it out yourself