pygpt-net 2.6.25__py3-none-any.whl → 2.6.27__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. pygpt_net/CHANGELOG.txt +8 -0
  2. pygpt_net/__init__.py +1 -1
  3. pygpt_net/app.py +3 -1
  4. pygpt_net/controller/access/voice.py +3 -5
  5. pygpt_net/controller/audio/audio.py +9 -6
  6. pygpt_net/controller/audio/ui.py +263 -0
  7. pygpt_net/controller/chat/common.py +17 -1
  8. pygpt_net/controller/model/importer.py +17 -3
  9. pygpt_net/controller/theme/theme.py +4 -1
  10. pygpt_net/core/audio/backend/native.py +113 -79
  11. pygpt_net/core/audio/backend/pyaudio.py +16 -19
  12. pygpt_net/core/audio/backend/pygame.py +12 -15
  13. pygpt_net/core/audio/capture.py +10 -9
  14. pygpt_net/core/audio/context.py +3 -6
  15. pygpt_net/core/models/models.py +5 -1
  16. pygpt_net/core/types/openai.py +2 -1
  17. pygpt_net/data/config/config.json +18 -4
  18. pygpt_net/data/config/models.json +2 -2
  19. pygpt_net/data/config/settings.json +58 -10
  20. pygpt_net/data/locale/locale.de.ini +2 -0
  21. pygpt_net/data/locale/locale.en.ini +10 -2
  22. pygpt_net/data/locale/locale.es.ini +2 -0
  23. pygpt_net/data/locale/locale.fr.ini +2 -0
  24. pygpt_net/data/locale/locale.it.ini +2 -0
  25. pygpt_net/data/locale/locale.pl.ini +3 -1
  26. pygpt_net/data/locale/locale.uk.ini +2 -0
  27. pygpt_net/data/locale/locale.zh.ini +2 -0
  28. pygpt_net/plugin/audio_input/simple.py +5 -10
  29. pygpt_net/plugin/audio_output/plugin.py +4 -17
  30. pygpt_net/provider/core/config/patch.py +10 -1
  31. pygpt_net/provider/llms/local.py +8 -2
  32. pygpt_net/provider/llms/open_router.py +104 -0
  33. pygpt_net/ui/layout/chat/input.py +5 -2
  34. pygpt_net/ui/main.py +1 -2
  35. pygpt_net/ui/widget/audio/bar.py +5 -1
  36. pygpt_net/ui/widget/textarea/input.py +475 -50
  37. {pygpt_net-2.6.25.dist-info → pygpt_net-2.6.27.dist-info}/METADATA +46 -35
  38. {pygpt_net-2.6.25.dist-info → pygpt_net-2.6.27.dist-info}/RECORD +41 -39
  39. {pygpt_net-2.6.25.dist-info → pygpt_net-2.6.27.dist-info}/LICENSE +0 -0
  40. {pygpt_net-2.6.25.dist-info → pygpt_net-2.6.27.dist-info}/WHEEL +0 -0
  41. {pygpt_net-2.6.25.dist-info → pygpt_net-2.6.27.dist-info}/entry_points.txt +0 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "__meta__": {
3
- "version": "2.6.25",
4
- "app.version": "2.6.25",
3
+ "version": "2.6.27",
4
+ "app.version": "2.6.27",
5
5
  "updated_at": "2025-08-26T00:00:00"
6
6
  },
7
7
  "access.audio.event.speech": false,
@@ -77,6 +77,7 @@
77
77
  "api_endpoint_anthropic": "https://api.anthropic.com/v1",
78
78
  "api_endpoint_mistral": "https://api.mistral.ai/v1",
79
79
  "api_endpoint_hugging_face": "https://router.huggingface.co/v1",
80
+ "api_endpoint_open_router": "https://openrouter.ai/api/v1",
80
81
  "api_key": "",
81
82
  "api_key_google": "",
82
83
  "api_key_anthropic": "",
@@ -86,6 +87,7 @@
86
87
  "api_key_xai": "",
87
88
  "api_key_mistral": "",
88
89
  "api_key_voyage": "",
90
+ "api_key_open_router": "",
89
91
  "api_proxy": "",
90
92
  "api_use_responses": true,
91
93
  "api_use_responses_llama": false,
@@ -173,7 +175,9 @@
173
175
  "vision": "",
174
176
  "agent": "",
175
177
  "agent_llama": "",
176
- "expert": ""
178
+ "agent_openai": "",
179
+ "expert": "",
180
+ "computer": ""
177
181
  },
178
182
  "debug": false,
179
183
  "debug.render": false,
@@ -244,6 +248,16 @@
244
248
  "name": "model_name",
245
249
  "value": "text-embedding-3-small",
246
250
  "type": "str"
251
+ },
252
+ {
253
+ "name": "api_base",
254
+ "value": "https://api.openai.com/v1",
255
+ "type": "str"
256
+ },
257
+ {
258
+ "name": "timeout",
259
+ "value": 60,
260
+ "type": "float"
247
261
  }
248
262
  ],
249
263
  "llama.idx.embeddings.env": [
@@ -333,7 +347,7 @@
333
347
  "plugins": {},
334
348
  "plugins_enabled": {
335
349
  "agent": false,
336
- "audio_input": false,
350
+ "audio_input": true,
337
351
  "audio_output": false,
338
352
  "cmd_api": false,
339
353
  "cmd_code_interpreter": false,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "__meta__": {
3
- "version": "2.6.25",
4
- "app.version": "2.6.25",
3
+ "version": "2.6.27",
4
+ "app.version": "2.6.27",
5
5
  "updated_at": "2025-08-26T23:07:35"
6
6
  },
7
7
  "items": {
@@ -388,6 +388,40 @@
388
388
  "advanced": false,
389
389
  "tab": "Voyage"
390
390
  },
391
+ "api_key_open_router": {
392
+ "section": "api_keys",
393
+ "type": "text",
394
+ "slider": false,
395
+ "label": "settings.api_key.open_router",
396
+ "description": "settings.api_key.open_router.desc",
397
+ "value": "",
398
+ "min": null,
399
+ "max": null,
400
+ "multiplier": null,
401
+ "step": null,
402
+ "extra": {
403
+ "bold": true
404
+ },
405
+ "secret": true,
406
+ "persist": true,
407
+ "advanced": false,
408
+ "tab": "OpenRouter"
409
+ },
410
+ "api_endpoint_open_router": {
411
+ "section": "api_keys",
412
+ "type": "text",
413
+ "slider": false,
414
+ "label": "settings.api_endpoint_open_router",
415
+ "description": "settings.api_endpoint_open_router.desc",
416
+ "value": "https://openrouter.ai/api/v1",
417
+ "min": null,
418
+ "max": null,
419
+ "multiplier": null,
420
+ "step": null,
421
+ "secret": false,
422
+ "advanced": false,
423
+ "tab": "OpenRouter"
424
+ },
391
425
  "app.env": {
392
426
  "section": "general",
393
427
  "type": "dict",
@@ -1395,7 +1429,20 @@
1395
1429
  "step": 1,
1396
1430
  "advanced": false,
1397
1431
  "tab": "device"
1398
- },
1432
+ },
1433
+ "audio.input.timeout": {
1434
+ "section": "audio",
1435
+ "type": "int",
1436
+ "slider": false,
1437
+ "label": "settings.audio.input.timeout",
1438
+ "description": "settings.audio.input.timeout.desc",
1439
+ "value": 120,
1440
+ "min": 0,
1441
+ "multiplier": 1,
1442
+ "step": 1,
1443
+ "advanced": false,
1444
+ "tab": "options"
1445
+ },
1399
1446
  "audio.input.stop_interval": {
1400
1447
  "section": "audio",
1401
1448
  "type": "int",
@@ -1410,16 +1457,17 @@
1410
1457
  "advanced": false,
1411
1458
  "tab": "options"
1412
1459
  },
1413
- "audio.input.timeout": {
1460
+ "audio.input.continuous": {
1414
1461
  "section": "audio",
1415
- "type": "int",
1462
+ "type": "bool",
1416
1463
  "slider": false,
1417
- "label": "settings.audio.input.timeout",
1418
- "description": "settings.audio.input.timeout.desc",
1419
- "value": 120,
1420
- "min": 0,
1421
- "multiplier": 1,
1422
- "step": 1,
1464
+ "label": "settings.audio.input.continuous",
1465
+ "description": "settings.audio.input.continuous.desc",
1466
+ "value": false,
1467
+ "min": null,
1468
+ "max": null,
1469
+ "multiplier": null,
1470
+ "step": null,
1423
1471
  "advanced": false,
1424
1472
  "tab": "options"
1425
1473
  },
@@ -1435,7 +1483,7 @@
1435
1483
  "step": null,
1436
1484
  "advanced": false,
1437
1485
  "tab": "options"
1438
- },
1486
+ },
1439
1487
  "audio.cache.enabled": {
1440
1488
  "section": "audio",
1441
1489
  "type": "bool",
@@ -1116,6 +1116,8 @@ settings.audio.input.backend = Backend für Audioeingabe
1116
1116
  settings.audio.input.backend.desc = Wählen Sie das Backend für die Audioeingabe.
1117
1117
  settings.audio.input.channels = Kanäle
1118
1118
  settings.audio.input.channels.desc = Eingabekanäle, Standard: 1
1119
+ settings.audio.input.continuous = Kontinuierliche Audioaufnahme (Stücke)
1120
+ settings.audio.input.continuous.desc = Aktivieren Sie die Aufnahme in Stücken für lange Audioaufnahmen im Notizblock (Sprachnotizen).
1119
1121
  settings.audio.input.device = Gerät für Audioeingabe
1120
1122
  settings.audio.input.device.desc = Wählen Sie das Gerät für Mikrofoneingang.
1121
1123
  settings.audio.input.rate = Abtastrate
@@ -1059,10 +1059,10 @@ settings.agent.idx = Index to use
1059
1059
  settings.agent.idx.auto_retrieve = Auto retrieve additional context from RAG
1060
1060
  settings.agent.idx.auto_retrieve.desc = Auto retrieve additional context from RAG at the beginning if the index is provided.
1061
1061
  settings.agent.idx.desc = Only if sub-mode is Chat with Files, choose the index to use in Autonomous and Experts modes
1062
- settings.agent.llama.eval_model = Model for evaluation
1063
- settings.agent.llama.eval_model.desc = Model used for evaluation with score/percentage (loop). If not selected, then current active model will be used.
1064
1062
  settings.agent.llama.append_eval = Append and compare previous evaluation prompt in next evaluation
1065
1063
  settings.agent.llama.append_eval.desc = If enabled, previous improvement prompt will be checked in next eval in loop
1064
+ settings.agent.llama.eval_model = Model for evaluation
1065
+ settings.agent.llama.eval_model.desc = Model used for evaluation with score/percentage (loop). If not selected, then current active model will be used.
1066
1066
  settings.agent.llama.iterations = Max run iterations
1067
1067
  settings.agent.llama.iterations.desc = Max run iterations before goal achieved in Always-continue mode
1068
1068
  settings.agent.llama.max_eval = Max evaluation steps in loop
@@ -1092,6 +1092,8 @@ settings.api_endpoint_hugging_face = Router API Endpoint
1092
1092
  settings.api_endpoint_hugging_face.desc = API Endpoint for HuggingFace Router provider (OpenAI compatible ChatCompletions)
1093
1093
  settings.api_endpoint_mistral = API Endpoint
1094
1094
  settings.api_endpoint_mistral.desc = Mistral AI API endpoint URL, default: https://api.mistral.ai/v1
1095
+ settings.api_endpoint_open_router = API Endpoint
1096
+ settings.api_endpoint_open_router.desc = OpenRouter API endpoint URL, default: https://openrouter.ai/api/v1
1095
1097
  settings.api_endpoint_perplexity = API Endpoint
1096
1098
  settings.api_endpoint_perplexity.desc = Perplexity API endpoint URL, default: https://api.perplexity.ai
1097
1099
  settings.api_endpoint_xai = API Endpoint
@@ -1108,6 +1110,8 @@ settings.api_key.hugging_face = HuggingFace API KEY
1108
1110
  settings.api_key.hugging_face.desc = Required for the HuggingFace API.
1109
1111
  settings.api_key.mistral = Mistral AI API KEY
1110
1112
  settings.api_key.mistral.desc = Required for the Mistral AI API.
1113
+ settings.api_key.open_router = OpenRouter API KEY
1114
+ settings.api_key.open_router.desc = Required for the OpenRouter API.
1111
1115
  settings.api_key.perplexity = Perplexity API KEY
1112
1116
  settings.api_key.perplexity.desc = Required for the Perplexity API.
1113
1117
  settings.api_key.voyage = VoyageAI API KEY
@@ -1130,6 +1134,8 @@ settings.audio.input.backend = Audio Input Backend
1130
1134
  settings.audio.input.backend.desc = Select the audio input backend.
1131
1135
  settings.audio.input.channels = Channels
1132
1136
  settings.audio.input.channels.desc = Input channels, default: 1
1137
+ settings.audio.input.continuous = Continuous Audio Recording (Chunks)
1138
+ settings.audio.input.continuous.desc = Enable recording in chunks for long audio recordings in notepad (voice notes).
1133
1139
  settings.audio.input.device = Audio Input Device
1134
1140
  settings.audio.input.device.desc = Select the audio device for Microphone input.
1135
1141
  settings.audio.input.rate = Sampling Rate
@@ -1345,7 +1351,9 @@ settings.section.api_keys.google = Google
1345
1351
  settings.section.api_keys.huggingface = HuggingFace
1346
1352
  settings.section.api_keys.mistral_ai = Mistral AI
1347
1353
  settings.section.api_keys.openai = OpenAI
1354
+ settings.section.api_keys.openrouter = OpenRouter
1348
1355
  settings.section.api_keys.perplexity = Perplexity
1356
+ settings.section.api_keys.voyage = VoyageAI
1349
1357
  settings.section.api_keys.xai = xAI
1350
1358
  settings.section.audio = Audio
1351
1359
  settings.section.audio.cache = Cache
@@ -1117,6 +1117,8 @@ settings.audio.input.backend = Backend para la entrada de audio
1117
1117
  settings.audio.input.backend.desc = Selecciona el backend para la entrada de audio.
1118
1118
  settings.audio.input.channels = Canaux
1119
1119
  settings.audio.input.channels.desc = Canaux d'entrée, par défaut : 1
1120
+ settings.audio.input.continuous = Grabación de Audio Continua (Fragmentos)
1121
+ settings.audio.input.continuous.desc = Habilitar grabación en fragmentos para grabaciones de audio largas en el bloc de notas (notas de voz).
1120
1122
  settings.audio.input.device = Dispositivo para la entrada de audio
1121
1123
  settings.audio.input.device.desc = Selecciona el dispositivo para la entrada del micrófono.
1122
1124
  settings.audio.input.rate = Taux d'échantillonnage
@@ -1116,6 +1116,8 @@ settings.audio.input.backend = Backend pour l'entrée audio
1116
1116
  settings.audio.input.backend.desc = Sélectionnez le backend pour l'entrée audio.
1117
1117
  settings.audio.input.channels = Canaux
1118
1118
  settings.audio.input.channels.desc = Canaux d'entrée, par défaut : 1
1119
+ settings.audio.input.continuous = Enregistrement Audio Continu (Morceaux)
1120
+ settings.audio.input.continuous.desc = Activer l'enregistrement en morceaux pour les longs enregistrements audio dans le bloc-notes (notes vocales).
1119
1121
  settings.audio.input.device = Périphérique pour l'entrée audio
1120
1122
  settings.audio.input.device.desc = Sélectionnez le périphérique pour l'entrée du microphone.
1121
1123
  settings.audio.input.rate = Taux d'échantillonnage
@@ -1116,6 +1116,8 @@ settings.audio.input.backend = Backend per l'ingresso audio
1116
1116
  settings.audio.input.backend.desc = Seleziona il backend per l'ingresso audio.
1117
1117
  settings.audio.input.channels = Canali
1118
1118
  settings.audio.input.channels.desc = Canali di ingresso, predefinito: 1
1119
+ settings.audio.input.continuous = Registrazione Audio Continua (Pezzi)
1120
+ settings.audio.input.continuous.desc = Abilita la registrazione a pezzi per lunghe registrazioni audio nei blocchi note (note vocali).
1119
1121
  settings.audio.input.device = Dispositivo per l'ingresso audio
1120
1122
  settings.audio.input.device.desc = Seleziona il dispositivo per l'ingresso del microfono.
1121
1123
  settings.audio.input.rate = Frequenza di campionamento
@@ -80,7 +80,7 @@ agent.eval.feedback = Feedback
80
80
  agent.eval.next = Ponowne uruchomienie z feedbackiem
81
81
  agent.eval.score = Ocena ewaluatora
82
82
  agent.eval.score.good = Odpowiedź wystarczająco dobra, wychodzenie.
83
- agent.evolve.generation = Generacja
83
+ agent.evolve.generation = Generacja
84
84
  agent.evolve.maxgen_limit = Osiągnięto maksymalną liczbę generacji, wychodzenie.
85
85
  agent.evolve.option.max_generations = Maksymalna liczba generacji
86
86
  agent.evolve.option.num_parents = Liczba rodziców
@@ -1117,6 +1117,8 @@ settings.audio.input.backend = Backend dla wejścia audio
1117
1117
  settings.audio.input.backend.desc = Wybierz backend dla wejścia audio.
1118
1118
  settings.audio.input.channels = Kanały
1119
1119
  settings.audio.input.channels.desc = Kanały wejściowe, domyślnie: 1
1120
+ settings.audio.input.continuous = Ciągłe Nagrywanie Dźwięku (Kawałki)
1121
+ settings.audio.input.continuous.desc = Włącz nagrywanie w kawałkach dla długich nagrań audio w notatniku (notatki głosowe).
1120
1122
  settings.audio.input.device = Urządzenie do wejścia audio
1121
1123
  settings.audio.input.device.desc = Wybierz urządzenie do wejścia mikrofonu.
1122
1124
  settings.audio.input.rate = Częstotliwość próbkowania
@@ -1116,6 +1116,8 @@ settings.audio.input.backend = Бекенд для аудіовходу
1116
1116
  settings.audio.input.backend.desc = Виберіть бекенд для аудіовходу.
1117
1117
  settings.audio.input.channels = Канали
1118
1118
  settings.audio.input.channels.desc = Вхідні канали, за замовчуванням: 1
1119
+ settings.audio.input.continuous = Безперервний Аудіозапис (Частини)
1120
+ settings.audio.input.continuous.desc = Увімкніть запис частинами для довгих аудіозаписів у блокноті (голосові нотатки).
1119
1121
  settings.audio.input.device = Пристрій для аудіовходу
1120
1122
  settings.audio.input.device.desc = Виберіть пристрій для входу мікрофону.
1121
1123
  settings.audio.input.rate = Частота дискретизації
@@ -1116,6 +1116,8 @@ settings.audio.input.backend = 音频输入的后端
1116
1116
  settings.audio.input.backend.desc = 选择音频输入的后端。
1117
1117
  settings.audio.input.channels = 声道
1118
1118
  settings.audio.input.channels.desc = 输入声道,默认: 1
1119
+ settings.audio.input.continuous = 连续音频录制(片段)
1120
+ settings.audio.input.continuous.desc = 启用记事本中的长音频录制分段记录(语音笔记)。
1119
1121
  settings.audio.input.device = 音频输入的设备
1120
1122
  settings.audio.input.device.desc = 选择用于麦克风输入的音频设备。
1121
1123
  settings.audio.input.rate = 采样率
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.08.07 03:00:00 #
9
+ # Updated Date: 2025.08.27 07:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
@@ -41,14 +41,11 @@ class Simple:
41
41
 
42
42
  def switch_btn_stop(self):
43
43
  """Switch button to stop"""
44
- self.plugin.window.ui.plugin_addon['audio.input.btn'].btn_toggle.setText(trans('audio.speak.btn.stop'))
45
- self.plugin.window.ui.plugin_addon['audio.input.btn'].btn_toggle.setToolTip(
46
- trans('audio.speak.btn.stop.tooltip'))
44
+ self.plugin.window.controller.audio.ui.on_input_begin("input")
47
45
 
48
46
  def switch_btn_start(self):
49
47
  """Switch button to start"""
50
- self.plugin.window.ui.plugin_addon['audio.input.btn'].btn_toggle.setText(trans('audio.speak.btn'))
51
- self.plugin.window.ui.plugin_addon['audio.input.btn'].btn_toggle.setToolTip(trans('audio.speak.btn.tooltip'))
48
+ self.plugin.window.controller.audio.ui.on_input_end("input")
52
49
 
53
50
  def stop_timeout(self):
54
51
  """Stop timeout"""
@@ -85,10 +82,8 @@ class Simple:
85
82
  # stop audio output if playing
86
83
  self.plugin.window.controller.audio.stop_output()
87
84
 
88
- # set audio volume bar
89
- self.plugin.window.core.audio.capture.set_bar(
90
- self.plugin.window.ui.plugin_addon['audio.input.btn'].bar
91
- )
85
+ # set audio input mode
86
+ self.plugin.window.core.audio.capture.set_mode("input")
92
87
 
93
88
  # start timeout timer to prevent infinite recording
94
89
  # disable in continuous mode
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.08.15 23:00:00 #
9
+ # Updated Date: 2025.08.27 07:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from typing import Any
@@ -250,7 +250,8 @@ class Plugin(BasePlugin):
250
250
  worker.signals.stop.connect(self.handle_stop)
251
251
  worker.signals.volume_changed.connect(self.handle_volume)
252
252
 
253
- self.window.controller.audio.on_begin("")
253
+ if not self.window.controller.audio.ui.recording:
254
+ self.window.controller.audio.on_begin("")
254
255
 
255
256
  backend = self.window.core.config.get("audio.output.backend", "native")
256
257
  if backend == "native":
@@ -275,20 +276,6 @@ class Plugin(BasePlugin):
275
276
  """
276
277
  self.window.ui.plugin_addon['audio.output'].set_status(status)
277
278
 
278
- def show_stop_button(self):
279
- """Show stop button"""
280
- self.window.ui.plugin_addon['audio.output'].stop.setVisible(True)
281
-
282
- def hide_stop_button(self):
283
- """Hide stop button"""
284
- self.window.ui.plugin_addon['audio.output'].stop.setVisible(False)
285
-
286
- def stop_speak(self):
287
- """Stop speaking"""
288
- self.window.ui.plugin_addon['audio.output'].stop.setVisible(False)
289
- self.window.ui.plugin_addon['audio.output'].set_status('Stopped')
290
- self.window.ui.plugin_addon['audio.output'].stop_audio()
291
-
292
279
  def stop_audio(self):
293
280
  """
294
281
  Event: AUDIO_OUTPUT_STOP
@@ -336,4 +323,4 @@ class Plugin(BasePlugin):
336
323
 
337
324
  :param volume: volume level
338
325
  """
339
- self.window.ui.plugin_addon['audio.output.bar'].setLevel(volume)
326
+ self.window.controller.audio.ui.on_output_volume_change(int(volume))
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.08.26 19:00:00 #
9
+ # Updated Date: 2025.08.26 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import copy
@@ -2335,6 +2335,15 @@ class Patch:
2335
2335
  })
2336
2336
  updated = True
2337
2337
 
2338
+ # < 2.6.26
2339
+ if old < parse_version("2.6.26"):
2340
+ print("Migrating config from < 2.6.26...")
2341
+ if "api_key_open_router" not in data:
2342
+ data["api_key_open_router"] = ""
2343
+ if "api_endpoint_open_router" not in data:
2344
+ data["api_endpoint_open_router"] = "https://openrouter.ai/api/v1"
2345
+ updated = True
2346
+
2338
2347
  # update file
2339
2348
  migrated = False
2340
2349
  if updated:
@@ -39,7 +39,7 @@ class LocalLLM(BaseLLM):
39
39
  :param config: config keyword arguments list
40
40
  :return: Embedding provider instance
41
41
  """
42
- from llama_index.embeddings.openai import OpenAIEmbedding
42
+ from llama_index.embeddings.openai_like import OpenAILikeEmbedding
43
43
  args = {}
44
44
  if config is not None:
45
45
  args = self.parse_args({
@@ -47,7 +47,7 @@ class LocalLLM(BaseLLM):
47
47
  }, window)
48
48
  if "model" in args and "model_name" not in args:
49
49
  args["model_name"] = args.pop("model")
50
- return OpenAIEmbedding(**args)
50
+ return OpenAILikeEmbedding(**args)
51
51
 
52
52
  def llama(
53
53
  self,
@@ -65,4 +65,10 @@ class LocalLLM(BaseLLM):
65
65
  """
66
66
  from llama_index.llms.openai_like import OpenAILike
67
67
  args = self.parse_args(model.llama_index, window)
68
+ if "model" not in args:
69
+ args["model"] = model.id
70
+ if "is_chat_model" not in args:
71
+ args["is_chat_model"] = True
72
+ if "is_function_calling_model" not in args:
73
+ args["is_function_calling_model"] = model.tool_calls
68
74
  return OpenAILike(**args)
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # ================================================== #
4
+ # This file is a part of PYGPT package #
5
+ # Website: https://pygpt.net #
6
+ # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
+ # MIT License #
8
+ # Created By : Marcin Szczygliński #
9
+ # Updated Date: 2025.08.26 23:00:00 #
10
+ # ================================================== #
11
+
12
+ from typing import Optional, Dict, List
13
+
14
+ from llama_index.core.base.embeddings.base import BaseEmbedding
15
+ from llama_index.core.llms.llm import BaseLLM as LlamaBaseLLM
16
+
17
+ from pygpt_net.core.types import (
18
+ MODE_LLAMA_INDEX,
19
+ )
20
+ from pygpt_net.provider.llms.base import BaseLLM
21
+ from pygpt_net.item.model import ModelItem
22
+
23
+
24
+ class OpenRouterLLM(BaseLLM):
25
+ def __init__(self, *args, **kwargs):
26
+ super(OpenRouterLLM, self).__init__(*args, **kwargs)
27
+ self.id = "open_router"
28
+ self.name = "OpenRouter"
29
+ self.type = [MODE_LLAMA_INDEX, "embeddings"]
30
+
31
+ def get_embeddings_model(
32
+ self,
33
+ window,
34
+ config: Optional[List[Dict]] = None
35
+ ) -> BaseEmbedding:
36
+ """
37
+ Return provider instance for embeddings
38
+
39
+ :param window: window instance
40
+ :param config: config keyword arguments list
41
+ :return: Embedding provider instance
42
+ """
43
+ from llama_index.embeddings.openai_like import OpenAILikeEmbedding
44
+ args = {}
45
+ if config is not None:
46
+ args = self.parse_args({
47
+ "args": config,
48
+ }, window)
49
+ if "api_key" not in args:
50
+ args["api_key"] = window.core.config.get("api_key_open_router", "")
51
+ if "api_base" not in args:
52
+ args["api_base"] = window.core.config.get("api_endpoint_open_router", "")
53
+ if "model" in args and "model_name" not in args:
54
+ args["model_name"] = args.pop("model")
55
+ return OpenAILikeEmbedding(**args)
56
+
57
+ def llama(
58
+ self,
59
+ window,
60
+ model: ModelItem,
61
+ stream: bool = False
62
+ ) -> LlamaBaseLLM:
63
+ """
64
+ Return LLM provider instance for llama
65
+
66
+ :param window: window instance
67
+ :param model: model instance
68
+ :param stream: stream mode
69
+ :return: LLM provider instance
70
+ """
71
+ from llama_index.llms.openai_like import OpenAILike
72
+ args = self.parse_args(model.llama_index, window)
73
+ if "model" not in args:
74
+ args["model"] = model.id
75
+ if "api_key" not in args:
76
+ args["api_key"] = window.core.config.get("api_key_open_router", "")
77
+ if "api_base" not in args:
78
+ args["api_base"] = window.core.config.get("api_endpoint_open_router", "")
79
+ if "is_chat_model" not in args:
80
+ args["is_chat_model"] = True
81
+ if "is_function_calling_model" not in args:
82
+ args["is_function_calling_model"] = model.tool_calls
83
+ return OpenAILike(**args)
84
+
85
+ def get_models(
86
+ self,
87
+ window,
88
+ ) -> List[Dict]:
89
+ """
90
+ Return list of models for the provider
91
+
92
+ :param window: window instance
93
+ :return: list of models
94
+ """
95
+ items = []
96
+ client = self.get_client(window)
97
+ models_list = client.models.list()
98
+ if models_list.data:
99
+ for item in models_list.data:
100
+ items.append({
101
+ "id": item.id,
102
+ "name": item.id,
103
+ })
104
+ return items
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.08.24 23:00:00 #
9
+ # Updated Date: 2025.08.27 07:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from functools import partial
@@ -149,6 +149,9 @@ class Input:
149
149
  self.window.ui.plugin_addon['audio.input'] = AudioInput(self.window)
150
150
  self.window.ui.plugin_addon['audio.input.btn'] = AudioInputButton(self.window)
151
151
 
152
+ self.window.ui.plugin_addon['audio.input'].setVisible(False)
153
+ self.window.ui.plugin_addon['audio.input.btn'].setVisible(False)
154
+
152
155
  grid = QGridLayout()
153
156
 
154
157
  center_layout = QHBoxLayout()
@@ -204,7 +207,7 @@ class Input:
204
207
 
205
208
  nodes['input.stop_btn'] = QPushButton(trans("input.btn.stop"))
206
209
  nodes['input.stop_btn'].setVisible(False)
207
- nodes['input.stop_btn'].clicked.connect(controller.kernel.stop)
210
+ nodes['input.stop_btn'].clicked.connect(controller.chat.common.handle_stop)
208
211
 
209
212
  nodes['input.update_btn'] = QPushButton(trans("input.btn.update"))
210
213
  nodes['input.update_btn'].setVisible(False)
pygpt_net/ui/main.py CHANGED
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.08.24 23:00:00 #
9
+ # Updated Date: 2025.08.27 07:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
@@ -254,7 +254,6 @@ class MainWindow(QMainWindow, QtStyleTools):
254
254
  """
255
255
  message = message if isinstance(message, str) else str(message)
256
256
  self.dispatch(KernelEvent(KernelEvent.STATUS, {"status": message}))
257
- del message # free memory
258
257
 
259
258
  @Slot(str)
260
259
  def update_state(self, state: str):
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.08.24 23:00:00 #
9
+ # Updated Date: 2025.08.27 07:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import Qt
@@ -25,6 +25,8 @@ class InputBar(QWidget):
25
25
 
26
26
  :param level: level
27
27
  """
28
+ if self._level == level:
29
+ return
28
30
  self._level = level
29
31
  self.update()
30
32
 
@@ -69,6 +71,8 @@ class OutputBar(QWidget):
69
71
 
70
72
  :param level: level
71
73
  """
74
+ if self._level == level:
75
+ return
72
76
  self._level = level
73
77
  self.update()
74
78