From a65b87c99ec5c3353ce607d59ee5d347956bea44 Mon Sep 17 00:00:00 2001 From: Marcin Szczyglinski Date: Mon, 25 Nov 2024 21:30:21 +0100 Subject: [PATCH] Added "Auto index on upload" option --- CHANGELOG.md | 8 + README.md | 14 +- docs/source/attachments.rst | 4 + src/pygpt_net/CHANGELOG.txt | 8 + src/pygpt_net/controller/attachment.py | 15 ++ src/pygpt_net/controller/chat/attachment.py | 141 +++++++++++++++++- src/pygpt_net/core/attachments/context.py | 55 +++++-- src/pygpt_net/data/config/config.json | 1 + src/pygpt_net/data/locale/locale.de.ini | 8 +- src/pygpt_net/data/locale/locale.en.ini | 8 +- src/pygpt_net/data/locale/locale.es.ini | 8 +- src/pygpt_net/data/locale/locale.fr.ini | 8 +- src/pygpt_net/data/locale/locale.it.ini | 8 +- src/pygpt_net/data/locale/locale.pl.ini | 10 +- src/pygpt_net/data/locale/locale.uk.ini | 8 +- src/pygpt_net/data/locale/locale.zh.ini | 8 +- src/pygpt_net/provider/core/config/patch.py | 8 + src/pygpt_net/ui/layout/chat/attachments.py | 22 +++ .../ui/layout/chat/attachments_ctx.py | 11 +- .../ui/widget/lists/attachment_ctx.py | 68 ++++++++- 20 files changed, 396 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cbbbc0be..1908c65f 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # CHANGELOG +## 2.4.31 (2024-11-25) + +- Added an option checkbox `Auto-index on upload` in the `Attachments` tab: + +**Tip:** To use the `Query only` mode, the file must be indexed in the vector database. This occurs automatically at the time of upload if the `Auto-index on upload` option in the `Attachments` tab is enabled. When uploading large files, such indexing might take a while - therefore, if you are using the `Full context` option, which does not use the index, you can disable the `Auto-index` option to speed up the upload of the attachment. In this case, it will only be indexed when the `Query only` option is called for the first time, and until then, attachment will be available in the form of `Full context` and `Summary`. + +- Added context menu options in `Uploaded attachments` tab: `Open`, `Open Source directory` and `Open Storage directory`. + ## 2.4.30 (2024-11-25) - Added instruction to model about mapped data directory in both legacy and IPython code interepreter. diff --git a/README.md b/README.md index 6e20da0d..110d1f19 100755 --- a/README.md +++ b/README.md @@ -356,7 +356,7 @@ This mode in **PyGPT** mirrors `ChatGPT`, allowing you to chat with models such The main part of the interface is a chat window where conversations appear. Right below that is where you type your messages. On the right side of the screen, there's a section to set up or change your system prompts. You can also save these setups as presets to quickly switch between different models or tasks. -Above where you type your messages, the interface shows you the number of tokens your message will use up as you type it – this helps to keep track of usage. There's also a feature to upload files in this area. Go to the `Files` tab to manage your uploads or add attachments to send to the OpenAI API (but this makes effect only in `Assisant` and `Vision` modes). +Above where you type your messages, the interface shows you the number of tokens your message will use up as you type it – this helps to keep track of usage. There's also a feature to upload files in this area. Go to the `Attachments` tab to manage your uploads or add attachments to send to the OpenAI API (but this makes effect only in `Assisant` and `Vision` modes). ![v2_mode_chat](https://github.com/szczyglis-dev/py-gpt/assets/61396542/f573ee22-8539-4259-b180-f97e54bc0d94) @@ -1097,6 +1097,10 @@ The content from the uploaded attachments will be used in the current conversati **Note:** Only text files from the list above are included in the additional context. Images will not be included in the context but will be used by the vision model in real-time. Adding image files to the context will be available in future versions. +**Uploading larger files and auto-index:** + +To use the `Query only` mode, the file must be indexed in the vector database. This occurs automatically at the time of upload if the `Auto-index on upload` option in the `Attachments` tab is enabled. When uploading large files, such indexing might take a while - therefore, if you are using the `Full context` option, which does not use the index, you can disable the `Auto-index` option to speed up the upload of the attachment. In this case, it will only be indexed when the `Query only` option is called for the first time, and until then, attachment will be available in the form of `Full context` and `Summary`. + ## Files (download, code generation) **PyGPT** enables the automatic download and saving of files created by the model. This is carried out in the background, with the files being saved to an `data` folder located within the user's working directory. To view or manage these files, users can navigate to the `Files` tab which features a file browser for this specific directory. Here, users have the interface to handle all files sent by the AI. @@ -3652,6 +3656,14 @@ may consume additional tokens that are not displayed in the main window. ## Recent changes: +**2.4.31 (2024-11-25)** + +- Added an option checkbox `Auto-index on upload` in the `Attachments` tab: + +**Tip:** To use the `Query only` mode, the file must be indexed in the vector database. This occurs automatically at the time of upload if the `Auto-index on upload` option in the `Attachments` tab is enabled. When uploading large files, such indexing might take a while - therefore, if you are using the `Full context` option, which does not use the index, you can disable the `Auto-index` option to speed up the upload of the attachment. In this case, it will only be indexed when the `Query only` option is called for the first time, and until then, attachment will be available in the form of `Full context` and `Summary`. + +- Added context menu options in `Uploaded attachments` tab: `Open`, `Open Source directory` and `Open Storage directory`. + **2.4.30 (2024-11-25)** - Added instruction to model about mapped data directory in both legacy and IPython code interepreter. diff --git a/docs/source/attachments.rst b/docs/source/attachments.rst index 9e363616..bc010590 100755 --- a/docs/source/attachments.rst +++ b/docs/source/attachments.rst @@ -48,6 +48,10 @@ The content from the uploaded attachments will be used in the current conversati **Note:** Only text files from the list above are included in the additional context. Images will not be included in the context but will be used by the vision model in real-time. Adding image files to the context will be available in future versions. +**Uploading larger files and auto-index:** + +To use the ``Query only`` mode, the file must be indexed in the vector database. This occurs automatically at the time of upload if the ``Auto-index on upload`` option in the ``Attachments`` tab is enabled. When uploading large files, such indexing might take a while - therefore, if you are using the ``Full context`` option, which does not use the index, you can disable the ``Auto-index`` option to speed up the upload of the attachment. In this case, it will only be indexed when the ``Query only`` option is called for the first time, and until then, attachment will be available in the form of ``Full context`` and ``Summary``. + Files (download, code generation) --------------------------------- diff --git a/src/pygpt_net/CHANGELOG.txt b/src/pygpt_net/CHANGELOG.txt index 51112658..be9cb6fb 100755 --- a/src/pygpt_net/CHANGELOG.txt +++ b/src/pygpt_net/CHANGELOG.txt @@ -1,3 +1,11 @@ +2.4.31 (2024-11-25) + +- Added an option checkbox `Auto-index on upload` in the `Attachments` tab: + +Tip: To use the `Query only` mode, the file must be indexed in the vector database. This occurs automatically at the time of upload if the `Auto-index on upload` option in the `Attachments` tab is enabled. When uploading large files, such indexing might take a while - therefore, if you are using the `Full context` option, which does not use the index, you can disable the `Auto-index` option to speed up the upload of the attachment. In this case, it will only be indexed when the `Query only` option is called for the first time, and until then, attachment will be available in the form of `Full context` and `Summary`. + +- Added context menu options in `Uploaded attachments` tab: `Open`, `Open Source directory` and `Open Storage directory`. + 2.4.30 (2024-11-25) - Added instruction to model about mapped data directory in both legacy and IPython code interepreter. diff --git a/src/pygpt_net/controller/attachment.py b/src/pygpt_net/controller/attachment.py index b6ee34db..55942111 100755 --- a/src/pygpt_net/controller/attachment.py +++ b/src/pygpt_net/controller/attachment.py @@ -51,6 +51,13 @@ def setup(self): else: self.window.ui.nodes['attachments.capture_clear'].setChecked(False) + # auto-index + if self.window.core.config.has('attachments_auto_index') \ + and self.window.core.config.get('attachments_auto_index'): + self.window.ui.nodes['attachments.auto_index'].setChecked(True) + else: + self.window.ui.nodes['attachments.auto_index'].setChecked(False) + self.window.core.attachments.load() self.update() @@ -411,6 +418,14 @@ def toggle_capture_clear(self, value: bool): """ self.window.core.config.set('attachments_capture_clear', value) + def toggle_auto_index(self, value: bool): + """ + Toggle auto index + + :param value: value of the checkbox + """ + self.window.core.config.set('attachments_auto_index', value) + def is_capture_clear(self) -> bool: """ Return True if capture clear is enabled diff --git a/src/pygpt_net/controller/chat/attachment.py b/src/pygpt_net/controller/chat/attachment.py index af376879..f8e6492e 100755 --- a/src/pygpt_net/controller/chat/attachment.py +++ b/src/pygpt_net/controller/chat/attachment.py @@ -114,9 +114,12 @@ def upload(self, meta: CtxMeta, mode: str, prompt: str) -> bool: :return: True if uploaded """ self.uploaded = False + auto_index = self.window.core.config.get("attachments_auto_index", False) attachments = self.window.core.attachments.get_all(mode, only_files=True) + if self.is_verbose() and len(attachments) > 0: print("\nUploading attachments...\nWork Mode: {}".format(mode)) + for uuid in attachments: attachment = attachments[uuid] if not self.is_allowed(attachment.path): @@ -137,7 +140,13 @@ def upload(self, meta: CtxMeta, mode: str, prompt: str) -> bool: if self.is_allowed(str(path)): if self.is_verbose(): print("Uploading unpacked from archive: {}".format(path_relative)) - item = self.window.core.attachments.context.upload(meta, sub_attachment, prompt) + item = self.window.core.attachments.context.upload( + meta=meta, + attachment=sub_attachment, + prompt=prompt, + real_path=attachment.path, + auto_index=auto_index, + ) if item: item["path"] = os.path.basename(attachment.path) + "/" + path_relative item["size"] = os.path.getsize(path) @@ -149,7 +158,13 @@ def upload(self, meta: CtxMeta, mode: str, prompt: str) -> bool: attachment.consumed = True self.window.core.filesystem.packer.remove_tmp(tmp_path) # clean else: - item = self.window.core.attachments.context.upload(meta, attachment, prompt) + item = self.window.core.attachments.context.upload( + meta=meta, + attachment=attachment, + prompt=prompt, + real_path=attachment.path, + auto_index=auto_index, + ) if item: if meta.additional_ctx is None: meta.additional_ctx = [] @@ -362,6 +377,128 @@ def clear(self, force: bool = False, remove_local=False, auto: bool = False): self.window.core.attachments.context.clear(meta, delete_files=remove_local) self.update_list(meta) + def select(self, idx: int): + """ + Select uploaded file + + :param idx: index of file + """ + pass + + def open_by_idx(self, idx: int): + """ + Open attachment by index + + :param idx: Index on list + """ + meta = self.window.core.ctx.get_current_meta() + if meta is None or meta.additional_ctx is None: + return + items = self.window.core.attachments.context.get_all(meta) + if idx < len(items): + item = items[idx] + path = item["path"] + if "real_path" in item: + path = item["real_path"] + if os.path.exists(path) and os.path.isfile(path): + print("Opening attachment: {}".format(path)) + self.window.controller.files.open(path) + + def open_dir_src_by_idx(self, idx: int): + """ + Open source directory by index + + :param idx: Index on list + """ + meta = self.window.core.ctx.get_current_meta() + if meta is None or meta.additional_ctx is None: + return + items = self.window.core.attachments.context.get_all(meta) + if idx < len(items): + item = items[idx] + path = item["path"] + if "real_path" in item: + path = item["real_path"] + dir = os.path.dirname(path) + if os.path.exists(dir) and os.path.isdir(dir): + print("Opening source directory: {}".format(dir)) + self.window.controller.files.open(dir) + + def open_dir_dest_by_idx(self, idx: int): + """ + Open destination directory by index + + :param idx: Index on list + """ + meta = self.window.core.ctx.get_current_meta() + if meta is None or meta.additional_ctx is None: + return + items = self.window.core.attachments.context.get_all(meta) + if idx < len(items): + item = items[idx] + root_dir = self.window.core.attachments.context.get_dir(meta) + dir = os.path.join(root_dir, item["uuid"]) + if os.path.exists(dir) and os.path.isdir(dir): + self.window.controller.files.open(dir) + print("Opening destination directory: {}".format(dir)) + + def has_file_by_idx(self, idx: int) -> bool: + """ + Check if has file by index + + :param idx: Index on list + :return: True if has file + """ + meta = self.window.core.ctx.get_current_meta() + if meta is None or meta.additional_ctx is None: + return False + items = self.window.core.attachments.context.get_all(meta) + if idx < len(items): + item = items[idx] + path = item["path"] + if "real_path" in item: + path = item["real_path"] + return os.path.exists(path) and os.path.isfile(path) + return False + + def has_src_by_idx(self, idx: int) -> bool: + """ + Check if has source directory by index + + :param idx: Index on list + :return: True if has source directory + """ + meta = self.window.core.ctx.get_current_meta() + if meta is None or meta.additional_ctx is None: + return False + items = self.window.core.attachments.context.get_all(meta) + if idx < len(items): + item = items[idx] + path = item["path"] + if "real_path" in item: + path = item["real_path"] + dir = os.path.dirname(path) + return os.path.exists(dir) and os.path.isdir(dir) + return False + + def has_dest_by_idx(self, idx: int) -> bool: + """ + Check if has destination directory by index + + :param idx: Index on list + :return: True if has destination directory + """ + meta = self.window.core.ctx.get_current_meta() + if meta is None or meta.additional_ctx is None: + return False + items = self.window.core.attachments.context.get_all(meta) + if idx < len(items): + item = items[idx] + root_dir = self.window.core.attachments.context.get_dir(meta) + dir = os.path.join(root_dir, item["uuid"]) + return os.path.exists(dir) and os.path.isdir(dir) + return False + @Slot(object) def handle_upload_error(self, error: Exception): """ diff --git a/src/pygpt_net/core/attachments/context.py b/src/pygpt_net/core/attachments/context.py index 4c6483c9..951f5cd6 100755 --- a/src/pygpt_net/core/attachments/context.py +++ b/src/pygpt_net/core/attachments/context.py @@ -111,6 +111,28 @@ def query_context(self, meta: CtxMeta, query: str) -> str: if not os.path.exists(meta_path) or not os.path.isdir(meta_path): return "" idx_path = os.path.join(self.get_dir(meta), self.dir_index) + + indexed = False + # index files if not indexed by auto_index + for i, file in enumerate(meta.additional_ctx): + if "indexed" not in file or not file["indexed"]: + file_id = file["uuid"] + file_idx_path = os.path.join(meta_path, file_id) + file_path = os.path.join(file_idx_path, file["name"]) + model = None + doc_ids = self.window.core.idx.indexing.index_attachment(file_path, idx_path, model) + if self.is_verbose(): + print("Attachments: indexed. Doc IDs: {}".format(doc_ids)) + file["indexed"] = True + file["doc_ids"] = doc_ids + #meta.additional_ctx[i] = file # update meta + indexed = True + + if indexed: + # update ctx in DB + self.window.core.ctx.replace(meta) + self.window.core.ctx.save(meta.id) + model = None result = self.window.core.idx.chat.query_attachment(query, idx_path, model) @@ -162,13 +184,22 @@ def summary_context(self, ctx: CtxItem, query: str) -> str: print("Attachments: summary received: {}".format(response)) return response - def upload(self, meta: CtxMeta, attachment: AttachmentItem, prompt: str) -> dict: + def upload( + self, + meta: CtxMeta, + attachment: AttachmentItem, + prompt: str, + auto_index: bool = False, + real_path: str = None + ) -> dict: """ Upload attachment for context :param meta: CtxMeta instance :param attachment: AttachmentItem instance :param prompt: user input prompt + :param auto_index: auto index + :param real_path: real path :return: Dict with attachment data """ if self.is_verbose(): @@ -185,7 +216,8 @@ def upload(self, meta: CtxMeta, attachment: AttachmentItem, prompt: str) -> dict if self.is_verbose(): print("Attachments: created path: {}".format(meta_path)) - print("Attachments: vector index path: {}".format(index_path)) + if auto_index: + print("Attachments: vector index path: {}".format(index_path)) # copy raw file raw_path = os.path.join(file_idx_path, name) @@ -214,24 +246,29 @@ def upload(self, meta: CtxMeta, attachment: AttachmentItem, prompt: str) -> dict tokens = self.window.core.tokens.from_str(text) # index file to ctx index - model = None - doc_ids = self.window.core.idx.indexing.index_attachment(attachment.path, index_path, model) - - if self.is_verbose(): - print("Attachments: indexed. Doc IDs: {}".format(doc_ids)) + doc_ids = [] + if auto_index: + model = None + doc_ids = self.window.core.idx.indexing.index_attachment(attachment.path, index_path, model) + if self.is_verbose(): + print("Attachments: indexed. Doc IDs: {}".format(doc_ids)) result = { "name": name, "path": attachment.path, "type": "local_file", "uuid": str(file_id), - "doc_ids": doc_ids, - "indexed": True, "content_type": "text", "size": os.path.getsize(attachment.path), "length": len(text), "tokens": tokens, + "indexed": False, } + if auto_index: + result["indexed"] = True + result["doc_ids"] = doc_ids + if real_path: + result["real_path"] = real_path if self.is_verbose(): print("Attachments: uploaded: {}".format(result)) diff --git a/src/pygpt_net/data/config/config.json b/src/pygpt_net/data/config/config.json index 2f2d6a51..891bbd8e 100755 --- a/src/pygpt_net/data/config/config.json +++ b/src/pygpt_net/data/config/config.json @@ -65,6 +65,7 @@ "assistant": "", "assistant_thread": "", "assistant.store.hide_threads": true, + "attachments_auto_index": false, "attachments_send_clear": true, "attachments_capture_clear": true, "audio.transcribe.convert_video": true, diff --git a/src/pygpt_net/data/locale/locale.de.ini b/src/pygpt_net/data/locale/locale.de.ini index ddc6564f..de467afc 100644 --- a/src/pygpt_net/data/locale/locale.de.ini +++ b/src/pygpt_net/data/locale/locale.de.ini @@ -29,6 +29,9 @@ action.mkdir = Verzeichnis erstellen... action.move_to = Verschieben nach action.open = Öffnen action.open_dir = Im Verzeichnis öffnen... +action.open_dir_dest = Zielverzeichnis öffnen +action.open_dir_src = Quellverzeichnis öffnen +action.open_dir_storage = Speicherverzeichnis öffnen action.paste = Einfügen action.pin = Oben anheften action.profile.delete = Profil entfernen (nur aus Liste) @@ -93,16 +96,19 @@ assistant.tool.file_search = Chat mit Dateien assistant.tool.function = Werkzeug: Funktion assistant.tool.retrieval = Werkzeug: Abruf assistant.vector_store = Vektor Speicher +attachments.auto_index = Automatische Indizierung beim Hochladen attachments.btn.add = Datei hinzufügen attachments.btn.clear = Dateien löschen attachments.capture_clear = Beim Erfassen löschen attachments.clear.confirm = Liste löschen? +attachments.ctx.indexed = Ja attachments.ctx.label = Zusätzlicher Kontext attachments.ctx.mode.full = Vollständiger Kontext attachments.ctx.mode.off = Aus (deaktivieren) attachments.ctx.mode.query = Nur Abfrage attachments.ctx.mode.summary = Zusammenfassung attachments.delete.confirm = Datei aus der Liste entfernen? +attachments.header.idx = Index attachments.header.length = Länge (Zeichen / Tokens) attachments.header.name = Name attachments.header.path = Pfad @@ -902,7 +908,7 @@ text.context_menu.copy_to.notepad = Notepad text.context_menu.find = Suchen... theme.dark = Dunkel theme.light = Hell -tip.input.attachments = Hier können Sie Ihrer Nachricht Anhänge hinzufügen, wenn der Modus dies unterstützt. Hier können Sie Dateien zur Analyse im Assistant-Modus oder Bilder und von der Kamera erfasste Bilder zur Analyse im Vision-Modus senden. +tip.input.attachments = Hier können Sie Anhänge zur Nachricht hinzufügen, die Sie senden. Sie können Textdateien, Code-Dateien, PDFs, Dokumente, Tabellenkalkulationen und andere senden - sie werden als zusätzlicher Kontext in der Konversation verwendet. Sie können auch Bilder oder aufgenommene Fotos von einer Kamera zur Analyse senden. tip.input.attachments.ctx = Unten sind die hochgeladenen und indexierten Anhänge, die Sie als zusätzlichen Kontext verwenden können. Der zusätzliche Kontext steht für die gesamte obige Diskussion zur Verfügung. Optionen: Vollständiger Kontext - enthält den gesamten zusätzlichen Inhalt (roh) im System-Prompt, Nur Abfrage - fragt nur den indexierten Inhalt ab, Zusammenfassung - enthält eine Zusammenfassung des hinzugefügten Inhalts im Prompt, Aus - zusätzlichen Kontext deaktivieren. tip.input.attachments.uploaded = Hier ist eine Liste von Dateien, die im Assistant-Modus auf den Server hochgeladen wurden. Diese Dateien befinden sich auf einem entfernten Server und nicht auf Ihrem lokalen Computer, sodass das Modell sie mit extern auf dem entfernten Server verfügbaren Werkzeugen verwenden und analysieren kann. tip.output.tab.calendar = Mit dem Kalender können Sie zu ausgewählten Gesprächen von einem bestimmten Tag navigieren. Klicken Sie in den Kalender auf einen Tag, um die Anzeige des Chat-Verlaufs auf diesen Tag zu beschränken. Sie können auch Tagesnotizen erstellen und ihnen farbige Etiketten zuweisen. diff --git a/src/pygpt_net/data/locale/locale.en.ini b/src/pygpt_net/data/locale/locale.en.ini index 7ecf569e..2401b620 100644 --- a/src/pygpt_net/data/locale/locale.en.ini +++ b/src/pygpt_net/data/locale/locale.en.ini @@ -31,6 +31,9 @@ action.move_to = Move to action.new = New... action.open = Open action.open_dir = Open in directory... +action.open_dir_dest = Open Destination Directory +action.open_dir_src = Open Source Directory +action.open_dir_storage = Open Storage directory action.open_new_window = Open (new window) action.paste = Paste action.pin = Pin on top @@ -102,10 +105,12 @@ assistant.tool.file_search = Chat with files assistant.tool.function = Function assistant.tool.retrieval = Retrieval assistant.vector_store = Vector Store +attachments.auto_index = Auto-index on upload attachments.btn.add = Add file attachments.btn.clear = Clear files attachments.capture_clear = Clear on capture attachments.clear.confirm = Clear list? +attachments.ctx.indexed = Yes attachments.ctx.label = Extra context attachments.ctx.mode.full = Full context attachments.ctx.mode.off = Off (disable) @@ -113,6 +118,7 @@ attachments.ctx.mode.query = Query only attachments.ctx.mode.summary = Summary attachments.delete.confirm = Remove file from list? attachments.header.ctx = Ctx +attachments.header.idx = Idx attachments.header.length = Length (chars / tokens) attachments.header.name = Name attachments.header.path = Path @@ -1133,7 +1139,7 @@ text.context_menu.copy_to.python.input = Python interpreter (Input) text.context_menu.find = Find... theme.dark = Dark theme.light = Light -tip.input.attachments = Here you can add attachments to the message you are sending if the mode supports it. You can send files here for analysis in Assistant mode or images and captured images from the camera for analysis in Vision mode. +tip.input.attachments = Here you can add attachments to the message you are sending. You can send text files, code files, PDFs, documents, spreadsheets, and others - they will be used as additional context in the conversation. You can also send images or captured photos from a camera for analysis. tip.input.attachments.ctx = Below are the uploaded and indexed attachments that you can use as additional context. The additional context is available for above entire discussion. Options: Full context - includes the entire additional content (raw) in the system prompt, Query only - only queries the indexed content, Summary - includes a summary of the added content in the prompt, Off - disable additional context. tip.input.attachments.uploaded = Here is a list of files uploaded to the server in Assistant mode. These files are located on a remote server, not on your local computer, so the model can use and analyze them using tools available externally on the remote server. tip.output.tab.calendar = Using the calendar, you can navigate back to selected conversations from a specific day. Click on a day in the calendar to limit the display of chat history to that day. You can also create day notes and assign them colorful labels. diff --git a/src/pygpt_net/data/locale/locale.es.ini b/src/pygpt_net/data/locale/locale.es.ini index 7997c3eb..016f1f4b 100644 --- a/src/pygpt_net/data/locale/locale.es.ini +++ b/src/pygpt_net/data/locale/locale.es.ini @@ -29,6 +29,9 @@ action.mkdir = Crear directorio... action.move_to = Mover a action.open = Abri action.open_dir = Abrir en el directorio... +action.open_dir_dest = Abrir directorio de destino +action.open_dir_src = Abrir directorio fuente +action.open_dir_storage = Abrir directorio de almacenamiento action.paste = Pegar action.pin = Fijar en la parte superior action.profile.delete = Eliminar perfil (solo de la lista) @@ -93,16 +96,19 @@ assistant.tool.file_search = Chat con archivos assistant.tool.function = Herramienta: función assistant.tool.retrieval = Herramienta: recuperación assistant.vector_store = Almacén de vectores +attachments.auto_index = Indexación automática al subir attachments.btn.add = Añadir archivo attachments.btn.clear = Limpiar archivos attachments.capture_clear = Limpiar al capturar attachments.clear.confirm = ¿Limpiar la lista? +attachments.ctx.indexed = Sí attachments.ctx.label = Contexto adicional attachments.ctx.mode.full = Contexto completo attachments.ctx.mode.off = Apagado (desactivar) attachments.ctx.mode.query = Solo consulta attachments.ctx.mode.summary = Resumen attachments.delete.confirm = ¿Quitar archivo de la lista? +attachments.header.idx = Índice attachments.header.length = Longitud (caracteres / tokens) attachments.header.name = Nombre attachments.header.path = Ruta @@ -902,7 +908,7 @@ text.context_menu.copy_to.notepad = Bloc de notas text.context_menu.find = Encontrar... theme.dark = Oscuro theme.light = Claro -tip.input.attachments = Aquí puedes añadir adjuntos al mensaje que estás enviando si el modo lo permite. Aquí puedes enviar archivos para análisis en el modo Asistente o imágenes y capturas de la cámara para análisis en el modo Visión. +tip.input.attachments = Aquí puedes agregar archivos adjuntos al mensaje que estás enviando. Puedes enviar archivos de texto, archivos de código, PDF, documentos, hojas de cálculo, y otros - se utilizarán como contexto adicional en la conversación. También puedes enviar imágenes o fotos capturadas de una cámara para su análisis. tip.input.attachments.ctx = A continuación se muestran los archivos adjuntos cargados e indexados que puede usar como contexto adicional. El contexto adicional está disponible para toda la discusión anterior. Opciones: Contexto completo - incluye todo el contenido adicional (en bruto) en el aviso del sistema, Solo consulta - solo consulta el contenido indexado, Resumen - incluye un resumen del contenido agregado en el aviso, Apagado - desactiva el contexto adicional. tip.input.attachments.uploaded = Aquí tienes una lista de archivos subidos al servidor en el modo Asistente. Estos archivos están ubicados en un servidor remoto, no en tu computadora local, por lo que el modelo puede usarlos y analizarlos utilizando herramientas disponibles externamente en el servidor remoto. tip.output.tab.calendar = Usando el calendario, puedes navegar de vuelta a conversaciones seleccionadas de un día específico. Haz clic en un día en el calendario para limitar la visualización del historial de chat a ese día. También puedes crear notas diarias y asignarles etiquetas de colores. diff --git a/src/pygpt_net/data/locale/locale.fr.ini b/src/pygpt_net/data/locale/locale.fr.ini index f5ebfbe2..2344fbd8 100644 --- a/src/pygpt_net/data/locale/locale.fr.ini +++ b/src/pygpt_net/data/locale/locale.fr.ini @@ -29,6 +29,9 @@ action.mkdir = Créer un répertoire... action.move_to = Déplacer vers action.open = Ouvrir action.open_dir = Ouvrir dans le répertoire... +action.open_dir_dest = Ouvrir le répertoire de destination +action.open_dir_src = Ouvrir le répertoire source +action.open_dir_storage = Ouvrir le répertoire de stockage action.paste = Coller action.pin = Épingler en haut action.profile.delete = Supprimer le profil (seulement de la liste) @@ -93,16 +96,19 @@ assistant.tool.file_search = Chat avec des fichiers assistant.tool.function = Outil : fonction assistant.tool.retrieval = Outil : récupération assistant.vector_store = Base vectorielle +attachments.auto_index = Indexation automatique lors du téléchargement attachments.btn.add = Ajouter un fichier attachments.btn.clear = Effacer les fichiers attachments.capture_clear = Effacer à la capture attachments.clear.confirm = Effacer la liste ? +attachments.ctx.indexed = Oui attachments.ctx.label = Contexte supplémentaire attachments.ctx.mode.full = Contexte complet attachments.ctx.mode.off = Désactivé attachments.ctx.mode.query = Requête uniquement attachments.ctx.mode.summary = Résumé attachments.delete.confirm = Supprimer le fichier de la liste ? +attachments.header.idx = Index attachments.header.length = Longueur (caractères / jetons) attachments.header.name = Nom attachments.header.path = Chemin @@ -902,7 +908,7 @@ text.context_menu.copy_to.notepad = Bloc-notes text.context_menu.find = Trouver... theme.dark = Sombre theme.light = Lumière -tip.input.attachments = Ici, vous pouvez ajouter des pièces jointes au message que vous envoyez si le mode le permet. Vous pouvez envoyer ici des fichiers pour analyse en mode Assistant ou des images et des images capturées de la caméra pour analyse en mode Vision. +tip.input.attachments = Ici, vous pouvez ajouter des pièces jointes au message que vous envoyez. Vous pouvez envoyer des fichiers texte, des fichiers de code, des PDF, des documents, des feuilles de calcul, et d'autres - ils seront utilisés comme contexte supplémentaire dans la conversation. Vous pouvez également envoyer des images ou des photos capturées par une caméra pour analyse. tip.input.attachments.ctx = Ci-dessous se trouvent les pièces jointes téléchargées et indexées que vous pouvez utiliser comme contexte supplémentaire. Le contexte supplémentaire est disponible pour toute la discussion ci-dessus. Options : Contexte complet - inclut tout le contenu supplémentaire (brut) dans l'invite du système, Requête uniquement - interroge uniquement le contenu indexé, Résumé - inclut un résumé du contenu ajouté dans l'invite, Désactivé - désactive le contexte supplémentaire. tip.input.attachments.uploaded = Voici une liste de fichiers téléchargés sur le serveur en mode Assistant. Ces fichiers sont situés sur un serveur distant, pas sur votre ordinateur local, donc le modèle peut les utiliser et les analyser à l'aide des outils disponibles à l'extérieur sur le serveur distant. tip.output.tab.calendar = En utilisant le calendrier, vous pouvez revenir à des conversations sélectionnées d'un jour spécifique. Cliquez sur un jour dans le calendrier pour limiter l'affichage de l'historique de chat à ce jour. Vous pouvez également créer des notes de jour et leur attribuer des étiquettes colorées. diff --git a/src/pygpt_net/data/locale/locale.it.ini b/src/pygpt_net/data/locale/locale.it.ini index c068b950..711fd398 100644 --- a/src/pygpt_net/data/locale/locale.it.ini +++ b/src/pygpt_net/data/locale/locale.it.ini @@ -29,6 +29,9 @@ action.mkdir = Crea directory... action.move_to = Sposta in action.open = Apri action.open_dir = Apri nella cartella... +action.open_dir_dest = Apri la cartella di destinazione +action.open_dir_src = Apri la cartella sorgente +action.open_dir_storage = Apri la cartella di archiviazione action.paste = Incolla action.pin = Fissa in alto action.profile.delete = Rimuovi profilo (solo dall'elenco) @@ -93,16 +96,19 @@ assistant.tool.file_search = Chat con file assistant.tool.function = Strumento: funzione assistant.tool.retrieval = Strumento: recupero assistant.vector_store = Archivio vettoriale +attachments.auto_index = Indicizzazione automatica al caricamento attachments.btn.add = Aggiungi file attachments.btn.clear = Pulisci file attachments.capture_clear = Pulisci alla cattura attachments.clear.confirm = Pulire l'elenco? +attachments.ctx.indexed = Sì attachments.ctx.label = Contesto aggiuntivo attachments.ctx.mode.full = Contesto completo attachments.ctx.mode.off = Spento (disabilita) attachments.ctx.mode.query = Solo query attachments.ctx.mode.summary = Sommario attachments.delete.confirm = Rimuovere il file dall'elenco? +attachments.header.idx = Indice attachments.header.length = Lunghezza (caratteri / token) attachments.header.name = Nome attachments.header.path = Percorso @@ -902,7 +908,7 @@ text.context_menu.copy_to.notepad = Blocco note text.context_menu.find = Trova... theme.dark = Scuro theme.light = Luminoso -tip.input.attachments = Qui puoi aggiungere allegati al messaggio che stai inviando se la modalità lo supporta. Qui puoi inviare файлы per l'analisi in modalità Assistant o immagini e immagini catturate dalla fotocamera per l'analisi in modalità Vision. +tip.input.attachments = Qui puoi aggiungere allegati al messaggio che stai inviando. Puoi inviare file di testo, file di codice, PDF, documenti, fogli di calcolo e altri - verranno utilizzati come contesto aggiuntivo nella conversazione. Puoi anche inviare immagini o foto catturate da una fotocamera per l'analisi. tip.input.attachments.ctx = Di seguito sono riportati gli allegati caricati e indicizzati che puoi utilizzare come contesto aggiuntivo. Il contesto aggiuntivo è disponibile per l'intera discussione sopra. Opzioni: Contesto completo - include tutto il contenuto aggiuntivo (grezzo) nel prompt del sistema, Solo query - interroga solo il contenuto indicizzato, Sommario - include un sommario del contenuto aggiunto nel prompt, Spento - disabilita il contesto aggiuntivo. tip.input.attachments.uploaded = Qui è presente un elenco di файлы caricati sul server in modalità Assistant. Questi файлы si trovano su un сервер remoto, non sul tuo computer locale, quindi il modello può utilizzarli e analizzarli utilizzando strumenti disponibili all'esterno sul сервер remoto. tip.output.tab.calendar = Utilizzando il calendario, puoi tornare a conversazioni selezionate di un giorno specifico. Clicca su un giorno nel calendario per limitare la visualizzazione della cronologia della chat a quel giorno. Puoi anche creare note giornaliere e assegnarle etichette colorate. diff --git a/src/pygpt_net/data/locale/locale.pl.ini b/src/pygpt_net/data/locale/locale.pl.ini index 552b2343..66d9ec9b 100644 --- a/src/pygpt_net/data/locale/locale.pl.ini +++ b/src/pygpt_net/data/locale/locale.pl.ini @@ -29,6 +29,9 @@ action.mkdir = Utwórz katalog... action.move_to = Przenieś do action.open = Otwórz action.open_dir = Otwórz w katalogu... +action.open_dir_dest = Otwórz katalog docelowy +action.open_dir_src = Otwórz katalog źródłowy +action.open_dir_storage = Otwórz katalog magazynowy action.paste = Wklej action.pin = Przypnij na górze action.profile.delete = Usuń profil (tylko z listy) @@ -93,16 +96,19 @@ assistant.tool.file_search = Czat z plikami assistant.tool.function = Tool: function assistant.tool.retrieval = Tool: retrieval assistant.vector_store = Baza wektorowa +attachments.auto_index = Auto-indeksacja przy przesyłaniu attachments.btn.add = Dodaj plik attachments.btn.clear = Wyczyść attachments.capture_clear = Wyczyść przy przechwytywaniu attachments.clear.confirm = Wyczyścić listę plików? +attachments.ctx.indexed = Tak attachments.ctx.label = Dodatkowy kontekst attachments.ctx.mode.full = Pełny kontekst attachments.ctx.mode.off = Wyłączone attachments.ctx.mode.query = Tylko zapytanie attachments.ctx.mode.summary = Podsumowanie attachments.delete.confirm = Usunąć plik z listy? +attachments.header.idx = Indeks attachments.header.length = Długość (znaki / tokeny) attachments.header.name = Nazwa attachments.header.path = Ścieżka @@ -746,7 +752,7 @@ settings.cmd.field.desc = Włącz narzędzie `{cmd}`. settings.cmd.field.enable = Narzędzie: {cmd} settings.cmd.field.instruction = Instrukcja dla modelu settings.cmd.field.params = Parametry JSON (argumenty narzędzia) -settings.cmd.field.tooltip = Włącz narzędzie `{cmd}` +settings.cmd.field.tooltip = Włącz narzędzie `{cmd}` settings.context_threshold = Zarezerwowany kontekst settings.ctx.audio = Zawsze pokazuj ikonę audio settings.ctx.auto_summary = Kontekst: auto-podsumowanie @@ -903,7 +909,7 @@ text.context_menu.copy_to.notepad = Notatnik text.context_menu.find = Znajdź... theme.dark = Ciemny theme.light = Jasny -tip.input.attachments = Tutaj możesz dodać załączniki do wysyłanej wiadomości, jeśli tryb na to pozwala. Możesz wysyłać pliki do analizy w trybie Asystenta lub obrazy i przechwycone zdjęcia z kamery do analizy w trybie Vision. +tip.input.attachments = Tutaj możesz dodać załączniki do wysyłanej wiadomości. Możesz wysyłać pliki tekstowe, z kodem, PDF, dokumenty, arkusze i inne - zostaną one użyte jako dodatkowy kontekst w konwersacji. Możesz także wysyłać obrazy lub przechwycone zdjęcia z kamery do analizy. tip.input.attachments.ctx = Poniżej znajdują się przesłane i zindeksowane załączniki, które możesz wykorzystać jako dodatkowy kontekst. Dodatkowy kontekst jest dostępny dla całej powyższej dyskusji. Opcje: Pełny kontekst - zawiera cały dodatkowy materiał (surowy) w zapytaniu systemowym, Tylko zapytanie - zapytuje tylko zindeksowaną treść, Podsumowanie - zawiera podsumowanie dodanej treści w zapytaniu, Wyłączone - wyłącza dodatkowy kontekst. tip.input.attachments.uploaded = Tutaj znajduje się lista plików przesłanych na serwer w trybie Asystenta. Te pliki znajdują się na zdalnym serwerze, a nie na lokalnym komputerze, więc model może używać i analizować je za pomocą narzędzi dostępnych zewnętrznie na zdalnym serwerze. tip.output.tab.calendar = Korzystając z kalendarza, możesz wrócić do wybranych rozmów z określonego dnia. Kliknij na dzień w kalendarzu, aby ograniczyć wyświetlanie historii czatu do tego dnia. Możesz również tworzyć notatki dnia i przypisywać im kolorowe etykiety. diff --git a/src/pygpt_net/data/locale/locale.uk.ini b/src/pygpt_net/data/locale/locale.uk.ini index 58095f51..39ee6933 100644 --- a/src/pygpt_net/data/locale/locale.uk.ini +++ b/src/pygpt_net/data/locale/locale.uk.ini @@ -29,6 +29,9 @@ action.mkdir = Створити каталог... action.move_to = Перемістити до action.open = Відкрити action.open_dir = Відкрити в директорії... +action.open_dir_dest = Відкрити пункт призначення +action.open_dir_src = Відкрити вихідний каталог +action.open_dir_storage = Відкрити каталог зберігання action.paste = Вставити action.pin = Прикріпити зверху action.profile.delete = Видалити профіль (лише зі списку) @@ -93,16 +96,19 @@ assistant.tool.file_search = Чат з файлами assistant.tool.function = Інструмент: функція assistant.tool.retrieval = Інструмент: пошук assistant.vector_store = Векторне сховище +attachments.auto_index = Автоматичне індексування при завантаженні attachments.btn.add = Додати файл attachments.btn.clear = Очистити файли attachments.capture_clear = Очистити під час захоплення attachments.clear.confirm = Очистити список? +attachments.ctx.indexed = Так attachments.ctx.label = Додатковий контекст attachments.ctx.mode.full = Повний контекст attachments.ctx.mode.off = Вимкнено attachments.ctx.mode.query = Лише запит attachments.ctx.mode.summary = Резюме attachments.delete.confirm = Видалити файл зі списку? +attachments.header.idx = Індекс attachments.header.length = Довжина (символи / токени) attachments.header.name = Ім'я attachments.header.path = Шлях @@ -902,7 +908,7 @@ text.context_menu.copy_to.notepad = Блокнот text.context_menu.find = Знайти... theme.dark = Темна theme.light = Світла -tip.input.attachments = Тут ви можете додати вкладення до повідомлення, яке ви відправляєте, якщо режим це підтримує. Тут ви можете відправляти файли для аналізу у режимі Асистента або зображення та захоплені зображення з камери для аналізу у режимі Vision. +tip.input.attachments = Тут ви можете додати вкладення до повідомлення, яке ви надсилаєте. Ви можете надіслати текстові файли, файли з кодом, PDF, документи, електронні таблиці та інші - вони будуть використані як додатковий контекст у розмові. Ви також можете надіслати зображення або знімки, зроблені за допомогою камери, для аналізу. tip.input.attachments.ctx = Нижче наведено завантажені та проіндексовані вкладення, які ви можете використовувати як додатковий контекст. Додатковий контекст доступний для всієї вищезгаданої дискусії. Варіанти: Повний контекст - включає весь додатковий вміст (сирий) у системному запиті, Лише запит - запитує лише проіндексований вміст, Резюме - включає резюме доданого вмісту в запиті, Вимкнено - вимкнути додатковий контекст. tip.input.attachments.uploaded = Тут є список файлів, завантажених на сервер у режимі Асистента. Ці файли розташовані на віддаленому сервері, а не на вашому локальному комп'ютері, тому модель може використовувати їх та аналізувати за допомогою інструментів, доступних ззовні на віддаленому сервері. tip.output.tab.calendar = Використовуючи календар, ви можете повертатись до обраних розмов з певного дня. Натисніть на день у календарі, щоб обмежити відображення історії чату до цього дня. Ви також можете створювати денні нотатки та присвоювати їм кольорові мітки. diff --git a/src/pygpt_net/data/locale/locale.zh.ini b/src/pygpt_net/data/locale/locale.zh.ini index c2335b4d..070fcc86 100644 --- a/src/pygpt_net/data/locale/locale.zh.ini +++ b/src/pygpt_net/data/locale/locale.zh.ini @@ -29,6 +29,9 @@ action.mkdir = 創建目錄... action.move_to = 移动到 action.open = 打開 action.open_dir = 在目錄中打開... +action.open_dir_dest = 打开目标目录 +action.open_dir_src = 打开源目录 +action.open_dir_storage = 打开存储目录 action.paste = 粘贴 action.pin = 置頂 action.profile.delete = 删除个人资料(仅从列表中删除) @@ -95,16 +98,19 @@ assistant.tool.file_search = 文件聊天 assistant.tool.function = 工具:函數 assistant.tool.retrieval = 工具:檢索 assistant.vector_store = 向量存储库 +attachments.auto_index = 上传时自动索引 attachments.btn.add = 添加文件 attachments.btn.clear = 清除文件 attachments.capture_clear = 捕獲後清除 attachments.clear.confirm = 清除列表? +attachments.ctx.indexed = 是 attachments.ctx.label = 附加上下文 attachments.ctx.mode.full = 完整上下文 attachments.ctx.mode.off = 关闭(禁用 attachments.ctx.mode.query = 仅查询 attachments.ctx.mode.summary = 摘要 attachments.delete.confirm = 從列表中移除文件? +attachments.header.idx = 索引 attachments.header.length = 长度(字符/标记 attachments.header.name = 名稱 attachments.header.path = 路徑 @@ -1018,7 +1024,7 @@ text.context_menu.copy_to.notepad = 記事本 text.context_menu.find = 查找... theme.dark = 暗色 theme.light = 亮色 -tip.input.attachments = 如果模式支持,您可以在這裡添加附件到您發送的消息中。您可以在這裡發送文件以在助手模式下進行分析,或者在視覺模式下發送圖像和從相機捕獲的圖像。 +tip.input.attachments = 在这里,您可以向正在发送的消息添加附件。 您可以发送文本文件、代码文件、PDF、文档、电子表格和其他文件 - 它们将用作对话中的附加上下文。 您还可以发送图像或从相机捕获的照片进行分析。 tip.input.attachments.ctx = 以下是已上传和索引的附件,您可以将其用作附加上下文。附加上下文适用于整个讨论。选项:完整上下文 - 在系统提示中包含所有附加内容(原始),仅查询 - 仅查询索引内容,摘要 - 在提示中包含添加内容的摘要,关闭 - 禁用附加上下文。 tip.input.attachments.uploaded = 這是已上傳到服務器的文件列表,在助手模式下。這些文件位於遠程服務器上,而不是您的本地計算機上,因此模型可以使用並分析外部遠程服務器上可用的工具。 tip.output.tab.calendar = 使用日曆,您可以導航回特定日期的選定對話。點擊日曆中的一天以限制聊天歷史顯示到該天。您還可以創建日記並為它們分配彩色標籤。 diff --git a/src/pygpt_net/provider/core/config/patch.py b/src/pygpt_net/provider/core/config/patch.py index 9c61f76e..44ecf157 100755 --- a/src/pygpt_net/provider/core/config/patch.py +++ b/src/pygpt_net/provider/core/config/patch.py @@ -1701,6 +1701,14 @@ def execute(self, version: Version) -> bool: del data['plugins']['cmd_code_interpreter']['ipython_dockerfile'] updated = True + # < 2.4.31 + if old < parse_version("2.4.31"): + print("Migrating config from < 2.4.31...") + if 'attachments_auto_index' not in data: + data["attachments_auto_index"] = self.window.core.config.get_base( + 'attachments_auto_index') + updated = True + # update file migrated = False if updated: diff --git a/src/pygpt_net/ui/layout/chat/attachments.py b/src/pygpt_net/ui/layout/chat/attachments.py index 05dd10b2..40653139 100755 --- a/src/pygpt_net/ui/layout/chat/attachments.py +++ b/src/pygpt_net/ui/layout/chat/attachments.py @@ -42,6 +42,7 @@ def setup(self) -> QVBoxLayout: buttons = QHBoxLayout() buttons.addWidget(self.window.ui.nodes['attachments.btn.add']) buttons.addWidget(self.window.ui.nodes['attachments.btn.clear']) + buttons.addWidget(self.setup_auto_index()) buttons.addWidget(self.setup_send_clear()) buttons.addWidget(self.setup_capture_clear()) @@ -88,6 +89,22 @@ def setup_capture_clear(self) -> QWidget: return widget + def setup_auto_index(self) -> QWidget: + """ + Setup auto index checkbox + + :return: QWidget + """ + layout = QHBoxLayout() + layout.setContentsMargins(0, 0, 0, 0) + layout.setAlignment(Qt.AlignCenter) + layout.addWidget(self.window.ui.nodes['attachments.auto_index']) + + widget = QWidget() + widget.setLayout(layout) + + return widget + def setup_buttons(self): """ Setup buttons @@ -110,6 +127,11 @@ def setup_buttons(self): lambda: self.window.controller.attachment.toggle_capture_clear( self.window.ui.nodes['attachments.capture_clear'].isChecked())) + self.window.ui.nodes['attachments.auto_index'] = QCheckBox(trans('attachments.auto_index')) + self.window.ui.nodes['attachments.auto_index'].stateChanged.connect( + lambda: self.window.controller.attachment.toggle_auto_index( + self.window.ui.nodes['attachments.auto_index'].isChecked())) + def setup_attachments(self): """ Setup attachments list diff --git a/src/pygpt_net/ui/layout/chat/attachments_ctx.py b/src/pygpt_net/ui/layout/chat/attachments_ctx.py index 6ccd77e2..08ab5e43 100644 --- a/src/pygpt_net/ui/layout/chat/attachments_ctx.py +++ b/src/pygpt_net/ui/layout/chat/attachments_ctx.py @@ -105,11 +105,12 @@ def create_model(self, parent) -> QStandardItemModel: :param parent: parent widget :return: QStandardItemModel """ - model = QStandardItemModel(0, 4, parent) + model = QStandardItemModel(0, 5, parent) model.setHeaderData(0, Qt.Horizontal, trans('attachments.header.name')) model.setHeaderData(1, Qt.Horizontal, trans('attachments.header.path')) model.setHeaderData(2, Qt.Horizontal, trans('attachments.header.size')) model.setHeaderData(3, Qt.Horizontal, trans('attachments.header.length')) + model.setHeaderData(4, Qt.Horizontal, trans('attachments.header.idx')) return model def update(self, data): @@ -121,6 +122,7 @@ def update(self, data): self.window.ui.models[self.id].removeRows(0, self.window.ui.models[self.id].rowCount()) i = 0 for item in data: + indexed = False name = "No name" if 'name' in item: name = item['name'] @@ -136,6 +138,12 @@ def update(self, data): length = str(item['length']) if 'tokens' in item: length += ' / ~' + str(item['tokens']) + if 'indexed' in item and item['indexed']: + indexed = True + + idx_str = "" + if indexed: + idx_str = trans("attachments.ctx.indexed") if os.path.exists(path): size = self.window.core.filesystem.sizeof_fmt(os.path.getsize(path)) @@ -149,4 +157,5 @@ def update(self, data): self.window.ui.models[self.id].setData(self.window.ui.models[self.id].index(i, 1), path) self.window.ui.models[self.id].setData(self.window.ui.models[self.id].index(i, 2), size) self.window.ui.models[self.id].setData(self.window.ui.models[self.id].index(i, 3), length) + self.window.ui.models[self.id].setData(self.window.ui.models[self.id].index(i, 4), idx_str) i += 1 diff --git a/src/pygpt_net/ui/widget/lists/attachment_ctx.py b/src/pygpt_net/ui/widget/lists/attachment_ctx.py index acf01b2c..3e66e8cd 100644 --- a/src/pygpt_net/ui/widget/lists/attachment_ctx.py +++ b/src/pygpt_net/ui/widget/lists/attachment_ctx.py @@ -85,18 +85,47 @@ def contextMenuEvent(self, event): """ actions = {} + item = self.indexAt(event.pos()) + idx = item.row() + + has_file = False + has_src = False + has_dest = False + + if idx >= 0: + has_file = self.window.controller.chat.attachment.has_file_by_idx(idx) + has_src = self.window.controller.chat.attachment.has_src_by_idx(idx) + has_dest = self.window.controller.chat.attachment.has_dest_by_idx(idx) + + actions['open'] = QAction(QIcon(":/icons/view.svg"), trans('action.open'), self) + actions['open'].triggered.connect( + lambda: self.action_open(event) + ) + actions['open_dir_src'] = QAction(QIcon(":/icons/folder.svg"), trans('action.open_dir_src'), self) + actions['open_dir_src'].triggered.connect( + lambda: self.action_open_dir_src(event) + ) + actions['open_dir_dest'] = QAction(QIcon(":/icons/folder.svg"), trans('action.open_dir_storage'), self) + actions['open_dir_dest'].triggered.connect( + lambda: self.action_open_dir_dest(event) + ) + actions['delete'] = QAction(QIcon(":/icons/delete.svg"), trans('action.delete'), self) actions['delete'].triggered.connect( lambda: self.action_delete(event) ) menu = QMenu(self) + if has_file: + menu.addAction(actions['open']) + if has_src: + menu.addAction(actions['open_dir_src']) + if has_dest: + menu.addAction(actions['open_dir_dest']) menu.addAction(actions['delete']) - item = self.indexAt(event.pos()) - idx = item.row() if idx >= 0: - self.window.controller.assistant.files.select(item.row()) + self.window.controller.chat.attachment.select(item.row()) menu.exec_(event.globalPos()) def action_delete(self, event): @@ -109,3 +138,36 @@ def action_delete(self, event): idx = item.row() if idx >= 0: self.window.controller.chat.attachment.delete_by_idx(idx) + + def action_open(self, event): + """ + Open action handler + + :param event: mouse event + """ + item = self.indexAt(event.pos()) + idx = item.row() + if idx >= 0: + self.window.controller.chat.attachment.open_by_idx(idx) + + def action_open_dir_src(self, event): + """ + Open source directory action handler + + :param event: mouse event + """ + item = self.indexAt(event.pos()) + idx = item.row() + if idx >= 0: + self.window.controller.chat.attachment.open_dir_src_by_idx(idx) + + def action_open_dir_dest(self, event): + """ + Open destination directory action handler + + :param event: mouse event + """ + item = self.indexAt(event.pos()) + idx = item.row() + if idx >= 0: + self.window.controller.chat.attachment.open_dir_dest_by_idx(idx)