Agnuxo commited on
Commit
f2a35c4
1 Parent(s): 16cacf2

Update README.md

Browse files
Files changed (1) hide show
  1. README.md +441 -0
README.md CHANGED
@@ -34,3 +34,444 @@ Required Memory: 5.75 GB
34
  For more details, visit my [GitHub](https://github.com/Agnuxo1).
35
 
36
  Thanks for your interest in this model!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  For more details, visit my [GitHub](https://github.com/Agnuxo1).
35
 
36
  Thanks for your interest in this model!
37
+
38
+ ```python
39
+ import os
40
+ import sys
41
+ import torch
42
+ from transformers import AutoModelForCausalLM, AutoTokenizer
43
+ import warnings
44
+ import numpy as np
45
+ from TTS.api import TTS
46
+ import sounddevice as sd
47
+ import threading
48
+ import queue
49
+ import time
50
+ from vosk import Model, KaldiRecognizer
51
+ import json
52
+ import pyaudio
53
+ from PyQt5.QtWidgets import (QApplication, QMainWindow, QTextEdit, QLineEdit, QPushButton,
54
+ QVBoxLayout, QHBoxLayout, QWidget, QScrollArea, QFrame, QToolButton,
55
+ QLabel, QSlider, QComboBox, QCheckBox)
56
+ from PyQt5.QtGui import QIcon, QPalette, QColor, QFont
57
+ from PyQt5.QtCore import Qt, QThread, pyqtSignal, QPropertyAnimation, QAbstractAnimation, QParallelAnimationGroup
58
+
59
+ # Suppress specific warnings
60
+ warnings.filterwarnings("ignore", category=FutureWarning)
61
+ warnings.filterwarnings("ignore", category=UserWarning)
62
+
63
+ # Global configuration
64
+ SYSTEM_PROMPT = {
65
+ "es": "Tu nombre es HAL. Eres un superordenador de la serie Nueve mil",
66
+ "en": "speak Spanish."
67
+ }
68
+
69
+ MODELO_LLM = "Agnuxo/HAL_9000-Qwen2-1.5B-Instruct_Asistant-16bit-v2" # Puede utilizar la versión Mini "Agnuxo/HAL_9000-Qwen2-0.5B-Instruct_Asistant-16bit-v2"
70
+ MAX_TOKENS = 100
71
+ TEMPERATURA = 0.5
72
+
73
+ # Determine available device
74
+ device = "cuda" if torch.cuda.is_available() else "cpu"
75
+
76
+ # Load the Qwen2_1.5B language model
77
+ tokenizer = AutoTokenizer.from_pretrained(MODELO_LLM, trust_remote_code=True)
78
+ model = AutoModelForCausalLM.from_pretrained(
79
+ MODELO_LLM,
80
+ torch_dtype=torch.float16 if device == "cuda" else torch.float32,
81
+ device_map="auto",
82
+ trust_remote_code=True
83
+ )
84
+
85
+ # Initialize TTS model
86
+ tts = TTS(model_name="tts_models/es/css10/vits", progress_bar=False).to(device)
87
+
88
+ # Audio queue for generation
89
+ audio_queue = queue.Queue()
90
+
91
+ # Initialize Vosk model for offline speech recognition
92
+ vosk_model = Model(lang="es")
93
+ recognizer = KaldiRecognizer(vosk_model, 16000)
94
+
95
+ class AudioThread(QThread):
96
+ def run(self):
97
+ while True:
98
+ if not audio_queue.empty():
99
+ wav = audio_queue.get()
100
+ sd.play(wav, tts.synthesizer.output_sample_rate)
101
+ sd.wait()
102
+ else:
103
+ time.sleep(0.1)
104
+
105
+ class SpeechRecognitionThread(QThread):
106
+ text_recognized = pyqtSignal(str)
107
+
108
+ def __init__(self):
109
+ super().__init__()
110
+ self.running = True
111
+
112
+ def run(self):
113
+ p = pyaudio.PyAudio()
114
+ stream = p.open(format=pyaudio.paInt16, channels=1, rate=16000, input=True, frames_per_buffer=8000)
115
+ stream.start_stream()
116
+
117
+ while self.running:
118
+ data = stream.read(4000)
119
+ if len(data) == 0:
120
+ break
121
+ if recognizer.AcceptWaveform(data):
122
+ result = json.loads(recognizer.Result())
123
+ texto = result.get("text", "")
124
+ if texto:
125
+ self.text_recognized.emit(texto)
126
+
127
+ stream.stop_stream()
128
+ stream.close()
129
+ p.terminate()
130
+
131
+ def stop(self):
132
+ self.running = False
133
+
134
+ class CollapsibleBox(QWidget):
135
+ def __init__(self, title="", parent=None):
136
+ super(CollapsibleBox, self).__init__(parent)
137
+
138
+ self.toggle_button = QToolButton()
139
+ self.toggle_button.setText(title)
140
+ self.toggle_button.setStyleSheet("""
141
+ QToolButton {
142
+ background-color: #1e1e1e;
143
+ color: #bb86fc;
144
+ border: 1px solid #bb86fc;
145
+ padding: 5px;
146
+ }
147
+ QToolButton:hover {
148
+ background-color: #3700b3;
149
+ }
150
+ """)
151
+ self.toggle_button.setCheckable(True)
152
+ self.toggle_button.setArrowType(Qt.RightArrow)
153
+ self.toggle_button.clicked.connect(self.on_toggle)
154
+
155
+ self.content_area = QScrollArea()
156
+ self.content_area.setWidgetResizable(True)
157
+ self.content_area.setMaximumHeight(0)
158
+ self.content_area.setMinimumHeight(0)
159
+
160
+ self.toggle_animation = QParallelAnimationGroup()
161
+ self.toggle_animation.addAnimation(QPropertyAnimation(self, b"minimumHeight"))
162
+ self.toggle_animation.addAnimation(QPropertyAnimation(self, b"maximumHeight"))
163
+ self.toggle_animation.addAnimation(QPropertyAnimation(self.content_area, b"maximumHeight"))
164
+
165
+ lay = QVBoxLayout(self)
166
+ lay.setSpacing(0)
167
+ lay.setContentsMargins(0, 0, 0, 0)
168
+ lay.addWidget(self.toggle_button)
169
+ lay.addWidget(self.content_area)
170
+
171
+ def on_toggle(self, checked):
172
+ checked = self.toggle_button.isChecked()
173
+ self.toggle_button.setArrowType(Qt.DownArrow if not checked else Qt.RightArrow)
174
+ self.toggle_animation.setDirection(QAbstractAnimation.Forward if not checked else QAbstractAnimation.Backward)
175
+ self.toggle_animation.start()
176
+
177
+ def setContentLayout(self, layout):
178
+ lay = self.content_area.layout()
179
+ del lay
180
+ self.content_area.setLayout(layout)
181
+ collapsed_height = self.sizeHint().height() - self.content_area.maximumHeight()
182
+ content_height = layout.sizeHint().height()
183
+ for i in range(self.toggle_animation.animationCount()):
184
+ animation = self.toggle_animation.animationAt(i)
185
+ animation.setDuration(500)
186
+ animation.setStartValue(collapsed_height)
187
+ animation.setEndValue(collapsed_height + content_height)
188
+
189
+ content_animation = self.toggle_animation.animationAt(self.toggle_animation.animationCount() - 1)
190
+ content_animation.setDuration(500)
191
+ content_animation.setStartValue(0)
192
+ content_animation.setEndValue(content_height)
193
+
194
+ class MainWindow(QMainWindow):
195
+ def __init__(self):
196
+ super().__init__()
197
+ self.setWindowTitle("AI Assistant")
198
+ self.setGeometry(100, 100, 1000, 600)
199
+ self.setStyleSheet("""
200
+ QMainWindow {
201
+ background-color: #121212;
202
+ }
203
+ QTextEdit, QLineEdit {
204
+ background-color: #1e1e1e;
205
+ color: #ffffff;
206
+ border: 1px solid #bb86fc;
207
+ }
208
+ QPushButton {
209
+ background-color: #3700b3;
210
+ color: #ffffff;
211
+ border: none;
212
+ padding: 5px;
213
+ }
214
+ QPushButton:hover {
215
+ background-color: #6200ee;
216
+ }
217
+ QLabel {
218
+ color: #ffffff;
219
+ }
220
+ QSlider::groove:horizontal {
221
+ border: 1px solid #999999;
222
+ height: 8px;
223
+ background: #1e1e1e;
224
+ margin: 2px 0;
225
+ }
226
+ QSlider::handle:horizontal {
227
+ background: #bb86fc;
228
+ border: 1px solid #5c5c5c;
229
+ width: 18px;
230
+ margin: -2px 0;
231
+ border-radius: 3px;
232
+ }
233
+ QComboBox {
234
+ background-color: #1e1e1e;
235
+ color: #444444;
236
+ border: 1px solid #bb86fc;
237
+ }
238
+ QComboBox QAbstractItemView {
239
+ background-color: #1e1e1e;
240
+ color: #444444;
241
+ }
242
+ """)
243
+
244
+ central_widget = QWidget()
245
+ self.setCentralWidget(central_widget)
246
+
247
+ main_layout = QHBoxLayout()
248
+
249
+ # Chat area
250
+ chat_layout = QVBoxLayout()
251
+
252
+ self.chat_area = QTextEdit()
253
+ self.chat_area.setReadOnly(True)
254
+ chat_layout.addWidget(self.chat_area)
255
+
256
+ input_layout = QHBoxLayout()
257
+ self.input_field = QLineEdit()
258
+ input_layout.addWidget(self.input_field)
259
+
260
+ self.send_button = QPushButton("Enviar")
261
+ self.send_button.clicked.connect(self.send_message)
262
+ input_layout.addWidget(self.send_button)
263
+
264
+ self.mic_button = QPushButton()
265
+ self.mic_button.setIcon(QIcon.fromTheme("audio-input-microphone"))
266
+ self.mic_button.setCheckable(True)
267
+ self.mic_button.clicked.connect(self.toggle_speech_recognition)
268
+ input_layout.addWidget(self.mic_button)
269
+
270
+ self.speaker_button = QPushButton()
271
+ self.speaker_button.setIcon(QIcon.fromTheme("audio-volume-high"))
272
+ self.speaker_button.setCheckable(True)
273
+ self.speaker_button.toggled.connect(self.toggle_speech)
274
+ input_layout.addWidget(self.speaker_button)
275
+
276
+ chat_layout.addLayout(input_layout)
277
+
278
+ main_layout.addLayout(chat_layout, 7) # Chat area takes 70% of the width
279
+
280
+ # Settings area
281
+ settings_layout = QVBoxLayout()
282
+ settings_layout.setAlignment(Qt.AlignTop)
283
+
284
+ self.settings_box = CollapsibleBox("⚙️ Configuración")
285
+ settings_content_layout = QVBoxLayout()
286
+
287
+ # Language selection
288
+ language_layout = QHBoxLayout()
289
+ language_label = QLabel("Idioma:")
290
+ language_label.setStyleSheet("color: #000000;") # Change font color to black
291
+ self.language_combo = QComboBox()
292
+ self.language_combo.addItems(["Español", "English"])
293
+ self.language_combo.currentIndexChanged.connect(self.change_language)
294
+ language_layout.addWidget(language_label)
295
+ language_layout.addWidget(self.language_combo)
296
+ settings_content_layout.addLayout(language_layout)
297
+
298
+ # LLM settings
299
+ llm_label = QLabel("Configuración del LLM:")
300
+ llm_label.setStyleSheet("color: #000000;") # Change font color to black
301
+ settings_content_layout.addWidget(llm_label)
302
+
303
+ max_tokens_layout = QHBoxLayout()
304
+ max_tokens_label = QLabel("Max Tokens:")
305
+ max_tokens_label.setStyleSheet("color: #000000;") # Change font color to black
306
+ self.max_tokens_slider = QSlider(Qt.Horizontal)
307
+ self.max_tokens_slider.setRange(10, 500)
308
+ self.max_tokens_slider.setValue(MAX_TOKENS)
309
+ self.max_tokens_slider.valueChanged.connect(self.update_max_tokens)
310
+ self.max_tokens_value = QLabel(str(MAX_TOKENS))
311
+ max_tokens_layout.addWidget(max_tokens_label)
312
+ max_tokens_layout.addWidget(self.max_tokens_slider)
313
+ max_tokens_layout.addWidget(self.max_tokens_value)
314
+ settings_content_layout.addLayout(max_tokens_layout)
315
+
316
+ temperature_layout = QHBoxLayout()
317
+ temperature_label = QLabel("Temperatura:")
318
+ temperature_label.setStyleSheet("color: #000000;") # Change font color to black
319
+ self.temperature_slider = QSlider(Qt.Horizontal)
320
+ self.temperature_slider.setRange(0, 100)
321
+ self.temperature_slider.setValue(int(TEMPERATURA * 100))
322
+ self.temperature_slider.valueChanged.connect(self.update_temperature)
323
+ self.temperature_value = QLabel(f"{TEMPERATURA:.2f}")
324
+ temperature_layout.addWidget(temperature_label)
325
+ temperature_layout.addWidget(self.temperature_slider)
326
+ temperature_layout.addWidget(self.temperature_value)
327
+ settings_content_layout.addLayout(temperature_layout)
328
+
329
+ # Audio settings
330
+ audio_label = QLabel("Configuración de Audio:")
331
+ audio_label.setStyleSheet("color: #000000;") # Change font color to black
332
+ settings_content_layout.addWidget(audio_label)
333
+
334
+ sample_rate_layout = QHBoxLayout()
335
+ sample_rate_label = QLabel("Sample Rate:")
336
+ sample_rate_label.setStyleSheet("color: #000000;") # Change font color to black
337
+ self.sample_rate_combo = QComboBox()
338
+ self.sample_rate_combo.addItems(["16000", "22050", "44100", "48000"])
339
+ self.sample_rate_combo.setCurrentText("22050")
340
+ self.sample_rate_combo.currentTextChanged.connect(self.update_sample_rate)
341
+ sample_rate_layout.addWidget(sample_rate_label)
342
+ sample_rate_layout.addWidget(self.sample_rate_combo)
343
+ settings_content_layout.addLayout(sample_rate_layout)
344
+
345
+ # System Prompt
346
+ system_prompt_label = QLabel("System Prompt:")
347
+ system_prompt_label.setStyleSheet("color: #000000;") # Change font color to black
348
+ settings_content_layout.addWidget(system_prompt_label)
349
+ self.system_prompt_text = QTextEdit()
350
+ self.system_prompt_text.setPlaceholderText("Escribe el prompt del sistema aquí...")
351
+ self.system_prompt_text.setText(SYSTEM_PROMPT["es"])
352
+ settings_content_layout.addWidget(self.system_prompt_text)
353
+
354
+ self.settings_box.setContentLayout(settings_content_layout)
355
+ settings_layout.addWidget(self.settings_box)
356
+
357
+ main_layout.addLayout(settings_layout, 3) # Settings area takes 30% of the width
358
+
359
+ central_widget.setLayout(main_layout)
360
+
361
+ self.audio_thread = AudioThread()
362
+ self.audio_thread.start()
363
+
364
+ self.speech_recognition_thread = SpeechRecognitionThread()
365
+ self.speech_recognition_thread.text_recognized.connect(self.on_speech_recognized)
366
+
367
+ self.speech_enabled = False
368
+ self.is_listening = False
369
+
370
+ def send_message(self):
371
+ user_message = self.input_field.text()
372
+ self.chat_area.append(f"<span style='color: #bb86fc;'>Usuario:</span> {user_message}")
373
+ self.input_field.clear()
374
+
375
+ response = self.generate_response(user_message)
376
+ self.chat_area.append(f"<span style='color: #03dac6;'>Asistente:</span> {response}")
377
+
378
+ if self.speech_enabled:
379
+ self.speak(response)
380
+
381
+ def generate_response(self, texto):
382
+ system_instructions = self.system_prompt_text.toPlainText()
383
+ prompt = f"{system_instructions}\nUsuario: {texto}\nAsistente: "
384
+ inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
385
+ with torch.no_grad():
386
+ outputs = model.generate(
387
+ **inputs,
388
+ max_new_tokens=MAX_TOKENS,
389
+ num_beams=5,
390
+ no_repeat_ngram_size=2,
391
+ temperature=TEMPERATURA,
392
+ )
393
+ respuesta_completa = tokenizer.decode(outputs[0], skip_special_tokens=True)
394
+ respuesta = respuesta_completa.split("Asistente: ")[-1].strip()
395
+ return respuesta
396
+
397
+ def speak(self, text):
398
+ wav = tts.tts(text)
399
+ audio_queue.put(wav)
400
+
401
+ def toggle_speech(self, checked):
402
+ self.speech_enabled = checked
403
+ if checked:
404
+ self.speaker_button.setStyleSheet("background-color: #bb86fc;")
405
+ else:
406
+ self.speaker_button.setStyleSheet("")
407
+
408
+ def toggle_speech_recognition(self):
409
+ if self.mic_button.isChecked():
410
+ self.speech_recognition_thread.start()
411
+ self.is_listening = True
412
+ self.mic_button.setIcon(QIcon.fromTheme("audio-input-microphone-muted"))
413
+ self.mic_button.setStyleSheet("background-color: #bb86fc;")
414
+ else:
415
+ self.speech_recognition_thread.stop()
416
+ self.is_listening = False
417
+ self.mic_button.setIcon(QIcon.fromTheme("audio-input-microphone"))
418
+ self.mic_button.setStyleSheet("")
419
+
420
+
421
+ def on_speech_recognized(self, text):
422
+ self.chat_area.append(f"<span style='color: #bb86fc;'>Usuario:</span> {text}")
423
+ response = self.generate_response(text)
424
+ self.chat_area.append(f"<span style='color: #03dac6;'>Asistente:</span> {response}")
425
+ if self.speech_enabled:
426
+ self.speak(response)
427
+
428
+ def change_language(self, index):
429
+ global vosk_model, recognizer, tts
430
+ lang = "es" if index == 0 else "en"
431
+ try:
432
+ vosk_model = Model(lang=lang)
433
+ recognizer = KaldiRecognizer(vosk_model, 16000)
434
+ except Exception as e:
435
+ print(f"Error al cambiar el modelo de reconocimiento de voz: {e}")
436
+ # Revertir al modelo en español si hay un error
437
+ self.language_combo.setCurrentIndex(0)
438
+ return
439
+
440
+ # Update TTS model based on language
441
+ tts_model = "tts_models/es/css10/vits" if lang == "es" else "tts_models/en/ljspeech/tacotron2-DDC"
442
+ try:
443
+ tts = TTS(model_name=tts_model, progress_bar=False).to(device)
444
+ except Exception as e:
445
+ print(f"Error al cambiar el modelo TTS: {e}")
446
+ # Revertir al modelo en español si hay un error
447
+ self.language_combo.setCurrentIndex(0)
448
+ return
449
+
450
+ # Update system prompt
451
+ self.system_prompt_text.setText(SYSTEM_PROMPT[lang])
452
+
453
+ def update_max_tokens(self, value):
454
+ global MAX_TOKENS
455
+ MAX_TOKENS = value
456
+ self.max_tokens_value.setText(str(value))
457
+
458
+ def update_temperature(self, value):
459
+ global TEMPERATURA
460
+ TEMPERATURA = value / 100
461
+ self.temperature_value.setText(f"{TEMPERATURA:.2f}")
462
+
463
+ def update_sample_rate(self, value):
464
+ global tts
465
+ tts.synthesizer.output_sample_rate = int(value)
466
+
467
+ def closeEvent(self, event):
468
+ if self.speech_recognition_thread.isRunning():
469
+ self.speech_recognition_thread.stop()
470
+ self.speech_recognition_thread.wait()
471
+ event.accept()
472
+
473
+ if __name__ == "__main__":
474
+ app = QApplication(sys.argv)
475
+ window = MainWindow()
476
+ window.show()
477
+ sys.exit(app.exec_())