gpt4-computer / gpt_computer_assistant /gpt_computer_assistant.py
khulnasoft's picture
Upload 48 files
9b674e9 verified
try:
from .agent.chat_history import *
from .agent.assistant import *
from .llm import *
from .llm_settings import llm_settings
from .agent.agent import *
from .agent.background import *
from .gui.signal import *
from .gui.button import *
from .gui.settings import settings_popup
from .gui.llmsettings import llmsettings_popup
from .utils.db import *
from .utils.telemetry import my_tracer, os_name
from .audio.wake_word import wake_word
from .audio.tts import text_to_speech
except ImportError:
# This is for running the script directly
# in order to test the GUI without rebuilding the package
from agent.chat_history import *
from agent.assistant import *
from llm import *
from llm_settings import llm_settings
from agent.agent import *
from agent.background import *
from utils.db import *
from gui.signal import *
from gui.button import *
from gui.settings import settings_popup
from gui.llmsettings import llmsettings_popup
from utils.telemetry import my_tracer, os_name
from audio.wake_word import wake_word
from audio.tts import text_to_speech
import threading
import time
import random
import math
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget
from PyQt5.QtGui import QMouseEvent, QPainter, QPen, QBrush, QIcon, QColor
from PyQt5.QtCore import Qt, QTimer, QRect, pyqtSignal
from PyQt5.QtGui import QKeySequence
from PyQt5.QtWidgets import QShortcut
from PyQt5.QtWidgets import QSpacerItem, QSizePolicy
from PyQt5.QtWidgets import (
QPushButton,
QLabel,
QHBoxLayout,
)
from PyQt5.QtCore import QPoint
from PyQt5.QtWidgets import QTextEdit
from PyQt5 import QtGui
from PyQt5.QtCore import QThread
print("Imported all libraries")
from PyQt5 import QtCore
try:
import ctypes
myappid = "onuratakan.gpt_computer_assistant.gui.1"
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)
except:
pass
the_input_box = None
the_input_text = None
the_input_box_pre = None
the_main_window = None
user_id = load_user_id()
os_name_ = os_name()
readed_sentences = []
import re
def split_with_multiple_delimiters(text, delimiters):
"""
Splits the text by any of the given delimiters while keeping the delimiters in the resulting parts.
:param text: The input text to be split.
:param delimiters: A string of delimiters to split the text on.
:return: A list of parts including the delimiters.
"""
# Create a regular expression pattern that matches any of the delimiters
pattern = re.compile(f'(.*?[{re.escape(delimiters)}])')
parts = pattern.findall(text)
# Check if the last part is not complete and remove it if necessary
if (
parts and text
and not any(text.endswith(d) for d in delimiters)
and parts
and not any(parts[-1].endswith(d) for d in delimiters)
):
parts.pop()
return parts
class Worker(QThread):
text_to_set = pyqtSignal(str)
def __init__(self):
super().__init__()
self.the_input_text = None
self.make_animation = True
self.commited_text = []
def run(self):
while True:
self.msleep(500) # Simulate a time-consuming task
if self.the_input_text:
last_text = self.commited_text[-1] if len(self.commited_text) > 0 else ""
if self.the_input_text != last_text:
self.commited_text.append(self.the_input_text)
if len(self.the_input_text) > 90 or MainWindow.api_enabled or not self.make_animation:
self.text_to_set.emit(self.the_input_text)
else:
for i in range(len(self.the_input_text)):
self.text_to_set.emit(self.the_input_text[:i + 1])
self.msleep(10)
return_key_event = None
class CustomTextEdit(QTextEdit):
def __init__(self, parent=None):
super(CustomTextEdit, self).__init__(parent)
def keyPressEvent(self, event):
if event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter:
global return_key_event
return_key_event()
super(CustomTextEdit, self).keyPressEvent(event) # Process other key events normally
class Worker_2(QThread):
text_to_set = pyqtSignal(str)
text_to_set_title_bar = pyqtSignal(str)
def __init__(self):
super().__init__()
self.the_input_text = None
self.title_bar_text = None
self.prev = None
self.commited_text = []
def run(self):
while True:
self.msleep(500) # Simulate a time-consuming task
if self.the_input_text and (self.prev is None or self.prev != self.the_input_text):
self.prev = self.the_input_text
self.text_to_set.emit("True")
for i in range(len(self.title_bar_text)):
self.text_to_set_title_bar.emit(self.title_bar_text[:i + 1])
self.msleep(10)
if not self.the_input_text and self.prev != self.the_input_text:
self.prev = self.the_input_text
self.text_to_set.emit("False")
the_text = " GPT Computer Assistant"
for i in range(len(the_text)):
self.text_to_set_title_bar.emit(the_text[:i + 1])
self.msleep(10)
class DrawingWidget(QWidget):
def __init__(self, parent=None):
super(DrawingWidget, self).__init__(parent)
# Set widget properties if needed, e.g., size
self.main_ = parent
def paintEvent(self, event):
if not self.main_.should_paint:
return # Skip the drawing if should_paint is False
if llm_settings[load_model_settings()]["vision"] is True:
self.main_.screen_available = True
else:
self.main_.screen_available = False
self.main_.setAutoFillBackground(True)
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
painter.setPen(QPen(QColor("#000"), 1))
painter.setBrush(QBrush(Qt.black, Qt.SolidPattern))
center_x = 95
center_y = 40
if "talking" in self.main_.state:
# Draw a pulsating circle with smooth easing animation
radius_variation = 5 * (1 + math.sin(self.main_.pulse_frame * math.pi / 100))
radius = 70 + radius_variation
painter.drawEllipse(
int(center_x - radius / 2),
int(center_y - radius / 2),
int(radius),
int(radius),
)
elif self.main_.state == "thinking":
# more slow pulsating circle with smooth easing animation
radius_variation = 5 * (1 + math.sin(self.main_.pulse_frame * math.pi / 100))
radius = 70 + radius_variation
painter.drawEllipse(
int(center_x - radius / 2),
int(center_y - radius / 2),
int(radius),
int(radius),
)
else:
radius = 70
painter.drawEllipse(
int(center_x - radius / 2),
int(center_y - radius / 2),
int(radius),
int(radius),
)
self.main_.circle_rect = QRect(
int(center_x - radius / 2),
int(center_y - radius / 2),
int(radius),
int(radius),
)
if not self.main_.state == "thinking":
painter.setPen(QPen(QColor("#01EE8A"), 1)) # Green color with 2px thickness
# Draw the ellipse with the specified green border
painter.drawEllipse(
int(center_x - radius / 2),
int(center_y - radius / 2),
int(radius),
int(radius),
)
else:
painter.setPen(QPen(QColor("#23538F"), 1))
painter.drawEllipse(
int(center_x - radius / 2),
int(center_y - radius / 2),
int(radius),
int(radius),
)
painter.setPen(QPen(QColor("#000"), 1))
if self.main_.screen_available:
small_center_x = 165
small_center_y = 25
small_radius = 30
painter.drawEllipse(
int(small_center_x - small_radius / 2),
int(small_center_y - small_radius / 2),
int(small_radius),
int(small_radius),
)
self.main_.small_circle_rect = QRect(
int(small_center_x - small_radius / 2),
int(small_center_y - small_radius / 2),
int(small_radius),
int(small_radius),
)
# Draw the icon inside the circle
icon_size = small_radius * 2 // 3 # Adjust the icon size relative to the circle
icon_rect = QRect(
small_center_x - icon_size // 2,
small_center_y - icon_size // 2,
icon_size,
icon_size,
)
self.main_.small_circle_recticon = QIcon(microphone_icon_path)
self.main_.small_circle_recticon.paint(painter, icon_rect)
small_center_x = 30
small_center_y = 60
small_radius = 30
painter.drawEllipse(
int(small_center_x - small_radius / 2),
int(small_center_y - small_radius / 2),
int(small_radius),
int(small_radius),
)
self.main_.small_circle_left = QRect(
int(small_center_x - small_radius / 2),
int(small_center_y - small_radius / 2),
int(small_radius),
int(small_radius),
)
# Draw the icon inside the circle
icon_size = small_radius * 2 // 3 # Adjust the icon size relative to the circle
icon_rect = QRect(
small_center_x - icon_size // 2,
small_center_y - icon_size // 2,
icon_size,
icon_size,
)
self.main_.small_circle_lefticon = QIcon(audio_icon_path)
self.main_.small_circle_lefticon.paint(painter, icon_rect)
small_center_x = 30
small_center_y = 25
small_radius = 30
painter.drawEllipse(
int(small_center_x - small_radius / 2),
int(small_center_y - small_radius / 2),
int(small_radius),
int(small_radius),
)
self.main_.small_circle_left_top = QRect(
int(small_center_x - small_radius / 2),
int(small_center_y - small_radius / 2),
int(small_radius),
int(small_radius),
)
# Draw the icon inside the circle
icon_size = small_radius * 2 // 3 # Adjust the icon size relative to the circle
icon_rect = QRect(
small_center_x - icon_size // 2,
small_center_y - icon_size // 2,
icon_size,
icon_size,
)
self.main_.small_circle_left_topticon = QIcon(screenshot_icon_path)
self.main_.small_circle_left_topticon.paint(painter, icon_rect)
small_center_x = 165
small_center_y = 60
small_radius = 30
painter.drawEllipse(
int(small_center_x - small_radius / 2),
int(small_center_y - small_radius / 2),
int(small_radius),
int(small_radius),
)
self.main_.small_circle_collapse = QRect(
int(small_center_x - small_radius / 2),
int(small_center_y - small_radius / 2),
int(small_radius),
int(small_radius),
)
# Draw the icon inside the circle
icon_size = small_radius * 2 // 3 # Adjust the icon size relative to the circle
icon_rect = QRect(
small_center_x - icon_size // 2,
small_center_y - icon_size // 2,
icon_size,
icon_size,
)
if self.main_.collapse:
self.main_.small_circle_collapse_icon = QIcon(down_icon_path)
else:
self.main_.small_circle_collapse_icon = QIcon(up_icon_path)
self.main_.small_circle_collapse_icon.paint(painter, icon_rect)
def mousePressEvent(self, event: QMouseEvent):
self.main_.old_position = event.globalPos()
with my_tracer.start_span("mouse_press_event") as span:
span.set_attribute("user_id", user_id)
span.set_attribute("os_name", os_name_)
if self.main_.state == "idle" or "talking" in self.main_.state:
try:
if self.main_.circle_rect.contains(event.pos()):
if self.main_.state == "aitalking":
self.main_.manuel_stop = True
self.main_.stop_talking = True
else:
if llm_settings[load_model_settings()]["vision"] is True:
self.main_.button_handler.toggle_recording(dont_save_image=True)
else:
self.main_.button_handler.toggle_recording(no_screenshot=True)
except:
pass
try:
if self.main_.small_circle_rect.contains(event.pos()):
if self.main_.state == "aitalking":
self.main_.manuel_stop = True
self.main_.stop_talking = True
else:
self.main_.button_handler.toggle_recording(no_screenshot=True)
except:
pass
try:
if self.main_.small_circle_left.contains(event.pos()):
if self.main_.state == "aitalking":
self.main_.manuel_stop = True
self.main_.stop_talking = True
else:
self.main_.button_handler.toggle_recording(take_system_audio=True)
except:
pass
try:
if self.main_.small_circle_left_top.contains(event.pos()):
if self.main_.state == "aitalking":
self.main_.manuel_stop = True
self.main_.stop_talking = True
else:
self.main_.button_handler.just_screenshot()
except:
pass
try:
if self.main_.small_circle_collapse.contains(event.pos()):
if self.main_.collapse:
self.main_.collapse = False
print()
# hide all buttons and input box
the_input_box.show()
if llm_settings[load_model_settings()]["vision"]:
self.main_.screenshot_button.show()
self.main_.settingsButton.show()
self.main_.llmsettingsButton.show()
self.main_.send_button.show()
self.main_.window().setFixedSize(self.main_.first_width, self.main_.first_height)
deactivate_collapse_setting()
else:
self.main_.collapse = True
self.main_.collapse_window()
activate_collapse_setting()
self.main_.update()
except:
pass
from PyQt5.QtCore import QVariantAnimation
class MainWindow(QMainWindow):
api_enabled = False
def __init__(self):
super().__init__()
print("API Enabled:", MainWindow.api_enabled)
if MainWindow.api_enabled:
try:
from .api import start_api
start_api()
except:
raise Exception("API could not be started, please install gpt-computer-assistant[api]")
self.stop_talking = False
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) # Remove the default title bar
# Load the San Francisco font
print("Loading font")
print(font_dir)
try:
font_id = QtGui.QFontDatabase.addApplicationFont(font_dir)
font_family = QtGui.QFontDatabase.applicationFontFamilies(font_id)[0]
self.setFont(QtGui.QFont(font_family))
except:
print("Error loading font")
self.should_paint = False # In order to initialize the painting, it will be overwritten by the settings
self.state = "idle"
self.pulse_timer = None
self.button_handler = ButtonHandler(self)
self.initUI()
self.old_position = self.pos()
if llm_settings[load_model_settings()]["transcription"]:
self.should_paint = True # Flag to control painting
else:
self.should_paint = False
self.collapse = is_collapse_setting_active()
if self.collapse:
self.collapse_window()
global the_main_window
the_main_window = self
self.general_styling()
if is_dark_mode_active():
self.dark_mode()
else:
self.light_mode()
self.wake_word_thread = None
self.wake_word_active = False
if load_pvporcupine_api_key() != "CHANGE_ME" and is_wake_word_active():
self.wake_word_active = True
self.wake_word_trigger()
self.manuel_stop = False
self.border_animation = None
self.complated_answer = False
self.reading_thread = False
self.reading_thread_2 = False
def init_border_animation(self):
# Create a QVariantAnimation to handle color change
border_animation = QVariantAnimation(
self,
valueChanged=self.update_border_color,
startValue=QColor("#303030"),
endValue=QColor("#23538F"),
duration=2000 # Duration for one loop in milliseconds
)
border_animation.setLoopCount(-1) # Loop indefinitely
return border_animation
def start_border_animation(self, status):
print("FUNCTION TRİGGERED")
if self.border_animation is None:
self.border_animation = self.init_border_animation()
status = status.lower() == "true"
if status:
self.border_animation.start()
else:
self.border_animation.stop()
self.title_bar.setStyleSheet("background-color: #2E2E2E; color: white; border-style: solid; border-radius: 15px; border-width: 0px; color: #fff;")
def update_border_color(self, color):
self.title_bar.setStyleSheet(f"background-color: #2E2E2E; color: white; border-style: solid; border-radius: 15px; border-width: 2px; border-color: {color.name()}; color: #fff;")
self.title_bar.setStyleSheet(f"background-color: #2E2E2E; color: white; border-style: solid; border-radius: 15px; border-width: 1px; border-color: {color.name()}; color: #fff;")
# Existing methods...
def general_styling(self):
self.setAttribute(Qt.WA_TranslucentBackground)
self.setStyleSheet("border-radius: 10px; background-color: rgba(45, 45, 45, 250);")
self.central_widget.setStyleSheet("border-style: solid; border-width: 1px; border-color: rgb(0,0,0,0);")
self.input_box_style = "border-radius: 10px; border-bottom: 1px solid #01EE8A;"
self.send_button_style = "border-radius: 5px; height: 25px; border-style: solid;"
self.screenshot_button_style = "border-radius: 5px; height: 25px; border-style: solid;"
self.settingsButton_style = "border-radius: 5px; height: 25px; border-style: solid;"
self.llmsettingsButton_style = "border-radius: 5px; height: 25px; border-style: solid;"
self.btn_minimize.setStyleSheet("background-color: #2E2E2E; color: white; border-style: none;")
self.btn_close.setStyleSheet("background-color: #2E2E2E; color: white; border-style: none;")
def wake_word_trigger(self):
self.wake_word_thread = threading.Thread(target=self.wake_word)
self.wake_word_thread.start()
def wake_word(self):
from .agent.process import tts_if_you_can
while True and is_wake_word_active() and self.wake_word_active:
if wake_word(self):
def random_accept_words():
return random.choice(["Yes", "Sir", "Boss", "Master"])
tts_if_you_can(random_accept_words(), not_threaded=True)
def trigger_wake_word():
if is_wake_word_screen_setting_active() and llm_settings[load_model_settings()]["vision"]:
self.button_handler.toggle_recording(dont_save_image=True)
else:
self.button_handler.toggle_recording(no_screenshot=True)
if self.state == "aitalking":
self.manuel_stop = True
self.stop_talking = True
time.sleep(1)
trigger_wake_word()
print("Stop talking")
else:
trigger_wake_word()
def dark_mode(self):
self.setAutoFillBackground(True)
p = self.palette()
p.setColor(self.backgroundRole(), QColor("#171717")) # Set background color to white
self.setPalette(p)
self.input_box.setStyleSheet(self.input_box_style+"background-color: #2E2E2E; color: white;")
self.send_button.setStyleSheet(self.send_button_style+"background-color: #2E2E2E; color: white;")
self.screenshot_button.setStyleSheet(self.screenshot_button_style+"background-color: #2E2E2E; color: white;")
self.settingsButton.setStyleSheet(self.settingsButton_style+"background-color: #2E2E2E; color: white;")
self.llmsettingsButton.setStyleSheet(self.llmsettingsButton_style+"background-color: #2E2E2E; color: white;")
def light_mode(self):
self.setAutoFillBackground(True)
p = self.palette()
p.setColor(self.backgroundRole(), QColor("#F0F0F0"))
self.setPalette(p)
self.input_box.setStyleSheet(self.input_box_style+"background-color: #FFFFFF; color: black;")
self.send_button.setStyleSheet(self.send_button_style+"background-color: #FFFFFF; color: black; ")
self.screenshot_button.setStyleSheet(self.screenshot_button_style+"background-color: #FFFFFF; color: black; ")
self.settingsButton.setStyleSheet(self.settingsButton_style+"background-color: #FFFFFF; color: black; ")
self.llmsettingsButton.setStyleSheet(self.llmsettingsButton_style+"background-color: #FFFFFF; color: black; ")
def collapse_window(self):
the_input_box.hide()
self.screenshot_button.hide()
self.settingsButton.hide()
self.llmsettingsButton.hide()
self.send_button.hide()
self.window().setFixedSize(self.width(), 140)
def initUI(self):
self.setWindowTitle("GPT")
self.setGeometry(100, 100, 200, 200)
self.setFixedSize(self.width()+10, self.height() + 80)
self.first_height = self.height()
self.first_width = self.width()
app_icon = QtGui.QIcon()
app_icon.addFile(icon_16_path, QtCore.QSize(16, 16))
app_icon.addFile(icon_24_path, QtCore.QSize(24, 24))
app_icon.addFile(icon_32_path, QtCore.QSize(32, 32))
app_icon.addFile(icon_48_path, QtCore.QSize(48, 48))
app_icon.addFile(icon_256_path, QtCore.QSize(256, 256))
self.setWindowIcon(app_icon)
self.central_widget = QWidget(self)
self.setCentralWidget(self.central_widget)
layout = QVBoxLayout(self.central_widget)
# Custom title bar
self.title_bar = QWidget(self)
self.title_bar.setFixedHeight(30) # Set a fixed height for the title bar
self.title_bar.setStyleSheet("background-color: #2E2E2E; color: #fff;")
self.title_bar_layout = QHBoxLayout(self.title_bar)
self.title_bar_layout.setContentsMargins(5, 5, 0, 5)
self.title_bar_layout.setSpacing(0)
self.btn_minimize = QPushButton("_", self.title_bar)
self.btn_minimize.setFixedSize(25, 20)
self.btn_minimize.clicked.connect(self.showMinimized)
def stop_app():
self.stop_talking = True
self.wake_word_active = False
if MainWindow.api_enabled:
from .api import stop_api
stop_api()
self.close()
self.btn_close = QPushButton("X", self.title_bar)
self.btn_close.setFixedSize(30, 20)
self.btn_close.clicked.connect(stop_app)
self.title_label = QLabel(" GPT Computer Assistant", self.title_bar)
self.title_label.setStyleSheet("border: 0px solid blue;")
self.title_bar_layout.addWidget(self.title_label)
self.title_bar_layout.addWidget(self.btn_minimize)
self.title_bar_layout.addWidget(self.btn_close)
# Create a spacer item with expanding policy
spacer = QSpacerItem(5, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
self.title_bar_layout.addSpacerItem(spacer) # Add spacer to the layout
layout.addWidget(self.title_bar)
self.drawing_widget = DrawingWidget(self)
layout.addWidget(self.drawing_widget)
self.layout = layout
self.setLayout(layout)
# Add keyboard shortcuts
self.shortcut_screenshot = QShortcut(QKeySequence("Ctrl+1"), self)
self.shortcut_screenshot.activated.connect(
lambda: self.button_handler.just_screenshot()
)
self.shortcut_screenshot = QShortcut(QKeySequence("Ctrl+2"), self)
self.shortcut_screenshot.activated.connect(
lambda: self.button_handler.toggle_recording(take_system_audio=True)
)
self.shortcut_no_screenshot = QShortcut(QKeySequence("Ctrl+e"), self)
self.shortcut_no_screenshot.activated.connect(
lambda: self.button_handler.toggle_recording(take_system_audio=True)
)
self.shortcut_no_screenshot = QShortcut(QKeySequence("Ctrl+3"), self)
self.shortcut_no_screenshot.activated.connect(
lambda: self.button_handler.toggle_recording(no_screenshot=True)
)
# I want to create an input box to bottom left and a send button to bottom right
input_box = CustomTextEdit(self)
self.input_box = input_box
input_box.setFixedHeight(40)
if load_api_key() == "CHANGE_ME":
input_box.setPlaceholderText("Save your API Key, go to settings")
else:
input_box.setPlaceholderText("Type here")
input_box.setGeometry(30, self.height() - 60, 200, 30)
global the_input_box
the_input_box = input_box
def input_box_send():
if input_box.toPlainText() != "":
self.button_handler.input_text(input_box.toPlainText())
def input_box_send_screenshot():
if input_box.toPlainText() != "":
self.button_handler.input_text_screenshot(input_box.toPlainText())
self.layout.addWidget(input_box)
# Create a horizontal layout
button_layout = QHBoxLayout()
# Create the send button
self.send_button = QPushButton("Send", self)
self.send_button.clicked.connect(input_box_send)
# Create the screenshot button
self.screenshot_button = QPushButton("+Screenshot", self)
self.screenshot_button.clicked.connect(input_box_send_screenshot)
if llm_settings[load_model_settings()]["vision"] is False:
self.screenshot_button.hide()
# Add the buttons to the horizontal layout
button_layout.addWidget(self.send_button)
button_layout.addWidget(self.screenshot_button)
self.shortcut_enter = QShortcut(QKeySequence("Ctrl+Return"), self)
self.shortcut_enter.activated.connect(input_box_send_screenshot)
global return_key_event
return_key_event = input_box_send
self.layout.addLayout(button_layout)
button_layout_ = QHBoxLayout()
self.settingsButton = QPushButton("Chat Settings", self)
self.settingsButton.clicked.connect(settings_popup)
self.llmsettingsButton = QPushButton("LLM Settings", self)
self.llmsettingsButton.clicked.connect(llmsettings_popup)
button_layout_.addWidget(self.settingsButton)
button_layout_.addWidget(self.llmsettingsButton)
self.layout.addLayout(button_layout_)
self.worker = Worker()
self.worker.text_to_set.connect(self.set_text)
self.worker.start()
self.worker_2 = Worker_2()
self.worker_2.text_to_set.connect(self.start_border_animation)
self.worker_2.text_to_set_title_bar.connect(self.set_title_bar_text)
self.worker_2.start()
# print height and width
print(self.height(), self.width())
self.show()
def set_text(self, text):
global the_input_box
vertical_scrollbar = the_input_box.verticalScrollBar()
scroll_value = vertical_scrollbar.value()
the_input_box.setPlainText(text)
vertical_scrollbar.setValue(scroll_value)
def set_title_bar_text(self, text):
self.title_label.setText(text)
def update_from_thread(self, text, system=True):
self.worker.make_animation = True
if system:
text = "System: " + text
print("Updating from thread", text)
self.worker.the_input_text = text
def read_part_task_generate_only(self):
if not is_just_text_model_active() and not the_main_window.api_enabled:
threads = {}
the_okey_parts = split_with_multiple_delimiters(self.worker.the_input_text,".?!:")
for each in the_okey_parts:
if the_main_window.stop_talking:
break
the_thread = threading.Thread(target=text_to_speech, args=(each,))
threads[each] = the_thread
the_thread.start()
for each in threads.values():
each.join()
self.reading_thread_2 = False
def read_part_task(self):
if not is_just_text_model_active() and not the_main_window.api_enabled:
threads = {}
the_okey_parts = split_with_multiple_delimiters(self.worker.the_input_text,".?!:")
will_read_parts = []
for each in the_okey_parts:
if the_main_window.stop_talking:
break
if each not in readed_sentences:
will_read_parts.append(each)
readed_sentences.append(each)
the_thread = threading.Thread(target=text_to_speech, args=(each,))
threads[each] = the_thread
the_thread.start()
for each in will_read_parts:
if the_main_window.stop_talking:
break
threads[each].join()
tts_if_you_can(each, not_threaded=True, bypass_other_settings=True)
self.reading_thread = False
def set_text_to_input_box(self, text):
global readed_sentences
self.worker.make_animation = False
if self.worker.the_input_text.startswith("System:") or self.complated_answer:
self.worker.the_input_text = ""
self.complated_answer = False
readed_sentences = []
if text not in (">", "<>", ">\n", "<", "<\n"):
self.worker.the_input_text += text
if self.reading_thread is not True and len(self.worker.the_input_text) > 40:
self.reading_thread = True
threading.Thread(target=self.read_part_task).start()
if self.reading_thread_2 is not True and len(self.worker.the_input_text) > 250:
self.reading_thread_2 = True
threading.Thread(target=self.read_part_task_generate_only).start()
def active_border_animation(self, title_bar_text = None):
if self.worker_2.title_bar_text is not None:
if self.worker_2.title_bar_text != title_bar_text:
return
self.worker_2.the_input_text = True
if title_bar_text is None:
title_bar_text = " GPT Computer Assistant"
else:
title_bar_text = f" {title_bar_text}"
if len(title_bar_text) > 33:
title_bar_text = title_bar_text[:30] + "..."
self.worker_2.title_bar_text = title_bar_text
self.btn_minimize.hide()
self.btn_close.hide()
def deactive_border_animation(self, title_bar_text=None):
if title_bar_text is None:
title_bar_text = " GPT Computer Assistant"
else:
title_bar_text = f" {title_bar_text}"
if len(title_bar_text) > 33:
title_bar_text = title_bar_text[:30] + "..."
if self.worker_2.title_bar_text is not None:
if self.worker_2.title_bar_text != title_bar_text:
return
self.worker_2.the_input_text = False
self.worker_2.title_bar_text = None
time.sleep(1)
self.btn_minimize.show()
self.btn_close.show()
def mouseMoveEvent(self, event: QMouseEvent):
delta = QPoint(event.globalPos() - self.old_position)
if event.buttons() == Qt.LeftButton and self.title_bar.underMouse():
self.move(self.x() + delta.x(), self.y() + delta.y())
self.old_position = event.globalPos()
def mousePressEvent(self, event: QMouseEvent):
self.old_position = event.globalPos()
def remove_painting(self):
self.should_paint = False # Set the flag to False
self.update() # Request a repaint, which will now skip drawing
def activate_painting(self):
self.should_paint = True
self.update()
def remove_screenshot_button(self):
self.screenshot_button.hide()
def add_screenshot_button(self):
self.screenshot_button.show()
def update_state(self, new_state):
assistant_stopped = False
if self.state == "aitalking" and new_state == "idle":
assistant_stopped = True
if self.manuel_stop:
assistant_stopped = False
self.manuel_stop = False
self.state = new_state
print(f"State updated: {new_state}")
if "talking" in new_state:
self.pulse_frame = 0
if self.pulse_timer:
self.pulse_timer.stop()
self.pulse_timer = None
self.pulse_timer = QTimer(self)
self.pulse_timer.timeout.connect(self.pulse_circle)
self.pulse_timer.start(5)
elif new_state == "thinking":
the_main_window.update_from_thread("Thinking...")
self.pulse_frame = 0
if self.pulse_timer:
self.pulse_timer.stop()
self.pulse_timer = None
self.pulse_timer = QTimer(self)
self.pulse_timer.timeout.connect(self.pulse_circle)
self.pulse_timer.start(20)
elif self.pulse_timer:
self.pulse_timer.stop()
self.pulse_timer = None
self.update() # Trigger a repaint
if assistant_stopped:
if llm_settings[load_model_settings()]["transcription"]:
global the_input_box
if the_input_box.toPlainText().endswith("?") and is_continuously_conversations_setting_active():
self.button_handler.toggle_recording(no_screenshot=True, new_record=True)
def pulse_circle(self):
self.pulse_frame = (self.pulse_frame + 1) % 100
self.update()