Code Interpreter

How to build an AI capable of generating and running code

You can retrieve the full example of this recipe here 🥞

It was also inspired by this tutorial made by E2B.

What we're cooking today 🧑‍🍳

In this recipe, we will build a simple version of ChatGPT Code Interpreter using OpenAI GPT-4 and E2B.

Here's the final result:

Example of code executor chat built with AgentLabs

What's the plan?

Building a code interpreter is pretty straightforward; we'll proceed as follows:

  1. We'll use the AgentLabs SDK to listen for user's input in the Chat.

  2. We'll send the request to GPT-4 and ask it to generate some code snippets if asked by the user.

  3. GPT is returning some code to run; then, we'll use E2B to run the code in a sandboxed cloud environment.

  4. We'll use the AgentLabs SDK again to display the result to the user

Using E2B is not mandatory, but it's a great solution to run code safely in a sandboxed environment, so we highly recommend you check this out.

Let's code

Prepare the environment variables

In this tutorial, we'll need many environment variables. If you look at our example, you'll see we verify every variable is present before running the app, but you're free to manage your environment variables as you want.

We'll need the following variables:

  • AgentLabs Project ID, Agent ID, URL and Secret (that you can find on your console)

  • Open AI Api Key

  • E2B Api Key

Handle user requests

Once our variables are ready, we'll import and init the AgentLabs SDK.

Here, we instantiate the project and the agent.

We start listening for user messages using the .onChatMessage() method, we'll complete it later in this recipe.

We don't forget to use the .connect() method to open the socket connection.

Talk to GPT-4

Whenever a user sends a message, we'll forward it to GPT-4 using the ChatCompletionAPI. We expect GPT-4 to send us a response with potentially the code to execute.

We'll provide GPT with two kinds of information:

  • The context: a list of fake history messages so GPT understands what we expect, plus in the end the message sent by the user.

  • The function calling config: we leverage the function call API so ChatGPT will hopefully output some code we can directly execute in the sandbox.

Parsing GPT's response

If you look at the chatCompletion result, you will see it contains something like this:

From this result we want to:

  • Know if the choices[0].function_call.name equals exec_code. If yes, it means we have to execute the code.

  • Parse the arguments of choices[0].function_call.arguments in order to extract the value of the code to execute.

Executing the code

Now we have extracted the code to run; we can use E2B to execute it safely in a sandboxed environment.

We will use their process API to start a new process that will run our code.

Here's the plan:

  1. Initiate an E2B session using Session.create() method.

  2. Write the code we want to execute in a file named index.js in the sandbox.

  3. Create a new process, running the node index.js command to run our code remotely.

  4. We'll keep the onStdout and onStderr callbacks empty for now but we'll use them later.

  5. We'll wait for the process execution to be completed.

The code above will run our code until the execution is completed. Every output in Stdout or Stderr will trigger a call of one of the given callbacks.

Sending results and feedback to the user in real time

So far we're able to listen for messages, ask completions to OpenAI, and eventually execute the code.

We still need to implement some real-time feedback to the users so they know what's going on, and they will view the output generated by the code interpreter.

To do so, we'll leverage the agent.createSteam() method provided by AgentLabs.

We can add some feedback whenever we want.

Let's create a stream if the ChatCompletion contains a function_call.

Here, we open a stream channel, and we indicate we'll send some Markdown, so the Chat UI knows how to display the code output.

Now we can use stream.write to write on the chat every time we need to.

For example, we can indicate we received some code to execute.

Note we stream in markdown format, so we use ``` in front of the code so it's shown in a code block.

Then, we want to notify the user we'll start executing the code, and crucially we want to output the result of the code interpreter in real time. To do so, we'll write to our stream before executing the code, and every time the onStdout or onStderr callbacks are called.

And once we're done, we'll end the stream.

Et voilà 🎉

Congrats, you just rebuilt your own code interpreter!

Feel free to check out the full example here.

Last updated