pygpt-net 2.6.29__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 +7 -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/theme.py +3 -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/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 +89 -31
- 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.29.dist-info → pygpt_net-2.6.30.dist-info}/METADATA +32 -44
- {pygpt_net-2.6.29.dist-info → pygpt_net-2.6.30.dist-info}/RECORD +113 -105
- /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.29.dist-info → pygpt_net-2.6.30.dist-info}/LICENSE +0 -0
- {pygpt_net-2.6.29.dist-info → pygpt_net-2.6.30.dist-info}/WHEEL +0 -0
- {pygpt_net-2.6.29.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**.
|
|
@@ -2637,10 +2618,12 @@ Enable/disable remote tools, like Web Search or Image generation to use in OpenA
|
|
|
2637
2618
|
|
|
2638
2619
|
- `Check for updates in background`: Enables checking for updates in background (checking every 5 minutes). Default: True.
|
|
2639
2620
|
|
|
2640
|
-
**
|
|
2621
|
+
**Debug**
|
|
2641
2622
|
|
|
2642
2623
|
- `Show debug menu`: Enables debug (developer) menu.
|
|
2643
2624
|
|
|
2625
|
+
- `Log level`: toggle log level (ERROR|WARNING|INFO|DEBUG)
|
|
2626
|
+
|
|
2644
2627
|
- `Log and debug context`: Enables logging of context input/output.
|
|
2645
2628
|
|
|
2646
2629
|
- `Log and debug events`: Enables logging of event dispatch.
|
|
@@ -2657,8 +2640,6 @@ Enable/disable remote tools, like Web Search or Image generation to use in OpenA
|
|
|
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,13 @@ 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
|
+
|
|
3578
3566
|
**2.6.29 (2025-08-28)**
|
|
3579
3567
|
|
|
3580
3568
|
- Verbose options have been moved to the Developer section in settings.
|