diff --git a/docs/_toc.yml b/docs/_toc.yml index 38309dbcfc..c78b19355d 100644 --- a/docs/_toc.yml +++ b/docs/_toc.yml @@ -111,6 +111,8 @@ parts: title: YOLO - file: source/reference/ai/stablediffusion title: Stable Diffusion + - file: source/reference/ai/e2b-code-execution + title: E2B Sandboxed Code Execution - file: source/reference/ai/custom-ai-function title: Bring Your Own AI Function diff --git a/docs/source/reference/ai/e2b-code-execution.rst b/docs/source/reference/ai/e2b-code-execution.rst new file mode 100644 index 0000000000..f99723e150 --- /dev/null +++ b/docs/source/reference/ai/e2b-code-execution.rst @@ -0,0 +1,36 @@ +Executing Code Generated by OpenAI Chat Completion Model +======================================================== + +This section provides an overview on how to use the E2B Sandbox and EvaDB to execute code snippets generated by ChatGPT / Chat Completion Model. + +1. Getting a cursor and Create the E2BExec Function + +.. code-block:: python + + import evadb + cursor = evadb.connect().cursor() + cursor.query("DROP FUNCTION IF EXISTS E2BExec").execute() + cursor.query(f"CREATE FUNCTION IF NOT EXISTS E2BExec IMPL '/e2b_exec.py'").execute() + +Assume output of OpenAI Chat Completion model has been stored in a table named `CodeToExecute` +under the column `codejson` + +The input that this function expects should look like + +.. code-block:: json + + { + "function_call":{ + "name":"exec_code", + "arguments":"{\n \"code\": \"def fibonacci(n):\\n fibonacci_sequence = [0, 1]\\n while len(fibonacci_sequence) < n:\\n fibonacci_sequence.append(fibonacci_sequence[-1] + fibonacci_sequence[-2])\\n return fibonacci_sequence\\n\\nprint(fibonacci(100))\"\n}" + } + } + +2. Using the following snippet it will execute each column and return stderr and stdout + +.. code-block:: python + + result = cursor.query("SELECT E2BExec(codejson) FROM CodeToExecute").execute() + +.. note:: + Remember to set your E2B API key as `E2B_API_KEY` environment variable \ No newline at end of file diff --git a/evadb/functions/e2b_exec.py b/evadb/functions/e2b_exec.py new file mode 100644 index 0000000000..511082a77c --- /dev/null +++ b/evadb/functions/e2b_exec.py @@ -0,0 +1,76 @@ +# coding=utf-8 +# Copyright 2018-2023 EvaDB +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json + +import pandas as pd +from evadb.catalog.catalog_type import NdArrayType +from evadb.functions.abstract.abstract_function import AbstractFunction, InputType +from evadb.functions.decorators.decorators import setup, forward +from evadb.functions.decorators.io_descriptors.data_types import PandasDataframe +from e2b import Sandbox + + +class E2BExec(AbstractFunction): + """ + Takes input as a string like: + { + "function_call":{ + "name":"exec_code", + "arguments":"{\n \"code\": \"def fibonacci(n):\\n fibonacci_sequence = [0, 1]\\n while len(fibonacci_sequence) < n:\\n fibonacci_sequence.append(fibonacci_sequence[-1] + fibonacci_sequence[-2])\\n return fibonacci_sequence\\n\\nprint(fibonacci(100))\"\n}" + } + } + This is the output from OpenAI Chat Completion model. + """ + @setup(cacheable=False, function_type="code_execution", batchable=True) + def setup(self, *args, **kwargs) -> None: + pass + + @forward( + input_signatures=[ + PandasDataframe( + columns=["data"], + column_types=[NdArrayType.STR], + column_shapes=[(1,)], + ) + ], + output_signatures=[ + PandasDataframe( + columns=["stdout", "stderr"], + column_types=[NdArrayType.STR, ], + column_shapes=[(1,), (1, )], + ) + ], + ) + def forward(self, frames: InputType) -> InputType: + self.sandbox = Sandbox() + output = [] + stderrs = [] + for code in frames['codejson']: + code_obj = json.loads(code) + code_text = json.loads(code_obj['function_call']['arguments'])['code'] + self.sandbox.filesystem.write('/home/user/test.py', code_text) + proc = self.sandbox.process.start('python /home/user/test.py') + out = proc.wait() + output.append(out.stdout) + stderrs.append(out.stderr) + + return_df = pd.DataFrame({"stdout": output, "stderr": stderrs}) + self.sandbox.close() + return return_df + + @property + def name(self) -> str: + return 'E2BExec'