top of page

Building a Python Code Debugger with OpenAI: A Step-by-Step Tutorial

Updated: Aug 13, 2024


Debugging code can often feel like solving a puzzle, and sometimes we need a little help to crack the toughest problems. Debugging code is an essential skill for any programmer. With the help of OpenAI's powerful language models, we can automate parts of this process, making it more efficient and less error-prone.  In this tutorial, we'll build a Python code debugger that leverages OpenAI's powerful language models to analyze and debug Python code. This tool will provide detailed error analysis and step-by-step suggestions to fix issues, making your coding journey smoother and more efficient.


Introduction to the Python Code Debugger

The Python Code Debugger is designed to help developers identify and fix errors in their Python code. By inputting code snippets, the debugger uses OpenAI's GPT-3.5-turbo model to analyze the code and provide suggestions for corrections. This tool is particularly useful for beginners and even experienced developers who want to streamline their debugging process.


What You'll Learn

  1. How to set up OpenAI's API in your Python environment.

  2. How to create a function that interacts with OpenAI to get debugging suggestions.

  3. How to build an interactive interface for inputting code and displaying results.


Prerequisites

Before we dive in, make sure you have the following:

  • Python installed on your system.

  • An OpenAI API key. You can get one by signing up at OpenAI's website.

  • Basic knowledge of Python programming.


Before going ahead If you've read my previous tutorial, such as those on creating a Fact Checker, you'll find that much of the code structure here is similar. The key components like setting up the OpenAI API, handling user inputs, and constructing the user interface are consistent across these projects. The primary difference is in the prompt that we pass to the AI, which tailors the tool's functionality to different tasks, it's debugging code. This consistency allows you to build various AI-driven applications by simply modifying the prompt while keeping the rest of the code largely the same.



Setting Up the Environment

First, we need to install the OpenAI Python package and Panel for building our user interface. Open your terminal and run:

pip install openai panel

This command installs the necessary packages for interacting with the OpenAI API and creating a web interface.


Writing the Code

Let's start by importing the required libraries and setting up our OpenAI API key.

import openai
import os

# Set your OpenAI API key here
openai.api_key = 'your-api-key-here'

Replace 'your-api-key-here' with your actual OpenAI API key.


Creating the Completion Function

Next, we'll define a function to get responses from the OpenAI model. This function sends a prompt to the model and returns the generated response.


def get_completion(prompt, model="gpt-3.5-turbo"):
    messages = [{"role": "user", "content": prompt}]
    response = openai.ChatCompletion.create(
        model=model,
        messages=messages,
        temperature=0,  # This controls the randomness of the model's output
    )
    return response.choices[0].message["content"]

Breaking Down the Code


The Function: get_completion

This function is designed to take a prompt (a question or statement) and get a response from OpenAI's language model. Here's how it works:


Function Definition

def get_completion(prompt, model="gpt-3.5-turbo"):
  • def: This keyword is used to define a new function in Python.

  • get_completion: This is the name of our function.

  • prompt: This is a parameter that the function takes. It's the question or statement we want to send to the OpenAI model.

  • model="gpt-3.5-turbo": This is another parameter with a default value. If you don't provide a model when you call the function, it will use "gpt-3.5-turbo" by default.


Preparing the Message

messages = [{"role": "user", "content": prompt}]
  • messages: This is a list that will contain our message to the OpenAI model.

  • [{"role": "user", "content": prompt}]: This creates a dictionary (a kind of list) with two key-value pairs:

    • "role": "user": This indicates that the message is coming from the user.

    • "content": prompt: This is the actual message or question we want to send to the model.


Getting a Response from OpenAI

response = openai.ChatCompletion.create(
    model=model,
    messages=messages,
    temperature=0,  # This controls the randomness of the model's output
)
  • openai.ChatCompletion.create(): This function sends our message to the OpenAI model and gets a response.

  • model=model: We're specifying which model to use. By default, it's "gpt-3.5-turbo".

  • messages=messages: We're sending the list of messages we created earlier.

  • temperature=0: This controls how random or creative the model's responses will be. A temperature of 0 makes the model's output very predictable.


Returning the Response

return response.choices[0].message["content"]
  • return: This keyword is used to send back the result from the function.

  • response.choices[0].message["content"]: This accesses the content of the response from the model.

    • response.choices: The response can contain multiple choices (answers).

    • [0]: We're choosing the first response.

    • .message["content"]: We're getting the actual text content of the response.


Building the User Interface 

Now, let's create the user interface using Panel. First, import Panel and initialize it.

import panel as pn
pn.extension()

We'll then define the main function to handle user input and display the debugging results.

def collect_messages(debug=False):

    user_input = inp.value_input
    if debug: 
        print(f"Input = {user_input}")

    if user_input == "":
        return
    inp.value = ''

    prompt = f"""
    Please carefully review the python code and identify the type of error or issues that may be causing it not to function correctly. 
    After analyzing the code, provide step-by-step suggestions or explanations on how to fix the code and make it work 
    as intended. Present the response in the following manner:
    - **Type of error**:
    - **Suggestions**:(in step-by-step manner)
    - **Correct code**:

    You will only debug python code.
    The code is delimited with triple backticks.
    Make your response to the point and specific.

    Code: '''{user_input}'''
    """

    global context

    response, context = get_completion(prompt), context
    context.append({'role':'Code Debugger', 'content':f"{response}"})
    panels.append(
        pn.Row('User:', pn.pane.Markdown(user_input, width=600))
    )
    panels.append(
        pn.Row('Code Debugger:', pn.pane.Markdown(response, width=600, style={'background-color': '#caf0f8'}))
    )

    return pn.Column(*panels)

Let’s break down this code step-by-step.


The Function: collect_messages

This function handles the collection of user input (a Python code snippet), sends it to the OpenAI model to get a response, and then displays both the input and the debugging output.


Function Definition

def collect_messages(debug=False):
  • def: This keyword is used to define a new function in Python.

  • collect_messages: This is the name of our function.

  • debug=False: This is a parameter with a default value. If debug is set to True, the function will print the user input for debugging purposes.


Getting User Input

user_input = inp.value_input
  • user_input: This variable stores the value of the user's input from a text input widget (inp).


Debugging (Optional)

if debug: 
    print(f"Input = {user_input}")
  • if debug: This checks if the debug parameter is set to True.

  • print(f"Input = {user_input}"): If debug is True, this line prints the user input. This helps with debugging to see what the input was.


Handling Empty Input

if user_input == "":
    return
inp.value = ''
  • if user_input == "": This checks if the user input is an empty string (i.e., the user didn't type anything).

  • return: If the input is empty, the function stops and returns nothing.

  • inp.value = '': If there was input, this clears the input field for the next code snippet.


Creating the Prompt for OpenAI


Creating an effective prompt is crucial for fine-tuning large language models (LLMs). The prompt sets the context and guides the model's response, ensuring it aligns with the user's expectations. A well-crafted prompt can significantly enhance the model's performance, making its outputs more accurate and relevant. Fine-tuning with precise prompts allows for better control over the model's behaviour, tailoring it to specific tasks and improving overall user experience.


prompt = f"""
Please carefully review the python code and identify the type of error or issues that may be causing it not to function correctly. 
After analyzing the code, provide step-by-step suggestions or explanations on how to fix the code and make it work 
as intended. Present the response in the following manner:
- **Type of error**:
- **Suggestions**:(in step-by-step manner)
- **Correct code**:

You will only debug python code.
The code is delimited with triple backticks.
Make your response to the point and specific.

Code: '''{user_input}'''
"""
  • prompt: This variable stores a formatted string that instructs the OpenAI model on how to respond to the user's input.

  • f""" ... """: This is a multi-line f-string, which allows us to include the user_input directly in the string.


Getting the Response from OpenAI and Managing Context

panels.append(
    pn.Row('User:', pn.pane.Markdown(user_input, width=600))
)
panels.append(
    pn.Row('Code Debugger:', pn.pane.Markdown(response, width=600, style={'background-color': '#caf0f8'}))
)
  • global context: This tells the function to use the context variable from the global scope, not just within the function.

  • response, context = get_completion(prompt), context: This line calls the get_completion function to get the response from OpenAI and assigns it to response. The context remains unchanged.

  • context.append({'role':'Code Debugger', 'content':f"{response}"}): This adds the response to the context list, which keeps track of the conversation history.


Displaying the Input and Output

panels.append(
    pn.Row('User:', pn.pane.Markdown(user_input, width=600))
)
panels.append(
    pn.Row('Code Debugger:', pn.pane.Markdown(response, width=600, style={'background-color': '#caf0f8'}))
)
  • panels.append(...): This adds new rows to the panels list.

  • pn.Row('User:', pn.pane.Markdown(user_input, width=600)): This creates a row displaying the user's input code.

  • pn.Row('Code Debugger:', pn.pane.Markdown(response, width=600, style={'background-color': '#caf0f8'})): This creates a row displaying the model's response, with a background color for distinction.


Returning the Result

panels = []  # Collect display
context = [{'role': 'Code Debugger', 'content': "You are a debugging assistant, and your task is to help debug python code only."}]

inp = pn.widgets.TextInput(placeholder='Enter code here...', sizing_mode='stretch_width')
button_conversation = pn.widgets.Button(name="Debug", button_type="primary")

interactive_conversation = pn.bind(collect_messages, button_conversation)

dashboard = pn.Column(
    inp,
    pn.Row(button_conversation),
    pn.panel(interactive_conversation, loading_indicator=True, height=300),
)

dashboard.servable()
  • return pn.Column(*panels): This combines all the rows in the panels list into a single column layout and returns it. This column will display both the user’s input and the model’s response.


Assembling the Components

Finally, let's assemble the components to create a complete Python Code Debugger application. This code sets up a text input for the code snippet, a button to trigger the debugger, and a panel to display the code and debugging suggestions.

panels = []  # Collect display
context = [{'role': 'Code Debugger', 'content': "You are a debugging assistant, and your task is to help debug python code only."}]

inp = pn.widgets.TextInput(placeholder='Enter code here...', sizing_mode='stretch_width')
button_conversation = pn.widgets.Button(name="Debug", button_type="primary")

interactive_conversation = pn.bind(collect_messages, button_conversation)

dashboard = pn.Column(
    inp,
    pn.Row(button_conversation),
    pn.panel(interactive_conversation, loading_indicator=True, height=300),
)

dashboard.servable()

Breaking Down the Additional Code

Setting Up the Interface

This part of the code is responsible for setting up the user interface using the Panel library. It creates the input field, button, and layout to display the code and suggestions.


Initialize Panels List

panels = []  # Collect display
  • panels: This is an empty list that will hold the different display components (the code and the suggestions).


Initialize Context

context = [{'role': 'Code Debugger', 'content': "You are a debugging assistant, and your task is to help debug python code only."}]
  • context: This list contains an initial message to set the context for the Code Debugger. It tells the model that it is supposed to act as a debugging assistant.


Create Input Field

inp = pn.widgets.TextInput(placeholder='Enter code here...', sizing_mode='stretch_width')
  • inp: This is a text input widget where the user can type their code.

  • placeholder='Enter code here…': This is the placeholder text that appears inside the input field before the user types anything.

  • sizing_mode='stretch_width': This makes the input field stretch to fit the width of the container.


Create Debug Button

button_conversation = pn.widgets.Button(name="Debug", button_type="primary")
  • button_conversation: This is a button widget that the user will click to submit their code.

  • name="Debug": This sets the label of the button to "Debug".

  • button_type="primary": This sets the style of the button.


Bind Function to Button

interactive_conversation = pn.bind(collect_messages, button_conversation)
  • interactive_conversation: This binds the collect_messages function to the button_conversation button. When the button is clicked, the collect_messages function will be called.


Create Dashboard Layout

dashboard = pn.Column(
    inp,
    pn.Row(button_conversation),
    pn.panel(interactive_conversation, loading_indicator=True, height=300),
)
  • dashboard: This is a column layout that contains all the elements of our interface.

  • pn.Column(...): This creates a vertical layout.

  • inp: Adds the input field to the column.

  • pn.Row(button_conversation): Adds the button to the column in a row layout.

  • pn.panel(interactive_conversation, loading_indicator=True, height=300): Adds the interactive conversation panel to the column. The loading_indicator=True shows a loading animation while the response is being processed, and height=300 sets the height of the panel.


Complete Code

Here's the entire code in one block for easy copying:

import openai
import os

openai.api_key  = ''

def get_completion(prompt, model="gpt-3.5-turbo"): # Andrew mentioned that the prompt/ completion paradigm is preferable for this class
    messages = [{"role": "user", "content": prompt}]
    response = openai.ChatCompletion.create(
        model = model,
        messages = messages,
        temperature = 0, # this is the degree of randomness of the model's output
    )
    return response.choices[0].message["content"]

import panel as pn
pn.extension()

def collect_messages(debug=False):

    user_input = inp.value_input
    if debug: print(f"Input = {user_input}")
    if user_input == "":
        return
    inp.value = ''


    prompt = f"""

    Please carefully review the python code and identify the type of error or issues that may be causing it not to function correctly.
    After analyzing the code, provide step-by-step suggestions or explanations on how to fix the code and make it work
    as intended. Present the response in the following manner:
    - **Type of error**:
    - **Suggestions**:(in step by step manner)
    - **Correct code**:


    You will only debug python code.

    The code is delimited with triple backticks. \
    Make your response to the point and specific.

    Code: '''{user_input}'''
    """


    global context

   
    response, context = get_completion(prompt), context
    context.append({'role':'Code Debugger', 'content':f"{response}"})
    panels.append(
        pn.Row('User:', pn.pane.Markdown(user_input, width=600)))
    panels.append(
        pn.Row('Code Debugger:', pn.pane.Markdown(response, width=600, style={'background-color': '#caf0f8'})))

    return pn.Column(*panels)

panels = [] # collect display

context = [ {'role':'Code Debugger', 'content':"You are a debugging assistant, and your task is to help debug python code only."} ]

inp = pn.widgets.TextInput(placeholder='Enter code here...', width=500, sizing_mode='stretch_width')
button_conversation = pn.widgets.Button(name="Debug", button_type= "primary")

interactive_conversation = pn.bind(collect_messages, button_conversation)

dashboard = pn.Column(
    inp,
    pn.Row(button_conversation),
    pn.panel(interactive_conversation, loading_indicator=True, height=300),
)

dashboard

We have just built a powerful Python Code Debugger using OpenAI. This project demonstrates the incredible potential of AI in assisting with code debugging and improving the development process. Feel free to expand this project by adding more features or integrating it with other applications. If you have any questions or suggestions, feel free to leave a comment below. Happy coding!


screenshots

Here, I am sharing some screenshots that I took after running the project. This will help you understand how it works.



2.


Demo Video




Other Blogs Links


For the complete solution or any help regarding the ChatGPT and Open AI API assignment help feel free to contact us.


Comments


bottom of page