pygpt-net 2.6.11__py3-none-any.whl → 2.6.12__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 +4 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/app.py +7 -1
- pygpt_net/controller/chat/response.py +3 -3
- pygpt_net/controller/chat/stream.py +10 -4
- pygpt_net/core/ctx/bag.py +2 -1
- pygpt_net/core/debug/debug.py +12 -3
- pygpt_net/core/render/web/body.py +52 -10
- pygpt_net/core/render/web/pid.py +19 -4
- pygpt_net/core/render/web/renderer.py +155 -46
- pygpt_net/data/config/config.json +3 -3
- pygpt_net/data/config/models.json +3 -3
- pygpt_net/item/ctx.py +3 -3
- pygpt_net/launcher.py +2 -9
- pygpt_net/provider/gpt/__init__.py +13 -4
- pygpt_net/tools/code_interpreter/body.py +2 -3
- pygpt_net/ui/main.py +5 -2
- pygpt_net/ui/widget/textarea/html.py +2 -7
- pygpt_net/ui/widget/textarea/web.py +36 -26
- pygpt_net/utils.py +15 -8
- {pygpt_net-2.6.11.dist-info → pygpt_net-2.6.12.dist-info}/METADATA +6 -2
- {pygpt_net-2.6.11.dist-info → pygpt_net-2.6.12.dist-info}/RECORD +25 -25
- {pygpt_net-2.6.11.dist-info → pygpt_net-2.6.12.dist-info}/LICENSE +0 -0
- {pygpt_net-2.6.11.dist-info → pygpt_net-2.6.12.dist-info}/WHEEL +0 -0
- {pygpt_net-2.6.11.dist-info → pygpt_net-2.6.12.dist-info}/entry_points.txt +0 -0
pygpt_net/CHANGELOG.txt
CHANGED
pygpt_net/__init__.py
CHANGED
|
@@ -6,15 +6,15 @@
|
|
|
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.19 00:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
__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.6.
|
|
17
|
-
__build__ = "2025-08-
|
|
16
|
+
__version__ = "2.6.12"
|
|
17
|
+
__build__ = "2025-08-19"
|
|
18
18
|
__maintainer__ = "Marcin Szczygliński"
|
|
19
19
|
__github__ = "https://github.com/szczyglis-dev/py-gpt"
|
|
20
20
|
__report__ = "https://github.com/szczyglis-dev/py-gpt/issues"
|
pygpt_net/app.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.08.
|
|
9
|
+
# Updated Date: 2025.08.19 07:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import os
|
|
@@ -25,6 +25,12 @@ if platform.system() == 'Windows':
|
|
|
25
25
|
# enable debug logging
|
|
26
26
|
# os.environ["QT_LOGGING_RULES"] = "*.debug=true"
|
|
27
27
|
# os.environ["QTWEBENGINE_REMOTE_DEBUGGING"] = "9222"
|
|
28
|
+
os.environ["QTWEBENGINE_CHROMIUM_FLAGS"] = (
|
|
29
|
+
"--renderer-process-limit=1 "
|
|
30
|
+
"--process-per-site "
|
|
31
|
+
"--enable-precise-memory-info "
|
|
32
|
+
"--js-flags=--expose-gc"
|
|
33
|
+
)
|
|
28
34
|
|
|
29
35
|
_original_open = builtins.open
|
|
30
36
|
|
|
@@ -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.
|
|
9
|
+
# Updated Date: 2025.08.19 07:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from typing import Dict, Any
|
|
@@ -238,7 +238,7 @@ class Response:
|
|
|
238
238
|
self.window.core.ctx.update_item(ctx)
|
|
239
239
|
|
|
240
240
|
# update ctx meta
|
|
241
|
-
if mode in
|
|
241
|
+
if mode in (MODE_AGENT_LLAMA, MODE_AGENT_OPENAI) and ctx.meta is not None:
|
|
242
242
|
self.window.core.ctx.replace(ctx.meta)
|
|
243
243
|
self.window.core.ctx.save(ctx.meta.id)
|
|
244
244
|
# update preset if exists
|
|
@@ -269,7 +269,7 @@ class Response:
|
|
|
269
269
|
self.window.dispatch(event)
|
|
270
270
|
|
|
271
271
|
# if continue reasoning
|
|
272
|
-
if global_mode not in
|
|
272
|
+
if global_mode not in (MODE_AGENT_LLAMA, MODE_AGENT_OPENAI):
|
|
273
273
|
return # no agent mode, nothing to do
|
|
274
274
|
|
|
275
275
|
if ctx.extra is None or (type(ctx.extra) == dict and "agent_finish" not in ctx.extra):
|
|
@@ -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.
|
|
9
|
+
# Updated Date: 2025.08.19 07:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import base64
|
|
@@ -65,6 +65,7 @@ class StreamWorker(QRunnable):
|
|
|
65
65
|
self.signals = WorkerSignals()
|
|
66
66
|
self.ctx = ctx
|
|
67
67
|
self.window = window
|
|
68
|
+
self.stream = None
|
|
68
69
|
|
|
69
70
|
@Slot()
|
|
70
71
|
def run(self):
|
|
@@ -90,8 +91,7 @@ class StreamWorker(QRunnable):
|
|
|
90
91
|
force_func_call = False
|
|
91
92
|
stopped = False
|
|
92
93
|
chunk_type: ChunkType = "raw"
|
|
93
|
-
generator =
|
|
94
|
-
ctx.stream = None
|
|
94
|
+
generator = self.stream
|
|
95
95
|
|
|
96
96
|
base_data = {
|
|
97
97
|
"meta": ctx.meta,
|
|
@@ -363,6 +363,7 @@ class StreamWorker(QRunnable):
|
|
|
363
363
|
finally:
|
|
364
364
|
output = "".join(output_parts)
|
|
365
365
|
output_parts.clear()
|
|
366
|
+
del output_parts
|
|
366
367
|
|
|
367
368
|
if has_unclosed_code_tag(output):
|
|
368
369
|
output += "\n```"
|
|
@@ -374,11 +375,14 @@ class StreamWorker(QRunnable):
|
|
|
374
375
|
pass
|
|
375
376
|
|
|
376
377
|
del generator
|
|
378
|
+
self.stream = None
|
|
377
379
|
|
|
378
380
|
ctx.output = output
|
|
379
381
|
ctx.set_tokens(ctx.input_tokens, output_tokens)
|
|
380
382
|
core.ctx.update_item(ctx)
|
|
381
383
|
|
|
384
|
+
output = None
|
|
385
|
+
|
|
382
386
|
if files and not stopped:
|
|
383
387
|
core.debug.info("[chat] Container files found, downloading...")
|
|
384
388
|
try:
|
|
@@ -464,11 +468,13 @@ class Stream:
|
|
|
464
468
|
self.extra = extra if extra is not None else {}
|
|
465
469
|
|
|
466
470
|
worker = StreamWorker(ctx, self.window)
|
|
467
|
-
self.worker = worker
|
|
468
471
|
|
|
472
|
+
worker.stream = ctx.stream
|
|
469
473
|
worker.signals.eventReady.connect(self.handleEvent)
|
|
470
474
|
worker.signals.errorOccurred.connect(self.handleError)
|
|
471
475
|
worker.signals.end.connect(self.handleEnd)
|
|
476
|
+
ctx.stream = None
|
|
477
|
+
self.worker = worker
|
|
472
478
|
|
|
473
479
|
self.window.core.debug.info("[chat] Stream begin...")
|
|
474
480
|
self.window.threadpool.start(worker)
|
pygpt_net/core/ctx/bag.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.08.
|
|
9
|
+
# Updated Date: 2025.08.19 07:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from typing import List
|
|
@@ -44,6 +44,7 @@ class Bag:
|
|
|
44
44
|
def clear_items(self):
|
|
45
45
|
"""Clear items"""
|
|
46
46
|
self.items.clear()
|
|
47
|
+
self.items = []
|
|
47
48
|
|
|
48
49
|
def count_items(self) -> int:
|
|
49
50
|
"""
|
pygpt_net/core/debug/debug.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.08.
|
|
9
|
+
# Updated Date: 2025.08.19 07:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import gc
|
|
@@ -338,8 +338,17 @@ class Debug:
|
|
|
338
338
|
:param label: label for memory usage
|
|
339
339
|
:return: formatted memory usage string
|
|
340
340
|
"""
|
|
341
|
-
|
|
342
|
-
|
|
341
|
+
rss_mb = self._process.memory_info().rss / (1024 * 1024)
|
|
342
|
+
uss_mb = getattr(self._process.memory_full_info(), "uss", 0) / 1024 / 1024
|
|
343
|
+
data = f"RSS={rss_mb:.0f} MB USS={uss_mb:.0f} MB"
|
|
344
|
+
|
|
345
|
+
children_parts = []
|
|
346
|
+
for c in self._process.children(recursive=True):
|
|
347
|
+
children_parts.append(
|
|
348
|
+
f"{c.pid} {c.name()} {round(c.memory_info().rss / 1024 / 1024)} MB"
|
|
349
|
+
)
|
|
350
|
+
if children_parts:
|
|
351
|
+
data += "\n" + "\n".join(children_parts)
|
|
343
352
|
print(f"[{label}] {data}")
|
|
344
353
|
return data
|
|
345
354
|
|
|
@@ -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.
|
|
9
|
+
# Updated Date: 2025.08.19 07:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import os
|
|
@@ -42,9 +42,7 @@ class Body:
|
|
|
42
42
|
<script type="text/javascript" src="qrc:///js/highlight.min.js"></script>
|
|
43
43
|
<script type="text/javascript" src="qrc:///js/katex.min.js"></script>
|
|
44
44
|
<script>
|
|
45
|
-
|
|
46
45
|
const DEBUG_MODE = false;
|
|
47
|
-
|
|
48
46
|
let scrollTimeout = null;
|
|
49
47
|
let prevScroll = 0;
|
|
50
48
|
let bridge;
|
|
@@ -69,6 +67,23 @@ class Body:
|
|
|
69
67
|
let pendingHighlightMath = false;
|
|
70
68
|
let scrollScheduled = false;
|
|
71
69
|
|
|
70
|
+
// timers
|
|
71
|
+
let tipsTimers = [];
|
|
72
|
+
|
|
73
|
+
// clear previous references
|
|
74
|
+
function resetEphemeralDomRefs() {
|
|
75
|
+
domLastCodeBlock = null;
|
|
76
|
+
domLastParagraphBlock = null;
|
|
77
|
+
}
|
|
78
|
+
function dropIfDetached() {
|
|
79
|
+
if (domLastCodeBlock && !domLastCodeBlock.isConnected) domLastCodeBlock = null;
|
|
80
|
+
if (domLastParagraphBlock && !domLastParagraphBlock.isConnected) domLastParagraphBlock = null;
|
|
81
|
+
}
|
|
82
|
+
function stopTipsTimers() {
|
|
83
|
+
tipsTimers.forEach(clearTimeout);
|
|
84
|
+
tipsTimers = [];
|
|
85
|
+
}
|
|
86
|
+
|
|
72
87
|
history.scrollRestoration = "manual";
|
|
73
88
|
document.addEventListener('keydown', function(event) {
|
|
74
89
|
if (event.ctrlKey && event.key === 'f') {
|
|
@@ -137,6 +152,7 @@ class Body:
|
|
|
137
152
|
}
|
|
138
153
|
function hideTips() {
|
|
139
154
|
if (tips_hidden) return;
|
|
155
|
+
stopTipsTimers();
|
|
140
156
|
const t = els.tips || document.getElementById('tips');
|
|
141
157
|
if (t) t.style.display = 'none';
|
|
142
158
|
tips_hidden = true;
|
|
@@ -151,21 +167,23 @@ class Body:
|
|
|
151
167
|
function cycleTips() {
|
|
152
168
|
if (tips_hidden) return;
|
|
153
169
|
if (tips.length === 0) return;
|
|
154
|
-
let tipContainer = els.tips || document.getElementById('tips');
|
|
155
170
|
let currentTip = 0;
|
|
156
171
|
function showNextTip() {
|
|
157
172
|
if (tips_hidden) return;
|
|
173
|
+
const tipContainer = els.tips || document.getElementById('tips');
|
|
174
|
+
if (!tipContainer) return;
|
|
158
175
|
tipContainer.innerHTML = tips[currentTip];
|
|
159
176
|
tipContainer.classList.add('visible');
|
|
160
|
-
setTimeout(function() {
|
|
177
|
+
tipsTimers.push(setTimeout(function() {
|
|
161
178
|
if (tips_hidden) return;
|
|
162
179
|
tipContainer.classList.remove('visible');
|
|
163
|
-
setTimeout(function(){
|
|
180
|
+
tipsTimers.push(setTimeout(function(){
|
|
164
181
|
currentTip = (currentTip + 1) % tips.length;
|
|
165
182
|
showNextTip();
|
|
166
|
-
}, 1000);
|
|
167
|
-
}, 15000);
|
|
183
|
+
}, 1000));
|
|
184
|
+
}, 15000));
|
|
168
185
|
}
|
|
186
|
+
stopTipsTimers();
|
|
169
187
|
showNextTip();
|
|
170
188
|
}
|
|
171
189
|
function renderMath(root) {
|
|
@@ -224,7 +242,7 @@ class Body:
|
|
|
224
242
|
}
|
|
225
243
|
}
|
|
226
244
|
function getStreamContainer() {
|
|
227
|
-
if (domOutputStream &&
|
|
245
|
+
if (domOutputStream && domOutputStream.isConnected) {
|
|
228
246
|
return domOutputStream;
|
|
229
247
|
}
|
|
230
248
|
let element = els.appendOutput || document.getElementById('_append_output_');
|
|
@@ -247,6 +265,24 @@ class Body:
|
|
|
247
265
|
scheduleScroll();
|
|
248
266
|
}
|
|
249
267
|
}
|
|
268
|
+
function clean() {
|
|
269
|
+
if (DEBUG_MODE) {
|
|
270
|
+
log("-- CLEAN DOM --");
|
|
271
|
+
}
|
|
272
|
+
const el = els.nodes || document.getElementById('_nodes_');
|
|
273
|
+
if (el) {
|
|
274
|
+
el.replaceChildren();
|
|
275
|
+
}
|
|
276
|
+
resetEphemeralDomRefs();
|
|
277
|
+
els = {};
|
|
278
|
+
try {
|
|
279
|
+
if (window.gc) {
|
|
280
|
+
window.gc();
|
|
281
|
+
}
|
|
282
|
+
} catch (e) {
|
|
283
|
+
// gc not available
|
|
284
|
+
}
|
|
285
|
+
}
|
|
250
286
|
function appendExtra(id, content) {
|
|
251
287
|
hideTips();
|
|
252
288
|
prevScroll = 0;
|
|
@@ -270,6 +306,7 @@ class Body:
|
|
|
270
306
|
if (element) {
|
|
271
307
|
element.remove();
|
|
272
308
|
}
|
|
309
|
+
resetEphemeralDomRefs();
|
|
273
310
|
highlightCode();
|
|
274
311
|
scheduleScroll();
|
|
275
312
|
}
|
|
@@ -280,13 +317,14 @@ class Body:
|
|
|
280
317
|
const elements = container.querySelectorAll('.msg-box');
|
|
281
318
|
let remove = false;
|
|
282
319
|
elements.forEach(function(element) {
|
|
283
|
-
if (element.id.endsWith('-' + id)) {
|
|
320
|
+
if (element.id && element.id.endsWith('-' + id)) {
|
|
284
321
|
remove = true;
|
|
285
322
|
}
|
|
286
323
|
if (remove) {
|
|
287
324
|
element.remove();
|
|
288
325
|
}
|
|
289
326
|
});
|
|
327
|
+
resetEphemeralDomRefs();
|
|
290
328
|
highlightCode(true, container);
|
|
291
329
|
scheduleScroll();
|
|
292
330
|
}
|
|
@@ -347,6 +385,7 @@ class Body:
|
|
|
347
385
|
}
|
|
348
386
|
}
|
|
349
387
|
function appendStream(name_header, content, chunk, replace = false, is_code_block = false) {
|
|
388
|
+
dropIfDetached(); // clear references to detached elements
|
|
350
389
|
hideTips();
|
|
351
390
|
if (DEBUG_MODE) {
|
|
352
391
|
log("APPEND CHUNK: {" + chunk + "}, CONTENT: {"+content+"}, replace: " + replace + ", is_code_block: " + is_code_block);
|
|
@@ -561,6 +600,7 @@ class Body:
|
|
|
561
600
|
element.replaceChildren();
|
|
562
601
|
element.classList.add('empty_list');
|
|
563
602
|
}
|
|
603
|
+
resetEphemeralDomRefs();
|
|
564
604
|
}
|
|
565
605
|
function clearInput() {
|
|
566
606
|
const element = els.appendInput || document.getElementById('_append_input_');
|
|
@@ -585,9 +625,11 @@ class Body:
|
|
|
585
625
|
element.classList.add('hidden');
|
|
586
626
|
setTimeout(function() {
|
|
587
627
|
element.replaceChildren();
|
|
628
|
+
resetEphemeralDomRefs();
|
|
588
629
|
}, 1000);
|
|
589
630
|
} else {
|
|
590
631
|
element.replaceChildren();
|
|
632
|
+
resetEphemeralDomRefs();
|
|
591
633
|
}
|
|
592
634
|
}
|
|
593
635
|
}
|
pygpt_net/core/render/web/pid.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.08.
|
|
9
|
+
# Updated Date: 2025.08.19 07:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import io
|
|
@@ -43,6 +43,9 @@ class PidData:
|
|
|
43
43
|
|
|
44
44
|
@buffer.setter
|
|
45
45
|
def buffer(self, value: str):
|
|
46
|
+
if value is None or value == "":
|
|
47
|
+
self._buffer.close()
|
|
48
|
+
self._buffer = io.StringIO()
|
|
46
49
|
self._buffer.seek(0)
|
|
47
50
|
self._buffer.truncate(0)
|
|
48
51
|
if value:
|
|
@@ -57,6 +60,9 @@ class PidData:
|
|
|
57
60
|
|
|
58
61
|
@live_buffer.setter
|
|
59
62
|
def live_buffer(self, value: str):
|
|
63
|
+
if value is None or value == "":
|
|
64
|
+
self._live_buffer.close()
|
|
65
|
+
self._live_buffer = io.StringIO()
|
|
60
66
|
self._live_buffer.seek(0)
|
|
61
67
|
self._live_buffer.truncate(0)
|
|
62
68
|
if value:
|
|
@@ -71,6 +77,9 @@ class PidData:
|
|
|
71
77
|
|
|
72
78
|
@html.setter
|
|
73
79
|
def html(self, value: str):
|
|
80
|
+
if value is None or value == "":
|
|
81
|
+
self._html.close()
|
|
82
|
+
self._html = io.StringIO()
|
|
74
83
|
self._html.seek(0)
|
|
75
84
|
self._html.truncate(0)
|
|
76
85
|
if value:
|
|
@@ -85,6 +94,9 @@ class PidData:
|
|
|
85
94
|
|
|
86
95
|
@document.setter
|
|
87
96
|
def document(self, value: str):
|
|
97
|
+
if value is None or value == "":
|
|
98
|
+
self._document.close()
|
|
99
|
+
self._document = io.StringIO()
|
|
88
100
|
self._document.seek(0)
|
|
89
101
|
self._document.truncate(0)
|
|
90
102
|
if value:
|
|
@@ -99,9 +111,12 @@ class PidData:
|
|
|
99
111
|
|
|
100
112
|
:param all: If True, clear all data, otherwise only buffers
|
|
101
113
|
"""
|
|
102
|
-
for
|
|
103
|
-
|
|
104
|
-
|
|
114
|
+
for name in ("_buffer", "_live_buffer", "_html", "_document"):
|
|
115
|
+
try:
|
|
116
|
+
getattr(self, name).close()
|
|
117
|
+
except Exception:
|
|
118
|
+
pass
|
|
119
|
+
setattr(self, name, io.StringIO())
|
|
105
120
|
|
|
106
121
|
if all:
|
|
107
122
|
self.item = None
|