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
@@ -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.12.14 22:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from pygpt_net.plugin.base.plugin import BasePlugin
@@ -57,7 +57,12 @@ class Plugin(BasePlugin):
57
57
  data = event.data
58
58
  ctx = event.ctx
59
59
 
60
- always_events = [Event.FORCE_STOP, Event.PLUGIN_SETTINGS_CHANGED, Event.ENABLE, Event.DISABLE]
60
+ always_events = [
61
+ Event.FORCE_STOP,
62
+ Event.PLUGIN_SETTINGS_CHANGED,
63
+ Event.ENABLE,
64
+ Event.DISABLE
65
+ ]
61
66
 
62
67
  if not self.is_allowed() and name != Event.DISABLE:
63
68
  return
@@ -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.13 08:00:00 #
9
+ # Updated Date: 2024.12.14 18:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import Slot
@@ -167,6 +167,11 @@ class Plugin(BasePlugin):
167
167
  cache_file = None
168
168
  if event.data is not None and isinstance(event.data, dict) and "cache_file" in event.data:
169
169
  cache_file = event.data["cache_file"]
170
+
171
+ # check for audio read allowed. Prevents reading audio in commands, results, etc.
172
+ if name == Event.CTX_AFTER:
173
+ if not ctx.audio_read_allowed():
174
+ return # abort if audio read is not allowed (commands, results, etc.)
170
175
 
171
176
  try:
172
177
  if text is not None and len(text) > 0:
@@ -6,17 +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.12.14 00:00:00 #
9
+ # Updated Date: 2024.12.14 22:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import copy
13
- from typing import Optional
13
+ from typing import Optional, Any, Dict, List
14
14
 
15
15
  from PySide6.QtCore import QObject, Slot
16
16
 
17
- from pygpt_net.core.types import (
18
- MODE_AGENT_LLAMA,
19
- )
20
17
  from pygpt_net.core.bridge.context import BridgeContext
21
18
  from pygpt_net.core.events import Event, KernelEvent
22
19
  from pygpt_net.item.ctx import CtxItem
@@ -43,7 +40,7 @@ class BasePlugin(QObject):
43
40
  self.use_locale = False
44
41
  self.order = 0
45
42
 
46
- def setup(self) -> dict:
43
+ def setup(self) -> Dict[str, Any]:
47
44
  """
48
45
  Return available config options
49
46
 
@@ -51,7 +48,12 @@ class BasePlugin(QObject):
51
48
  """
52
49
  return self.options
53
50
 
54
- def add_option(self, name: str, type: str, **kwargs) -> dict:
51
+ def add_option(
52
+ self,
53
+ name: str,
54
+ type: str,
55
+ **kwargs
56
+ ) -> Dict[str, Any]:
55
57
  """
56
58
  Add plugin configuration option
57
59
 
@@ -84,7 +86,11 @@ class BasePlugin(QObject):
84
86
  self.options[name] = option
85
87
  return option
86
88
 
87
- def add_cmd(self, cmd: str, **kwargs) -> dict:
89
+ def add_cmd(
90
+ self,
91
+ cmd: str,
92
+ **kwargs
93
+ ) -> Dict[str, Any]:
88
94
  """
89
95
  Add plugin command
90
96
 
@@ -125,7 +131,10 @@ class BasePlugin(QObject):
125
131
 
126
132
  return self.add_option(name, "cmd", **kwargs)
127
133
 
128
- def has_cmd(self, cmd: str) -> bool:
134
+ def has_cmd(
135
+ self,
136
+ cmd: str
137
+ ) -> bool:
129
138
  """
130
139
  Check if command exists
131
140
 
@@ -138,7 +147,10 @@ class BasePlugin(QObject):
138
147
  return self.options[key]["value"]["enabled"]
139
148
  return False
140
149
 
141
- def cmd_allowed(self, cmd: str) -> bool:
150
+ def cmd_allowed(
151
+ self,
152
+ cmd: str
153
+ ) -> bool:
142
154
  """
143
155
  Check if command allowed
144
156
 
@@ -157,7 +169,10 @@ class BasePlugin(QObject):
157
169
  """
158
170
  return self.window.core.config.get("cmd")
159
171
 
160
- def get_cmd(self, cmd: str) -> dict:
172
+ def get_cmd(
173
+ self,
174
+ cmd: str
175
+ ) -> Dict[str, Any]:
161
176
  """
162
177
  Return command
163
178
 
@@ -170,7 +185,10 @@ class BasePlugin(QObject):
170
185
  data = {"cmd": cmd, **data}
171
186
  return data
172
187
 
173
- def has_option(self, name: str) -> bool:
188
+ def has_option(
189
+ self,
190
+ name: str
191
+ ) -> bool:
174
192
  """
175
193
  Check if option exists
176
194
 
@@ -179,7 +197,10 @@ class BasePlugin(QObject):
179
197
  """
180
198
  return name in self.options
181
199
 
182
- def get_option(self, name: str) -> dict:
200
+ def get_option(
201
+ self,
202
+ name: str
203
+ ) -> Dict[str, Any]:
183
204
  """
184
205
  Return option
185
206
 
@@ -189,7 +210,10 @@ class BasePlugin(QObject):
189
210
  if self.has_option(name):
190
211
  return self.options[name]
191
212
 
192
- def get_option_value(self, name: str) -> any:
213
+ def get_option_value(
214
+ self,
215
+ name: str
216
+ ) -> Any:
193
217
  """
194
218
  Return option value
195
219
 
@@ -207,7 +231,12 @@ class BasePlugin(QObject):
207
231
  """
208
232
  self.window = window
209
233
 
210
- def handle(self, event: Event, *args, **kwargs):
234
+ def handle(
235
+ self,
236
+ event: Event,
237
+ *args,
238
+ **kwargs
239
+ ):
211
240
  """
212
241
  Handle event
213
242
 
@@ -235,7 +264,10 @@ class BasePlugin(QObject):
235
264
  """
236
265
  return
237
266
 
238
- def trans(self, text: Optional[str] = None) -> str:
267
+ def trans(
268
+ self,
269
+ text: Optional[str] = None
270
+ ) -> str:
239
271
  """
240
272
  Translate text using plugin domain
241
273
 
@@ -247,7 +279,7 @@ class BasePlugin(QObject):
247
279
  domain = 'plugin.{}'.format(self.id)
248
280
  return trans(text, False, domain)
249
281
 
250
- def error(self, err: any):
282
+ def error(self, err: Any):
251
283
  """
252
284
  Send error message to logger and alert dialog
253
285
 
@@ -257,7 +289,7 @@ class BasePlugin(QObject):
257
289
  msg = self.window.core.debug.parse_alert(err)
258
290
  self.window.ui.dialogs.alert("{}: {}".format(self.name, msg))
259
291
 
260
- def debug(self, data: any):
292
+ def debug(self, data: Any):
261
293
  """
262
294
  Send debug message to logger window
263
295
 
@@ -337,9 +369,9 @@ class BasePlugin(QObject):
337
369
  @Slot(object, object, dict)
338
370
  def handle_finished(
339
371
  self,
340
- response: dict,
372
+ response: Dict[str, Any],
341
373
  ctx: Optional[CtxItem] = None,
342
- extra_data: Optional[dict] = None
374
+ extra_data: Optional[Dict[str, Any]] = None
343
375
  ):
344
376
  """
345
377
  Handle finished response signal
@@ -367,9 +399,9 @@ class BasePlugin(QObject):
367
399
  @Slot(object, object, dict)
368
400
  def handle_finished_more(
369
401
  self,
370
- responses: list,
402
+ responses: List[Dict[str, Any]],
371
403
  ctx: Optional[CtxItem] = None,
372
- extra_data: Optional[dict] = None
404
+ extra_data: Optional[Dict[str, Any]] = None
373
405
  ):
374
406
  """
375
407
  Handle finished response signal
@@ -397,9 +429,9 @@ class BasePlugin(QObject):
397
429
 
398
430
  def prepare_reply_ctx(
399
431
  self,
400
- response: dict,
432
+ response: Dict[str, Any],
401
433
  ctx: Optional[CtxItem] = None
402
- ) -> dict:
434
+ ) -> Dict[str, Any]:
403
435
  """
404
436
  Prepare reply context
405
437
 
@@ -454,7 +486,7 @@ class BasePlugin(QObject):
454
486
  self.window.update_status(str(data))
455
487
 
456
488
  @Slot(object)
457
- def handle_error(self, err: any):
489
+ def handle_error(self, err: Any):
458
490
  """
459
491
  Handle thread error signal
460
492
 
@@ -463,7 +495,7 @@ class BasePlugin(QObject):
463
495
  self.error(err)
464
496
 
465
497
  @Slot(object)
466
- def handle_debug(self, msg: any):
498
+ def handle_debug(self, msg: Any):
467
499
  """
468
500
  Handle debug message signal
469
501
 
@@ -6,10 +6,10 @@
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 00:00:00 #
9
+ # Updated Date: 2024.12.14 22:00:00 #
10
10
  # ================================================== #
11
11
 
12
- from typing import Optional, Any
12
+ from typing import Optional, Any, Dict, List
13
13
 
14
14
  from PySide6.QtCore import QObject, QRunnable
15
15
  from typing_extensions import deprecated
@@ -44,7 +44,7 @@ class BaseWorker(QObject, QRunnable):
44
44
  if self.signals is not None and hasattr(self.signals, "destroyed"):
45
45
  self.signals.destroyed.emit()
46
46
 
47
- def error(self, err: any):
47
+ def error(self, err: Any):
48
48
  """
49
49
  Emit error signal
50
50
 
@@ -67,8 +67,8 @@ class BaseWorker(QObject, QRunnable):
67
67
  @deprecated("From 2.1.29: BaseWorker.response() is deprecated, use BaseWorker.reply() instead")
68
68
  def response(
69
69
  self,
70
- response: dict,
71
- extra_data: Optional[dict] = None
70
+ response: Dict[str, Any],
71
+ extra_data: Optional[Dict[str, Any]] = None
72
72
  ):
73
73
  """
74
74
  Emit finished signal (deprecated)
@@ -82,8 +82,8 @@ class BaseWorker(QObject, QRunnable):
82
82
 
83
83
  def reply(
84
84
  self,
85
- response: dict,
86
- extra_data: Optional[dict] = None
85
+ response: Dict[str, Any],
86
+ extra_data: Optional[Dict[str, Any]] = None
87
87
  ):
88
88
  """
89
89
  Emit finished signal (on reply from command output)
@@ -101,8 +101,8 @@ class BaseWorker(QObject, QRunnable):
101
101
 
102
102
  def reply_more(
103
103
  self,
104
- responses: list,
105
- extra_data: Optional[dict] = None
104
+ responses: List[Dict[str, Any]],
105
+ extra_data: Optional[Dict[str, Any]] = None
106
106
  ):
107
107
  """
108
108
  Emit finished_more signal (on reply from command output, multiple responses)
@@ -166,7 +166,10 @@ class BaseWorker(QObject, QRunnable):
166
166
  self.signals.status.connect(parent.handle_status)
167
167
  self.signals.error.connect(parent.handle_error)
168
168
 
169
- def from_request(self, item: dict) -> dict:
169
+ def from_request(
170
+ self,
171
+ item: Dict[str, Any]
172
+ ) -> Dict[str, Any]:
170
173
  """
171
174
  Prepare request item for result
172
175
 
@@ -177,10 +180,10 @@ class BaseWorker(QObject, QRunnable):
177
180
 
178
181
  def make_response(
179
182
  self,
180
- item: dict,
181
- result: any,
182
- extra: Optional[dict] = None
183
- ) -> dict:
183
+ item: Dict[str, Any],
184
+ result: Any,
185
+ extra: Optional[Dict[str, Any]] = None
186
+ ) -> Dict[str, Any]:
184
187
  """
185
188
  Prepare response item
186
189
 
@@ -211,7 +214,7 @@ class BaseWorker(QObject, QRunnable):
211
214
 
212
215
  def has_param(
213
216
  self,
214
- item: dict,
217
+ item: Dict[str, Any],
215
218
  param: str
216
219
  ) -> bool:
217
220
  """
@@ -227,10 +230,10 @@ class BaseWorker(QObject, QRunnable):
227
230
 
228
231
  def get_param(
229
232
  self,
230
- item: dict,
233
+ item: Dict[str, Any],
231
234
  param: str,
232
235
  default: Any = None
233
- ) -> any:
236
+ ) -> Any:
234
237
  """
235
238
  Get parameter value from item
236
239
 
@@ -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 19:00:00 #
9
+ # Updated Date: 2024.12.14 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from pygpt_net.plugin.base.config import BaseConfig, BasePlugin
@@ -34,7 +34,7 @@ class Config(BaseConfig):
34
34
  plugin.add_option(
35
35
  "model_summarize",
36
36
  type="combo",
37
- value="gpt-3.5-turbo",
37
+ value="gpt-4o-mini",
38
38
  label="Model",
39
39
  description="Model used for summarize, default: gpt-3.5-turbo",
40
40
  tooltip="Summarize model",
@@ -6,14 +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.12.13 08:00:00 #
9
+ # Updated Date: 2024.12.15 01:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import ssl
13
13
  from urllib.request import Request, urlopen
14
14
 
15
- from requests import HTTPError
16
-
17
15
  from pygpt_net.plugin.base.plugin import BasePlugin
18
16
  from pygpt_net.provider.web.base import BaseProvider
19
17
  from pygpt_net.core.events import Event
@@ -38,6 +36,7 @@ class Plugin(BasePlugin):
38
36
  "web_urls",
39
37
  "web_url_open",
40
38
  "web_url_raw",
39
+ "web_request",
41
40
  "web_index",
42
41
  "web_index_query",
43
42
  "web_extract_links",
@@ -96,7 +95,7 @@ class Plugin(BasePlugin):
96
95
 
97
96
  :return: providers dict
98
97
  """
99
- return self.window.core.web.get_providers("search_engine")
98
+ return self.window.core.web.get_providers(self.window.core.web.PROVIDER_SEARCH_ENGINE)
100
99
 
101
100
  def get_provider_options(self) -> list:
102
101
  """Get provider options"""
@@ -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.13 08:00:00 #
9
+ # Updated Date: 2024.12.15 01:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from pygpt_net.plugin.base.config import BaseConfig, BasePlugin
@@ -150,11 +150,12 @@ class Config(BaseConfig):
150
150
  )
151
151
  plugin.add_option(
152
152
  "idx",
153
- type="text",
153
+ type="combo",
154
154
  value="base",
155
155
  label="Index to use",
156
156
  description="ID of index to use for web page indexing (persistent index)",
157
157
  tooltip="Index name",
158
+ use="idx",
158
159
  tab="indexing",
159
160
  )
160
161
  plugin.add_option(
@@ -162,7 +163,7 @@ class Config(BaseConfig):
162
163
  type="combo",
163
164
  value="gpt-4o-mini",
164
165
  label="Model used for web page summarize",
165
- description="Model used for web page summarize, default: gpt-3.5-turbo-1106",
166
+ description="Model used for web page summarize, default: gpt-4o-mini",
166
167
  use="models",
167
168
  advanced=True,
168
169
  )
@@ -246,6 +247,73 @@ class Config(BaseConfig):
246
247
  enabled=True,
247
248
  description="If enabled, model will be able to search the Web and get founded URLs list",
248
249
  )
250
+ plugin.add_cmd(
251
+ "web_request",
252
+ instruction="send HTTP request to specified URL or API endpoint, using `requests` library. Tip: to "
253
+ "send raw data, use `data` parameter. To send data in `application/x-www-form-urlencoded` format, "
254
+ "use `data_form` parameter. To send data in `application/json` format, use `data_json` parameter. "
255
+ "Sending data in `data_form` and `data_json` parameters will automatically set `Content-Type`. To "
256
+ "upload files, use `files` parameter. To send cookies, use `cookies` parameter. To set custom headers, "
257
+ "use `headers` parameter. You can combine all parameters.",
258
+ params=[
259
+ {
260
+ "name": "url",
261
+ "type": "str",
262
+ "description": "URL to website or API endpoint",
263
+ "required": True,
264
+ },
265
+ {
266
+ "name": "method",
267
+ "type": "str",
268
+ "description": "HTTP method, default: GET",
269
+ "required": False,
270
+ },
271
+ {
272
+ "name": "headers",
273
+ "type": "dict",
274
+ "description": "HTTP headers",
275
+ "required": False,
276
+ },
277
+ {
278
+ "name": "params",
279
+ "type": "dict",
280
+ "description": "GET parameters",
281
+ "required": False,
282
+ },
283
+ {
284
+ "name": "data",
285
+ "type": "str",
286
+ "description": "raw data to send in POST requests",
287
+ "required": False,
288
+ },
289
+ {
290
+ "name": "data_form",
291
+ "type": "dict",
292
+ "description": "data to send in POST `application/x-www-form-urlencoded` requests",
293
+ "required": False,
294
+ },
295
+ {
296
+ "name": "data_json",
297
+ "type": "dict",
298
+ "description": "JSON data to send in POST `application/json` requests",
299
+ "required": False,
300
+ },
301
+ {
302
+ "name": "cookies",
303
+ "type": "dict",
304
+ "description": "Cookies",
305
+ "required": False,
306
+ },
307
+ {
308
+ "name": "files",
309
+ "type": "dict",
310
+ "description": "Files to upload, key is form field name, value is absolute path to file",
311
+ "required": False,
312
+ },
313
+ ],
314
+ enabled=True,
315
+ description="If enabled, model will be able to send any HTTP request to specified URL or API endpoint",
316
+ )
249
317
  plugin.add_cmd(
250
318
  "web_extract_links",
251
319
  instruction="open webpage and get list of all links from it",
@@ -6,10 +6,11 @@
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.13 08:00:00 #
9
+ # Updated Date: 2024.12.14 22:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import re
13
+ from typing import Optional, Tuple, Any, List
13
14
 
14
15
  from bs4 import BeautifulSoup
15
16
 
@@ -32,7 +33,7 @@ class WebSearch:
32
33
  query: str,
33
34
  num: int,
34
35
  offset: int = 1
35
- ) -> list:
36
+ ) -> List[str]:
36
37
  """
37
38
  Execute search query and return list of urls
38
39
 
@@ -43,7 +44,7 @@ class WebSearch:
43
44
  """
44
45
  return self.plugin.get_provider().search(query, num, offset)
45
46
 
46
- def get_urls(self, query: str) -> list:
47
+ def get_urls(self, query: str) -> List[str]:
47
48
  """
48
49
  Search the web and returns URLs
49
50
 
@@ -104,7 +105,7 @@ class WebSearch:
104
105
  self,
105
106
  text: str,
106
107
  chunk_size: int
107
- ) -> list:
108
+ ) -> List[str]:
108
109
  """
109
110
  Split text into chunks
110
111
 
@@ -120,7 +121,7 @@ class WebSearch:
120
121
  self,
121
122
  chunks: list,
122
123
  query: str,
123
- summarize_prompt: str = None
124
+ summarize_prompt: Optional[str] = None
124
125
  ) -> str:
125
126
  """
126
127
  Get summarized text from chunks
@@ -195,7 +196,7 @@ class WebSearch:
195
196
  query: str,
196
197
  page_no: int = 1,
197
198
  summarize_prompt: str = ""
198
- ) -> (str, int, int, str, str):
199
+ ) -> Tuple[str, int, int, str, str]:
199
200
  """
200
201
  Get result from search query
201
202
 
@@ -260,7 +261,7 @@ class WebSearch:
260
261
  if result is not None and result != "":
261
262
  # get thumbnail image
262
263
  if self.plugin.get_option_value("img_thumbnail"):
263
- img = self.plugin.window.core.web.get_main_image(url)
264
+ img = self.plugin.window.core.web.helpers.get_main_image(url)
264
265
  self.log("Summary generated (chars: {})".format(len(result)))
265
266
  # index webpage if auto-index is enabled
266
267
  self.index_url(url)
@@ -289,7 +290,11 @@ class WebSearch:
289
290
  url, \
290
291
  img
291
292
 
292
- def open_url(self, url: str, summarize_prompt: str = "") -> (str, str, str):
293
+ def open_url(
294
+ self,
295
+ url: str,
296
+ summarize_prompt: str = ""
297
+ ) -> Tuple[Optional[str], str, Optional[str]]:
293
298
  """
294
299
  Get result from specified URL
295
300
 
@@ -337,7 +342,7 @@ class WebSearch:
337
342
 
338
343
  # get thumbnail image
339
344
  if self.plugin.get_option_value("img_thumbnail"):
340
- img = self.plugin.window.core.web.get_main_image(url)
345
+ img = self.plugin.window.core.web.helpers.get_main_image(url)
341
346
 
342
347
  if result is not None and result != "":
343
348
  self.log("Summary generated (chars: {})".format(len(result)))
@@ -357,7 +362,10 @@ class WebSearch:
357
362
 
358
363
  return result, url, img
359
364
 
360
- def open_url_raw(self, url: str) -> (str, str, str):
365
+ def open_url_raw(
366
+ self,
367
+ url: str
368
+ ) -> Tuple[str, str, Optional[str]]:
361
369
  """
362
370
  Get raw content from specified URL
363
371
 
@@ -377,7 +385,7 @@ class WebSearch:
377
385
  # index webpage if auto-index is enabled
378
386
  if result:
379
387
  if self.plugin.get_option_value("img_thumbnail"):
380
- img = self.plugin.window.core.web.get_main_image(url)
388
+ img = self.plugin.window.core.web.helpers.get_main_image(url)
381
389
  self.index_url(url)
382
390
 
383
391
  # strip if too long
@@ -414,7 +422,7 @@ class WebSearch:
414
422
  except Exception as e:
415
423
  self.error(e)
416
424
 
417
- def error(self, err: any):
425
+ def error(self, err: Any):
418
426
  """
419
427
  Log error message
420
428