Agnuxo commited on
Commit
62cb9b6
·
verified ·
1 Parent(s): 845a27d

Update README.md

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