Загрузка данных
import json
import os
import shutil
import webbrowser
import datetime
import speech_recognition as sr
from gtts import gTTS
import pygame
from groq import Groq
import pyautogui
import psutil
import time
client = Groq(api_key="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")
MEMORY_FILE = "nova_memory.json"
SETTINGS_FILE = "nova_settings.json"
def load_settings():
if os.path.exists(SETTINGS_FILE):
try:
with open(SETTINGS_FILE, "r", encoding="utf-8") as f:
return json.load(f)
except Exception:
return {"user_name": "друг", "lang": "ru"}
return {"user_name": "друг", "lang": "ru"}
def save_settings(settings):
try:
with open(SETTINGS_FILE, "w", encoding="utf-8") as f:
json.dump(settings, f, ensure_ascii=False, indent=2)
except Exception as e:
print(f"Ошибка сохранения настроек: {e}")
def load_memory():
if os.path.exists(MEMORY_FILE):
try:
with open(MEMORY_FILE, "r", encoding="utf-8") as f:
return json.load(f)
except Exception:
return []
return []
def save_memory():
try:
with open(MEMORY_FILE, "w", encoding="utf-8") as f:
json.dump(chat_history, f, ensure_ascii=False, indent=2)
except Exception as e:
print(f"Ошибка сохранения памяти: {e}")
chat_history = load_memory()
app_settings = load_settings()
user_name = app_settings.get("user_name", "друг")
current_lang = app_settings.get("lang", "ru")
def speak(text, lang=None):
use_lang = lang if lang else current_lang
print(f"Нова [{use_lang}]: {text}")
try:
tts = gTTS(text=text, lang=use_lang)
audio_file = "temp_voice.mp3"
tts.save(audio_file)
pygame.mixer.init()
pygame.mixer.music.load(audio_file)
pygame.mixer.music.play()
while pygame.mixer.music.get_busy():
pygame.time.Clock().tick(10)
pygame.mixer.quit()
if os.path.exists(audio_file):
os.remove(audio_file)
except Exception as e:
print(f"Ошибка озвучки: {e}")
def listen():
r = sr.Recognizer()
with sr.Microphone() as source:
print("\nСлушаю...")
r.adjust_for_ambient_noise(source, duration=0.5)
try:
audio = r.listen(source, timeout=5, phrase_time_limit=10)
except sr.WaitTimeoutError:
return ""
try:
rec_lang = "ru-RU" if current_lang == "ru" else "en-US"
command = r.recognize_google(audio, language=rec_lang)
print(f"Вы сказали: {command}")
return command
except sr.UnknownValueError:
return ""
except sr.RequestError:
print("Ошибка соединения с сервисом распознавания речи.")
return ""
def parse_intent_with_ai(user_speech):
global chat_history, user_name, current_lang
chat_history.append(f"{user_name}: {user_speech}")
context_slice = chat_history[-10:]
context_str = "\n".join(context_slice)
prompt = f"""
Ты — Нова, элитный голосовой ассистент на ПК. Пользователя зовут "{user_name}". Текущий язык: "{current_lang}".
Проанализируй фразу и верни СТРОГО JSON без markdown-оформления (без ```json):
{{
"action": "open_chat", "change_language", "set_name", "open_youtube", "google_search", "open_app",
"open_folder", "empty_recycle_bin", "shutdown_pc", "cancel_shutdown", "sleep_pc",
"time_info", "battery_info", "take_screenshot", "create_note", "copy_files", "exit", или "chat",
"messenger": "telegram, discord или whatsapp",
"chat_target": "имя контакта или чата",
"new_lang": "код языка",
"new_name": "новое имя",
"query": "поисковый запрос",
"app_name": "программа",
"folder_name": "папка",
"minutes": 0,
"note_text": "текст",
"source_path": "",
"dest_path": "",
"text": "ответ пользователю"
}}
История разговора:
{context_str}
Текущая фраза: "{user_speech}"
"""
try:
completion = client.chat.completions.create(
model="llama-3.3-70b-versatile",
messages=[{"role": "user", "content": prompt}],
temperature=0.1
)
clean_text = completion.choices[0].message.content.replace("```json", "").replace("```", "").strip()
result = json.loads(clean_text)
if result.get("action") == "change_language":
n_lang = result.get("new_lang")
if n_lang:
current_lang = n_lang.lower()
app_settings["lang"] = current_lang
save_settings(app_settings)
if result.get("action") == "set_name":
new_n = result.get("new_name")
if new_n:
user_name = new_n
app_settings["user_name"] = user_name
save_settings(app_settings)
if result.get("action") in ["chat", "set_name", "change_language", "open_chat"]:
chat_history.append(f"Нова: {result.get('text')}")
save_memory()
return result
except Exception as e:
print(f"Ошибка ИИ Groq: {e}")
return {"action": "chat", "text": "Я не совсем поняла команду, повторите пожалуйста."}
def execute_action(intent):
action = intent.get("action")
if action == "open_chat":
messenger = intent.get("messenger", "").lower()
target = intent.get("chat_target", "")
speak(f"Открываю чат с пользователем {target} в приложении {messenger}.")
if "telegram" in messenger:
os.system("start telegram")
time.sleep(2)
pyautogui.hotkey('ctrl', 'k')
time.sleep(0.5)
pyautogui.write(target, interval=0.1)
time.sleep(1)
pyautogui.press('enter')
elif "discord" in messenger or "дискорд" in messenger:
os.system("start discord")
time.sleep(2)
pyautogui.hotkey('ctrl', 'k')
time.sleep(0.5)
pyautogui.write(target, interval=0.1)
time.sleep(1)
pyautogui.press('enter')
else:
speak("Не удалось определить мессенджер для открытия чата.")
elif action == "change_language":
speak(intent.get("text", "Я сменила язык."))
elif action == "open_youtube":
q = intent.get("query", "")
webbrowser.open(f"[https://www.youtube.com/results?search_query=](https://www.youtube.com/results?search_query=){q}")
speak(f"Ищу на ютубе: {q}")
elif action == "google_search":
q = intent.get("query", "")
webbrowser.open(f"[https://www.google.com/search?q=](https://www.google.com/search?q=){q}")
speak("Ищу в интернете.")
elif action == "open_app":
app = intent.get("app_name", "").lower()
if "steam" in app: os.system("start steam://")
elif "calc" in app or "калькулятор" in app: os.system("calc")
elif "discord" in app: os.system("start discord")
elif "telegram" in app: os.system("start telegram")
elif "chrome" in app or "браузер" in app: os.system("start chrome")
elif "notepad" in app or "блокнот" in app: os.system("notepad")
elif "code" in app or "vs code" in app: os.system("code")
speak("Запускаю приложение.")
elif action == "open_folder":
folder = intent.get("folder_name", "").lower()
userprofile = os.environ.get("USERPROFILE", "C:\\Users\\Default")
path_to_open = ""
if "загруз" in folder or "downloads" in folder:
path_to_open = os.path.join(userprofile, "Downloads")
elif "документ" in folder or "documents" in folder:
path_to_open = os.path.join(userprofile, "Documents")
elif "рабочий стол" in folder or "desktop" in folder:
path_to_open = os.path.join(userprofile, "Desktop")
else:
path_to_open = folder
if path_to_open and os.path.exists(path_to_open):
os.startfile(path_to_open)
speak("Открываю папку.")
else:
speak("Не удалось найти указанную папку.")
elif action == "empty_recycle_bin":
try:
os.system("PowerShell -Command \"Clear-RecycleBin -Force -ErrorAction SilentlyContinue\"")
speak("Корзина успешно очищена.")
except Exception as e:
speak(f"Не удалось очистить корзину: {e}")
elif action == "shutdown_pc":
minutes = int(intent.get("minutes", 0))
if minutes > 0:
os.system(f"shutdown /s /t {minutes * 60}")
speak(f"Компьютер выключится через {minutes} минут.")
else:
os.system("shutdown /s /t 60")
speak("Компьютер выключится через минуту.")
elif action == "cancel_shutdown":
os.system("shutdown /a")
speak("Отменила выключение компьютера.")
elif action == "sleep_pc":
speak("Перевожу компьютер в спящий режим.")
os.system("rundll32.exe powrprof.dll,SetSuspendState 0,1,0")
elif action == "time_info":
now = datetime.datetime.now().strftime("%H:%M")
speak(f"Текущее время: {now}")
elif action == "battery_info":
battery = psutil.sensors_battery()
if battery:
plugged = "подключен к зарядке" if battery.power_plugged else "работает от батареи"
speak(f"Заряд батареи {battery.percent} процентов, компьютер {plugged}.")
else:
speak("Не удалось определить состояние батареи.")
elif action == "take_screenshot":
try:
os.makedirs("screenshots", exist_ok=True)
filename = f"screenshots/shot_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.png"
pyautogui.screenshot().save(filename)
speak("Скриншот успешно сохранен.")
except Exception as e:
speak(f"Не удалось сделать скриншот: {e}")
elif action == "create_note":
text = intent.get("note_text", "Пустая заметка")
with open("nova_notes.txt", "a", encoding="utf-8") as f:
f.write(f"[{datetime.datetime.now().strftime('%Y-%m-%d %H:%M')}] {text}\n")
speak("Записала в блокнот.")
elif action == "copy_files":
src = intent.get("source_path")
dst = intent.get("dest_path")
try:
if src and dst and os.path.exists(src):
if os.path.isdir(src):
shutil.copytree(src, dst, dirs_exist_ok=True)
else:
shutil.copy(src, dst)
speak("Файлы успешно скопированы.")
else:
speak("Не найден указанный путь.")
except Exception as e:
speak(f"Ошибка копирования: {e}")
elif action == "set_name":
speak(intent.get("text", "Готово."))
elif action == "exit":
speak(f"До свидания, {user_name}!")
exit()
elif action == "chat":
speak(intent.get("text", "Слушаю вас."))
if __name__ == "__main__":
speak(f"Нова активирована. Рада вас слышать, {user_name}!")
while True:
cmd = listen()
if cmd:
intent_data = parse_intent_with_ai(cmd)
execute_action(intent_data)