From da75d51fe8431aae6b7333cdeee0ecf5d9e91843 Mon Sep 17 00:00:00 2001 From: Eduardo Chiarotti Date: Thu, 20 Jun 2024 20:24:26 -0300 Subject: [PATCH] feat: add Dockerfile, Makefile and update version of code --- .../tools/code_interpreter_tool/Dockerfile | 9 +--- .../tools/code_interpreter_tool/Makefile | 6 +++ .../code_interpreter_tool.py | 51 ++++++++++++------- 3 files changed, 41 insertions(+), 25 deletions(-) create mode 100644 src/crewai_tools/tools/code_interpreter_tool/Makefile diff --git a/src/crewai_tools/tools/code_interpreter_tool/Dockerfile b/src/crewai_tools/tools/code_interpreter_tool/Dockerfile index b72a51a88..ae9b2ffd6 100644 --- a/src/crewai_tools/tools/code_interpreter_tool/Dockerfile +++ b/src/crewai_tools/tools/code_interpreter_tool/Dockerfile @@ -1,8 +1,4 @@ -# Use an official Ubuntu as a parent image -FROM ubuntu:20.04 - -# Set environment variables -ENV DEBIAN_FRONTEND=noninteractive +FROM python:3.11-slim # Install common utilities RUN apt-get update && apt-get install -y \ @@ -11,9 +7,6 @@ RUN apt-get update && apt-get install -y \ wget \ software-properties-common -# Install Python -RUN apt-get install -y python3 python3-pip - # Clean up RUN apt-get clean && rm -rf /var/lib/apt/lists/* diff --git a/src/crewai_tools/tools/code_interpreter_tool/Makefile b/src/crewai_tools/tools/code_interpreter_tool/Makefile new file mode 100644 index 000000000..5a514db0a --- /dev/null +++ b/src/crewai_tools/tools/code_interpreter_tool/Makefile @@ -0,0 +1,6 @@ +# Makefile +IMAGE_NAME=code-interpreter +TAG=latest + +build: + docker build -t $(IMAGE_NAME):$(TAG) . diff --git a/src/crewai_tools/tools/code_interpreter_tool/code_interpreter_tool.py b/src/crewai_tools/tools/code_interpreter_tool/code_interpreter_tool.py index a2066ca03..f497a7c96 100644 --- a/src/crewai_tools/tools/code_interpreter_tool/code_interpreter_tool.py +++ b/src/crewai_tools/tools/code_interpreter_tool/code_interpreter_tool.py @@ -6,23 +6,27 @@ from pydantic.v1 import BaseModel, Field class FixedCodeInterpreterSchemaSchema(BaseModel): - """Input for DirectoryReadTool.""" + """Input for CodeInterpreterTool.""" pass class CodeInterpreterSchema(FixedCodeInterpreterSchemaSchema): - """Input for DirectoryReadTool.""" + """Input for CodeInterpreterTool.""" code: str = Field( ..., - description="Python3 code used to be interpreted in the Docker container and output the result", + description="Python3 code used to be interpreted in the Docker container. ALWAYS PRINT the final result and the output of the code", + ) + libraries_used: Optional[str] = Field( + None, + description="List of libraries used in the code with proper installing names separated by commas. Example: numpy,pandas,beautifulsoup4", ) class CodeInterpreterTool(BaseTool): name: str = "Code Interpreter" - description: str = "Interprets Python code in a Docker container" + description: str = "Interprets Python code in a Docker container. ALWAYS PRINT the final result and the output of the code" args_schema: Type[BaseModel] = CodeInterpreterSchema code: Optional[str] = None @@ -30,28 +34,41 @@ class CodeInterpreterTool(BaseTool): super().__init__(**kwargs) if code is not None: self.code = code - self.description = ( - "A tool that can be used to run Python code in a Docker container" - ) + self.description = "Interprets Python code in a Docker container. ALWAYS PRINT the final result and the output of the code" self.args_schema = FixedCodeInterpreterSchemaSchema self._generate_description() def _run(self, **kwargs): code = kwargs.get("code", self.code) - return self.run_code_in_docker(code) + libraries_used = kwargs.get("libraries_used", None) + return self.run_code_in_docker(code, libraries_used) - def run_code_in_docker(self, code): + def run_code_in_docker(self, code, libraries_used): client = docker.from_env() - container = client.containers.run( - "code-interpreter", - command=f'python3 -c "{code}"', - detach=True, - working_dir="/workspace", - ) - result = container.logs().decode("utf-8") + def run_code(container, code): + cmd_to_run = f'python3 -c "{code}"' + exec_result = container.exec_run(cmd_to_run) + return exec_result + + container = client.containers.run( + "code-interpreter", detach=True, tty=True, working_dir="/workspace" + ) + if libraries_used: + self._install_libraries(container, libraries_used.split(",")) + + exec_result = run_code(container, code) container.stop() container.remove() + if exec_result.exit_code != 0: + return f"Something went wrong while running the code: \n{exec_result.output.decode('utf-8')}" - return result + return exec_result.output.decode("utf-8") + + def _install_libraries(self, container, libraries): + """ + Install missing libraries in the Docker container + """ + for library in libraries: + container.exec_run(f"pip install {library}")