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
|
@@ -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.
|
|
9
|
+
# Updated Date: 2025.08.28 09:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import datetime
|
|
@@ -14,6 +14,7 @@ import os
|
|
|
14
14
|
import shutil
|
|
15
15
|
from typing import Any, Optional, Dict
|
|
16
16
|
|
|
17
|
+
from PySide6.QtCore import Slot
|
|
17
18
|
from PySide6.QtWidgets import QVBoxLayout, QWidget, QHBoxLayout
|
|
18
19
|
|
|
19
20
|
from pygpt_net.core.types import (
|
|
@@ -101,10 +102,10 @@ class Editor:
|
|
|
101
102
|
"type": "bool",
|
|
102
103
|
"label": "preset.completion",
|
|
103
104
|
},
|
|
104
|
-
MODE_VISION: {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
},
|
|
105
|
+
#MODE_VISION: {
|
|
106
|
+
# "type": "bool",
|
|
107
|
+
# "label": "preset.vision",
|
|
108
|
+
#},
|
|
108
109
|
#MODE_LANGCHAIN: {
|
|
109
110
|
# "type": "bool",
|
|
110
111
|
# "label": "preset.langchain",
|
|
@@ -262,32 +263,30 @@ class Editor:
|
|
|
262
263
|
if not self.tab_options_idx:
|
|
263
264
|
return
|
|
264
265
|
mode = self.window.core.config.get('mode')
|
|
266
|
+
tabs = self.window.ui.tabs['preset.editor.extra']
|
|
265
267
|
if mode not in [MODE_AGENT_OPENAI, MODE_AGENT_LLAMA]:
|
|
266
|
-
# show base prompt
|
|
267
|
-
self.
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
if self.window.ui.tabs['preset.editor.extra'].count() >= tab_idx:
|
|
272
|
-
self.window.ui.tabs['preset.editor.extra'].setTabVisible(tab_idx, False)
|
|
268
|
+
tabs.setTabVisible(0, True) # show base prompt
|
|
269
|
+
for opt_id in self.tab_options_idx: # hide all tabs
|
|
270
|
+
for tab_idx in self.tab_options_idx[opt_id]:
|
|
271
|
+
if tabs.count() >= tab_idx:
|
|
272
|
+
tabs.setTabVisible(tab_idx, False)
|
|
273
273
|
return
|
|
274
274
|
else:
|
|
275
|
-
# hide all tabs
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
self.window.ui.tabs['preset.editor.extra'].setTabVisible(tab_idx, False)
|
|
275
|
+
for opt_id in self.tab_options_idx: # hide all tabs
|
|
276
|
+
for tab_idx in self.tab_options_idx[opt_id]:
|
|
277
|
+
if tabs.count() >= tab_idx:
|
|
278
|
+
tabs.setTabVisible(tab_idx, False)
|
|
280
279
|
|
|
281
280
|
self.toggle_extra_options_by_provider()
|
|
282
281
|
|
|
283
282
|
def toggle_extra_options_by_provider(self):
|
|
284
283
|
"""Toggle extra options in preset editor by provider"""
|
|
285
284
|
if not self.tab_options_idx:
|
|
286
|
-
# show base prompt
|
|
287
|
-
self.window.ui.tabs['preset.editor.extra'].setTabVisible(0, True)
|
|
285
|
+
self.window.ui.tabs['preset.editor.extra'].setTabVisible(0, True) # show base prompt
|
|
288
286
|
return
|
|
289
287
|
|
|
290
288
|
mode = self.window.core.config.get('mode')
|
|
289
|
+
tabs = self.window.ui.tabs['preset.editor.extra']
|
|
291
290
|
key_agent = ""
|
|
292
291
|
|
|
293
292
|
if mode in [MODE_AGENT_OPENAI, MODE_AGENT_LLAMA]:
|
|
@@ -303,32 +302,29 @@ class Editor:
|
|
|
303
302
|
option=self.options[key_agent],
|
|
304
303
|
)
|
|
305
304
|
if current_provider is None or current_provider == "":
|
|
306
|
-
# show base prompt
|
|
307
|
-
self.window.ui.tabs['preset.editor.extra'].setTabVisible(0, True)
|
|
305
|
+
tabs.setTabVisible(0, True) # show base prompt
|
|
308
306
|
return
|
|
309
307
|
|
|
310
308
|
# show all tabs for current provider
|
|
311
|
-
for
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
if self.window.ui.tabs['preset.editor.extra'].count() >= tab_idx:
|
|
318
|
-
self.window.ui.tabs['preset.editor.extra'].setTabVisible(tab_idx, False)
|
|
309
|
+
for opt_id in self.tab_options_idx:
|
|
310
|
+
tabs.setTabVisible(0, False)
|
|
311
|
+
if opt_id != current_provider:
|
|
312
|
+
for tab_idx in self.tab_options_idx[opt_id]:
|
|
313
|
+
if tabs.count() >= tab_idx:
|
|
314
|
+
tabs.setTabVisible(tab_idx, False)
|
|
319
315
|
else:
|
|
320
|
-
for tab_idx in self.tab_options_idx[
|
|
321
|
-
if
|
|
322
|
-
|
|
316
|
+
for tab_idx in self.tab_options_idx[opt_id]:
|
|
317
|
+
if tabs.count() >= tab_idx:
|
|
318
|
+
tabs.setTabVisible(tab_idx, True)
|
|
323
319
|
|
|
324
320
|
# show base prompt if no custom options in current agent
|
|
325
321
|
agent = self.window.core.agents.provider.get(current_provider)
|
|
326
322
|
if not agent:
|
|
327
|
-
|
|
323
|
+
tabs.setTabVisible(0, True)
|
|
328
324
|
return
|
|
329
325
|
option_tabs = agent.get_options()
|
|
330
326
|
if not option_tabs or len(option_tabs) == 0:
|
|
331
|
-
|
|
327
|
+
tabs.setTabVisible(0, True)
|
|
332
328
|
|
|
333
329
|
def load_extra_options(self, preset: PresetItem):
|
|
334
330
|
"""
|
|
@@ -337,7 +333,6 @@ class Editor:
|
|
|
337
333
|
:param preset: preset item
|
|
338
334
|
"""
|
|
339
335
|
mode = self.window.core.config.get('mode')
|
|
340
|
-
id = None
|
|
341
336
|
if mode == MODE_AGENT_OPENAI:
|
|
342
337
|
if preset.agent_provider_openai is None or preset.agent_provider_openai == "":
|
|
343
338
|
return
|
|
@@ -356,6 +351,8 @@ class Editor:
|
|
|
356
351
|
if not preset.extra or id not in preset.extra:
|
|
357
352
|
return
|
|
358
353
|
|
|
354
|
+
apply_value = self.window.controller.config.apply_value
|
|
355
|
+
|
|
359
356
|
data_dict = preset.extra[id]
|
|
360
357
|
option_tabs = agent.get_options()
|
|
361
358
|
for option_tab_id in data_dict:
|
|
@@ -372,7 +369,7 @@ class Editor:
|
|
|
372
369
|
for key in extra_options:
|
|
373
370
|
value = data_dict[option_tab_id].get(key, None)
|
|
374
371
|
if value is not None:
|
|
375
|
-
|
|
372
|
+
apply_value(
|
|
376
373
|
parent_id=option_key,
|
|
377
374
|
key=key,
|
|
378
375
|
option=extra_options[key],
|
|
@@ -382,7 +379,7 @@ class Editor:
|
|
|
382
379
|
# from defaults
|
|
383
380
|
if "default" not in extra_options[key]:
|
|
384
381
|
continue
|
|
385
|
-
|
|
382
|
+
apply_value(
|
|
386
383
|
parent_id=option_key,
|
|
387
384
|
key=key,
|
|
388
385
|
option=extra_options[key],
|
|
@@ -397,6 +394,8 @@ class Editor:
|
|
|
397
394
|
if mode not in [MODE_AGENT_OPENAI, MODE_AGENT_LLAMA]:
|
|
398
395
|
return
|
|
399
396
|
|
|
397
|
+
apply_value = self.window.controller.config.apply_value
|
|
398
|
+
|
|
400
399
|
# load defaults for all tabs
|
|
401
400
|
for id in self.tab_options_idx:
|
|
402
401
|
agent = self.window.core.agents.provider.get(id)
|
|
@@ -411,7 +410,7 @@ class Editor:
|
|
|
411
410
|
for key in extra_options:
|
|
412
411
|
value = extra_options[key].get('default', None)
|
|
413
412
|
if value is not None:
|
|
414
|
-
|
|
413
|
+
apply_value(
|
|
415
414
|
parent_id=option_key,
|
|
416
415
|
key=key,
|
|
417
416
|
option=extra_options[key],
|
|
@@ -440,11 +439,13 @@ class Editor:
|
|
|
440
439
|
elif mode == MODE_AGENT_LLAMA:
|
|
441
440
|
current_provider_id = preset.agent_provider if preset else None
|
|
442
441
|
|
|
442
|
+
get_value = self.window.controller.config.get_value
|
|
443
|
+
apply_value = self.window.controller.config.apply_value
|
|
444
|
+
|
|
443
445
|
# load defaults for all tabs
|
|
444
446
|
for id in self.tab_options_idx:
|
|
445
|
-
# skip current provider
|
|
446
447
|
if current_provider_id and id == current_provider_id:
|
|
447
|
-
continue
|
|
448
|
+
continue # skip current provider
|
|
448
449
|
agent = self.window.core.agents.provider.get(id)
|
|
449
450
|
if not agent:
|
|
450
451
|
continue
|
|
@@ -456,9 +457,8 @@ class Editor:
|
|
|
456
457
|
extra_options = option_tabs[option_tab_id]['options']
|
|
457
458
|
for key in extra_options:
|
|
458
459
|
value = extra_options[key].get('default', None)
|
|
459
|
-
if value is not None:
|
|
460
|
-
|
|
461
|
-
current_value = self.window.controller.config.get_value(
|
|
460
|
+
if value is not None: # check current, apply only if current is empty
|
|
461
|
+
current_value = get_value(
|
|
462
462
|
parent_id=option_key,
|
|
463
463
|
key=key,
|
|
464
464
|
option=extra_options[key],
|
|
@@ -466,7 +466,7 @@ class Editor:
|
|
|
466
466
|
if current_value is not None and current_value != "":
|
|
467
467
|
continue
|
|
468
468
|
|
|
469
|
-
|
|
469
|
+
apply_value(
|
|
470
470
|
parent_id=option_key,
|
|
471
471
|
key=key,
|
|
472
472
|
option=extra_options[key],
|
|
@@ -491,6 +491,7 @@ class Editor:
|
|
|
491
491
|
else:
|
|
492
492
|
return
|
|
493
493
|
|
|
494
|
+
get_value = self.window.controller.config.get_value
|
|
494
495
|
options = {}
|
|
495
496
|
agent = self.window.core.agents.provider.get(id)
|
|
496
497
|
if not agent:
|
|
@@ -509,7 +510,7 @@ class Editor:
|
|
|
509
510
|
data_dict[option_tab_id] = {}
|
|
510
511
|
extra_options = option_tabs[option_tab_id]['options']
|
|
511
512
|
for key in extra_options:
|
|
512
|
-
data_dict[option_tab_id][key] =
|
|
513
|
+
data_dict[option_tab_id][key] = get_value(
|
|
513
514
|
parent_id=option_key,
|
|
514
515
|
key=key,
|
|
515
516
|
option=extra_options[key],
|
|
@@ -528,6 +529,8 @@ class Editor:
|
|
|
528
529
|
]
|
|
529
530
|
agents = self.window.core.agents.provider.all()
|
|
530
531
|
tabs = self.window.ui.tabs['preset.editor.extra']
|
|
532
|
+
build_option_widgets = self.window.ui.dialogs.preset.build_option_widgets
|
|
533
|
+
|
|
531
534
|
tab_idx = 1
|
|
532
535
|
for id in agents:
|
|
533
536
|
agent = agents[id]
|
|
@@ -543,20 +546,19 @@ class Editor:
|
|
|
543
546
|
option = option_tabs[option_tab_id]
|
|
544
547
|
title = option.get('label', '')
|
|
545
548
|
config_id = "agent." + id + "." + option_tab_id
|
|
546
|
-
widgets, options =
|
|
549
|
+
widgets, options = build_option_widgets(config_id, option['options'])
|
|
547
550
|
layout = QVBoxLayout()
|
|
548
551
|
layout.setContentsMargins(0, 10, 0, 10)
|
|
549
552
|
|
|
550
|
-
|
|
553
|
+
checkbox_layout = QHBoxLayout()
|
|
551
554
|
for key in options:
|
|
552
555
|
opt_layout = options[key]
|
|
553
556
|
if option['options'][key]['type'] == 'bool':
|
|
554
|
-
# checkbox
|
|
555
|
-
checkboxLayout.addLayout(opt_layout)
|
|
557
|
+
checkbox_layout.addLayout(opt_layout) # checkbox
|
|
556
558
|
else:
|
|
557
559
|
layout.addLayout(opt_layout)
|
|
558
560
|
layout.addStretch(1)
|
|
559
|
-
layout.addLayout(
|
|
561
|
+
layout.addLayout(checkbox_layout)
|
|
560
562
|
|
|
561
563
|
# as tab
|
|
562
564
|
tab_widget = QWidget()
|
|
@@ -575,7 +577,10 @@ class Editor:
|
|
|
575
577
|
def append_default_prompt(self):
|
|
576
578
|
"""Append default prompt to the preset editor"""
|
|
577
579
|
mode = self.window.core.config.get('mode')
|
|
578
|
-
if mode not in [
|
|
580
|
+
if mode not in [
|
|
581
|
+
MODE_AGENT_OPENAI,
|
|
582
|
+
MODE_AGENT_LLAMA
|
|
583
|
+
]:
|
|
579
584
|
return
|
|
580
585
|
|
|
581
586
|
parent_key = ""
|
|
@@ -698,8 +703,8 @@ class Editor:
|
|
|
698
703
|
data.completion = True
|
|
699
704
|
elif mode == MODE_IMAGE:
|
|
700
705
|
data.img = True
|
|
701
|
-
elif mode == MODE_VISION:
|
|
702
|
-
data.vision = True
|
|
706
|
+
# elif mode == MODE_VISION:
|
|
707
|
+
# data.vision = True
|
|
703
708
|
# elif mode == MODE_LANGCHAIN:
|
|
704
709
|
# data.langchain = True
|
|
705
710
|
# elif mode == MODE_ASSISTANT:
|
|
@@ -768,7 +773,7 @@ class Editor:
|
|
|
768
773
|
:param force: force overwrite file
|
|
769
774
|
:param close: close dialog
|
|
770
775
|
"""
|
|
771
|
-
|
|
776
|
+
preset_id = self.window.controller.config.get_value(
|
|
772
777
|
parent_id=self.id,
|
|
773
778
|
key="filename",
|
|
774
779
|
option=self.options["filename"],
|
|
@@ -778,7 +783,7 @@ class Editor:
|
|
|
778
783
|
MODE_CHAT,
|
|
779
784
|
MODE_COMPLETION,
|
|
780
785
|
MODE_IMAGE,
|
|
781
|
-
MODE_VISION,
|
|
786
|
+
# MODE_VISION,
|
|
782
787
|
# MODE_LANGCHAIN,
|
|
783
788
|
MODE_LLAMA_INDEX,
|
|
784
789
|
MODE_EXPERT,
|
|
@@ -790,11 +795,11 @@ class Editor:
|
|
|
790
795
|
]
|
|
791
796
|
|
|
792
797
|
# disallow editing default preset
|
|
793
|
-
if
|
|
798
|
+
if preset_id == "current." + mode:
|
|
794
799
|
self.window.ui.dialogs.alert("Reserved ID. Please use another ID.")
|
|
795
800
|
return
|
|
796
801
|
|
|
797
|
-
if
|
|
802
|
+
if preset_id is None or preset_id == "":
|
|
798
803
|
name = self.window.controller.config.get_value(
|
|
799
804
|
parent_id=self.id,
|
|
800
805
|
key="name",
|
|
@@ -806,33 +811,34 @@ class Editor:
|
|
|
806
811
|
return
|
|
807
812
|
|
|
808
813
|
# generate new filename
|
|
809
|
-
|
|
814
|
+
preset_id = self.window.controller.presets.make_filename(name)
|
|
810
815
|
path = os.path.join(
|
|
811
816
|
self.window.core.config.path,
|
|
812
817
|
"presets",
|
|
813
|
-
|
|
818
|
+
preset_id + ".json",
|
|
814
819
|
)
|
|
815
820
|
if os.path.exists(path) and not force:
|
|
816
|
-
|
|
821
|
+
preset_id += '_' + datetime.datetime.now().strftime('%Y%m%d%H%M%S')
|
|
817
822
|
|
|
818
823
|
# validate filename
|
|
819
|
-
|
|
824
|
+
preset_id = self.window.controller.presets.validate_filename(preset_id)
|
|
820
825
|
is_new = False
|
|
821
|
-
if
|
|
826
|
+
if preset_id not in self.window.core.presets.items:
|
|
822
827
|
is_new = True
|
|
823
|
-
self.window.core.presets.items[
|
|
828
|
+
self.window.core.presets.items[preset_id] = self.window.core.presets.build()
|
|
824
829
|
elif not force:
|
|
825
830
|
self.window.ui.dialogs.confirm(
|
|
826
831
|
type='preset_exists',
|
|
827
|
-
id=
|
|
832
|
+
id=preset_id,
|
|
828
833
|
msg=trans('confirm.preset.overwrite'),
|
|
829
834
|
)
|
|
830
835
|
return
|
|
831
836
|
|
|
832
837
|
# check if at least one mode is selected
|
|
833
838
|
is_mode = False
|
|
839
|
+
get_value = self.window.controller.config.get_value
|
|
834
840
|
for check in modes:
|
|
835
|
-
if
|
|
841
|
+
if get_value(
|
|
836
842
|
parent_id=self.id,
|
|
837
843
|
key=check,
|
|
838
844
|
option=self.options[check],
|
|
@@ -846,12 +852,12 @@ class Editor:
|
|
|
846
852
|
return
|
|
847
853
|
|
|
848
854
|
# assign data from fields to preset object in items
|
|
849
|
-
self.assign_data(
|
|
855
|
+
self.assign_data(preset_id)
|
|
850
856
|
|
|
851
857
|
if is_new:
|
|
852
858
|
# assign tmp avatar
|
|
853
859
|
if self.tmp_avatar is not None:
|
|
854
|
-
self.window.core.presets.items[
|
|
860
|
+
self.window.core.presets.items[preset_id].ai_avatar = self.tmp_avatar
|
|
855
861
|
self.tmp_avatar = None
|
|
856
862
|
else:
|
|
857
863
|
self.tmp_avatar = None
|
|
@@ -859,26 +865,26 @@ class Editor:
|
|
|
859
865
|
# if agent, assign experts and select only agent mode
|
|
860
866
|
curr_mode = self.window.core.config.get('mode')
|
|
861
867
|
if curr_mode == MODE_AGENT:
|
|
862
|
-
self.window.core.presets.items[
|
|
868
|
+
self.window.core.presets.items[preset_id].mode = [MODE_AGENT]
|
|
863
869
|
elif curr_mode == MODE_AGENT_LLAMA:
|
|
864
|
-
self.window.core.presets.items[
|
|
870
|
+
self.window.core.presets.items[preset_id].mode = [MODE_AGENT_LLAMA]
|
|
865
871
|
elif curr_mode == MODE_AGENT_OPENAI:
|
|
866
|
-
self.window.core.presets.items[
|
|
872
|
+
self.window.core.presets.items[preset_id].mode = [MODE_AGENT_OPENAI]
|
|
867
873
|
|
|
868
874
|
# apply changes to current active preset
|
|
869
875
|
current = self.window.core.config.get('preset')
|
|
870
|
-
if current is not None and current ==
|
|
871
|
-
self.to_current(self.window.core.presets.items[
|
|
876
|
+
if current is not None and current == preset_id:
|
|
877
|
+
self.to_current(self.window.core.presets.items[preset_id])
|
|
872
878
|
self.window.core.config.save()
|
|
873
879
|
|
|
874
880
|
# update current uuid
|
|
875
|
-
self.current = self.window.core.presets.items[
|
|
881
|
+
self.current = self.window.core.presets.items[preset_id].uuid
|
|
876
882
|
|
|
877
883
|
# save
|
|
878
884
|
no_scroll = False
|
|
879
885
|
if not is_new:
|
|
880
886
|
no_scroll = True
|
|
881
|
-
self.window.core.presets.save(
|
|
887
|
+
self.window.core.presets.save(preset_id)
|
|
882
888
|
self.window.controller.presets.refresh(no_scroll=no_scroll)
|
|
883
889
|
|
|
884
890
|
# close dialog
|
|
@@ -890,7 +896,7 @@ class Editor:
|
|
|
890
896
|
parent_id=self.id,
|
|
891
897
|
key="filename",
|
|
892
898
|
option=self.options["filename"],
|
|
893
|
-
value=
|
|
899
|
+
value=preset_id,
|
|
894
900
|
)
|
|
895
901
|
self.window.update_status(trans('status.preset.saved'))
|
|
896
902
|
|
|
@@ -898,7 +904,7 @@ class Editor:
|
|
|
898
904
|
self.window.core.presets.sort_by_name()
|
|
899
905
|
|
|
900
906
|
# switch to editing preset on save
|
|
901
|
-
self.window.controller.presets.set(mode,
|
|
907
|
+
self.window.controller.presets.set(mode, preset_id)
|
|
902
908
|
self.window.controller.presets.select_model()
|
|
903
909
|
|
|
904
910
|
# update presets list
|
|
@@ -914,12 +920,12 @@ class Editor:
|
|
|
914
920
|
|
|
915
921
|
:param id: preset id (filename)
|
|
916
922
|
"""
|
|
923
|
+
get_value = self.window.controller.config.get_value
|
|
917
924
|
data_dict = {}
|
|
918
925
|
for key in self.options:
|
|
919
|
-
# assigned separately
|
|
920
926
|
if key == "tool.function":
|
|
921
|
-
continue
|
|
922
|
-
data_dict[key] =
|
|
927
|
+
continue # assigned separately
|
|
928
|
+
data_dict[key] = get_value(
|
|
923
929
|
parent_id=self.id,
|
|
924
930
|
key=key,
|
|
925
931
|
option=self.options[key],
|
|
@@ -948,42 +954,46 @@ class Editor:
|
|
|
948
954
|
|
|
949
955
|
:param preset: preset item
|
|
950
956
|
"""
|
|
951
|
-
self.window.core.config
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
957
|
+
config = self.window.core.config
|
|
958
|
+
config.set('ai_name', preset.ai_name)
|
|
959
|
+
config.set('user_name', preset.user_name)
|
|
960
|
+
config.set('prompt', preset.prompt)
|
|
961
|
+
config.set('temperature', preset.temperature)
|
|
955
962
|
|
|
963
|
+
@Slot()
|
|
956
964
|
def from_current(self):
|
|
957
965
|
"""Copy data from current active preset"""
|
|
958
|
-
self.window.controller.config.apply_value
|
|
966
|
+
apply_value = self.window.controller.config.apply_value
|
|
967
|
+
get_config = self.window.core.config.get
|
|
968
|
+
apply_value(
|
|
959
969
|
parent_id=self.id,
|
|
960
970
|
key="ai_name",
|
|
961
971
|
option=self.options["ai_name"],
|
|
962
|
-
value=
|
|
972
|
+
value=get_config('ai_name'),
|
|
963
973
|
)
|
|
964
|
-
|
|
974
|
+
apply_value(
|
|
965
975
|
parent_id=self.id,
|
|
966
976
|
key="user_name",
|
|
967
977
|
option=self.options["user_name"],
|
|
968
|
-
value=
|
|
978
|
+
value=get_config('user_name'),
|
|
969
979
|
)
|
|
970
|
-
|
|
980
|
+
apply_value(
|
|
971
981
|
parent_id=self.id,
|
|
972
982
|
key="prompt",
|
|
973
983
|
option=self.options["prompt"],
|
|
974
|
-
value=
|
|
984
|
+
value=get_config('prompt'),
|
|
975
985
|
)
|
|
976
|
-
|
|
986
|
+
apply_value(
|
|
977
987
|
parent_id=self.id,
|
|
978
988
|
key="temperature",
|
|
979
989
|
option=self.options["temperature"],
|
|
980
|
-
value=
|
|
990
|
+
value=get_config('temperature'),
|
|
981
991
|
)
|
|
982
|
-
|
|
992
|
+
apply_value(
|
|
983
993
|
parent_id=self.id,
|
|
984
994
|
key="model",
|
|
985
995
|
option=self.options["model"],
|
|
986
|
-
value=
|
|
996
|
+
value=get_config('model'),
|
|
987
997
|
)
|
|
988
998
|
|
|
989
999
|
def update_from_global(self, key: str, value: Any):
|
|
@@ -1021,6 +1031,8 @@ class Editor:
|
|
|
1021
1031
|
store_name = preset_name + "_" + datetime.datetime.now().strftime('%Y%m%d%H%M%S') + file_ext
|
|
1022
1032
|
avatar_path = os.path.join(avatars_dir, store_name)
|
|
1023
1033
|
|
|
1034
|
+
avatar_widget = self.window.ui.nodes['preset.editor.avatar']
|
|
1035
|
+
|
|
1024
1036
|
# copy avatar to avatars directory
|
|
1025
1037
|
if os.path.exists(avatar_path):
|
|
1026
1038
|
os.remove(avatar_path)
|
|
@@ -1036,8 +1048,8 @@ class Editor:
|
|
|
1036
1048
|
option=self.options["ai_avatar"],
|
|
1037
1049
|
value=store_name,
|
|
1038
1050
|
)
|
|
1039
|
-
|
|
1040
|
-
|
|
1051
|
+
avatar_widget.load_avatar(avatar_path)
|
|
1052
|
+
avatar_widget.enable_remove_button(True)
|
|
1041
1053
|
return avatar_path
|
|
1042
1054
|
|
|
1043
1055
|
def update_avatar_config(self, preset: PresetItem):
|
|
@@ -1046,6 +1058,7 @@ class Editor:
|
|
|
1046
1058
|
|
|
1047
1059
|
:param preset: preset item
|
|
1048
1060
|
"""
|
|
1061
|
+
avatar_widget = self.window.ui.nodes['preset.editor.avatar']
|
|
1049
1062
|
avatar_path = preset.ai_avatar
|
|
1050
1063
|
if avatar_path:
|
|
1051
1064
|
file_path = os.path.join(
|
|
@@ -1054,13 +1067,13 @@ class Editor:
|
|
|
1054
1067
|
avatar_path,
|
|
1055
1068
|
)
|
|
1056
1069
|
if not os.path.exists(file_path):
|
|
1057
|
-
|
|
1070
|
+
avatar_widget.remove_avatar()
|
|
1058
1071
|
print("Avatar file does not exist:", file_path)
|
|
1059
1072
|
return
|
|
1060
|
-
|
|
1061
|
-
|
|
1073
|
+
avatar_widget.load_avatar(file_path)
|
|
1074
|
+
avatar_widget.enable_remove_button(True)
|
|
1062
1075
|
else:
|
|
1063
|
-
|
|
1076
|
+
avatar_widget.remove_avatar()
|
|
1064
1077
|
|
|
1065
1078
|
def remove_avatar(self, force: bool = False):
|
|
1066
1079
|
"""
|
|
@@ -196,6 +196,8 @@ class Common:
|
|
|
196
196
|
continue
|
|
197
197
|
for file in os.listdir(path):
|
|
198
198
|
if file.startswith("web-") and file.endswith('.css'):
|
|
199
|
+
if file.endswith("darkest.css"):
|
|
200
|
+
continue
|
|
199
201
|
to_replace = ['web-', '.css', '.light', '.dark']
|
|
200
202
|
for item in to_replace:
|
|
201
203
|
file = file.replace(item, '')
|
|
@@ -15,7 +15,7 @@ from typing import Any, Optional
|
|
|
15
15
|
from PySide6.QtWidgets import QApplication
|
|
16
16
|
|
|
17
17
|
from pygpt_net.core.events import RenderEvent
|
|
18
|
-
from pygpt_net.utils import trans
|
|
18
|
+
from pygpt_net.utils import trans, freeze_updates
|
|
19
19
|
|
|
20
20
|
from .common import Common
|
|
21
21
|
from .markdown import Markdown
|
|
@@ -55,7 +55,8 @@ class Theme:
|
|
|
55
55
|
return
|
|
56
56
|
self.window.update_status(trans("status.reloading"))
|
|
57
57
|
QApplication.processEvents()
|
|
58
|
-
self.
|
|
58
|
+
with freeze_updates(self.window):
|
|
59
|
+
self.toggle(name, force=True)
|
|
59
60
|
self.window.update_status("")
|
|
60
61
|
|
|
61
62
|
def toggle_option_by_menu(self, name: str, value: Any = None):
|
|
@@ -114,6 +115,9 @@ class Theme:
|
|
|
114
115
|
|
|
115
116
|
:param name: web style name
|
|
116
117
|
"""
|
|
118
|
+
styles_list = self.common.get_styles_list()
|
|
119
|
+
if name not in styles_list:
|
|
120
|
+
name = "chatgpt"
|
|
117
121
|
QApplication.processEvents()
|
|
118
122
|
core = self.window.core
|
|
119
123
|
core.config.set('theme.style', name)
|
|
@@ -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.
|
|
9
|
+
# Updated Date: 2025.08.28 09:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from pygpt_net.core.types import (
|
|
@@ -40,9 +40,9 @@ class Vision:
|
|
|
40
40
|
mode = self.window.core.config.get("mode")
|
|
41
41
|
if mode == MODE_IMAGE:
|
|
42
42
|
return False
|
|
43
|
-
if mode == MODE_VISION:
|
|
44
|
-
return True
|
|
45
|
-
if self.window.controller.
|
|
43
|
+
# if mode == MODE_VISION:
|
|
44
|
+
# return True
|
|
45
|
+
if self.window.controller.chat.vision.allowed():
|
|
46
46
|
return True
|
|
47
47
|
if self.is_vision_model() and mode in (
|
|
48
48
|
MODE_CHAT,
|
pygpt_net/core/agents/legacy.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.
|
|
9
|
+
# Updated Date: 2025.08.28 09:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from typing import List
|
|
@@ -32,7 +32,7 @@ class Legacy:
|
|
|
32
32
|
self.allowed_modes = [
|
|
33
33
|
MODE_CHAT,
|
|
34
34
|
MODE_COMPLETION,
|
|
35
|
-
MODE_VISION,
|
|
35
|
+
# MODE_VISION,
|
|
36
36
|
# MODE_LANGCHAIN,
|
|
37
37
|
MODE_LLAMA_INDEX,
|
|
38
38
|
MODE_AUDIO,
|
|
@@ -68,8 +68,8 @@ class OpenAIWorkflow(BaseRunner):
|
|
|
68
68
|
context = agent_kwargs.get("context", BridgeContext())
|
|
69
69
|
attachments = context.attachments if context else []
|
|
70
70
|
history, previous_response_id = self.window.core.agents.memory.prepare_openai(context)
|
|
71
|
-
msg = self.window.core.
|
|
72
|
-
self.window.core.
|
|
71
|
+
msg = self.window.core.api.openai.vision.build_agent_input(prompt, attachments) # build content with attachments
|
|
72
|
+
self.window.core.api.openai.vision.append_images(ctx) # append images to ctx if provided
|
|
73
73
|
history = history + msg
|
|
74
74
|
|
|
75
75
|
# ------------ callbacks ----------------
|
|
@@ -245,12 +245,12 @@ class Files:
|
|
|
245
245
|
if store_id is None or store_id == "":
|
|
246
246
|
continue # skip if no store_id
|
|
247
247
|
try:
|
|
248
|
-
self.window.core.
|
|
248
|
+
self.window.core.api.openai.store.delete_store_file(store_id, file_id) # remove from vector store
|
|
249
249
|
except Exception as e:
|
|
250
250
|
self.window.core.debug.log("Failed to delete file from vector store: " + str(e))
|
|
251
251
|
self.provider.delete_by_id(file.record_id) # delete file in DB
|
|
252
252
|
try:
|
|
253
|
-
self.window.core.
|
|
253
|
+
self.window.core.api.openai.store.delete_file(file.file_id) # delete file in API
|
|
254
254
|
except Exception as e:
|
|
255
255
|
self.window.core.debug.log("Failed to delete remote file: " + str(e))
|
|
256
256
|
if file.record_id in self.items:
|
|
@@ -290,9 +290,9 @@ class Files:
|
|
|
290
290
|
:return: True if truncated
|
|
291
291
|
"""
|
|
292
292
|
if store_id is not None:
|
|
293
|
-
self.window.core.
|
|
293
|
+
self.window.core.api.openai.store.remove_from_store(store_id) # remove files from vector store
|
|
294
294
|
else:
|
|
295
|
-
self.window.core.
|
|
295
|
+
self.window.core.api.openai.store.remove_from_stores() # remove files from all vector stores
|
|
296
296
|
return self.truncate_local(store_id) # truncate files in DB
|
|
297
297
|
|
|
298
298
|
def truncate_local(self, store_id: Optional[str] = None) -> bool:
|
|
@@ -316,7 +316,7 @@ class Files:
|
|
|
316
316
|
:param store_id: store ID
|
|
317
317
|
:return: True if imported
|
|
318
318
|
"""
|
|
319
|
-
files = self.window.core.
|
|
319
|
+
files = self.window.core.api.openai.store.import_store_files(store_id)
|
|
320
320
|
for file in files:
|
|
321
321
|
self.create(file.assistant, file.thread_id, file.file_id, file.name, file.path, file.size)
|
|
322
322
|
return True
|