pygpt-net 2.4.49__py3-none-any.whl → 2.4.51__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.
- CHANGELOG.md +10 -0
- README.md +12 -62
- pygpt_net/CHANGELOG.txt +10 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/controller/access/voice.py +19 -36
- pygpt_net/controller/audio/__init__.py +15 -1
- pygpt_net/controller/lang/custom.py +2 -1
- pygpt_net/controller/ui/tabs.py +7 -1
- pygpt_net/core/audio/__init__.py +10 -17
- pygpt_net/core/audio/capture.py +349 -0
- pygpt_net/data/config/config.json +5 -3
- pygpt_net/data/config/models.json +3 -3
- pygpt_net/data/config/modes.json +3 -3
- pygpt_net/data/config/settings.json +13 -0
- pygpt_net/data/locale/locale.de.ini +3 -0
- pygpt_net/data/locale/locale.en.ini +3 -0
- pygpt_net/data/locale/locale.es.ini +3 -0
- pygpt_net/data/locale/locale.fr.ini +3 -0
- pygpt_net/data/locale/locale.it.ini +3 -0
- pygpt_net/data/locale/locale.pl.ini +3 -0
- pygpt_net/data/locale/locale.uk.ini +3 -0
- pygpt_net/data/locale/locale.zh.ini +3 -0
- pygpt_net/plugin/audio_input/simple.py +45 -55
- pygpt_net/provider/core/config/patch.py +9 -1
- pygpt_net/ui/layout/chat/input.py +0 -12
- pygpt_net/ui/menu/__init__.py +4 -3
- pygpt_net/ui/widget/audio/input_button.py +84 -24
- pygpt_net/ui/widget/dialog/snap.py +2 -2
- pygpt_net/ui/widget/dialog/update.py +3 -2
- {pygpt_net-2.4.49.dist-info → pygpt_net-2.4.51.dist-info}/METADATA +13 -63
- {pygpt_net-2.4.49.dist-info → pygpt_net-2.4.51.dist-info}/RECORD +34 -33
- {pygpt_net-2.4.49.dist-info → pygpt_net-2.4.51.dist-info}/LICENSE +0 -0
- {pygpt_net-2.4.49.dist-info → pygpt_net-2.4.51.dist-info}/WHEEL +0 -0
- {pygpt_net-2.4.49.dist-info → pygpt_net-2.4.51.dist-info}/entry_points.txt +0 -0
@@ -6,16 +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:
|
9
|
+
# Updated Date: 2025.01.17 02:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
|
-
import pyaudio
|
13
|
-
import wave
|
14
12
|
import os
|
15
13
|
|
16
14
|
from PySide6.QtCore import QTimer
|
17
15
|
|
18
16
|
from pygpt_net.core.events import AppEvent
|
17
|
+
from pygpt_net.core.tabs.tab import Tab
|
19
18
|
from pygpt_net.utils import trans
|
20
19
|
|
21
20
|
|
@@ -32,9 +31,6 @@ class Simple:
|
|
32
31
|
"""
|
33
32
|
self.plugin = plugin
|
34
33
|
self.is_recording = False
|
35
|
-
self.frames = []
|
36
|
-
self.p = None
|
37
|
-
self.stream = None
|
38
34
|
self.timer = None
|
39
35
|
|
40
36
|
def toggle_recording(self):
|
@@ -59,56 +55,48 @@ class Simple:
|
|
59
55
|
"""Stop timeout"""
|
60
56
|
self.stop_recording(timeout=True)
|
61
57
|
|
62
|
-
def start_recording(self):
|
63
|
-
"""
|
64
|
-
|
58
|
+
def start_recording(self, force: bool = False):
|
59
|
+
"""
|
60
|
+
Start recording
|
65
61
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
62
|
+
:param force: True to force recording
|
63
|
+
"""
|
64
|
+
# enable continuous mode if notepad tab is active
|
65
|
+
self.plugin.window.core.audio.capture.stop_callback = self.on_stop
|
66
|
+
continuous_enabled = self.plugin.window.core.config.get('audio.input.continuous', False)
|
67
|
+
if continuous_enabled and self.plugin.window.controller.ui.tabs.get_current_type() == Tab.TAB_NOTEPAD:
|
68
|
+
self.plugin.window.core.audio.capture.loop = True # set loop
|
69
|
+
else:
|
70
|
+
self.plugin.window.core.audio.capture.loop = False
|
72
71
|
|
73
72
|
try:
|
74
|
-
self.is_recording = True
|
75
|
-
self.switch_btn_stop()
|
76
|
-
|
77
73
|
# stop audio output if playing
|
78
74
|
if self.plugin.window.controller.audio.is_playing():
|
79
75
|
self.plugin.window.controller.audio.stop_output()
|
80
76
|
|
77
|
+
# set audio volume bar
|
78
|
+
self.plugin.window.core.audio.capture.set_bar(
|
79
|
+
self.plugin.window.ui.plugin_addon['audio.input.btn'].bar
|
80
|
+
)
|
81
|
+
|
81
82
|
# start timeout timer to prevent infinite recording
|
82
83
|
if self.timer is None:
|
83
84
|
self.timer = QTimer()
|
84
85
|
self.timer.timeout.connect(self.stop_timeout)
|
85
86
|
self.timer.start(self.TIMEOUT_SECONDS * 1000)
|
86
87
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
message = "Selected audio input device is not compatible. Please select another one. ERROR: " + str(err)
|
94
|
-
self.is_recording = False
|
95
|
-
self.plugin.window.core.debug.log(message)
|
96
|
-
self.plugin.window.ui.dialogs.alert(message)
|
97
|
-
self.switch_btn_start() # switch button to start
|
98
|
-
return
|
99
|
-
|
100
|
-
self.p = pyaudio.PyAudio()
|
101
|
-
self.stream = self.p.open(format=pyaudio.paInt16,
|
102
|
-
channels=channels,
|
103
|
-
rate=rate,
|
104
|
-
input=True,
|
105
|
-
input_device_index=device_id,
|
106
|
-
frames_per_buffer=1024,
|
107
|
-
stream_callback=callback)
|
88
|
+
if not force:
|
89
|
+
if not self.plugin.window.core.audio.capture.check_audio_input():
|
90
|
+
raise Exception("Audio input not working.")
|
91
|
+
# IMPORTANT!!!!
|
92
|
+
# Stop here if audio input not working!
|
93
|
+
# This prevents the app from freezing when audio input is not working!
|
108
94
|
|
95
|
+
self.is_recording = True
|
96
|
+
self.switch_btn_stop()
|
97
|
+
self.plugin.window.core.audio.capture.start() # start recording if audio is OK
|
109
98
|
self.plugin.window.update_status(trans('audio.speak.now'))
|
110
99
|
self.plugin.window.dispatch(AppEvent(AppEvent.INPUT_VOICE_LISTEN_STARTED)) # app event
|
111
|
-
self.stream.start_stream()
|
112
100
|
except Exception as e:
|
113
101
|
self.is_recording = False
|
114
102
|
self.plugin.window.core.debug.log(e)
|
@@ -127,6 +115,7 @@ class Simple:
|
|
127
115
|
|
128
116
|
:param timeout: True if stopped due to timeout
|
129
117
|
"""
|
118
|
+
self.plugin.window.core.audio.capture.reset_audio_level()
|
130
119
|
self.is_recording = False
|
131
120
|
self.plugin.window.dispatch(AppEvent(AppEvent.INPUT_VOICE_LISTEN_STOPPED)) # app event
|
132
121
|
if self.timer:
|
@@ -134,30 +123,31 @@ class Simple:
|
|
134
123
|
self.timer = None
|
135
124
|
self.switch_btn_start() # switch button to start
|
136
125
|
path = os.path.join(self.plugin.window.core.config.path, self.plugin.input_file)
|
126
|
+
self.plugin.window.core.audio.capture.set_path(path)
|
137
127
|
|
138
|
-
if self.
|
139
|
-
self.
|
140
|
-
self.stream.close()
|
141
|
-
self.p.terminate()
|
142
|
-
|
128
|
+
if self.plugin.window.core.audio.capture.has_source():
|
129
|
+
self.plugin.window.core.audio.capture.stop() # stop recording
|
143
130
|
# abort if timeout
|
144
131
|
if timeout:
|
145
132
|
self.plugin.window.update_status("Aborted.".format(self.TIMEOUT_SECONDS))
|
146
133
|
return
|
147
134
|
|
148
|
-
if self.
|
149
|
-
|
135
|
+
if self.plugin.window.core.audio.capture.has_frames():
|
136
|
+
frames = self.plugin.window.core.audio.capture.get_frames()
|
137
|
+
if len(frames) < self.MIN_FRAMES:
|
150
138
|
self.plugin.window.update_status(trans("status.audio.too_short"))
|
151
139
|
self.plugin.window.dispatch(AppEvent(AppEvent.VOICE_CONTROL_STOPPED)) # app event
|
152
140
|
return
|
153
|
-
|
154
|
-
channels = int(self.plugin.window.core.config.get('audio.input.channels', 1))
|
155
|
-
rate = int(self.plugin.window.core.config.get('audio.input.rate', 44100))
|
156
|
-
wf.setnchannels(channels)
|
157
|
-
wf.setsampwidth(self.p.get_sample_size(pyaudio.paInt16))
|
158
|
-
wf.setframerate(rate)
|
159
|
-
wf.writeframes(b''.join(self.frames))
|
160
|
-
wf.close()
|
141
|
+
|
161
142
|
self.plugin.handle_thread(True) # handle transcription in simple mode
|
162
143
|
else:
|
163
144
|
self.plugin.window.update_status("")
|
145
|
+
|
146
|
+
|
147
|
+
def on_stop(self):
|
148
|
+
"""Handle auto-transcribe"""
|
149
|
+
path = os.path.join(self.plugin.window.core.config.path, self.plugin.input_file)
|
150
|
+
self.plugin.window.core.audio.capture.set_path(path)
|
151
|
+
self.plugin.window.core.audio.capture.stop()
|
152
|
+
self.plugin.window.core.audio.capture.start()
|
153
|
+
self.plugin.handle_thread(True)
|
@@ -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:
|
9
|
+
# Updated Date: 2025.01.17 02:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import copy
|
@@ -1803,6 +1803,14 @@ class Patch:
|
|
1803
1803
|
data["api_key_hugging_face"] = ""
|
1804
1804
|
updated = True
|
1805
1805
|
|
1806
|
+
# < 2.4.51
|
1807
|
+
if old < parse_version("2.4.51"):
|
1808
|
+
print("Migrating config from < 2.4.51...")
|
1809
|
+
if 'audio.input.stop_interval' not in data:
|
1810
|
+
data["audio.input.stop_interval"] = 10
|
1811
|
+
if 'audio.input.continuous' not in data:
|
1812
|
+
data["audio.input.continuous"] = False
|
1813
|
+
|
1806
1814
|
# update file
|
1807
1815
|
migrated = False
|
1808
1816
|
if updated:
|
@@ -160,24 +160,12 @@ class Input:
|
|
160
160
|
|
161
161
|
grid = QGridLayout()
|
162
162
|
|
163
|
-
#left_layout = QHBoxLayout()
|
164
|
-
#left_layout.addWidget(self.window.ui.nodes['input.label'])
|
165
|
-
#left_layout.addWidget(self.window.ui.nodes['inline.vision'])
|
166
|
-
#left_layout.addStretch(1)
|
167
|
-
|
168
163
|
center_layout = QHBoxLayout()
|
169
164
|
center_layout.addStretch()
|
170
165
|
center_layout.addWidget(self.window.ui.plugin_addon['audio.input'])
|
171
166
|
center_layout.addWidget(self.window.ui.plugin_addon['audio.input.btn'])
|
172
167
|
center_layout.addStretch()
|
173
|
-
|
174
|
-
#right_layout = QHBoxLayout()
|
175
|
-
#right_layout.addStretch(1)
|
176
|
-
#right_layout.addWidget(self.window.ui.nodes['input.counter'])
|
177
|
-
|
178
|
-
#grid.addLayout(left_layout, 0, 0)
|
179
168
|
grid.addLayout(center_layout, 0, 1, alignment=Qt.AlignCenter)
|
180
|
-
#grid.addLayout(right_layout, 0, 2, alignment=Qt.AlignRight)
|
181
169
|
|
182
170
|
grid.setContentsMargins(0, 0, 0, 0)
|
183
171
|
return grid
|
pygpt_net/ui/menu/__init__.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.01.
|
9
|
+
# Updated Date: 2025.01.17 02:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from .about import About
|
@@ -50,15 +50,16 @@ class Menu:
|
|
50
50
|
self.audio.setup()
|
51
51
|
self.video.setup()
|
52
52
|
self.config.setup()
|
53
|
-
self.about.setup()
|
54
53
|
|
55
54
|
def post_setup(self):
|
56
55
|
"""Post setup menus"""
|
57
56
|
# tools menu
|
58
57
|
self.tools.setup()
|
59
|
-
self.
|
58
|
+
self.about.setup()
|
60
59
|
|
61
60
|
# debug menu
|
62
61
|
show = self.window.core.config.get('debug')
|
63
62
|
self.debug.setup()
|
64
63
|
self.window.ui.menu['menu.debug'].menuAction().setVisible(show)
|
64
|
+
|
65
|
+
self.donate.setup()
|
@@ -6,14 +6,17 @@
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
7
|
# MIT License #
|
8
8
|
# Created By : Marcin Szczygliński #
|
9
|
-
# Updated Date:
|
9
|
+
# Updated Date: 2025.01.17 02:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from PySide6.QtCore import Qt
|
13
|
-
from PySide6.
|
13
|
+
from PySide6.QtGui import QPainter, QIcon
|
14
|
+
from PySide6.QtWidgets import QLabel, QHBoxLayout, QWidget, QPushButton, QVBoxLayout
|
14
15
|
|
15
16
|
from pygpt_net.core.events import Event, AppEvent
|
17
|
+
from pygpt_net.ui.widget.option.toggle_label import ToggleLabel
|
16
18
|
from pygpt_net.utils import trans
|
19
|
+
import pygpt_net.icons_rc
|
17
20
|
|
18
21
|
class VoiceControlButton(QWidget):
|
19
22
|
def __init__(self, window=None):
|
@@ -25,20 +28,24 @@ class VoiceControlButton(QWidget):
|
|
25
28
|
super(VoiceControlButton, self).__init__(window)
|
26
29
|
self.window = window
|
27
30
|
|
28
|
-
self.btn_toggle = QPushButton(trans('audio.control.btn'))
|
31
|
+
self.btn_toggle = QPushButton(QIcon(":/icons/mic.svg"), trans('audio.control.btn'))
|
29
32
|
self.btn_toggle.clicked.connect(self.toggle_recording)
|
30
33
|
self.btn_toggle.setToolTip(trans('audio.speak.btn.tooltip'))
|
31
34
|
self.btn_toggle.setCursor(Qt.PointingHandCursor)
|
32
35
|
self.btn_toggle.setMinimumWidth(200)
|
33
36
|
|
37
|
+
self.bar = LevelBar(self)
|
38
|
+
self.bar.setLevel(0)
|
39
|
+
|
34
40
|
# status
|
35
41
|
self.status = QLabel("")
|
36
42
|
self.status.setStyleSheet("color: #999; font-size: 10px; font-weight: 400; margin: 0; padding: 0; border: 0;")
|
37
43
|
self.status.setMaximumHeight(15)
|
38
44
|
|
39
|
-
self.layout =
|
45
|
+
self.layout = QVBoxLayout(self)
|
40
46
|
self.layout.addWidget(self.btn_toggle)
|
41
|
-
self.layout.addWidget(self.status)
|
47
|
+
# self.layout.addWidget(self.status)
|
48
|
+
self.layout.addWidget(self.bar)
|
42
49
|
|
43
50
|
# self.layout.addWidget(self.stop)
|
44
51
|
self.layout.setAlignment(Qt.AlignCenter)
|
@@ -76,25 +83,43 @@ class AudioInputButton(QWidget):
|
|
76
83
|
super(AudioInputButton, self).__init__(window)
|
77
84
|
self.window = window
|
78
85
|
|
79
|
-
self.btn_toggle = QPushButton(trans('audio.speak.btn'))
|
86
|
+
self.btn_toggle = QPushButton(QIcon(":/icons/mic.svg"), trans('audio.speak.btn'))
|
80
87
|
self.btn_toggle.clicked.connect(self.toggle_recording)
|
81
88
|
self.btn_toggle.setToolTip(trans('audio.speak.btn.tooltip'))
|
82
89
|
self.btn_toggle.setCursor(Qt.PointingHandCursor)
|
83
90
|
self.btn_toggle.setMinimumWidth(200)
|
84
91
|
|
85
|
-
|
86
|
-
self.
|
87
|
-
self.status.setStyleSheet("color: #999; font-size: 10px; font-weight: 400; margin: 0; padding: 0; border: 0;")
|
88
|
-
self.status.setMaximumHeight(15)
|
92
|
+
self.bar = LevelBar(self)
|
93
|
+
self.bar.setLevel(0)
|
89
94
|
|
90
|
-
|
91
|
-
|
92
|
-
|
95
|
+
btn_layout = QVBoxLayout()
|
96
|
+
btn_layout.addWidget(self.btn_toggle)
|
97
|
+
btn_layout.addWidget(self.bar)
|
98
|
+
btn_layout.setContentsMargins(0, 0, 0, 0)
|
99
|
+
btn_widget = QWidget()
|
100
|
+
btn_widget.setLayout(btn_layout)
|
101
|
+
|
102
|
+
self.continuous = ToggleLabel(trans('audio.speak.btn.continuous'), label_position="right")
|
103
|
+
self.continuous.box.stateChanged.connect(
|
104
|
+
lambda: self.window.controller.audio.toggle_continuous(
|
105
|
+
self.continuous.box.isChecked())
|
106
|
+
)
|
107
|
+
|
108
|
+
self.notepad_layout = QHBoxLayout()
|
109
|
+
self.notepad_layout.addWidget(self.continuous)
|
110
|
+
self.notepad_layout.setContentsMargins(0, 0, 0, 0)
|
111
|
+
|
112
|
+
self.notepad_footer = QWidget()
|
113
|
+
self.notepad_footer.setLayout(self.notepad_layout)
|
114
|
+
|
115
|
+
self.layout = QHBoxLayout()
|
116
|
+
self.layout.addWidget(btn_widget)
|
117
|
+
self.layout.addWidget(self.notepad_footer)
|
118
|
+
self.layout.setContentsMargins(0, 0, 0, 0)
|
93
119
|
|
94
|
-
# self.layout.addWidget(self.stop)
|
95
|
-
self.layout.setAlignment(Qt.AlignCenter)
|
96
120
|
self.setLayout(self.layout)
|
97
|
-
|
121
|
+
btn_widget.setMaximumHeight(80)
|
122
|
+
self.setMaximumHeight(120)
|
98
123
|
|
99
124
|
def add_widget(self, widget):
|
100
125
|
"""
|
@@ -104,15 +129,50 @@ class AudioInputButton(QWidget):
|
|
104
129
|
"""
|
105
130
|
self.layout.addWidget(widget)
|
106
131
|
|
107
|
-
def set_status(self, text):
|
108
|
-
"""
|
109
|
-
Set status text
|
110
|
-
|
111
|
-
:param text: text
|
112
|
-
"""
|
113
|
-
self.status.setText(text)
|
114
|
-
|
115
132
|
def toggle_recording(self):
|
116
133
|
"""Toggle recording"""
|
117
134
|
event = Event(Event.AUDIO_INPUT_RECORD_TOGGLE)
|
118
135
|
self.window.dispatch(event)
|
136
|
+
|
137
|
+
|
138
|
+
class LevelBar(QWidget):
|
139
|
+
def __init__(self, parent=None):
|
140
|
+
super().__init__(parent)
|
141
|
+
self._level = 0.0 # level from 0.0 to 100.0
|
142
|
+
self.setFixedSize(200, 5) # bar size
|
143
|
+
|
144
|
+
def setLevel(self, level):
|
145
|
+
"""
|
146
|
+
Set volume level
|
147
|
+
|
148
|
+
:param level: level
|
149
|
+
"""
|
150
|
+
self._level = level
|
151
|
+
self.update()
|
152
|
+
|
153
|
+
def paintEvent(self, event):
|
154
|
+
"""
|
155
|
+
Paint event
|
156
|
+
|
157
|
+
:param event: event
|
158
|
+
"""
|
159
|
+
painter = QPainter(self)
|
160
|
+
painter.fillRect(self.rect(), Qt.transparent)
|
161
|
+
level_width = (self._level / 100.0) * self.width()
|
162
|
+
painter.setBrush(Qt.green)
|
163
|
+
painter.setPen(Qt.NoPen)
|
164
|
+
painter.drawRect(0, 0, level_width, self.height())
|
165
|
+
|
166
|
+
"""
|
167
|
+
# --- bar from center ---
|
168
|
+
def paintEvent(self, event):
|
169
|
+
painter = QPainter(self)
|
170
|
+
painter.fillRect(self.rect(), Qt.transparent)
|
171
|
+
level_width = (self._level / 100.0) * self.width()
|
172
|
+
half_level_width = level_width / 2
|
173
|
+
center_x = self.width() / 2
|
174
|
+
rect_x = center_x - half_level_width
|
175
|
+
painter.setBrush(Qt.green)
|
176
|
+
painter.setPen(Qt.NoPen)
|
177
|
+
painter.drawRect(rect_x, 0, level_width, self.height())
|
178
|
+
"""
|
@@ -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:
|
9
|
+
# Updated Date: 2025.01.16 17:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from PySide6.QtWidgets import QDialog, QLabel, QVBoxLayout, QPushButton
|
@@ -55,7 +55,7 @@ class SnapDialogAudioInput(QDialog):
|
|
55
55
|
self.window = window
|
56
56
|
self.setParent(window)
|
57
57
|
self.setWindowTitle("Snap is detected")
|
58
|
-
self.cmd = CmdLabel(self.window, "sudo snap connect pygpt:audio-record :audio-record")
|
58
|
+
self.cmd = CmdLabel(self.window, "sudo snap connect pygpt:alsa && sudo snap connect pygpt:audio-record :audio-record")
|
59
59
|
|
60
60
|
self.btn = QPushButton("OK")
|
61
61
|
self.btn.clicked.connect(self.accept)
|
@@ -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:
|
9
|
+
# Updated Date: 2025.01.16 17:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import os
|
@@ -177,7 +177,8 @@ class UpdateDialog(BaseDialog):
|
|
177
177
|
if self.window.core.platforms.is_windows():
|
178
178
|
self.download_link = download_windows
|
179
179
|
self.download_file.setText("{} .msi ({})".format(trans("action.download"), version))
|
180
|
-
self.download_file.setVisible(
|
180
|
+
self.download_file.setVisible(False) # Windows Store: disabled
|
181
|
+
self.info_upgrade.setVisible(False) # Windows Store: disabled
|
181
182
|
elif self.window.core.platforms.is_linux():
|
182
183
|
self.download_link = download_linux
|
183
184
|
self.download_file.setText("{} .tar.gz ({})".format(trans("action.download"), version))
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: pygpt-net
|
3
|
-
Version: 2.4.
|
3
|
+
Version: 2.4.51
|
4
4
|
Summary: Desktop AI Assistant powered by models: OpenAI o1, GPT-4o, GPT-4, GPT-4 Vision, GPT-3.5, DALL-E 3, Llama 3, Mistral, Gemini, Claude, Bielik, and other models supported by Langchain, 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
|
Home-page: https://pygpt.net
|
6
6
|
License: MIT
|
@@ -93,7 +93,7 @@ Description-Content-Type: text/markdown
|
|
93
93
|
|
94
94
|
[](https://snapcraft.io/pygpt)
|
95
95
|
|
96
|
-
Release: **2.4.
|
96
|
+
Release: **2.4.51** | build: **2025.01.17** | Python: **>=3.10, <3.13**
|
97
97
|
|
98
98
|
> Official website: https://pygpt.net | Documentation: https://pygpt.readthedocs.io
|
99
99
|
>
|
@@ -209,6 +209,7 @@ sudo snap connect pygpt:camera
|
|
209
209
|
|
210
210
|
```commandline
|
211
211
|
sudo snap connect pygpt:audio-record :audio-record
|
212
|
+
sudo snap connect pygpt:alsa
|
212
213
|
```
|
213
214
|
|
214
215
|
**Connecting IPython in Docker in Snap version**:
|
@@ -4043,6 +4044,16 @@ may consume additional tokens that are not displayed in the main window.
|
|
4043
4044
|
|
4044
4045
|
## Recent changes:
|
4045
4046
|
|
4047
|
+
**2.4.51 (2025-01-17)**
|
4048
|
+
|
4049
|
+
- Added a "Continuous recording" mode under Audio Input in the Notepad tab, allowing for recording long voice notes and real-time auto-transcription. (beta)
|
4050
|
+
- A new option has been added in Settings -> Audio -> Continuous recording auto-transcribe interval.
|
4051
|
+
|
4052
|
+
**2.4.50 (2025-01-16)**
|
4053
|
+
|
4054
|
+
- Refactored audio input core.
|
4055
|
+
- Added audio input volume progress bar.
|
4056
|
+
|
4046
4057
|
**2.4.49 (2025-01-16)**
|
4047
4058
|
|
4048
4059
|
- Fix: stream render in Assistants mode.
|
@@ -4068,67 +4079,6 @@ may consume additional tokens that are not displayed in the main window.
|
|
4068
4079
|
- Introduced a new mode in "Chat with Files": "Retrieve Only", which allows for retrieving raw documents from the index.
|
4069
4080
|
- Fixed a bug related to tool calls in the Gemini provider when using Chat with Files mode.
|
4070
4081
|
|
4071
|
-
**2.4.45 (2024-12-16)**
|
4072
|
-
|
4073
|
-
- Enhanced web data loaders UI.
|
4074
|
-
|
4075
|
-
**2.4.44 (2024-12-16)**
|
4076
|
-
|
4077
|
-
- Enhanced web data loaders.
|
4078
|
-
- Web loaders have been added to attachments, allowing external web content to be attached to context via the "+Web" button in the Attachments tab.
|
4079
|
-
- Improved handling of attachments in groups and added an attachment icon when a group contains attachments.
|
4080
|
-
|
4081
|
-
**2.4.43 (2024-12-15)**
|
4082
|
-
|
4083
|
-
- Fix: Bug on attachment upload.
|
4084
|
-
- Added: Attachments uploaded in groups are now available for all contexts in the group (beta).
|
4085
|
-
|
4086
|
-
**2.4.42 (2024-12-15)**
|
4087
|
-
|
4088
|
-
- Added Mailer plugin, which allows sending and retrieving emails from the server, and reading them. It currently supports only SMTP.
|
4089
|
-
- Added 'web_request' command to the Web Search plugin, enabling GET/POST/PUT and other connections to any address and API endpoint. It also supports sending POST data, files, headers, cookies, and more.
|
4090
|
-
- Improved audio output.
|
4091
|
-
- Enhanced visibility of the Video menu.
|
4092
|
-
- Other fixes.
|
4093
|
-
|
4094
|
-
**2.4.41 (2024-12-14)**
|
4095
|
-
|
4096
|
-
- Improved switching between columns on a split screen.
|
4097
|
-
- Added visual identification of the active column.
|
4098
|
-
|
4099
|
-
**2.4.40 (2024-12-13)**
|
4100
|
-
|
4101
|
-
- Enhanced Split Screen mode, now promoted from beta to stable.
|
4102
|
-
- Python Code Interpreter tool added to the Tabs.
|
4103
|
-
- HTML/JS Canvas tool added to the Tabs.
|
4104
|
-
- Added attachment icon to the context list if context has attachments.
|
4105
|
-
- Improved audio playback.
|
4106
|
-
- Improved web search.
|
4107
|
-
- Added a thumbnail image to web search results.
|
4108
|
-
- Added a new commands to web search: "extract_images" and "extract_links".
|
4109
|
-
- Added the option "Use raw content (without summarization)" to the web search plugin, which provides a more detailed result to the main model.
|
4110
|
-
- Extended the default maximum result characters to 50,000 in the web search plugin.
|
4111
|
-
|
4112
|
-
**2.4.39 (2024-12-09)**
|
4113
|
-
|
4114
|
-
- Added "Split Screen" mode (accessible via the switch in the bottom-right corner of the screen), which allows you to work in two windows simultaneously. It is currently experimental (beta). Future updates will include Code Interpreter and Canvas running in tabs.
|
4115
|
-
|
4116
|
-
- Fixed: Language switch.
|
4117
|
-
|
4118
|
-
**2.4.38 (2024-12-08)**
|
4119
|
-
|
4120
|
-
- Added the ability to select a style for chat display between: Blocks, ChatGPT-like, and ChatGPT-like Wide. New option in the menu: Config -> Theme -> Style...
|
4121
|
-
- Added configuration options for audio input in Settings -> Audio -> Audio Input Device, Channels, and Sampling rate.
|
4122
|
-
|
4123
|
-
**2.4.37 (2024-11-30)**
|
4124
|
-
|
4125
|
-
- The `Query only` mode in `Uploaded` tab has been renamed to `RAG`.
|
4126
|
-
- New options have been added under `Settings -> Files and Attachments`:
|
4127
|
-
- `Use history in RAG query`: When enabled, the content of the entire conversation will be used when preparing a query if the mode is set to RAG or Summary.
|
4128
|
-
- `RAG limit`: This option is applicable only if 'Use history in RAG query' is enabled. It specifies the limit on how many recent entries in the conversation will be used when generating a query for RAG. A value of 0 indicates no limit.
|
4129
|
-
- Cache: dynamic parts of the system prompt (from plugins) have been moved to the very end of the prompt stack to enable the use of prompt cache mechanisms in OpenAI.
|
4130
|
-
|
4131
|
-
|
4132
4082
|
# Credits and links
|
4133
4083
|
|
4134
4084
|
**Official website:** <https://pygpt.net>
|