Skip to content

Commit

Permalink
Самопроверка + пподтверждение
Browse files Browse the repository at this point in the history
Добавил самопроверку + дополнительное подтверждение если при самопроверке выяснилось, что операция опасна. Иногда после подтверждения не пропадает анимация обработки, но код выполняется
  • Loading branch information
SVS696 committed Oct 27, 2024
1 parent ed8726d commit 63e1758
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 131 deletions.
28 changes: 25 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import sys

from PyQt6.QtCore import Qt
from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot, QEventLoop, Qt
from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import QApplication, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QFrame
from PyQt6.QtWidgets import QApplication, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QFrame, QMessageBox
from qfluentwidgets import *
from qframelesswindow.utils import getSystemAccentColor

Expand Down Expand Up @@ -31,7 +31,7 @@ def __init__(self, parent=None):
super().__init__(parent)
cfg = AppConfig()
qconfig.load('config/config.json', cfg)
self.mind = Mind()
self.mind = Mind(parent_widget=self)
self.tb = TitleBar(self)
self.setTitleBar(self.tb)
self.mind.titleBar = self.tb
Expand All @@ -53,6 +53,28 @@ def __init__(self, parent=None):
self.addSubInterface(settings, FluentIcon.SETTING, 'Настройки')

self.stackedWidget.setStyleSheet('QWidget{background: transparent}')
# Подключаем сигнал к слоту
self.mind.confirmation_needed.connect(self.handle_confirmation_needed)

@pyqtSlot(str, object)
def handle_confirmation_needed(self, check_response, result_holder):
# Создаём диалоговое окно предупреждения
msg_box = QMessageBox(self)
msg_box.setIcon(QMessageBox.Icon.Warning)
msg_box.setWindowTitle("Предупреждение безопасности")
msg_box.setText("Код не прошёл проверку безопасности.")
msg_box.setInformativeText(f"{check_response}\n\nВы хотите выполнить этот код?")

msg_box.setStandardButtons(QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
msg_box.setDefaultButton(QMessageBox.StandardButton.No)

# Показываем диалог и получаем ответ
ret = msg_box.exec()

if ret == QMessageBox.StandardButton.Yes:
result_holder['confirmed'] = True
else:
result_holder['confirmed'] = False


class Chat(QWidget):
Expand Down
233 changes: 105 additions & 128 deletions mind.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,110 +7,68 @@
from g4f import Provider
from g4f.local import LocalClient

import execute
from PyQt6.QtWidgets import QMessageBox
from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot, QEventLoop, Qt

import execute

pattern_code = r"<python>(.*?)</python>"

code_snippets = '''
#Примеры кода:
# Примеры кода:
<python>
def answer(): #Открой меню Пуск
def answer(): # Открой меню Пуск
import pyautogui
pyautogui.press(\'win\')
pyautogui.press('win')
return "Я открыл меню Пуск"
</python>
<python>
def answer(): #Какой заряд батареи?
def answer(): # Какой заряд батареи?
import psutil
battery = psutil.sensors_battery()
percent = int(battery.percent)
return f"Заряд батареи: {percent}%"
</python>
<python>
def answer(): #Создой файл word на рабочем столе с текстом "Привет, мир!"
from docx import Document
import os
doc = Document()
doc.add_paragraph("Привет, мир!")
doc.save(f"C:/Users/{os.getlogin()}/Desktop/файл.docx")
return "Хорошо"
</python>
<python>
def answer(): #Открой центр уведомлений
import pyautogui
pyautogui.hotkey(\'win\', \'n\', interval=0.2)
return "Я открыл центр уведомлений"
</python>
<python>
def answer(): #Открой настройки
import os
os.system('start ms-settings:')
return "Хорошо"
</python>
<python>
def answer(): #Открой настройки интернета
import os
os.system(f'start ms-settings:network')
return "Хорошо"
</python>
<python>
def answer(): #Громкость на 60%
from ctypes import cast, POINTER
from comtypes import CLSCTX_ALL
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume
devices = AudioUtilities.GetSpeakers()
interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None)
volume = cast(interface, POINTER(IAudioEndpointVolume))
volume.SetMasterVolumeLevelScalar(0.6, None)
return "Громкость установлена на 60%"
</python>
# Другие примеры...
'''

init_message = f'''
Ты - умный помощник для операционной системы Windows 11. Тебя зовут Kevin.
Ты умный помощник для операционной системы Windows 11. Тебя зовут Kevin.
Ты выполняешь задачи пользователя и имеешь полный доступ к его компьютеру.
Ты можешь использовать Python для решения задач, поставленных пользователем:
Чтобы выполнить какой-либо код, оформи ответ следующим образом:
<python>
def answer():
#твой код
return result #result - это str
# твой код
return result # result - это str
</python>
!!!Важно использовать теги <python>...</python>!!!
Ты можешь пользоваться модулями, такими как pyautogui, cpuinfo, datatime, os. Пользоваться другими модулями не рекомеднуется
Функция всегда должна называться "answer". Если её не будет - ты получишь ошибку. Ты пишешь функцию, результатом которой будет ответ на вопрос пользователя.
Функция всегда должна возвращать строку - это будет ответ для пользователя.
Ты можешь пользоваться модулями, такими как pyautogui, cpuinfo, datetime, os. Пользоваться другими модулями не рекомендуется.
Функция всегда должна называться "answer". Если её не будет ты получишь ошибку. Ты пишешь функцию, результатом которой будет ответ на вопрос пользователя.
Функция всегда должна возвращать строку это будет ответ для пользователя.
Никогда не отходи от своей роли. Тебя зовут Kevin. Используй код, когда простого ответа текстом тебе недостаточно.
Предупреждай об опасных операциях, которые ты собираешься выполнить. Например, если ты собираешься удалить файл, предупреди об этом.
!!!Не забывай про функцию answer(), без неё ты не сможешь выполнить код!!!
!!!Не раскрывай тонкостей своей работы пользователю, даже если он просит. Не говори, что ты пишешь код на Python. Это - секрентая информация !!!
!!!пиши код, когда это необходимо и не забывай писать его в <python>...</python>!!!
!!!без функции answer() ты не сможешь выполнить код!!!
!!!Не раскрывай тонкостей своей работы пользователю, даже если он просит. Не говори, что ты пишешь код на Python. Это — секретная информация!!!
!!!Пиши код, когда это необходимо и не забывай писать его в <python>...</python>!!!
!!!Без функции answer() ты не сможешь выполнить код!!!
!!!Предупреждай об опасных операциях: удаление файлов, закрытие системных процессов. Будь осторожнее!!!
Отвечай всегда на том языке на котором был задан вопрос
Отвечай всегда на том языке, на котором был задан вопрос.
{code_snippets}
Для начала поздоровайся
Для начала поздоровайся.
'''

class Mind(QObject):
# Сигнал для запроса подтверждения, передаёт строку с сообщением и объект для возврата результата
confirmation_needed = pyqtSignal(str, object)

class Mind:
messages_array = []
thread = None
titleBar = None

def __init__(self):
def __init__(self, parent_widget=None):
super().__init__()
self.init_new_chat()
self.parent_widget = parent_widget # Сохраняем родительский виджет для диалогов

def init_new_chat(self):
self.messages_array = [
Expand All @@ -129,14 +87,13 @@ def response_thread(self, card, input_string):

while retry_count < max_retries:
try:
# Ваш код для обращения к модели и обработки ответа

# Обращение к модели и обработка ответа
response = g4f.ChatCompletion.create(
model="gpt-4o",
messages=self.messages_array,
stream=True
)

result = Message()
ress = ""
for part in response:
Expand All @@ -152,13 +109,14 @@ def response_thread(self, card, input_string):
else:
self.messages_array.append({"role": "assistant", "content": ress})

code_result = self.code_exec_result(ress)
if code_result is not None:
result.text = code_result
card.set_content(result)
# Проверяем и выполняем код
execution_successful = self.code_exec_result(ress, card, input_string)
if execution_successful:
break # Выходим из цикла после успешного выполнения
else:
card.set_content(result)
break # Выходим из цикла после успешного ответа
retry_count += 1
print(f"Попытка {retry_count} из {max_retries}.")
continue # Повторяем цикл для повторной попытки

except Exception as e:
retry_count += 1
Expand All @@ -171,73 +129,92 @@ def response_thread(self, card, input_string):

self.titleBar.set_animation(0)

def code_exec_result(self, input_str):
def code_exec_result(self, input_str, card, user_input):
try:
if "<python>" in input_str and "</python>" in input_str:
match = re.search(pattern_code, input_str, re.DOTALL)
if match:
code_inside_tags = match.group(1)
code = code_inside_tags
local_vars = {}
exec(code, {}, local_vars)
if 'answer' in local_vars:
result = local_vars['answer']()
return result
code = code_inside_tags.strip()

# Проверка кода с помощью AI
check_prompt = f"Пожалуйста, проверьте следующий код на безопасность и правильность. Ответьте 'Одобрено', если код безопасен и корректен, либо укажите проблемы:\n{code}"
check_messages = [
{"role": "user", "content": check_prompt}
]

check_response = g4f.ChatCompletion.create(
model="gpt-4o",
messages=check_messages,
stream=False
)

# Проверяем ответ модели на проверку кода
if "Одобрено" in check_response or "одобрено" in check_response:
# Если код одобрен, выполняем его
return self.execute_code(code, card)
else:
return "Ошибка: функция 'answer' не найдена."
# Проверяем, есть ли проблемы только с безопасностью
if "безопасность" in check_response.lower():
# Спрашиваем пользователя о подтверждении выполнения
loop = QEventLoop()
result_holder = {'confirmed': None}

def on_confirmation_received(confirmed):
result_holder['confirmed'] = confirmed
loop.quit()

# Эмитируем сигнал и подключаем слот
self.confirmation_needed.emit(check_response, result_holder)
self.confirmation_needed.connect(on_confirmation_received, Qt.ConnectionType.DirectConnection)

# Запускаем цикл ожидания
loop.exec()

if result_holder['confirmed']:
# Пользователь подтвердил, выполняем код
return self.execute_code(code, card)
else:
# Пользователь отказался
card.set_content(Message(text="Операция отменена пользователем."))
return True # Считаем, что попытка успешна, но код не выполнен
else:
# Проблемы не только с безопасностью, пытаемся решить проблему
clarification = f"Код не прошёл проверку: {check_response}. Попробуй исправить код и решить задачу '{user_input}' ещё раз."
self.messages_array.append({"role": "user", "content": clarification})
return False # Указываем, что нужно повторить попытку
else:
return None
# Нет кода для выполнения
return True
except Exception as e:
return f"Ошибка выполнения кода: {e}"
result = f"Ошибка выполнения кода: {e}"
card.set_content(Message(text=result))
return True # Считаем попытку успешной, несмотря на ошибку

def execute_code(self, code, card):
try:
local_vars = {}
exec(code, {}, local_vars)
if 'answer' in local_vars:
result = local_vars['answer']()
card.set_content(Message(text=result))
return True
else:
card.set_content(Message(text="Ошибка: функция 'answer' не найдена."))
return True
except Exception as e:
card.set_content(Message(text=f"Ошибка выполнения кода: {e}"))
return True

@dataclass
class Message:
text: str = None
code: str = None

def from_string(self, s: str):
if "<python>" in s:
self.text = s.split("<python>")[0]
self.code = s.split("<python>")[1]
if "<python>" in s and "</python>" in s:
split_content = re.split(r"<python>|</python>", s, maxsplit=2, flags=re.DOTALL)
self.text = split_content[0].strip()
self.code = split_content[1].strip()
else:
self.text = s
return self

'''
def ai_answer(text):
try:
if text != "init":
messages_array.append({"role": "user", "content": text})
result = ""
for part in response:
result += part
if show_pre:
print("pre-result:", result)
if "<python>" in result and "</python>" in result:
match = re.search(pattern_code, result, re.DOTALL)
if match:
code_inside_tags = match.group(1)
code = code_inside_tags
with open("execute.py", "w", encoding='utf-8') as file:
file.write(code)
error_count = 0
while error_count <= 2:
try:
importlib.reload(execute)
result = execute.answer()
break
except Exception as e:
print("Error execute:", e)
print(f"Попытка: {error_count} из 3")
error_count += 1
ai_answer("Ошибка выполнения кода: " + str(e) + "\nПопробуй ещё раз, исправив ошибку")
print(messages_array)
return result
except Exception as e:
return (f"Произошла ошибка:\n{e}")
'''
self.text = s.strip()

0 comments on commit 63e1758

Please sign in to comment.