Skip to content

Commit

Permalink
update code_interpreter, minor text fixes, make testable (#877)
Browse files Browse the repository at this point in the history
* update code_interpreter, minor text fixes, make testable

* resolve bug detected by type-checker, resolve silly warning by type-checker

* move from for-loop to iter
  • Loading branch information
charlesfrye committed Sep 17, 2024
1 parent e69f543 commit ce48140
Showing 1 changed file with 18 additions and 17 deletions.
35 changes: 18 additions & 17 deletions misc/code_interpreter.py → 08_advanced/code_interpreter.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
# ---
# deploy: false
# lambda-test: true
# cmd: ["python", "-m", "misc.code_interpreter"]
# cmd: ["python", "08_advanced/code_interpreter.py"]
# ---
#
# This script demonstrates building a simple code interpeter for LLM apps on top of
# Modal's Sandbox functionality.
# This script demonstrates a simple code interpeter for LLM apps on top of
# Modal's [Sandbox](https://modal.com/docs/guide/sandbox) functionality.
#
# Modal's Sandboxes are a secure, trustless compute environment which enables usage of custom
# container images, filesystem storage, cloud bucket mounts, GPUs, and more.
# Modal's Sandboxes are a secure, trustless compute environment with access to all of Modal's features:
# custom container images, remote and local filesystem storage, cloud bucket mounts, GPUs, and more.
import uuid

import modal
Expand All @@ -17,8 +15,8 @@
# to indicate that some code ran but returned no output.
NULL_MARKER = str(uuid.uuid4())

# Our code interpreter will use a Debian base with Python 3.11 and pip install the IPython
# package so we get the familiar JupyterHub REPL interface.
# Our code interpreter will use a Debian base with Python 3.11 and install the `IPython`
# package for its cleaner REPL interface.
image = modal.Image.debian_slim(python_version="3.11").pip_install(
"IPython==8.26.0"
)
Expand Down Expand Up @@ -64,7 +62,7 @@ def __init__(self, text: str):


# Our code interpreter could take many forms (it could even not run Python!)
# but for this example we implement a Jupyer Notebook-like interface.
# but for this example we implement a Jupyter Notebook-like interface.


class Notebook:
Expand All @@ -82,10 +80,10 @@ def _exec_cell_remote(self, code: str) -> ExecutionResult:
self.sb.stdin.write(code.encode("utf-8"))
self.sb.stdin.write(b"\n")
self.sb.stdin.drain()
for message in self.sb.stdout:
if message.strip() == NULL_MARKER:
return ExecutionResult(None)
return ExecutionResult(message)
message = next(iter(self.sb.stdout))
if message.strip() == NULL_MARKER:
return ExecutionResult(None)
return ExecutionResult(message)

def _exec_cell_local(self, code: str) -> ExecutionResult:
try:
Expand All @@ -98,7 +96,7 @@ def _exec_cell_local(self, code: str) -> ExecutionResult:


# The `CodeInterpreter` is a context manager class which manages
# the lifecycle of the underlying modal.Sandbox.
# the lifecycle of the underlying `modal.Sandbox`.


class CodeInterpreter:
Expand All @@ -109,6 +107,9 @@ def __init__(self, timeout: int = 600, debug: bool = False):
DRIVER_PROGRAM,
timeout=timeout,
image=image,
app=modal.App.lookup(
"example-code-interpreter", create_if_missing=True
),
)
self.notebook = Notebook(self.sb)
self.debug = debug
Expand All @@ -118,7 +119,7 @@ def __enter__(self) -> "CodeInterpreter":
print("Entering Code interpreter")
return self

def __exit__(self, exc_type, exc_value, traceback) -> bool:
def __exit__(self, exc_type, exc_value, traceback):
if self.debug:
print("Exiting Code interpreter")
self.sb.stdin.write_eof()
Expand Down Expand Up @@ -159,7 +160,7 @@ def main():
execution = sandbox.notebook.exec_cell(
"import pathlib; pathlib.Path('/tmp/foo').write_text('hello!')"
)
stdout = sandbox.exec("ls", "/tmp/") # outputs 'foo\n'
stdout = sandbox.exec("cat", "/tmp/foo") # outputs 'hello!'
print(stdout)


Expand Down

0 comments on commit ce48140

Please sign in to comment.