pygpt-net 2.4.30__py3-none-any.whl → 2.4.34__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. CHANGELOG.md +24 -0
  2. README.md +46 -5
  3. pygpt_net/CHANGELOG.txt +24 -0
  4. pygpt_net/__init__.py +3 -3
  5. pygpt_net/controller/access/__init__.py +5 -5
  6. pygpt_net/controller/access/control.py +3 -2
  7. pygpt_net/controller/attachment.py +67 -1
  8. pygpt_net/controller/audio/__init__.py +34 -6
  9. pygpt_net/controller/chat/__init__.py +3 -1
  10. pygpt_net/controller/chat/attachment.py +239 -37
  11. pygpt_net/controller/chat/audio.py +99 -0
  12. pygpt_net/controller/chat/input.py +10 -3
  13. pygpt_net/controller/chat/output.py +4 -1
  14. pygpt_net/controller/chat/text.py +7 -3
  15. pygpt_net/controller/dialogs/confirm.py +17 -1
  16. pygpt_net/controller/lang/custom.py +3 -1
  17. pygpt_net/controller/mode.py +2 -1
  18. pygpt_net/controller/presets/editor.py +11 -2
  19. pygpt_net/core/access/voice.py +2 -2
  20. pygpt_net/core/agents/legacy.py +3 -1
  21. pygpt_net/core/attachments/__init__.py +11 -7
  22. pygpt_net/core/attachments/context.py +226 -44
  23. pygpt_net/core/{audio.py → audio/__init__.py} +1 -1
  24. pygpt_net/core/audio/context.py +34 -0
  25. pygpt_net/core/bridge/context.py +29 -1
  26. pygpt_net/core/ctx/__init__.py +4 -1
  27. pygpt_net/core/db/__init__.py +4 -2
  28. pygpt_net/core/debug/attachments.py +3 -1
  29. pygpt_net/core/debug/context.py +5 -1
  30. pygpt_net/core/debug/presets.py +3 -1
  31. pygpt_net/core/events/event.py +2 -1
  32. pygpt_net/core/experts/__init__.py +3 -1
  33. pygpt_net/core/idx/chat.py +28 -6
  34. pygpt_net/core/idx/indexing.py +123 -15
  35. pygpt_net/core/modes.py +3 -1
  36. pygpt_net/core/presets.py +13 -2
  37. pygpt_net/core/render/markdown/pid.py +2 -1
  38. pygpt_net/core/render/plain/pid.py +2 -1
  39. pygpt_net/core/render/web/body.py +34 -12
  40. pygpt_net/core/render/web/pid.py +2 -1
  41. pygpt_net/core/render/web/renderer.py +8 -3
  42. pygpt_net/core/tokens.py +4 -2
  43. pygpt_net/core/types/mode.py +2 -1
  44. pygpt_net/data/config/config.json +5 -3
  45. pygpt_net/data/config/models.json +190 -5
  46. pygpt_net/data/config/modes.json +11 -5
  47. pygpt_net/data/config/presets/current.audio.json +34 -0
  48. pygpt_net/data/config/settings.json +15 -1
  49. pygpt_net/data/css/web.css +70 -0
  50. pygpt_net/data/css/web.dark.css +4 -1
  51. pygpt_net/data/css/web.light.css +1 -1
  52. pygpt_net/data/locale/locale.de.ini +26 -13
  53. pygpt_net/data/locale/locale.en.ini +61 -46
  54. pygpt_net/data/locale/locale.es.ini +26 -13
  55. pygpt_net/data/locale/locale.fr.ini +28 -15
  56. pygpt_net/data/locale/locale.it.ini +26 -13
  57. pygpt_net/data/locale/locale.pl.ini +30 -17
  58. pygpt_net/data/locale/locale.uk.ini +26 -13
  59. pygpt_net/data/locale/locale.zh.ini +33 -20
  60. pygpt_net/data/locale/plugin.cmd_files.de.ini +4 -4
  61. pygpt_net/data/locale/plugin.cmd_files.en.ini +4 -4
  62. pygpt_net/data/locale/plugin.cmd_files.es.ini +4 -4
  63. pygpt_net/data/locale/plugin.cmd_files.fr.ini +4 -4
  64. pygpt_net/data/locale/plugin.cmd_files.it.ini +4 -4
  65. pygpt_net/data/locale/plugin.cmd_files.pl.ini +4 -4
  66. pygpt_net/data/locale/plugin.cmd_files.uk.ini +4 -4
  67. pygpt_net/data/locale/plugin.cmd_files.zh.ini +4 -4
  68. pygpt_net/data/locale/plugin.cmd_web.de.ini +5 -5
  69. pygpt_net/data/locale/plugin.cmd_web.en.ini +5 -5
  70. pygpt_net/data/locale/plugin.cmd_web.es.ini +5 -5
  71. pygpt_net/data/locale/plugin.cmd_web.fr.ini +5 -5
  72. pygpt_net/data/locale/plugin.cmd_web.it.ini +5 -5
  73. pygpt_net/data/locale/plugin.cmd_web.pl.ini +5 -5
  74. pygpt_net/data/locale/plugin.cmd_web.uk.ini +5 -5
  75. pygpt_net/data/locale/plugin.cmd_web.zh.ini +5 -5
  76. pygpt_net/data/locale/plugin.idx_llama_index.de.ini +12 -12
  77. pygpt_net/data/locale/plugin.idx_llama_index.en.ini +12 -12
  78. pygpt_net/data/locale/plugin.idx_llama_index.es.ini +12 -12
  79. pygpt_net/data/locale/plugin.idx_llama_index.fr.ini +12 -12
  80. pygpt_net/data/locale/plugin.idx_llama_index.it.ini +12 -12
  81. pygpt_net/data/locale/plugin.idx_llama_index.pl.ini +12 -12
  82. pygpt_net/data/locale/plugin.idx_llama_index.uk.ini +12 -12
  83. pygpt_net/data/locale/plugin.idx_llama_index.zh.ini +12 -12
  84. pygpt_net/item/attachment.py +9 -1
  85. pygpt_net/item/ctx.py +9 -1
  86. pygpt_net/item/preset.py +5 -1
  87. pygpt_net/launcher.py +3 -1
  88. pygpt_net/migrations/Version20241126170000.py +28 -0
  89. pygpt_net/migrations/__init__.py +3 -1
  90. pygpt_net/plugin/audio_input/__init__.py +11 -1
  91. pygpt_net/plugin/audio_input/worker.py +9 -1
  92. pygpt_net/plugin/audio_output/__init__.py +37 -7
  93. pygpt_net/plugin/audio_output/worker.py +38 -41
  94. pygpt_net/plugin/cmd_code_interpreter/runner.py +2 -2
  95. pygpt_net/plugin/cmd_mouse_control/__init__.py +4 -2
  96. pygpt_net/plugin/openai_dalle/__init__.py +3 -1
  97. pygpt_net/plugin/openai_vision/__init__.py +3 -1
  98. pygpt_net/provider/core/attachment/json_file.py +4 -1
  99. pygpt_net/provider/core/config/patch.py +16 -0
  100. pygpt_net/provider/core/ctx/db_sqlite/storage.py +14 -4
  101. pygpt_net/provider/core/ctx/db_sqlite/utils.py +19 -2
  102. pygpt_net/provider/core/model/patch.py +7 -1
  103. pygpt_net/provider/core/preset/json_file.py +5 -1
  104. pygpt_net/provider/gpt/__init__.py +14 -2
  105. pygpt_net/provider/gpt/audio.py +63 -0
  106. pygpt_net/provider/gpt/chat.py +76 -44
  107. pygpt_net/provider/gpt/utils.py +27 -0
  108. pygpt_net/provider/gpt/vision.py +37 -15
  109. pygpt_net/provider/loaders/base.py +10 -1
  110. pygpt_net/provider/loaders/web_yt.py +19 -1
  111. pygpt_net/tools/image_viewer/ui/dialogs.py +3 -1
  112. pygpt_net/ui/dialog/preset.py +3 -1
  113. pygpt_net/ui/dialog/url.py +29 -0
  114. pygpt_net/ui/dialogs.py +5 -1
  115. pygpt_net/ui/layout/chat/attachments.py +42 -6
  116. pygpt_net/ui/layout/chat/attachments_ctx.py +14 -4
  117. pygpt_net/ui/layout/chat/attachments_uploaded.py +8 -4
  118. pygpt_net/ui/widget/dialog/url.py +59 -0
  119. pygpt_net/ui/widget/lists/attachment.py +22 -17
  120. pygpt_net/ui/widget/lists/attachment_ctx.py +65 -3
  121. pygpt_net/ui/widget/textarea/url.py +43 -0
  122. {pygpt_net-2.4.30.dist-info → pygpt_net-2.4.34.dist-info}/METADATA +48 -7
  123. {pygpt_net-2.4.30.dist-info → pygpt_net-2.4.34.dist-info}/RECORD +126 -117
  124. {pygpt_net-2.4.30.dist-info → pygpt_net-2.4.34.dist-info}/LICENSE +0 -0
  125. {pygpt_net-2.4.30.dist-info → pygpt_net-2.4.34.dist-info}/WHEEL +0 -0
  126. {pygpt_net-2.4.30.dist-info → pygpt_net-2.4.34.dist-info}/entry_points.txt +0 -0
pygpt_net/item/ctx.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: 2024.11.23 00:00:00 #
9
+ # Updated Date: 2024.11.26 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import copy
@@ -58,6 +58,7 @@ class CtxItem:
58
58
  self.current = False
59
59
  self.internal = False
60
60
  self.is_vision = False
61
+ self.is_audio = False
61
62
  self.idx = 0
62
63
  self.first = False
63
64
  self.live = False # True if is current flow (not loaded from DB)
@@ -72,6 +73,9 @@ class CtxItem:
72
73
  self.sub_reply = False # sub call reply
73
74
  self.hidden = False # hidden context
74
75
  self.pid = 0
76
+ self.audio_id = None
77
+ self.audio_output = None
78
+ self.audio_expires_ts = 0
75
79
 
76
80
 
77
81
  @property
@@ -193,6 +197,8 @@ class CtxItem:
193
197
  "thread": self.thread,
194
198
  "msg_id": self.msg_id,
195
199
  "run_id": self.run_id,
200
+ "audio_id": self.audio_id,
201
+ "audio_expires_ts": self.audio_expires_ts,
196
202
  "input_name": self.input_name,
197
203
  "output_name": self.output_name,
198
204
  "input_timestamp": self.input_timestamp,
@@ -246,6 +252,8 @@ class CtxItem:
246
252
  self.thread = data.get("thread", None)
247
253
  self.msg_id = data.get("msg_id", None)
248
254
  self.run_id = data.get("run_id", None)
255
+ self.audio_id = data.get("audio_id", None)
256
+ self.audio_expires_ts = data.get("audio_expires_ts", None)
249
257
  self.input_name = data.get("input_name", None)
250
258
  self.output_name = data.get("output_name", None)
251
259
  self.input_timestamp = data.get("input_timestamp", None)
pygpt_net/item/preset.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: 2024.11.15 00:00:00 #
9
+ # Updated Date: 2024.11.26 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import json
@@ -30,6 +30,7 @@ class PresetItem:
30
30
  self.agent = False
31
31
  self.agent_llama = False
32
32
  self.expert = False
33
+ self.audio = False
33
34
  self.temperature = 1.0
34
35
  self.filename = None
35
36
  self.model = None
@@ -63,6 +64,7 @@ class PresetItem:
63
64
  "agent": self.agent,
64
65
  "agent_llama": self.agent_llama,
65
66
  "expert": self.expert,
67
+ "audio": self.audio,
66
68
  "temperature": self.temperature,
67
69
  "filename": self.filename,
68
70
  "model": self.model,
@@ -105,6 +107,8 @@ class PresetItem:
105
107
  self.agent_llama = data["agent_llama"]
106
108
  if "expert" in data:
107
109
  self.expert = data["expert"]
110
+ if "audio" in data:
111
+ self.audio = data["audio"]
108
112
  if "temperature" in data:
109
113
  self.temperature = data["temperature"]
110
114
  if "filename" in data:
pygpt_net/launcher.py CHANGED
@@ -13,6 +13,7 @@ import sys
13
13
  import argparse
14
14
  from logging import ERROR, WARNING, INFO, DEBUG
15
15
 
16
+ from PySide6 import QtCore
16
17
  from PySide6.QtCore import QCoreApplication, Qt
17
18
  from PySide6.QtGui import QScreen
18
19
  from PySide6.QtWidgets import QApplication
@@ -100,6 +101,7 @@ class Launcher:
100
101
  Platforms.prepare() # setup platform specific options
101
102
  QCoreApplication.setAttribute(Qt.AA_ShareOpenGLContexts)
102
103
  self.app = QApplication(sys.argv)
104
+ self.app.setAttribute(QtCore.Qt.AA_DontUseNativeMenuBar)
103
105
  self.window = MainWindow(self.app, args=args)
104
106
  self.shortcut_filter = GlobalShortcutFilter(self.window)
105
107
 
@@ -225,7 +227,7 @@ class Launcher:
225
227
 
226
228
  def add_agent(self, agent: BaseAgent):
227
229
  """
228
- Register agent (Llama-index agent)
230
+ Register agent (LlamaIndex agent)
229
231
 
230
232
  :param agent: Agent instance
231
233
  """
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # ================================================== #
4
+ # This file is a part of PYGPT package #
5
+ # Website: https://pygpt.net #
6
+ # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
+ # MIT License #
8
+ # Created By : Marcin Szczygliński #
9
+ # Updated Date: 2024.11.26 19:00:00 #
10
+ # ================================================== #
11
+
12
+ from sqlalchemy import text
13
+
14
+ from .base import BaseMigration
15
+
16
+
17
+ class Version20241126170000(BaseMigration):
18
+ def __init__(self, window=None):
19
+ super(Version20241126170000, self).__init__(window)
20
+ self.window = window
21
+
22
+ def up(self, conn):
23
+ conn.execute(text("""
24
+ ALTER TABLE ctx_item ADD COLUMN audio_id TEXT;
25
+ """))
26
+ conn.execute(text("""
27
+ ALTER TABLE ctx_item ADD COLUMN audio_expires_ts INTEGER;
28
+ """))
@@ -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: 2024.11.23 00:00:00 #
9
+ # Updated Date: 2024.11.26 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from .Version20231227152900 import Version20231227152900 # 2.0.59
@@ -21,6 +21,7 @@ from .Version20240408180000 import Version20240408180000 # 2.1.41
21
21
  from .Version20240426050000 import Version20240426050000 # 2.1.79
22
22
  from .Version20240501030000 import Version20240501030000 # 2.2.7
23
23
  from .Version20241122130000 import Version20241122130000 # 2.4.21
24
+ from .Version20241126170000 import Version20241126170000 # 2.4.34
24
25
 
25
26
  class Migrations:
26
27
  def __init__(self):
@@ -46,4 +47,5 @@ class Migrations:
46
47
  Version20240426050000(), # 2.1.79
47
48
  Version20240501030000(), # 2.2.7
48
49
  Version20241122130000(), # 2.4.21
50
+ Version20241126170000(), # 2.4.34
49
51
  ]
@@ -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: 2024.11.21 20:00:00 #
9
+ # Updated Date: 2024.11.26 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
@@ -343,6 +343,7 @@ class Plugin(BasePlugin):
343
343
  worker.signals.destroyed.connect(self.handle_destroy)
344
344
  worker.signals.started.connect(self.handle_started)
345
345
  worker.signals.stopped.connect(self.handle_stop)
346
+ worker.signals.on_realtime.connect(self.handle_realtime)
346
347
 
347
348
  worker.run_async()
348
349
 
@@ -371,6 +372,15 @@ class Plugin(BasePlugin):
371
372
  """
372
373
  self.window.ui.plugin_addon['audio.input'].set_status(status)
373
374
 
375
+ @Slot(str)
376
+ def handle_realtime(self, path: str):
377
+ """
378
+ Handle realtime audio input
379
+
380
+ :param path: audio input file path
381
+ """
382
+ self.window.controller.chat.audio.handle_input(path)
383
+
374
384
  @Slot(object, object)
375
385
  def handle_input(self, text: str, ctx: CtxItem = None):
376
386
  """
@@ -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: 2024.11.18 21:00:00 #
9
+ # Updated Date: 2024.11.26 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os.path
@@ -22,6 +22,7 @@ from pygpt_net.plugin.base.worker import BaseWorker, BaseSignals
22
22
 
23
23
  class WorkerSignals(BaseSignals):
24
24
  transcribed = Signal(str, str)
25
+ on_realtime = Signal(str)
25
26
 
26
27
 
27
28
  class Worker(BaseWorker):
@@ -73,6 +74,13 @@ class Worker(BaseWorker):
73
74
  if os.path.exists(self.path):
74
75
  # set status
75
76
  self.status(trans('audio.speak.wait'))
77
+
78
+ # if multimodal audio, then only return path to audio file and do not transcribe
79
+ if self.plugin.window.controller.chat.audio.enabled():
80
+ self.signals.on_realtime.emit(self.path)
81
+ self.status('')
82
+ return
83
+
76
84
  # transcribe audio
77
85
  transcript = self.plugin.get_provider().transcribe(self.path)
78
86
  self.status('')
@@ -6,11 +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: 2024.11.20 03:00:00 #
9
+ # Updated Date: 2024.11.26 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import Slot
13
13
 
14
+ from pygpt_net.core.types import MODE_AUDIO
14
15
  from pygpt_net.plugin.base.plugin import BasePlugin
15
16
  from pygpt_net.provider.audio_output.base import BaseProvider
16
17
  from pygpt_net.core.events import Event
@@ -118,15 +119,21 @@ class Plugin(BasePlugin):
118
119
  name = event.name
119
120
  data = event.data
120
121
  ctx = event.ctx
122
+ mode = self.window.core.config.get("mode")
121
123
 
122
124
  if name == Event.INPUT_BEFORE:
123
125
  self.on_input_before(data['value'])
124
126
 
125
- elif name in [
126
- Event.CTX_AFTER,
127
- Event.AUDIO_READ_TEXT
128
- ]:
129
- self.on_ctx_after(ctx, event)
127
+ elif name == Event.CTX_AFTER:
128
+ if mode == MODE_AUDIO:
129
+ return # skip if audio mode
130
+ self.on_generate(ctx, event)
131
+
132
+ elif name == Event.AUDIO_READ_TEXT:
133
+ self.on_generate(ctx, event)
134
+
135
+ elif name == Event.AUDIO_PLAYBACK:
136
+ self.on_playback(ctx, event)
130
137
 
131
138
  elif name == Event.AUDIO_OUTPUT_STOP:
132
139
  self.stop_audio()
@@ -139,7 +146,7 @@ class Plugin(BasePlugin):
139
146
  """
140
147
  self.input_text = text
141
148
 
142
- def on_ctx_after(self, ctx: CtxItem, event: Event):
149
+ def on_generate(self, ctx: CtxItem, event: Event):
143
150
  """
144
151
  Events: CTX_AFTER, AUDIO_READ_TEXT
145
152
 
@@ -166,6 +173,7 @@ class Plugin(BasePlugin):
166
173
  worker.event = name
167
174
  worker.cache_file = cache_file
168
175
  worker.text = self.window.core.audio.clean_text(text)
176
+ worker.mode = "generate"
169
177
 
170
178
  # signals
171
179
  worker.signals.playback.connect(self.handle_playback)
@@ -180,6 +188,28 @@ class Plugin(BasePlugin):
180
188
  except Exception as e:
181
189
  self.error(e)
182
190
 
191
+ def on_playback(self, ctx: CtxItem, event: Event):
192
+ """
193
+ Events: AUDIO_PLAYBACK
194
+
195
+ :param ctx: CtxItem
196
+ :param event: Event
197
+ """
198
+ try:
199
+ worker = Worker()
200
+ worker.from_defaults(self)
201
+ worker.audio_file = event.data["audio_file"]
202
+ worker.mode = "playback"
203
+
204
+ # signals
205
+ worker.signals.playback.connect(self.handle_playback)
206
+ worker.signals.stop.connect(self.handle_stop)
207
+
208
+ worker.run_async()
209
+
210
+ except Exception as e:
211
+ self.error(e)
212
+
183
213
  def destroy(self):
184
214
  """Destroy thread"""
185
215
  pass
@@ -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: 2024.11.18 21:00:00 #
9
+ # Updated Date: 2024.11.26 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import time
@@ -30,28 +30,50 @@ class Worker(BaseWorker):
30
30
  self.text = None
31
31
  self.event = None
32
32
  self.cache_file = None # path to cache file
33
+ self.mode = "generate" # generate|playback
34
+ self.audio_file = None
33
35
 
34
36
  @Slot()
35
37
  def run(self):
36
- from pygame import mixer
37
38
  try:
38
- if self.text is None or self.text == "":
39
- time.sleep(0.2) # wait
40
- return
41
- path = self.plugin.get_provider().speech(self.text)
42
- if path:
43
- mixer.init()
44
- playback = mixer.Sound(path)
45
- self.stop_playback() # stop previous playback
46
- playback.play()
47
- self.send(playback) # send playback object to main thread
48
-
49
- # store in cache if enabled
50
- if self.cache_file:
51
- self.cache_audio_file(path, self.cache_file)
39
+ if self.mode == "generate":
40
+ self.generate()
41
+ elif self.mode == "playback":
42
+ self.play()
52
43
  except Exception as e:
53
44
  self.error(e)
54
45
 
46
+ def generate(self):
47
+ """
48
+ Generate and play audio file
49
+ """
50
+ if self.text is None or self.text == "":
51
+ time.sleep(0.2) # wait
52
+ return
53
+ path = self.plugin.get_provider().speech(self.text)
54
+ if path:
55
+ from pygame import mixer
56
+ mixer.init()
57
+ playback = mixer.Sound(path)
58
+ self.stop_playback() # stop previous playback
59
+ playback.play()
60
+ self.send(playback) # send playback object to main thread to allow force stop
61
+
62
+ # store in cache if enabled
63
+ if self.cache_file:
64
+ self.cache_audio_file(path, self.cache_file)
65
+
66
+ def play(self):
67
+ """
68
+ Play audio file only
69
+ """
70
+ if self.audio_file:
71
+ from pygame import mixer
72
+ mixer.init()
73
+ playback = mixer.Sound(self.audio_file)
74
+ playback.play()
75
+ self.send(playback) # send playback object to main thread to allow force stop
76
+
55
77
  def cache_audio_file(self, src: str, dst: str):
56
78
  """
57
79
  Store audio file in cache
@@ -81,28 +103,3 @@ class Worker(BaseWorker):
81
103
  def stop(self):
82
104
  """Send stop signal to main thread"""
83
105
  self.signals.stop.emit()
84
-
85
-
86
- class PlayWorker(BaseWorker):
87
- def __init__(self, *args, **kwargs):
88
- super(PlayWorker, self).__init__()
89
- self.signals = WorkerSignals()
90
- self.args = args
91
- self.kwargs = kwargs
92
- self.window = None
93
- self.path = None
94
-
95
- @Slot()
96
- def run(self):
97
- from pygame import mixer
98
- try:
99
- if self.path:
100
- mixer.init()
101
- playback = mixer.Sound(self.path)
102
- playback.play()
103
- except Exception as e:
104
- self.error(e)
105
-
106
-
107
-
108
-
@@ -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: 2024.11.25 02:00:00 #
9
+ # Updated Date: 2024.11.26 04:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os.path
@@ -140,7 +140,7 @@ class Runner:
140
140
 
141
141
  # append to ctx
142
142
  ctx.files = paths
143
- ctx.images = images_list
143
+ ctx.images = self.plugin.window.core.filesystem.make_local_list(list(images_list))
144
144
  return paths
145
145
 
146
146
  def handle_result_ipython(self, ctx: CtxItem, response) -> str:
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.11.24 04:00:00 #
9
+ # Updated Date: 2024.11.26 04:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import Slot, QTimer
@@ -141,7 +141,9 @@ class Plugin(BasePlugin):
141
141
  self.window.controller.attachment.clear_silent()
142
142
  path = self.window.controller.painter.capture.screenshot(attach_cursor=True,
143
143
  silent=True) # attach screenshot
144
- ctx.images.append(path)
144
+
145
+ img_path = self.window.core.filesystem.make_local(path)
146
+ ctx.images.append(img_path)
145
147
  #ctx.images_before.append(path)
146
148
 
147
149
  context = BridgeContext()
@@ -6,13 +6,14 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.11.21 20:00:00 #
9
+ # Updated Date: 2024.11.26 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from pygpt_net.core.types import (
13
13
  MODE_AGENT,
14
14
  MODE_AGENT_LLAMA,
15
15
  MODE_ASSISTANT,
16
+ MODE_AUDIO,
16
17
  MODE_CHAT,
17
18
  MODE_LANGCHAIN,
18
19
  MODE_LLAMA_INDEX,
@@ -44,6 +45,7 @@ class Plugin(BasePlugin):
44
45
  MODE_LLAMA_INDEX,
45
46
  MODE_ASSISTANT,
46
47
  MODE_AGENT,
48
+ MODE_AUDIO,
47
49
  ]
48
50
  self.allowed_cmds = [
49
51
  "image",
@@ -6,12 +6,13 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.11.24 04:00:00 #
9
+ # Updated Date: 2024.11.26 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from pygpt_net.core.types import (
13
13
  MODE_AGENT,
14
14
  MODE_AGENT_LLAMA,
15
+ MODE_AUDIO,
15
16
  MODE_LANGCHAIN,
16
17
  MODE_LLAMA_INDEX,
17
18
  MODE_VISION,
@@ -59,6 +60,7 @@ class Plugin(BasePlugin):
59
60
  MODE_AGENT_LLAMA,
60
61
  MODE_LLAMA_INDEX,
61
62
  MODE_LANGCHAIN,
63
+ MODE_AUDIO,
62
64
  ]
63
65
  self.worker = None
64
66
  self.config = Config(self)
@@ -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: 2023.12.31 04:00:00 #
9
+ # Updated Date: 2024.11.26 02:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import json
@@ -143,6 +143,7 @@ class JsonFileProvider(BaseProvider):
143
143
  'remote': attachment.remote,
144
144
  'send': attachment.send,
145
145
  'vector_store_ids': attachment.vector_store_ids,
146
+ 'type': attachment.type,
146
147
  }
147
148
 
148
149
  @staticmethod
@@ -165,6 +166,8 @@ class JsonFileProvider(BaseProvider):
165
166
  attachment.send = data['send']
166
167
  if 'vector_store_ids' in data:
167
168
  attachment.vector_store_ids = data['vector_store_ids']
169
+ if 'type' in data:
170
+ attachment.type = data['type']
168
171
 
169
172
  def dump(self, item: AttachmentItem) -> str:
170
173
  """
@@ -1701,6 +1701,22 @@ class Patch:
1701
1701
  del data['plugins']['cmd_code_interpreter']['ipython_dockerfile']
1702
1702
  updated = True
1703
1703
 
1704
+ # < 2.4.31
1705
+ if old < parse_version("2.4.31"):
1706
+ print("Migrating config from < 2.4.31...")
1707
+ if 'attachments_auto_index' not in data:
1708
+ data["attachments_auto_index"] = self.window.core.config.get_base(
1709
+ 'attachments_auto_index')
1710
+ updated = True
1711
+
1712
+ # < 2.4.34
1713
+ if old < parse_version("2.4.34"):
1714
+ print("Migrating config from < 2.4.34...")
1715
+ if 'ctx.attachment.query.model' not in data:
1716
+ data["ctx.attachment.query.model"] = self.window.core.config.get_base(
1717
+ 'ctx.attachment.query.model')
1718
+ updated = True
1719
+
1704
1720
  # update file
1705
1721
  migrated = False
1706
1722
  if updated:
@@ -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: 2024.11.23 00:00:00 #
9
+ # Updated Date: 2024.11.26 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from datetime import datetime
@@ -718,7 +718,9 @@ class Storage:
718
718
  output_tokens,
719
719
  total_tokens,
720
720
  is_internal,
721
- docs_json
721
+ docs_json,
722
+ audio_id,
723
+ audio_expires_ts
722
724
  )
723
725
  VALUES
724
726
  (
@@ -749,7 +751,9 @@ class Storage:
749
751
  :output_tokens,
750
752
  :total_tokens,
751
753
  :is_internal,
752
- :docs_json
754
+ :docs_json,
755
+ :audio_id,
756
+ :audio_expires_ts
753
757
  )
754
758
  """).bindparams(
755
759
  meta_id=int(meta.id),
@@ -780,6 +784,8 @@ class Storage:
780
784
  total_tokens=int(item.total_tokens or 0),
781
785
  is_internal=int(item.internal),
782
786
  docs_json=pack_item_value(item.doc_ids),
787
+ audio_id=item.audio_id,
788
+ audio_expires_ts=int(item.audio_expires_ts or 0)
783
789
  )
784
790
  with db.begin() as conn:
785
791
  result = conn.execute(stmt)
@@ -822,7 +828,9 @@ class Storage:
822
828
  output_tokens = :output_tokens,
823
829
  total_tokens = :total_tokens,
824
830
  is_internal = :is_internal,
825
- docs_json = :docs_json
831
+ docs_json = :docs_json,
832
+ audio_id = :audio_id,
833
+ audio_expires_ts = :audio_expires_ts
826
834
  WHERE id = :id
827
835
  """).bindparams(
828
836
  id=item.id,
@@ -852,6 +860,8 @@ class Storage:
852
860
  total_tokens=int(item.total_tokens or 0),
853
861
  is_internal=int(item.internal or 0),
854
862
  docs_json=pack_item_value(item.doc_ids),
863
+ audio_id=item.audio_id,
864
+ audio_expires_ts=int(item.audio_expires_ts or 0)
855
865
  )
856
866
  with db.begin() as conn:
857
867
  conn.execute(stmt)
@@ -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: 2024.11.23 00:00:00 #
9
+ # Updated Date: 2024.11.26 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import json
@@ -158,11 +158,28 @@ def unpack_item(item: CtxItem, row: dict) -> CtxItem:
158
158
  item.total_tokens = unpack_var(row['total_tokens'], 'int')
159
159
  item.internal = unpack_var(row['is_internal'], 'bool')
160
160
  item.doc_ids = unpack_item_value(row['docs_json'])
161
-
161
+ item.audio_id = row['audio_id']
162
+ item.audio_expires_ts = row['audio_expires_ts']
163
+
164
+ # set defaults
165
+ if item.cmds is None:
166
+ item.cmds = []
167
+ if item.results is None:
168
+ item.results = []
169
+ if item.urls is None:
170
+ item.urls = []
171
+ if item.images is None:
172
+ item.images = []
173
+ if item.files is None:
174
+ item.files = []
175
+ if item.attachments is None:
176
+ item.attachments = []
162
177
  if item.additional_ctx is None:
163
178
  item.additional_ctx = []
164
179
  if item.doc_ids is None:
165
180
  item.doc_ids = []
181
+ if item.extra is None:
182
+ item.extra = {}
166
183
  return item
167
184
 
168
185
 
@@ -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: 2024.11.15 00:00:00 #
9
+ # Updated Date: 2024.11.26 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from packaging.version import parse as parse_version, Version
@@ -308,6 +308,12 @@ class Patch:
308
308
  model.mode.append("agent_llama")
309
309
  updated = True
310
310
 
311
+ # < 2.4.34 <--- add gpt-4o-audio-preview, gpt-4o-2024-11-20
312
+ if old < parse_version("2.4.34"):
313
+ print("Migrating models from < 2.4.34...")
314
+ # add missing gpt-4o-audio-preview, gpt-4o-2024-11-20
315
+ updated = True
316
+
311
317
  # update file
312
318
  if updated:
313
319
  data = dict(sorted(data.items()))