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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. CHANGELOG.md +40 -0
  2. README.md +62 -5
  3. pygpt_net/CHANGELOG.txt +40 -0
  4. pygpt_net/__init__.py +3 -3
  5. pygpt_net/controller/access/__init__.py +5 -5
  6. pygpt_net/controller/access/control.py +3 -2
  7. pygpt_net/controller/attachment.py +67 -1
  8. pygpt_net/controller/audio/__init__.py +34 -6
  9. pygpt_net/controller/chat/__init__.py +3 -1
  10. pygpt_net/controller/chat/attachment.py +239 -37
  11. pygpt_net/controller/chat/audio.py +99 -0
  12. pygpt_net/controller/chat/input.py +10 -3
  13. pygpt_net/controller/chat/output.py +4 -1
  14. pygpt_net/controller/chat/text.py +10 -5
  15. pygpt_net/controller/dialogs/confirm.py +17 -1
  16. pygpt_net/controller/kernel/reply.py +5 -8
  17. pygpt_net/controller/lang/custom.py +3 -1
  18. pygpt_net/controller/mode.py +2 -1
  19. pygpt_net/controller/presets/editor.py +11 -2
  20. pygpt_net/core/access/voice.py +2 -2
  21. pygpt_net/core/agents/legacy.py +3 -1
  22. pygpt_net/core/attachments/__init__.py +11 -7
  23. pygpt_net/core/attachments/context.py +226 -44
  24. pygpt_net/core/{audio.py → audio/__init__.py} +1 -1
  25. pygpt_net/core/audio/context.py +34 -0
  26. pygpt_net/core/bridge/context.py +29 -1
  27. pygpt_net/core/bridge/worker.py +16 -1
  28. pygpt_net/core/ctx/__init__.py +4 -1
  29. pygpt_net/core/db/__init__.py +4 -2
  30. pygpt_net/core/debug/attachments.py +3 -1
  31. pygpt_net/core/debug/context.py +5 -1
  32. pygpt_net/core/debug/presets.py +3 -1
  33. pygpt_net/core/docker/__init__.py +170 -16
  34. pygpt_net/core/docker/builder.py +6 -2
  35. pygpt_net/core/events/event.py +3 -1
  36. pygpt_net/core/experts/__init__.py +24 -6
  37. pygpt_net/core/idx/chat.py +55 -4
  38. pygpt_net/core/idx/indexing.py +123 -15
  39. pygpt_net/core/modes.py +3 -1
  40. pygpt_net/core/presets.py +13 -2
  41. pygpt_net/core/render/markdown/pid.py +2 -1
  42. pygpt_net/core/render/plain/pid.py +2 -1
  43. pygpt_net/core/render/web/body.py +34 -12
  44. pygpt_net/core/render/web/pid.py +2 -1
  45. pygpt_net/core/render/web/renderer.py +12 -3
  46. pygpt_net/core/tokens.py +4 -2
  47. pygpt_net/core/types/mode.py +2 -1
  48. pygpt_net/data/config/config.json +7 -4
  49. pygpt_net/data/config/models.json +191 -6
  50. pygpt_net/data/config/modes.json +11 -5
  51. pygpt_net/data/config/presets/current.audio.json +34 -0
  52. pygpt_net/data/config/settings.json +15 -1
  53. pygpt_net/data/css/web.css +70 -0
  54. pygpt_net/data/css/web.dark.css +4 -1
  55. pygpt_net/data/css/web.light.css +1 -1
  56. pygpt_net/data/locale/locale.de.ini +33 -20
  57. pygpt_net/data/locale/locale.en.ini +73 -58
  58. pygpt_net/data/locale/locale.es.ini +33 -20
  59. pygpt_net/data/locale/locale.fr.ini +35 -22
  60. pygpt_net/data/locale/locale.it.ini +33 -20
  61. pygpt_net/data/locale/locale.pl.ini +36 -23
  62. pygpt_net/data/locale/locale.uk.ini +33 -20
  63. pygpt_net/data/locale/locale.zh.ini +40 -27
  64. pygpt_net/data/locale/plugin.cmd_code_interpreter.de.ini +6 -0
  65. pygpt_net/data/locale/plugin.cmd_code_interpreter.en.ini +15 -7
  66. pygpt_net/data/locale/plugin.cmd_code_interpreter.es.ini +6 -0
  67. pygpt_net/data/locale/plugin.cmd_code_interpreter.fr.ini +6 -0
  68. pygpt_net/data/locale/plugin.cmd_code_interpreter.it.ini +6 -0
  69. pygpt_net/data/locale/plugin.cmd_code_interpreter.pl.ini +6 -0
  70. pygpt_net/data/locale/plugin.cmd_code_interpreter.uk.ini +6 -0
  71. pygpt_net/data/locale/plugin.cmd_code_interpreter.zh.ini +6 -0
  72. pygpt_net/data/locale/plugin.cmd_files.de.ini +4 -4
  73. pygpt_net/data/locale/plugin.cmd_files.en.ini +4 -4
  74. pygpt_net/data/locale/plugin.cmd_files.es.ini +4 -4
  75. pygpt_net/data/locale/plugin.cmd_files.fr.ini +4 -4
  76. pygpt_net/data/locale/plugin.cmd_files.it.ini +4 -4
  77. pygpt_net/data/locale/plugin.cmd_files.pl.ini +4 -4
  78. pygpt_net/data/locale/plugin.cmd_files.uk.ini +4 -4
  79. pygpt_net/data/locale/plugin.cmd_files.zh.ini +4 -4
  80. pygpt_net/data/locale/plugin.cmd_system.de.ini +6 -6
  81. pygpt_net/data/locale/plugin.cmd_system.en.ini +12 -6
  82. pygpt_net/data/locale/plugin.cmd_system.es.ini +6 -6
  83. pygpt_net/data/locale/plugin.cmd_system.fr.ini +6 -6
  84. pygpt_net/data/locale/plugin.cmd_system.it.ini +6 -6
  85. pygpt_net/data/locale/plugin.cmd_system.pl.ini +6 -6
  86. pygpt_net/data/locale/plugin.cmd_system.uk.ini +6 -6
  87. pygpt_net/data/locale/plugin.cmd_system.zh.ini +6 -6
  88. pygpt_net/data/locale/plugin.cmd_web.de.ini +5 -5
  89. pygpt_net/data/locale/plugin.cmd_web.en.ini +5 -5
  90. pygpt_net/data/locale/plugin.cmd_web.es.ini +5 -5
  91. pygpt_net/data/locale/plugin.cmd_web.fr.ini +5 -5
  92. pygpt_net/data/locale/plugin.cmd_web.it.ini +5 -5
  93. pygpt_net/data/locale/plugin.cmd_web.pl.ini +5 -5
  94. pygpt_net/data/locale/plugin.cmd_web.uk.ini +5 -5
  95. pygpt_net/data/locale/plugin.cmd_web.zh.ini +5 -5
  96. pygpt_net/data/locale/plugin.idx_llama_index.de.ini +12 -12
  97. pygpt_net/data/locale/plugin.idx_llama_index.en.ini +12 -12
  98. pygpt_net/data/locale/plugin.idx_llama_index.es.ini +12 -12
  99. pygpt_net/data/locale/plugin.idx_llama_index.fr.ini +12 -12
  100. pygpt_net/data/locale/plugin.idx_llama_index.it.ini +12 -12
  101. pygpt_net/data/locale/plugin.idx_llama_index.pl.ini +12 -12
  102. pygpt_net/data/locale/plugin.idx_llama_index.uk.ini +12 -12
  103. pygpt_net/data/locale/plugin.idx_llama_index.zh.ini +12 -12
  104. pygpt_net/item/attachment.py +9 -1
  105. pygpt_net/item/ctx.py +9 -1
  106. pygpt_net/item/preset.py +5 -1
  107. pygpt_net/launcher.py +3 -1
  108. pygpt_net/migrations/Version20241126170000.py +28 -0
  109. pygpt_net/migrations/__init__.py +3 -1
  110. pygpt_net/plugin/audio_input/__init__.py +11 -1
  111. pygpt_net/plugin/audio_input/worker.py +9 -1
  112. pygpt_net/plugin/audio_output/__init__.py +37 -7
  113. pygpt_net/plugin/audio_output/worker.py +38 -41
  114. pygpt_net/plugin/cmd_code_interpreter/__init__.py +51 -35
  115. pygpt_net/plugin/cmd_code_interpreter/builder.py +16 -4
  116. pygpt_net/plugin/cmd_code_interpreter/config.py +98 -39
  117. pygpt_net/plugin/cmd_code_interpreter/docker.py +4 -0
  118. pygpt_net/plugin/cmd_code_interpreter/ipython/__init__.py +13 -0
  119. pygpt_net/plugin/cmd_code_interpreter/{ipython.py → ipython/docker_kernel.py} +10 -3
  120. pygpt_net/plugin/cmd_code_interpreter/ipython/local_kernel.py +220 -0
  121. pygpt_net/plugin/cmd_code_interpreter/runner.py +5 -5
  122. pygpt_net/plugin/cmd_mouse_control/__init__.py +4 -2
  123. pygpt_net/plugin/cmd_system/config.py +50 -0
  124. pygpt_net/plugin/cmd_system/docker.py +4 -0
  125. pygpt_net/plugin/idx_llama_index/__init__.py +23 -1
  126. pygpt_net/plugin/idx_llama_index/worker.py +10 -0
  127. pygpt_net/plugin/openai_dalle/__init__.py +3 -1
  128. pygpt_net/plugin/openai_vision/__init__.py +3 -1
  129. pygpt_net/provider/core/attachment/json_file.py +4 -1
  130. pygpt_net/provider/core/config/patch.py +25 -0
  131. pygpt_net/provider/core/ctx/db_sqlite/storage.py +14 -4
  132. pygpt_net/provider/core/ctx/db_sqlite/utils.py +19 -2
  133. pygpt_net/provider/core/model/patch.py +7 -1
  134. pygpt_net/provider/core/preset/json_file.py +5 -1
  135. pygpt_net/provider/gpt/__init__.py +14 -2
  136. pygpt_net/provider/gpt/audio.py +63 -0
  137. pygpt_net/provider/gpt/chat.py +76 -44
  138. pygpt_net/provider/gpt/utils.py +27 -0
  139. pygpt_net/provider/gpt/vision.py +37 -15
  140. pygpt_net/provider/loaders/base.py +10 -1
  141. pygpt_net/provider/loaders/web_yt.py +19 -1
  142. pygpt_net/tools/code_interpreter/__init__.py +1 -0
  143. pygpt_net/tools/image_viewer/ui/dialogs.py +3 -1
  144. pygpt_net/ui/dialog/preset.py +3 -1
  145. pygpt_net/ui/dialog/url.py +29 -0
  146. pygpt_net/ui/dialogs.py +5 -1
  147. pygpt_net/ui/layout/chat/attachments.py +42 -6
  148. pygpt_net/ui/layout/chat/attachments_ctx.py +14 -4
  149. pygpt_net/ui/layout/chat/attachments_uploaded.py +8 -4
  150. pygpt_net/ui/layout/toolbox/agent.py +8 -7
  151. pygpt_net/ui/layout/toolbox/agent_llama.py +5 -4
  152. pygpt_net/ui/layout/toolbox/prompt.py +8 -6
  153. pygpt_net/ui/menu/tools.py +17 -11
  154. pygpt_net/ui/widget/anims/toggles.py +167 -0
  155. pygpt_net/ui/widget/dialog/url.py +59 -0
  156. pygpt_net/ui/widget/element/group.py +2 -1
  157. pygpt_net/ui/widget/lists/attachment.py +22 -17
  158. pygpt_net/ui/widget/lists/attachment_ctx.py +65 -3
  159. pygpt_net/ui/widget/option/checkbox.py +69 -5
  160. pygpt_net/ui/widget/option/cmd.py +4 -5
  161. pygpt_net/ui/widget/option/toggle.py +62 -0
  162. pygpt_net/ui/widget/option/toggle_label.py +79 -0
  163. pygpt_net/ui/widget/textarea/url.py +43 -0
  164. {pygpt_net-2.4.28.dist-info → pygpt_net-2.4.34.dist-info}/METADATA +65 -7
  165. {pygpt_net-2.4.28.dist-info → pygpt_net-2.4.34.dist-info}/RECORD +168 -154
  166. {pygpt_net-2.4.28.dist-info → pygpt_net-2.4.34.dist-info}/LICENSE +0 -0
  167. {pygpt_net-2.4.28.dist-info → pygpt_net-2.4.34.dist-info}/WHEEL +0 -0
  168. {pygpt_net-2.4.28.dist-info → pygpt_net-2.4.34.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.11.26 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from httpx_socks import SyncProxyTransport
@@ -15,6 +15,7 @@ from openai import OpenAI, DefaultHttpxClient
15
15
 
16
16
  from pygpt_net.core.types import (
17
17
  MODE_ASSISTANT,
18
+ MODE_AUDIO,
18
19
  MODE_CHAT,
19
20
  MODE_COMPLETION,
20
21
  MODE_IMAGE,
@@ -22,6 +23,7 @@ from pygpt_net.core.types import (
22
23
  )
23
24
  from pygpt_net.core.bridge.context import BridgeContext
24
25
 
26
+ from .audio import Audio
25
27
  from .assistants import Assistants
26
28
  from .chat import Chat
27
29
  from .completion import Completion
@@ -40,6 +42,7 @@ class Gpt:
40
42
  """
41
43
  self.window = window
42
44
  self.assistants = Assistants(window)
45
+ self.audio = Audio(window)
43
46
  self.chat = Chat(window)
44
47
  self.completion = Completion(window)
45
48
  self.image = Image(window)
@@ -114,7 +117,7 @@ class Gpt:
114
117
  used_tokens = self.completion.get_used_tokens()
115
118
 
116
119
  # chat
117
- elif mode == MODE_CHAT:
120
+ elif mode in [MODE_CHAT, MODE_AUDIO]:
118
121
  response = self.chat.send(
119
122
  context=context,
120
123
  extra=extra,
@@ -187,6 +190,15 @@ class Gpt:
187
190
  ctx.tool_calls = self.window.core.command.unpack_tool_calls(
188
191
  response.choices[0].message.tool_calls,
189
192
  )
193
+ # audio
194
+ elif mode in [MODE_AUDIO]:
195
+ if response.choices[0]:
196
+ if response.choices[0].message and response.choices[0].message.audio:
197
+ ctx.audio_output = response.choices[0].message.audio.data
198
+ ctx.audio_id = response.choices[0].message.audio.id
199
+ ctx.audio_expires_ts = response.choices[0].message.audio.expires_at
200
+ ctx.is_audio = True
201
+ output = response.choices[0].message.audio.transcript # from transcript
190
202
 
191
203
  ctx.set_output(output, ai_name)
192
204
  ctx.set_tokens(
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # ================================================== #
4
+ # This file is a part of PYGPT package #
5
+ # Website: https://pygpt.net #
6
+ # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
+ # MIT License #
8
+ # Created By : Marcin Szczygliński #
9
+ # Updated Date: 2024.11.26 19:00:00 #
10
+ # ================================================== #
11
+
12
+ import base64
13
+
14
+ from pygpt_net.core.bridge.context import MultimodalContext
15
+
16
+
17
+ class Audio:
18
+ def __init__(self, window=None):
19
+ """
20
+ Audio input wrapper
21
+
22
+ :param window: Window instance
23
+ """
24
+ self.window = window
25
+
26
+ def build_content(
27
+ self,
28
+ content,
29
+ multimodal_ctx: MultimodalContext = None,
30
+ ) -> list:
31
+ """
32
+ Build audio content
33
+
34
+ :param content: previous content or input prompt
35
+ :param multimodal_ctx: multimodal context
36
+ :return: List of contents
37
+ """
38
+ if not isinstance(content, list):
39
+ if content:
40
+ content = [
41
+ {
42
+ "type": "text",
43
+ "text": str(content),
44
+ }
45
+ ]
46
+ else:
47
+ content = [] # if empty input return empty list
48
+
49
+ # abort if no audio input provided
50
+ if not multimodal_ctx.is_audio_input:
51
+ return content
52
+
53
+ encoded = base64.b64encode(multimodal_ctx.audio_data).decode('utf-8')
54
+ audio_format = multimodal_ctx.audio_format # wav by default
55
+ audio_data = {
56
+ "type": "input_audio",
57
+ "input_audio": {
58
+ "data": encoded,
59
+ "format": audio_format,
60
+ }
61
+ }
62
+ content.append(audio_data)
63
+ return content
@@ -6,20 +6,22 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.11.23 00:00:00 #
9
+ # Updated Date: 2024.11.26 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import json
13
- import re
13
+ import time
14
14
 
15
15
  from pygpt_net.core.types import (
16
16
  MODE_CHAT,
17
17
  MODE_VISION,
18
+ MODE_AUDIO,
18
19
  )
19
- from pygpt_net.core.bridge.context import BridgeContext
20
+ from pygpt_net.core.bridge.context import BridgeContext, MultimodalContext
20
21
  from pygpt_net.item.ctx import CtxItem
21
22
  from pygpt_net.item.model import ModelItem
22
23
 
24
+ from .utils import sanitize_name
23
25
 
24
26
  class Chat:
25
27
  def __init__(self, window=None):
@@ -31,7 +33,11 @@ class Chat:
31
33
  self.window = window
32
34
  self.input_tokens = 0
33
35
 
34
- def send(self, context: BridgeContext, extra: dict = None):
36
+ def send(
37
+ self,
38
+ context: BridgeContext,
39
+ extra: dict = None
40
+ ):
35
41
  """
36
42
  Call OpenAI API for chat
37
43
 
@@ -43,9 +49,11 @@ class Chat:
43
49
  stream = context.stream
44
50
  max_tokens = int(context.max_tokens or 0)
45
51
  system_prompt = context.system_prompt
52
+ mode = context.mode
46
53
  model = context.model
47
54
  functions = context.external_functions
48
55
  attachments = context.attachments
56
+ multimodal_ctx = context.multimodal_ctx
49
57
 
50
58
  ctx = context.ctx
51
59
  if ctx is None:
@@ -64,6 +72,7 @@ class Chat:
64
72
  attachments=attachments,
65
73
  ai_name=ai_name,
66
74
  user_name=user_name,
75
+ multimodal_ctx=multimodal_ctx,
67
76
  )
68
77
  msg_tokens = self.window.core.tokens.from_messages(
69
78
  messages,
@@ -79,25 +88,24 @@ class Chat:
79
88
  # extra API kwargs
80
89
  response_kwargs = {}
81
90
 
82
- # tools / functions
91
+ # tools / functions >>>>>>>>>> TMP DISABLED FOR AUDIO <<<<<<<<<<
83
92
  tools = []
84
- if functions is not None and isinstance(functions, list):
85
- for function in functions:
86
- if str(function['name']).strip() == '' or function['name'] is None:
87
- continue
88
- params = {}
89
- if function['params'] is not None and function['params'] != "":
90
- params = json.loads(function['params']) # unpack JSON from string
91
- tools.append(
92
- {
93
+ if mode not in [MODE_AUDIO]:
94
+ if functions is not None and isinstance(functions, list):
95
+ for function in functions:
96
+ if str(function['name']).strip() == '' or function['name'] is None:
97
+ continue
98
+ params = {}
99
+ if function['params'] is not None and function['params'] != "":
100
+ params = json.loads(function['params']) # unpack JSON from string
101
+ tools.append({
93
102
  "type": "function",
94
103
  "function": {
95
104
  "name": function['name'],
96
105
  "parameters": params,
97
106
  "description": function['desc'],
98
107
  }
99
- }
100
- )
108
+ })
101
109
 
102
110
  # fix: o1 compatibility
103
111
  if model.id is not None and not model.id.startswith("o1"):
@@ -117,11 +125,24 @@ class Chat:
117
125
  if model.id is not None and model.id.startswith("o1"):
118
126
  stream = False
119
127
 
128
+ # audio mode
129
+ if mode in [MODE_AUDIO]:
130
+ stream = False
131
+ voice_id = "alloy"
132
+ tmp_voice = self.window.core.plugins.get_option("audio_output", "openai_voice")
133
+ if tmp_voice:
134
+ voice_id = tmp_voice
135
+ response_kwargs["modalities"] = ["text", "audio"]
136
+ response_kwargs["audio"] = {
137
+ "voice": voice_id,
138
+ "format": "wav"
139
+ }
140
+
120
141
  response = client.chat.completions.create(
121
142
  messages=messages,
122
143
  model=model.id,
123
144
  stream=stream,
124
- **response_kwargs
145
+ **response_kwargs,
125
146
  )
126
147
  return response
127
148
 
@@ -133,7 +154,8 @@ class Chat:
133
154
  history: list = None,
134
155
  attachments: dict = None,
135
156
  ai_name: str = None,
136
- user_name: str = None
157
+ user_name: str = None,
158
+ multimodal_ctx: MultimodalContext = None,
137
159
  ) -> list:
138
160
  """
139
161
  Build list of chat messages
@@ -145,6 +167,7 @@ class Chat:
145
167
  :param attachments: attachments
146
168
  :param ai_name: AI name
147
169
  :param user_name: username
170
+ :param multimodal_ctx: Multimodal context
148
171
  :return: messages list
149
172
  """
150
173
  messages = []
@@ -190,26 +213,49 @@ class Chat:
190
213
  )
191
214
  for item in items:
192
215
  # input
193
- role_name = "system"
194
- if not allowed_system:
195
- role_name = "user"
196
216
  if item.final_input is not None and item.final_input != "":
197
- messages.append({"role": role_name, "name": self.sanitize_name(user_name), "content": item.final_input})
217
+ messages.append({
218
+ "role": "user",
219
+ "name": sanitize_name(user_name),
220
+ "content": item.final_input,
221
+ })
198
222
 
199
223
  # output
200
- role_name = "system"
201
- if not allowed_system:
202
- role_name = "assistant"
203
224
  if item.final_output is not None and item.final_output != "":
204
- messages.append({"role": role_name, "name": self.sanitize_name(ai_name), "content": item.final_output})
205
-
206
- # use vision if available in current model
225
+ msg = {
226
+ "role": "assistant",
227
+ "name": sanitize_name(ai_name),
228
+ "content": item.final_output,
229
+ }
230
+ # append previous audio ID
231
+ if MODE_AUDIO in model.mode and item.audio_id:
232
+ # at first check expires_at - expired audio throws error in API
233
+ current_timestamp = time.time()
234
+ audio_timestamp = int(item.audio_expires_ts) if item.audio_expires_ts else 0
235
+ if audio_timestamp and audio_timestamp > current_timestamp:
236
+ msg["audio"] = {
237
+ "id": item.audio_id
238
+ }
239
+ messages.append(msg)
240
+
241
+ # use vision and audio if available in current model
207
242
  content = str(prompt)
208
243
  if MODE_VISION in model.mode:
209
- content = self.window.core.gpt.vision.build_content(prompt, attachments)
244
+ content = self.window.core.gpt.vision.build_content(
245
+ content=content,
246
+ attachments=attachments,
247
+ )
248
+ if MODE_AUDIO in model.mode:
249
+ content = self.window.core.gpt.audio.build_content(
250
+ content=content,
251
+ multimodal_ctx=multimodal_ctx,
252
+ )
210
253
 
211
254
  # append current prompt
212
- messages.append({"role": "user", "content": content})
255
+ messages.append({
256
+ "role": "user",
257
+ "content": content,
258
+ })
213
259
 
214
260
  # input tokens: update
215
261
  self.input_tokens += self.window.core.tokens.from_messages(
@@ -218,20 +264,6 @@ class Chat:
218
264
  )
219
265
  return messages
220
266
 
221
- def sanitize_name(self, name: str) -> str:
222
- """
223
- Sanitize name
224
-
225
- :param name: name
226
- :return: sanitized name
227
- """
228
- if name is None:
229
- return ""
230
- # allowed characters: a-z, A-Z, 0-9, _, and -
231
- name = name.strip().lower()
232
- sanitized_name = re.sub(r'[^a-z0-9_-]', '_', name)
233
- return sanitized_name[:64] # limit to 64 characters
234
-
235
267
  def reset_tokens(self):
236
268
  """Reset input tokens counter"""
237
269
  self.input_tokens = 0
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # ================================================== #
4
+ # This file is a part of PYGPT package #
5
+ # Website: https://pygpt.net #
6
+ # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
+ # MIT License #
8
+ # Created By : Marcin Szczygliński #
9
+ # Updated Date: 2024.11.26 19:00:00 #
10
+ # ================================================== #
11
+
12
+ import re
13
+
14
+
15
+ def sanitize_name(name: str) -> str:
16
+ """
17
+ Sanitize name
18
+
19
+ :param name: name
20
+ :return: sanitized name
21
+ """
22
+ if name is None:
23
+ return ""
24
+ # allowed characters: a-z, A-Z, 0-9, _, and -
25
+ name = name.strip().lower()
26
+ sanitized_name = re.sub(r'[^a-z0-9_-]', '_', name)
27
+ return sanitized_name[:64] # limit to 64 characters
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.11.23 00:00:00 #
9
+ # Updated Date: 2024.11.26 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import base64
@@ -109,10 +109,16 @@ class Vision:
109
109
 
110
110
  # append initial (system) message
111
111
  if system_prompt is not None and system_prompt != "":
112
- messages.append({"role": "system", "content": system_prompt})
112
+ messages.append({
113
+ "role": "system",
114
+ "content": system_prompt,
115
+ })
113
116
  else:
114
117
  if system_prompt is not None and system_prompt != "":
115
- messages.append({"role": "system", "content": system_prompt})
118
+ messages.append({
119
+ "role": "system",
120
+ "content": system_prompt,
121
+ })
116
122
 
117
123
  # append messages from context (memory)
118
124
  if self.window.core.config.get('use_context'):
@@ -126,15 +132,24 @@ class Vision:
126
132
  for item in items:
127
133
  # input
128
134
  if item.final_input is not None and item.final_input != "":
129
- messages.append({"role": "user", "content": item.final_input})
135
+ messages.append({
136
+ "role": "user",
137
+ "content": item.final_input,
138
+ })
130
139
 
131
140
  # output
132
141
  if item.final_output is not None and item.final_output != "":
133
- messages.append({"role": "assistant", "content": item.final_output})
142
+ messages.append({
143
+ "role": "assistant",
144
+ "content": item.final_output,
145
+ })
134
146
 
135
147
  # append current prompt
136
148
  content = self.build_content(prompt, attachments)
137
- messages.append({"role": "user", "content": content})
149
+ messages.append({
150
+ "role": "user",
151
+ "content": content,
152
+ })
138
153
 
139
154
  # input tokens: update
140
155
  self.input_tokens += self.window.core.tokens.from_messages(
@@ -143,20 +158,27 @@ class Vision:
143
158
  )
144
159
  return messages
145
160
 
146
- def build_content(self, prompt: str, attachments: dict = None) -> list:
161
+ def build_content(
162
+ self,
163
+ content: str or list,
164
+ attachments: dict = None,
165
+ ) -> list:
147
166
  """
148
- Build vision contents
167
+ Build vision content
149
168
 
150
- :param prompt: prompt (user input)
169
+ :param content: content (str or list)
151
170
  :param attachments: attachments (dict, optional)
152
171
  :return: List of contents
153
172
  """
154
- content = [
155
- {
156
- "type": "text",
157
- "text": str(prompt)
158
- }
159
- ]
173
+ if not isinstance(content, list):
174
+ content = [
175
+ {
176
+ "type": "text",
177
+ "text": str(content)
178
+ }
179
+ ]
180
+
181
+ prompt = content[0]['text']
160
182
 
161
183
  self.attachments = {} # reset attachments, only current prompt
162
184
  self.urls = []
@@ -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.04.17 01:00:00 #
9
+ # Updated Date: 2024.11.26 04:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from llama_index.core.readers.base import BaseReader
@@ -75,6 +75,15 @@ class BaseLoader:
75
75
  return args.get("url")
76
76
  return ""
77
77
 
78
+ def is_supported_attachment(self, source: str) -> bool:
79
+ """
80
+ Check if attachment is supported by loader
81
+
82
+ :param source: attachment source
83
+ :return: True if supported
84
+ """
85
+ return False
86
+
78
87
  def get(self) -> BaseReader:
79
88
  """
80
89
  Get reader instance
@@ -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.03.12 06:00:00 #
9
+ # Updated Date: 2024.11.26 04:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from llama_index.core.readers.base import BaseReader
@@ -52,3 +52,21 @@ class Loader(BaseLoader):
52
52
  args = {}
53
53
  args["ytlinks"] = [kwargs.get("url")] # list of links
54
54
  return args
55
+
56
+ def is_supported_attachment(self, source: str) -> bool:
57
+ """
58
+ Check if attachment is supported by loader
59
+
60
+ :param source: attachment source
61
+ :return: True if supported
62
+ """
63
+ yt_prefix = [
64
+ "https://youtube.com",
65
+ "https://youtu.be",
66
+ "https://www.youtube.com",
67
+ "https://m.youtube.com",
68
+ ]
69
+ for prefix in yt_prefix:
70
+ if source.startswith(prefix):
71
+ return True
72
+ return False
@@ -233,6 +233,7 @@ class CodeInterpreter(BaseTool):
233
233
 
234
234
  def restart_kernel(self):
235
235
  """Restart kernel"""
236
+ print("Sending restart event...")
236
237
  commands = [
237
238
  {
238
239
  "cmd": "ipython_kernel_restart",
@@ -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.03.26 15:00:00 #
9
+ # Updated Date: 2024.11.26 02:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import Qt
@@ -17,6 +17,8 @@ from pygpt_net.ui.widget.dialog.base import BaseDialog
17
17
  from pygpt_net.ui.widget.image.display import ImageLabel
18
18
  from pygpt_net.utils import trans
19
19
 
20
+ import pygpt_net.icons_rc
21
+
20
22
  class DialogSpawner:
21
23
  def __init__(self, window=None):
22
24
  """
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.11.21 20:00:00 #
9
+ # Updated Date: 2024.11.26 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import Qt
@@ -15,6 +15,7 @@ from PySide6.QtWidgets import QPushButton, QHBoxLayout, QLabel, QVBoxLayout, QSp
15
15
  from pygpt_net.core.types import (
16
16
  MODE_AGENT,
17
17
  MODE_AGENT_LLAMA,
18
+ MODE_AUDIO,
18
19
  MODE_CHAT,
19
20
  MODE_COMPLETION,
20
21
  MODE_EXPERT,
@@ -108,6 +109,7 @@ class Preset(BaseConfigDialog):
108
109
  MODE_LLAMA_INDEX,
109
110
  MODE_AGENT_LLAMA,
110
111
  MODE_AGENT,
112
+ MODE_AUDIO,
111
113
  MODE_EXPERT,
112
114
  ]
113
115
  rows_mode = QVBoxLayout()
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # ================================================== #
4
+ # This file is a part of PYGPT package #
5
+ # Website: https://pygpt.net #
6
+ # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
+ # MIT License #
8
+ # Created By : Marcin Szczygliński #
9
+ # Updated Date: 2024.11.26 02:00:00 #
10
+ # ================================================== #
11
+
12
+ from pygpt_net.ui.widget.dialog.url import UrlDialog
13
+ from pygpt_net.utils import trans
14
+
15
+
16
+ class Url:
17
+ def __init__(self, window=None):
18
+ """
19
+ URL dialog
20
+
21
+ :param window: Window instance
22
+ """
23
+ self.window = window
24
+
25
+ def setup(self):
26
+ """Setup URL dialog"""
27
+ id = 'url'
28
+ self.window.ui.dialog[id] = UrlDialog(self.window, id)
29
+ self.window.ui.dialog[id].setWindowTitle(trans("dialog.url.title"))
pygpt_net/ui/dialogs.py CHANGED
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.11.14 01:00:00 #
9
+ # Updated Date: 2024.11.26 02:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import threading
@@ -35,6 +35,7 @@ from pygpt_net.ui.dialog.settings import Settings
35
35
  from pygpt_net.ui.dialog.snap import Snap
36
36
  from pygpt_net.ui.dialog.start import Start
37
37
  from pygpt_net.ui.dialog.update import Update
38
+ from pygpt_net.ui.dialog.url import Url
38
39
  from pygpt_net.ui.dialog.workdir import Workdir
39
40
  from pygpt_net.ui.widget.dialog.alert import AlertDialog
40
41
  from pygpt_net.ui.widget.dialog.confirm import ConfirmDialog
@@ -66,6 +67,7 @@ class Dialogs:
66
67
  self.snap = Snap(self.window)
67
68
  self.start = Start(self.window)
68
69
  self.update = Update(self.window)
70
+ self.url = Url(self.window)
69
71
  self.workdir = Workdir(self.window)
70
72
 
71
73
  def setup(self):
@@ -85,6 +87,8 @@ class Dialogs:
85
87
  self.snap.setup()
86
88
  self.start.setup()
87
89
  self.update.setup()
90
+ self.url.setup()
91
+
88
92
  self.image.setup()
89
93
  self.license.setup()
90
94
  self.logger.setup()