pygpt-net 2.5.20__py3-none-any.whl → 2.5.21__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.
pygpt_net/CHANGELOG.txt CHANGED
@@ -1,3 +1,8 @@
1
+ 2.5.21 (2025-06-28)
2
+
3
+ - Fixed JS errors in logger.
4
+ - Updated CSS.
5
+
1
6
  2.5.20 (2025-06-28)
2
7
 
3
8
  - LlamaIndex upgraded to 0.12.44.
pygpt_net/__init__.py CHANGED
@@ -13,7 +13,7 @@ __author__ = "Marcin Szczygliński"
13
13
  __copyright__ = "Copyright 2025, Marcin Szczygliński"
14
14
  __credits__ = ["Marcin Szczygliński"]
15
15
  __license__ = "MIT"
16
- __version__ = "2.5.20"
16
+ __version__ = "2.5.21"
17
17
  __build__ = "2025-06-28"
18
18
  __maintainer__ = "Marcin Szczygliński"
19
19
  __github__ = "https://github.com/szczyglis-dev/py-gpt"
@@ -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: 2025.06.21 16:00:00 #
9
+ # Updated Date: 2025.06.28 22:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import json
@@ -1001,7 +1001,7 @@ class Renderer(BaseRenderer):
1001
1001
  escaped_html = json.dumps(html)
1002
1002
  try:
1003
1003
  node = self.get_output_node_by_pid(pid)
1004
- node.page().runJavaScript(f"appendNode({escaped_html});")
1004
+ node.page().runJavaScript(f"if (typeof window.appendNode !== 'undefined') appendNode({escaped_html});")
1005
1005
  node.update_current_content()
1006
1006
  except Exception as e:
1007
1007
  pass
@@ -1083,7 +1083,7 @@ class Renderer(BaseRenderer):
1083
1083
  :param ctx: context item
1084
1084
  """
1085
1085
  try:
1086
- self.get_output_node(ctx.meta).page().runJavaScript("removeNode({});".format(ctx.id))
1086
+ self.get_output_node(ctx.meta).page().runJavaScript("if (typeof window.removeNode !== 'undefined') removeNode({});".format(ctx.id))
1087
1087
  except Exception as e:
1088
1088
  pass
1089
1089
 
@@ -1094,7 +1094,7 @@ class Renderer(BaseRenderer):
1094
1094
  :param ctx: context item
1095
1095
  """
1096
1096
  try:
1097
- self.get_output_node(ctx.meta).page().runJavaScript("removeNodesFromId({});".format(ctx.id))
1097
+ self.get_output_node(ctx.meta).page().runJavaScript("if (typeof window.removeNodesFromId !== 'undefined') removeNodesFromId({});".format(ctx.id))
1098
1098
  except Exception as e:
1099
1099
  pass
1100
1100
 
@@ -1147,7 +1147,7 @@ class Renderer(BaseRenderer):
1147
1147
  try:
1148
1148
  nodes = self.get_all_nodes()
1149
1149
  for node in nodes:
1150
- node.page().runJavaScript("enableEditIcons();")
1150
+ node.page().runJavaScript("if (typeof window.enableEditIcons !== 'undefined') enableEditIcons();")
1151
1151
  except Exception as e:
1152
1152
  pass
1153
1153
 
@@ -1162,7 +1162,7 @@ class Renderer(BaseRenderer):
1162
1162
  try:
1163
1163
  nodes = self.get_all_nodes()
1164
1164
  for node in nodes:
1165
- node.page().runJavaScript("disableEditIcons();")
1165
+ node.page().runJavaScript("if (typeof window.disableEditIcons !== 'undefined') disableEditIcons();")
1166
1166
  except Exception as e:
1167
1167
  pass
1168
1168
 
@@ -1177,7 +1177,7 @@ class Renderer(BaseRenderer):
1177
1177
  try:
1178
1178
  nodes = self.get_all_nodes()
1179
1179
  for node in nodes:
1180
- node.page().runJavaScript("enableTimestamp();")
1180
+ node.page().runJavaScript("if (typeof window.enableTimestamp !== 'undefined') enableTimestamp();")
1181
1181
  except Exception as e:
1182
1182
  pass
1183
1183
 
@@ -1192,7 +1192,7 @@ class Renderer(BaseRenderer):
1192
1192
  try:
1193
1193
  nodes = self.get_all_nodes()
1194
1194
  for node in nodes:
1195
- node.page().runJavaScript("disableTimestamp();")
1195
+ node.page().runJavaScript("if (typeof window.disableTimestamp !== 'undefined') disableTimestamp();")
1196
1196
  except Exception as e:
1197
1197
  pass
1198
1198
 
@@ -1253,11 +1253,11 @@ class Renderer(BaseRenderer):
1253
1253
  for pid in self.pids:
1254
1254
  if self.pids[pid].loaded:
1255
1255
  for node in nodes:
1256
- node.page().runJavaScript("updateCSS({});".format(to_json))
1256
+ node.page().runJavaScript("if (typeof window.updateCSS !== 'undefined') updateCSS({});".format(to_json))
1257
1257
  if self.window.core.config.get('render.blocks'):
1258
- node.page().runJavaScript("enableBlocks();")
1258
+ node.page().runJavaScript("if (typeof window.enableBlocks !== 'undefined') enableBlocks();")
1259
1259
  else:
1260
- node.page().runJavaScript("disableBlocks();") # TODO: ctx!!!!!
1260
+ node.page().runJavaScript("if (typeof window.disableBlocks !== 'undefined') disableBlocks();") # TODO: ctx!!!!!
1261
1261
  return
1262
1262
 
1263
1263
  def on_theme_change(self):
@@ -1281,7 +1281,7 @@ class Renderer(BaseRenderer):
1281
1281
  """
1282
1282
  escaped_content = json.dumps(content)
1283
1283
  try:
1284
- self.get_output_node(meta).page().runJavaScript(f"appendToolOutput({escaped_content});")
1284
+ self.get_output_node(meta).page().runJavaScript(f"if (typeof window.appendToolOutput !== 'undefined') appendToolOutput({escaped_content});")
1285
1285
  except Exception as e:
1286
1286
  pass
1287
1287
 
@@ -1298,7 +1298,7 @@ class Renderer(BaseRenderer):
1298
1298
  """
1299
1299
  escaped_content = json.dumps(content)
1300
1300
  try:
1301
- self.get_output_node(meta).page().runJavaScript(f"updateToolOutput({escaped_content});")
1301
+ self.get_output_node(meta).page().runJavaScript(f"if (typeof window.updateToolOutput !== 'undefined') updateToolOutput({escaped_content});")
1302
1302
  except Exception as e:
1303
1303
  pass
1304
1304
 
@@ -1309,7 +1309,7 @@ class Renderer(BaseRenderer):
1309
1309
  :param meta: context meta
1310
1310
  """
1311
1311
  try:
1312
- self.get_output_node(meta).page().runJavaScript(f"clearToolOutput();")
1312
+ self.get_output_node(meta).page().runJavaScript(f"if (typeof window.clearToolOutput !== 'undefined') clearToolOutput();")
1313
1313
  except Exception as e:
1314
1314
  pass
1315
1315
 
@@ -1320,14 +1320,14 @@ class Renderer(BaseRenderer):
1320
1320
  :param meta: context meta
1321
1321
  """
1322
1322
  try:
1323
- self.get_output_node(meta).page().runJavaScript(f"beginToolOutput();")
1323
+ self.get_output_node(meta).page().runJavaScript(f"if (typeof window.beginToolOutput !== 'undefined') beginToolOutput();")
1324
1324
  except Exception as e:
1325
1325
  pass
1326
1326
 
1327
1327
  def tool_output_end(self):
1328
1328
  """End tool output"""
1329
1329
  try:
1330
- self.get_output_node().page().runJavaScript(f"endToolOutput();")
1330
+ self.get_output_node().page().runJavaScript(f"if (typeof window.endToolOutput !== 'undefined') endToolOutput();")
1331
1331
  except Exception as e:
1332
1332
  pass
1333
1333
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "__meta__": {
3
- "version": "2.5.20",
4
- "app.version": "2.5.20",
3
+ "version": "2.5.21",
4
+ "app.version": "2.5.21",
5
5
  "updated_at": "2025-06-28T00:00:00"
6
6
  },
7
7
  "access.audio.event.speech": false,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "__meta__": {
3
- "version": "2.5.20",
4
- "app.version": "2.5.20",
3
+ "version": "2.5.21",
4
+ "app.version": "2.5.21",
5
5
  "updated_at": "2025-06-28T01:31:35"
6
6
  },
7
7
  "items": {
@@ -269,7 +269,7 @@ code {{
269
269
  margin: 0;
270
270
  padding-top: 10px;
271
271
  display: block;
272
- font-size: 0.95rem;
272
+ font-size: 0.8rem;
273
273
  }}
274
274
  .extra-src-img-box .img-outer {{
275
275
  display: flex;
@@ -298,7 +298,7 @@ code {{
298
298
  display: block;
299
299
  width: 100%;
300
300
  height: 100%;
301
- object-fit: cover;
301
+ object-fit: contain;
302
302
  }}
303
303
 
304
304
  /* common */
@@ -205,8 +205,8 @@ ctx.delete.confirm = Sind Sie sicher, dass Sie löschen möchten?
205
205
  ctx.delete.item.confirm = Gesprächselement löschen?
206
206
  ctx.delete.item.link = löschen
207
207
  ctx.extra.audio = Antwort vorlesen (Audio)
208
- ctx.extra.copy = In die Zwischenablage kopieren
209
- ctx.extra.copy_code = in die Zwischenablage kopieren
208
+ ctx.extra.copy = Kopieren
209
+ ctx.extra.copy_code = kopieren
210
210
  ctx.extra.delete = Diesen Eintrag löschen
211
211
  ctx.extra.edit = Bearbeiten und Antwort neu generieren (ab diesem Punkt)
212
212
  ctx.extra.join = An vorherige Antwort anhängen (zusammenführen)
@@ -222,8 +222,8 @@ ctx.delete.confirm = Are you sure you want to delete?
222
222
  ctx.delete.item.confirm = Delete conversation item?
223
223
  ctx.delete.item.link = delete
224
224
  ctx.extra.audio = Read response (audio)
225
- ctx.extra.copy = Copy to clipboard
226
- ctx.extra.copy_code = Copy to clipboard
225
+ ctx.extra.copy = Copy
226
+ ctx.extra.copy_code = Copy
227
227
  ctx.extra.delete = Delete this item
228
228
  ctx.extra.edit = Edit and regenerate (from this point)
229
229
  ctx.extra.join = Append to previous response (merge)
@@ -205,8 +205,8 @@ ctx.delete.confirm = ¿Está seguro de querer eliminar?
205
205
  ctx.delete.item.confirm = ¿Eliminar elemento de la conversación?
206
206
  ctx.delete.item.link = eliminar
207
207
  ctx.extra.audio = Leer respuesta (audio)
208
- ctx.extra.copy = Copiar al portapapeles
209
- ctx.extra.copy_code = copiar al portapapeles
208
+ ctx.extra.copy = Copiar
209
+ ctx.extra.copy_code = copiar
210
210
  ctx.extra.delete = Eliminar este elemento
211
211
  ctx.extra.edit = Editar y regenerar (desde este punto)
212
212
  ctx.extra.join = Adjuntar a la respuesta anterior (combinar)
@@ -205,8 +205,8 @@ ctx.delete.confirm = Êtes-vous sûr de vouloir supprimer ?
205
205
  ctx.delete.item.confirm = Supprimer l'élément de la conversation ?
206
206
  ctx.delete.item.link = supprimer
207
207
  ctx.extra.audio = Lire la réponse (audio)
208
- ctx.extra.copy = Copier dans le presse-papier
209
- ctx.extra.copy_code = copier dans le presse-papier
208
+ ctx.extra.copy = Copier
209
+ ctx.extra.copy_code = copier
210
210
  ctx.extra.delete = Supprimer cet élément
211
211
  ctx.extra.edit = Modifier et régénérer (à partir de ce point)
212
212
  ctx.extra.join = Joindre à la réponse précédente (fusionner)
@@ -205,8 +205,8 @@ ctx.delete.confirm = Sei sicuro di voler eliminare?
205
205
  ctx.delete.item.confirm = Eliminare l'elemento della conversazione?
206
206
  ctx.delete.item.link = elimina
207
207
  ctx.extra.audio = Leggi la risposta (audio)
208
- ctx.extra.copy = Copia negli appunti
209
- ctx.extra.copy_code = copia negli appunti
208
+ ctx.extra.copy = Copia
209
+ ctx.extra.copy_code = copia
210
210
  ctx.extra.delete = Elimina questo elemento
211
211
  ctx.extra.edit = Modifica e rigenera (da questo punto)
212
212
  ctx.extra.join = Aggiungi alla risposta precedente (unisci)
@@ -205,8 +205,8 @@ ctx.delete.confirm = Czy na pewno usunąć?
205
205
  ctx.delete.item.confirm = Usunąć element rozmowy?
206
206
  ctx.delete.item.link = usuń
207
207
  ctx.extra.audio = Odczytaj odpowiedź (audio)
208
- ctx.extra.copy = Kopiuj do schowka
209
- ctx.extra.copy_code = kopiuj do schowka
208
+ ctx.extra.copy = Kopiuj
209
+ ctx.extra.copy_code = kopiuj
210
210
  ctx.extra.delete = Usuń ten element
211
211
  ctx.extra.edit = Edytuj i wygeneruj ponownie (od tego miejsca)
212
212
  ctx.extra.join = Dołącz do poprzedniej odpowiedzi (połącz)
@@ -205,8 +205,8 @@ ctx.delete.confirm = Ви впевнені, що хочете видалити?
205
205
  ctx.delete.item.confirm = Видалити елемент розмови?
206
206
  ctx.delete.item.link = видалити
207
207
  ctx.extra.audio = Читати відповідь (аудіо)
208
- ctx.extra.copy = Скопіювати до буфера обміну
209
- ctx.extra.copy_code = скопіювати в буфер обміну
208
+ ctx.extra.copy = Копіювати
209
+ ctx.extra.copy_code = kопіювати
210
210
  ctx.extra.delete = Видалити цей елемент
211
211
  ctx.extra.edit = Редагувати та згенерувати знову (з цього місця)
212
212
  ctx.extra.join = Долучити до попередньої відповіді (об'єднати)
@@ -205,8 +205,8 @@ ctx.delete.confirm = 您確定要刪除嗎?
205
205
  ctx.delete.item.confirm = 刪除對話項目?
206
206
  ctx.delete.item.link = 刪除
207
207
  ctx.extra.audio = 朗读回应(音频)
208
- ctx.extra.copy = 复制到剪贴板
209
- ctx.extra.copy_code = 复制到剪贴板
208
+ ctx.extra.copy = 复制
209
+ ctx.extra.copy_code = 复制
210
210
  ctx.extra.delete = 删除这一项
211
211
  ctx.extra.edit = 编辑并重新生成响应(从这一点开始)
212
212
  ctx.extra.join = 附加到前一个回应(合并)
@@ -1891,6 +1891,12 @@ class Patch:
1891
1891
  data["mode"] = "chat"
1892
1892
  updated = True
1893
1893
 
1894
+ # < 2.5.21
1895
+ if old < parse_version("2.5.21"):
1896
+ print("Migrating config from < 2.5.21...")
1897
+ self.window.core.updater.patch_css('web-chatgpt.css', True) # force replace file
1898
+ updated = True
1899
+
1894
1900
  # update file
1895
1901
  migrated = False
1896
1902
  if updated:
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pygpt-net
3
- Version: 2.5.20
3
+ Version: 2.5.21
4
4
  Summary: Desktop AI Assistant powered by models: OpenAI o1, o3, GPT-4o, GPT-4 Vision, DALL-E 3, Llama 3, Mistral, Gemini, Claude, DeepSeek, Bielik, and other models supported by Llama Index, and Ollama. Features include chatbot, text completion, image generation, vision analysis, speech-to-text, internet access, file handling, command execution and more.
5
5
  License: MIT
6
- Keywords: py_gpt,py-gpt,pygpt,desktop,app,o1,gpt,gpt4,gpt-4o,gpt-4v,gpt3.5,gpt-4,gpt-4-vision,gpt-3.5,llama3,mistral,gemini,deepseek,bielik,claude,tts,whisper,vision,chatgpt,dall-e,chat,chatbot,assistant,text completion,image generation,ai,api,openai,api key,langchain,llama-index,ollama,presets,ui,qt,pyside
6
+ Keywords: py_gpt,py-gpt,pygpt,desktop,app,o1,gpt,gpt4,gpt-4o,gpt-4v,gpt3.5,gpt-4,gpt-4-vision,gpt-3.5,llama3,mistral,gemini,grok,deepseek,bielik,claude,tts,whisper,vision,chatgpt,dall-e,chat,chatbot,assistant,text completion,image generation,ai,api,openai,api key,langchain,llama-index,ollama,presets,ui,qt,pyside
7
7
  Author: Marcin Szczyglinski
8
8
  Author-email: info@pygpt.net
9
9
  Requires-Python: >=3.10,<3.13
@@ -96,7 +96,7 @@ Description-Content-Type: text/markdown
96
96
 
97
97
  [![pygpt](https://snapcraft.io/pygpt/badge.svg)](https://snapcraft.io/pygpt)
98
98
 
99
- Release: **2.5.20** | build: **2025-06-28** | Python: **>=3.10, <3.13**
99
+ Release: **2.5.21** | build: **2025-06-28** | Python: **>=3.10, <3.13**
100
100
 
101
101
  > Official website: https://pygpt.net | Documentation: https://pygpt.readthedocs.io
102
102
  >
@@ -108,7 +108,7 @@ Release: **2.5.20** | build: **2025-06-28** | Python: **>=3.10, <3.13**
108
108
 
109
109
  ## Overview
110
110
 
111
- **PyGPT** is **all-in-one** Desktop AI Assistant that provides direct interaction with OpenAI language models, including `o1`, `gpt-4o`, `gpt-4`, `gpt-4 Vision`, and `gpt-3.5`, through the `OpenAI API`. By utilizing `LlamaIndex`, the application also supports alternative LLMs, like those available on `HuggingFace`, locally available models (like `Llama 3`,`Mistral`, `DeepSeek V3/R1` or `Bielik`), `Google Gemini` and `Anthropic Claude`.
111
+ **PyGPT** is **all-in-one** Desktop AI Assistant that provides direct interaction with OpenAI language models, including `o1`, `o3`, `gpt-4o`, `gpt-4`, `gpt-4 Vision`, and `gpt-3.5`, through the `OpenAI API`. By utilizing `LlamaIndex`, the application also supports alternative LLMs, like those available on `HuggingFace`, locally available models via `Ollama` (like `Llama 3`,`Mistral`, `DeepSeek V3/R1` or `Bielik`), `Google Gemini`, `Anthropic Claude`, and `xAI Grok`.
112
112
 
113
113
  This assistant offers multiple modes of operation such as chat, assistants, completions, and image-related tasks using `DALL-E 3` for generation and `gpt-4 Vision` for image analysis. **PyGPT** has filesystem capabilities for file I/O, can generate and run Python code, execute system commands, execute custom commands and manage file transfers. It also allows models to perform web searches with the `Google` and `Microsoft Bing`.
114
114
 
@@ -132,8 +132,8 @@ You can download compiled 64-bit versions for Windows and Linux here: https://py
132
132
 
133
133
  - Desktop AI Assistant for `Linux`, `Windows` and `Mac`, written in Python.
134
134
  - Works similarly to `ChatGPT`, but locally (on a desktop computer).
135
- - 11 modes of operation: Chat, Vision, Completion, Assistant, Image generation, Chat with Files, Chat with Audio, Research (Perplexity), Experts, Autonomous Mode and Agents.
136
- - Supports multiple models: `o1`, `GPT-4o`, `GPT-4`, `GPT-3.5`, and any model accessible through `LlamaIndex` and `Ollama` such as `Llama 3`, `Mistral`, `Google Gemini`, `Anthropic Claude`, `DeepSeek V3/R1`, `Bielik`, etc.
135
+ - 11 modes of operation: Chat, Chat with Files, Chat with Audio, Research (Perplexity), Completion, Image generation, Vision, Assistants, Experts, Agents and Autonomous Mode.
136
+ - Supports multiple models: `o1`, `o1`, `GPT-4o`, `GPT-4`, `GPT-3.5`, and any model accessible through `LlamaIndex` and `Ollama` such as `Llama 3`, `Mistral`, `Google Gemini`, `Anthropic Claude`, `xAI Grok`, `DeepSeek V3/R1`, `Bielik`, etc.
137
137
  - Chat with your own Files: integrated `LlamaIndex` support: chat with data such as: `txt`, `pdf`, `csv`, `html`, `md`, `docx`, `json`, `epub`, `xlsx`, `xml`, webpages, `Google`, `GitHub`, video/audio, images and other data types, or use conversation history as additional context provided to the model.
138
138
  - Built-in vector databases support and automated files and data embedding.
139
139
  - Included support features for individuals with disabilities: customizable keyboard shortcuts, voice control, and translation of on-screen actions into audio via speech synthesis.
@@ -310,6 +310,13 @@ poetry env use python3.10
310
310
  poetry shell
311
311
  ```
312
312
 
313
+ or (Poetry >= 2.0):
314
+
315
+ ```commandline
316
+ poetry env use python3.10
317
+ poetry env activate
318
+ ```
319
+
313
320
  4. Install requirements:
314
321
 
315
322
  ```commandline
@@ -480,6 +487,114 @@ Plugin allows you to generate images in Chat mode:
480
487
 
481
488
  ![v3_img_chat](https://github.com/user-attachments/assets/1af65452-1ed1-43ec-8d78-21b0e61f0ec3)
482
489
 
490
+ ## Chat with Files (LlamaIndex)
491
+
492
+ This mode enables chat interaction with your documents and entire context history through conversation.
493
+ It seamlessly incorporates `LlamaIndex` into the chat interface, allowing for immediate querying of your indexed documents.
494
+
495
+ **Querying single files**
496
+
497
+ You can also query individual files "on the fly" using the `query_file` command from the `Files I/O` plugin. This allows you to query any file by simply asking a question about that file. A temporary index will be created in memory for the file being queried, and an answer will be returned from it. From version `2.1.9` similar command is available for querying web and external content: `Directly query web content with LlamaIndex`.
498
+
499
+ **For example:**
500
+
501
+ If you have a file: `data/my_cars.txt` with content `My car is red.`
502
+
503
+ You can ask for: `Query the file my_cars.txt about what color my car is.`
504
+
505
+ And you will receive the response: `Red`.
506
+
507
+ Note: this command indexes the file only for the current query and does not persist it in the database. To store queried files also in the standard index you must enable the option `Auto-index readed files` in plugin settings. Remember to enable `+ Tools` checkbox to allow usage of tools and commands from plugins.
508
+
509
+ **Using Chat with Files mode**
510
+
511
+ In this mode, you are querying the whole index, stored in a vector store database.
512
+ To start, you need to index (embed) the files you want to use as additional context.
513
+ Embedding transforms your text data into vectors. If you're unfamiliar with embeddings and how they work, check out this article:
514
+
515
+ https://stackoverflow.blog/2023/11/09/an-intuitive-introduction-to-text-embeddings/
516
+
517
+ For a visualization from OpenAI's page, see this picture:
518
+
519
+ ![vectors](https://github.com/szczyglis-dev/py-gpt/assets/61396542/4bbb3860-58a0-410d-b5cb-3fbfadf1a367)
520
+
521
+ Source: https://cdn.openai.com/new-and-improved-embedding-model/draft-20221214a/vectors-3.svg
522
+
523
+ To index your files, simply copy or upload them into the `data` directory and initiate indexing (embedding) by clicking the `Index all` button, or right-click on a file and select `Index...`. Additionally, you have the option to utilize data from indexed files in any Chat mode by activating the `Chat with Files (LlamaIndex, inline)` plugin.
524
+
525
+ ![v2_idx1](https://github.com/szczyglis-dev/py-gpt/assets/61396542/c3dfbc89-cbfe-4ae3-b7e7-821401d755cd)
526
+
527
+ After the file(s) are indexed (embedded in vector store), you can use context from them in chat mode:
528
+
529
+ ![v2_idx2](https://github.com/szczyglis-dev/py-gpt/assets/61396542/70c9ab66-82d9-4f61-81ed-268743bfa6b4)
530
+
531
+ Built-in file loaders:
532
+
533
+ **Files:**
534
+
535
+ - CSV files (csv)
536
+ - Epub files (epub)
537
+ - Excel .xlsx spreadsheets (xlsx)
538
+ - HTML files (html, htm)
539
+ - IPYNB Notebook files (ipynb)
540
+ - Image (vision) (jpg, jpeg, png, gif, bmp, tiff, webp)
541
+ - JSON files (json)
542
+ - Markdown files (md)
543
+ - PDF documents (pdf)
544
+ - Txt/raw files (txt)
545
+ - Video/audio (mp4, avi, mov, mkv, webm, mp3, mpeg, mpga, m4a, wav)
546
+ - Word .docx documents (docx)
547
+ - XML files (xml)
548
+
549
+ **Web/external content:**
550
+
551
+ - Bitbucket
552
+ - ChatGPT Retrieval Plugin
553
+ - GitHub Issues
554
+ - GitHub Repository
555
+ - Google Calendar
556
+ - Google Docs
557
+ - Google Drive
558
+ - Google Gmail
559
+ - Google Keep
560
+ - Google Sheets
561
+ - Microsoft OneDrive
562
+ - RSS
563
+ - SQL Database
564
+ - Sitemap (XML)
565
+ - Twitter/X posts
566
+ - Webpages (crawling any webpage content)
567
+ - YouTube (transcriptions)
568
+
569
+ You can configure data loaders in `Settings / Indexes (LlamaIndex) / Data Loaders` by providing list of keyword arguments for specified loaders.
570
+ You can also develop and provide your own custom loader and register it within the application.
571
+
572
+ LlamaIndex is also integrated with context database - you can use data from database (your context history) as additional context in discussion.
573
+ Options for indexing existing context history or enabling real-time indexing new ones (from database) are available in `Settings / Indexes (LlamaIndex)` section.
574
+
575
+ **WARNING:** remember that when indexing content, API calls to the embedding model are used. Each indexing consumes additional tokens. Always control the number of tokens used on the OpenAI page.
576
+
577
+ **Tip:** Using the Chat with Files mode, you have default access to files manually indexed from the /data directory. However, you can use additional context by attaching a file - such additional context from the attachment does not land in the main index, but only in a temporary one, available only for the given conversation.
578
+
579
+ **Token limit:** When you use `Chat with Files` in non-query mode, LlamaIndex adds extra context to the system prompt. If you use a plugins (which also adds more instructions to system prompt), you might go over the maximum number of tokens allowed. If you get a warning that says you've used too many tokens, turn off plugins you're not using or turn off the "+ Tools" option to reduce the number of tokens used by the system prompt.
580
+
581
+ **Available vector stores** (provided by `LlamaIndex`):
582
+
583
+ ```
584
+ - ChromaVectorStore
585
+ - ElasticsearchStore
586
+ - PinecodeVectorStore
587
+ - RedisVectorStore
588
+ - SimpleVectorStore
589
+ ```
590
+
591
+ You can configure selected vector store by providing config options like `api_key`, etc. in `Settings -> LlamaIndex` window. See the section: `Configuration / Vector stores` for configuration reference.
592
+
593
+
594
+ **Configuring data loaders**
595
+
596
+ In the `Settings -> LlamaIndex -> Data loaders` section you can define the additional keyword arguments to pass into data loader instance. See the section: `Configuration / Data Loaders` for configuration reference.
597
+
483
598
 
484
599
  ## Chat with Audio
485
600
 
@@ -617,114 +732,6 @@ The vector database in use will be displayed in the list of uploaded files, on t
617
732
 
618
733
  ![v2_assistant_stores_upload](https://github.com/szczyglis-dev/py-gpt/assets/61396542/8f13c2eb-f961-4eae-b08b-0b4937f06ca9)
619
734
 
620
- ## Chat with Files (LlamaIndex)
621
-
622
- This mode enables chat interaction with your documents and entire context history through conversation.
623
- It seamlessly incorporates `LlamaIndex` into the chat interface, allowing for immediate querying of your indexed documents.
624
-
625
- **Querying single files**
626
-
627
- You can also query individual files "on the fly" using the `query_file` command from the `Files I/O` plugin. This allows you to query any file by simply asking a question about that file. A temporary index will be created in memory for the file being queried, and an answer will be returned from it. From version `2.1.9` similar command is available for querying web and external content: `Directly query web content with LlamaIndex`.
628
-
629
- **For example:**
630
-
631
- If you have a file: `data/my_cars.txt` with content `My car is red.`
632
-
633
- You can ask for: `Query the file my_cars.txt about what color my car is.`
634
-
635
- And you will receive the response: `Red`.
636
-
637
- Note: this command indexes the file only for the current query and does not persist it in the database. To store queried files also in the standard index you must enable the option `Auto-index readed files` in plugin settings. Remember to enable `+ Tools` checkbox to allow usage of tools and commands from plugins.
638
-
639
- **Using Chat with Files mode**
640
-
641
- In this mode, you are querying the whole index, stored in a vector store database.
642
- To start, you need to index (embed) the files you want to use as additional context.
643
- Embedding transforms your text data into vectors. If you're unfamiliar with embeddings and how they work, check out this article:
644
-
645
- https://stackoverflow.blog/2023/11/09/an-intuitive-introduction-to-text-embeddings/
646
-
647
- For a visualization from OpenAI's page, see this picture:
648
-
649
- ![vectors](https://github.com/szczyglis-dev/py-gpt/assets/61396542/4bbb3860-58a0-410d-b5cb-3fbfadf1a367)
650
-
651
- Source: https://cdn.openai.com/new-and-improved-embedding-model/draft-20221214a/vectors-3.svg
652
-
653
- To index your files, simply copy or upload them into the `data` directory and initiate indexing (embedding) by clicking the `Index all` button, or right-click on a file and select `Index...`. Additionally, you have the option to utilize data from indexed files in any Chat mode by activating the `Chat with Files (LlamaIndex, inline)` plugin.
654
-
655
- ![v2_idx1](https://github.com/szczyglis-dev/py-gpt/assets/61396542/c3dfbc89-cbfe-4ae3-b7e7-821401d755cd)
656
-
657
- After the file(s) are indexed (embedded in vector store), you can use context from them in chat mode:
658
-
659
- ![v2_idx2](https://github.com/szczyglis-dev/py-gpt/assets/61396542/70c9ab66-82d9-4f61-81ed-268743bfa6b4)
660
-
661
- Built-in file loaders:
662
-
663
- **Files:**
664
-
665
- - CSV files (csv)
666
- - Epub files (epub)
667
- - Excel .xlsx spreadsheets (xlsx)
668
- - HTML files (html, htm)
669
- - IPYNB Notebook files (ipynb)
670
- - Image (vision) (jpg, jpeg, png, gif, bmp, tiff, webp)
671
- - JSON files (json)
672
- - Markdown files (md)
673
- - PDF documents (pdf)
674
- - Txt/raw files (txt)
675
- - Video/audio (mp4, avi, mov, mkv, webm, mp3, mpeg, mpga, m4a, wav)
676
- - Word .docx documents (docx)
677
- - XML files (xml)
678
-
679
- **Web/external content:**
680
-
681
- - Bitbucket
682
- - ChatGPT Retrieval Plugin
683
- - GitHub Issues
684
- - GitHub Repository
685
- - Google Calendar
686
- - Google Docs
687
- - Google Drive
688
- - Google Gmail
689
- - Google Keep
690
- - Google Sheets
691
- - Microsoft OneDrive
692
- - RSS
693
- - SQL Database
694
- - Sitemap (XML)
695
- - Twitter/X posts
696
- - Webpages (crawling any webpage content)
697
- - YouTube (transcriptions)
698
-
699
- You can configure data loaders in `Settings / Indexes (LlamaIndex) / Data Loaders` by providing list of keyword arguments for specified loaders.
700
- You can also develop and provide your own custom loader and register it within the application.
701
-
702
- LlamaIndex is also integrated with context database - you can use data from database (your context history) as additional context in discussion.
703
- Options for indexing existing context history or enabling real-time indexing new ones (from database) are available in `Settings / Indexes (LlamaIndex)` section.
704
-
705
- **WARNING:** remember that when indexing content, API calls to the embedding model are used. Each indexing consumes additional tokens. Always control the number of tokens used on the OpenAI page.
706
-
707
- **Tip:** Using the Chat with Files mode, you have default access to files manually indexed from the /data directory. However, you can use additional context by attaching a file - such additional context from the attachment does not land in the main index, but only in a temporary one, available only for the given conversation.
708
-
709
- **Token limit:** When you use `Chat with Files` in non-query mode, LlamaIndex adds extra context to the system prompt. If you use a plugins (which also adds more instructions to system prompt), you might go over the maximum number of tokens allowed. If you get a warning that says you've used too many tokens, turn off plugins you're not using or turn off the "+ Tools" option to reduce the number of tokens used by the system prompt.
710
-
711
- **Available vector stores** (provided by `LlamaIndex`):
712
-
713
- ```
714
- - ChromaVectorStore
715
- - ElasticsearchStore
716
- - PinecodeVectorStore
717
- - RedisVectorStore
718
- - SimpleVectorStore
719
- ```
720
-
721
- You can configure selected vector store by providing config options like `api_key`, etc. in `Settings -> LlamaIndex` window. See the section: `Configuration / Vector stores` for configuration reference.
722
-
723
-
724
- **Configuring data loaders**
725
-
726
- In the `Settings -> LlamaIndex -> Data loaders` section you can define the additional keyword arguments to pass into data loader instance. See the section: `Configuration / Data Loaders` for configuration reference.
727
-
728
735
 
729
736
  ## Agent (LlamaIndex)
730
737
 
@@ -4090,6 +4097,11 @@ may consume additional tokens that are not displayed in the main window.
4090
4097
 
4091
4098
  ## Recent changes:
4092
4099
 
4100
+ **2.5.21 (2025-06-28)**
4101
+
4102
+ - Fixed JS errors in logger.
4103
+ - Updated CSS.
4104
+
4093
4105
  **2.5.20 (2025-06-28)**
4094
4106
 
4095
4107
  - LlamaIndex upgraded to 0.12.44.
@@ -1,6 +1,6 @@
1
- pygpt_net/CHANGELOG.txt,sha256=Ufd0AeKxqsCnYgRNiOTpeAKosqLnYwYzK95A9kKF660,84820
1
+ pygpt_net/CHANGELOG.txt,sha256=JrLK-SNNHRSLQir3kR9I3FwhTcj3pBWWdlLhlvKtZHA,84886
2
2
  pygpt_net/LICENSE,sha256=dz9sfFgYahvu2NZbx4C1xCsVn9GVer2wXcMkFRBvqzY,1146
3
- pygpt_net/__init__.py,sha256=lJGMJ_msgHgCOw8t26coU_0we3JTFrqAM08V9vZ_dfU,1373
3
+ pygpt_net/__init__.py,sha256=67e3FlOfsdVfzsOgyHHNhlr4IORWCB3VAzPY134MtgA,1373
4
4
  pygpt_net/app.py,sha256=wIuKYBQFxgWEasSO36baU_aZA7qi1noM7IQP0ofhQ48,16333
5
5
  pygpt_net/config.py,sha256=Qc1FOBtTf3O6A6-6KoqUGtoJ0u8hXQeowvCVbZFwtik,16405
6
6
  pygpt_net/container.py,sha256=4puHeSNIyj3q6gTjPLsQKE1U-4fAhoNANYKiDq-mTqA,4054
@@ -225,7 +225,7 @@ pygpt_net/core/render/web/body.py,sha256=4sieQEevnBYGz-oJw-rThwRSQBp4sbKqU96rdxL
225
225
  pygpt_net/core/render/web/helpers.py,sha256=ymJl1vUAYoEh3PyMmtjpRtH4KyhZIhMjRhpwR73NLic,3576
226
226
  pygpt_net/core/render/web/parser.py,sha256=49Vq3jqRrUWWKy0WlBiwR8JcDzp3_MKoLNEXOpbL3qU,10230
227
227
  pygpt_net/core/render/web/pid.py,sha256=ZyYmzB01adMqY9-1Zi0QhGgrzyg-E9xC_VxqjNvTHWk,1331
228
- pygpt_net/core/render/web/renderer.py,sha256=khZX06XDum2j9vlbkUglNGZpaXGSyf4_q4UDhFFfEqQ,39329
228
+ pygpt_net/core/render/web/renderer.py,sha256=g-Bi8lvV4yGXZEelAtoJvZ3sFBIQHIVqGDIU5doRQmQ,40077
229
229
  pygpt_net/core/render/web/syntax_highlight.py,sha256=QSLGF5cJL_Xeqej7_TYwY_5C2w9enXV_cMEuaJ3C43U,2005
230
230
  pygpt_net/core/settings/__init__.py,sha256=onqwNiICm2VhHfmXLvp1MiEJ14m2jzeeI2pjUiaUwtY,7787
231
231
  pygpt_net/core/tabs/__init__.py,sha256=ZNKeb0o3eOw2t-Cwadt3cHmtMKzn2XyphwdnmsBgJkQ,25213
@@ -248,8 +248,8 @@ pygpt_net/css_rc.py,sha256=i13kX7irhbYCWZ5yJbcMmnkFp_UfS4PYnvRFSPF7XXo,11349
248
248
  pygpt_net/data/audio/click_off.mp3,sha256=aNiRDP1pt-Jy7ija4YKCNFBwvGWbzU460F4pZWZDS90,65201
249
249
  pygpt_net/data/audio/click_on.mp3,sha256=qfdsSnthAEHVXzeyN4LlC0OvXuyW8p7stb7VXtlvZ1k,65201
250
250
  pygpt_net/data/audio/ok.mp3,sha256=LTiV32pEBkpUGBkKkcOdOFB7Eyt_QoP2Nv6c5AaXftk,32256
251
- pygpt_net/data/config/config.json,sha256=y0ElTRT9Y-gz90AG-UD1783JuvFtN9Ls4rXc4Di4W-Y,20384
252
- pygpt_net/data/config/models.json,sha256=I64WoRGsOEpT4aYgixSCGD_LyCQRlL7m-_bXtQENoac,81125
251
+ pygpt_net/data/config/config.json,sha256=98aICLztjMz4ZP2j7wW01ldpB9ipU7YhxOmT8bi4dRs,20384
252
+ pygpt_net/data/config/models.json,sha256=lKI2mLIO4cQbb-O9-JiiA7a7naMKvY_YCef5qbTxbBs,81125
253
253
  pygpt_net/data/config/modes.json,sha256=OhpcZWkHSYuMAz8SgDYzGe9ZUcBdt-7AIghPSGgITrI,1923
254
254
  pygpt_net/data/config/presets/agent_openai.json,sha256=vMTR-soRBiEZrpJJHuFLWyx8a3Ez_BqtqjyXgxCAM_Q,733
255
255
  pygpt_net/data/config/presets/agent_openai_assistant.json,sha256=awJw9lNTGpKML6SJUShVn7lv8AXh0oic7wBeyoN7AYs,798
@@ -283,7 +283,7 @@ pygpt_net/data/css/style.light.css,sha256=szc-rgR_UoLOTegJerDoL2Rx_l-E6BOYSe956s
283
283
  pygpt_net/data/css/web-blocks.css,sha256=H_crm4OL_qsdSe8Ln8Lzcwu4NOe0myhmiBbmOKPPIGE,6316
284
284
  pygpt_net/data/css/web-blocks.dark.css,sha256=x0b3DYWv0-XeUgCSKajIpkAXAEEg-YR7GIg94pwXO7A,1319
285
285
  pygpt_net/data/css/web-blocks.light.css,sha256=TEzRZsdjY3xLkMQNzQemxORzsKvHkW_c53mYFNAGnNc,1379
286
- pygpt_net/data/css/web-chatgpt.css,sha256=uZUOIiSBcGRG2Brf7GejsgQjotcvPyR6gRsPc8g08XM,6621
286
+ pygpt_net/data/css/web-chatgpt.css,sha256=AXz-G4R40VHrcXSZPzEGrtcSDgmA2wD9hUqkGvgApfY,6622
287
287
  pygpt_net/data/css/web-chatgpt.dark.css,sha256=fFYWpV4IraSto-GyaNe8sDjmtwEoWOiQYBLmQ5G5TOM,1106
288
288
  pygpt_net/data/css/web-chatgpt.light.css,sha256=XoOyh-VP1gIpCqeBpSOi6jB6zG_7BMfvwo0-t67XmP8,1196
289
289
  pygpt_net/data/css/web-chatgpt_wide.css,sha256=QMs7L1Tcoc5zCA9YjUZRC01rF12JdF67Dk-zSVhJo8o,6620
@@ -1487,14 +1487,14 @@ pygpt_net/data/js/katex/fonts/KaTeX_Typewriter-Regular.woff,sha256=4U_tArGrp86fW
1487
1487
  pygpt_net/data/js/katex/fonts/KaTeX_Typewriter-Regular.woff2,sha256=cdUX1ngneHz6vfGGkUzDNY7aU543kxlB8rL9SiH2jAs,13568
1488
1488
  pygpt_net/data/js/katex/katex.min.css,sha256=lVaKnUaQNG4pI71WHffQZVALLQF4LMZEk4nOia8U9ow,23532
1489
1489
  pygpt_net/data/js/katex/katex.min.js,sha256=KLASOtKS2x8pUxWVzCDmlWJ4jhuLb0vtrgakbD6gDDo,276757
1490
- pygpt_net/data/locale/locale.de.ini,sha256=rqWfqXip_kNrIr6o07PI6yMmdTiBWJIT__zWlAsgNPY,66016
1491
- pygpt_net/data/locale/locale.en.ini,sha256=zqs0feieCOkRjCCqFeoR28yjjmYWQhqfV6PfU0e0bt4,79867
1492
- pygpt_net/data/locale/locale.es.ini,sha256=ALVNLou4HbMfmJL-mNUa9NkXccStUgSqInIx7qnCV6s,66183
1493
- pygpt_net/data/locale/locale.fr.ini,sha256=b6LaF_MnW4j-nU7PuMgY5R7LvjZ7juKd0OwoJGXhNkY,68231
1494
- pygpt_net/data/locale/locale.it.ini,sha256=PILGaGTCumfULasxW-2eJ0d3-06QJJJWC8_KEvjuuAs,64951
1495
- pygpt_net/data/locale/locale.pl.ini,sha256=RmU7uUgWjWGHh6V3SH4f4-303BYMvJNSYKcGNOwoqVE,64941
1496
- pygpt_net/data/locale/locale.uk.ini,sha256=3_H-9Ra5UFUX9GUOgnzKiggFs-dVMumrbDWDfiZ026o,90285
1497
- pygpt_net/data/locale/locale.zh.ini,sha256=wdQ836TvaXkiTJGN9gZLWVVSRHSKbU_AXE5WM0JYy2M,66392
1490
+ pygpt_net/data/locale/locale.de.ini,sha256=GbTpkWd-z0-KNU4VxIk0D4N5B6hidaZXUR0SgrzpPFk,65972
1491
+ pygpt_net/data/locale/locale.en.ini,sha256=Ws91HWVJ5jE8AO_QxjxHIr9djSXgKtp8MaUjoouJFYw,79841
1492
+ pygpt_net/data/locale/locale.es.ini,sha256=QZDtkHOPSumTxjYMupVCjHAk8kaZESFFo_qU69c93P0,66151
1493
+ pygpt_net/data/locale/locale.fr.ini,sha256=oUvwEl5n0H9GWezHy4xrdVtZZ1AR7qOQAd_u8ZgQO58,68187
1494
+ pygpt_net/data/locale/locale.it.ini,sha256=ZpA8rBEU6kbXK-HB_UzV7QrYZh11jr0-v4d-qCK4VVM,64923
1495
+ pygpt_net/data/locale/locale.pl.ini,sha256=Ez_kxUEaW9VbbG7pBet_5JKVmbgpAwHKa0BwRtDtocc,64919
1496
+ pygpt_net/data/locale/locale.uk.ini,sha256=9A0TudZG_nfaqfi5t7YRPtdmXzNpvB4EgHk-6upzEyU,90222
1497
+ pygpt_net/data/locale/locale.zh.ini,sha256=1lg6j4pEL5-T7064trvheWSNkx8UZIthb0OEVxZYD_g,66368
1498
1498
  pygpt_net/data/locale/plugin.agent.de.ini,sha256=BY28KpfFvgfVYJzcw2o5ScWnR4uuErIYGyc3NVHlmTw,1714
1499
1499
  pygpt_net/data/locale/plugin.agent.en.ini,sha256=88LkZUpilbV9l4QDbMyIdq_K9sbWt-CQPpavEttPjJU,1489
1500
1500
  pygpt_net/data/locale/plugin.agent.es.ini,sha256=bqaJQne8HPKFVtZ8Ukzo1TSqVW41yhYbGUqW3j2x1p8,1680
@@ -1822,7 +1822,7 @@ pygpt_net/provider/core/calendar/db_sqlite/storage.py,sha256=QDclQCQdr4QyRIqjgGX
1822
1822
  pygpt_net/provider/core/config/__init__.py,sha256=jQQgG9u_ZLsZWXustoc1uvC-abUvj4RBKPAM30-f2Kc,488
1823
1823
  pygpt_net/provider/core/config/base.py,sha256=cbvzbMNqL2XgC-36gGubnU37t94AX7LEw0lecb2Nm80,1365
1824
1824
  pygpt_net/provider/core/config/json_file.py,sha256=P78SRQpNr_nF7TYftYLnHl_DVo7GLPNs4_lvw97sqq8,5122
1825
- pygpt_net/provider/core/config/patch.py,sha256=D4Duerav5dmQt6QVNRHyeQTbTe6p1qtFaykaSRodAHs,99024
1825
+ pygpt_net/provider/core/config/patch.py,sha256=UMZ1A83IRDUJ2q9RORxFV3mpNrl4VR__obdk4b-1H0I,99282
1826
1826
  pygpt_net/provider/core/ctx/__init__.py,sha256=jQQgG9u_ZLsZWXustoc1uvC-abUvj4RBKPAM30-f2Kc,488
1827
1827
  pygpt_net/provider/core/ctx/base.py,sha256=Tfb4MDNe9BXXPU3lbzpdYwJF9S1oa2-mzgu5XT4It9g,3003
1828
1828
  pygpt_net/provider/core/ctx/db_sqlite/__init__.py,sha256=G2pB7kZfREJRLJZmfv3DKTslXC-K7EhNN2sn56q6BFA,11753
@@ -2186,8 +2186,8 @@ pygpt_net/ui/widget/textarea/web.py,sha256=2LebPHa_e5lvBqnIVzjwsLcFMoc11BonXgAUs
2186
2186
  pygpt_net/ui/widget/vision/__init__.py,sha256=8HT4tQFqQogEEpGYTv2RplKBthlsFKcl5egnv4lzzEw,488
2187
2187
  pygpt_net/ui/widget/vision/camera.py,sha256=T8b5cmK6uhf_WSSxzPt_Qod8JgMnst6q8sQqRvgQiSA,2584
2188
2188
  pygpt_net/utils.py,sha256=WtrdagJ-BlCjxGEEVq2rhsyAZMcU6JqltCXzOs823po,6707
2189
- pygpt_net-2.5.20.dist-info/LICENSE,sha256=rbPqNB_xxANH8hKayJyIcTwD4bj4Y2G-Mcm85r1OImM,1126
2190
- pygpt_net-2.5.20.dist-info/METADATA,sha256=Ezlt3umW69DKNKO9Y1VmUQ6aHQ3T8FRHh40yp2PLqnI,168480
2191
- pygpt_net-2.5.20.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
2192
- pygpt_net-2.5.20.dist-info/entry_points.txt,sha256=qvpII6UHIt8XfokmQWnCYQrTgty8FeJ9hJvOuUFCN-8,43
2193
- pygpt_net-2.5.20.dist-info/RECORD,,
2189
+ pygpt_net-2.5.21.dist-info/LICENSE,sha256=rbPqNB_xxANH8hKayJyIcTwD4bj4Y2G-Mcm85r1OImM,1126
2190
+ pygpt_net-2.5.21.dist-info/METADATA,sha256=zej14g-wySqf5rKDXiqN92b3jSV2BTeR3Bal5CeOz7s,168693
2191
+ pygpt_net-2.5.21.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
2192
+ pygpt_net-2.5.21.dist-info/entry_points.txt,sha256=qvpII6UHIt8XfokmQWnCYQrTgty8FeJ9hJvOuUFCN-8,43
2193
+ pygpt_net-2.5.21.dist-info/RECORD,,