Add a text field to this GUI for entering a filename where the extracted code gets saved to (python file) and also add a button to save and execute the extracted code . Add lots and lots of animated progress bars and indicators flashing lights and flashing text boxes to indicate processing and gui status. import sys
import re
import threading
import io
import contextlib
from PyQt6.QtCore import QObject, QThread, pyqtSignal
from PyQt6.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QLabel, QLineEdit,
    QPushButton, QSlider, QTextEdit
)
from PyQt6.QtCore import Qt
from gradio_client import Client


class Worker(QObject):
    finished = pyqtSignal()  # Signal to indicate the worker is done
    result_ready = pyqtSignal(str, str)  # Signal to send the response and code back to the GUI
    execution_result = pyqtSignal(str)  # Signal to send the execution result back

    def __init__(self, client, inputs, top_p, temperature, retries=5):
        super().__init__()
        self.client = client
        self.inputs = inputs
        self.top_p = top_p
        self.temperature = temperature
        self.retries = retries

    def run(self):
        try_count = 0
        while try_count < self.retries:
            try:
                # Make the API call in the worker thread
                result = self.client.predict(
                    inputs=self.inputs,
                    top_p=self.top_p,
                    temperature=self.temperature,
                    chat_counter=0,
                    chatbot=[],
                    api_name="/predict"
                )

                # Extract the relevant parts of the response
                response_text = result[0][0][1]
                code = self.extract_code(response_text)

                # Emit the result to the main thread
                self.result_ready.emit(response_text, code)

                # Execute the code and capture the output or any errors
                exec_output = self.execute_code(code)
                self.execution_result.emit(exec_output)

                if "error" not in exec_output.lower():
                    break  # Success, no need for further retries
            except Exception as e:
                self.result_ready.emit(f"Error: {str(e)}", "")
                self.execution_result.emit(f"Execution error: {str(e)}")

            try_count += 1

        # Indicate the thread has finished
        self.finished.emit()

    def extract_code(self, text):
        pattern = r'```python(.*?)```'
        matches = re.findall(pattern, text, re.DOTALL)
        if matches:
            return "\n".join(match.strip() for match in matches)
        else:
            return "No code found."

    def execute_code(self, code):
        if code == "No code found.":
            return "No code to execute."

        try:
            output = io.StringIO()
            with contextlib.redirect_stdout(output):
                exec(code, globals())
            return output.getvalue() if output.getvalue() else "Code executed without output."
        except Exception as e:
            return f"Execution error: {str(e)}"


class ChatGPTApp(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("ChatGPT API Interface")
        self.setGeometry(100, 100, 800, 600)

        self.client = Client("yuntian-deng/ChatGPT")
        self.initUI()

    def initUI(self):
        layout = QVBoxLayout()

        # Input field for the chat input
        self.input_field = QLineEdit(self)
        self.input_field.setPlaceholderText("Type your message here...")
        layout.addWidget(self.input_field)

        # Top-p slider
        self.top_p_slider = QSlider(Qt.Orientation.Horizontal)
        self.top_p_slider.setRange(0, 100)
        self.top_p_slider.setValue(100)
        layout.addWidget(QLabel("Top-p (nucleus sampling):"))
        layout.addWidget(self.top_p_slider)

        # Temperature slider
        self.temperature_slider = QSlider(Qt.Orientation.Horizontal)
        self.temperature_slider.setRange(0, 100)
        self.temperature_slider.setValue(100)
        layout.addWidget(QLabel("Temperature:"))
        layout.addWidget(self.temperature_slider)

        # Prediction button
        self.predict_button = QPushButton("Predict", self)
        self.predict_button.clicked.connect(self.start_prediction_thread)
        layout.addWidget(self.predict_button)

        # Reset button
        self.reset_button = QPushButton("Reset Textbox", self)
        self.reset_button.clicked.connect(self.reset_textbox)
        layout.addWidget(self.reset_button)

        # Response text area
        self.response_area = QTextEdit(self)
        self.response_area.setReadOnly(True)
        layout.addWidget(QLabel("Response:"))
        layout.addWidget(self.response_area)

        # Code output text area
        self.code_area = QTextEdit(self)
        self.code_area.setReadOnly(True)
        layout.addWidget(QLabel("Extracted Code:"))
        layout.addWidget(self.code_area)

        # Code execution result text area
        self.execution_area = QTextEdit(self)
        self.execution_area.setReadOnly(True)
        layout.addWidget(QLabel("Execution Result:"))
        layout.addWidget(self.execution_area)

        # Debug Console for tracking retries
        self.debug_console = QTextEdit(self)
        self.debug_console.setReadOnly(True)
        layout.addWidget(QLabel("Debug Console:"))
        layout.addWidget(self.debug_console)

        self.setLayout(layout)

    def start_prediction_thread(self):
        inputs = self.input_field.text()
        top_p = self.top_p_slider.value() / 100.0
        temperature = self.temperature_slider.value() / 100.0

        # Create a QThread object
        self.thread = QThread()

        # Create a worker object
        self.worker = Worker(self.client, inputs, top_p, temperature)

        # Move the worker to the thread
        self.worker.moveToThread(self.thread)

        # Connect signals and slots
        self.thread.started.connect(self.worker.run)
        self.worker.finished.connect(self.thread.quit)
        self.worker.finished.connect(self.worker.deleteLater)
        self.thread.finished.connect(self.thread.deleteLater)
        self.worker.result_ready.connect(self.update_ui)
        self.worker.execution_result.connect(self.update_execution_result)

        # Start the thread
        self.thread.start()

    def update_ui(self, response_text, code):
        self.response_area.setPlainText(response_text)
        self.code_area.setPlainText(code)
        self.debug_console.append(f"New code received:\n{code}\n")

    def update_execution_result(self, execution_result):
        self.execution_area.setPlainText(execution_result)
        self.debug_console.append(f"Execution result:\n{execution_result}\n")

    def reset_textbox(self):
        self.input_field.clear()
        self.response_area.clear()
        self.code_area.clear()
        self.execution_area.clear()
        self.debug_console.clear()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = ChatGPTApp()
    window.show()
    sys.exit(app.exec())