pygpt-net 2.4.37__py3-none-any.whl → 2.4.42__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 (340) hide show
  1. CHANGELOG.md +37 -0
  2. README.md +176 -182
  3. pygpt_net/CHANGELOG.txt +37 -0
  4. pygpt_net/__init__.py +3 -3
  5. pygpt_net/app.py +3 -1
  6. pygpt_net/controller/__init__.py +7 -3
  7. pygpt_net/controller/access/control.py +1 -1
  8. pygpt_net/controller/access/voice.py +11 -5
  9. pygpt_net/controller/agent/experts.py +11 -6
  10. pygpt_net/controller/agent/legacy.py +8 -6
  11. pygpt_net/controller/agent/llama.py +4 -2
  12. pygpt_net/controller/assistant/__init__.py +9 -4
  13. pygpt_net/controller/assistant/batch.py +38 -21
  14. pygpt_net/controller/assistant/editor.py +7 -6
  15. pygpt_net/controller/assistant/files.py +23 -7
  16. pygpt_net/controller/assistant/store.py +20 -7
  17. pygpt_net/controller/assistant/threads.py +34 -8
  18. pygpt_net/controller/attachment.py +29 -10
  19. pygpt_net/controller/audio/__init__.py +26 -5
  20. pygpt_net/controller/calendar/__init__.py +23 -4
  21. pygpt_net/controller/calendar/note.py +57 -11
  22. pygpt_net/controller/camera.py +4 -12
  23. pygpt_net/controller/chat/__init__.py +5 -3
  24. pygpt_net/controller/chat/attachment.py +34 -7
  25. pygpt_net/controller/chat/audio.py +2 -2
  26. pygpt_net/controller/chat/command.py +4 -2
  27. pygpt_net/controller/chat/common.py +11 -4
  28. pygpt_net/controller/chat/files.py +10 -3
  29. pygpt_net/controller/chat/image.py +17 -5
  30. pygpt_net/controller/chat/input.py +10 -7
  31. pygpt_net/controller/chat/output.py +21 -6
  32. pygpt_net/controller/chat/render.py +100 -21
  33. pygpt_net/controller/chat/response.py +34 -7
  34. pygpt_net/controller/chat/stream.py +4 -2
  35. pygpt_net/controller/chat/text.py +6 -4
  36. pygpt_net/controller/command.py +11 -3
  37. pygpt_net/controller/config/__init__.py +34 -6
  38. pygpt_net/controller/config/field/checkbox.py +7 -4
  39. pygpt_net/controller/config/field/cmd.py +7 -5
  40. pygpt_net/controller/config/field/combo.py +14 -6
  41. pygpt_net/controller/config/field/dictionary.py +14 -11
  42. pygpt_net/controller/config/field/input.py +9 -6
  43. pygpt_net/controller/config/field/slider.py +11 -8
  44. pygpt_net/controller/config/field/textarea.py +8 -5
  45. pygpt_net/controller/config/placeholder.py +66 -21
  46. pygpt_net/controller/ctx/__init__.py +138 -49
  47. pygpt_net/controller/ctx/common.py +15 -4
  48. pygpt_net/controller/ctx/extra.py +11 -3
  49. pygpt_net/controller/ctx/summarizer.py +24 -5
  50. pygpt_net/controller/debug/__init__.py +27 -6
  51. pygpt_net/controller/dialogs/confirm.py +34 -7
  52. pygpt_net/controller/dialogs/debug.py +4 -2
  53. pygpt_net/controller/dialogs/info.py +7 -2
  54. pygpt_net/controller/files.py +48 -10
  55. pygpt_net/controller/finder.py +11 -5
  56. pygpt_net/controller/idx/__init__.py +10 -3
  57. pygpt_net/controller/idx/common.py +4 -2
  58. pygpt_net/controller/idx/indexer.py +25 -17
  59. pygpt_net/controller/idx/settings.py +9 -3
  60. pygpt_net/controller/kernel/__init__.py +34 -8
  61. pygpt_net/controller/kernel/reply.py +12 -3
  62. pygpt_net/controller/kernel/stack.py +5 -3
  63. pygpt_net/controller/lang/custom.py +2 -7
  64. pygpt_net/controller/lang/mapping.py +5 -3
  65. pygpt_net/controller/layout.py +2 -2
  66. pygpt_net/controller/mode.py +16 -4
  67. pygpt_net/controller/model/__init__.py +14 -3
  68. pygpt_net/controller/model/editor.py +8 -3
  69. pygpt_net/controller/notepad.py +26 -12
  70. pygpt_net/controller/painter/capture.py +23 -4
  71. pygpt_net/controller/painter/common.py +9 -7
  72. pygpt_net/controller/plugins/__init__.py +19 -5
  73. pygpt_net/controller/plugins/presets.py +15 -6
  74. pygpt_net/controller/plugins/settings.py +9 -3
  75. pygpt_net/controller/presets/__init__.py +55 -16
  76. pygpt_net/controller/presets/editor.py +26 -10
  77. pygpt_net/controller/settings/__init__.py +3 -2
  78. pygpt_net/controller/settings/editor.py +29 -7
  79. pygpt_net/controller/settings/profile.py +22 -5
  80. pygpt_net/controller/theme/__init__.py +54 -12
  81. pygpt_net/controller/theme/common.py +24 -2
  82. pygpt_net/controller/theme/markdown.py +32 -16
  83. pygpt_net/controller/theme/menu.py +26 -5
  84. pygpt_net/controller/theme/nodes.py +2 -5
  85. pygpt_net/controller/tools/__init__.py +40 -2
  86. pygpt_net/controller/ui/__init__.py +4 -6
  87. pygpt_net/controller/ui/mode.py +16 -21
  88. pygpt_net/controller/ui/tabs.py +363 -65
  89. pygpt_net/core/access/actions.py +6 -4
  90. pygpt_net/core/access/shortcuts.py +4 -3
  91. pygpt_net/core/access/voice.py +6 -5
  92. pygpt_net/core/agents/legacy.py +4 -2
  93. pygpt_net/core/agents/memory.py +7 -2
  94. pygpt_net/core/agents/observer/evaluation.py +15 -7
  95. pygpt_net/core/agents/provider.py +9 -4
  96. pygpt_net/core/agents/runner.py +61 -15
  97. pygpt_net/core/agents/tools.py +23 -5
  98. pygpt_net/core/assistants/__init__.py +6 -4
  99. pygpt_net/core/assistants/files.py +35 -12
  100. pygpt_net/core/assistants/store.py +20 -10
  101. pygpt_net/core/attachments/__init__.py +54 -15
  102. pygpt_net/core/attachments/context.py +92 -29
  103. pygpt_net/core/audio/__init__.py +74 -3
  104. pygpt_net/core/audio/context.py +7 -2
  105. pygpt_net/core/audio/whisper.py +37 -0
  106. pygpt_net/core/bridge/__init__.py +22 -6
  107. pygpt_net/core/bridge/context.py +5 -3
  108. pygpt_net/core/bridge/worker.py +2 -2
  109. pygpt_net/core/calendar/__init__.py +57 -11
  110. pygpt_net/core/chain/__init__.py +8 -2
  111. pygpt_net/core/chain/chat.py +10 -8
  112. pygpt_net/core/chain/completion.py +10 -7
  113. pygpt_net/core/command.py +62 -17
  114. pygpt_net/core/ctx/__init__.py +260 -58
  115. pygpt_net/core/ctx/bag.py +25 -4
  116. pygpt_net/core/ctx/container.py +28 -17
  117. pygpt_net/core/ctx/idx.py +45 -8
  118. pygpt_net/core/ctx/output.py +95 -74
  119. pygpt_net/core/ctx/reply.py +5 -2
  120. pygpt_net/core/db/__init__.py +8 -7
  121. pygpt_net/core/db/viewer.py +17 -11
  122. pygpt_net/core/debug/__init__.py +10 -9
  123. pygpt_net/core/debug/events.py +22 -10
  124. pygpt_net/core/debug/tabs.py +9 -3
  125. pygpt_net/core/docker/__init__.py +11 -5
  126. pygpt_net/core/docker/builder.py +11 -3
  127. pygpt_net/core/events/app.py +5 -3
  128. pygpt_net/core/events/base.py +11 -5
  129. pygpt_net/core/events/control.py +5 -3
  130. pygpt_net/core/events/event.py +17 -7
  131. pygpt_net/core/events/kernel.py +5 -3
  132. pygpt_net/core/events/render.py +5 -3
  133. pygpt_net/core/experts/__init__.py +5 -4
  134. pygpt_net/core/filesystem/__init__.py +52 -34
  135. pygpt_net/core/filesystem/actions.py +8 -5
  136. pygpt_net/core/filesystem/editor.py +13 -3
  137. pygpt_net/core/filesystem/types.py +12 -7
  138. pygpt_net/core/filesystem/url.py +7 -3
  139. pygpt_net/core/history.py +3 -2
  140. pygpt_net/core/idx/__init__.py +48 -27
  141. pygpt_net/core/idx/chat.py +51 -17
  142. pygpt_net/core/idx/context.py +6 -2
  143. pygpt_net/core/idx/indexing.py +107 -42
  144. pygpt_net/core/idx/llm.py +11 -3
  145. pygpt_net/core/idx/metadata.py +13 -3
  146. pygpt_net/core/idx/types/ctx.py +32 -6
  147. pygpt_net/core/idx/types/external.py +41 -7
  148. pygpt_net/core/idx/types/files.py +31 -6
  149. pygpt_net/core/image.py +15 -4
  150. pygpt_net/core/installer.py +2 -4
  151. pygpt_net/core/llm/__init__.py +13 -3
  152. pygpt_net/core/locale.py +34 -8
  153. pygpt_net/core/models.py +63 -17
  154. pygpt_net/core/modes.py +11 -13
  155. pygpt_net/core/notepad.py +10 -5
  156. pygpt_net/core/plugins.py +31 -19
  157. pygpt_net/core/presets.py +37 -17
  158. pygpt_net/core/profile.py +21 -7
  159. pygpt_net/core/prompt/__init__.py +10 -3
  160. pygpt_net/core/prompt/custom.py +7 -6
  161. pygpt_net/core/prompt/template.py +9 -3
  162. pygpt_net/core/render/base.py +117 -22
  163. pygpt_net/core/render/markdown/body.py +27 -7
  164. pygpt_net/core/render/markdown/renderer.py +119 -22
  165. pygpt_net/core/render/plain/body.py +22 -5
  166. pygpt_net/core/render/plain/renderer.py +97 -21
  167. pygpt_net/core/render/web/body.py +75 -25
  168. pygpt_net/core/render/web/parser.py +3 -1
  169. pygpt_net/core/render/web/renderer.py +313 -63
  170. pygpt_net/core/settings.py +10 -5
  171. pygpt_net/core/tabs/__init__.py +290 -103
  172. pygpt_net/core/tabs/tab.py +26 -5
  173. pygpt_net/core/tokens.py +47 -12
  174. pygpt_net/core/updater/__init__.py +20 -7
  175. pygpt_net/core/vision/analyzer.py +29 -6
  176. pygpt_net/core/{web.py → web/__init__.py} +29 -7
  177. pygpt_net/core/web/helpers.py +237 -0
  178. pygpt_net/data/config/config.json +15 -4
  179. pygpt_net/data/config/models.json +3 -3
  180. pygpt_net/data/config/modes.json +3 -3
  181. pygpt_net/data/config/settings.json +55 -10
  182. pygpt_net/data/config/settings_section.json +3 -0
  183. pygpt_net/data/css/style.light.css +1 -0
  184. pygpt_net/data/css/{web.css → web-blocks.css} +162 -133
  185. pygpt_net/data/css/{web.light.css → web-blocks.light.css} +7 -0
  186. pygpt_net/data/css/web-chatgpt.css +350 -0
  187. pygpt_net/data/css/web-chatgpt.dark.css +64 -0
  188. pygpt_net/data/css/web-chatgpt.light.css +75 -0
  189. pygpt_net/data/css/web-chatgpt_wide.css +350 -0
  190. pygpt_net/data/css/web-chatgpt_wide.dark.css +64 -0
  191. pygpt_net/data/css/web-chatgpt_wide.light.css +75 -0
  192. pygpt_net/data/icons/split_screen.svg +1 -0
  193. pygpt_net/data/locale/locale.de.ini +12 -0
  194. pygpt_net/data/locale/locale.en.ini +18 -2
  195. pygpt_net/data/locale/locale.es.ini +12 -0
  196. pygpt_net/data/locale/locale.fr.ini +12 -0
  197. pygpt_net/data/locale/locale.it.ini +12 -0
  198. pygpt_net/data/locale/locale.pl.ini +12 -0
  199. pygpt_net/data/locale/locale.uk.ini +12 -0
  200. pygpt_net/data/locale/locale.zh.ini +12 -0
  201. pygpt_net/data/locale/plugin.cmd_web.de.ini +2 -0
  202. pygpt_net/data/locale/plugin.cmd_web.en.ini +22 -10
  203. pygpt_net/data/locale/plugin.cmd_web.es.ini +2 -0
  204. pygpt_net/data/locale/plugin.cmd_web.fr.ini +2 -0
  205. pygpt_net/data/locale/plugin.cmd_web.it.ini +2 -0
  206. pygpt_net/data/locale/plugin.cmd_web.pl.ini +2 -0
  207. pygpt_net/data/locale/plugin.cmd_web.uk.ini +2 -0
  208. pygpt_net/data/locale/plugin.cmd_web.zh.ini +2 -0
  209. pygpt_net/data/locale/plugin.mailer.en.ini +21 -0
  210. pygpt_net/icons.qrc +1 -0
  211. pygpt_net/icons_rc.py +165 -136
  212. pygpt_net/item/ctx.py +58 -25
  213. pygpt_net/plugin/agent/__init__.py +7 -2
  214. pygpt_net/plugin/audio_input/simple.py +21 -5
  215. pygpt_net/plugin/audio_output/__init__.py +9 -1
  216. pygpt_net/plugin/base/config.py +4 -2
  217. pygpt_net/plugin/base/plugin.py +75 -23
  218. pygpt_net/plugin/base/worker.py +42 -11
  219. pygpt_net/plugin/cmd_code_interpreter/__init__.py +39 -37
  220. pygpt_net/plugin/cmd_code_interpreter/runner.py +25 -12
  221. pygpt_net/plugin/cmd_history/config.py +2 -2
  222. pygpt_net/plugin/cmd_web/__init__.py +48 -9
  223. pygpt_net/plugin/cmd_web/config.py +135 -41
  224. pygpt_net/plugin/cmd_web/websearch.py +74 -33
  225. pygpt_net/plugin/cmd_web/worker.py +142 -13
  226. pygpt_net/plugin/idx_llama_index/config.py +3 -3
  227. pygpt_net/plugin/mailer/__init__.py +123 -0
  228. pygpt_net/plugin/mailer/config.py +149 -0
  229. pygpt_net/plugin/mailer/runner.py +285 -0
  230. pygpt_net/plugin/mailer/worker.py +123 -0
  231. pygpt_net/provider/agents/base.py +5 -2
  232. pygpt_net/provider/agents/openai.py +4 -2
  233. pygpt_net/provider/agents/openai_assistant.py +4 -2
  234. pygpt_net/provider/agents/planner.py +4 -2
  235. pygpt_net/provider/agents/react.py +4 -2
  236. pygpt_net/provider/audio_output/openai_tts.py +5 -11
  237. pygpt_net/provider/core/assistant/base.py +5 -3
  238. pygpt_net/provider/core/assistant/json_file.py +8 -5
  239. pygpt_net/provider/core/assistant_file/base.py +4 -3
  240. pygpt_net/provider/core/assistant_file/db_sqlite/__init__.py +4 -3
  241. pygpt_net/provider/core/assistant_file/db_sqlite/storage.py +3 -2
  242. pygpt_net/provider/core/assistant_store/base.py +6 -4
  243. pygpt_net/provider/core/assistant_store/db_sqlite/__init__.py +5 -4
  244. pygpt_net/provider/core/assistant_store/db_sqlite/storage.py +5 -3
  245. pygpt_net/provider/core/attachment/base.py +5 -3
  246. pygpt_net/provider/core/attachment/json_file.py +4 -3
  247. pygpt_net/provider/core/calendar/base.py +5 -3
  248. pygpt_net/provider/core/calendar/db_sqlite/__init__.py +6 -5
  249. pygpt_net/provider/core/calendar/db_sqlite/storage.py +5 -4
  250. pygpt_net/provider/core/config/base.py +8 -6
  251. pygpt_net/provider/core/config/json_file.py +9 -7
  252. pygpt_net/provider/core/config/patch.py +43 -1
  253. pygpt_net/provider/core/ctx/base.py +30 -25
  254. pygpt_net/provider/core/ctx/db_sqlite/__init__.py +59 -34
  255. pygpt_net/provider/core/ctx/db_sqlite/storage.py +62 -30
  256. pygpt_net/provider/core/ctx/db_sqlite/utils.py +11 -9
  257. pygpt_net/provider/core/index/base.py +129 -23
  258. pygpt_net/provider/core/index/db_sqlite/__init__.py +130 -23
  259. pygpt_net/provider/core/index/db_sqlite/storage.py +130 -23
  260. pygpt_net/provider/core/index/db_sqlite/utils.py +4 -2
  261. pygpt_net/provider/core/mode/base.py +5 -3
  262. pygpt_net/provider/core/mode/json_file.py +7 -6
  263. pygpt_net/provider/core/model/base.py +6 -4
  264. pygpt_net/provider/core/model/json_file.py +9 -7
  265. pygpt_net/provider/core/notepad/base.py +5 -3
  266. pygpt_net/provider/core/notepad/db_sqlite/__init__.py +5 -4
  267. pygpt_net/provider/core/notepad/db_sqlite/storage.py +4 -3
  268. pygpt_net/provider/core/plugin_preset/base.py +4 -2
  269. pygpt_net/provider/core/plugin_preset/json_file.py +5 -3
  270. pygpt_net/provider/core/preset/base.py +6 -4
  271. pygpt_net/provider/core/preset/json_file.py +9 -9
  272. pygpt_net/provider/core/prompt/base.py +6 -3
  273. pygpt_net/provider/core/prompt/json_file.py +11 -6
  274. pygpt_net/provider/gpt/assistants.py +21 -11
  275. pygpt_net/provider/gpt/audio.py +6 -5
  276. pygpt_net/provider/gpt/chat.py +10 -7
  277. pygpt_net/provider/gpt/completion.py +11 -5
  278. pygpt_net/provider/gpt/image.py +9 -2
  279. pygpt_net/provider/gpt/store.py +53 -18
  280. pygpt_net/provider/gpt/vision.py +17 -11
  281. pygpt_net/provider/llms/anthropic.py +7 -2
  282. pygpt_net/provider/llms/azure_openai.py +26 -5
  283. pygpt_net/provider/llms/base.py +47 -9
  284. pygpt_net/provider/llms/google.py +7 -2
  285. pygpt_net/provider/llms/hugging_face.py +13 -3
  286. pygpt_net/provider/llms/hugging_face_api.py +18 -4
  287. pygpt_net/provider/llms/local.py +7 -2
  288. pygpt_net/provider/llms/ollama.py +30 -6
  289. pygpt_net/provider/llms/openai.py +32 -6
  290. pygpt_net/provider/vector_stores/__init__.py +45 -14
  291. pygpt_net/provider/vector_stores/base.py +35 -8
  292. pygpt_net/provider/vector_stores/chroma.py +13 -3
  293. pygpt_net/provider/vector_stores/ctx_attachment.py +31 -12
  294. pygpt_net/provider/vector_stores/elasticsearch.py +12 -3
  295. pygpt_net/provider/vector_stores/pinecode.py +12 -3
  296. pygpt_net/provider/vector_stores/redis.py +12 -3
  297. pygpt_net/provider/vector_stores/simple.py +12 -3
  298. pygpt_net/provider/vector_stores/temp.py +16 -4
  299. pygpt_net/provider/web/base.py +10 -3
  300. pygpt_net/provider/web/google_custom_search.py +9 -3
  301. pygpt_net/provider/web/microsoft_bing.py +9 -3
  302. pygpt_net/tools/__init__.py +20 -4
  303. pygpt_net/tools/audio_transcriber/__init__.py +4 -3
  304. pygpt_net/tools/base.py +28 -7
  305. pygpt_net/tools/code_interpreter/__init__.py +177 -77
  306. pygpt_net/tools/code_interpreter/ui/dialogs.py +21 -103
  307. pygpt_net/tools/code_interpreter/ui/widgets.py +284 -9
  308. pygpt_net/tools/html_canvas/__init__.py +81 -25
  309. pygpt_net/tools/html_canvas/ui/dialogs.py +46 -62
  310. pygpt_net/tools/html_canvas/ui/widgets.py +96 -3
  311. pygpt_net/tools/image_viewer/__init__.py +10 -4
  312. pygpt_net/tools/indexer/__init__.py +8 -7
  313. pygpt_net/tools/media_player/__init__.py +4 -3
  314. pygpt_net/tools/text_editor/__init__.py +36 -10
  315. pygpt_net/ui/base/context_menu.py +2 -2
  316. pygpt_net/ui/layout/chat/input.py +10 -18
  317. pygpt_net/ui/layout/chat/output.py +27 -45
  318. pygpt_net/ui/layout/ctx/ctx_list.py +13 -4
  319. pygpt_net/ui/layout/toolbox/footer.py +18 -2
  320. pygpt_net/ui/main.py +2 -2
  321. pygpt_net/ui/menu/audio.py +12 -1
  322. pygpt_net/ui/menu/config.py +7 -11
  323. pygpt_net/ui/menu/debug.py +11 -1
  324. pygpt_net/ui/menu/theme.py +9 -2
  325. pygpt_net/ui/widget/filesystem/explorer.py +2 -2
  326. pygpt_net/ui/widget/lists/context.py +27 -5
  327. pygpt_net/ui/widget/tabs/Input.py +2 -2
  328. pygpt_net/ui/widget/tabs/body.py +2 -1
  329. pygpt_net/ui/widget/tabs/layout.py +195 -0
  330. pygpt_net/ui/widget/tabs/output.py +218 -55
  331. pygpt_net/ui/widget/textarea/html.py +11 -1
  332. pygpt_net/ui/widget/textarea/output.py +10 -1
  333. pygpt_net/ui/widget/textarea/search_input.py +4 -1
  334. pygpt_net/ui/widget/textarea/web.py +49 -9
  335. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.42.dist-info}/METADATA +177 -183
  336. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.42.dist-info}/RECORD +340 -325
  337. /pygpt_net/data/css/{web.dark.css → web-blocks.dark.css} +0 -0
  338. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.42.dist-info}/LICENSE +0 -0
  339. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.42.dist-info}/WHEEL +0 -0
  340. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.42.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.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.11.20 21: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,8 +36,11 @@ 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",
42
+ "web_extract_links",
43
+ "web_extract_images",
43
44
  ]
44
45
  self.order = 100
45
46
  self.use_locale = True
@@ -94,7 +95,7 @@ class Plugin(BasePlugin):
94
95
 
95
96
  :return: providers dict
96
97
  """
97
- return self.window.core.web.get_providers("search_engine")
98
+ return self.window.core.web.get_providers(self.window.core.web.PROVIDER_SEARCH_ENGINE)
98
99
 
99
100
  def get_provider_options(self) -> list:
100
101
  """Get provider options"""
@@ -269,26 +270,66 @@ class Plugin(BasePlugin):
269
270
 
270
271
  :param data: event data dict
271
272
  """
273
+ max_urls = self.get_option_value("max_open_urls")
274
+ is_summary = True
275
+ if self.get_option_value("raw"):
276
+ is_summary = False
277
+
272
278
  for option in self.allowed_cmds:
273
279
  if not self.has_cmd(option):
274
280
  continue
275
281
 
276
- # special case for web_index
277
282
  if option == "web_index":
278
283
  data['cmd'].append(self.prepare_idx_syntax()) # prepare params
279
284
  continue
280
285
  elif option == "web_index_query":
281
286
  data['cmd'].append(self.prepare_idx_query_syntax()) # prepare params
282
287
  continue
288
+ elif option == "web_url_open":
289
+ cmd = self.get_cmd(option)
290
+ try:
291
+ cmd["instruction"] = cmd["instruction"].format(
292
+ max_urls=max_urls,
293
+ )
294
+ if not is_summary:
295
+ for param in list(cmd["params"]):
296
+ if param["name"] == "summarize_prompt":
297
+ cmd["params"].remove(param)
298
+ data['cmd'].append(cmd)
299
+ continue
300
+ except Exception as e:
301
+ pass
302
+ elif option == "web_url_raw":
303
+ cmd = self.get_cmd(option)
304
+ try:
305
+ cmd["instruction"] = cmd["instruction"].format(
306
+ max_urls=max_urls,
307
+ )
308
+ if not is_summary:
309
+ for param in list(cmd["params"]):
310
+ if param["name"] == "summarize_prompt":
311
+ cmd["params"].remove(param)
312
+ data['cmd'].append(cmd)
313
+ continue
314
+ except Exception as e:
315
+ pass
283
316
  elif option == "web_search":
284
317
  max_pages = self.get_option_value("num_pages")
285
318
  cmd = self.get_cmd(option)
286
319
  try:
287
- cmd["instruction"] = cmd["instruction"].format(max_pages=max_pages)
320
+ cmd["instruction"] = cmd["instruction"].format(
321
+ max_pages=max_pages,
322
+ max_urls=max_urls,
323
+ )
324
+ if not is_summary:
325
+ for param in list(cmd["params"]):
326
+ if param["name"] == "summarize_prompt":
327
+ cmd["params"].remove(param)
288
328
  data['cmd'].append(cmd)
289
329
  continue
290
330
  except Exception as e:
291
331
  pass
332
+
292
333
  data['cmd'].append(self.get_cmd(option)) # append command
293
334
 
294
335
  def cmd(self, ctx: CtxItem, cmds: list):
@@ -389,8 +430,6 @@ class Plugin(BasePlugin):
389
430
  req,
390
431
  timeout=self.get_option_value('timeout'),
391
432
  ).read()
392
- except HTTPError as e:
393
- data = str(e)
394
433
  except Exception as e:
395
- raise e
434
+ data = str(e)
396
435
  return data
@@ -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.15 01:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from pygpt_net.plugin.base.config import BaseConfig, BasePlugin
@@ -41,6 +41,15 @@ class Config(BaseConfig):
41
41
  min=1,
42
42
  max=None,
43
43
  )
44
+ plugin.add_option(
45
+ "max_open_urls",
46
+ type="int",
47
+ value=1,
48
+ label="Number of max URLs to open at once",
49
+ description="Number of max URLs to open at once",
50
+ min=1,
51
+ max=None,
52
+ )
44
53
  plugin.add_option(
45
54
  "max_page_content_length",
46
55
  type="int",
@@ -59,6 +68,14 @@ class Config(BaseConfig):
59
68
  min=1,
60
69
  max=None,
61
70
  )
71
+ plugin.add_option(
72
+ "raw",
73
+ type="bool",
74
+ value=True,
75
+ label="Use raw content (without summarization)",
76
+ description="Return raw content from web search instead of summarized content",
77
+ tooltip="Use raw content for search",
78
+ )
62
79
  plugin.add_option(
63
80
  "disable_ssl",
64
81
  type="bool",
@@ -67,6 +84,14 @@ class Config(BaseConfig):
67
84
  description="Disables SSL verification when crawling web pages",
68
85
  tooltip="Disable SSL verify",
69
86
  )
87
+ plugin.add_option(
88
+ "img_thumbnail",
89
+ type="bool",
90
+ value=True,
91
+ label="Show thumbnail images",
92
+ description="Enable fetching thumbnails from opened websites",
93
+ tooltip="Enable fetching thumbnails from opened websites",
94
+ )
70
95
  plugin.add_option(
71
96
  "timeout",
72
97
  type="int",
@@ -86,7 +111,7 @@ class Config(BaseConfig):
86
111
  plugin.add_option(
87
112
  "max_result_length",
88
113
  type="int",
89
- value=1500,
114
+ value=50000,
90
115
  label="Max result length",
91
116
  description="Max length of summarized result (characters)",
92
117
  min=0,
@@ -104,10 +129,10 @@ class Config(BaseConfig):
104
129
  plugin.add_option(
105
130
  "model_tmp_query",
106
131
  type="combo",
107
- value="gpt-3.5-turbo",
132
+ value="gpt-4o-mini",
108
133
  label="Model for query in-memory index",
109
134
  description="Model used for query in-memory index for `web_index_query` command, "
110
- "default: gpt-3.5-turbo",
135
+ "default: gpt-4o-mini",
111
136
  tooltip="Query model",
112
137
  use="models",
113
138
  tab="indexing",
@@ -125,19 +150,21 @@ class Config(BaseConfig):
125
150
  )
126
151
  plugin.add_option(
127
152
  "idx",
128
- type="text",
153
+ type="combo",
129
154
  value="base",
130
155
  label="Index to use",
131
156
  description="ID of index to use for web page indexing (persistent index)",
132
157
  tooltip="Index name",
158
+ use="idx",
133
159
  tab="indexing",
134
160
  )
135
161
  plugin.add_option(
136
162
  "summary_model",
137
- type="text",
138
- value="gpt-3.5-turbo-1106",
163
+ type="combo",
164
+ value="gpt-4o-mini",
139
165
  label="Model used for web page summarize",
140
- 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",
167
+ use="models",
141
168
  advanced=True,
142
169
  )
143
170
  plugin.add_option(
@@ -163,12 +190,40 @@ class Config(BaseConfig):
163
190
  )
164
191
 
165
192
  # commands
193
+ plugin.add_cmd(
194
+ "web_url_open",
195
+ instruction="read and get text content from ANY website URL. Always open a max of {max_urls} URLs at a time.",
196
+ params=[
197
+ {
198
+ "name": "url",
199
+ "type": "str",
200
+ "description": "URL to website",
201
+ "required": True,
202
+ },
203
+ ],
204
+ enabled=True,
205
+ description="If enabled, model will be able to open URL and read text content from it",
206
+ )
207
+ plugin.add_cmd(
208
+ "web_url_raw",
209
+ instruction="read and get raw HTML body from ANY website URL. Always open a max of {max_urls} URLs at a time.",
210
+ params=[
211
+ {
212
+ "name": "url",
213
+ "type": "str",
214
+ "description": "URL to website",
215
+ "required": True,
216
+ },
217
+ ],
218
+ enabled=True,
219
+ description="If enabled, model will be able to open specified URL and get raw HTML body from it",
220
+ )
166
221
  plugin.add_cmd(
167
222
  "web_search",
168
- instruction="search the Web for more info, prepare a query for the search engine itself, start from page 1. "
169
- "If no results, then try the next page. "
170
- "Use a custom summary prompt if necessary, otherwise, a default summary will be used. "
171
- "Max pages: {max_pages}",
223
+ instruction="search the Web for list of URLs, prepare search query itself, list of "
224
+ "URLs will be returned, 10 links per page max. After receiving the list of URLs, "
225
+ "choose the best matched URLs and use the `web_url_open` command to read the content. "
226
+ "Always open a max of {max_urls} URLs at a time.",
172
227
  params=[
173
228
  {
174
229
  "name": "query",
@@ -183,39 +238,85 @@ class Config(BaseConfig):
183
238
  "required": False,
184
239
  },
185
240
  {
186
- "name": "summarize_prompt",
187
- "type": "str",
188
- "description": "summary prompt",
241
+ "name": "num_links",
242
+ "type": "int",
243
+ "description": "links per page",
189
244
  "required": False,
190
245
  },
191
246
  ],
192
247
  enabled=True,
193
- description="If enabled, model will be able to search the Web",
248
+ description="If enabled, model will be able to search the Web and get founded URLs list",
194
249
  )
195
250
  plugin.add_cmd(
196
- "web_url_open",
197
- instruction="read and get summarized content from ANY website URL. Use a custom summary prompt if necessary, "
198
- "otherwise default summary will be used",
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.",
199
258
  params=[
200
259
  {
201
260
  "name": "url",
202
261
  "type": "str",
203
- "description": "URL to website",
262
+ "description": "URL to website or API endpoint",
204
263
  "required": True,
205
264
  },
206
265
  {
207
- "name": "summarize_prompt",
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",
208
285
  "type": "str",
209
- "description": "summary prompt",
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",
210
311
  "required": False,
211
312
  },
212
313
  ],
213
314
  enabled=True,
214
- description="If enabled, model will be able to open URL and summarize content",
315
+ description="If enabled, model will be able to send any HTTP request to specified URL or API endpoint",
215
316
  )
216
317
  plugin.add_cmd(
217
- "web_url_raw",
218
- instruction="read and get raw HTML/txt content (not summarized) from ANY website URL",
318
+ "web_extract_links",
319
+ instruction="open webpage and get list of all links from it",
219
320
  params=[
220
321
  {
221
322
  "name": "url",
@@ -225,34 +326,27 @@ class Config(BaseConfig):
225
326
  },
226
327
  ],
227
328
  enabled=True,
228
- description="If enabled, model will be able to open specified URL and get raw content",
329
+ description="If enabled, model will be able to open URL and get list of all links from it",
229
330
  )
230
331
  plugin.add_cmd(
231
- "web_urls",
232
- instruction="search the Web for list of URLs, prepare search query itself, list of "
233
- "URLs will be returned, 10 links per page max.",
332
+ "web_extract_images",
333
+ instruction="open webpage and get list of all images from it",
234
334
  params=[
235
335
  {
236
- "name": "query",
336
+ "name": "url",
237
337
  "type": "str",
238
- "description": "search query",
338
+ "description": "URL to website",
239
339
  "required": True,
240
340
  },
241
341
  {
242
- "name": "page",
243
- "type": "int",
244
- "description": "page number",
245
- "required": False,
246
- },
247
- {
248
- "name": "num_links",
249
- "type": "int",
250
- "description": "links per page",
342
+ "name": "download",
343
+ "type": "bool",
344
+ "description": "Download images to disk if user wants to, default: False",
251
345
  "required": False,
252
346
  },
253
347
  ],
254
348
  enabled=True,
255
- description="If enabled, model will be able to search the Web and get founded URLs list",
349
+ description="If enabled, model will be able to open URL and get list of all images from it",
256
350
  )
257
351
  plugin.add_cmd(
258
352
  "web_index",
@@ -6,10 +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.21 02: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
14
+
13
15
  from bs4 import BeautifulSoup
14
16
 
15
17
  from pygpt_net.core.events import KernelEvent
@@ -31,7 +33,7 @@ class WebSearch:
31
33
  query: str,
32
34
  num: int,
33
35
  offset: int = 1
34
- ) -> list:
36
+ ) -> List[str]:
35
37
  """
36
38
  Execute search query and return list of urls
37
39
 
@@ -42,7 +44,7 @@ class WebSearch:
42
44
  """
43
45
  return self.plugin.get_provider().search(query, num, offset)
44
46
 
45
- def get_urls(self, query: str) -> list:
47
+ def get_urls(self, query: str) -> List[str]:
46
48
  """
47
49
  Search the web and returns URLs
48
50
 
@@ -103,7 +105,7 @@ class WebSearch:
103
105
  self,
104
106
  text: str,
105
107
  chunk_size: int
106
- ) -> list:
108
+ ) -> List[str]:
107
109
  """
108
110
  Split text into chunks
109
111
 
@@ -119,7 +121,7 @@ class WebSearch:
119
121
  self,
120
122
  chunks: list,
121
123
  query: str,
122
- summarize_prompt: str = None
124
+ summarize_prompt: Optional[str] = None
123
125
  ) -> str:
124
126
  """
125
127
  Get summarized text from chunks
@@ -194,19 +196,22 @@ class WebSearch:
194
196
  query: str,
195
197
  page_no: int = 1,
196
198
  summarize_prompt: str = ""
197
- ) -> (str, int, int, str):
199
+ ) -> Tuple[str, int, int, str, str]:
198
200
  """
199
201
  Get result from search query
200
202
 
201
203
  :param query: query to search
202
204
  :param page_no: page number
203
205
  :param summarize_prompt: custom prompt
204
- :return: result, total_found, current, url
206
+ :return: result, total_found, current, url, thumb image
205
207
  """
206
208
  self.log("Using web query: " + query)
207
209
  urls = self.get_urls(query)
208
210
 
209
211
  # get options
212
+ is_summary = True
213
+ if self.plugin.get_option_value("raw"):
214
+ is_summary = False
210
215
  max_per_page = int(self.plugin.get_option_value("max_page_content_length"))
211
216
  chunk_size = int(self.plugin.get_option_value("chunk_size"))
212
217
  max_result_size = int(self.plugin.get_option_value("max_result_length"))
@@ -216,6 +221,7 @@ class WebSearch:
216
221
  i = 1
217
222
  current = 1
218
223
  url = ""
224
+ img = None
219
225
  for url in urls:
220
226
  if url is None or url == "":
221
227
  continue
@@ -236,19 +242,27 @@ class WebSearch:
236
242
  if 0 < max_per_page < len(content):
237
243
  content = content[:max_per_page]
238
244
 
239
- chunks = self.to_chunks(content, chunk_size) # it returns list of chunks
240
- self.debug(
241
- "Plugin: cmd_web: URL: {}".format(url)
242
- )
243
- result = self.get_summary(
244
- chunks,
245
- str(query),
246
- summarize_prompt,
247
- )
245
+ # get summary
246
+ if is_summary:
247
+ chunks = self.to_chunks(content, chunk_size) # it returns list of chunks
248
+ self.debug(
249
+ "Plugin: cmd_web: URL: {}".format(url)
250
+ )
251
+ result = self.get_summary(
252
+ chunks,
253
+ str(query),
254
+ summarize_prompt,
255
+ )
256
+ else:
257
+ # no summary
258
+ result = str(content)
259
+
248
260
  # if result then stop
249
261
  if result is not None and result != "":
262
+ # get thumbnail image
263
+ if self.plugin.get_option_value("img_thumbnail"):
264
+ img = self.plugin.window.core.web.helpers.get_main_image(url)
250
265
  self.log("Summary generated (chars: {})".format(len(result)))
251
-
252
266
  # index webpage if auto-index is enabled
253
267
  self.index_url(url)
254
268
  break
@@ -262,7 +276,7 @@ class WebSearch:
262
276
  "Plugin: cmd_web: summary length: {}".format(len(result))
263
277
  )
264
278
 
265
- if len(result) > max_result_size:
279
+ if 0 < max_result_size < len(result):
266
280
  result = result[:max_result_size]
267
281
 
268
282
  self.debug(
@@ -273,25 +287,37 @@ class WebSearch:
273
287
  result, \
274
288
  total_found, \
275
289
  current, \
276
- url
290
+ url, \
291
+ img
277
292
 
278
- def open_url(self, url: str, summarize_prompt: str = "") -> (str, str):
293
+ def open_url(
294
+ self,
295
+ url: str,
296
+ summarize_prompt: str = ""
297
+ ) -> Tuple[Optional[str], str, Optional[str]]:
279
298
  """
280
299
  Get result from specified URL
281
300
 
282
301
  :param url: URL to visit
283
302
  :param summarize_prompt: custom prompt
284
- :return: result, url
303
+ :return: result, url, thumb image
285
304
  """
286
305
  self.log("Using URL: " + url)
287
-
288
306
  # get options
307
+ is_summary = True
308
+ if self.plugin.get_option_value("raw"):
309
+ is_summary = False
289
310
  max_per_page = int(self.plugin.get_option_value("max_page_content_length"))
290
311
  chunk_size = int(self.plugin.get_option_value("chunk_size"))
291
312
  max_result_size = int(self.plugin.get_option_value("max_result_length"))
292
313
 
314
+ img = None
293
315
  self.log("URL: " + url)
294
316
  content = self.query_url(url)
317
+
318
+ if content is None:
319
+ return None, url, img
320
+
295
321
  self.log("Content found (chars: {}). Please wait...".format(len(content)))
296
322
 
297
323
  # index webpage if auto-index is enabled
@@ -300,14 +326,23 @@ class WebSearch:
300
326
 
301
327
  if 0 < max_per_page < len(content):
302
328
  content = content[:max_per_page]
303
- chunks = self.to_chunks(
304
- content,
305
- chunk_size,
306
- ) # it returns list of chunks
307
329
 
308
330
  self.debug("Plugin: cmd_web: URL: {}".format(url)) # log
309
331
 
310
- result = self.get_summary(chunks, "", summarize_prompt)
332
+ # get summary
333
+ if is_summary:
334
+ chunks = self.to_chunks(
335
+ content,
336
+ chunk_size,
337
+ ) # it returns list of chunks
338
+ result = self.get_summary(chunks, "", summarize_prompt)
339
+ else:
340
+ # no summary
341
+ result = str(content)
342
+
343
+ # get thumbnail image
344
+ if self.plugin.get_option_value("img_thumbnail"):
345
+ img = self.plugin.window.core.web.helpers.get_main_image(url)
311
346
 
312
347
  if result is not None and result != "":
313
348
  self.log("Summary generated (chars: {})".format(len(result)))
@@ -318,21 +353,24 @@ class WebSearch:
318
353
  "Plugin: cmd_web: summary length: {}".format(len(result))
319
354
  )
320
355
 
321
- if len(result) > max_result_size:
356
+ if 0 < max_result_size < len(result):
322
357
  result = result[:max_result_size]
323
358
 
324
359
  self.debug(
325
360
  "Plugin: cmd_web: result length: {}".format(len(result))
326
361
  )
327
362
 
328
- return result, url
363
+ return result, url, img
329
364
 
330
- def open_url_raw(self, url: str) -> (str, str):
365
+ def open_url_raw(
366
+ self,
367
+ url: str
368
+ ) -> Tuple[str, str, Optional[str]]:
331
369
  """
332
370
  Get raw content from specified URL
333
371
 
334
372
  :param url: URL to visit
335
- :return: result, url
373
+ :return: result, url, thumb image
336
374
  """
337
375
  self.log("Using URL: " + url)
338
376
 
@@ -343,8 +381,11 @@ class WebSearch:
343
381
  result = self.query_url(url)
344
382
  self.log("Content found (chars: {}). Please wait...".format(len(result)))
345
383
 
384
+ img = None
346
385
  # index webpage if auto-index is enabled
347
386
  if result:
387
+ if self.plugin.get_option_value("img_thumbnail"):
388
+ img = self.plugin.window.core.web.helpers.get_main_image(url)
348
389
  self.index_url(url)
349
390
 
350
391
  # strip if too long
@@ -355,7 +396,7 @@ class WebSearch:
355
396
  "Plugin: cmd_web: result length: {}".format(len(result))
356
397
  )
357
398
 
358
- return result, url
399
+ return result, url, img
359
400
 
360
401
  def index_url(self, url: str):
361
402
  """
@@ -381,7 +422,7 @@ class WebSearch:
381
422
  except Exception as e:
382
423
  self.error(e)
383
424
 
384
- def error(self, err: any):
425
+ def error(self, err: Any):
385
426
  """
386
427
  Log error message
387
428