pygpt-net 2.5.13__py3-none-any.whl → 2.5.15__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 +12 -1
- pygpt_net/__init__.py +3 -3
- pygpt_net/controller/chat/input.py +9 -2
- pygpt_net/controller/lang/mapping.py +4 -2
- pygpt_net/controller/model/__init__.py +3 -1
- pygpt_net/controller/model/importer.py +337 -0
- pygpt_net/controller/settings/editor.py +3 -0
- pygpt_net/core/camera/__init__.py +1 -1
- pygpt_net/core/models/__init__.py +6 -3
- pygpt_net/core/models/ollama.py +7 -2
- pygpt_net/data/config/config.json +9 -4
- pygpt_net/data/config/models.json +22 -22
- pygpt_net/data/config/modes.json +3 -3
- pygpt_net/data/locale/locale.de.ini +18 -0
- pygpt_net/data/locale/locale.en.ini +19 -2
- pygpt_net/data/locale/locale.es.ini +18 -0
- pygpt_net/data/locale/locale.fr.ini +18 -0
- pygpt_net/data/locale/locale.it.ini +18 -0
- pygpt_net/data/locale/locale.pl.ini +19 -1
- pygpt_net/data/locale/locale.uk.ini +18 -0
- pygpt_net/data/locale/locale.zh.ini +17 -0
- pygpt_net/item/__init__.py +0 -0
- pygpt_net/item/assistant.py +1 -1
- pygpt_net/item/attachment.py +2 -2
- pygpt_net/item/calendar_note.py +1 -1
- pygpt_net/item/ctx.py +1 -1
- pygpt_net/item/index.py +0 -0
- pygpt_net/item/mode.py +0 -0
- pygpt_net/item/model.py +5 -1
- pygpt_net/item/notepad.py +2 -2
- pygpt_net/item/preset.py +0 -0
- pygpt_net/item/prompt.py +2 -2
- pygpt_net/provider/core/ctx/db_sqlite/patch.py +2 -1
- pygpt_net/provider/core/model/json_file.py +3 -0
- pygpt_net/provider/core/model/patch.py +24 -1
- pygpt_net/provider/core/notepad/db_sqlite/patch.py +1 -0
- pygpt_net/provider/llms/ollama.py +7 -2
- pygpt_net/provider/llms/ollama_custom.py +693 -0
- pygpt_net/ui/dialog/models_importer.py +82 -0
- pygpt_net/ui/dialogs.py +3 -1
- pygpt_net/ui/main.py +4 -1
- pygpt_net/ui/menu/config.py +18 -7
- pygpt_net/ui/widget/dialog/model_importer.py +55 -0
- pygpt_net/ui/widget/lists/model_importer.py +151 -0
- {pygpt_net-2.5.13.dist-info → pygpt_net-2.5.15.dist-info}/METADATA +74 -9
- {pygpt_net-2.5.13.dist-info → pygpt_net-2.5.15.dist-info}/RECORD +45 -40
- {pygpt_net-2.5.13.dist-info → pygpt_net-2.5.15.dist-info}/LICENSE +0 -0
- {pygpt_net-2.5.13.dist-info → pygpt_net-2.5.15.dist-info}/WHEEL +0 -0
- {pygpt_net-2.5.13.dist-info → pygpt_net-2.5.15.dist-info}/entry_points.txt +0 -0
pygpt_net/CHANGELOG.txt
CHANGED
@@ -1,6 +1,17 @@
|
|
1
|
+
2.5.15 (2025-06-24)
|
2
|
+
|
3
|
+
- Added Ollama models importer in "Settings -> Models -> Import from Ollama".
|
4
|
+
- Fixed Ollama provider in the newest LlamaIndex.
|
5
|
+
- Added the ability to set a custom base URL for Ollama -> ENV: OLLAMA_API_BASE.
|
6
|
+
|
7
|
+
2.5.14 (2025-06-23)
|
8
|
+
|
9
|
+
- Fix: crash if empty shortcuts in config.
|
10
|
+
- Fix: UUID serialization.
|
11
|
+
|
1
12
|
2.5.13 (2025-06-22)
|
2
13
|
|
3
|
-
- Disabled auto-switch to vision mode in
|
14
|
+
- Disabled auto-switch to vision mode in Painter.
|
4
15
|
- UI fixes.
|
5
16
|
|
6
17
|
2.5.12 (2025-06-22)
|
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-06-
|
9
|
+
# Updated Date: 2025-06-24 19: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.5.
|
17
|
-
__build__ = "2025-06-
|
16
|
+
__version__ = "2.5.15"
|
17
|
+
__build__ = "2025-06-24"
|
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"
|
@@ -6,9 +6,9 @@
|
|
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.
|
9
|
+
# Updated Date: 2025.06.24 16:00:00 #
|
10
10
|
# ================================================== #
|
11
|
-
|
11
|
+
import os
|
12
12
|
from typing import Optional, Any, Dict
|
13
13
|
|
14
14
|
from pygpt_net.core.bridge import BridgeContext
|
@@ -80,6 +80,13 @@ class Input:
|
|
80
80
|
model_data = self.window.core.models.get(model)
|
81
81
|
if model_data is not None and model_data.is_ollama():
|
82
82
|
model_id = model_data.get_ollama_model()
|
83
|
+
# load ENV vars first
|
84
|
+
if ('env' in model_data.llama_index
|
85
|
+
and model_data.llama_index['env'] is not None):
|
86
|
+
for item in model_data.llama_index['env']:
|
87
|
+
key = item.get('name', '').strip()
|
88
|
+
value = item.get('value', '').strip()
|
89
|
+
os.environ[key] = value
|
83
90
|
status = self.window.core.models.ollama.check_model(model_id)
|
84
91
|
is_installed = status.get('is_installed', False)
|
85
92
|
is_model = status.get('is_model', False)
|
@@ -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.
|
9
|
+
# Updated Date: 2025.06.24 02:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from typing import Dict
|
@@ -351,6 +351,7 @@ class Mapping:
|
|
351
351
|
menu_title['config.edit.css'] = 'menu.config.edit.css'
|
352
352
|
menu_title['config.edit.json'] = 'menu.config.edit.json'
|
353
353
|
menu_title['config.profile'] = 'menu.config.profile'
|
354
|
+
menu_title['config.models'] = 'menu.config.models'
|
354
355
|
menu_title['menu.lang'] = 'menu.lang'
|
355
356
|
menu_title['menu.debug'] = 'menu.debug'
|
356
357
|
menu_title['menu.theme'] = 'menu.theme'
|
@@ -376,7 +377,8 @@ class Mapping:
|
|
376
377
|
menu_text['app.clear_history_groups'] = 'menu.file_clear_history_groups'
|
377
378
|
menu_text['app.exit'] = 'menu.file.exit'
|
378
379
|
menu_text['config.settings'] = 'menu.config.settings'
|
379
|
-
menu_text['config.models'] = 'menu.config.models'
|
380
|
+
menu_text['config.models.edit'] = 'menu.config.models.edit'
|
381
|
+
menu_text['config.models.import.ollama'] = 'menu.config.models.import.ollama'
|
380
382
|
menu_text['config.access'] = 'menu.config.access'
|
381
383
|
menu_text['config.open_dir'] = 'menu.config.open_dir'
|
382
384
|
menu_text['config.change_dir'] = 'menu.config.change_dir'
|
@@ -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.
|
9
|
+
# Updated Date: 2025.06.24 02:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from typing import Optional
|
@@ -15,6 +15,7 @@ from pygpt_net.core.events import Event, AppEvent
|
|
15
15
|
from pygpt_net.item.model import ModelItem
|
16
16
|
|
17
17
|
from .editor import Editor
|
18
|
+
from .importer import Importer
|
18
19
|
|
19
20
|
|
20
21
|
class Model:
|
@@ -26,6 +27,7 @@ class Model:
|
|
26
27
|
"""
|
27
28
|
self.window = window
|
28
29
|
self.editor = Editor(window)
|
30
|
+
self.importer = Importer(window)
|
29
31
|
|
30
32
|
def select(self, model: str):
|
31
33
|
"""
|
@@ -0,0 +1,337 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# ================================================== #
|
4
|
+
# This file is a part of PYGPT package #
|
5
|
+
# Website: https://pygpt.net #
|
6
|
+
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
|
+
# MIT License #
|
8
|
+
# Created By : Marcin Szczygliński #
|
9
|
+
# Updated Date: 2025.06.24 02:00:00 #
|
10
|
+
# ================================================== #
|
11
|
+
|
12
|
+
import copy
|
13
|
+
import os
|
14
|
+
from typing import List, Dict, Optional
|
15
|
+
|
16
|
+
from pygpt_net.utils import trans
|
17
|
+
|
18
|
+
|
19
|
+
class Importer:
|
20
|
+
def __init__(self, window=None):
|
21
|
+
"""
|
22
|
+
Models importer controller
|
23
|
+
|
24
|
+
:param window: Window instance
|
25
|
+
"""
|
26
|
+
self.window = window
|
27
|
+
self.dialog = False
|
28
|
+
self.initialized = False
|
29
|
+
self.width = 800
|
30
|
+
self.height = 500
|
31
|
+
self.items_available = {} # available models for import
|
32
|
+
self.items_current = {} # current models in use
|
33
|
+
self.pending = {} # waiting to be imported models
|
34
|
+
self.removed = {} # waiting to be removed models
|
35
|
+
self.selected_available = None # selected available model
|
36
|
+
self.selected_current = None # selected current model
|
37
|
+
self.all = False # show all models, not only available for import
|
38
|
+
|
39
|
+
def in_current(self, model: str) -> bool:
|
40
|
+
"""
|
41
|
+
Check if model is in current list
|
42
|
+
|
43
|
+
:param model: model ID
|
44
|
+
:return: True if model is in current list, False otherwise
|
45
|
+
"""
|
46
|
+
if model in self.items_current:
|
47
|
+
return True
|
48
|
+
for key in list(self.items_current.keys()):
|
49
|
+
m = self.items_current[key]
|
50
|
+
if m.id == model: # also check in IDs
|
51
|
+
return True
|
52
|
+
return False
|
53
|
+
|
54
|
+
def change_available(self):
|
55
|
+
"""On change available model selection"""
|
56
|
+
val = self.window.ui.nodes["models.importer.available"].selectionModel().currentIndex()
|
57
|
+
idx = val.row()
|
58
|
+
if idx < 0:
|
59
|
+
self.selected_available = None
|
60
|
+
self.window.ui.nodes["models.importer.add"].setEnabled(False)
|
61
|
+
else:
|
62
|
+
self.selected_available = self.get_by_idx(idx, self.items_available)
|
63
|
+
if self.items_available.get(self.selected_available) is None:
|
64
|
+
self.selected_available = None
|
65
|
+
self.window.ui.nodes["models.importer.add"].setEnabled(False)
|
66
|
+
else:
|
67
|
+
# if not in current then enable add button
|
68
|
+
if not self.in_current(self.selected_available):
|
69
|
+
self.window.ui.nodes["models.importer.add"].setEnabled(True)
|
70
|
+
else:
|
71
|
+
self.window.ui.nodes["models.importer.add"].setEnabled(False)
|
72
|
+
|
73
|
+
def change_current(self):
|
74
|
+
"""On change current model selection"""
|
75
|
+
val = self.window.ui.nodes["models.importer.current"].selectionModel().currentIndex()
|
76
|
+
idx = val.row()
|
77
|
+
if idx < 0:
|
78
|
+
self.selected_current = None
|
79
|
+
self.window.ui.nodes["models.importer.remove"].setEnabled(False)
|
80
|
+
else:
|
81
|
+
self.selected_current = self.get_by_idx(idx, self.items_current)
|
82
|
+
if self.items_current.get(self.selected_current) is None:
|
83
|
+
self.selected_current = None
|
84
|
+
self.window.ui.nodes["models.importer.remove"].setEnabled(False)
|
85
|
+
else:
|
86
|
+
if self.selected_current in self.items_current and self.items_current[self.selected_current].imported:
|
87
|
+
self.window.ui.nodes["models.importer.remove"].setEnabled(True)
|
88
|
+
else:
|
89
|
+
self.window.ui.nodes["models.importer.remove"].setEnabled(False)
|
90
|
+
|
91
|
+
def add(self):
|
92
|
+
"""Add model to current list"""
|
93
|
+
if self.selected_available is None:
|
94
|
+
self.set_status(trans('models.importer.error.add.no_model'))
|
95
|
+
return
|
96
|
+
if self.in_current(self.selected_available):
|
97
|
+
self.set_status(trans('models.importer.error.add.not_exists'))
|
98
|
+
return
|
99
|
+
model = self.items_available[self.selected_available]
|
100
|
+
self.items_current[self.selected_available] = model
|
101
|
+
if self.selected_available not in self.pending:
|
102
|
+
self.pending[self.selected_available] = model
|
103
|
+
if self.selected_available in self.removed:
|
104
|
+
del self.removed[self.selected_available]
|
105
|
+
if not self.all:
|
106
|
+
del self.items_available[self.selected_available]
|
107
|
+
self.refresh()
|
108
|
+
|
109
|
+
def remove(self):
|
110
|
+
"""Remove model from current list"""
|
111
|
+
if self.selected_current is None:
|
112
|
+
self.set_status(trans('models.importer.error.remove.no_model'))
|
113
|
+
return
|
114
|
+
if not self.in_current(self.selected_current):
|
115
|
+
self.set_status(trans('models.importer.error.remove.not_exists'))
|
116
|
+
return
|
117
|
+
model = self.items_current[self.selected_current]
|
118
|
+
self.items_available[self.selected_current] = model
|
119
|
+
if self.selected_current not in self.removed:
|
120
|
+
self.removed[self.selected_current] = model
|
121
|
+
del self.items_current[self.selected_current]
|
122
|
+
if self.selected_current in self.pending:
|
123
|
+
del self.pending[self.selected_current]
|
124
|
+
self.refresh()
|
125
|
+
|
126
|
+
def setup(self):
|
127
|
+
"""Set up importer"""
|
128
|
+
idx = None
|
129
|
+
self.window.model_importer.setup(idx) # widget dialog setup
|
130
|
+
|
131
|
+
def toggle_editor(self):
|
132
|
+
"""Toggle models importer dialog"""
|
133
|
+
if self.dialog:
|
134
|
+
self.close()
|
135
|
+
else:
|
136
|
+
self.open()
|
137
|
+
|
138
|
+
def open(self, force: bool = False):
|
139
|
+
"""
|
140
|
+
Open models editor dialog
|
141
|
+
|
142
|
+
:param force: force open dialog
|
143
|
+
"""
|
144
|
+
if not self.initialized:
|
145
|
+
self.setup()
|
146
|
+
self.initialized = True
|
147
|
+
if not self.dialog or force:
|
148
|
+
self.pending = {}
|
149
|
+
self.removed = {}
|
150
|
+
self.init()
|
151
|
+
self.window.ui.dialogs.open(
|
152
|
+
"models.importer",
|
153
|
+
width=self.width,
|
154
|
+
height=self.height,
|
155
|
+
)
|
156
|
+
self.dialog = True
|
157
|
+
|
158
|
+
def close(self):
|
159
|
+
"""Close models importer dialog"""
|
160
|
+
if self.dialog:
|
161
|
+
self.window.ui.dialogs.close('models.importer')
|
162
|
+
self.dialog = False
|
163
|
+
|
164
|
+
def cancel(self):
|
165
|
+
"""Cancel models importer dialog"""
|
166
|
+
self.close()
|
167
|
+
|
168
|
+
def init(self):
|
169
|
+
"""Initialize importer"""
|
170
|
+
if self.initialized and self.window.ui.nodes["models.importer.available.all"].isChecked():
|
171
|
+
self.all = True
|
172
|
+
|
173
|
+
base_url = "http://localhost:11434"
|
174
|
+
if 'OLLAMA_API_BASE' in os.environ:
|
175
|
+
base_url = os.environ['OLLAMA_API_BASE']
|
176
|
+
self.window.ui.nodes["models.importer.url"].setText(base_url)
|
177
|
+
self.items_available = self.get_ollama_available()
|
178
|
+
self.items_current = self.get_ollama_current()
|
179
|
+
self.refresh()
|
180
|
+
|
181
|
+
def toggle_all(self, all: bool):
|
182
|
+
"""
|
183
|
+
Toggle all models visibility
|
184
|
+
|
185
|
+
:param all: show all models, not only available for import
|
186
|
+
"""
|
187
|
+
self.all = all
|
188
|
+
self.refresh(reload=True)
|
189
|
+
|
190
|
+
def set_status(self, status: str):
|
191
|
+
"""
|
192
|
+
Set status message
|
193
|
+
|
194
|
+
:param status: status message
|
195
|
+
"""
|
196
|
+
if self.initialized:
|
197
|
+
self.window.ui.nodes["models.importer.status"].setText(status)
|
198
|
+
|
199
|
+
def get_ollama_current(self) -> Dict:
|
200
|
+
"""
|
201
|
+
Get current ollama models
|
202
|
+
|
203
|
+
:return: ollama models dictionary
|
204
|
+
"""
|
205
|
+
items = copy.deepcopy(self.window.core.models.items)
|
206
|
+
for key in list(items.keys()):
|
207
|
+
if (items[key].llama_index is None
|
208
|
+
or 'provider' not in items[key].llama_index
|
209
|
+
or items[key].llama_index['provider'] != 'ollama'):
|
210
|
+
del items[key]
|
211
|
+
return items
|
212
|
+
|
213
|
+
def get_ollama_available(self) -> Dict:
|
214
|
+
"""
|
215
|
+
Get available ollama models
|
216
|
+
|
217
|
+
:return: ollama models dictionary
|
218
|
+
"""
|
219
|
+
models = {}
|
220
|
+
status = self.window.core.models.ollama.get_status()
|
221
|
+
if not status['status']:
|
222
|
+
self.set_status(trans('models.importer.error.no_connection'))
|
223
|
+
return models
|
224
|
+
else:
|
225
|
+
ollama_models = status.get('models', [])
|
226
|
+
if not ollama_models:
|
227
|
+
self.set_status(trans('models.importer.error.no_models'))
|
228
|
+
return models
|
229
|
+
else:
|
230
|
+
for model in ollama_models:
|
231
|
+
name = model.get('name').replace(":latest", "")
|
232
|
+
m = self.window.core.models.create_empty(append=False)
|
233
|
+
m.id = name
|
234
|
+
m.name = name
|
235
|
+
m.mode = [
|
236
|
+
"llama_index",
|
237
|
+
"agent",
|
238
|
+
"agent_llama",
|
239
|
+
"expert",
|
240
|
+
]
|
241
|
+
m.llama_index['provider'] = 'ollama'
|
242
|
+
m.llama_index['mode'] = ['chat']
|
243
|
+
m.llama_index['args'] = [
|
244
|
+
{
|
245
|
+
'name': 'model',
|
246
|
+
'value': name,
|
247
|
+
'type': 'str'
|
248
|
+
}
|
249
|
+
]
|
250
|
+
m.langchain['provider'] = 'ollama'
|
251
|
+
m.langchain['mode'] = ['chat']
|
252
|
+
m.langchain['args'] = [
|
253
|
+
{
|
254
|
+
'name': 'model',
|
255
|
+
'value': name,
|
256
|
+
'type': 'str'
|
257
|
+
}
|
258
|
+
]
|
259
|
+
m.imported = True
|
260
|
+
m.ctx = 32000 # default
|
261
|
+
key = m.id
|
262
|
+
#if key in self.items_current:
|
263
|
+
#key += "_imported"
|
264
|
+
models[key] = m
|
265
|
+
self.set_status(trans('models.importer.loaded'))
|
266
|
+
return models
|
267
|
+
|
268
|
+
def from_pending(self):
|
269
|
+
"""Move pending models to base list"""
|
270
|
+
added = False
|
271
|
+
base_models = self.window.core.models.items
|
272
|
+
for key in list(self.pending.keys()):
|
273
|
+
if key not in base_models:
|
274
|
+
base_models[key] = copy.deepcopy(self.pending[key])
|
275
|
+
base_models[key].imported = True
|
276
|
+
added = True
|
277
|
+
for key in list(self.removed.keys()):
|
278
|
+
if key in base_models:
|
279
|
+
del base_models[key]
|
280
|
+
added = True
|
281
|
+
self.pending = {}
|
282
|
+
self.removed = {}
|
283
|
+
if added:
|
284
|
+
self.window.core.models.save()
|
285
|
+
self.set_status(trans('models.importer.status.imported'))
|
286
|
+
|
287
|
+
def save(self, persist: bool = True):
|
288
|
+
"""
|
289
|
+
Save models
|
290
|
+
|
291
|
+
:param persist: persist to file and close dialog
|
292
|
+
"""
|
293
|
+
self.from_pending()
|
294
|
+
self.window.controller.model.init_list()
|
295
|
+
self.window.controller.model.update()
|
296
|
+
self.close()
|
297
|
+
|
298
|
+
def refresh(self, reload: bool = False):
|
299
|
+
"""
|
300
|
+
Reload items
|
301
|
+
|
302
|
+
:param reload: reload available models
|
303
|
+
"""
|
304
|
+
if reload:
|
305
|
+
self.items_available = self.get_ollama_available()
|
306
|
+
|
307
|
+
# remove from available if already in current
|
308
|
+
if not self.all:
|
309
|
+
for key in list(self.items_available.keys()):
|
310
|
+
if self.in_current(key):
|
311
|
+
del self.items_available[key]
|
312
|
+
|
313
|
+
self.window.ui.nodes['models.importer.editor'].update_available(self.items_available)
|
314
|
+
self.window.ui.nodes['models.importer.editor'].update_current(self.items_current)
|
315
|
+
|
316
|
+
def get_by_idx(self, idx: int, items: Dict) -> Optional[str]:
|
317
|
+
"""
|
318
|
+
Get model key by list index
|
319
|
+
|
320
|
+
:param idx: list index
|
321
|
+
:param items: items dictionary
|
322
|
+
:return: model key
|
323
|
+
"""
|
324
|
+
model_idx = 0
|
325
|
+
for id in self.get_ids(items):
|
326
|
+
if model_idx == idx:
|
327
|
+
return id
|
328
|
+
model_idx += 1
|
329
|
+
return None
|
330
|
+
|
331
|
+
def get_ids(self, items: Dict) -> List[str]:
|
332
|
+
"""
|
333
|
+
Return models ids
|
334
|
+
|
335
|
+
:return: model ids list
|
336
|
+
"""
|
337
|
+
return list(items.keys())
|
@@ -203,6 +203,9 @@ class Editor:
|
|
203
203
|
if self.config_changed('access.shortcuts'):
|
204
204
|
self.window.setup_global_shortcuts()
|
205
205
|
|
206
|
+
# update ENV
|
207
|
+
self.window.core.config.setup_env()
|
208
|
+
|
206
209
|
self.before_config = copy.deepcopy(self.window.core.config.all())
|
207
210
|
self.window.controller.settings.close_window(id)
|
208
211
|
|
@@ -61,7 +61,7 @@ class CaptureWorker(QRunnable):
|
|
61
61
|
try:
|
62
62
|
# get params from global config
|
63
63
|
self.capture = cv2.VideoCapture(self.window.core.config.get('vision.capture.idx'))
|
64
|
-
if not self.capture.isOpened():
|
64
|
+
if not self.capture or not self.capture.isOpened():
|
65
65
|
self.allow_finish = False
|
66
66
|
self.signals.unfinished.emit()
|
67
67
|
return
|
@@ -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.
|
9
|
+
# Updated Date: 2025.06.24 02:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import copy
|
@@ -230,17 +230,20 @@ class Models:
|
|
230
230
|
id = "model-" + str(int(id.split("-")[1]) + 1).zfill(3)
|
231
231
|
return id
|
232
232
|
|
233
|
-
def create_empty(self) -> ModelItem:
|
233
|
+
def create_empty(self, append: bool = True) -> ModelItem:
|
234
234
|
"""
|
235
235
|
Create new empty model
|
236
236
|
|
237
|
+
:param append: if True, append model to items
|
237
238
|
:return: new model
|
239
|
+
|
238
240
|
"""
|
239
241
|
id = self.create_id()
|
240
242
|
model = ModelItem()
|
241
243
|
model.id = id
|
242
244
|
model.name = "New model"
|
243
|
-
|
245
|
+
if append:
|
246
|
+
self.items[id] = model
|
244
247
|
return model
|
245
248
|
|
246
249
|
def get_all(self) -> Dict[str, ModelItem]:
|
pygpt_net/core/models/ollama.py
CHANGED
@@ -6,8 +6,9 @@
|
|
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.
|
9
|
+
# Updated Date: 2025.06.24 16:00:00 #
|
10
10
|
# ================================================== #
|
11
|
+
import os
|
11
12
|
|
12
13
|
import requests
|
13
14
|
|
@@ -27,7 +28,11 @@ class Ollama:
|
|
27
28
|
|
28
29
|
:return: dict
|
29
30
|
"""
|
30
|
-
|
31
|
+
api_base = "http://localhost:11434"
|
32
|
+
if 'OLLAMA_API_BASE' in os.environ:
|
33
|
+
api_base = os.environ['OLLAMA_API_BASE']
|
34
|
+
print("Using Ollama base URL:", api_base)
|
35
|
+
url = api_base + "/api/tags"
|
31
36
|
try:
|
32
37
|
response = requests.get(url, timeout=2)
|
33
38
|
if response.status_code == 200:
|
@@ -1,8 +1,8 @@
|
|
1
1
|
{
|
2
2
|
"__meta__": {
|
3
|
-
"version": "2.5.
|
4
|
-
"app.version": "2.5.
|
5
|
-
"updated_at": "2025-06-
|
3
|
+
"version": "2.5.15",
|
4
|
+
"app.version": "2.5.15",
|
5
|
+
"updated_at": "2025-06-24T00:00:00"
|
6
6
|
},
|
7
7
|
"access.audio.event.speech": false,
|
8
8
|
"access.audio.event.speech.disabled": [],
|
@@ -69,7 +69,12 @@
|
|
69
69
|
"api_key_deepseek": "",
|
70
70
|
"api_key_perplexity": "",
|
71
71
|
"api_proxy": "",
|
72
|
-
"app.env": [
|
72
|
+
"app.env": [
|
73
|
+
{
|
74
|
+
"name": "OLLAMA_API_BASE",
|
75
|
+
"value": "http://localhost:11434"
|
76
|
+
}
|
77
|
+
],
|
73
78
|
"assistant": "",
|
74
79
|
"assistant_thread": "",
|
75
80
|
"assistant.store.hide_threads": true,
|
@@ -1,8 +1,8 @@
|
|
1
1
|
{
|
2
2
|
"__meta__": {
|
3
|
-
"version": "2.5.
|
4
|
-
"app.version": "2.5.
|
5
|
-
"updated_at": "2025-06-
|
3
|
+
"version": "2.5.15",
|
4
|
+
"app.version": "2.5.15",
|
5
|
+
"updated_at": "2025-06-24T00:00:00"
|
6
6
|
},
|
7
7
|
"items": {
|
8
8
|
"claude-3-5-sonnet-20240620": {
|
@@ -416,9 +416,9 @@
|
|
416
416
|
"tokens": 8000,
|
417
417
|
"default": false
|
418
418
|
},
|
419
|
-
"
|
420
|
-
"id": "deepseek-r1
|
421
|
-
"name": "deepseek-r1
|
419
|
+
"deepseek-r1:1.5b": {
|
420
|
+
"id": "deepseek-r1:1.5b",
|
421
|
+
"name": "deepseek-r1:1.5b",
|
422
422
|
"mode": [
|
423
423
|
"llama_index",
|
424
424
|
"agent",
|
@@ -467,9 +467,9 @@
|
|
467
467
|
"tokens": 8000,
|
468
468
|
"default": false
|
469
469
|
},
|
470
|
-
"
|
471
|
-
"id": "deepseek-r1
|
472
|
-
"name": "deepseek-r1
|
470
|
+
"deepseek-r1:7b": {
|
471
|
+
"id": "deepseek-r1:7b",
|
472
|
+
"name": "deepseek-r1:7b",
|
473
473
|
"mode": [
|
474
474
|
"llama_index",
|
475
475
|
"agent",
|
@@ -518,9 +518,9 @@
|
|
518
518
|
"tokens": 8000,
|
519
519
|
"default": false
|
520
520
|
},
|
521
|
-
"
|
522
|
-
"id": "deepseek-r1
|
523
|
-
"name": "deepseek-r1
|
521
|
+
"deepseek-r1:14b": {
|
522
|
+
"id": "deepseek-r1:14b",
|
523
|
+
"name": "deepseek-r1:14b",
|
524
524
|
"mode": [
|
525
525
|
"llama_index",
|
526
526
|
"agent",
|
@@ -569,9 +569,9 @@
|
|
569
569
|
"tokens": 8000,
|
570
570
|
"default": false
|
571
571
|
},
|
572
|
-
"
|
573
|
-
"id": "deepseek-r1
|
574
|
-
"name": "deepseek-r1
|
572
|
+
"deepseek-r1:32b": {
|
573
|
+
"id": "deepseek-r1:32b",
|
574
|
+
"name": "deepseek-r1:32b",
|
575
575
|
"mode": [
|
576
576
|
"llama_index",
|
577
577
|
"agent",
|
@@ -620,9 +620,9 @@
|
|
620
620
|
"tokens": 8000,
|
621
621
|
"default": false
|
622
622
|
},
|
623
|
-
"
|
624
|
-
"id": "deepseek-r1
|
625
|
-
"name": "deepseek-r1
|
623
|
+
"deepseek-r1:70b": {
|
624
|
+
"id": "deepseek-r1:70b",
|
625
|
+
"name": "deepseek-r1:70b",
|
626
626
|
"mode": [
|
627
627
|
"llama_index",
|
628
628
|
"agent",
|
@@ -671,9 +671,9 @@
|
|
671
671
|
"tokens": 8000,
|
672
672
|
"default": false
|
673
673
|
},
|
674
|
-
"
|
675
|
-
"id": "deepseek-r1
|
676
|
-
"name": "deepseek-r1
|
674
|
+
"deepseek-r1:671b": {
|
675
|
+
"id": "deepseek-r1:671b",
|
676
|
+
"name": "deepseek-r1:671b",
|
677
677
|
"mode": [
|
678
678
|
"llama_index",
|
679
679
|
"agent",
|
@@ -722,7 +722,7 @@
|
|
722
722
|
"tokens": 8000,
|
723
723
|
"default": false
|
724
724
|
},
|
725
|
-
"
|
725
|
+
"deepseek-v3:671b": {
|
726
726
|
"id": "deepseek-v3:671b",
|
727
727
|
"name": "deepseek-v3:671b",
|
728
728
|
"mode": [
|
pygpt_net/data/config/modes.json
CHANGED