pygpt-net 2.4.30__py3-none-any.whl → 2.4.35__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.
- CHANGELOG.md +32 -0
- README.md +2105 -1892
- pygpt_net/CHANGELOG.txt +32 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/controller/access/__init__.py +5 -5
- pygpt_net/controller/access/control.py +3 -2
- pygpt_net/controller/attachment.py +68 -1
- pygpt_net/controller/audio/__init__.py +34 -6
- pygpt_net/controller/chat/__init__.py +3 -1
- pygpt_net/controller/chat/attachment.py +263 -38
- pygpt_net/controller/chat/audio.py +99 -0
- pygpt_net/controller/chat/input.py +10 -3
- pygpt_net/controller/chat/output.py +4 -1
- pygpt_net/controller/chat/text.py +7 -3
- pygpt_net/controller/dialogs/confirm.py +17 -1
- pygpt_net/controller/lang/custom.py +3 -1
- pygpt_net/controller/mode.py +2 -1
- pygpt_net/controller/painter/capture.py +2 -2
- pygpt_net/controller/presets/editor.py +15 -2
- pygpt_net/controller/ui/__init__.py +4 -1
- pygpt_net/core/access/voice.py +2 -2
- pygpt_net/core/agents/legacy.py +3 -1
- pygpt_net/core/attachments/__init__.py +14 -9
- pygpt_net/core/attachments/context.py +226 -44
- pygpt_net/core/{audio.py → audio/__init__.py} +1 -1
- pygpt_net/core/audio/context.py +34 -0
- pygpt_net/core/bridge/context.py +29 -1
- pygpt_net/core/ctx/__init__.py +4 -1
- pygpt_net/core/db/__init__.py +4 -2
- pygpt_net/core/debug/attachments.py +3 -1
- pygpt_net/core/debug/context.py +5 -1
- pygpt_net/core/debug/presets.py +3 -1
- pygpt_net/core/events/event.py +2 -1
- pygpt_net/core/experts/__init__.py +3 -1
- pygpt_net/core/idx/chat.py +28 -6
- pygpt_net/core/idx/indexing.py +123 -15
- pygpt_net/core/modes.py +3 -1
- pygpt_net/core/presets.py +13 -2
- pygpt_net/core/render/markdown/pid.py +2 -1
- pygpt_net/core/render/plain/pid.py +2 -1
- pygpt_net/core/render/web/body.py +34 -12
- pygpt_net/core/render/web/pid.py +2 -1
- pygpt_net/core/render/web/renderer.py +8 -3
- pygpt_net/core/tokens.py +4 -2
- pygpt_net/core/types/mode.py +2 -1
- pygpt_net/data/config/config.json +7 -5
- pygpt_net/data/config/models.json +190 -5
- pygpt_net/data/config/modes.json +11 -5
- pygpt_net/data/config/presets/current.audio.json +34 -0
- pygpt_net/data/config/settings.json +15 -1
- pygpt_net/data/css/web.css +70 -0
- pygpt_net/data/css/web.dark.css +4 -1
- pygpt_net/data/css/web.light.css +1 -1
- pygpt_net/data/locale/locale.de.ini +27 -14
- pygpt_net/data/locale/locale.en.ini +63 -47
- pygpt_net/data/locale/locale.es.ini +27 -14
- pygpt_net/data/locale/locale.fr.ini +29 -16
- pygpt_net/data/locale/locale.it.ini +27 -14
- pygpt_net/data/locale/locale.pl.ini +31 -18
- pygpt_net/data/locale/locale.uk.ini +27 -14
- pygpt_net/data/locale/locale.zh.ini +34 -21
- pygpt_net/data/locale/plugin.cmd_files.de.ini +4 -4
- pygpt_net/data/locale/plugin.cmd_files.en.ini +4 -4
- pygpt_net/data/locale/plugin.cmd_files.es.ini +4 -4
- pygpt_net/data/locale/plugin.cmd_files.fr.ini +4 -4
- pygpt_net/data/locale/plugin.cmd_files.it.ini +4 -4
- pygpt_net/data/locale/plugin.cmd_files.pl.ini +4 -4
- pygpt_net/data/locale/plugin.cmd_files.uk.ini +4 -4
- pygpt_net/data/locale/plugin.cmd_files.zh.ini +4 -4
- pygpt_net/data/locale/plugin.cmd_web.de.ini +5 -5
- pygpt_net/data/locale/plugin.cmd_web.en.ini +5 -5
- pygpt_net/data/locale/plugin.cmd_web.es.ini +5 -5
- pygpt_net/data/locale/plugin.cmd_web.fr.ini +5 -5
- pygpt_net/data/locale/plugin.cmd_web.it.ini +5 -5
- pygpt_net/data/locale/plugin.cmd_web.pl.ini +5 -5
- pygpt_net/data/locale/plugin.cmd_web.uk.ini +5 -5
- pygpt_net/data/locale/plugin.cmd_web.zh.ini +5 -5
- pygpt_net/data/locale/plugin.idx_llama_index.de.ini +12 -12
- pygpt_net/data/locale/plugin.idx_llama_index.en.ini +12 -12
- pygpt_net/data/locale/plugin.idx_llama_index.es.ini +12 -12
- pygpt_net/data/locale/plugin.idx_llama_index.fr.ini +12 -12
- pygpt_net/data/locale/plugin.idx_llama_index.it.ini +12 -12
- pygpt_net/data/locale/plugin.idx_llama_index.pl.ini +12 -12
- pygpt_net/data/locale/plugin.idx_llama_index.uk.ini +12 -12
- pygpt_net/data/locale/plugin.idx_llama_index.zh.ini +12 -12
- pygpt_net/data/win32/USER-LICENSE.rtf +0 -0
- pygpt_net/data/win32/banner.bmp +0 -0
- pygpt_net/data/win32/banner_welcome.bmp +0 -0
- pygpt_net/item/attachment.py +9 -1
- pygpt_net/item/ctx.py +9 -1
- pygpt_net/item/preset.py +5 -1
- pygpt_net/launcher.py +3 -1
- pygpt_net/migrations/Version20241126170000.py +28 -0
- pygpt_net/migrations/__init__.py +3 -1
- pygpt_net/plugin/audio_input/__init__.py +11 -1
- pygpt_net/plugin/audio_input/worker.py +9 -1
- pygpt_net/plugin/audio_output/__init__.py +37 -7
- pygpt_net/plugin/audio_output/worker.py +38 -41
- pygpt_net/plugin/cmd_code_interpreter/runner.py +2 -2
- pygpt_net/plugin/cmd_mouse_control/__init__.py +4 -2
- pygpt_net/plugin/openai_dalle/__init__.py +3 -1
- pygpt_net/plugin/openai_vision/__init__.py +3 -1
- pygpt_net/provider/core/attachment/json_file.py +4 -1
- pygpt_net/provider/core/config/patch.py +22 -0
- pygpt_net/provider/core/ctx/db_sqlite/storage.py +14 -4
- pygpt_net/provider/core/ctx/db_sqlite/utils.py +19 -2
- pygpt_net/provider/core/model/patch.py +7 -1
- pygpt_net/provider/core/preset/json_file.py +5 -1
- pygpt_net/provider/gpt/__init__.py +14 -2
- pygpt_net/provider/gpt/audio.py +63 -0
- pygpt_net/provider/gpt/chat.py +76 -44
- pygpt_net/provider/gpt/utils.py +27 -0
- pygpt_net/provider/gpt/vision.py +37 -15
- pygpt_net/provider/loaders/base.py +10 -1
- pygpt_net/provider/loaders/web_yt.py +19 -1
- pygpt_net/tools/image_viewer/ui/dialogs.py +3 -1
- pygpt_net/ui/dialog/about.py +1 -1
- pygpt_net/ui/dialog/preset.py +3 -1
- pygpt_net/ui/dialog/url.py +29 -0
- pygpt_net/ui/dialogs.py +5 -1
- pygpt_net/ui/layout/chat/attachments.py +42 -6
- pygpt_net/ui/layout/chat/attachments_ctx.py +14 -4
- pygpt_net/ui/layout/chat/attachments_uploaded.py +8 -4
- pygpt_net/ui/widget/anims/toggles.py +2 -2
- pygpt_net/ui/widget/dialog/url.py +59 -0
- pygpt_net/ui/widget/lists/attachment.py +22 -17
- pygpt_net/ui/widget/lists/attachment_ctx.py +65 -3
- pygpt_net/ui/widget/option/checkbox.py +1 -3
- pygpt_net/ui/widget/option/toggle.py +1 -0
- pygpt_net/ui/widget/textarea/url.py +43 -0
- {pygpt_net-2.4.30.dist-info → pygpt_net-2.4.35.dist-info}/METADATA +2107 -1894
- {pygpt_net-2.4.30.dist-info → pygpt_net-2.4.35.dist-info}/RECORD +135 -124
- {pygpt_net-2.4.30.dist-info → pygpt_net-2.4.35.dist-info}/LICENSE +0 -0
- {pygpt_net-2.4.30.dist-info → pygpt_net-2.4.35.dist-info}/WHEEL +0 -0
- {pygpt_net-2.4.30.dist-info → pygpt_net-2.4.35.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.
|
9
|
+
# Updated Date: 2024.11.26 04:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import copy
|
@@ -31,6 +31,11 @@ class Context:
|
|
31
31
|
"""
|
32
32
|
self.window = window
|
33
33
|
self.dir_index = "index"
|
34
|
+
self.last_used_item = None
|
35
|
+
self.last_used_content = None
|
36
|
+
self.last_used_context = None
|
37
|
+
self.last_files = []
|
38
|
+
self.last_urls = []
|
34
39
|
self.summary_prompt = """
|
35
40
|
Summarize the text below by extracting the most important information,
|
36
41
|
especially those that may help answer the question:
|
@@ -87,16 +92,38 @@ class Context:
|
|
87
92
|
context = ""
|
88
93
|
if os.path.exists(meta_path) and os.path.isdir(meta_path):
|
89
94
|
for file in meta.additional_ctx:
|
90
|
-
if "type" not in file
|
95
|
+
if ("type" not in file
|
96
|
+
or file["type"] not in ["local_file", "url"]):
|
91
97
|
continue
|
92
98
|
file_id = file["uuid"]
|
93
99
|
file_idx_path = os.path.join(meta_path, file_id)
|
94
100
|
text_path = os.path.join(file_idx_path, file_id + ".txt")
|
101
|
+
store_path = file["path"]
|
102
|
+
if "real_path" in file:
|
103
|
+
store_path = file["real_path"]
|
95
104
|
if filename:
|
96
|
-
|
105
|
+
if file["type"] == "url":
|
106
|
+
context += "URL: {}\n".format(file["path"]) + "\n"
|
107
|
+
else:
|
108
|
+
context += "Filename: {}\n".format(file["name"]) + "\n"
|
109
|
+
|
110
|
+
# store used files and URLs in ctx
|
111
|
+
if file["type"] == "url":
|
112
|
+
if store_path not in self.last_urls:
|
113
|
+
self.last_urls.append(store_path)
|
114
|
+
else:
|
115
|
+
if store_path not in self.last_files:
|
116
|
+
self.last_files.append(store_path)
|
117
|
+
|
97
118
|
if os.path.exists(text_path):
|
98
|
-
|
99
|
-
|
119
|
+
try:
|
120
|
+
with open(text_path, "r", encoding="utf-8") as f:
|
121
|
+
context += f.read() + "\n\n"
|
122
|
+
except Exception as e:
|
123
|
+
print("Attachments: read error: {}".format(e))
|
124
|
+
|
125
|
+
self.last_used_content = context
|
126
|
+
self.last_used_context = context
|
100
127
|
return context
|
101
128
|
|
102
129
|
def query_context(self, meta: CtxMeta, query: str) -> str:
|
@@ -111,14 +138,55 @@ class Context:
|
|
111
138
|
if not os.path.exists(meta_path) or not os.path.isdir(meta_path):
|
112
139
|
return ""
|
113
140
|
idx_path = os.path.join(self.get_dir(meta), self.dir_index)
|
114
|
-
|
115
|
-
|
141
|
+
|
142
|
+
indexed = False
|
143
|
+
# index files if not indexed by auto_index
|
144
|
+
for i, file in enumerate(meta.additional_ctx):
|
145
|
+
if "indexed" not in file or not file["indexed"]:
|
146
|
+
file_id = file["uuid"]
|
147
|
+
file_idx_path = os.path.join(meta_path, file_id)
|
148
|
+
file_path = os.path.join(file_idx_path, file["name"])
|
149
|
+
type = AttachmentItem.TYPE_FILE
|
150
|
+
source = file_path
|
151
|
+
if "type" in file:
|
152
|
+
if file["type"] == "url":
|
153
|
+
type = AttachmentItem.TYPE_URL
|
154
|
+
source = file["path"] # URL
|
155
|
+
doc_ids = self.index_attachment(type, source, idx_path)
|
156
|
+
file["indexed"] = True
|
157
|
+
file["doc_ids"] = doc_ids
|
158
|
+
indexed = True
|
159
|
+
|
160
|
+
if indexed:
|
161
|
+
# update ctx in DB
|
162
|
+
self.window.core.ctx.replace(meta)
|
163
|
+
self.window.core.ctx.save(meta.id)
|
164
|
+
|
165
|
+
model, model_item = self.get_selected_model("query")
|
166
|
+
result = self.window.core.idx.chat.query_attachment(query, idx_path, model_item)
|
167
|
+
self.last_used_context = result
|
116
168
|
|
117
169
|
if self.is_verbose():
|
118
170
|
print("Attachments: query result: {}".format(result))
|
119
171
|
|
120
172
|
return result
|
121
173
|
|
174
|
+
def get_selected_model(self, mode: str = "summary"):
|
175
|
+
"""
|
176
|
+
Get selected model for attachments
|
177
|
+
|
178
|
+
:return: model name, model item
|
179
|
+
"""
|
180
|
+
model_item = None
|
181
|
+
model = None
|
182
|
+
if mode == "summary":
|
183
|
+
model = self.window.core.config.get("ctx.attachment.summary.model", "gpt-4o-mini")
|
184
|
+
elif mode == "query":
|
185
|
+
model = self.window.core.config.get("ctx.attachment.query.model", "gpt-4o-mini")
|
186
|
+
if model:
|
187
|
+
model_item = self.window.core.models.get(model)
|
188
|
+
return model, model_item
|
189
|
+
|
122
190
|
def summary_context(self, ctx: CtxItem, query: str) -> str:
|
123
191
|
"""
|
124
192
|
Get summary of the context
|
@@ -127,20 +195,17 @@ class Context:
|
|
127
195
|
:param query: query string
|
128
196
|
:return: query result
|
129
197
|
"""
|
130
|
-
model_item =
|
131
|
-
model = self.window.core.config.get("ctx.attachment.summary.model", "gpt-4o-mini")
|
132
|
-
if model:
|
133
|
-
model_item = self.window.core.models.get(model)
|
134
|
-
|
198
|
+
model, model_item = self.get_selected_model("summary")
|
135
199
|
if model_item is None:
|
136
200
|
raise Exception("Attachments: summary model not found: {}".format(model))
|
137
201
|
|
138
202
|
if self.is_verbose():
|
139
203
|
print("Attachments: using summary model: {}".format(model))
|
140
204
|
|
205
|
+
content = self.get_context_text(ctx, filename=True)
|
141
206
|
prompt = self.summary_prompt.format(
|
142
207
|
query=str(query).strip(),
|
143
|
-
content=str(
|
208
|
+
content=str(content).strip(),
|
144
209
|
)
|
145
210
|
if self.is_verbose():
|
146
211
|
print("Attachments: summary prompt: {}".format(prompt))
|
@@ -158,17 +223,27 @@ class Context:
|
|
158
223
|
})
|
159
224
|
self.window.dispatch(event)
|
160
225
|
response = event.data.get("response")
|
226
|
+
self.last_used_context = response
|
161
227
|
if self.is_verbose():
|
162
228
|
print("Attachments: summary received: {}".format(response))
|
163
229
|
return response
|
164
230
|
|
165
|
-
def upload(
|
231
|
+
def upload(
|
232
|
+
self,
|
233
|
+
meta: CtxMeta,
|
234
|
+
attachment: AttachmentItem,
|
235
|
+
prompt: str,
|
236
|
+
auto_index: bool = False,
|
237
|
+
real_path: str = None
|
238
|
+
) -> dict:
|
166
239
|
"""
|
167
240
|
Upload attachment for context
|
168
241
|
|
169
242
|
:param meta: CtxMeta instance
|
170
243
|
:param attachment: AttachmentItem instance
|
171
244
|
:param prompt: user input prompt
|
245
|
+
:param auto_index: auto index
|
246
|
+
:param real_path: real path
|
172
247
|
:return: Dict with attachment data
|
173
248
|
"""
|
174
249
|
if self.is_verbose():
|
@@ -180,64 +255,147 @@ class Context:
|
|
180
255
|
meta_path = self.get_dir(meta)
|
181
256
|
file_idx_path = os.path.join(meta_path, file_id)
|
182
257
|
index_path = os.path.join(meta_path, self.dir_index)
|
258
|
+
|
183
259
|
os.makedirs(meta_path, exist_ok=True)
|
184
260
|
os.makedirs(file_idx_path, exist_ok=True)
|
185
261
|
|
186
262
|
if self.is_verbose():
|
187
263
|
print("Attachments: created path: {}".format(meta_path))
|
188
|
-
|
264
|
+
if auto_index:
|
265
|
+
print("Attachments: vector index path: {}".format(index_path))
|
189
266
|
|
190
|
-
#
|
191
|
-
|
192
|
-
if os.path.exists(raw_path):
|
193
|
-
os.remove(raw_path)
|
194
|
-
copyfile(attachment.path, raw_path)
|
267
|
+
# store content to read
|
268
|
+
src_file = self.store_content(attachment, file_idx_path)
|
195
269
|
|
196
270
|
# extract text content using data loader
|
197
|
-
|
198
|
-
|
199
|
-
} # extra loader kwargs
|
200
|
-
text = self.window.core.idx.indexing.read_text_content(
|
201
|
-
path=raw_path,
|
202
|
-
loader_kwargs=loader_kwargs,
|
203
|
-
)
|
204
|
-
if text:
|
271
|
+
content = self.read_content(attachment, src_file, prompt)
|
272
|
+
if content:
|
205
273
|
text_path = os.path.join(file_idx_path, file_id + ".txt")
|
206
|
-
with open(text_path, "w") as f:
|
207
|
-
f.write(
|
208
|
-
|
274
|
+
with open(text_path, "w", encoding="utf-8") as f:
|
275
|
+
f.write(content)
|
209
276
|
if self.is_verbose():
|
210
|
-
print("Attachments: read text content: {}".format(
|
277
|
+
print("Attachments: read text content: {}".format(content))
|
211
278
|
|
212
279
|
tokens = 0
|
213
|
-
if
|
214
|
-
tokens = self.window.core.tokens.from_str(
|
280
|
+
if content:
|
281
|
+
tokens = self.window.core.tokens.from_str(content)
|
215
282
|
|
216
|
-
|
217
|
-
|
218
|
-
|
283
|
+
type = "local_file"
|
284
|
+
size = 0
|
285
|
+
if attachment.type == AttachmentItem.TYPE_FILE:
|
286
|
+
size = os.path.getsize(attachment.path)
|
287
|
+
elif attachment.type == AttachmentItem.TYPE_URL:
|
288
|
+
size = os.path.getsize(src_file)
|
289
|
+
type = "url" # extra ctx type
|
219
290
|
|
220
|
-
|
221
|
-
|
291
|
+
# index file to ctx index
|
292
|
+
doc_ids = []
|
293
|
+
if auto_index:
|
294
|
+
source = src_file
|
295
|
+
if attachment.type == AttachmentItem.TYPE_URL:
|
296
|
+
source = attachment.path # URL
|
297
|
+
doc_ids = self.index_attachment(attachment.type, source, index_path)
|
222
298
|
|
223
299
|
result = {
|
224
300
|
"name": name,
|
225
301
|
"path": attachment.path,
|
226
|
-
"type":
|
302
|
+
"type": type,
|
227
303
|
"uuid": str(file_id),
|
228
|
-
"doc_ids": doc_ids,
|
229
|
-
"indexed": True,
|
230
304
|
"content_type": "text",
|
231
|
-
"size":
|
232
|
-
"length": len(
|
305
|
+
"size": size,
|
306
|
+
"length": len(content),
|
233
307
|
"tokens": tokens,
|
308
|
+
"indexed": False,
|
234
309
|
}
|
310
|
+
if auto_index:
|
311
|
+
result["indexed"] = True
|
312
|
+
result["doc_ids"] = doc_ids
|
313
|
+
|
314
|
+
if real_path:
|
315
|
+
result["real_path"] = real_path
|
235
316
|
|
236
317
|
if self.is_verbose():
|
237
318
|
print("Attachments: uploaded: {}".format(result))
|
238
319
|
|
239
320
|
return result
|
240
321
|
|
322
|
+
def read_content(self, attachment: AttachmentItem, path: str, prompt: str) -> str:
|
323
|
+
"""
|
324
|
+
Read content from attachment
|
325
|
+
|
326
|
+
:param attachment: AttachmentItem instance
|
327
|
+
:param path: source file path
|
328
|
+
:param prompt: user input prompt
|
329
|
+
:return: content
|
330
|
+
"""
|
331
|
+
content = ""
|
332
|
+
if attachment.type == AttachmentItem.TYPE_FILE:
|
333
|
+
loader_kwargs = {
|
334
|
+
"prompt": prompt,
|
335
|
+
} # extra loader kwargs
|
336
|
+
content = self.window.core.idx.indexing.read_text_content(
|
337
|
+
path=path,
|
338
|
+
loader_kwargs=loader_kwargs,
|
339
|
+
)
|
340
|
+
elif attachment.type == AttachmentItem.TYPE_URL:
|
341
|
+
# directly from path
|
342
|
+
with open(path, "r", encoding="utf-8") as f:
|
343
|
+
content = f.read() # already crawled
|
344
|
+
|
345
|
+
return content
|
346
|
+
|
347
|
+
def store_content(self, attachment: AttachmentItem, dir: str) -> str:
|
348
|
+
"""
|
349
|
+
Prepare content for attachment
|
350
|
+
|
351
|
+
:param attachment: AttachmentItem instance
|
352
|
+
:param dir: directory to save content
|
353
|
+
:return: content
|
354
|
+
"""
|
355
|
+
path = None
|
356
|
+
if attachment.type == AttachmentItem.TYPE_FILE:
|
357
|
+
# copy raw file
|
358
|
+
name = os.path.basename(attachment.path)
|
359
|
+
path = os.path.join(dir, name)
|
360
|
+
if os.path.exists(path):
|
361
|
+
os.remove(path)
|
362
|
+
copyfile(attachment.path, path)
|
363
|
+
elif attachment.type == AttachmentItem.TYPE_URL:
|
364
|
+
web_type = self.window.core.idx.indexing.get_webtype(attachment.path)
|
365
|
+
content = self.window.core.idx.indexing.read_web_content(
|
366
|
+
url=attachment.path,
|
367
|
+
type=web_type, # webpage, default, TODO: add more types
|
368
|
+
extra_args={},
|
369
|
+
)
|
370
|
+
# src file save
|
371
|
+
name = "url.txt"
|
372
|
+
path = os.path.join(dir, name)
|
373
|
+
if os.path.exists(path):
|
374
|
+
os.remove(path)
|
375
|
+
with open(path, "w", encoding="utf-8") as f:
|
376
|
+
f.write(content)
|
377
|
+
return path
|
378
|
+
|
379
|
+
def index_attachment(self, type: str, source: str, idx_path: str, documents: list = None) -> list:
|
380
|
+
"""
|
381
|
+
Index attachment
|
382
|
+
|
383
|
+
:param type: attachment type
|
384
|
+
:param source: source file or URL
|
385
|
+
:param idx_path: index path
|
386
|
+
:param documents: list of documents (optional)
|
387
|
+
:return: list of doc IDs
|
388
|
+
"""
|
389
|
+
model = None
|
390
|
+
doc_ids = []
|
391
|
+
if type == AttachmentItem.TYPE_FILE:
|
392
|
+
doc_ids = self.window.core.idx.indexing.index_attachment(source, idx_path, model, documents)
|
393
|
+
elif type == AttachmentItem.TYPE_URL:
|
394
|
+
doc_ids = self.window.core.idx.indexing.index_attachment_web(source, idx_path, model, documents)
|
395
|
+
if self.is_verbose():
|
396
|
+
print("Attachments: indexed. Doc IDs: {}".format(doc_ids))
|
397
|
+
return doc_ids
|
398
|
+
|
241
399
|
def duplicate(self, from_meta_id: int, to_meta_id: int) -> bool:
|
242
400
|
"""
|
243
401
|
Duplicate attachments from one meta to another
|
@@ -390,6 +548,30 @@ class Context:
|
|
390
548
|
except Exception as e:
|
391
549
|
self.window.core.debug.error("Attachment.truncate", e)
|
392
550
|
|
551
|
+
def reset(self):
|
552
|
+
"""Reset context info"""
|
553
|
+
self.last_used_item = None
|
554
|
+
self.last_used_content = None
|
555
|
+
self.last_used_context = None
|
556
|
+
self.last_files = []
|
557
|
+
self.last_urls = []
|
558
|
+
|
559
|
+
def get_used_files(self) -> list:
|
560
|
+
"""
|
561
|
+
Get last used files
|
562
|
+
|
563
|
+
:return: list of files
|
564
|
+
"""
|
565
|
+
return self.last_files
|
566
|
+
|
567
|
+
def get_used_urls(self) -> list:
|
568
|
+
"""
|
569
|
+
Get last used URLs
|
570
|
+
|
571
|
+
:return: list of URLs
|
572
|
+
"""
|
573
|
+
return self.last_urls
|
574
|
+
|
393
575
|
def is_verbose(self) -> bool:
|
394
576
|
"""
|
395
577
|
Check if verbose mode is enabled
|
@@ -0,0 +1,34 @@
|
|
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.21 20:00:00 #
|
10
|
+
# ================================================== #
|
11
|
+
|
12
|
+
class AudioContext:
|
13
|
+
def __init__(self, **kwargs):
|
14
|
+
"""
|
15
|
+
Audio context
|
16
|
+
|
17
|
+
:param kwargs: keyword arguments
|
18
|
+
"""
|
19
|
+
self.data = kwargs.get("ctx", None)
|
20
|
+
self.prev_id = kwargs.get("prev_id", None)
|
21
|
+
|
22
|
+
def to_dict(self) -> dict:
|
23
|
+
"""
|
24
|
+
Return as dictionary
|
25
|
+
|
26
|
+
:return: dictionary
|
27
|
+
"""
|
28
|
+
data = {
|
29
|
+
"data": self.data,
|
30
|
+
"prev_id": self.prev_id
|
31
|
+
}
|
32
|
+
# sort by keys
|
33
|
+
data = dict(sorted(data.items(), key=lambda item: item[0]))
|
34
|
+
return data
|
pygpt_net/core/bridge/context.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.
|
9
|
+
# Updated Date: 2024.11.26 19:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from pygpt_net.item.ctx import CtxItem
|
@@ -39,6 +39,7 @@ class BridgeContext:
|
|
39
39
|
self.attachments = kwargs.get("attachments", [])
|
40
40
|
self.file_ids = kwargs.get("file_ids", [])
|
41
41
|
self.reply_context = kwargs.get("reply_ctx", None) # ReplyContext
|
42
|
+
self.multimodal_ctx = kwargs.get("multimodal_ctx", MultimodalContext()) # AudioContext
|
42
43
|
|
43
44
|
# check types
|
44
45
|
if self.ctx is not None and not isinstance(self.ctx, CtxItem):
|
@@ -78,6 +79,33 @@ class BridgeContext:
|
|
78
79
|
if self.model is not None:
|
79
80
|
data["model"] = self.model.to_dict()
|
80
81
|
|
82
|
+
# sort by keys
|
83
|
+
data = dict(sorted(data.items(), key=lambda item: item[0]))
|
84
|
+
return data
|
85
|
+
|
86
|
+
class MultimodalContext:
|
87
|
+
def __init__(self, **kwargs):
|
88
|
+
"""
|
89
|
+
Multimodal context
|
90
|
+
|
91
|
+
:param kwargs: keyword arguments
|
92
|
+
"""
|
93
|
+
self.is_audio_input = kwargs.get("is_audio_input", False)
|
94
|
+
self.is_audio_output = kwargs.get("is_audio_output", False)
|
95
|
+
self.audio_data = kwargs.get("audio_data", None)
|
96
|
+
self.audio_format = kwargs.get("audio_format", "wav")
|
97
|
+
|
98
|
+
def to_dict(self) -> dict:
|
99
|
+
"""
|
100
|
+
Return as dictionary
|
101
|
+
|
102
|
+
:return: dictionary
|
103
|
+
"""
|
104
|
+
data = {
|
105
|
+
"is_audio_input": self.is_audio_input,
|
106
|
+
"is_audio_output": self.is_audio_output,
|
107
|
+
"audio_format": self.audio_format,
|
108
|
+
}
|
81
109
|
# sort by keys
|
82
110
|
data = dict(sorted(data.items(), key=lambda item: item[0]))
|
83
111
|
return data
|
pygpt_net/core/ctx/__init__.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.
|
9
|
+
# Updated Date: 2024.11.26 19:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import copy
|
@@ -19,6 +19,7 @@ from pygpt_net.core.types import (
|
|
19
19
|
MODE_AGENT,
|
20
20
|
MODE_AGENT_LLAMA,
|
21
21
|
MODE_ASSISTANT,
|
22
|
+
MODE_AUDIO,
|
22
23
|
MODE_CHAT,
|
23
24
|
MODE_COMPLETION,
|
24
25
|
MODE_EXPERT,
|
@@ -78,6 +79,7 @@ class Ctx:
|
|
78
79
|
MODE_LLAMA_INDEX,
|
79
80
|
MODE_AGENT,
|
80
81
|
MODE_EXPERT,
|
82
|
+
MODE_AUDIO,
|
81
83
|
]
|
82
84
|
self.allowed_modes = {
|
83
85
|
MODE_CHAT: self.all_modes,
|
@@ -89,6 +91,7 @@ class Ctx:
|
|
89
91
|
MODE_LLAMA_INDEX: self.all_modes,
|
90
92
|
MODE_AGENT: self.all_modes,
|
91
93
|
MODE_EXPERT: self.all_modes,
|
94
|
+
MODE_AUDIO: self.all_modes,
|
92
95
|
MODE_AGENT_LLAMA: [MODE_AGENT_LLAMA],
|
93
96
|
}
|
94
97
|
self.current_sys_prompt = ""
|
pygpt_net/core/db/__init__.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.
|
9
|
+
# Updated Date: 2024.11.26 19:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import os
|
@@ -82,6 +82,8 @@ class Database:
|
|
82
82
|
'is_internal',
|
83
83
|
'docs_json',
|
84
84
|
'external_id',
|
85
|
+
'audio_id',
|
86
|
+
'audio_expires_ts',
|
85
87
|
]
|
86
88
|
columns["ctx_meta"] = [
|
87
89
|
'id',
|
@@ -218,7 +220,7 @@ class Database:
|
|
218
220
|
'columns': columns["ctx_item"],
|
219
221
|
'sort_by': columns["ctx_item"],
|
220
222
|
'search_fields': ['id', 'input', 'output', 'input_name', 'output_name', 'meta_id', 'hidden_input', 'hidden_output'],
|
221
|
-
'timestamp_columns': ['input_ts', 'output_ts'],
|
223
|
+
'timestamp_columns': ['input_ts', 'output_ts', 'audio_expires_ts'],
|
222
224
|
'json_columns': ['cmds_json', 'results_json', 'urls_json', 'images_json', 'files_json', 'attachments_json', 'docs_json', 'additional_ctx_json'],
|
223
225
|
'default_sort': 'id',
|
224
226
|
'default_order': 'DESC',
|
@@ -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.
|
9
|
+
# Updated Date: 2024.11.26 02:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
class AttachmentsDebug:
|
@@ -36,6 +36,8 @@ class AttachmentsDebug:
|
|
36
36
|
'send': attachment.send,
|
37
37
|
'key': key,
|
38
38
|
'mode': mode,
|
39
|
+
'type': attachment.type,
|
40
|
+
'consumed': attachment.consumed,
|
39
41
|
}
|
40
42
|
self.window.core.debug.add(self.id, attachment.name, str(data))
|
41
43
|
|
pygpt_net/core/debug/context.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.
|
9
|
+
# Updated Date: 2024.11.26 04:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
import json
|
12
12
|
|
@@ -45,6 +45,10 @@ class ContextDebug:
|
|
45
45
|
self.window.core.debug.add(self.id, 'CMD (current)', str(self.window.core.ctx.current_cmd))
|
46
46
|
self.window.core.debug.add(self.id, 'CMD schema (current)', str(self.window.core.ctx.current_cmd_schema))
|
47
47
|
self.window.core.debug.add(self.id, 'FUNCTIONS (current)', str(self.get_functions()))
|
48
|
+
self.window.core.debug.add(self.id, 'Attachments: last used content',
|
49
|
+
str(self.window.core.attachments.context.last_used_content))
|
50
|
+
self.window.core.debug.add(self.id, 'Attachments: last used context',
|
51
|
+
str(self.window.core.attachments.context.last_used_context))
|
48
52
|
|
49
53
|
current = None
|
50
54
|
if self.window.core.ctx.get_current() is not None:
|
pygpt_net/core/debug/presets.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.
|
9
|
+
# Updated Date: 2024.11.26 19:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import os
|
@@ -15,6 +15,7 @@ from pygpt_net.core.types import (
|
|
15
15
|
MODE_AGENT,
|
16
16
|
MODE_AGENT_LLAMA,
|
17
17
|
MODE_ASSISTANT,
|
18
|
+
MODE_AUDIO,
|
18
19
|
MODE_CHAT,
|
19
20
|
MODE_COMPLETION,
|
20
21
|
MODE_EXPERT,
|
@@ -64,6 +65,7 @@ class PresetsDebug:
|
|
64
65
|
MODE_AGENT: preset.agent,
|
65
66
|
MODE_AGENT_LLAMA: preset.agent_llama,
|
66
67
|
MODE_EXPERT: preset.expert,
|
68
|
+
MODE_AUDIO: preset.audio,
|
67
69
|
'temperature': preset.temperature,
|
68
70
|
'version': preset.version,
|
69
71
|
}
|
pygpt_net/core/events/event.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.
|
9
|
+
# Updated Date: 2024.11.26 19:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import json
|
@@ -27,6 +27,7 @@ class Event(BaseEvent):
|
|
27
27
|
AUDIO_INPUT_TOGGLE = "audio.input.toggle"
|
28
28
|
AUDIO_OUTPUT_STOP = "audio.output.stop"
|
29
29
|
AUDIO_OUTPUT_TOGGLE = "audio.output.toggle"
|
30
|
+
AUDIO_PLAYBACK = "audio.playback"
|
30
31
|
AUDIO_READ_TEXT = "audio.read_text"
|
31
32
|
CMD_EXECUTE = "cmd.execute"
|
32
33
|
CMD_INLINE = "cmd.inline"
|
@@ -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.
|
9
|
+
# Updated Date: 2024.11.26 19:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
|
@@ -18,6 +18,7 @@ from pygpt_net.core.types import (
|
|
18
18
|
MODE_LANGCHAIN,
|
19
19
|
MODE_LLAMA_INDEX,
|
20
20
|
MODE_VISION,
|
21
|
+
MODE_AUDIO,
|
21
22
|
)
|
22
23
|
from pygpt_net.core.bridge.context import BridgeContext
|
23
24
|
from pygpt_net.core.events import Event, KernelEvent, RenderEvent
|
@@ -39,6 +40,7 @@ class Experts:
|
|
39
40
|
MODE_VISION,
|
40
41
|
MODE_LANGCHAIN,
|
41
42
|
MODE_LLAMA_INDEX,
|
43
|
+
MODE_AUDIO,
|
42
44
|
]
|
43
45
|
self.allowed_cmds = ["expert_call"]
|
44
46
|
|