pygpt-net 2.4.41__py3-none-any.whl → 2.4.43__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 (146) hide show
  1. CHANGELOG.md +13 -0
  2. README.md +142 -70
  3. pygpt_net/CHANGELOG.txt +13 -0
  4. pygpt_net/__init__.py +3 -3
  5. pygpt_net/app.py +3 -1
  6. pygpt_net/controller/audio/__init__.py +2 -2
  7. pygpt_net/controller/camera.py +1 -10
  8. pygpt_net/controller/chat/attachment.py +36 -23
  9. pygpt_net/controller/chat/audio.py +2 -2
  10. pygpt_net/controller/config/placeholder.py +15 -1
  11. pygpt_net/controller/ui/mode.py +16 -21
  12. pygpt_net/core/attachments/__init__.py +1 -1
  13. pygpt_net/core/attachments/context.py +10 -8
  14. pygpt_net/core/audio/__init__.py +4 -1
  15. pygpt_net/core/audio/whisper.py +37 -0
  16. pygpt_net/core/bridge/worker.py +2 -2
  17. pygpt_net/core/db/__init__.py +2 -1
  18. pygpt_net/core/debug/events.py +22 -10
  19. pygpt_net/core/debug/tabs.py +6 -3
  20. pygpt_net/core/history.py +3 -2
  21. pygpt_net/core/idx/__init__.py +16 -4
  22. pygpt_net/core/idx/chat.py +15 -5
  23. pygpt_net/core/idx/indexing.py +24 -8
  24. pygpt_net/core/installer.py +2 -4
  25. pygpt_net/core/models.py +62 -17
  26. pygpt_net/core/modes.py +11 -13
  27. pygpt_net/core/notepad.py +4 -4
  28. pygpt_net/core/plugins.py +27 -16
  29. pygpt_net/core/presets.py +20 -9
  30. pygpt_net/core/profile.py +11 -3
  31. pygpt_net/core/render/web/parser.py +3 -1
  32. pygpt_net/core/settings.py +5 -5
  33. pygpt_net/core/tabs/tab.py +10 -2
  34. pygpt_net/core/tokens.py +8 -6
  35. pygpt_net/core/web/__init__.py +105 -0
  36. pygpt_net/core/{web.py → web/helpers.py} +93 -67
  37. pygpt_net/data/config/config.json +3 -3
  38. pygpt_net/data/config/models.json +3 -3
  39. pygpt_net/data/config/modes.json +3 -3
  40. pygpt_net/data/locale/locale.en.ini +1 -0
  41. pygpt_net/data/locale/plugin.cmd_web.en.ini +2 -0
  42. pygpt_net/data/locale/plugin.mailer.en.ini +21 -0
  43. pygpt_net/item/ctx.py +66 -3
  44. pygpt_net/migrations/Version20241215110000.py +25 -0
  45. pygpt_net/migrations/__init__.py +3 -1
  46. pygpt_net/plugin/agent/__init__.py +7 -2
  47. pygpt_net/plugin/audio_output/__init__.py +6 -1
  48. pygpt_net/plugin/base/plugin.py +58 -26
  49. pygpt_net/plugin/base/worker.py +20 -17
  50. pygpt_net/plugin/cmd_history/config.py +2 -2
  51. pygpt_net/plugin/cmd_web/__init__.py +3 -4
  52. pygpt_net/plugin/cmd_web/config.py +71 -3
  53. pygpt_net/plugin/cmd_web/websearch.py +20 -12
  54. pygpt_net/plugin/cmd_web/worker.py +67 -4
  55. pygpt_net/plugin/idx_llama_index/config.py +3 -3
  56. pygpt_net/plugin/mailer/__init__.py +123 -0
  57. pygpt_net/plugin/mailer/config.py +149 -0
  58. pygpt_net/plugin/mailer/runner.py +285 -0
  59. pygpt_net/plugin/mailer/worker.py +123 -0
  60. pygpt_net/provider/agents/base.py +5 -2
  61. pygpt_net/provider/agents/openai.py +4 -2
  62. pygpt_net/provider/agents/openai_assistant.py +4 -2
  63. pygpt_net/provider/agents/planner.py +4 -2
  64. pygpt_net/provider/agents/react.py +4 -2
  65. pygpt_net/provider/audio_output/openai_tts.py +5 -11
  66. pygpt_net/provider/core/assistant/base.py +5 -3
  67. pygpt_net/provider/core/assistant/json_file.py +8 -5
  68. pygpt_net/provider/core/assistant_file/base.py +4 -3
  69. pygpt_net/provider/core/assistant_file/db_sqlite/__init__.py +4 -3
  70. pygpt_net/provider/core/assistant_file/db_sqlite/storage.py +3 -2
  71. pygpt_net/provider/core/assistant_store/base.py +6 -4
  72. pygpt_net/provider/core/assistant_store/db_sqlite/__init__.py +5 -4
  73. pygpt_net/provider/core/assistant_store/db_sqlite/storage.py +5 -3
  74. pygpt_net/provider/core/attachment/base.py +5 -3
  75. pygpt_net/provider/core/attachment/json_file.py +4 -3
  76. pygpt_net/provider/core/calendar/base.py +5 -3
  77. pygpt_net/provider/core/calendar/db_sqlite/__init__.py +6 -5
  78. pygpt_net/provider/core/calendar/db_sqlite/storage.py +5 -4
  79. pygpt_net/provider/core/config/base.py +8 -6
  80. pygpt_net/provider/core/config/json_file.py +9 -7
  81. pygpt_net/provider/core/ctx/base.py +27 -25
  82. pygpt_net/provider/core/ctx/db_sqlite/__init__.py +51 -35
  83. pygpt_net/provider/core/ctx/db_sqlite/storage.py +92 -38
  84. pygpt_net/provider/core/ctx/db_sqlite/utils.py +37 -11
  85. pygpt_net/provider/core/index/base.py +129 -23
  86. pygpt_net/provider/core/index/db_sqlite/__init__.py +130 -23
  87. pygpt_net/provider/core/index/db_sqlite/storage.py +130 -23
  88. pygpt_net/provider/core/index/db_sqlite/utils.py +4 -2
  89. pygpt_net/provider/core/mode/base.py +5 -3
  90. pygpt_net/provider/core/mode/json_file.py +7 -6
  91. pygpt_net/provider/core/model/base.py +6 -4
  92. pygpt_net/provider/core/model/json_file.py +9 -7
  93. pygpt_net/provider/core/notepad/base.py +5 -3
  94. pygpt_net/provider/core/notepad/db_sqlite/__init__.py +5 -4
  95. pygpt_net/provider/core/notepad/db_sqlite/storage.py +4 -3
  96. pygpt_net/provider/core/plugin_preset/base.py +4 -2
  97. pygpt_net/provider/core/plugin_preset/json_file.py +5 -3
  98. pygpt_net/provider/core/preset/base.py +6 -4
  99. pygpt_net/provider/core/preset/json_file.py +9 -9
  100. pygpt_net/provider/core/prompt/base.py +6 -3
  101. pygpt_net/provider/core/prompt/json_file.py +11 -6
  102. pygpt_net/provider/gpt/assistants.py +15 -6
  103. pygpt_net/provider/gpt/audio.py +5 -5
  104. pygpt_net/provider/gpt/chat.py +7 -5
  105. pygpt_net/provider/gpt/completion.py +8 -4
  106. pygpt_net/provider/gpt/image.py +3 -3
  107. pygpt_net/provider/gpt/store.py +46 -12
  108. pygpt_net/provider/gpt/vision.py +16 -11
  109. pygpt_net/provider/llms/anthropic.py +7 -2
  110. pygpt_net/provider/llms/azure_openai.py +26 -5
  111. pygpt_net/provider/llms/base.py +47 -9
  112. pygpt_net/provider/llms/google.py +7 -2
  113. pygpt_net/provider/llms/hugging_face.py +13 -3
  114. pygpt_net/provider/llms/hugging_face_api.py +18 -4
  115. pygpt_net/provider/llms/local.py +7 -2
  116. pygpt_net/provider/llms/ollama.py +30 -6
  117. pygpt_net/provider/llms/openai.py +32 -6
  118. pygpt_net/provider/vector_stores/__init__.py +45 -14
  119. pygpt_net/provider/vector_stores/base.py +35 -8
  120. pygpt_net/provider/vector_stores/chroma.py +13 -3
  121. pygpt_net/provider/vector_stores/ctx_attachment.py +32 -13
  122. pygpt_net/provider/vector_stores/elasticsearch.py +12 -3
  123. pygpt_net/provider/vector_stores/pinecode.py +12 -3
  124. pygpt_net/provider/vector_stores/redis.py +12 -3
  125. pygpt_net/provider/vector_stores/simple.py +12 -3
  126. pygpt_net/provider/vector_stores/temp.py +16 -4
  127. pygpt_net/provider/web/base.py +10 -3
  128. pygpt_net/provider/web/google_custom_search.py +9 -3
  129. pygpt_net/provider/web/microsoft_bing.py +9 -3
  130. pygpt_net/tools/__init__.py +13 -5
  131. pygpt_net/tools/audio_transcriber/__init__.py +4 -3
  132. pygpt_net/tools/base.py +15 -8
  133. pygpt_net/tools/code_interpreter/__init__.py +4 -3
  134. pygpt_net/tools/html_canvas/__init__.py +4 -3
  135. pygpt_net/tools/image_viewer/__init__.py +10 -4
  136. pygpt_net/tools/indexer/__init__.py +8 -7
  137. pygpt_net/tools/media_player/__init__.py +4 -3
  138. pygpt_net/tools/text_editor/__init__.py +36 -10
  139. pygpt_net/ui/layout/chat/output.py +2 -2
  140. pygpt_net/ui/layout/ctx/ctx_list.py +1 -1
  141. pygpt_net/ui/menu/audio.py +12 -1
  142. {pygpt_net-2.4.41.dist-info → pygpt_net-2.4.43.dist-info}/METADATA +143 -71
  143. {pygpt_net-2.4.41.dist-info → pygpt_net-2.4.43.dist-info}/RECORD +146 -138
  144. {pygpt_net-2.4.41.dist-info → pygpt_net-2.4.43.dist-info}/LICENSE +0 -0
  145. {pygpt_net-2.4.41.dist-info → pygpt_net-2.4.43.dist-info}/WHEEL +0 -0
  146. {pygpt_net-2.4.41.dist-info → pygpt_net-2.4.43.dist-info}/entry_points.txt +0 -0
@@ -180,7 +180,7 @@ class Attachment(QObject):
180
180
  if tmp_path:
181
181
  for root, dirs, files in os.walk(tmp_path):
182
182
  for file in files:
183
- path = os.path.join(root, file)
183
+ path = str(os.path.join(root, file))
184
184
  sub_attachment = AttachmentItem()
185
185
  sub_attachment.path = path
186
186
  sub_attachment.name = os.path.basename(path)
@@ -197,11 +197,9 @@ class Attachment(QObject):
197
197
  auto_index=auto_index,
198
198
  )
199
199
  if item:
200
- item["path"] = os.path.basename(attachment.path) + "/" + path_relative
200
+ item["path"] = os.path.basename(attachment.path) + "/" + str(path_relative)
201
201
  item["size"] = os.path.getsize(path)
202
- if meta.additional_ctx is None:
203
- meta.additional_ctx = []
204
- meta.additional_ctx.append(item)
202
+ self.append_to_meta(meta, item)
205
203
  uploaded = True
206
204
  sub_attachment.consumed = True
207
205
  attachment.consumed = True
@@ -215,14 +213,27 @@ class Attachment(QObject):
215
213
  auto_index=auto_index,
216
214
  )
217
215
  if item:
218
- if meta.additional_ctx is None:
219
- meta.additional_ctx = []
220
- meta.additional_ctx.append(item)
216
+ self.append_to_meta(meta, item)
221
217
  attachment.consumed = True # allow for deletion
222
218
  uploaded = True
223
-
224
219
  return uploaded
225
220
 
221
+ def append_to_meta(self, meta: CtxMeta, item: Dict[str, Any]):
222
+ """
223
+ Append item to meta
224
+
225
+ :param meta: CtxMeta instance
226
+ :param item: Attachment item
227
+ """
228
+ if meta.group:
229
+ if meta.group.additional_ctx is None:
230
+ meta.group.additional_ctx = []
231
+ meta.group.additional_ctx.append(item)
232
+ return
233
+ if meta.additional_ctx is None:
234
+ meta.additional_ctx = []
235
+ meta.additional_ctx.append(item)
236
+
226
237
  def upload_web(
227
238
  self,
228
239
  attachment: AttachmentItem,
@@ -248,9 +259,9 @@ class Attachment(QObject):
248
259
  :param meta: CtxMeta
249
260
  :return: True if has context
250
261
  """
251
- if meta is None or meta.additional_ctx is None:
262
+ if meta is None:
252
263
  return False
253
- return len(meta.additional_ctx) > 0
264
+ return meta.has_additional_ctx()
254
265
 
255
266
  def current_has_context(self) -> bool:
256
267
  """
@@ -334,7 +345,7 @@ class Attachment(QObject):
334
345
  :param meta: CtxMeta instance
335
346
  """
336
347
  # update list of attachments
337
- if meta is None or meta.additional_ctx is None:
348
+ if meta is None or not meta.has_additional_ctx():
338
349
  items = []
339
350
  else:
340
351
  items = self.window.core.attachments.context.get_all(meta)
@@ -347,7 +358,7 @@ class Attachment(QObject):
347
358
 
348
359
  :param meta: CtxMeta instance
349
360
  """
350
- if meta is None or meta.additional_ctx is None:
361
+ if meta is None or not meta.has_additional_ctx():
351
362
  num_files = 0
352
363
  else:
353
364
  num_files = self.window.core.attachments.context.count(meta)
@@ -402,13 +413,14 @@ class Attachment(QObject):
402
413
  )
403
414
  return
404
415
  meta = self.window.core.ctx.get_current_meta()
405
- if meta is None or meta.additional_ctx is None:
416
+ if meta is None or not meta.has_additional_ctx():
406
417
  return
407
418
  items = self.window.core.attachments.context.get_all(meta)
408
419
  if idx < len(items):
409
420
  item = items[idx]
410
421
  self.window.core.attachments.context.delete(meta, item, delete_files=remove_local)
411
422
  self.update_list(meta)
423
+ self.window.controller.ctx.update()
412
424
 
413
425
  def clear(
414
426
  self,
@@ -432,10 +444,11 @@ class Attachment(QObject):
432
444
  return
433
445
 
434
446
  meta = self.window.core.ctx.get_current_meta()
435
- if meta is None or meta.additional_ctx is None:
447
+ if meta is None or not meta.has_additional_ctx():
436
448
  return
437
449
  self.window.core.attachments.context.clear(meta, delete_files=remove_local)
438
450
  self.update_list(meta)
451
+ self.window.controller.ctx.update()
439
452
 
440
453
  def select(self, idx: int):
441
454
  """
@@ -452,7 +465,7 @@ class Attachment(QObject):
452
465
  :param idx: Index on list
453
466
  """
454
467
  meta = self.window.core.ctx.get_current_meta()
455
- if meta is None or meta.additional_ctx is None:
468
+ if meta is None or not meta.has_additional_ctx():
456
469
  return
457
470
  items = self.window.core.attachments.context.get_all(meta)
458
471
  if idx < len(items):
@@ -471,7 +484,7 @@ class Attachment(QObject):
471
484
  :param idx: Index on list
472
485
  """
473
486
  meta = self.window.core.ctx.get_current_meta()
474
- if meta is None or meta.additional_ctx is None:
487
+ if meta is None or not meta.has_additional_ctx():
475
488
  return
476
489
  items = self.window.core.attachments.context.get_all(meta)
477
490
  if idx < len(items):
@@ -491,7 +504,7 @@ class Attachment(QObject):
491
504
  :param idx: Index on list
492
505
  """
493
506
  meta = self.window.core.ctx.get_current_meta()
494
- if meta is None or meta.additional_ctx is None:
507
+ if meta is None or not meta.has_additional_ctx():
495
508
  return
496
509
  items = self.window.core.attachments.context.get_all(meta)
497
510
  if idx < len(items):
@@ -510,7 +523,7 @@ class Attachment(QObject):
510
523
  :return: True if has file
511
524
  """
512
525
  meta = self.window.core.ctx.get_current_meta()
513
- if meta is None or meta.additional_ctx is None:
526
+ if meta is None or not meta.has_additional_ctx():
514
527
  return False
515
528
  items = self.window.core.attachments.context.get_all(meta)
516
529
  if idx < len(items):
@@ -529,7 +542,7 @@ class Attachment(QObject):
529
542
  :return: True if has source directory
530
543
  """
531
544
  meta = self.window.core.ctx.get_current_meta()
532
- if meta is None or meta.additional_ctx is None:
545
+ if meta is None or not meta.has_additional_ctx():
533
546
  return False
534
547
  items = self.window.core.attachments.context.get_all(meta)
535
548
  if idx < len(items):
@@ -549,7 +562,7 @@ class Attachment(QObject):
549
562
  :return: True if has destination directory
550
563
  """
551
564
  meta = self.window.core.ctx.get_current_meta()
552
- if meta is None or meta.additional_ctx is None:
565
+ if meta is None or not meta.has_additional_ctx():
553
566
  return False
554
567
  items = self.window.core.attachments.context.get_all(meta)
555
568
  if idx < len(items):
@@ -570,10 +583,10 @@ class Attachment(QObject):
570
583
  meta = self.window.core.ctx.get_current_meta()
571
584
  if meta is None:
572
585
  return 0
573
- if meta.additional_ctx is None:
586
+ if not meta.has_additional_ctx():
574
587
  return 0
575
588
  tokens = 0
576
- for item in meta.additional_ctx:
589
+ for item in meta.get_additional_ctx():
577
590
  if "tokens" in item:
578
591
  try:
579
592
  tokens += int(item["tokens"])
@@ -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.26 19:00:00 #
9
+ # Updated Date: 2024.12.14 18:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import base64
@@ -63,7 +63,7 @@ class Audio:
63
63
  :param ctx: Context item
64
64
  """
65
65
  wav_path = os.path.join(self.window.core.config.get_user_path(), self.audio_file)
66
- if ctx.is_audio and ctx.audio_output:
66
+ if ctx.is_audio and ctx.audio_output and ctx.audio_read_allowed():
67
67
  wav_bytes = base64.b64decode(ctx.audio_output)
68
68
  with open(wav_path, "wb") as f:
69
69
  f.write(wav_bytes)
@@ -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.12.14 08:00:00 #
9
+ # Updated Date: 2024.12.14 18:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from typing import Dict, Any, List
@@ -104,9 +104,23 @@ class Placeholder:
104
104
  return self.get_voice_control_actions()
105
105
  elif id == "audio_input_devices":
106
106
  return self.get_audio_input_devices()
107
+ elif id == "audio_tts_whisper_voices":
108
+ return self.get_audio_tts_whisper_voices()
107
109
  else:
108
110
  return []
109
111
 
112
+ def get_audio_tts_whisper_voices(self) -> List[Dict[str, str]]:
113
+ """
114
+ Get audio TTS whisper voices list
115
+
116
+ :return: placeholders list
117
+ """
118
+ voices = self.window.core.audio.whisper.get_voices()
119
+ data = []
120
+ for voice in voices:
121
+ data.append({voice: voice})
122
+ return data
123
+
110
124
  def get_audio_input_devices(self) -> List[Dict[str, str]]:
111
125
  """
112
126
  Get audio input devices list
@@ -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.12.14 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from pygpt_net.core.types import (
@@ -189,8 +189,12 @@ class Mode:
189
189
  self.window.ui.tabs['input'].setTabVisible(2, False)
190
190
  self.window.ui.tabs['input'].setTabVisible(3, False)
191
191
 
192
- # toggle chat footer
193
- if not self.is_chat_tab():
192
+ # chat footer
193
+ self.toggle_chat_footer()
194
+
195
+ def toggle_chat_footer(self):
196
+ """Toggle chat footer"""
197
+ if self.window.controller.ui.tabs.get_current_type() != Tab.TAB_CHAT:
194
198
  self.hide_chat_footer()
195
199
  else:
196
200
  self.show_chat_footer()
@@ -200,18 +204,12 @@ class Mode:
200
204
  Check if vision is allowed
201
205
 
202
206
  :param mode: current mode
207
+ :return: True if vision is allowed
203
208
  """
204
- if mode == MODE_VISION:
205
- return True
206
-
207
- allowed = self.window.controller.painter.is_active()
208
- if allowed:
209
+ if self.window.controller.ui.vision.has_vision():
209
210
  return True
210
211
 
211
- if mode in [MODE_IMAGE, MODE_ASSISTANT]:
212
- return False
213
-
214
- if self.window.controller.ui.vision.is_vision_model():
212
+ if self.window.controller.painter.is_active():
215
213
  return True
216
214
 
217
215
  # event: UI: vision
@@ -224,7 +222,12 @@ class Mode:
224
222
  return event.data['value']
225
223
 
226
224
  def are_attachments(self, mode: str) -> bool:
227
- """Check if attachments are allowed"""
225
+ """
226
+ Check if attachments are allowed
227
+
228
+ :param mode: current mode
229
+ :return: True if attachments are allowed
230
+ """
228
231
  if mode in [MODE_VISION, MODE_ASSISTANT]:
229
232
  return True
230
233
 
@@ -243,14 +246,6 @@ class Mode:
243
246
  self.window.dispatch(event)
244
247
  return event.data['value']
245
248
 
246
- def is_chat_tab(self) -> bool:
247
- """
248
- Check if current tab is chat
249
-
250
- :return: True if chat tab
251
- """
252
- return self.window.controller.ui.tabs.get_current_type() == Tab.TAB_CHAT
253
-
254
249
  def show_chat_footer(self):
255
250
  """Show chat footer"""
256
251
  self.window.ui.nodes['chat.footer'].setVisible(True)
@@ -161,7 +161,7 @@ class Attachments:
161
161
  if meta is None:
162
162
  return []
163
163
  attachments = []
164
- for attachment in meta.additional_ctx:
164
+ for attachment in meta.get_additional_ctx():
165
165
  item = AttachmentItem()
166
166
  if 'uuid' not in attachment:
167
167
  continue
@@ -125,7 +125,7 @@ class Context:
125
125
  meta_path = self.get_dir(meta)
126
126
  context = ""
127
127
  if os.path.exists(meta_path) and os.path.isdir(meta_path):
128
- for file in meta.additional_ctx:
128
+ for file in meta.get_additional_ctx():
129
129
  if ("type" not in file
130
130
  or file["type"] not in ["local_file", "url"]):
131
131
  continue
@@ -183,7 +183,7 @@ class Context:
183
183
 
184
184
  indexed = False
185
185
  # index files if not indexed by auto_index
186
- for i, file in enumerate(meta.additional_ctx):
186
+ for i, file in enumerate(meta.get_additional_ctx()):
187
187
  if "indexed" not in file or not file["indexed"]:
188
188
  file_id = file["uuid"]
189
189
  file_idx_path = os.path.join(meta_path, file_id)
@@ -496,7 +496,7 @@ class Context:
496
496
  :param meta: CtxMeta instance
497
497
  :return: list of attachments
498
498
  """
499
- return meta.additional_ctx
499
+ return meta.get_additional_ctx()
500
500
 
501
501
  def get_dir(self, meta: CtxMeta) -> str:
502
502
  """
@@ -506,6 +506,8 @@ class Context:
506
506
  :return: directory path
507
507
  """
508
508
  meta_uuid = str(meta.uuid)
509
+ if meta.group:
510
+ meta_uuid = str(meta.group.uuid)
509
511
  return os.path.join(self.window.core.config.get_user_dir("ctx_idx"), meta_uuid)
510
512
 
511
513
  def get_selected_model(self, mode: str = "summary"):
@@ -562,7 +564,7 @@ class Context:
562
564
  :param meta: CtxMeta instance
563
565
  :return: number of attachments
564
566
  """
565
- return len(meta.additional_ctx)
567
+ return len(meta.get_additional_ctx())
566
568
 
567
569
  def delete(
568
570
  self,
@@ -577,11 +579,11 @@ class Context:
577
579
  :param item: Attachment item dict
578
580
  :param delete_files: delete files
579
581
  """
580
- meta.additional_ctx.remove(item)
582
+ meta.remove_additional_ctx(item)
581
583
  self.window.core.ctx.save(meta.id)
582
584
  if delete_files:
583
585
  self.delete_local(meta, item)
584
- if len(meta.additional_ctx) == 0:
586
+ if len(meta.get_additional_ctx()) == 0:
585
587
  self.delete_index(meta)
586
588
 
587
589
  def delete_by_meta(self, meta: CtxMeta):
@@ -613,7 +615,7 @@ class Context:
613
615
  :param meta: CtxMeta instance
614
616
  :param delete_files: delete files
615
617
  """
616
- meta.additional_ctx = []
618
+ meta.reset_additional_ctx()
617
619
  self.window.core.ctx.save(meta.id)
618
620
  if delete_files:
619
621
  self.delete_index(meta)
@@ -644,7 +646,7 @@ class Context:
644
646
  :param meta: CtxMeta instance
645
647
  :param delete_files: delete files
646
648
  """
647
- meta.additional_ctx = []
649
+ meta.reset_additional_ctx()
648
650
  self.window.core.ctx.save(meta.id)
649
651
  if delete_files:
650
652
  self.delete_index(meta)
@@ -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.12.14 08:00:00 #
9
+ # Updated Date: 2024.12.14 18:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import re
@@ -17,6 +17,8 @@ from bs4 import UnicodeDammit
17
17
  from pygpt_net.provider.audio_input.base import BaseProvider as InputBaseProvider
18
18
  from pygpt_net.provider.audio_output.base import BaseProvider as OutputBaseProvider
19
19
 
20
+ from .whisper import Whisper
21
+
20
22
 
21
23
  class Audio:
22
24
  def __init__(self, window=None):
@@ -26,6 +28,7 @@ class Audio:
26
28
  :param window: Window instance
27
29
  """
28
30
  self.window = window
31
+ self.whisper = Whisper(window)
29
32
  self.providers = {
30
33
  "input": {},
31
34
  "output": {},
@@ -0,0 +1,37 @@
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.12.14 18:00:00 #
10
+ # ================================================== #
11
+
12
+ from typing import List
13
+
14
+ class Whisper:
15
+ def __init__(self, window=None):
16
+ """
17
+ Whisper core
18
+
19
+ :param window: Window instance
20
+ """
21
+ self.window = window
22
+ self.voices = [
23
+ "alloy",
24
+ "echo",
25
+ "fable",
26
+ "onyx",
27
+ "nova",
28
+ "shimmer",
29
+ ]
30
+
31
+ def get_voices(self) -> List[str]:
32
+ """
33
+ Get whisper voices
34
+
35
+ :return: whisper voice name
36
+ """
37
+ return self.voices
@@ -60,14 +60,14 @@ class BridgeWorker(QObject, QRunnable):
60
60
  extra=self.extra,
61
61
  )
62
62
 
63
- # Llama-index: chat with files
63
+ # LlamaIndex: chat with files
64
64
  elif self.mode == MODE_LLAMA_INDEX:
65
65
  result = self.window.core.idx.chat.call(
66
66
  context=self.context,
67
67
  extra=self.extra,
68
68
  )
69
69
 
70
- # Llama-index: agents
70
+ # LlamaIndex: agents
71
71
  elif self.mode == MODE_AGENT_LLAMA:
72
72
  result = self.window.core.agents.runner.call(
73
73
  context=self.context,
@@ -122,6 +122,7 @@ class Database:
122
122
  'updated_ts',
123
123
  'created_ts',
124
124
  'uuid',
125
+ 'additional_ctx_json',
125
126
  ]
126
127
  columns["idx_ctx"] = [
127
128
  'id',
@@ -242,7 +243,7 @@ class Database:
242
243
  'sort_by': columns["ctx_group"],
243
244
  'search_fields': ['id', 'name'],
244
245
  'timestamp_columns': ['created_ts', 'updated_ts'],
245
- 'json_columns': [],
246
+ 'json_columns': ['additional_ctx_json'],
246
247
  'default_sort': 'id',
247
248
  'default_order': 'DESC',
248
249
  'primary_key': 'id',
@@ -6,10 +6,17 @@
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.12.14 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
- from pygpt_net.core.events import ControlEvent, AppEvent, Event, KernelEvent, RenderEvent
12
+ from pygpt_net.core.events import (
13
+ ControlEvent,
14
+ AppEvent,
15
+ Event,
16
+ KernelEvent,
17
+ RenderEvent,
18
+ BaseEvent
19
+ )
13
20
 
14
21
 
15
22
  class EventsDebug:
@@ -25,19 +32,24 @@ class EventsDebug:
25
32
  def update(self):
26
33
  """Update debug window."""
27
34
  self.window.core.debug.begin(self.id)
28
- self.window.core.debug.add(self.id, 'App Events:', str(AppEvent.__dict__))
29
- self.window.core.debug.add(self.id, 'Control Events:', str(ControlEvent.__dict__))
30
- self.window.core.debug.add(self.id, 'Kernel Events:', str(KernelEvent.__dict__))
31
- self.window.core.debug.add(self.id, 'Render Events:', str(RenderEvent.__dict__))
32
- self.window.core.debug.add(self.id, 'Plugin Events:', str(self.extract_plugins()))
35
+ self.window.core.debug.add(self.id, 'App Events:', str(self.extract_events(AppEvent)))
36
+ self.window.core.debug.add(self.id, 'Control Events:', str(self.extract_events(ControlEvent)))
37
+ self.window.core.debug.add(self.id, 'Kernel Events:', str(self.extract_events(KernelEvent)))
38
+ self.window.core.debug.add(self.id, 'Render Events:', str(self.extract_events(RenderEvent)))
39
+ self.window.core.debug.add(self.id, 'Plugin Events:', str(self.extract_events(Event)))
40
+ self.window.core.debug.add(self.id, '----', '')
33
41
  self.window.core.debug.add(self.id, 'Voice Cmds (all):', str(self.window.core.access.voice.commands))
34
42
  self.window.core.debug.add(self.id, 'Voice Cmds (allowed):', str(self.window.core.access.voice.get_commands()))
35
43
  self.window.core.debug.end(self.id)
36
44
 
37
- def extract_plugins(self) -> dict:
38
- """Extract plugin events"""
45
+ def extract_events(self, events: BaseEvent) -> dict:
46
+ """
47
+ Extract events
48
+
49
+ :param events: Events class
50
+ """
39
51
  result = {}
40
- for property, value in vars(Event).items():
52
+ for property, value in vars(events).items():
41
53
  if (isinstance(value, str)
42
54
  or isinstance(value, int)
43
55
  or isinstance(value, float)
@@ -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.12.12 01:00:00 #
9
+ # Updated Date: 2024.12.14 17:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  class TabsDebug:
@@ -22,10 +22,12 @@ class TabsDebug:
22
22
  def update(self):
23
23
  """Update debug window."""
24
24
  self.window.core.debug.begin(self.id)
25
- self.window.core.debug.add(self.id, 'current PID', str(self.window.controller.ui.tabs.get_current_pid()))
25
+ self.window.core.debug.add(self.id, 'current Col', str(self.window.controller.ui.tabs.get_current_column_idx()))
26
26
  self.window.core.debug.add(self.id, 'current IDX', str(self.window.controller.ui.tabs.get_current_idx()))
27
+ self.window.core.debug.add(self.id, 'current Tab', str(self.window.controller.ui.tabs.get_current_tab()))
28
+ self.window.core.debug.add(self.id, 'current PID', str(self.window.controller.ui.tabs.get_current_pid()))
27
29
  self.window.core.debug.add(self.id, 'current Type', str(self.window.controller.ui.tabs.get_current_type()))
28
- self.window.core.debug.add(self.id, 'current Column', str(self.window.controller.ui.tabs.get_current_column_idx()))
30
+ self.window.core.debug.add(self.id, '----', '')
29
31
  self.window.core.debug.add(self.id, 'last_pid', str(self.window.core.tabs.last_pid))
30
32
  self.window.core.debug.add(self.id, 'locked', str(self.window.controller.ui.tabs.locked))
31
33
  self.window.core.debug.add(self.id, 'col', str(self.window.controller.ui.tabs.col))
@@ -40,6 +42,7 @@ class TabsDebug:
40
42
  self.window.core.debug.add(self.id, "PID ["+str(pid)+"]", str(data))
41
43
 
42
44
  # mapping PID => meta.id
45
+ self.window.core.debug.add(self.id, '----', '')
43
46
  self.window.core.debug.add(self.id, 'PID => meta.id', str(self.window.core.ctx.output.mapping))
44
47
  self.window.core.debug.add(self.id, '(last) meta.id => PID', str(self.window.core.ctx.output.last_pids))
45
48
  self.window.core.debug.add(self.id, '(last) PID', str(self.window.core.ctx.output.last_pid))
pygpt_net/core/history.py CHANGED
@@ -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.01.19 05:00:00 #
9
+ # Updated Date: 2024.12.14 22:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import datetime
13
13
  import os
14
+ from typing import List
14
15
 
15
16
  from pygpt_net.item.ctx import CtxItem
16
17
  from pygpt_net.provider.core.history.txt_file import TxtFileProvider
@@ -46,7 +47,7 @@ class History:
46
47
  # delete all txt history files from history dir
47
48
  self.provider.truncate()
48
49
 
49
- def remove_items(self, items: list):
50
+ def remove_items(self, items: List[CtxItem]):
50
51
  """
51
52
  Remove items from history (txt files)
52
53
 
@@ -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.12.14 08:00:00 #
9
+ # Updated Date: 2024.12.14 22:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import datetime
@@ -406,7 +406,11 @@ class Idx:
406
406
  return self.items[store_id]
407
407
  return {}
408
408
 
409
- def append(self, idx: str, files: Dict[str, str]):
409
+ def append(
410
+ self,
411
+ idx: str,
412
+ files: Dict[str, str]
413
+ ):
410
414
  """
411
415
  Append indexed files to index
412
416
 
@@ -454,7 +458,11 @@ class Idx:
454
458
  self.items[store_id][idx].items[file_id]["id"] = doc_id
455
459
  self.items[store_id][idx].items[file_id]["indexed_ts"] = ts
456
460
 
457
- def remove_doc(self, idx: str, doc_id: str):
461
+ def remove_doc(
462
+ self,
463
+ idx: str,
464
+ doc_id: str
465
+ ):
458
466
  """
459
467
  Remove document from index
460
468
 
@@ -465,7 +473,11 @@ class Idx:
465
473
  if self.storage.remove_document(idx, doc_id):
466
474
  self.log("Removed document from index: " + idx + " - " + doc_id)
467
475
 
468
- def remove_file(self, idx: str, file: str):
476
+ def remove_file(
477
+ self,
478
+ idx: str,
479
+ file: str
480
+ ):
469
481
  """
470
482
  Remove file from index
471
483