pygpt-net 2.5.14__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 +6 -0
- 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/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/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/model.py +5 -1
- pygpt_net/provider/core/model/json_file.py +3 -0
- pygpt_net/provider/core/model/patch.py +24 -1
- 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/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.14.dist-info → pygpt_net-2.5.15.dist-info}/METADATA +68 -8
- {pygpt_net-2.5.14.dist-info → pygpt_net-2.5.15.dist-info}/RECORD +34 -29
- {pygpt_net-2.5.14.dist-info → pygpt_net-2.5.15.dist-info}/LICENSE +0 -0
- {pygpt_net-2.5.14.dist-info → pygpt_net-2.5.15.dist-info}/WHEEL +0 -0
- {pygpt_net-2.5.14.dist-info → pygpt_net-2.5.15.dist-info}/entry_points.txt +0 -0
pygpt_net/CHANGELOG.txt
CHANGED
@@ -1,3 +1,9 @@
|
|
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
|
+
|
1
7
|
2.5.14 (2025-06-23)
|
2
8
|
|
3
9
|
- Fix: crash if empty shortcuts in config.
|
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
|
|
@@ -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": [
|
@@ -293,6 +293,10 @@ dialog.license.label = Durch die Verwendung dieser Software akzeptieren Sie die
|
|
293
293
|
dialog.license.title = Lizenz
|
294
294
|
dialog.logger.btn.clear = Löschen
|
295
295
|
dialog.logger.title = Protokollierung
|
296
|
+
dialog.models.importer = Modelle von Ollama importieren
|
297
|
+
dialog.models.importer.btn.cancel = Abbrechen
|
298
|
+
dialog.models.importer.btn.refresh = Aktualisieren
|
299
|
+
dialog.models.importer.btn.save = Speichern
|
296
300
|
dialog.ollama.model_not_found = Das angeforderte Modell ({model}) ist in deinem Ollama nicht verfügbar.\nBitte lade das Modell herunter, indem du den Befehl ausführst:\nollama pull {model}
|
297
301
|
dialog.ollama.not_installed = Ollama ist nicht installiert oder läuft nicht.\nBitte installiere zuerst Ollama, indem du die folgende Seite besuchst:\nhttps://ollama.com/download
|
298
302
|
dialog.plugin_settings = Plugin-Einstellungen
|
@@ -567,6 +571,9 @@ menu.config.edit.config = config.json bearbeiten...
|
|
567
571
|
menu.config.edit.css = CSS-Stylesheets bearbeiten...
|
568
572
|
menu.config.edit.css.restore = Standard-CSS wiederherstellen...
|
569
573
|
menu.config.edit.models = models.json bearbeiten...
|
574
|
+
menu.config.models = Modelle...
|
575
|
+
menu.config.models.edit = Modelle bearbeiten
|
576
|
+
menu.config.models.import.ollama = Von Ollama importieren
|
570
577
|
menu.config.open_dir = Arbeitsverzeichnis öffnen...
|
571
578
|
menu.config.profile = Profil
|
572
579
|
menu.config.profile.edit = Profile bearbeiten...
|
@@ -653,6 +660,17 @@ mode.langchain = Langchain
|
|
653
660
|
mode.langchain.tooltip = Chat mit Modellen von Langchain
|
654
661
|
mode.llama_index = Chat mit Dateien
|
655
662
|
mode.llama_index.tooltip = Chat mit zusätzlichem Kontext von LlamaIndex
|
663
|
+
models.importer.all = Alle anzeigen
|
664
|
+
models.importer.available.label = Ollama-Modelle
|
665
|
+
models.importer.current.label = PyGPT-Modelle
|
666
|
+
models.importer.error.add.no_model = Kein Modell zum Hinzufügen ausgewählt
|
667
|
+
models.importer.error.add.not_exists = Modell existiert bereits in der aktuellen Liste
|
668
|
+
models.importer.error.no_connection = Ollama läuft nicht oder ist nicht verfügbar! Bitte starten Sie den Ollama-Server und klicken Sie auf die AKTUALISIEREN-Schaltfläche.
|
669
|
+
models.importer.error.no_models = Keine Ollama-Modelle verfügbar! Bitte installieren Sie Modelle mit dem Ollama CLI und klicken Sie auf die AKTUALISIEREN-Schaltfläche.
|
670
|
+
models.importer.error.remove.no_model = Kein Modell zum Entfernen ausgewählt
|
671
|
+
models.importer.error.remove.not_exists = Modell existiert bereits in der aktuellen Liste
|
672
|
+
models.importer.loaded = Ollama-Modelle erfolgreich geladen.
|
673
|
+
models.importer.status.imported = Modelle erfolgreich importiert.
|
656
674
|
mode.vision = Vision
|
657
675
|
mode.vision.tooltip = Bildanalyse mit GPT-4 Vision
|
658
676
|
msg.agent.plan = Plan
|