pygpt-net 2.6.20__py3-none-any.whl → 2.6.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.
Files changed (89) hide show
  1. pygpt_net/CHANGELOG.txt +9 -0
  2. pygpt_net/__init__.py +3 -3
  3. pygpt_net/controller/agent/agent.py +130 -2
  4. pygpt_net/controller/agent/experts.py +93 -96
  5. pygpt_net/controller/agent/llama.py +2 -1
  6. pygpt_net/controller/assistant/assistant.py +18 -1
  7. pygpt_net/controller/attachment/attachment.py +17 -1
  8. pygpt_net/controller/camera/camera.py +15 -7
  9. pygpt_net/controller/chat/chat.py +2 -2
  10. pygpt_net/controller/chat/common.py +50 -33
  11. pygpt_net/controller/chat/image.py +67 -77
  12. pygpt_net/controller/chat/input.py +94 -166
  13. pygpt_net/controller/chat/output.py +83 -140
  14. pygpt_net/controller/chat/response.py +83 -102
  15. pygpt_net/controller/chat/text.py +116 -149
  16. pygpt_net/controller/ctx/common.py +2 -1
  17. pygpt_net/controller/ctx/ctx.py +86 -6
  18. pygpt_net/controller/files/files.py +13 -1
  19. pygpt_net/controller/idx/idx.py +26 -2
  20. pygpt_net/controller/kernel/reply.py +53 -66
  21. pygpt_net/controller/kernel/stack.py +16 -16
  22. pygpt_net/controller/model/importer.py +2 -1
  23. pygpt_net/controller/model/model.py +62 -3
  24. pygpt_net/controller/settings/editor.py +4 -4
  25. pygpt_net/controller/ui/ui.py +16 -2
  26. pygpt_net/core/agents/observer/evaluation.py +3 -3
  27. pygpt_net/core/agents/provider.py +25 -3
  28. pygpt_net/core/agents/runner.py +4 -1
  29. pygpt_net/core/agents/runners/llama_workflow.py +19 -7
  30. pygpt_net/core/agents/runners/loop.py +3 -1
  31. pygpt_net/core/agents/runners/openai_workflow.py +17 -3
  32. pygpt_net/core/agents/tools.py +4 -1
  33. pygpt_net/core/bridge/context.py +34 -37
  34. pygpt_net/core/ctx/ctx.py +1 -1
  35. pygpt_net/core/db/database.py +2 -2
  36. pygpt_net/core/debug/debug.py +12 -1
  37. pygpt_net/core/dispatcher/dispatcher.py +24 -1
  38. pygpt_net/core/events/app.py +7 -7
  39. pygpt_net/core/events/control.py +26 -26
  40. pygpt_net/core/events/event.py +6 -3
  41. pygpt_net/core/events/kernel.py +2 -2
  42. pygpt_net/core/events/render.py +13 -13
  43. pygpt_net/core/experts/experts.py +76 -82
  44. pygpt_net/core/experts/worker.py +12 -12
  45. pygpt_net/core/models/models.py +5 -1
  46. pygpt_net/core/models/ollama.py +14 -5
  47. pygpt_net/core/render/web/helpers.py +2 -2
  48. pygpt_net/core/render/web/renderer.py +4 -4
  49. pygpt_net/core/types/__init__.py +2 -1
  50. pygpt_net/core/types/agent.py +4 -4
  51. pygpt_net/core/types/base.py +19 -0
  52. pygpt_net/core/types/console.py +6 -6
  53. pygpt_net/core/types/mode.py +8 -8
  54. pygpt_net/core/types/multimodal.py +3 -3
  55. pygpt_net/core/types/openai.py +2 -1
  56. pygpt_net/data/config/config.json +4 -4
  57. pygpt_net/data/config/models.json +19 -3
  58. pygpt_net/data/config/settings.json +14 -14
  59. pygpt_net/data/locale/locale.en.ini +2 -2
  60. pygpt_net/item/ctx.py +256 -240
  61. pygpt_net/item/model.py +59 -116
  62. pygpt_net/item/preset.py +122 -105
  63. pygpt_net/provider/agents/llama_index/workflow/planner.py +3 -3
  64. pygpt_net/provider/agents/openai/agent.py +4 -12
  65. pygpt_net/provider/agents/openai/agent_b2b.py +10 -15
  66. pygpt_net/provider/agents/openai/agent_planner.py +4 -4
  67. pygpt_net/provider/agents/openai/agent_with_experts.py +3 -7
  68. pygpt_net/provider/agents/openai/agent_with_experts_feedback.py +4 -8
  69. pygpt_net/provider/agents/openai/agent_with_feedback.py +4 -8
  70. pygpt_net/provider/agents/openai/bot_researcher.py +2 -18
  71. pygpt_net/provider/agents/openai/bots/__init__.py +0 -0
  72. pygpt_net/provider/agents/openai/bots/research_bot/__init__.py +0 -0
  73. pygpt_net/provider/agents/openai/bots/research_bot/agents/__init__.py +0 -0
  74. pygpt_net/provider/agents/openai/bots/research_bot/agents/planner_agent.py +1 -1
  75. pygpt_net/provider/agents/openai/bots/research_bot/agents/search_agent.py +1 -0
  76. pygpt_net/provider/agents/openai/bots/research_bot/agents/writer_agent.py +1 -1
  77. pygpt_net/provider/agents/openai/bots/research_bot/manager.py +1 -10
  78. pygpt_net/provider/agents/openai/evolve.py +5 -9
  79. pygpt_net/provider/agents/openai/supervisor.py +4 -8
  80. pygpt_net/provider/core/config/patch.py +10 -3
  81. pygpt_net/provider/core/ctx/db_sqlite/utils.py +43 -43
  82. pygpt_net/provider/core/model/patch.py +11 -1
  83. pygpt_net/provider/core/preset/json_file.py +47 -49
  84. pygpt_net/provider/gpt/agents/experts.py +2 -2
  85. {pygpt_net-2.6.20.dist-info → pygpt_net-2.6.21.dist-info}/METADATA +13 -6
  86. {pygpt_net-2.6.20.dist-info → pygpt_net-2.6.21.dist-info}/RECORD +86 -85
  87. {pygpt_net-2.6.20.dist-info → pygpt_net-2.6.21.dist-info}/LICENSE +0 -0
  88. {pygpt_net-2.6.20.dist-info → pygpt_net-2.6.21.dist-info}/WHEEL +0 -0
  89. {pygpt_net-2.6.20.dist-info → pygpt_net-2.6.21.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.19 07:00:00 #
9
+ # Updated Date: 2025.08.24 02:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from typing import Dict, Any
@@ -25,6 +25,9 @@ from pygpt_net.utils import trans
25
25
 
26
26
 
27
27
  class Response:
28
+
29
+ AGENT_MODES_ALLOWED = (MODE_AGENT_LLAMA, MODE_AGENT_OPENAI)
30
+
28
31
  def __init__(self, window=None):
29
32
  """
30
33
  Response controller
@@ -47,12 +50,14 @@ class Response:
47
50
  :param context: BridgeContext
48
51
  :param extra: Extra data
49
52
  """
53
+ core = self.window.core
54
+ controller = self.window.controller
55
+ dispatch = self.window.dispatch
50
56
  ctx = context.ctx
57
+
51
58
  if not status:
52
- error = None
53
- if "error" in extra:
54
- error = extra.get("error")
55
- self.window.controller.chat.log("Bridge response: ERROR")
59
+ error = extra.get("error", None)
60
+ controller.chat.log("Bridge response: ERROR")
56
61
  if error is not None:
57
62
  self.window.ui.dialogs.alert(error)
58
63
  self.window.update_status(error)
@@ -60,8 +65,8 @@ class Response:
60
65
  self.window.ui.dialogs.alert(trans('status.error'))
61
66
  self.window.update_status(trans('status.error'))
62
67
  else:
63
- self.window.controller.chat.log_ctx(ctx, "output") # log
64
- if self.window.controller.kernel.stopped():
68
+ controller.chat.log_ctx(ctx, "output") # log
69
+ if controller.kernel.stopped():
65
70
  return
66
71
 
67
72
  ctx.current = False # reset current state
@@ -69,19 +74,16 @@ class Response:
69
74
  mode = extra.get('mode', MODE_CHAT)
70
75
  reply = extra.get('reply', False)
71
76
  internal = extra.get('internal', False)
72
- self.window.core.ctx.update_item(ctx)
77
+ core.ctx.update_item(ctx)
73
78
 
74
79
  # fix frozen chat
75
80
  if not status:
76
- data = {
81
+ dispatch(RenderEvent(RenderEvent.TOOL_CLEAR, {
77
82
  "meta": ctx.meta,
78
- }
79
- event = RenderEvent(RenderEvent.TOOL_CLEAR, data)
80
- self.window.dispatch(event) # hide cmd waiting
81
- if not self.window.controller.kernel.stopped():
82
- self.window.controller.chat.common.unlock_input() # unlock input
83
- # set state to: error
84
- self.window.dispatch(KernelEvent(KernelEvent.STATE_ERROR, {
83
+ })) # hide cmd waiting
84
+ if not controller.kernel.stopped():
85
+ controller.chat.common.unlock_input() # unlock input
86
+ dispatch(KernelEvent(KernelEvent.STATE_ERROR, {
85
87
  "id": "chat",
86
88
  }))
87
89
  return
@@ -89,7 +91,7 @@ class Response:
89
91
  try:
90
92
  if mode != MODE_ASSISTANT:
91
93
  ctx.from_previous() # append previous result if exists
92
- self.window.controller.chat.output.handle(
94
+ controller.chat.output.handle(
93
95
  ctx,
94
96
  mode,
95
97
  stream,
@@ -104,7 +106,7 @@ class Response:
104
106
  self.failed(context, extra)
105
107
 
106
108
  if stream:
107
- if mode not in self.window.controller.chat.output.not_stream_modes:
109
+ if mode not in controller.chat.output.NOT_STREAM_MODES:
108
110
  return # handled in stream:handleEnd()
109
111
 
110
112
  # post-handle, execute cmd, etc.
@@ -113,7 +115,7 @@ class Response:
113
115
  mode=mode,
114
116
  stream=stream,
115
117
  reply=reply,
116
- internal=internal
118
+ internal=internal,
117
119
  )
118
120
 
119
121
  def post_handle(
@@ -133,8 +135,9 @@ class Response:
133
135
  :param reply: True if reply mode
134
136
  :param internal: True if internal mode
135
137
  """
136
- self.window.controller.chat.output.post_handle(ctx, mode, stream, reply, internal)
137
- self.window.controller.chat.output.handle_end(ctx, mode) # handle end.
138
+ output = self.window.controller.chat.output
139
+ output.post_handle(ctx, mode, stream, reply, internal)
140
+ output.handle_end(ctx, mode) # handle end.
138
141
 
139
142
  def begin(
140
143
  self,
@@ -163,47 +166,46 @@ class Response:
163
166
  :param context: BridgeContext
164
167
  :param extra: Extra data
165
168
  """
166
- global_mode = self.window.core.config.get('mode', MODE_AGENT_LLAMA)
169
+ core = self.window.core
170
+ controller = self.window.controller
171
+ log = controller.chat.log
172
+ chat_output = controller.chat.output
173
+ dispatch = self.window.dispatch
174
+ global_mode = core.config.get("mode", MODE_AGENT_LLAMA)
167
175
  ctx = context.ctx
168
- if self.window.controller.kernel.stopped():
176
+
177
+ # if stopped
178
+ if controller.kernel.stopped():
169
179
  output = ctx.output
170
180
  if output and has_unclosed_code_tag(output):
171
181
  ctx.output += "\n```"
172
182
  ctx.msg_id = None
173
183
  if ctx.id is None:
174
- self.window.core.ctx.add(ctx) # store context to prevent current output from being lost
175
- self.window.controller.ctx.prepare_name(ctx) # summarize if not yet
176
-
177
- # finish render
178
- self.window.dispatch(AppEvent(AppEvent.CTX_END)) # app event
179
- self.window.dispatch(RenderEvent(RenderEvent.RELOAD)) # reload chat window
184
+ if not ctx.is_empty():
185
+ core.ctx.add(ctx) # store context to prevent current output from being lost
186
+ controller.ctx.prepare_name(ctx) # summarize if not yet
187
+ dispatch(AppEvent(AppEvent.CTX_END)) # finish render
188
+ dispatch(RenderEvent(RenderEvent.RELOAD)) # reload chat window
180
189
  return
181
190
 
182
- # at first, handle previous context (user input) if not handled yet
183
191
  prev_ctx = ctx.prev_ctx
184
- stream = False
185
192
  if prev_ctx and prev_ctx.current:
186
193
  prev_ctx.current = False # reset previous context
187
- self.window.core.ctx.update_item(prev_ctx)
194
+ core.ctx.update_item(prev_ctx)
188
195
  prev_ctx.from_previous() # append previous result if exists
189
- self.window.controller.chat.output.handle(
196
+ controller.chat.output.handle(
190
197
  ctx=prev_ctx,
191
198
  mode=prev_ctx.mode,
192
- stream_mode=False,
199
+ stream=False,
193
200
  )
194
- self.window.controller.chat.output.post_handle(ctx=prev_ctx,
195
- mode=prev_ctx.mode,
196
- stream=False,
197
- reply=False,
198
- internal=False)
199
-
200
- self.window.controller.chat.output.handle_end(ctx=prev_ctx,
201
- mode=prev_ctx.mode) # end previous context
201
+ controller.chat.output.post_handle(ctx=prev_ctx, mode=prev_ctx.mode, stream=False, reply=False, internal=False)
202
+ controller.chat.output.handle_end(ctx=prev_ctx, mode=prev_ctx.mode) # end previous context
202
203
 
204
+ stream = context.stream
203
205
 
204
206
  # if next in agent cycle
205
207
  if ctx.partial:
206
- self.window.dispatch(AppEvent(AppEvent.CTX_END)) # app event
208
+ dispatch(AppEvent(AppEvent.CTX_END)) # app event
207
209
 
208
210
  # handle current step
209
211
  ctx.current = False # reset current state
@@ -211,67 +213,65 @@ class Response:
211
213
  reply = ctx.reply
212
214
  internal = ctx.internal
213
215
 
214
- self.window.core.ctx.set_last_item(ctx)
215
- event = RenderEvent(RenderEvent.BEGIN, {
216
+ core.ctx.set_last_item(ctx)
217
+ dispatch(RenderEvent(RenderEvent.BEGIN, {
216
218
  "meta": ctx.meta,
217
219
  "ctx": ctx,
218
220
  "stream": stream,
219
- })
220
- self.window.dispatch(event)
221
+ }))
221
222
 
222
223
  # append step input to chat window
223
- event = RenderEvent(RenderEvent.INPUT_APPEND, {
224
+ dispatch(RenderEvent(RenderEvent.INPUT_APPEND, {
224
225
  "meta": ctx.meta,
225
226
  "ctx": ctx,
226
- })
227
- self.window.dispatch(event)
227
+ }))
228
228
 
229
229
  # CTX OUTPUT INFO:
230
230
  # - ctx.output may be empty here if stream in OpenAI agents
231
231
  # - ctx.live_output may be used against output in LlamaIndex agents
232
232
  if ctx.id is None:
233
- self.window.core.ctx.add(ctx)
234
- else:
235
- self.window.core.ctx.update_item(ctx)
233
+ core.ctx.add(ctx)
234
+
235
+ core.ctx.update_item(ctx)
236
236
 
237
237
  # update ctx meta
238
- if mode in (MODE_AGENT_LLAMA, MODE_AGENT_OPENAI) and ctx.meta is not None:
239
- self.window.core.ctx.replace(ctx.meta) # update meta in items
240
- self.window.core.ctx.save(ctx.meta.id)
238
+ if mode in self.AGENT_MODES_ALLOWED and ctx.meta:
239
+ core.ctx.replace(ctx.meta) # update meta in items
240
+ core.ctx.save(ctx.meta.id)
241
241
 
242
242
  # update preset if exists
243
- preset = self.window.controller.presets.get_current()
243
+ preset = controller.presets.get_current()
244
244
  if preset is not None:
245
245
  if ctx.meta.assistant is not None:
246
246
  preset.assistant_id = ctx.meta.assistant
247
- self.window.core.presets.update_and_save(preset)
247
+ core.presets.update_and_save(preset)
248
248
 
249
249
  try:
250
- self.window.controller.chat.output.handle(ctx, mode, stream)
250
+ chat_output.handle(ctx, mode, stream)
251
251
  except Exception as e:
252
- self.window.controller.chat.log(f"Output ERROR: {e}") # log
253
- self.window.controller.chat.handle_error(e)
252
+ log(f"Output ERROR: {e}") # log
253
+ controller.chat.handle_error(e)
254
254
  print(f"Error in append text: {e}")
255
255
 
256
256
  # post-handle, execute cmd, etc.
257
- self.window.controller.chat.output.post_handle(ctx, mode, stream, reply, internal)
258
- self.window.controller.chat.output.handle_end(ctx, mode) # handle end.
257
+ chat_output.post_handle(ctx, mode, stream, reply, internal)
258
+ chat_output.handle_end(ctx, mode) # handle end.
259
+ dispatch(RenderEvent(RenderEvent.RELOAD))
259
260
 
260
- event = RenderEvent(RenderEvent.RELOAD)
261
- self.window.dispatch(event)
261
+ # ----------- EVALUATE AGENT RESPONSE -----------
262
262
 
263
263
  # if continue reasoning
264
- if global_mode not in (MODE_AGENT_LLAMA, MODE_AGENT_OPENAI):
264
+ if global_mode not in self.AGENT_MODES_ALLOWED:
265
265
  return # no agent mode, nothing to do
266
266
 
267
267
  # not agent final response
268
268
  if ctx.extra is None or (isinstance(ctx.extra, dict) and "agent_finish" not in ctx.extra):
269
269
  self.window.update_status(trans("status.agent.reasoning"))
270
- self.window.controller.chat.common.lock_input() # lock input, re-enable stop button
270
+ controller.chat.common.lock_input() # lock input, re-enable stop button
271
271
 
272
272
  # agent final response
273
273
  if ctx.extra is not None and (isinstance(ctx.extra, dict) and "agent_finish" in ctx.extra):
274
- self.window.controller.agent.llama.on_finish(ctx) # evaluate response and continue if needed
274
+ controller.agent.llama.on_finish(ctx) # evaluate response and continue if needed
275
275
 
276
276
  def end(
277
277
  self,
@@ -284,14 +284,10 @@ class Response:
284
284
  :param context: BridgeContext
285
285
  :param extra: Extra data
286
286
  """
287
- msg = extra.get("msg", "")
288
- status = trans("status.finished")
289
- if msg:
290
- status = msg
287
+ status = extra.get("msg", trans("status.finished"))
291
288
  self.window.update_status(status)
292
289
  self.window.controller.agent.llama.on_end()
293
290
  self.window.controller.chat.common.unlock_input() # unlock input
294
- # set state to: idle
295
291
  self.window.dispatch(KernelEvent(KernelEvent.STATE_IDLE, {
296
292
  "id": "chat",
297
293
  }))
@@ -307,44 +303,32 @@ class Response:
307
303
  :param context: BridgeContext
308
304
  :param extra: Extra data
309
305
  """
310
- err = extra.get("error") if "error" in extra else None
311
- self.window.controller.chat.log(f"Output ERROR: {err}") # log
312
- self.window.controller.chat.handle_error(err)
306
+ msg = extra.get("error") if "error" in extra else None
307
+ self.window.controller.chat.log(f"Output ERROR: {msg}") # log
308
+ self.window.controller.chat.handle_error(msg)
313
309
  self.window.controller.chat.common.unlock_input() # unlock input
314
- print(f"Error in sending text: {err}")
315
- # set state to: error
310
+ print(f"Error in sending text: {msg}")
316
311
  self.window.dispatch(KernelEvent(KernelEvent.STATE_ERROR, {
317
312
  "id": "chat",
318
313
  }))
319
314
 
320
- def update_status(
315
+ def live_append(
321
316
  self,
322
317
  context: BridgeContext,
323
318
  extra: Dict[str, Any]
324
319
  ):
325
320
  """
326
- Handle Bridge evaluate
321
+ Handle Bridge live append
327
322
 
328
323
  :param context: BridgeContext
329
324
  :param extra: Extra data
330
325
  """
331
- msg = extra.get("msg", "")
332
- self.window.update_status(msg)
333
-
334
- def live_append(
335
- self,
336
- context: BridgeContext,
337
- extra: Dict[str, Any]
338
- ):
339
- ctx = context.ctx
340
- data = {
341
- "meta": ctx.meta,
342
- "ctx": ctx,
326
+ self.window.dispatch(RenderEvent(RenderEvent.LIVE_APPEND, {
327
+ "meta": context.ctx.meta,
328
+ "ctx": context.ctx,
343
329
  "chunk": extra.get("chunk", ""),
344
330
  "begin": extra.get("begin", False),
345
- }
346
- event = RenderEvent(RenderEvent.LIVE_APPEND, data)
347
- self.window.dispatch(event)
331
+ }))
348
332
 
349
333
  def live_clear(
350
334
  self,
@@ -357,10 +341,7 @@ class Response:
357
341
  :param context: BridgeContext
358
342
  :param extra: Extra data
359
343
  """
360
- ctx = context.ctx
361
- data = {
362
- "meta": ctx.meta,
363
- "ctx": ctx,
364
- }
365
- event = RenderEvent(RenderEvent.LIVE_CLEAR, data)
366
- self.window.dispatch(event)
344
+ self.window.dispatch(RenderEvent(RenderEvent.LIVE_CLEAR, {
345
+ "meta": context.ctx.meta,
346
+ "ctx": context.ctx,
347
+ }))