pygpt-net 2.6.28__py3-none-any.whl → 2.6.30__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.
- pygpt_net/CHANGELOG.txt +13 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/{container.py → app_core.py} +5 -6
- pygpt_net/controller/access/control.py +1 -9
- pygpt_net/controller/assistant/assistant.py +4 -4
- pygpt_net/controller/assistant/batch.py +7 -7
- pygpt_net/controller/assistant/files.py +4 -4
- pygpt_net/controller/assistant/threads.py +3 -3
- pygpt_net/controller/attachment/attachment.py +4 -7
- pygpt_net/controller/chat/common.py +1 -1
- pygpt_net/controller/chat/stream.py +961 -294
- pygpt_net/controller/chat/vision.py +11 -19
- pygpt_net/controller/config/placeholder.py +1 -1
- pygpt_net/controller/ctx/ctx.py +1 -1
- pygpt_net/controller/ctx/summarizer.py +1 -1
- pygpt_net/controller/mode/mode.py +21 -12
- pygpt_net/controller/plugins/settings.py +3 -2
- pygpt_net/controller/presets/editor.py +112 -99
- pygpt_net/controller/theme/common.py +2 -0
- pygpt_net/controller/theme/theme.py +6 -2
- pygpt_net/controller/ui/vision.py +4 -4
- pygpt_net/core/agents/legacy.py +2 -2
- pygpt_net/core/agents/runners/openai_workflow.py +2 -2
- pygpt_net/core/assistants/files.py +5 -5
- pygpt_net/core/assistants/store.py +4 -4
- pygpt_net/core/bridge/bridge.py +3 -3
- pygpt_net/core/bridge/worker.py +28 -9
- pygpt_net/core/debug/console/console.py +2 -2
- pygpt_net/core/debug/presets.py +2 -2
- pygpt_net/core/experts/experts.py +2 -2
- pygpt_net/core/idx/llm.py +21 -3
- pygpt_net/core/modes/modes.py +2 -2
- pygpt_net/core/presets/presets.py +3 -3
- pygpt_net/core/tokens/tokens.py +4 -4
- pygpt_net/core/types/mode.py +5 -2
- pygpt_net/core/vision/analyzer.py +1 -1
- pygpt_net/data/config/config.json +6 -3
- pygpt_net/data/config/models.json +75 -3
- pygpt_net/data/config/modes.json +3 -9
- pygpt_net/data/config/settings.json +112 -55
- pygpt_net/data/config/settings_section.json +2 -2
- pygpt_net/data/locale/locale.de.ini +2 -2
- pygpt_net/data/locale/locale.en.ini +9 -2
- pygpt_net/data/locale/locale.es.ini +2 -2
- pygpt_net/data/locale/locale.fr.ini +2 -2
- pygpt_net/data/locale/locale.it.ini +2 -2
- pygpt_net/data/locale/locale.pl.ini +3 -3
- pygpt_net/data/locale/locale.uk.ini +2 -2
- pygpt_net/data/locale/locale.zh.ini +2 -2
- pygpt_net/item/model.py +23 -3
- pygpt_net/plugin/openai_dalle/plugin.py +4 -4
- pygpt_net/plugin/openai_vision/plugin.py +12 -13
- pygpt_net/provider/agents/openai/agent.py +5 -5
- pygpt_net/provider/agents/openai/agent_b2b.py +5 -5
- pygpt_net/provider/agents/openai/agent_planner.py +5 -6
- pygpt_net/provider/agents/openai/agent_with_experts.py +5 -5
- pygpt_net/provider/agents/openai/agent_with_experts_feedback.py +4 -4
- pygpt_net/provider/agents/openai/agent_with_feedback.py +4 -4
- pygpt_net/provider/agents/openai/bot_researcher.py +2 -2
- pygpt_net/provider/agents/openai/bots/research_bot/agents/planner_agent.py +1 -1
- pygpt_net/provider/agents/openai/bots/research_bot/agents/search_agent.py +1 -1
- pygpt_net/provider/agents/openai/bots/research_bot/agents/writer_agent.py +1 -1
- pygpt_net/provider/agents/openai/evolve.py +5 -5
- pygpt_net/provider/agents/openai/supervisor.py +4 -4
- pygpt_net/provider/api/__init__.py +27 -0
- pygpt_net/provider/api/anthropic/__init__.py +68 -0
- pygpt_net/provider/api/google/__init__.py +262 -0
- pygpt_net/provider/api/google/audio.py +114 -0
- pygpt_net/provider/api/google/chat.py +552 -0
- pygpt_net/provider/api/google/image.py +287 -0
- pygpt_net/provider/api/google/tools.py +222 -0
- pygpt_net/provider/api/google/vision.py +129 -0
- pygpt_net/provider/{gpt → api/openai}/__init__.py +2 -2
- pygpt_net/provider/{gpt → api/openai}/agents/computer.py +1 -1
- pygpt_net/provider/{gpt → api/openai}/agents/experts.py +1 -1
- pygpt_net/provider/{gpt → api/openai}/agents/response.py +1 -1
- pygpt_net/provider/{gpt → api/openai}/assistants.py +1 -1
- pygpt_net/provider/{gpt → api/openai}/chat.py +15 -8
- pygpt_net/provider/{gpt → api/openai}/completion.py +1 -1
- pygpt_net/provider/{gpt → api/openai}/image.py +1 -1
- pygpt_net/provider/{gpt → api/openai}/remote_tools.py +1 -1
- pygpt_net/provider/{gpt → api/openai}/responses.py +34 -20
- pygpt_net/provider/{gpt → api/openai}/store.py +2 -2
- pygpt_net/provider/{gpt → api/openai}/vision.py +1 -1
- pygpt_net/provider/{gpt → api/openai}/worker/assistants.py +4 -4
- pygpt_net/provider/{gpt → api/openai}/worker/importer.py +10 -10
- pygpt_net/provider/audio_input/openai_whisper.py +1 -1
- pygpt_net/provider/audio_output/google_tts.py +12 -0
- pygpt_net/provider/audio_output/openai_tts.py +1 -1
- pygpt_net/provider/core/config/patch.py +11 -0
- pygpt_net/provider/core/model/patch.py +9 -0
- pygpt_net/provider/core/preset/json_file.py +2 -4
- pygpt_net/provider/llms/anthropic.py +2 -5
- pygpt_net/provider/llms/base.py +4 -3
- pygpt_net/provider/llms/openai.py +1 -1
- pygpt_net/provider/loaders/hub/image_vision/base.py +1 -1
- pygpt_net/ui/dialog/preset.py +71 -55
- pygpt_net/ui/main.py +6 -4
- pygpt_net/utils.py +9 -0
- {pygpt_net-2.6.28.dist-info → pygpt_net-2.6.30.dist-info}/METADATA +42 -48
- {pygpt_net-2.6.28.dist-info → pygpt_net-2.6.30.dist-info}/RECORD +115 -107
- /pygpt_net/provider/{gpt → api/openai}/agents/__init__.py +0 -0
- /pygpt_net/provider/{gpt → api/openai}/agents/client.py +0 -0
- /pygpt_net/provider/{gpt → api/openai}/agents/remote_tools.py +0 -0
- /pygpt_net/provider/{gpt → api/openai}/agents/utils.py +0 -0
- /pygpt_net/provider/{gpt → api/openai}/audio.py +0 -0
- /pygpt_net/provider/{gpt → api/openai}/computer.py +0 -0
- /pygpt_net/provider/{gpt → api/openai}/container.py +0 -0
- /pygpt_net/provider/{gpt → api/openai}/summarizer.py +0 -0
- /pygpt_net/provider/{gpt → api/openai}/tools.py +0 -0
- /pygpt_net/provider/{gpt → api/openai}/utils.py +0 -0
- /pygpt_net/provider/{gpt → api/openai}/worker/__init__.py +0 -0
- {pygpt_net-2.6.28.dist-info → pygpt_net-2.6.30.dist-info}/LICENSE +0 -0
- {pygpt_net-2.6.28.dist-info → pygpt_net-2.6.30.dist-info}/WHEEL +0 -0
- {pygpt_net-2.6.28.dist-info → pygpt_net-2.6.30.dist-info}/entry_points.txt +0 -0
pygpt_net/ui/dialog/preset.py
CHANGED
|
@@ -6,12 +6,12 @@
|
|
|
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.
|
|
9
|
+
# Updated Date: 2025.08.28 09:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from PySide6.QtCore import Qt
|
|
13
13
|
from PySide6.QtWidgets import QPushButton, QHBoxLayout, QLabel, QVBoxLayout, QSplitter, QWidget, QSizePolicy, \
|
|
14
|
-
QTabWidget,
|
|
14
|
+
QTabWidget, QFileDialog
|
|
15
15
|
|
|
16
16
|
from pygpt_net.core.types import (
|
|
17
17
|
MODE_AGENT,
|
|
@@ -51,12 +51,8 @@ class Preset(BaseConfigDialog):
|
|
|
51
51
|
"""Setup preset editor dialog"""
|
|
52
52
|
self.window.ui.nodes['preset.btn.current'] = QPushButton(trans("dialog.preset.btn.current"))
|
|
53
53
|
self.window.ui.nodes['preset.btn.save'] = QPushButton(trans("dialog.preset.btn.save"))
|
|
54
|
-
self.window.ui.nodes['preset.btn.current'].clicked.connect(
|
|
55
|
-
|
|
56
|
-
)
|
|
57
|
-
self.window.ui.nodes['preset.btn.save'].clicked.connect(
|
|
58
|
-
lambda: self.window.controller.presets.editor.save()
|
|
59
|
-
)
|
|
54
|
+
self.window.ui.nodes['preset.btn.current'].clicked.connect(self.window.controller.presets.editor.from_current)
|
|
55
|
+
self.window.ui.nodes['preset.btn.save'].clicked.connect(self.window.controller.presets.editor.save)
|
|
60
56
|
|
|
61
57
|
self.window.ui.nodes['preset.btn.current'].setAutoDefault(False)
|
|
62
58
|
self.window.ui.nodes['preset.btn.save'].setAutoDefault(True)
|
|
@@ -119,14 +115,14 @@ class Preset(BaseConfigDialog):
|
|
|
119
115
|
mode_keys_middle = [
|
|
120
116
|
MODE_COMPLETION,
|
|
121
117
|
MODE_IMAGE,
|
|
122
|
-
MODE_VISION,
|
|
118
|
+
# MODE_VISION,
|
|
123
119
|
MODE_COMPUTER,
|
|
120
|
+
MODE_EXPERT,
|
|
124
121
|
]
|
|
125
122
|
mode_keys_right = [
|
|
126
123
|
MODE_AGENT_LLAMA,
|
|
127
124
|
MODE_AGENT_OPENAI,
|
|
128
125
|
MODE_AGENT,
|
|
129
|
-
MODE_EXPERT,
|
|
130
126
|
]
|
|
131
127
|
|
|
132
128
|
rows_mode_left = QVBoxLayout()
|
|
@@ -156,17 +152,20 @@ class Preset(BaseConfigDialog):
|
|
|
156
152
|
rows_mode.addStretch(1)
|
|
157
153
|
|
|
158
154
|
# modes
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
155
|
+
modes = QWidget()
|
|
156
|
+
modes.setLayout(rows_mode)
|
|
157
|
+
modes.setContentsMargins(0, 0, 0, 0)
|
|
158
|
+
self.window.ui.nodes['preset.editor.modes'] = modes
|
|
162
159
|
|
|
163
160
|
# experts
|
|
164
161
|
self.window.ui.nodes['preset.editor.experts'] = ExpertsEditor(self.window)
|
|
165
162
|
|
|
166
163
|
# desc and prompt
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
164
|
+
desc = QWidget()
|
|
165
|
+
desc.setLayout(options['description'])
|
|
166
|
+
desc.setContentsMargins(0, 5, 0, 5)
|
|
167
|
+
self.window.ui.nodes['preset.editor.description'] = desc
|
|
168
|
+
|
|
170
169
|
|
|
171
170
|
# prompt + extra options
|
|
172
171
|
prompt_layout = QVBoxLayout()
|
|
@@ -195,6 +194,7 @@ class Preset(BaseConfigDialog):
|
|
|
195
194
|
"agent_provider_openai",
|
|
196
195
|
"idx",
|
|
197
196
|
]
|
|
197
|
+
# personalize tab
|
|
198
198
|
personalize_keys = [
|
|
199
199
|
"ai_name",
|
|
200
200
|
"user_name",
|
|
@@ -202,15 +202,18 @@ class Preset(BaseConfigDialog):
|
|
|
202
202
|
"ai_personalize",
|
|
203
203
|
]
|
|
204
204
|
for key in left_keys:
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
205
|
+
node_key = f"preset.editor.{key}"
|
|
206
|
+
node = QWidget()
|
|
207
|
+
node.setLayout(options[key])
|
|
208
|
+
node.setContentsMargins(0, 0, 0, 0)
|
|
209
|
+
rows.addWidget(node)
|
|
210
|
+
self.window.ui.nodes[node_key] = node
|
|
209
211
|
|
|
210
212
|
# remote tools
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
213
|
+
remote_tools = QWidget()
|
|
214
|
+
remote_tools.setLayout(options['remote_tools'])
|
|
215
|
+
remote_tools.setContentsMargins(0, 0, 0, 0)
|
|
216
|
+
self.window.ui.nodes['preset.editor.remote_tools'] = remote_tools
|
|
214
217
|
|
|
215
218
|
rows_remote_tools = QVBoxLayout()
|
|
216
219
|
rows_remote_tools.addWidget(self.window.ui.nodes['preset.editor.remote_tools'])
|
|
@@ -222,10 +225,12 @@ class Preset(BaseConfigDialog):
|
|
|
222
225
|
# personalize
|
|
223
226
|
personalize_rows = QVBoxLayout()
|
|
224
227
|
for key in personalize_keys:
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
228
|
+
node_key = f"preset.editor.{key}"
|
|
229
|
+
node = QWidget()
|
|
230
|
+
node.setLayout(options[key])
|
|
231
|
+
node.setContentsMargins(0, 0, 0, 0)
|
|
232
|
+
personalize_rows.addWidget(node)
|
|
233
|
+
self.window.ui.nodes[node_key] = node
|
|
229
234
|
|
|
230
235
|
self.window.ui.nodes['preset.editor.ai_avatar'].setVisible(False)
|
|
231
236
|
|
|
@@ -255,11 +260,12 @@ class Preset(BaseConfigDialog):
|
|
|
255
260
|
widget_main = QWidget()
|
|
256
261
|
widget_main.setLayout(main)
|
|
257
262
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
+
splitter = QSplitter(Qt.Vertical)
|
|
264
|
+
splitter.addWidget(widget_main)
|
|
265
|
+
splitter.addWidget(widget_prompt)
|
|
266
|
+
splitter.setStretchFactor(0, 1)
|
|
267
|
+
splitter.setStretchFactor(1, 2)
|
|
268
|
+
self.window.ui.splitters['editor.presets'] = splitter
|
|
263
269
|
|
|
264
270
|
widget_personalize = QWidget()
|
|
265
271
|
widget_personalize.setLayout(personalize_rows)
|
|
@@ -270,24 +276,26 @@ class Preset(BaseConfigDialog):
|
|
|
270
276
|
widget_experts = QWidget()
|
|
271
277
|
widget_experts.setLayout(experts_rows)
|
|
272
278
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
279
|
+
tabs = QTabWidget()
|
|
280
|
+
tabs.addTab(splitter, trans("preset.tab.general"))
|
|
281
|
+
tabs.addTab(widget_personalize, trans("preset.tab.personalize"))
|
|
282
|
+
tabs.addTab(widget_experts, trans("preset.tab.experts"))
|
|
283
|
+
tabs.addTab(widget_remote_tools, trans("preset.tab.remote_tools"))
|
|
284
|
+
self.window.ui.tabs['preset.editor.tabs'] = tabs
|
|
278
285
|
|
|
279
286
|
layout = QVBoxLayout()
|
|
280
287
|
layout.addWidget(self.window.ui.tabs['preset.editor.tabs'])
|
|
281
288
|
layout.addLayout(footer)
|
|
282
289
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
290
|
+
dialog = EditorDialog(self.window, self.dialog_id)
|
|
291
|
+
dialog.setSizeGripEnabled(True)
|
|
292
|
+
dialog.setWindowFlags(
|
|
293
|
+
dialog.windowFlags() | Qt.WindowMaximizeButtonHint
|
|
287
294
|
)
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
295
|
+
dialog.setLayout(layout)
|
|
296
|
+
dialog.setWindowTitle(trans('dialog.preset'))
|
|
297
|
+
dialog.on_close_callback = self.on_close
|
|
298
|
+
self.window.ui.dialog['editor.' + self.dialog_id] = dialog
|
|
291
299
|
|
|
292
300
|
|
|
293
301
|
def prepare_extra_config(self, prompt_layout):
|
|
@@ -301,15 +309,17 @@ class Preset(BaseConfigDialog):
|
|
|
301
309
|
prompt_widget.setLayout(prompt_layout)
|
|
302
310
|
|
|
303
311
|
self.window.ui.nodes['preset.editor.extra'] = {}
|
|
304
|
-
|
|
305
|
-
|
|
312
|
+
|
|
313
|
+
tabs = QTabWidget()
|
|
314
|
+
tabs.addTab(
|
|
306
315
|
prompt_widget,
|
|
307
316
|
trans("preset.prompt"),
|
|
308
317
|
)
|
|
309
|
-
|
|
310
|
-
|
|
318
|
+
tabs.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
|
319
|
+
tabs.setMinimumHeight(150)
|
|
311
320
|
layout = QVBoxLayout()
|
|
312
|
-
layout.addWidget(
|
|
321
|
+
layout.addWidget(tabs)
|
|
322
|
+
self.window.ui.tabs['preset.editor.extra'] = tabs
|
|
313
323
|
return layout
|
|
314
324
|
|
|
315
325
|
|
|
@@ -368,6 +378,7 @@ class AvatarWidget(QWidget):
|
|
|
368
378
|
self.init_ui()
|
|
369
379
|
|
|
370
380
|
def init_ui(self):
|
|
381
|
+
"""Initialize the avatar widget UI."""
|
|
371
382
|
main_layout = QVBoxLayout(self)
|
|
372
383
|
main_layout.setContentsMargins(0, 0, 0, 0)
|
|
373
384
|
|
|
@@ -397,13 +408,19 @@ class AvatarWidget(QWidget):
|
|
|
397
408
|
main_layout.addStretch()
|
|
398
409
|
|
|
399
410
|
def open_file_dialog(self):
|
|
411
|
+
"""Open a file dialog to select an avatar image file."""
|
|
400
412
|
file_name, _ = QFileDialog.getOpenFileName(
|
|
401
413
|
self, trans("preset.personalize.avatar.choose.title"), "", "Images (*.png *.jpg *.jpeg *.bmp *.gif *.webp)"
|
|
402
414
|
)
|
|
403
415
|
if file_name:
|
|
404
416
|
self.window.controller.presets.editor.upload_avatar(file_name)
|
|
405
417
|
|
|
406
|
-
def load_avatar(self, file_path):
|
|
418
|
+
def load_avatar(self, file_path: str):
|
|
419
|
+
"""
|
|
420
|
+
Load and display the avatar image from the given file path.
|
|
421
|
+
|
|
422
|
+
:param file_path: Path to the avatar image file
|
|
423
|
+
"""
|
|
407
424
|
from PySide6.QtGui import QPixmap
|
|
408
425
|
pixmap = QPixmap(file_path)
|
|
409
426
|
if not pixmap.isNull():
|
|
@@ -420,9 +437,7 @@ class AvatarWidget(QWidget):
|
|
|
420
437
|
self.remove_button.setEnabled(enabled)
|
|
421
438
|
|
|
422
439
|
def disable_remove_button(self):
|
|
423
|
-
"""
|
|
424
|
-
Disable the remove button.
|
|
425
|
-
"""
|
|
440
|
+
"""Disable the remove button."""
|
|
426
441
|
self.enable_remove_button(False)
|
|
427
442
|
|
|
428
443
|
def get_cover_pixmap(self, pixmap, target_width, target_height):
|
|
@@ -432,6 +447,7 @@ class AvatarWidget(QWidget):
|
|
|
432
447
|
:param pixmap: Original pixmap
|
|
433
448
|
:param target_width: Target width for the avatar preview
|
|
434
449
|
:param target_height: Target height for the avatar preview
|
|
450
|
+
:return: Scaled and cropped pixmap
|
|
435
451
|
"""
|
|
436
452
|
factor = max(target_width / pixmap.width(), target_height / pixmap.height())
|
|
437
453
|
new_width = int(pixmap.width() * factor)
|
|
@@ -439,9 +455,9 @@ class AvatarWidget(QWidget):
|
|
|
439
455
|
scaled_pix = pixmap.scaled(new_width, new_height, Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
|
440
456
|
x = (scaled_pix.width() - target_width) // 2
|
|
441
457
|
y = (scaled_pix.height() - target_height) // 2
|
|
442
|
-
|
|
443
|
-
return cropped_pix
|
|
458
|
+
return scaled_pix.copy(x, y, target_width, target_height)
|
|
444
459
|
|
|
445
460
|
def remove_avatar(self):
|
|
461
|
+
"""Remove the current avatar image."""
|
|
446
462
|
self.avatar_preview.clear()
|
|
447
463
|
self.remove_button.setEnabled(False)
|
pygpt_net/ui/main.py
CHANGED
|
@@ -17,12 +17,13 @@ from PySide6.QtWidgets import QMainWindow, QApplication
|
|
|
17
17
|
from qt_material import QtStyleTools
|
|
18
18
|
|
|
19
19
|
from pygpt_net.core.events import BaseEvent, KernelEvent, ControlEvent
|
|
20
|
-
from pygpt_net.
|
|
20
|
+
from pygpt_net.app_core import Core
|
|
21
21
|
from pygpt_net.controller import Controller
|
|
22
22
|
from pygpt_net.tools import Tools
|
|
23
23
|
from pygpt_net.ui import UI
|
|
24
24
|
from pygpt_net.ui.widget.textarea.web import ChatWebOutput
|
|
25
|
-
from pygpt_net.utils import get_app_meta
|
|
25
|
+
from pygpt_net.utils import get_app_meta, freeze_updates
|
|
26
|
+
|
|
26
27
|
|
|
27
28
|
class MainWindow(QMainWindow, QtStyleTools):
|
|
28
29
|
|
|
@@ -63,7 +64,7 @@ class MainWindow(QMainWindow, QtStyleTools):
|
|
|
63
64
|
self.meta = get_app_meta()
|
|
64
65
|
|
|
65
66
|
# setup service container
|
|
66
|
-
self.core =
|
|
67
|
+
self.core = Core(self)
|
|
67
68
|
self.core.init()
|
|
68
69
|
self.core.patch() # patch version if needed
|
|
69
70
|
self.core.post_setup()
|
|
@@ -85,7 +86,8 @@ class MainWindow(QMainWindow, QtStyleTools):
|
|
|
85
86
|
|
|
86
87
|
# setup UI
|
|
87
88
|
self.ui = UI(self)
|
|
88
|
-
self
|
|
89
|
+
with freeze_updates(self):
|
|
90
|
+
self.ui.init()
|
|
89
91
|
|
|
90
92
|
# global shortcuts
|
|
91
93
|
self.shortcuts = []
|
pygpt_net/utils.py
CHANGED
|
@@ -13,6 +13,7 @@ import json
|
|
|
13
13
|
import os
|
|
14
14
|
import re
|
|
15
15
|
from datetime import datetime
|
|
16
|
+
from contextlib import contextmanager
|
|
16
17
|
|
|
17
18
|
from PySide6 import QtCore, QtGui
|
|
18
19
|
from PySide6.QtWidgets import QApplication
|
|
@@ -61,6 +62,14 @@ def trans(key: str, reload: bool = False, domain: str = None) -> str:
|
|
|
61
62
|
return locale.get(key, domain)
|
|
62
63
|
|
|
63
64
|
|
|
65
|
+
@contextmanager
|
|
66
|
+
def freeze_updates(widget):
|
|
67
|
+
widget.setUpdatesEnabled(False)
|
|
68
|
+
try:
|
|
69
|
+
yield
|
|
70
|
+
finally:
|
|
71
|
+
widget.setUpdatesEnabled(True)
|
|
72
|
+
|
|
64
73
|
def get_init_value(key: str = "__version__") -> str:
|
|
65
74
|
"""
|
|
66
75
|
Return config value from __init__.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: pygpt-net
|
|
3
|
-
Version: 2.6.
|
|
3
|
+
Version: 2.6.30
|
|
4
4
|
Summary: Desktop AI Assistant powered by: OpenAI GPT-5, GPT-4, o1, o3, Gemini, Claude, Grok, DeepSeek, and other models supported by Llama Index, and Ollama. Chatbot, agents, completion, image generation, vision analysis, speech-to-text, plugins, internet access, file handling, command execution and more.
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: ai,api,api key,app,assistant,bielik,chat,chatbot,chatgpt,claude,dall-e,deepseek,desktop,gemini,gpt,gpt-3.5,gpt-4,gpt-4-vision,gpt-4o,gpt-5,gpt-oss,gpt3.5,gpt4,grok,langchain,llama-index,llama3,mistral,o1,o3,ollama,openai,presets,py-gpt,py_gpt,pygpt,pyside,qt,text completion,tts,ui,vision,whisper
|
|
@@ -117,7 +117,7 @@ Description-Content-Type: text/markdown
|
|
|
117
117
|
|
|
118
118
|
[](https://snapcraft.io/pygpt)
|
|
119
119
|
|
|
120
|
-
Release: **2.6.
|
|
120
|
+
Release: **2.6.30** | build: **2025-08-29** | Python: **>=3.10, <3.14**
|
|
121
121
|
|
|
122
122
|
> Official website: https://pygpt.net | Documentation: https://pygpt.readthedocs.io
|
|
123
123
|
>
|
|
@@ -157,7 +157,7 @@ You can download compiled 64-bit versions for Windows and Linux here: https://py
|
|
|
157
157
|
|
|
158
158
|
- Desktop AI Assistant for `Linux`, `Windows` and `Mac`, written in Python.
|
|
159
159
|
- Works similarly to `ChatGPT`, but locally (on a desktop computer).
|
|
160
|
-
-
|
|
160
|
+
- 11 modes of operation: Chat, Chat with Files, Chat with Audio, Research (Perplexity), Completion, Image generation, Assistants, Experts, Computer use, Agents and Autonomous Mode.
|
|
161
161
|
- Supports multiple models like `OpenAI GPT-5`, `GPT-4`, `o1`, `o3`, `o4`, `Google Gemini`, `Anthropic Claude`, `xAI Grok`, `DeepSeek V3/R1`, `Perplexity / Sonar`, and any model accessible through `LlamaIndex` and `Ollama` such as `DeepSeek`, `gpt-oss`, `Llama 3`, `Mistral`, `Bielik`, etc.
|
|
162
162
|
- Chat with your own Files: integrated `LlamaIndex` support: chat with data such as: `txt`, `pdf`, `csv`, `html`, `md`, `docx`, `json`, `epub`, `xlsx`, `xml`, webpages, `Google`, `GitHub`, video/audio, images and other data types, or use conversation history as additional context provided to the model.
|
|
163
163
|
- Built-in vector databases support and automated files and data embedding.
|
|
@@ -181,7 +181,7 @@ You can download compiled 64-bit versions for Windows and Linux here: https://py
|
|
|
181
181
|
- Includes simple painter / drawing tool.
|
|
182
182
|
- Supports multiple languages.
|
|
183
183
|
- Requires no previous knowledge of using AI models.
|
|
184
|
-
- Simplifies image generation using `DALL-E`.
|
|
184
|
+
- Simplifies image generation using image models like `DALL-E` and `Imagen`.
|
|
185
185
|
- Fully configurable.
|
|
186
186
|
- Themes support.
|
|
187
187
|
- Real-time code syntax highlighting.
|
|
@@ -439,9 +439,9 @@ Alternatively, you can try removing snap and reinstalling it:
|
|
|
439
439
|
`sudo snap install pygpt`
|
|
440
440
|
|
|
441
441
|
|
|
442
|
-
**Access to microphone and audio in Windows version:**
|
|
442
|
+
**Access to a microphone and audio in Windows version:**
|
|
443
443
|
|
|
444
|
-
If you have a problems with audio or microphone in the non-binary PIP/Python version on Windows, check to see if FFmpeg is installed. If it's not, install it and add it to the PATH. You can find a tutorial on how to do this here: https://phoenixnap.com/kb/ffmpeg-windows. The binary version already includes FFmpeg.
|
|
444
|
+
If you have a problems with audio or a microphone in the non-binary PIP/Python version on Windows, check to see if FFmpeg is installed. If it's not, install it and add it to the PATH. You can find a tutorial on how to do this here: https://phoenixnap.com/kb/ffmpeg-windows. The binary version already includes FFmpeg.
|
|
445
445
|
|
|
446
446
|
**Windows and VC++ Redistributable**
|
|
447
447
|
|
|
@@ -519,9 +519,16 @@ Here, you can add or manage API keys for any supported provider.
|
|
|
519
519
|
|
|
520
520
|
**+ Inline Vision and Image generation**
|
|
521
521
|
|
|
522
|
-
|
|
522
|
+
In **PyGPT**, this mode mirrors `ChatGPT`, allowing you to chat with models like `GPT-5`, `GPT-4`, `o1`, `o3`, `Claude`, `Gemini`, `Grok`, `Perplexity (Sonar)`, `Deepseek`, and more. It works using the OpenAI API `Responses` and `ChatCompletions`, or the `Google GenAI SDK` if the Google native client is enabled. You can choose the API endpoint for `ChatCompletions` in `Config -> Settings -> API Keys`.
|
|
523
523
|
|
|
524
|
-
**Tip
|
|
524
|
+
**Tip:** This mode uses the provider SDK directly. If there's no native client built into the app, models like Gemini, Claude, Grok, Sonar, or Llama3 are supported in Chat mode via LlamaIndex or compatible OpenAI API endpoints. The app automatically switches to these endpoints when using non-OpenAI models.
|
|
525
|
+
|
|
526
|
+
Currently built-in native clients:
|
|
527
|
+
|
|
528
|
+
- OpenAI SDK
|
|
529
|
+
- Google GenAI SDK
|
|
530
|
+
|
|
531
|
+
Support for Anthropic and xAI native clients is coming soon.
|
|
525
532
|
|
|
526
533
|
The main part of the interface is a chat window where you see your conversations. Below it is a message box for typing. On the right side, you can set up or change the model and system prompt. You can also save these settings as presets to easily switch between models or tasks.
|
|
527
534
|
|
|
@@ -683,17 +690,16 @@ From version `2.0.107` the `davinci` models are deprecated and has been replaced
|
|
|
683
690
|
|
|
684
691
|
## Image generation
|
|
685
692
|
|
|
686
|
-
### DALL-E 3
|
|
693
|
+
### OpenAI DALL-E 3 / Google Imagen 3 and 4
|
|
687
694
|
|
|
688
|
-
**PyGPT** enables quick and easy image creation with `DALL-E 3
|
|
689
|
-
|
|
690
|
-
and displaying the image onscreen. You can send raw prompt to `DALL-E` in `Image generation` mode or ask the model for the best prompt.
|
|
695
|
+
**PyGPT** enables quick and easy image creation with image models like `DALL-E 3`, `gpt-image-1` or `Google Imagen`.
|
|
696
|
+
Generating images is akin to a chat conversation - a user's prompt triggers the generation, followed by downloading, saving to the computer, and displaying the image onscreen. You can send raw prompt to the model in `Image generation` mode or ask the model for the best prompt.
|
|
691
697
|
|
|
692
698
|

|
|
693
699
|
|
|
694
|
-
Image generation using
|
|
700
|
+
Image generation using image models is also available in every mode via plugin `Image Generation (inline)`. Just ask any model, in any mode, like e.g. GPT or Gemini to generate an image and it will do it inline, without need to mode change.
|
|
695
701
|
|
|
696
|
-
If you want to generate images
|
|
702
|
+
If you want to generate images directly in chat you must enable plugin **Image generation (inline)** in the Plugins menu.
|
|
697
703
|
Plugin allows you to generate images in Chat mode:
|
|
698
704
|
|
|
699
705
|

|
|
@@ -708,7 +714,7 @@ the bottom of the screen. This replaces the conversation temperature slider when
|
|
|
708
714
|
|
|
709
715
|
There is an option for switching prompt generation mode.
|
|
710
716
|
|
|
711
|
-
If **Raw Mode** is enabled,
|
|
717
|
+
If **Raw Mode** is enabled, a model will receive the prompt exactly as you have provided it.
|
|
712
718
|
If **Raw Mode** is disabled, a model will generate the best prompt for you based on your instructions.
|
|
713
719
|
|
|
714
720
|
### Image storage
|
|
@@ -724,31 +730,6 @@ prompts for creating new images.
|
|
|
724
730
|
|
|
725
731
|
Images are stored in ``img`` directory in **PyGPT** user data folder.
|
|
726
732
|
|
|
727
|
-
|
|
728
|
-
## Vision
|
|
729
|
-
|
|
730
|
-
This mode enables image analysis using the `GPT-5`, `GPT-4o` and other vision (multimodal) models. Functioning much like the chat mode,
|
|
731
|
-
it also allows you to upload images or provide URLs to images. The vision feature can analyze both local
|
|
732
|
-
images and those found online.
|
|
733
|
-
|
|
734
|
-
Vision is also integrated into any chat mode via plugin `Vision (inline)`. Just enable the plugin and use Vision in other work modes, such as Chat or Chat with Files.
|
|
735
|
-
|
|
736
|
-
Vision mode also includes real-time video capture from camera. To capture image from camera and append it to chat just click on video at left side. You can also enable `Auto capture` - image will be captured and appended to chat message every time you send message.
|
|
737
|
-
|
|
738
|
-
**1) Video camera real-time image capture**
|
|
739
|
-
|
|
740
|
-

|
|
741
|
-
|
|
742
|
-
**2) you can also provide an image URL**
|
|
743
|
-
|
|
744
|
-

|
|
745
|
-
|
|
746
|
-
**3) or you can just upload your local images or use the inline Vision in the standard chat mode:**
|
|
747
|
-
|
|
748
|
-

|
|
749
|
-
|
|
750
|
-
**Tip:** When using `Vision (inline)` by utilizing a plugin in standard mode, such as `Chat` (not `Vision` mode), the `+ Vision` label will appear at the bottom of the Chat window.
|
|
751
|
-
|
|
752
733
|
## Assistants
|
|
753
734
|
|
|
754
735
|
This mode uses the OpenAI's **Assistants API**.
|
|
@@ -2363,8 +2344,6 @@ Config -> Settings...
|
|
|
2363
2344
|
|
|
2364
2345
|
- `Directory for file downloads`: Subdirectory for downloaded files, e.g. in Assistants mode, inside "data". Default: "download"
|
|
2365
2346
|
|
|
2366
|
-
- `Verbose mode`: Enabled verbose mode when using attachment as additional context.
|
|
2367
|
-
|
|
2368
2347
|
- `Model for querying index`: Model to use for preparing query and querying the index when the RAG option is selected.
|
|
2369
2348
|
|
|
2370
2349
|
- `Model for attachment content summary`: Model to use when generating a summary for the content of a file when the Summary option is selected.
|
|
@@ -2569,8 +2548,6 @@ Enable/disable remote tools, like Web Search or Image generation to use in OpenA
|
|
|
2569
2548
|
|
|
2570
2549
|
**General**
|
|
2571
2550
|
|
|
2572
|
-
- `Verbose` - enables verbose mode.
|
|
2573
|
-
|
|
2574
2551
|
- `Auto retrieve additional context from RAG`: Auto retrieve additional context from RAG at the beginning if the index is provided.
|
|
2575
2552
|
|
|
2576
2553
|
- `Display a tray notification when the goal is achieved.`: If enabled, a notification will be displayed after goal achieved / finished run.
|
|
@@ -2641,10 +2618,12 @@ Enable/disable remote tools, like Web Search or Image generation to use in OpenA
|
|
|
2641
2618
|
|
|
2642
2619
|
- `Check for updates in background`: Enables checking for updates in background (checking every 5 minutes). Default: True.
|
|
2643
2620
|
|
|
2644
|
-
**
|
|
2621
|
+
**Debug**
|
|
2645
2622
|
|
|
2646
2623
|
- `Show debug menu`: Enables debug (developer) menu.
|
|
2647
2624
|
|
|
2625
|
+
- `Log level`: toggle log level (ERROR|WARNING|INFO|DEBUG)
|
|
2626
|
+
|
|
2648
2627
|
- `Log and debug context`: Enables logging of context input/output.
|
|
2649
2628
|
|
|
2650
2629
|
- `Log and debug events`: Enables logging of event dispatch.
|
|
@@ -2653,12 +2632,14 @@ Enable/disable remote tools, like Web Search or Image generation to use in OpenA
|
|
|
2653
2632
|
|
|
2654
2633
|
- `Log DALL-E usage to console`: Enables logging of DALL-E usage to console.
|
|
2655
2634
|
|
|
2635
|
+
- `Log attachments usage to console`: Enables logging of attachments usage to console.
|
|
2636
|
+
|
|
2637
|
+
- `Log Agents usage to console`: Enables logging of Agents usage to console.
|
|
2638
|
+
|
|
2656
2639
|
- `Log LlamaIndex usage to console`: Enables logging of LlamaIndex usage to console.
|
|
2657
2640
|
|
|
2658
2641
|
- `Log Assistants usage to console`: Enables logging of Assistants API usage to console.
|
|
2659
2642
|
|
|
2660
|
-
- `Log level`: toggle log level (ERROR|WARNING|INFO|DEBUG)
|
|
2661
|
-
|
|
2662
2643
|
|
|
2663
2644
|
## JSON files
|
|
2664
2645
|
|
|
@@ -3363,7 +3344,7 @@ These wrappers are loaded into the application during startup using `launcher.ad
|
|
|
3363
3344
|
```python
|
|
3364
3345
|
# app.py
|
|
3365
3346
|
|
|
3366
|
-
from pygpt_net.provider.
|
|
3347
|
+
from pygpt_net.provider.api.openai import OpenAILLM
|
|
3367
3348
|
from pygpt_net.provider.llms.azure_openai import AzureOpenAILLM
|
|
3368
3349
|
from pygpt_net.provider.llms.anthropic import AnthropicLLM
|
|
3369
3350
|
from pygpt_net.provider.llms.hugging_face import HuggingFaceLLM
|
|
@@ -3575,6 +3556,19 @@ may consume additional tokens that are not displayed in the main window.
|
|
|
3575
3556
|
|
|
3576
3557
|
## Recent changes:
|
|
3577
3558
|
|
|
3559
|
+
**2.6.30 (2025-08-29)**
|
|
3560
|
+
|
|
3561
|
+
- Added native Google GenAI API support (beta); live audio is not supported yet (#132).
|
|
3562
|
+
- Added new predefined models for image generation: Google Imagen3 and Imagen4.
|
|
3563
|
+
- Optimized token usage in the Responses API.
|
|
3564
|
+
- Removed Vision mode (it is now integrated into Chat).
|
|
3565
|
+
|
|
3566
|
+
**2.6.29 (2025-08-28)**
|
|
3567
|
+
|
|
3568
|
+
- Verbose options have been moved to the Developer section in settings.
|
|
3569
|
+
- Enhanced logging of embeddings usage.
|
|
3570
|
+
- Fixed styles list.
|
|
3571
|
+
|
|
3578
3572
|
**2.6.28 (2025-08-27)**
|
|
3579
3573
|
|
|
3580
3574
|
- Added new plugins: Tuya (IoT) and Wikipedia.
|