pygpt-net 2.6.17.post1__py3-none-any.whl → 2.6.19__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. pygpt_net/CHANGELOG.txt +10 -0
  2. pygpt_net/__init__.py +3 -3
  3. pygpt_net/app.py +2 -0
  4. pygpt_net/controller/chat/output.py +2 -2
  5. pygpt_net/controller/chat/response.py +17 -28
  6. pygpt_net/core/agents/observer/evaluation.py +9 -9
  7. pygpt_net/core/agents/runner.py +53 -42
  8. pygpt_net/core/agents/tools.py +59 -40
  9. pygpt_net/core/experts/experts.py +32 -366
  10. pygpt_net/core/experts/worker.py +362 -0
  11. pygpt_net/core/idx/chat.py +49 -82
  12. pygpt_net/core/idx/context.py +10 -14
  13. pygpt_net/core/idx/idx.py +19 -8
  14. pygpt_net/core/idx/indexing.py +35 -38
  15. pygpt_net/core/idx/response.py +91 -2
  16. pygpt_net/core/idx/worker.py +3 -8
  17. pygpt_net/core/render/web/body.py +18 -1
  18. pygpt_net/core/render/web/renderer.py +28 -13
  19. pygpt_net/core/types/__init__.py +2 -1
  20. pygpt_net/core/types/tools.py +22 -0
  21. pygpt_net/data/config/config.json +4 -4
  22. pygpt_net/data/config/models.json +3 -3
  23. pygpt_net/data/config/presets/current.llama_index.json +1 -1
  24. pygpt_net/provider/agents/openai/evolve.py +1 -1
  25. pygpt_net/provider/gpt/summarizer.py +4 -0
  26. pygpt_net/ui/widget/filesystem/explorer.py +7 -9
  27. pygpt_net/utils.py +2 -0
  28. {pygpt_net-2.6.17.post1.dist-info → pygpt_net-2.6.19.dist-info}/METADATA +12 -2
  29. {pygpt_net-2.6.17.post1.dist-info → pygpt_net-2.6.19.dist-info}/RECORD +32 -30
  30. {pygpt_net-2.6.17.post1.dist-info → pygpt_net-2.6.19.dist-info}/LICENSE +0 -0
  31. {pygpt_net-2.6.17.post1.dist-info → pygpt_net-2.6.19.dist-info}/WHEEL +0 -0
  32. {pygpt_net-2.6.17.post1.dist-info → pygpt_net-2.6.19.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: 2025.08.02 20:00:00 #
9
+ # Updated Date: 2025.08.21 07:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
@@ -46,7 +46,7 @@ class Context:
46
46
  prev_message = None,
47
47
  allow_native_tool_calls: bool = False,
48
48
  attachments: Dict[str, AttachmentItem] = None,
49
- ):
49
+ ) -> List[ChatMessage]:
50
50
  """
51
51
  Get messages from db
52
52
 
@@ -57,7 +57,7 @@ class Context:
57
57
  :param prev_message: previous message
58
58
  :param allow_native_tool_calls: allow native tool calls
59
59
  :param attachments: attachments
60
- :return: Messages
60
+ :return: List of ChatMessage objects
61
61
  """
62
62
  messages = []
63
63
 
@@ -155,17 +155,13 @@ class Context:
155
155
 
156
156
  :param query: input query
157
157
  :param attachments: attachments
158
+ :return: ChatMessage object
158
159
  """
159
- blocks = []
160
- blocks.append(
161
- TextBlock(text=query)
162
- )
160
+ blocks = [TextBlock(text=query)]
163
161
 
164
162
  self.attachments = {} # reset attachments, only current prompt
165
163
  self.urls = []
166
164
 
167
- #https://pygpt.net/assets/img/img3.jpg?v=2024-11-28
168
-
169
165
  # extract URLs from prompt
170
166
  urls = self.extract_urls(query)
171
167
  if len(urls) > 0:
@@ -186,14 +182,12 @@ class Context:
186
182
  )
187
183
  self.attachments[id] = attachment.path
188
184
 
189
- msg = ChatMessage(
185
+ return ChatMessage(
190
186
  role=MessageRole.USER,
191
187
  blocks=blocks,
192
188
  )
193
- return msg
194
-
195
-
196
189
 
190
+ """
197
191
  urls.append(attachment.path)
198
192
  msg = ChatMessage(
199
193
  role=MessageRole.USER,
@@ -208,12 +202,14 @@ class Context:
208
202
  image_documents=image_documents,
209
203
  )
210
204
  return msg
205
+ """
211
206
 
212
207
  def add_system(self, prompt: str) -> ChatMessage:
213
208
  """
214
209
  Add system message to db
215
210
 
216
211
  :param prompt: system prompt
212
+ :return: ChatMessage object
217
213
  """
218
214
  return ChatMessage(
219
215
  role=MessageRole.SYSTEM,
@@ -224,7 +220,7 @@ class Context:
224
220
  """
225
221
  Append images content to context item
226
222
 
227
- :param ctx: context
223
+ :param ctx: context item
228
224
  """
229
225
  images = self.get_attachments() # dict -> key: id, value: path
230
226
  urls = self.get_urls() # list
pygpt_net/core/idx/idx.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: 2025.06.30 20:00:00 #
9
+ # Updated Date: 2025.08.21 07:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import datetime
@@ -78,6 +78,17 @@ class Idx:
78
78
  self.load()
79
79
  self.initialized = True
80
80
 
81
+ def is_valid(self, idx: str = None) -> bool:
82
+ """
83
+ Check if index is valid
84
+
85
+ :param idx: index name
86
+ :return: True if index is valid
87
+ """
88
+ if idx and idx != "_":
89
+ return self.has(idx)
90
+ return False
91
+
81
92
  def get_current_store(self) -> str:
82
93
  """
83
94
  Get current vector store name/ID
@@ -166,7 +177,7 @@ class Idx:
166
177
  ) # store index
167
178
 
168
179
  if errors:
169
- self.log("Error: " + str(errors))
180
+ self.log(f"Error: {errors}")
170
181
  return files, errors
171
182
 
172
183
  def index_db_by_meta_id(
@@ -202,7 +213,7 @@ class Idx:
202
213
  ) # store index
203
214
 
204
215
  if errors:
205
- self.log("Error: " + str(errors))
216
+ self.log(f"Error: {errors}")
206
217
  return num, errors
207
218
 
208
219
  def index_db_from_updated_ts(
@@ -235,7 +246,7 @@ class Idx:
235
246
  ) # store index
236
247
 
237
248
  if errors:
238
- self.log("Error: " + str(errors))
249
+ self.log(f"Error: {errors}")
239
250
  return num, errors
240
251
 
241
252
  def index_urls(
@@ -274,7 +285,7 @@ class Idx:
274
285
  ) # store index
275
286
 
276
287
  if errors:
277
- self.log("Error: " + str(errors))
288
+ self.log(f"Error: {errors}")
278
289
  return n, errors
279
290
 
280
291
  def index_web(
@@ -320,7 +331,7 @@ class Idx:
320
331
  ) # store index
321
332
 
322
333
  if errors:
323
- self.log("Error: " + str(errors))
334
+ self.log(f"Error: {errors}")
324
335
  return n, errors
325
336
 
326
337
  def get_idx_data(
@@ -478,7 +489,7 @@ class Idx:
478
489
  """
479
490
  self.llm.get_service_context(stream=False) # init environment only (ENV API keys, etc.)
480
491
  if self.storage.remove_document(idx, doc_id):
481
- self.log("Removed document from index: " + idx + " - " + doc_id)
492
+ self.log(f"Removed document from index: {idx} - {doc_id}")
482
493
 
483
494
  def remove_file(
484
495
  self,
@@ -592,5 +603,5 @@ class Idx:
592
603
  is_log = True
593
604
  self.window.core.debug.info(msg, not is_log)
594
605
  if is_log:
595
- print("[LLAMA-INDEX] {}".format(msg))
606
+ print(f"[LlamaIndex] {msg}")
596
607
  self.window.idx_logger_message.emit(msg)
@@ -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.08.06 01:00:00 #
9
+ # Updated Date: 2025.08.21 07:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import datetime
@@ -53,7 +53,7 @@ class Indexing:
53
53
  # check if compiled version is allowed
54
54
  is_compiled = self.window.core.config.is_compiled() or self.window.core.platforms.is_snap()
55
55
  if not loader.allow_compiled and is_compiled:
56
- self.window.core.idx.log("Loader not allowed in compiled version: " + loader.id)
56
+ self.window.core.idx.log(f"Loader not allowed in compiled version: {loader.id}" )
57
57
  return
58
58
 
59
59
  loader.attach_window(self.window)
@@ -67,7 +67,7 @@ class Indexing:
67
67
  for ext in extensions:
68
68
  self.loaders["file"][ext] = loader # set reader instance, by file extension
69
69
  except ImportError as e:
70
- msg = "Error while registering data loader: " + loader.id + " - " + str(e)
70
+ msg = f"Error while registering data loader: {loader.id} - {e}"
71
71
  self.window.core.debug.log(msg)
72
72
  self.window.core.debug.log(e)
73
73
 
@@ -101,7 +101,7 @@ class Indexing:
101
101
  self.external_config[loader.id][key]["description"] = loader.init_args_desc[key]
102
102
 
103
103
  except ImportError as e:
104
- msg = "Error while registering data loader: " + loader.id + " - " + str(e)
104
+ msg = f"Error while registering data loader: {loader.id} - {e}"
105
105
  self.window.core.debug.log(msg)
106
106
  self.window.core.debug.log(e)
107
107
 
@@ -305,7 +305,7 @@ class Indexing:
305
305
  """
306
306
  # TODO: if .zip then unpack here, and return path to /tmp
307
307
  if not silent:
308
- self.window.core.idx.log("Reading documents from path: {}".format(path))
308
+ self.window.core.idx.log(f"Reading documents from path: {path}")
309
309
  if os.path.isdir(path):
310
310
  reader = SimpleDirectoryReader(
311
311
  input_dir=path,
@@ -320,13 +320,13 @@ class Indexing:
320
320
  # check if not excluded extension
321
321
  if self.is_excluded(ext) and not force:
322
322
  if not silent:
323
- self.window.core.idx.log("Ignoring excluded extension: {}".format(ext))
323
+ self.window.core.idx.log(f"Ignoring excluded extension: {ext}")
324
324
  return []
325
325
 
326
326
  # check if not excluded path
327
327
  if self.is_excluded_path(path) and not force:
328
328
  if not silent:
329
- self.window.core.idx.log("Ignoring excluded path: {}".format(path))
329
+ self.window.core.idx.log(f"Ignoring excluded path: {path}")
330
330
  return []
331
331
 
332
332
  # check if archive (zip, tar)
@@ -337,7 +337,7 @@ class Indexing:
337
337
 
338
338
  if ext in self.loaders["file"]:
339
339
  if not silent:
340
- self.window.core.idx.log("Using loader for: {}".format(ext))
340
+ self.window.core.idx.log(f"Using loader for: {ext}")
341
341
  reader = self.loaders["file"][ext].get() # get data reader instance
342
342
 
343
343
  # use custom loader method if available
@@ -347,7 +347,7 @@ class Indexing:
347
347
  documents = reader.load_data(file=Path(path))
348
348
  else:
349
349
  if not silent:
350
- self.window.core.idx.log("Using default SimpleDirectoryReader for: {}".format(ext))
350
+ self.window.core.idx.log(f"Using default SimpleDirectoryReader for: {ext}")
351
351
  reader = SimpleDirectoryReader(input_files=[path])
352
352
  documents = reader.load_data()
353
353
 
@@ -424,8 +424,8 @@ class Indexing:
424
424
 
425
425
  # get unique external content identifier
426
426
  unique_id = self.data_providers[type].get_external_id(extra_args)
427
- self.window.core.idx.log("Loading web documents from: {}".format(unique_id))
428
- self.window.core.idx.log("Using web loader for type: {}".format(type))
427
+ self.window.core.idx.log(f"Loading web documents from: {unique_id}")
428
+ self.window.core.idx.log(f"Using web loader for type: {type}")
429
429
 
430
430
  args = self.data_providers[type].prepare_args(**extra_args)
431
431
 
@@ -509,10 +509,10 @@ class Indexing:
509
509
  self.prepare_document(d)
510
510
  self.index_document(index, d)
511
511
  indexed[file] = d.id_ # add to index
512
- self.window.core.idx.log("Inserted document: {}, metadata: {}".format(d.id_, d.metadata))
512
+ self.window.core.idx.log(f"Inserted document: {d.id_}, metadata: {d.metadata}")
513
513
  except Exception as e:
514
514
  errors.append(str(e))
515
- print("Error while indexing file: " + file)
515
+ print(f"Error while indexing file: {file}")
516
516
  self.window.core.debug.log(e)
517
517
  if self.stop_enabled():
518
518
  break # break loop if error
@@ -571,10 +571,10 @@ class Indexing:
571
571
  self.prepare_document(d)
572
572
  self.index_document(index, d)
573
573
  indexed[file_path] = d.id_ # add to index
574
- self.window.core.idx.log("Inserted document: {}, metadata: {}".format(d.id_, d.metadata))
574
+ self.window.core.idx.log(f"Inserted document: {d.id_}, metadata: {d.metadata}")
575
575
  except Exception as e:
576
576
  errors.append(str(e))
577
- print("Error while indexing file: " + file_path)
577
+ print(f"Error while indexing file: {file_path}")
578
578
  self.window.core.debug.log(e)
579
579
  if self.stop_enabled():
580
580
  is_break = True
@@ -607,10 +607,10 @@ class Indexing:
607
607
  self.prepare_document(d)
608
608
  self.index_document(index, d)
609
609
  indexed[path] = d.id_ # add to index
610
- self.window.core.idx.log("Inserted document: {}, metadata: {}".format(d.id_, d.metadata))
610
+ self.window.core.idx.log(f"Inserted document: {d.id_}, metadata: {d.metadata}")
611
611
  except Exception as e:
612
612
  errors.append(str(e))
613
- print("Error while indexing file: " + path)
613
+ print(f"Error while indexing file: {path}")
614
614
  self.window.core.debug.log(e)
615
615
 
616
616
  return indexed, errors
@@ -748,11 +748,10 @@ class Indexing:
748
748
  try:
749
749
  # remove old document from index if indexing by ID only and not from timestamp
750
750
  if from_ts == 0:
751
- self.window.core.idx.log("Indexing documents from database by meta id: {}".format(id))
751
+ self.window.core.idx.log(f"Indexing documents from database by meta id: {id}")
752
752
  self.remove_old_meta_id(idx, id)
753
753
  elif from_ts > 0:
754
- self.window.core.idx.log("Indexing documents from database by meta id: {} from timestamp: {}".
755
- format(id, from_ts))
754
+ self.window.core.idx.log(f"Indexing documents from database by meta id: {id} from timestamp: {from_ts}")
756
755
 
757
756
  # get items from database
758
757
  documents = self.get_db_data_by_id(id, from_ts)
@@ -762,8 +761,7 @@ class Indexing:
762
761
 
763
762
  self.index_document(index, d)
764
763
  doc_id = d.id_
765
- self.window.core.idx.log("Inserted ctx DB document: {} / {}, id: {}, metadata: {}".
766
- format(n+1, len(documents), d.id_, d.metadata))
764
+ self.window.core.idx.log(f"Inserted ctx DB document: {n+1} / {len(documents)}, id: {d.id_}, metadata: {d.metadata}")
767
765
  self.window.core.ctx.idx.set_meta_as_indexed(id, idx, doc_id) # update ctx
768
766
  n += 1
769
767
  except Exception as e:
@@ -785,7 +783,7 @@ class Indexing:
785
783
  :param from_ts: timestamp
786
784
  :return: number of indexed documents, errors
787
785
  """
788
- self.window.core.idx.log("Indexing documents from database from timestamp: {}".format(from_ts))
786
+ self.window.core.idx.log(f"Indexing documents from database from timestamp: {from_ts}")
789
787
  errors = []
790
788
  n = 0
791
789
  ids = self.get_db_meta_ids_from_ts(from_ts)
@@ -825,7 +823,7 @@ class Indexing:
825
823
 
826
824
  # check if web loader for defined type exists
827
825
  if type not in self.loaders["web"]:
828
- raise ValueError("No web loader for type: {}".format(type))
826
+ raise ValueError(f"No web loader for type: {type}")
829
827
 
830
828
  try:
831
829
  # remove old content from index if already indexed
@@ -851,8 +849,8 @@ class Indexing:
851
849
  if not is_tmp:
852
850
  self.remove_old_external(idx, unique_id, type)
853
851
 
854
- self.window.core.idx.log("Loading web documents from: {}".format(unique_id))
855
- self.window.core.idx.log("Using web loader for type: {}".format(type))
852
+ self.window.core.idx.log(f"Loading web documents from: {unique_id}")
853
+ self.window.core.idx.log(f"Using web loader for type: {type}")
856
854
 
857
855
  args = self.data_providers[type].prepare_args(**extra_args)
858
856
 
@@ -877,8 +875,7 @@ class Indexing:
877
875
  idx=idx,
878
876
  doc_id=doc_id,
879
877
  ) # update external index
880
- self.window.core.idx.log("Inserted web document: {} / {}, id: {}, metadata: {}".
881
- format(n+1, len(documents), d.id_, d.metadata))
878
+ self.window.core.idx.log(f"Inserted web document: {n+1} / {len(documents)}, id: {d.id_}, metadata: {d.metadata}")
882
879
  n += 1
883
880
  except Exception as e:
884
881
  errors.append(str(e))
@@ -910,7 +907,7 @@ class Indexing:
910
907
 
911
908
  # check if web loader for defined type exists
912
909
  if type not in self.loaders["web"]:
913
- msg = "No web loader for type: {}".format(type)
910
+ msg = f"No web loader for type: {type}"
914
911
  errors.append(msg)
915
912
  self.window.core.debug.log(msg)
916
913
  return n, errors
@@ -953,7 +950,7 @@ class Indexing:
953
950
  if self.window.core.idx.ctx.exists(store, idx, id):
954
951
  doc_id = self.window.core.idx.ctx.get_doc_id(store, idx, id)
955
952
  if doc_id:
956
- self.window.core.idx.log("Removing old document id: {}".format(doc_id))
953
+ self.window.core.idx.log(f"Removing old document id: {doc_id}")
957
954
  try:
958
955
  self.window.core.idx.storage.remove_document(
959
956
  id=idx,
@@ -986,7 +983,7 @@ class Indexing:
986
983
  if self.window.core.idx.files.exists(store, idx, file_id):
987
984
  doc_id = self.window.core.idx.files.get_doc_id(store, idx, file_id)
988
985
  if doc_id:
989
- self.window.core.idx.log("Removing old document id: {}".format(doc_id))
986
+ self.window.core.idx.log(f"Removing old document id: {doc_id}")
990
987
  try:
991
988
  self.window.core.idx.storage.remove_document(
992
989
  id=idx,
@@ -1021,7 +1018,7 @@ class Indexing:
1021
1018
  if self.window.core.idx.external.exists(store, idx, content, type):
1022
1019
  doc_id = self.window.core.idx.external.get_doc_id(store, idx, content, type)
1023
1020
  if doc_id:
1024
- self.window.core.idx.log("Removing old document id: {}".format(doc_id))
1021
+ self.window.core.idx.log(f"Removing old document id: {doc_id}")
1025
1022
  try:
1026
1023
  self.window.core.idx.storage.remove_document(
1027
1024
  id=idx,
@@ -1080,8 +1077,8 @@ class Indexing:
1080
1077
  embed_model=embed_model,
1081
1078
  ) # get or create ctx index
1082
1079
 
1083
- idx = "tmp:{}".format(index_path) # tmp index id
1084
- self.window.core.idx.log("Indexing to context attachment index: {}...".format(idx))
1080
+ idx = f"tmp:{index_path}" # tmp index id
1081
+ self.window.core.idx.log(f"Indexing to context attachment index: {idx}...")
1085
1082
 
1086
1083
  doc_ids = []
1087
1084
  if documents is None:
@@ -1118,8 +1115,8 @@ class Indexing:
1118
1115
  llm, embed_model = self.window.core.idx.llm.get_service_context(model=model, stream=False)
1119
1116
  index = self.window.core.idx.storage.get_ctx_idx(index_path, llm, embed_model) # get or create ctx index
1120
1117
 
1121
- idx = "tmp:{}".format(index_path) # tmp index id
1122
- self.window.core.idx.log("Indexing to context attachment index: {}...".format(idx))
1118
+ idx = f"tmp:{index_path}" # tmp index id
1119
+ self.window.core.idx.log(f"Indexing to context attachment index: {idx}...")
1123
1120
 
1124
1121
  web_type = self.get_webtype(url)
1125
1122
  doc_ids = []
@@ -1153,7 +1150,7 @@ class Indexing:
1153
1150
  if loader.is_supported_attachment(url):
1154
1151
  type = id
1155
1152
  break
1156
- print("Selected web data loader: {}".format(type))
1153
+ print(f"Selected web data loader: {type}")
1157
1154
  return type
1158
1155
 
1159
1156
  def remove_attachment(
@@ -1188,7 +1185,7 @@ class Indexing:
1188
1185
  time_since_last_call = now - self.last_call
1189
1186
  if time_since_last_call < interval:
1190
1187
  sleep_time = (interval - time_since_last_call).total_seconds()
1191
- self.window.core.idx.log("RPM limit: sleep for {} seconds".format(sleep_time))
1188
+ self.window.core.idx.log(f"RPM limit: sleep for {sleep_time} seconds")
1192
1189
  time.sleep(sleep_time)
1193
1190
  self.last_call = now
1194
1191
 
@@ -6,28 +6,87 @@
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.08.14 01:00:00 #
9
+ # Updated Date: 2025.08.21 07:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from typing import Any
13
+
13
14
  from pygpt_net.item.model import ModelItem
14
15
  from pygpt_net.item.ctx import CtxItem
15
16
 
16
17
  class Response:
17
18
  def __init__(self, window=None):
18
19
  """
19
- Response
20
+ Response handler for processing responses from LLM or index.
20
21
 
21
22
  :param window: Window instance
22
23
  """
23
24
  self.window = window
24
25
 
26
+ def handle(
27
+ self,
28
+ ctx: CtxItem,
29
+ model: ModelItem,
30
+ llm,
31
+ response: Any,
32
+ cmd_enabled: bool,
33
+ use_react: bool,
34
+ use_index: bool,
35
+ stream: bool
36
+ ) -> None:
37
+ """
38
+ Handle response based on the context, model, and response type.
39
+
40
+ :param ctx: Context item
41
+ :param model: Model item
42
+ :param llm: LLM instance
43
+ :param response: Response data
44
+ :param cmd_enabled: Tools enabled flag
45
+ :param use_react: Use REACT flag
46
+ :param use_index: Use index flag
47
+ :param stream: Stream enabled flag
48
+ """
49
+ if cmd_enabled:
50
+ # tools enabled
51
+ if use_react:
52
+ self.from_react(ctx, model, response) # TOOLS + REACT, non-stream
53
+ else:
54
+ if stream:
55
+ if use_index:
56
+ self.from_index_stream(ctx, model, response) # INDEX + STREAM
57
+ else:
58
+ self.from_llm_stream(ctx, model, llm, response) # LLM + STREAM
59
+ else:
60
+ if use_index:
61
+ self.from_index(ctx, model, response) # TOOLS + INDEX
62
+ else:
63
+ self.from_llm(ctx, model, llm, response) # TOOLS + LLM
64
+ else:
65
+ # no tools
66
+ if stream:
67
+ if use_index:
68
+ self.from_index_stream(ctx, model, response) # INDEX + STREAM
69
+ else:
70
+ self.from_llm_stream(ctx, model, llm, response) # LLM + STREAM
71
+ else:
72
+ if use_index:
73
+ self.from_index(ctx, model, response) # INDEX
74
+ else:
75
+ self.from_llm(ctx, model, llm, response) # LLM
76
+
25
77
  def from_react(
26
78
  self,
27
79
  ctx: CtxItem,
28
80
  model: ModelItem,
29
81
  response: Any
30
82
  ) -> None:
83
+ """
84
+ Handle response from REACT.
85
+
86
+ :param ctx: CtxItem
87
+ :param model: ModelItem
88
+ :param response: Response data
89
+ """
31
90
  output = str(response)
32
91
  if output is None:
33
92
  output = ""
@@ -39,6 +98,13 @@ class Response:
39
98
  model: ModelItem,
40
99
  response: Any
41
100
  ) -> None:
101
+ """
102
+ Handle response from index.
103
+
104
+ :param ctx: CtxItem
105
+ :param model: ModelItem
106
+ :param response: Response data
107
+ """
42
108
  output = str(response.response)
43
109
  if output is None:
44
110
  output = ""
@@ -51,6 +117,14 @@ class Response:
51
117
  llm,
52
118
  response: Any
53
119
  ) -> None:
120
+ """
121
+ Handle response from LLM.
122
+
123
+ :param ctx: CtxItem
124
+ :param model: ModelItem
125
+ :param llm: LLM instance
126
+ :param response: Response data
127
+ """
54
128
  output = response.message.content
55
129
  tool_calls = llm.get_tool_calls_from_response(
56
130
  response,
@@ -67,6 +141,13 @@ class Response:
67
141
  model: ModelItem,
68
142
  response: Any
69
143
  ) -> None:
144
+ """
145
+ Handle streaming response from index.
146
+
147
+ :param ctx: CtxItem
148
+ :param model: ModelItem
149
+ :param response: Response data
150
+ """
70
151
  ctx.stream = response.response_gen
71
152
  ctx.set_output("", "")
72
153
 
@@ -77,5 +158,13 @@ class Response:
77
158
  llm,
78
159
  response: Any
79
160
  ) -> None:
161
+ """
162
+ Handle streaming response from LLM.
163
+
164
+ :param ctx: CtxItem
165
+ :param model: ModelItem
166
+ :param llm: LLM instance
167
+ :param response: Response data
168
+ """
80
169
  ctx.stream = response # chunk is in response.delta
81
170
  ctx.set_output("", "")
@@ -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.08.11 14:00:00 #
9
+ # Updated Date: 2025.08.21 07:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import QObject, Signal, QRunnable, Slot
@@ -42,12 +42,7 @@ class IndexWorker(QRunnable):
42
42
 
43
43
  # log
44
44
  self.log("Indexing data...")
45
- self.log("Idx: {}, type: {}, content: {}, from_ts: {}".format(
46
- self.idx,
47
- self.type,
48
- self.content,
49
- self.from_ts,
50
- ))
45
+ self.log(f"Idx: {self.idx}, type: {self.type}, content: {self.content}, from_ts: {self.from_ts}")
51
46
 
52
47
  # execute indexing
53
48
  if self.type == "file":
@@ -126,5 +121,5 @@ class IndexWorker(QRunnable):
126
121
  is_log = True
127
122
  self.window.core.debug.info(msg, not is_log)
128
123
  if is_log:
129
- print("[LLAMA-INDEX] {}".format(msg))
124
+ print(f"[LlamaIndex] {msg}")
130
125
  self.window.idx_logger_message.emit(msg)
@@ -262,7 +262,22 @@ class Body:
262
262
  element.classList.remove('empty_list');
263
263
  element.insertAdjacentHTML('beforeend', content);
264
264
  highlightCode(true, element);
265
- scheduleScroll();
265
+ scrollToBottom(false); // without schedule
266
+ }
267
+ }
268
+ function replaceNodes(content) {
269
+ if (DEBUG_MODE) {
270
+ log("REPLACE NODES: {" + content + "}");
271
+ }
272
+ clearStreamBefore();
273
+ prevScroll = 0;
274
+ const element = els.nodes || document.getElementById('_nodes_');
275
+ if (element) {
276
+ element.classList.remove('empty_list');
277
+ element.replaceChildren();
278
+ element.insertAdjacentHTML('beforeend', content);
279
+ highlightCode(true, element);
280
+ scrollToBottom(false); // without schedule
266
281
  }
267
282
  }
268
283
  function clean() {
@@ -275,6 +290,7 @@ class Body:
275
290
  }
276
291
  resetEphemeralDomRefs();
277
292
  els = {};
293
+ /*
278
294
  try {
279
295
  if (window.gc) {
280
296
  window.gc();
@@ -282,6 +298,7 @@ class Body:
282
298
  } catch (e) {
283
299
  // gc not available
284
300
  }
301
+ */
285
302
  }
286
303
  function appendExtra(id, content) {
287
304
  hideTips();