See if you can upgrade this script to 2000 lines of code by adding logic and features: import sys
import re
import threading
import io
import contextlib
from PyQt6.QtCore import QObject, QThread, pyqtSignal, Qt, QTimer
from PyQt6.QtWidgets import (
    QApplication, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QLineEdit,
    QPushButton, QSlider, QTextEdit, QProgressBar, QMessageBox, QGroupBox
)
from gradio_client import Client


class Worker(QObject):
    finished = pyqtSignal()
    result_ready = pyqtSignal(str, str)
    execution_result = pyqtSignal(str)
    save_code_finished = pyqtSignal(bool, str)

    def __init__(self, client, inputs=None, top_p=0.7, temperature=0.7, retries=5):
        super().__init__()
        self.client = client
        self.inputs = inputs
        self.top_p = top_p
        self.temperature = temperature
        self.retries = retries
        self.api_call_count = 0
        self.is_saving = False

    def run(self):
        if isinstance(self.inputs, tuple):
            self.save_code()
        else:
            if self.inputs:
                self.run_prediction()
            else:
                self.save_code()

    def run_prediction(self):
        try_count = 0
        current_input = self.inputs
        last_error = ""
        while try_count < self.retries:
            try:
                self.api_call_count += 1
                result = self.client.predict(
                    inputs=current_input,
                    top_p=self.top_p,
                    temperature=self.temperature,
                    chat_counter=self.api_call_count,
                    chatbot=[],
                    api_name="/predict"
                )
                response_text = result[0][0][1]
                code = self.extract_code(response_text)

                # Emit raw response and code
                self.result_ready.emit(response_text, code)

                # Check if code is valid
                if self.is_valid_code(code):
                    exec_output = self.execute_code(code)
                    self.execution_result.emit(exec_output)
                    if "Execution error" not in exec_output:
                        # Success
                        break
                    else:
                        last_error = exec_output.replace("Execution error: ", "")
                        # Prepare input for next retry
                        current_input += f"\n\n# Fix the following error:\n{last_error}"
                else:
                    last_error = "No valid Python code found in the response."
                    break
            except Exception as e:
                last_error = f"An error occurred during API call: {str(e)}"
                self.result_ready.emit(f"Error: {str(e)}", "")
                self.execution_result.emit(f"Execution error: {str(e)}")
            try_count += 1

        if try_count == self.retries and "Execution error" in last_error:
            self.execution_result.emit(f"Failed after {self.retries} attempts. Last error: {last_error}")

        self.finished.emit()

    def save_code(self):
        filename, code = self.inputs  # inputs contains filename and code tuple
        try:
            with open(filename, 'w') as f:
                f.write(code)
            self.save_code_finished.emit(True, "Code saved successfully.")
        except Exception as e:
            self.save_code_finished.emit(False, f"Failed to save code: {str(e)}")

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

    def is_valid_code(self, code):
        return bool(code.strip()) and len(code.splitlines()) >= 2

    def execute_code(self, code):
        if not self.is_valid_code(code):
            return "No valid code to execute."

        try:
            output = io.StringIO()
            with contextlib.redirect_stdout(output):
                exec(code, {})
            exec_output = output.getvalue()
            return exec_output if exec_output 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.resize(900, 700)

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

    def initUI(self):
        layout = QVBoxLayout()

        # Group for input and parameters
        input_group = QGroupBox("Input & Parameters")
        input_layout = QVBoxLayout()

        self.input_field = QLineEdit(self)
        self.input_field.setPlaceholderText("Type your message here...")

        # Top-p Slider
        top_p_layout = QHBoxLayout()
        self.top_p_slider = QSlider(Qt.Orientation.Horizontal)
        self.top_p_slider.setRange(0, 100)
        self.top_p_slider.setValue(70)  # Default value
        self.top_p_slider.valueChanged.connect(self.update_top_p_label)
        self.top_p_label = QLabel("Top-p: 0.70")
        top_p_layout.addWidget(QLabel("Top-p:"))
        top_p_layout.addWidget(self.top_p_slider)
        top_p_layout.addWidget(self.top_p_label)

        # Temperature Slider
        temperature_layout = QHBoxLayout()
        self.temperature_slider = QSlider(Qt.Orientation.Horizontal)
        self.temperature_slider.setRange(0, 100)
        self.temperature_slider.setValue(70)  # Default value
        self.temperature_slider.valueChanged.connect(self.update_temperature_label)
        self.temperature_label = QLabel("Temperature: 0.70")
        temperature_layout.addWidget(QLabel("Temperature:"))
        temperature_layout.addWidget(self.temperature_slider)
        temperature_layout.addWidget(self.temperature_label)

        self.filename_field = QLineEdit(self)
        self.filename_field.setPlaceholderText("Enter filename to save code (e.g., output.py)")

        # Buttons
        button_layout = QHBoxLayout()
        self.predict_button = QPushButton("Predict", self)
        self.predict_button.clicked.connect(self.start_prediction_thread)
        self.save_execute_button = QPushButton("Save and Execute Code", self)
        self.save_execute_button.clicked.connect(self.save_and_execute_code)
        button_layout.addWidget(self.predict_button)
        button_layout.addWidget(self.save_execute_button)

        # Add to input layout
        input_layout.addWidget(self.input_field)
        input_layout.addLayout(top_p_layout)
        input_layout.addLayout(temperature_layout)
        input_layout.addWidget(self.filename_field)
        input_layout.addLayout(button_layout)

        input_group.setLayout(input_layout)

        # Group for response areas
        response_group = QGroupBox("Response Areas")
        response_layout = QVBoxLayout()

        self.response_area = QTextEdit(self)
        self.response_area.setReadOnly(True)

        self.code_area = QTextEdit(self)
        self.code_area.setReadOnly(True)

        self.execution_area = QTextEdit(self)
        self.execution_area.setReadOnly(True)

        response_layout.addWidget(QLabel("Response:"))
        response_layout.addWidget(self.response_area)
        response_layout.addWidget(QLabel("Extracted Code:"))
        response_layout.addWidget(self.code_area)
        response_layout.addWidget(QLabel("Execution Result:"))
        response_layout.addWidget(self.execution_area)

        response_group.setLayout(response_layout)

        # Progress Bar and Status Label
        self.api_counter_label = QLabel("API Call Count: 0")
        self.progress_bar = QProgressBar(self)
        self.progress_bar.setVisible(False)  # Hidden initially

        # Status Label
        self.status_label = QLabel("Status: Idle")

        layout.addWidget(input_group)
        layout.addWidget(response_group)
        layout.addWidget(self.api_counter_label)
        layout.addWidget(self.progress_bar)
        layout.addWidget(self.status_label)

        self.setLayout(layout)

    def update_top_p_label(self, value):
        top_p = value / 100.0
        self.top_p_label.setText(f"Top-p: {top_p:.2f}")

    def update_temperature_label(self, value):
        temperature = value / 100.0
        self.temperature_label.setText(f"Temperature: {temperature:.2f}")

    def start_prediction_thread(self):
        inputs = self.input_field.text()
        if not inputs.strip():
            QMessageBox.warning(self, "Warning", "Please enter a message before predicting.")
            return

        top_p = self.top_p_slider.value() / 100.0
        temperature = self.temperature_slider.value() / 100.0

        # Disable buttons to prevent multiple clicks
        self.predict_button.setEnabled(False)
        self.save_execute_button.setEnabled(False)

        # Reset response areas
        self.response_area.clear()
        self.code_area.clear()
        self.execution_area.clear()

        # Show progress bar
        self.progress_bar.setVisible(True)
        self.progress_bar.setRange(0, 0)  # Indeterminate
        self.status_label.setText("Status: Processing...")

        self.thread = QThread()
        self.worker = Worker(
            client=self.client,
            inputs=inputs,
            top_p=top_p,
            temperature=temperature,
            retries=5
        )

        self.worker.moveToThread(self.thread)
        self.thread.started.connect(self.worker.run)
        self.worker.result_ready.connect(self.update_ui)
        self.worker.execution_result.connect(self.update_execution_result)
        self.worker.finished.connect(self.thread.quit)
        self.worker.finished.connect(self.worker.deleteLater)
        self.thread.finished.connect(self.thread.deleteLater)
        self.worker.finished.connect(self.on_prediction_finished)

        # Update API call counter
        self.api_call_counter += 1
        self.api_counter_label.setText(f"API Call Count: {self.api_call_counter}")

        self.thread.start()

    def save_and_execute_code(self):
        code = self.code_area.toPlainText().strip()
        filename = self.filename_field.text().strip()

        if not filename:
            QMessageBox.warning(self, "Warning", "Please enter a filename to save the code.")
            return

        if not code:
            QMessageBox.warning(self, "Warning", "There is no code to save.")
            return

        # Disable buttons to prevent multiple clicks
        self.predict_button.setEnabled(False)
        self.save_execute_button.setEnabled(False)

        self.status_label.setText("Status: Saving code...")

        self.save_thread = QThread()
        self.save_worker = Worker(
            client=self.client,
            inputs=(filename, code)
        )
        self.save_worker.is_saving = True

        self.save_worker.moveToThread(self.save_thread)
        self.save_thread.started.connect(self.save_worker.run)
        self.save_worker.save_code_finished.connect(self.on_code_saved)
        self.save_worker.finished.connect(self.save_thread.quit)
        self.save_worker.finished.connect(self.save_worker.deleteLater)
        self.save_thread.finished.connect(self.save_thread.deleteLater)

        self.save_thread.start()

    def on_code_saved(self, success, message):
        if success:
            QMessageBox.information(self, "Success", message)
        else:
            QMessageBox.warning(self, "Error", message)

        self.predict_button.setEnabled(True)
        self.save_execute_button.setEnabled(True)
        self.status_label.setText("Status: Idle")

    def on_prediction_finished(self):
        self.progress_bar.setVisible(False)
        self.predict_button.setEnabled(True)
        self.save_execute_button.setEnabled(True)
        if "Execution error" in self.execution_area.toPlainText():
            self.status_label.setText("Status: Completed with errors.")
        else:
            self.status_label.setText("Status: Completed successfully.")

    def update_ui(self, response_text, code):
        self.response_area.setPlainText(response_text)
        self.code_area.setPlainText(code)

    def update_execution_result(self, execution_result):
        self.execution_area.setPlainText(execution_result)


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