pygpt-net 2.6.19.post1__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.
- pygpt_net/CHANGELOG.txt +14 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/app.py +3 -1
- pygpt_net/controller/agent/agent.py +130 -2
- pygpt_net/controller/agent/experts.py +93 -96
- pygpt_net/controller/agent/llama.py +2 -1
- pygpt_net/controller/assistant/assistant.py +18 -1
- pygpt_net/controller/attachment/attachment.py +17 -1
- pygpt_net/controller/camera/camera.py +15 -7
- pygpt_net/controller/chat/chat.py +2 -2
- pygpt_net/controller/chat/common.py +50 -33
- pygpt_net/controller/chat/image.py +67 -77
- pygpt_net/controller/chat/input.py +94 -166
- pygpt_net/controller/chat/output.py +83 -140
- pygpt_net/controller/chat/response.py +83 -102
- pygpt_net/controller/chat/text.py +116 -149
- pygpt_net/controller/ctx/common.py +2 -1
- pygpt_net/controller/ctx/ctx.py +86 -6
- pygpt_net/controller/files/files.py +13 -1
- pygpt_net/controller/idx/idx.py +26 -2
- pygpt_net/controller/kernel/reply.py +53 -66
- pygpt_net/controller/kernel/stack.py +16 -16
- pygpt_net/controller/model/importer.py +2 -1
- pygpt_net/controller/model/model.py +62 -3
- pygpt_net/controller/settings/editor.py +4 -4
- pygpt_net/controller/ui/ui.py +16 -2
- pygpt_net/core/agents/observer/evaluation.py +3 -3
- pygpt_net/core/agents/provider.py +25 -3
- pygpt_net/core/agents/runner.py +4 -1
- pygpt_net/core/agents/runners/llama_workflow.py +19 -7
- pygpt_net/core/agents/runners/loop.py +3 -1
- pygpt_net/core/agents/runners/openai_workflow.py +17 -3
- pygpt_net/core/agents/tools.py +4 -1
- pygpt_net/core/bridge/context.py +34 -37
- pygpt_net/core/ctx/ctx.py +1 -1
- pygpt_net/core/db/database.py +2 -2
- pygpt_net/core/debug/debug.py +12 -1
- pygpt_net/core/dispatcher/dispatcher.py +24 -1
- pygpt_net/core/events/app.py +7 -7
- pygpt_net/core/events/control.py +26 -26
- pygpt_net/core/events/event.py +6 -3
- pygpt_net/core/events/kernel.py +2 -2
- pygpt_net/core/events/render.py +13 -13
- pygpt_net/core/experts/experts.py +76 -82
- pygpt_net/core/experts/worker.py +12 -12
- pygpt_net/core/models/models.py +5 -1
- pygpt_net/core/models/ollama.py +14 -5
- pygpt_net/core/render/web/helpers.py +2 -2
- pygpt_net/core/render/web/renderer.py +4 -4
- pygpt_net/core/types/__init__.py +2 -1
- pygpt_net/core/types/agent.py +4 -4
- pygpt_net/core/types/base.py +19 -0
- pygpt_net/core/types/console.py +6 -6
- pygpt_net/core/types/mode.py +8 -8
- pygpt_net/core/types/multimodal.py +3 -3
- pygpt_net/core/types/openai.py +2 -1
- pygpt_net/data/config/config.json +4 -4
- pygpt_net/data/config/models.json +19 -3
- pygpt_net/data/config/settings.json +14 -14
- pygpt_net/data/locale/locale.en.ini +2 -2
- pygpt_net/item/ctx.py +256 -240
- pygpt_net/item/model.py +59 -116
- pygpt_net/item/preset.py +122 -105
- pygpt_net/plugin/server/__init__.py +12 -0
- pygpt_net/plugin/server/config.py +301 -0
- pygpt_net/plugin/server/plugin.py +111 -0
- pygpt_net/plugin/server/worker.py +1057 -0
- pygpt_net/provider/agents/llama_index/workflow/planner.py +3 -3
- pygpt_net/provider/agents/openai/agent.py +4 -12
- pygpt_net/provider/agents/openai/agent_b2b.py +10 -15
- pygpt_net/provider/agents/openai/agent_planner.py +4 -4
- pygpt_net/provider/agents/openai/agent_with_experts.py +3 -7
- pygpt_net/provider/agents/openai/agent_with_experts_feedback.py +4 -8
- pygpt_net/provider/agents/openai/agent_with_feedback.py +4 -8
- pygpt_net/provider/agents/openai/bot_researcher.py +2 -18
- pygpt_net/provider/agents/openai/bots/__init__.py +0 -0
- pygpt_net/provider/agents/openai/bots/research_bot/__init__.py +0 -0
- pygpt_net/provider/agents/openai/bots/research_bot/agents/__init__.py +0 -0
- pygpt_net/provider/agents/openai/bots/research_bot/agents/planner_agent.py +1 -1
- pygpt_net/provider/agents/openai/bots/research_bot/agents/search_agent.py +1 -0
- pygpt_net/provider/agents/openai/bots/research_bot/agents/writer_agent.py +1 -1
- pygpt_net/provider/agents/openai/bots/research_bot/manager.py +1 -10
- pygpt_net/provider/agents/openai/evolve.py +5 -9
- pygpt_net/provider/agents/openai/supervisor.py +4 -8
- pygpt_net/provider/core/config/patch.py +10 -3
- pygpt_net/provider/core/ctx/db_sqlite/utils.py +43 -43
- pygpt_net/provider/core/model/patch.py +11 -1
- pygpt_net/provider/core/preset/json_file.py +47 -49
- pygpt_net/provider/gpt/agents/experts.py +2 -2
- pygpt_net/ui/base/config_dialog.py +17 -3
- pygpt_net/ui/widget/option/checkbox.py +16 -2
- {pygpt_net-2.6.19.post1.dist-info → pygpt_net-2.6.21.dist-info}/METADATA +30 -6
- {pygpt_net-2.6.19.post1.dist-info → pygpt_net-2.6.21.dist-info}/RECORD +93 -88
- {pygpt_net-2.6.19.post1.dist-info → pygpt_net-2.6.21.dist-info}/LICENSE +0 -0
- {pygpt_net-2.6.19.post1.dist-info → pygpt_net-2.6.21.dist-info}/WHEEL +0 -0
- {pygpt_net-2.6.19.post1.dist-info → pygpt_net-2.6.21.dist-info}/entry_points.txt +0 -0
|
@@ -6,23 +6,31 @@
|
|
|
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.
|
|
9
|
+
# Updated Date: 2025.08.23 15:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from typing import Any, Optional
|
|
13
13
|
|
|
14
14
|
from pygpt_net.core.bridge import BridgeContext
|
|
15
15
|
from pygpt_net.core.types import (
|
|
16
|
-
MODE_AGENT,
|
|
17
16
|
MODE_ASSISTANT,
|
|
18
17
|
MODE_IMAGE,
|
|
19
18
|
)
|
|
20
19
|
from pygpt_net.core.events import Event, AppEvent, RenderEvent, KernelEvent
|
|
21
20
|
from pygpt_net.item.ctx import CtxItem
|
|
22
|
-
from pygpt_net.utils import mem_clean
|
|
23
21
|
|
|
24
22
|
|
|
25
23
|
class Output:
|
|
24
|
+
|
|
25
|
+
STATE_PARAMS = {
|
|
26
|
+
"id": "chat",
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
NOT_STREAM_MODES = (
|
|
30
|
+
MODE_ASSISTANT,
|
|
31
|
+
MODE_IMAGE
|
|
32
|
+
)
|
|
33
|
+
|
|
26
34
|
def __init__(self, window=None):
|
|
27
35
|
"""
|
|
28
36
|
Output controller
|
|
@@ -30,16 +38,12 @@ class Output:
|
|
|
30
38
|
:param window: Window instance
|
|
31
39
|
"""
|
|
32
40
|
self.window = window
|
|
33
|
-
self.not_stream_modes = [
|
|
34
|
-
MODE_ASSISTANT,
|
|
35
|
-
MODE_IMAGE,
|
|
36
|
-
]
|
|
37
41
|
|
|
38
42
|
def handle(
|
|
39
43
|
self,
|
|
40
44
|
ctx: CtxItem,
|
|
41
45
|
mode: str,
|
|
42
|
-
|
|
46
|
+
stream: bool = False,
|
|
43
47
|
is_response: bool = False,
|
|
44
48
|
reply: bool = False,
|
|
45
49
|
internal: bool = False,
|
|
@@ -51,20 +55,20 @@ class Output:
|
|
|
51
55
|
|
|
52
56
|
:param ctx: CtxItem
|
|
53
57
|
:param mode: mode (global)
|
|
54
|
-
:param
|
|
58
|
+
:param stream: stream enabled (local)
|
|
55
59
|
:param is_response: Is response output
|
|
56
60
|
:param reply: is reply
|
|
57
61
|
:param internal: is internal command
|
|
58
62
|
:param context: BridgeContext (optional)
|
|
59
63
|
:param extra: Extra data (optional)
|
|
60
64
|
"""
|
|
61
|
-
self.window.
|
|
65
|
+
self.window.dispatch(KernelEvent(KernelEvent.STATE_BUSY)) # state: busy
|
|
62
66
|
|
|
63
|
-
# if stream
|
|
67
|
+
# if stream then append chunk by chunk
|
|
64
68
|
end = True
|
|
65
|
-
if
|
|
66
|
-
if mode not in self.
|
|
67
|
-
end = False # don't end stream mode, append chunk by chunk
|
|
69
|
+
if stream: # local, not global config
|
|
70
|
+
if mode not in self.NOT_STREAM_MODES:
|
|
71
|
+
end = False # don't end if stream mode, append chunk by chunk
|
|
68
72
|
self.window.controller.chat.stream.append(
|
|
69
73
|
ctx=ctx,
|
|
70
74
|
mode=mode,
|
|
@@ -79,7 +83,7 @@ class Output:
|
|
|
79
83
|
self.handle_after(
|
|
80
84
|
ctx=ctx,
|
|
81
85
|
mode=mode,
|
|
82
|
-
stream=
|
|
86
|
+
stream=stream,
|
|
83
87
|
)
|
|
84
88
|
|
|
85
89
|
def handle_after(
|
|
@@ -93,59 +97,52 @@ class Output:
|
|
|
93
97
|
|
|
94
98
|
:param ctx: CtxItem
|
|
95
99
|
:param mode: mode (global)
|
|
96
|
-
:param stream: stream
|
|
100
|
+
:param stream: stream enabled (local)
|
|
97
101
|
"""
|
|
102
|
+
core = self.window.core
|
|
103
|
+
dispatch = self.window.dispatch
|
|
104
|
+
log = self.window.controller.chat.log
|
|
105
|
+
|
|
98
106
|
# check if tool calls detected
|
|
99
107
|
if ctx.tool_calls:
|
|
100
108
|
# if not internal commands in a text body then append tool calls as commands (prevent double commands)
|
|
101
|
-
if not
|
|
102
|
-
|
|
109
|
+
if not core.command.has_cmds(ctx.output):
|
|
110
|
+
core.command.append_tool_calls(ctx) # append tool calls as commands
|
|
103
111
|
if not isinstance(ctx.extra, dict):
|
|
104
112
|
ctx.extra = {}
|
|
105
113
|
ctx.extra["tool_calls"] = ctx.tool_calls
|
|
106
114
|
stream = False # disable stream mode, show tool calls at the end
|
|
107
|
-
|
|
115
|
+
log("Tool call received...")
|
|
108
116
|
else: # prevent execute twice
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
# agent mode
|
|
112
|
-
if mode == MODE_AGENT:
|
|
113
|
-
self.window.controller.agent.legacy.on_ctx_after(ctx)
|
|
117
|
+
log("Ignoring tool call because command received...")
|
|
114
118
|
|
|
115
119
|
# event: context after
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
120
|
+
dispatch(Event(Event.CTX_AFTER, {
|
|
121
|
+
'mode': mode,
|
|
122
|
+
}, ctx=ctx))
|
|
119
123
|
|
|
120
|
-
|
|
124
|
+
log("Appending output to chat window...")
|
|
121
125
|
|
|
122
126
|
# only append output if not in stream mode, TODO: plugin output add
|
|
123
|
-
|
|
127
|
+
stream_global = core.config.get('stream', False)
|
|
124
128
|
if not stream:
|
|
125
|
-
if
|
|
126
|
-
|
|
129
|
+
if stream_global: # use global stream settings here to persist previously added input
|
|
130
|
+
dispatch(RenderEvent(RenderEvent.INPUT_APPEND, {
|
|
127
131
|
"meta": ctx.meta,
|
|
128
132
|
"ctx": ctx,
|
|
129
133
|
"flush": True,
|
|
130
134
|
"append": True,
|
|
131
|
-
}
|
|
132
|
-
event = RenderEvent(RenderEvent.INPUT_APPEND, data)
|
|
133
|
-
self.window.dispatch(event)
|
|
135
|
+
}))
|
|
134
136
|
|
|
135
|
-
|
|
137
|
+
dispatch(RenderEvent(RenderEvent.OUTPUT_APPEND, {
|
|
136
138
|
"meta": ctx.meta,
|
|
137
139
|
"ctx": ctx,
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
self.window.dispatch(event)
|
|
141
|
-
|
|
142
|
-
data = {
|
|
140
|
+
}))
|
|
141
|
+
dispatch(RenderEvent(RenderEvent.EXTRA_APPEND, {
|
|
143
142
|
"meta": ctx.meta,
|
|
144
143
|
"ctx": ctx,
|
|
145
144
|
"footer": True,
|
|
146
|
-
}
|
|
147
|
-
event = RenderEvent(RenderEvent.EXTRA_APPEND, data)
|
|
148
|
-
self.window.dispatch(event) # + icons
|
|
145
|
+
})) # + icons
|
|
149
146
|
|
|
150
147
|
self.handle_complete(ctx)
|
|
151
148
|
|
|
@@ -155,29 +152,22 @@ class Output:
|
|
|
155
152
|
|
|
156
153
|
:param ctx: CtxItem
|
|
157
154
|
"""
|
|
158
|
-
|
|
159
|
-
self.window.
|
|
160
|
-
self.window.
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
# update response tokens
|
|
164
|
-
self.window.controller.chat.common.show_response_tokens(ctx)
|
|
155
|
+
core = self.window.core
|
|
156
|
+
controller = self.window.controller
|
|
157
|
+
dispatch = self.window.dispatch
|
|
158
|
+
mode = core.config.get('mode')
|
|
165
159
|
|
|
166
|
-
#
|
|
167
|
-
|
|
160
|
+
# post update context, store last mode, etc.
|
|
161
|
+
core.ctx.post_update(mode)
|
|
162
|
+
core.ctx.store()
|
|
168
163
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
self.window.core.history.append(ctx, "output")
|
|
164
|
+
controller.ctx.update_ctx()
|
|
165
|
+
controller.ctx.store_history(ctx, "output") # store to history
|
|
172
166
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
# reset state to: idle
|
|
178
|
-
self.window.dispatch(KernelEvent(KernelEvent.STATE_IDLE, {
|
|
179
|
-
"id": "chat",
|
|
180
|
-
}))
|
|
167
|
+
controller.chat.audio.handle_output(ctx) # handle audio output
|
|
168
|
+
controller.chat.common.auto_unlock(ctx) # unlock input if allowed
|
|
169
|
+
controller.chat.common.show_response_tokens(ctx) # update tokens
|
|
170
|
+
dispatch(KernelEvent(KernelEvent.STATE_IDLE, self.STATE_PARAMS)) # state: idle
|
|
181
171
|
|
|
182
172
|
def post_handle(
|
|
183
173
|
self,
|
|
@@ -196,46 +186,33 @@ class Output:
|
|
|
196
186
|
:param reply: is reply
|
|
197
187
|
:param internal: is internal
|
|
198
188
|
"""
|
|
189
|
+
core = self.window.core
|
|
190
|
+
controller = self.window.controller
|
|
191
|
+
dispatch = self.window.dispatch
|
|
192
|
+
|
|
199
193
|
# if commands enabled: post-execute commands (not assistant mode)
|
|
200
194
|
if mode != MODE_ASSISTANT:
|
|
201
195
|
ctx.clear_reply() # reset results
|
|
202
|
-
|
|
203
|
-
#
|
|
204
|
-
|
|
205
|
-
if num_calls == 0:
|
|
206
|
-
# handle commands only if no expert calls in queue
|
|
207
|
-
self.window.controller.chat.command.handle(ctx)
|
|
196
|
+
expert_calls = controller.agent.experts.handle(ctx)
|
|
197
|
+
if expert_calls == 0: # handle commands only if no expert calls in queue
|
|
198
|
+
controller.chat.command.handle(ctx)
|
|
208
199
|
|
|
209
200
|
ctx.from_previous() # append previous result again before save
|
|
210
|
-
|
|
201
|
+
core.ctx.update_item(ctx) # update ctx in DB
|
|
211
202
|
|
|
212
203
|
# render: end
|
|
213
204
|
if ctx.sub_calls == 0: # if no experts called
|
|
214
|
-
|
|
205
|
+
dispatch(RenderEvent(RenderEvent.END, {
|
|
215
206
|
"meta": ctx.meta,
|
|
216
207
|
"ctx": ctx,
|
|
217
208
|
"stream": stream,
|
|
218
|
-
}
|
|
219
|
-
event = RenderEvent(RenderEvent.END, data)
|
|
220
|
-
self.window.dispatch(event)
|
|
221
|
-
|
|
222
|
-
# don't unlock input and leave stop btn if assistant mode or if agent/autonomous is enabled
|
|
223
|
-
# send btn will be unlocked in agent mode on stop
|
|
224
|
-
if self.window.controller.chat.common.can_unlock(ctx):
|
|
225
|
-
if not self.window.controller.kernel.stopped():
|
|
226
|
-
self.window.controller.chat.common.unlock_input() # unlock input
|
|
227
|
-
|
|
228
|
-
# handle ctx name (generate title from summary if not initialized)
|
|
229
|
-
if not ctx.meta or not ctx.meta.initialized: # don't call if reply or internal mode
|
|
230
|
-
if self.window.core.config.get('ctx.auto_summary'):
|
|
231
|
-
self.log("Calling for prepare context name...")
|
|
232
|
-
self.window.controller.ctx.prepare_name(ctx) # async
|
|
209
|
+
}))
|
|
233
210
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
211
|
+
controller.chat.common.auto_unlock(ctx) # unlock input if allowed
|
|
212
|
+
controller.ctx.prepare_summary(ctx) # prepare ctx name
|
|
213
|
+
|
|
214
|
+
if self.window.state != self.window.STATE_ERROR and mode != MODE_ASSISTANT:
|
|
215
|
+
dispatch(KernelEvent(KernelEvent.STATE_IDLE, self.STATE_PARAMS)) # state: idle
|
|
239
216
|
|
|
240
217
|
def handle_end(
|
|
241
218
|
self,
|
|
@@ -248,60 +225,26 @@ class Output:
|
|
|
248
225
|
:param ctx: CtxItem
|
|
249
226
|
:param mode: mode
|
|
250
227
|
"""
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
if auto_clear and not self.window.controller.attachment.is_locked():
|
|
255
|
-
self.window.controller.attachment.clear(force=True, auto=True)
|
|
256
|
-
self.window.controller.attachment.update()
|
|
257
|
-
self.log("Attachments cleared.") # log
|
|
258
|
-
|
|
259
|
-
if self.window.core.config.get("log.ctx"):
|
|
260
|
-
self.log(f"Context: END: {ctx}")
|
|
261
|
-
else:
|
|
262
|
-
self.log("Context: END.")
|
|
263
|
-
|
|
264
|
-
# agent mode
|
|
265
|
-
if mode == MODE_AGENT:
|
|
266
|
-
agent_iterations = int(self.window.core.config.get("agent.iterations"))
|
|
267
|
-
self.log(f"Agent: ctx end, iterations: {agent_iterations}")
|
|
268
|
-
self.window.controller.agent.legacy.on_ctx_end(
|
|
269
|
-
ctx,
|
|
270
|
-
iterations=agent_iterations,
|
|
271
|
-
)
|
|
228
|
+
controller = self.window.controller
|
|
229
|
+
dispatch = self.window.dispatch
|
|
230
|
+
log = controller.chat.log
|
|
272
231
|
|
|
273
|
-
#
|
|
274
|
-
|
|
275
|
-
event.ctx = ctx
|
|
276
|
-
self.window.dispatch(event)
|
|
277
|
-
self.window.controller.ui.update_tokens() # update UI
|
|
278
|
-
self.window.controller.chat.input.generating = False # unlock
|
|
232
|
+
controller.attachment.cleanup(ctx) # clear after send
|
|
233
|
+
log(f"Context: END: {ctx}" if self.window.core.config.get("log.ctx") else "Context: END.")
|
|
279
234
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
235
|
+
# event: context end
|
|
236
|
+
dispatch(Event(Event.CTX_END, {
|
|
237
|
+
'mode': mode,
|
|
238
|
+
}, ctx=ctx))
|
|
239
|
+
controller.chat.input.generating = False # unlock
|
|
284
240
|
|
|
285
|
-
|
|
286
|
-
|
|
241
|
+
log("End.")
|
|
242
|
+
dispatch(AppEvent(AppEvent.CTX_END)) # app event
|
|
287
243
|
|
|
288
244
|
# restore state to idle if no errors
|
|
289
245
|
if self.window.state != self.window.STATE_ERROR:
|
|
290
|
-
|
|
246
|
+
dispatch(KernelEvent(KernelEvent.STATE_IDLE, self.STATE_PARAMS))
|
|
291
247
|
|
|
292
248
|
if mode != MODE_ASSISTANT:
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
self.window.dispatch(event) # reload chat window
|
|
296
|
-
|
|
297
|
-
mem_clean()
|
|
298
|
-
|
|
299
|
-
# self.window.core.debug.mem("END") # debug memory usage
|
|
300
|
-
|
|
301
|
-
def log(self, data: Any):
|
|
302
|
-
"""
|
|
303
|
-
Log data to debug
|
|
304
|
-
|
|
305
|
-
:param data: Data to log
|
|
306
|
-
"""
|
|
307
|
-
self.window.controller.chat.log(data)
|
|
249
|
+
controller.kernel.stack.handle() # handle reply
|
|
250
|
+
dispatch(RenderEvent(RenderEvent.RELOAD)) # reload chat window
|