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,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.11.08 17:00:00 #
9
+ # Updated Date: 2024.12.14 17:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from datetime import datetime
13
+ from typing import Dict, Any
13
14
 
14
15
 
15
16
  class Tab:
@@ -21,6 +22,7 @@ class Tab:
21
22
  TAB_FILES = 2
22
23
  TAB_TOOL_PAINTER = 3
23
24
  TAB_TOOL_CALENDAR = 4
25
+ TAB_TOOL = 100
24
26
 
25
27
  def __init__(self):
26
28
  """
@@ -34,15 +36,23 @@ class Tab:
34
36
  self.icon = None
35
37
  self.tooltip = None
36
38
  self.data_id = None
37
- self.reference = None
38
39
  self.new_idx = None
39
40
  self.custom_name = False
41
+ self.child = None
42
+ self.parent = None
43
+ self.column_idx = 0
44
+ self.tool_id = None
40
45
 
41
46
  dt = datetime.now()
42
47
  self.created_at = dt
43
48
  self.updated_at = dt
44
49
 
45
- def to_dict(self):
50
+ def to_dict(self) -> Dict[str, Any]:
51
+ """
52
+ Convert to dict
53
+
54
+ :return: dict
55
+ """
46
56
  return {
47
57
  "uuid": str(self.uuid),
48
58
  "pid": self.pid,
@@ -52,9 +62,20 @@ class Tab:
52
62
  "icon": self.icon,
53
63
  "tooltip": self.tooltip,
54
64
  "data_id": self.data_id,
55
- "reference": str(self.reference),
65
+ "child": str(self.child), # child widget
66
+ "parent": str(self.parent), # parent column
56
67
  "custom_name": self.custom_name,
57
68
  "custom_idx": self.new_idx,
58
69
  "created_at": str(self.created_at),
59
70
  "updated_at": str(self.updated_at),
60
- }
71
+ "column_idx": self.column_idx,
72
+ "tool_id": self.tool_id,
73
+ }
74
+
75
+ def __str__(self) -> str:
76
+ """
77
+ String representation
78
+
79
+ :return: str
80
+ """
81
+ return str(self.to_dict())
pygpt_net/core/tokens.py CHANGED
@@ -6,11 +6,16 @@
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 22:00:00 #
10
10
  # ================================================== #
11
11
 
12
+ from typing import Tuple, List
13
+
12
14
  import tiktoken
13
15
 
16
+ from langchain_core.messages import ChatMessage as ChatMessageLangchain
17
+ from llama_index.core.base.llms.types import ChatMessage as ChatMessageLlama
18
+
14
19
  from pygpt_net.core.types import (
15
20
  MODE_AGENT,
16
21
  MODE_AGENT_LLAMA,
@@ -37,7 +42,6 @@ CHAT_MODES = [
37
42
  MODE_AUDIO,
38
43
  ]
39
44
 
40
-
41
45
  class Tokens:
42
46
  def __init__(self, window=None):
43
47
  """
@@ -48,7 +52,10 @@ class Tokens:
48
52
  self.window = window
49
53
 
50
54
  @staticmethod
51
- def from_str(string: str, model: str = "gpt-4") -> int:
55
+ def from_str(
56
+ string: str,
57
+ model: str = "gpt-4"
58
+ ) -> int:
52
59
  """
53
60
  Return number of tokens from string
54
61
 
@@ -91,7 +98,11 @@ class Tokens:
91
98
  return 3
92
99
 
93
100
  @staticmethod
94
- def from_prompt(text: str, name: str, model: str = "gpt-4") -> int:
101
+ def from_prompt(
102
+ text: str,
103
+ name: str,
104
+ model: str = "gpt-4"
105
+ ) -> int:
95
106
  """
96
107
  Return number of tokens from prompt
97
108
 
@@ -116,7 +127,10 @@ class Tokens:
116
127
  return num
117
128
 
118
129
  @staticmethod
119
- def from_text(text: str, model: str = "gpt-4") -> int:
130
+ def from_text(
131
+ text: str,
132
+ model: str = "gpt-4"
133
+ ) -> int:
120
134
  """
121
135
  Return number of tokens from text, without any extra tokens
122
136
 
@@ -138,7 +152,10 @@ class Tokens:
138
152
  return num
139
153
 
140
154
  @staticmethod
141
- def from_messages(messages: list, model: str = "gpt-4") -> int:
155
+ def from_messages(
156
+ messages: List[dict],
157
+ model: str = "gpt-4"
158
+ ) -> int:
142
159
  """
143
160
  Return number of tokens from messages list
144
161
 
@@ -166,7 +183,10 @@ class Tokens:
166
183
  return num
167
184
 
168
185
  @staticmethod
169
- def from_langchain_messages(messages: list, model: str = "gpt-4") -> int:
186
+ def from_langchain_messages(
187
+ messages: List[ChatMessageLangchain],
188
+ model: str = "gpt-4"
189
+ ) -> int:
170
190
  """
171
191
  Return number of tokens from prompt
172
192
 
@@ -183,7 +203,11 @@ class Tokens:
183
203
  return num
184
204
 
185
205
  @staticmethod
186
- def from_llama_messages(query: str, messages: list, model: str = "gpt-4") -> int:
206
+ def from_llama_messages(
207
+ query: str,
208
+ messages: List[ChatMessageLlama],
209
+ model: str = "gpt-4"
210
+ ) -> int:
187
211
  """
188
212
  Return number of tokens from prompt
189
213
 
@@ -202,7 +226,11 @@ class Tokens:
202
226
  return num
203
227
 
204
228
  @staticmethod
205
- def from_ctx(ctx: CtxItem, mode: str = MODE_CHAT, model: str = "gpt-4") -> int:
229
+ def from_ctx(
230
+ ctx: CtxItem,
231
+ mode: str = MODE_CHAT,
232
+ model: str = "gpt-4"
233
+ ) -> int:
206
234
  """
207
235
  Return number of tokens from context ctx
208
236
 
@@ -280,7 +308,10 @@ class Tokens:
280
308
 
281
309
  return num
282
310
 
283
- def get_current(self, input_prompt: str) -> (int, int, int, int, int, int, int, int, int):
311
+ def get_current(
312
+ self,
313
+ input_prompt: str
314
+ ) -> Tuple[int, int, int, int, int, int, int, int, int]:
284
315
  """
285
316
  Return current number of used tokens
286
317
 
@@ -364,7 +395,11 @@ class Tokens:
364
395
  return input_tokens, system_tokens, extra_tokens, ctx_tokens, ctx_len, ctx_len_all, \
365
396
  sum_tokens, max_current, threshold
366
397
 
367
- def from_user(self, system_prompt: str, input_prompt: str) -> int:
398
+ def from_user(
399
+ self,
400
+ system_prompt: str,
401
+ input_prompt: str
402
+ ) -> int:
368
403
  """
369
404
  Count per-user used tokens
370
405
 
@@ -390,7 +425,7 @@ class Tokens:
390
425
  return tokens
391
426
 
392
427
  @staticmethod
393
- def get_config(model: str) -> (str, int, int):
428
+ def get_config(model: str) -> Tuple[str, int, int]:
394
429
  """
395
430
  Return tokens config values
396
431
 
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.11.15 02:00:00 #
9
+ # Updated Date: 2024.12.14 08:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import copy
@@ -15,6 +15,7 @@ import shutil
15
15
  import json
16
16
  import ssl
17
17
  import time
18
+ from typing import Tuple
18
19
 
19
20
  from urllib.request import urlopen, Request
20
21
 
@@ -134,7 +135,11 @@ class Updater:
134
135
  if self.window.core.notepad.patch(version):
135
136
  print("Migrated notepad. [OK]")
136
137
 
137
- def patch_dir(self, dir_name: str = "", force: bool = False):
138
+ def patch_dir(
139
+ self,
140
+ dir_name: str = "",
141
+ force: bool = False
142
+ ):
138
143
  """
139
144
  Patch directory (replace all files)
140
145
 
@@ -154,7 +159,11 @@ class Updater:
154
159
  except Exception as e:
155
160
  self.window.core.debug.log(e)
156
161
 
157
- def patch_file(self, filename: str = "", force: bool = False):
162
+ def patch_file(
163
+ self,
164
+ filename: str = "",
165
+ force: bool = False
166
+ ):
158
167
  """
159
168
  Patch file
160
169
 
@@ -175,7 +184,11 @@ class Updater:
175
184
  except Exception as e:
176
185
  self.window.core.debug.log(e)
177
186
 
178
- def patch_css(self, filename: str = "", force: bool = False):
187
+ def patch_css(
188
+ self,
189
+ filename: str = "",
190
+ force: bool = False
191
+ ):
179
192
  """
180
193
  Patch css file
181
194
 
@@ -212,7 +225,7 @@ class Updater:
212
225
  """
213
226
  return self.window.meta['website'] + "/api/version?v=" + str(self.window.meta['version'])
214
227
 
215
- def get_thanks(self) -> (str, str, str):
228
+ def get_thanks(self) -> Tuple[str, str, str]:
216
229
  """
217
230
  Get contributors, donates and sponsors
218
231
 
@@ -237,7 +250,7 @@ class Updater:
237
250
 
238
251
  return self.thanks
239
252
 
240
- def get_fetch_thanks(self) -> (str, str, str):
253
+ def get_fetch_thanks(self) -> Tuple[str, str, str]:
241
254
  """
242
255
  Get contributors, donates and sponsors
243
256
 
@@ -247,7 +260,7 @@ class Updater:
247
260
  return self.get_thanks()
248
261
  return self.thanks
249
262
 
250
- def check_silent(self) -> (bool, str, str, str, str, str):
263
+ def check_silent(self) -> Tuple[bool, str, str, str, str, str]:
251
264
  """
252
265
  Check version in background
253
266
 
@@ -6,8 +6,9 @@
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 00:00:00 #
10
10
  # ================================================== #
11
+
11
12
  import os
12
13
 
13
14
  from pygpt_net.core.bridge.context import BridgeContext
@@ -24,7 +25,12 @@ class Analyzer:
24
25
  """
25
26
  self.window = window
26
27
 
27
- def send(self, ctx: CtxItem, prompt: str, files: dict) -> str:
28
+ def send(
29
+ self,
30
+ ctx: CtxItem,
31
+ prompt: str,
32
+ files: dict
33
+ ) -> str:
28
34
  """
29
35
  Send text from user input (called from UI)
30
36
 
@@ -56,7 +62,11 @@ class Analyzer:
56
62
  self.window.controller.attachment.unlock()
57
63
  return output
58
64
 
59
- def from_screenshot(self, ctx: CtxItem, prompt: str) -> str:
65
+ def from_screenshot(
66
+ self,
67
+ ctx: CtxItem,
68
+ prompt: str
69
+ ) -> str:
60
70
  """
61
71
  Image analysis from screenshot
62
72
 
@@ -75,7 +85,11 @@ class Analyzer:
75
85
  }
76
86
  return self.send(ctx, prompt, files)
77
87
 
78
- def from_camera(self, ctx: CtxItem, prompt: str) -> str:
88
+ def from_camera(
89
+ self,
90
+ ctx: CtxItem,
91
+ prompt: str
92
+ ) -> str:
79
93
  """
80
94
  Image analysis from camera
81
95
 
@@ -94,7 +108,12 @@ class Analyzer:
94
108
  else:
95
109
  return "FAILED: There was a problem with capturing the image."
96
110
 
97
- def from_path(self, ctx: CtxItem, prompt: str, path: str) -> str:
111
+ def from_path(
112
+ self,
113
+ ctx: CtxItem,
114
+ prompt: str,
115
+ path: str
116
+ ) -> str:
98
117
  """
99
118
  Image analysis from path
100
119
 
@@ -116,7 +135,11 @@ class Analyzer:
116
135
  }
117
136
  return self.send(ctx, prompt, files)
118
137
 
119
- def from_current_attachments(self, ctx: CtxItem, prompt: str) -> str:
138
+ def from_current_attachments(
139
+ self,
140
+ ctx: CtxItem,
141
+ prompt: str
142
+ ) -> str:
120
143
  """
121
144
  Image analysis from current attachments
122
145
 
@@ -6,25 +6,37 @@
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.02.24 00:00:00 #
9
+ # Updated Date: 2024.12.14 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
+ from typing import Optional, List, Dict
13
+
12
14
  from pygpt_net.provider.web.base import BaseProvider
13
15
 
16
+ from .helpers import Helpers
17
+
14
18
 
15
19
  class Web:
20
+
21
+ PROVIDER_SEARCH_ENGINE = "search_engine"
22
+
16
23
  def __init__(self, window=None):
17
24
  """
18
- Web access core
25
+ Web core
19
26
 
20
27
  :param window: Window instance
21
28
  """
22
29
  self.window = window
30
+ self.helpers = Helpers(window)
23
31
  self.providers = {
24
- "search_engine": {},
32
+ self.PROVIDER_SEARCH_ENGINE: {},
25
33
  }
26
34
 
27
- def is_registered(self, id: str, type: str = "search_engine") -> bool:
35
+ def is_registered(
36
+ self,
37
+ id: str,
38
+ type: str = PROVIDER_SEARCH_ENGINE
39
+ ) -> bool:
28
40
  """
29
41
  Check if provider is registered
30
42
 
@@ -36,7 +48,10 @@ class Web:
36
48
  return id in self.providers[type]
37
49
  return False
38
50
 
39
- def get_providers(self, type: str = "search_engine") -> dict:
51
+ def get_providers(
52
+ self,
53
+ type: str = PROVIDER_SEARCH_ENGINE
54
+ ) -> Dict[str, BaseProvider]:
40
55
  """
41
56
  Get all providers
42
57
 
@@ -47,7 +62,10 @@ class Web:
47
62
  return self.providers[type]
48
63
  return {}
49
64
 
50
- def get_ids(self, type: str = "search_engine") -> list:
65
+ def get_ids(
66
+ self,
67
+ type: str = PROVIDER_SEARCH_ENGINE
68
+ ) -> List[str]:
51
69
  """
52
70
  Get all providers ids
53
71
 
@@ -58,7 +76,11 @@ class Web:
58
76
  return list(self.providers[type].keys())
59
77
  return []
60
78
 
61
- def get(self, id: str, type: str = "search_engine") -> BaseProvider or None:
79
+ def get(
80
+ self,
81
+ id: str,
82
+ type: str = PROVIDER_SEARCH_ENGINE
83
+ ) -> Optional[BaseProvider]:
62
84
  """
63
85
  Get provider instance
64
86
 
@@ -0,0 +1,237 @@
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.15 01:00:00 #
10
+ # ================================================== #
11
+
12
+ import os
13
+ import uuid
14
+ from typing import Optional, List, Dict, Tuple, Union
15
+
16
+ import requests
17
+
18
+ from bs4 import BeautifulSoup
19
+ from urllib.parse import urljoin
20
+
21
+
22
+ class Helpers:
23
+ def __init__(self, window=None):
24
+ """
25
+ Web helpers core
26
+
27
+ :param window: Window instance
28
+ """
29
+ self.window = window
30
+
31
+ def request(
32
+ self,
33
+ url: str = "",
34
+ method: str = "GET",
35
+ headers: Optional[dict] = None,
36
+ params: Optional[dict] = None,
37
+ data: Optional[Union[str, dict]] = None,
38
+ json: Optional[dict] = None,
39
+ files: Optional[dict] = None,
40
+ cookies: Optional[dict] = None,
41
+ timeout: int = 10,
42
+ disable_ssl_verify: bool = False,
43
+ allow_redirects: bool = True,
44
+ stream: bool = False,
45
+ user_agent: Optional[str] = None,
46
+ ) -> Tuple[Optional[int], Optional[str]]:
47
+ """
48
+ Make HTTP request
49
+
50
+ :param url: URL
51
+ :param method: HTTP method
52
+ :param headers: Headers
53
+ :param params: GET parameters
54
+ :param data: POST data
55
+ :param json: JSON data
56
+ :param files: Files
57
+ :param cookies: Cookies
58
+ :param timeout: Timeout
59
+ :param disable_ssl_verify: Disable SSL verification
60
+ :param allow_redirects: Allow redirects
61
+ :param stream: Stream
62
+ :param user_agent: User agent
63
+ :return: status code, response text
64
+ """
65
+ upload = {}
66
+ try:
67
+ method = method.upper()
68
+ session = requests.Session()
69
+ args = {}
70
+
71
+ if data:
72
+ args['data'] = data
73
+ if json:
74
+ args['json'] = json
75
+ if cookies:
76
+ args['cookies'] = cookies
77
+ if params:
78
+ args['params'] = params
79
+ if headers:
80
+ args['headers'] = headers
81
+
82
+ args['timeout'] = timeout
83
+ if disable_ssl_verify:
84
+ args['verify'] = False
85
+ if not allow_redirects:
86
+ args['allow_redirects'] = False
87
+ if stream:
88
+ args['stream'] = True
89
+ if user_agent:
90
+ if 'headers' not in args:
91
+ args['headers'] = {}
92
+ args['headers']['User-Agent'] = user_agent
93
+
94
+ if files:
95
+ for key, value in files.items():
96
+ if os.path.exists(value) and os.path.isfile(value):
97
+ upload[key] = open(value, 'rb')
98
+ args['files'] = upload
99
+
100
+ if method == 'GET':
101
+ response = session.get(url, **args)
102
+ elif method == 'POST':
103
+ response = session.post(url, **args)
104
+ elif method == 'PUT':
105
+ response = session.put(url, **args)
106
+ elif method == 'DELETE':
107
+ response = session.delete(url, **args)
108
+ elif method == 'PATCH':
109
+ response = session.patch(url, **args)
110
+ else:
111
+ return None, f'Invalid HTTP method: {method}'
112
+ for k in upload:
113
+ upload[k].close() # close files if opened
114
+ return response.status_code, response.text
115
+ except Exception as e:
116
+ for k in upload:
117
+ upload[k].close() # close files if opened
118
+ return None, f'Error: {e}'
119
+
120
+ def get_main_image(self, url: str) -> Optional[str]:
121
+ """
122
+ Get main image from URL
123
+
124
+ :param url: URL to get image from
125
+ :return: image URL
126
+ """
127
+ response = requests.get(url)
128
+ soup = BeautifulSoup(response.content, 'html.parser')
129
+
130
+ og_image = soup.find('meta', property='og:image')
131
+ if og_image and og_image.get('content'):
132
+ return og_image['content']
133
+
134
+ twitter_image = soup.find('meta', attrs={'name': 'twitter:image'})
135
+ if twitter_image and twitter_image.get('content'):
136
+ return twitter_image['content']
137
+
138
+ link_image = soup.find('link', rel='image_src')
139
+ if link_image and link_image.get('href'):
140
+ return link_image['href']
141
+
142
+ images = soup.find_all('img')
143
+ if images:
144
+ images = [img for img in images if 'logo' not in (img.get('src') or '').lower()]
145
+ largest_image = None
146
+ max_area = 0
147
+ for img in images:
148
+ src = img.get('src')
149
+ if not src:
150
+ continue
151
+ src = requests.compat.urljoin(url, src)
152
+ try:
153
+ img_response = requests.get(src, stream=True, timeout=5)
154
+ img_response.raw.decode_content = True
155
+
156
+ from PIL import Image
157
+ image = Image.open(img_response.raw)
158
+ width, height = image.size
159
+ area = width * height
160
+ if area > max_area:
161
+ max_area = area
162
+ largest_image = src
163
+ except:
164
+ continue
165
+ if largest_image:
166
+ return largest_image
167
+ return None
168
+
169
+ def get_links(self, url: str) -> List[Dict[str, str]]:
170
+ """
171
+ Get links from URL
172
+
173
+ :param url: URL to get links from
174
+ :return: links list
175
+ """
176
+ response = requests.get(url)
177
+ soup = BeautifulSoup(response.content, 'html.parser')
178
+ links = []
179
+ urls = []
180
+ for link in soup.find_all('a'):
181
+ try:
182
+ name = link.get_text(strip=True)
183
+ address = link.get('href')
184
+ if address:
185
+ address = urljoin(url, address)
186
+ if not name:
187
+ title = link.get('title')
188
+ if title:
189
+ name = title
190
+ else:
191
+ name = address
192
+ if address not in urls:
193
+ urls.append(address)
194
+ links.append({name: address})
195
+ except:
196
+ continue
197
+ return links
198
+
199
+
200
+ def get_images(self, url: str) -> List[str]:
201
+ """
202
+ Get images from URL
203
+
204
+ :param url: URL to get images from
205
+ :return: images list
206
+ """
207
+ response = requests.get(url)
208
+ soup = BeautifulSoup(response.content, 'html.parser')
209
+ images = []
210
+ for img in soup.find_all('img'):
211
+ try:
212
+ address = img.get('src')
213
+ if address:
214
+ address = urljoin(url, address)
215
+ if address not in images:
216
+ images.append(address)
217
+ except:
218
+ continue
219
+ return images
220
+
221
+ def download_image(self, img: str) -> str:
222
+ """
223
+ Download image from URL
224
+
225
+ :param img: URL to download image from
226
+ :return: local path to image
227
+ """
228
+ dir = self.window.core.config.get_user_dir("img")
229
+ response = requests.get(img, stream=True)
230
+ name = img.replace("http://", "").replace("https://", "").replace("/", "_")
231
+ path = os.path.join(dir, name)
232
+ if os.path.exists(path):
233
+ name = name + uuid.uuid4().hex[:6].upper()
234
+ download_path = os.path.join(dir, name)
235
+ with open(download_path, 'wb', ) as f:
236
+ f.write(response.content)
237
+ return self.window.core.filesystem.make_local(download_path)