MindsDB 25.9.1.0__py3-none-any.whl → 25.9.1.2__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.
Potentially problematic release.
This version of MindsDB might be problematic. Click here for more details.
- mindsdb/__about__.py +1 -1
- mindsdb/__main__.py +1 -1
- mindsdb/api/executor/utilities/mysql_to_duckdb_functions.py +466 -18
- mindsdb/api/executor/utilities/sql.py +9 -31
- mindsdb/api/http/initialize.py +21 -28
- mindsdb/api/http/namespaces/file.py +9 -3
- mindsdb/api/http/namespaces/handlers.py +77 -87
- mindsdb/api/http/start.py +3 -2
- mindsdb/integrations/handlers/autogluon_handler/requirements.txt +1 -1
- mindsdb/integrations/handlers/autosklearn_handler/requirements.txt +1 -1
- mindsdb/integrations/handlers/flaml_handler/requirements.txt +1 -1
- mindsdb/integrations/handlers/lightfm_handler/requirements.txt +1 -1
- mindsdb/integrations/handlers/lightwood_handler/requirements.txt +4 -4
- mindsdb/integrations/handlers/tpot_handler/requirements.txt +1 -1
- mindsdb/integrations/libs/llm/config.py +15 -0
- mindsdb/integrations/libs/llm/utils.py +15 -0
- mindsdb/interfaces/agents/langchain_agent.py +4 -0
- mindsdb/interfaces/agents/providers.py +20 -0
- mindsdb/interfaces/knowledge_base/controller.py +22 -6
- mindsdb/migrations/env.py +1 -7
- mindsdb/utilities/config.py +15 -8
- mindsdb/utilities/render/sqlalchemy_render.py +7 -1
- {mindsdb-25.9.1.0.dist-info → mindsdb-25.9.1.2.dist-info}/METADATA +281 -281
- {mindsdb-25.9.1.0.dist-info → mindsdb-25.9.1.2.dist-info}/RECORD +27 -26
- {mindsdb-25.9.1.0.dist-info → mindsdb-25.9.1.2.dist-info}/WHEEL +0 -0
- {mindsdb-25.9.1.0.dist-info → mindsdb-25.9.1.2.dist-info}/licenses/LICENSE +0 -0
- {mindsdb-25.9.1.0.dist-info → mindsdb-25.9.1.2.dist-info}/top_level.txt +0 -0
mindsdb/api/http/initialize.py
CHANGED
|
@@ -46,7 +46,7 @@ from mindsdb.interfaces.jobs.jobs_controller import JobsController
|
|
|
46
46
|
from mindsdb.interfaces.storage import db
|
|
47
47
|
from mindsdb.metrics.server import init_metrics
|
|
48
48
|
from mindsdb.utilities import log
|
|
49
|
-
from mindsdb.utilities.config import
|
|
49
|
+
from mindsdb.utilities.config import config
|
|
50
50
|
from mindsdb.utilities.context import context as ctx
|
|
51
51
|
from mindsdb.utilities.json_encoder import CustomJSONProvider
|
|
52
52
|
from mindsdb.utilities.ps import is_pid_listen_port, wait_func_is_true
|
|
@@ -95,7 +95,7 @@ def custom_output_json(data, code, headers=None):
|
|
|
95
95
|
return resp
|
|
96
96
|
|
|
97
97
|
|
|
98
|
-
def get_last_compatible_gui_version() -> Version:
|
|
98
|
+
def get_last_compatible_gui_version() -> Version | bool:
|
|
99
99
|
logger.debug("Getting last compatible frontend..")
|
|
100
100
|
try:
|
|
101
101
|
res = requests.get(
|
|
@@ -164,7 +164,6 @@ def get_last_compatible_gui_version() -> Version:
|
|
|
164
164
|
|
|
165
165
|
def get_current_gui_version() -> Version:
|
|
166
166
|
logger.debug("Getting current frontend version...")
|
|
167
|
-
config = Config()
|
|
168
167
|
static_path = Path(config["paths"]["static"])
|
|
169
168
|
version_txt_path = static_path.joinpath("version.txt")
|
|
170
169
|
|
|
@@ -181,7 +180,6 @@ def get_current_gui_version() -> Version:
|
|
|
181
180
|
|
|
182
181
|
def initialize_static():
|
|
183
182
|
logger.debug("Initializing static..")
|
|
184
|
-
config = Config()
|
|
185
183
|
last_gui_version_lv = get_last_compatible_gui_version()
|
|
186
184
|
current_gui_version_lv = get_current_gui_version()
|
|
187
185
|
required_gui_version = config["gui"].get("version")
|
|
@@ -190,17 +188,18 @@ def initialize_static():
|
|
|
190
188
|
required_gui_version_lv = parse_version(required_gui_version)
|
|
191
189
|
success = True
|
|
192
190
|
if current_gui_version_lv is None or required_gui_version_lv != current_gui_version_lv:
|
|
193
|
-
logger.debug("Updating gui..")
|
|
194
191
|
success = update_static(required_gui_version_lv)
|
|
195
192
|
else:
|
|
196
193
|
if last_gui_version_lv is False:
|
|
194
|
+
logger.debug(
|
|
195
|
+
"The number of the latest version has not been determined, "
|
|
196
|
+
f"so we will continue using the current version: {current_gui_version_lv}"
|
|
197
|
+
)
|
|
197
198
|
return False
|
|
198
199
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
return True
|
|
203
|
-
logger.debug("Updating gui..")
|
|
200
|
+
if current_gui_version_lv == last_gui_version_lv:
|
|
201
|
+
logger.debug(f"The latest version is already in use: {current_gui_version_lv}")
|
|
202
|
+
return True
|
|
204
203
|
success = update_static(last_gui_version_lv)
|
|
205
204
|
|
|
206
205
|
if db.session:
|
|
@@ -208,21 +207,22 @@ def initialize_static():
|
|
|
208
207
|
return success
|
|
209
208
|
|
|
210
209
|
|
|
211
|
-
def initialize_app(
|
|
210
|
+
def initialize_app():
|
|
212
211
|
static_root = config["paths"]["static"]
|
|
213
212
|
logger.debug(f"Static route: {static_root}")
|
|
214
213
|
gui_exists = Path(static_root).joinpath("index.html").is_file()
|
|
215
214
|
logger.debug(f"Does GUI already exist.. {'YES' if gui_exists else 'NO'}")
|
|
216
215
|
init_static_thread = None
|
|
217
|
-
|
|
216
|
+
|
|
217
|
+
if config["gui"]["autoupdate"] is True or (config["gui"]["open_on_start"] is True and gui_exists is False):
|
|
218
218
|
init_static_thread = threading.Thread(target=initialize_static, name="initialize_static")
|
|
219
219
|
init_static_thread.start()
|
|
220
220
|
|
|
221
221
|
# Wait for static initialization.
|
|
222
|
-
if
|
|
222
|
+
if config["gui"]["open_on_start"] is True and init_static_thread is not None:
|
|
223
223
|
init_static_thread.join()
|
|
224
224
|
|
|
225
|
-
app, api = initialize_flask(config, init_static_thread
|
|
225
|
+
app, api = initialize_flask(config, init_static_thread)
|
|
226
226
|
Compress(app)
|
|
227
227
|
|
|
228
228
|
initialize_interfaces(app)
|
|
@@ -312,7 +312,6 @@ def initialize_app(config, no_studio):
|
|
|
312
312
|
def before_request():
|
|
313
313
|
logger.debug(f"HTTP {request.method}: {request.path}")
|
|
314
314
|
ctx.set_default()
|
|
315
|
-
config = Config()
|
|
316
315
|
|
|
317
316
|
h = request.headers.get("Authorization")
|
|
318
317
|
if not h or not h.startswith("Bearer "):
|
|
@@ -372,21 +371,18 @@ def initialize_app(config, no_studio):
|
|
|
372
371
|
return app
|
|
373
372
|
|
|
374
373
|
|
|
375
|
-
def initialize_flask(config, init_static_thread
|
|
374
|
+
def initialize_flask(config, init_static_thread):
|
|
376
375
|
logger.debug("Initializing flask..")
|
|
377
376
|
# region required for windows https://github.com/mindsdb/mindsdb/issues/2526
|
|
378
377
|
mimetypes.add_type("text/css", ".css")
|
|
379
378
|
mimetypes.add_type("text/javascript", ".js")
|
|
380
379
|
# endregion
|
|
381
380
|
|
|
382
|
-
|
|
383
|
-
if
|
|
384
|
-
static_path = os.path.join(
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
kwargs["static_url_path"] = "/static"
|
|
388
|
-
kwargs["static_folder"] = static_path
|
|
389
|
-
logger.debug(f"Static path: {static_path}")
|
|
381
|
+
static_path = os.path.join(config["paths"]["static"], "static/")
|
|
382
|
+
if os.path.isabs(static_path) is False:
|
|
383
|
+
static_path = os.path.join(os.getcwd(), static_path)
|
|
384
|
+
kwargs = {"static_url_path": "/static", "static_folder": static_path}
|
|
385
|
+
logger.debug(f"Static path: {static_path}")
|
|
390
386
|
|
|
391
387
|
app = Flask(__name__, **kwargs)
|
|
392
388
|
init_metrics(app)
|
|
@@ -416,8 +412,7 @@ def initialize_flask(config, init_static_thread, no_studio):
|
|
|
416
412
|
port = config["api"]["http"]["port"]
|
|
417
413
|
host = config["api"]["http"]["host"]
|
|
418
414
|
|
|
419
|
-
|
|
420
|
-
if not no_studio:
|
|
415
|
+
if config["gui"]["open_on_start"]:
|
|
421
416
|
if host in ("", "0.0.0.0"):
|
|
422
417
|
url = f"http://127.0.0.1:{port}/"
|
|
423
418
|
else:
|
|
@@ -441,8 +436,6 @@ def initialize_interfaces(app):
|
|
|
441
436
|
app.database_controller = DatabaseController()
|
|
442
437
|
app.file_controller = FileController()
|
|
443
438
|
app.jobs_controller = JobsController()
|
|
444
|
-
config = Config()
|
|
445
|
-
app.config_obj = config
|
|
446
439
|
|
|
447
440
|
|
|
448
441
|
def _open_webbrowser(url: str, pid: int, port: int, init_static_thread, static_folder):
|
|
@@ -3,6 +3,7 @@ import shutil
|
|
|
3
3
|
import tarfile
|
|
4
4
|
import tempfile
|
|
5
5
|
import zipfile
|
|
6
|
+
from pathlib import Path
|
|
6
7
|
from urllib.parse import urlparse
|
|
7
8
|
|
|
8
9
|
import multipart
|
|
@@ -60,7 +61,10 @@ class File(Resource):
|
|
|
60
61
|
|
|
61
62
|
def on_file(file):
|
|
62
63
|
nonlocal file_object
|
|
63
|
-
|
|
64
|
+
file_name = file.file_name.decode()
|
|
65
|
+
data["file"] = file_name
|
|
66
|
+
if Path(file_name).name != file_name:
|
|
67
|
+
raise ValueError(f"Wrong file name: {file_name}")
|
|
64
68
|
file_object = file.file_object
|
|
65
69
|
|
|
66
70
|
temp_dir_path = tempfile.mkdtemp(prefix="mindsdb_file_")
|
|
@@ -72,8 +76,9 @@ class File(Resource):
|
|
|
72
76
|
on_file=on_file,
|
|
73
77
|
config={
|
|
74
78
|
"UPLOAD_DIR": temp_dir_path.encode(), # bytes required
|
|
75
|
-
"UPLOAD_KEEP_FILENAME":
|
|
79
|
+
"UPLOAD_KEEP_FILENAME": False,
|
|
76
80
|
"UPLOAD_KEEP_EXTENSIONS": True,
|
|
81
|
+
"UPLOAD_DELETE_TMP": False,
|
|
77
82
|
"MAX_MEMORY_FILE_SIZE": 0,
|
|
78
83
|
},
|
|
79
84
|
)
|
|
@@ -93,6 +98,7 @@ class File(Resource):
|
|
|
93
98
|
except (AttributeError, ValueError, OSError):
|
|
94
99
|
logger.debug("Failed to flush file_object before closing.", exc_info=True)
|
|
95
100
|
file_object.close()
|
|
101
|
+
Path(file_object.name).rename(Path(file_object.name).parent / data["file"])
|
|
96
102
|
file_object = None
|
|
97
103
|
else:
|
|
98
104
|
data = request.json
|
|
@@ -101,7 +107,7 @@ class File(Resource):
|
|
|
101
107
|
return http_error(
|
|
102
108
|
400,
|
|
103
109
|
"File already exists",
|
|
104
|
-
f"File with name '{
|
|
110
|
+
f"File with name '{mindsdb_file_name}' already exists",
|
|
105
111
|
)
|
|
106
112
|
|
|
107
113
|
if data.get("source_type") == "url":
|
|
@@ -19,96 +19,94 @@ from mindsdb.api.http.utils import http_error
|
|
|
19
19
|
from mindsdb.api.http.namespaces.configs.handlers import ns_conf
|
|
20
20
|
from mindsdb.api.executor.controllers.session_controller import SessionController
|
|
21
21
|
from mindsdb.api.executor.command_executor import ExecuteCommands
|
|
22
|
-
from mindsdb.utilities.config import Config
|
|
23
22
|
|
|
24
23
|
|
|
25
|
-
@ns_conf.route(
|
|
24
|
+
@ns_conf.route("/")
|
|
26
25
|
class HandlersList(Resource):
|
|
27
|
-
@ns_conf.doc(
|
|
28
|
-
@api_endpoint_metrics(
|
|
26
|
+
@ns_conf.doc("handlers_list")
|
|
27
|
+
@api_endpoint_metrics("GET", "/handlers")
|
|
29
28
|
def get(self):
|
|
30
|
-
|
|
29
|
+
"""List all db handlers"""
|
|
31
30
|
|
|
32
|
-
if request.args.get(
|
|
31
|
+
if request.args.get("lazy") == "1":
|
|
33
32
|
handlers = ca.integration_controller.get_handlers_metadata()
|
|
34
33
|
else:
|
|
35
34
|
handlers = ca.integration_controller.get_handlers_import_status()
|
|
36
35
|
result = []
|
|
37
36
|
for handler_type, handler_meta in handlers.items():
|
|
38
37
|
# remove non-integration handlers
|
|
39
|
-
if handler_type not in [
|
|
40
|
-
row = {
|
|
38
|
+
if handler_type not in ["utilities", "dummy_data"]:
|
|
39
|
+
row = {"name": handler_type}
|
|
41
40
|
row.update(handler_meta)
|
|
42
|
-
del row[
|
|
41
|
+
del row["path"]
|
|
43
42
|
result.append(row)
|
|
44
43
|
return result
|
|
45
44
|
|
|
46
45
|
|
|
47
|
-
@ns_conf.route(
|
|
46
|
+
@ns_conf.route("/<handler_name>/icon")
|
|
48
47
|
class HandlerIcon(Resource):
|
|
49
|
-
@ns_conf.param(
|
|
50
|
-
@api_endpoint_metrics(
|
|
48
|
+
@ns_conf.param("handler_name", "Handler name")
|
|
49
|
+
@api_endpoint_metrics("GET", "/handlers/handler/icon")
|
|
51
50
|
def get(self, handler_name):
|
|
52
51
|
try:
|
|
53
52
|
handler_meta = ca.integration_controller.get_handlers_metadata().get(handler_name)
|
|
54
53
|
if handler_meta is None:
|
|
55
|
-
return http_error(HTTPStatus.NOT_FOUND,
|
|
56
|
-
icon_name = handler_meta[
|
|
57
|
-
handler_folder = handler_meta[
|
|
58
|
-
mindsdb_path = Path(importlib.util.find_spec(
|
|
59
|
-
icon_path = mindsdb_path.joinpath(
|
|
54
|
+
return http_error(HTTPStatus.NOT_FOUND, "Icon not found", f"Icon for {handler_name} not found")
|
|
55
|
+
icon_name = handler_meta["icon"]["name"]
|
|
56
|
+
handler_folder = handler_meta["import"]["folder"]
|
|
57
|
+
mindsdb_path = Path(importlib.util.find_spec("mindsdb").origin).parent
|
|
58
|
+
icon_path = mindsdb_path.joinpath("integrations/handlers").joinpath(handler_folder).joinpath(icon_name)
|
|
60
59
|
if icon_path.is_absolute() is False:
|
|
61
60
|
icon_path = Path(os.getcwd()).joinpath(icon_path)
|
|
62
61
|
except Exception:
|
|
63
|
-
return http_error(HTTPStatus.NOT_FOUND,
|
|
62
|
+
return http_error(HTTPStatus.NOT_FOUND, "Icon not found", f"Icon for {handler_name} not found")
|
|
64
63
|
else:
|
|
65
64
|
return send_file(icon_path)
|
|
66
65
|
|
|
67
66
|
|
|
68
|
-
@ns_conf.route(
|
|
67
|
+
@ns_conf.route("/<handler_name>")
|
|
69
68
|
class HandlerInfo(Resource):
|
|
70
|
-
@ns_conf.param(
|
|
71
|
-
@api_endpoint_metrics(
|
|
69
|
+
@ns_conf.param("handler_name", "Handler name")
|
|
70
|
+
@api_endpoint_metrics("GET", "/handlers/handler")
|
|
72
71
|
def get(self, handler_name):
|
|
73
|
-
|
|
74
72
|
handler_meta = ca.integration_controller.get_handler_meta(handler_name)
|
|
75
|
-
row = {
|
|
73
|
+
row = {"name": handler_name}
|
|
76
74
|
row.update(handler_meta)
|
|
77
|
-
del row[
|
|
78
|
-
del row[
|
|
75
|
+
del row["path"]
|
|
76
|
+
del row["icon"]
|
|
79
77
|
return row
|
|
80
78
|
|
|
81
79
|
|
|
82
|
-
@ns_conf.route(
|
|
80
|
+
@ns_conf.route("/<handler_name>/install")
|
|
83
81
|
class InstallDependencies(Resource):
|
|
84
|
-
@ns_conf.param(
|
|
85
|
-
@api_endpoint_metrics(
|
|
82
|
+
@ns_conf.param("handler_name", "Handler name")
|
|
83
|
+
@api_endpoint_metrics("POST", "/handlers/handler/install")
|
|
86
84
|
def post(self, handler_name):
|
|
87
85
|
handler_meta = ca.integration_controller.get_handler_meta(handler_name)
|
|
88
86
|
|
|
89
87
|
if handler_meta is None:
|
|
90
|
-
return f
|
|
88
|
+
return f"Unknown handler: {handler_name}", 400
|
|
91
89
|
|
|
92
|
-
if handler_meta.get(
|
|
93
|
-
return
|
|
90
|
+
if handler_meta.get("import", {}).get("success", False) is True:
|
|
91
|
+
return "Installed", 200
|
|
94
92
|
|
|
95
|
-
dependencies = handler_meta[
|
|
93
|
+
dependencies = handler_meta["import"]["dependencies"]
|
|
96
94
|
if len(dependencies) == 0:
|
|
97
|
-
return
|
|
95
|
+
return "Installed", 200
|
|
98
96
|
|
|
99
97
|
result = install_dependencies(dependencies)
|
|
100
98
|
|
|
101
99
|
# reload it if any result, so we can get new error message
|
|
102
100
|
ca.integration_controller.reload_handler_module(handler_name)
|
|
103
|
-
if result.get(
|
|
101
|
+
if result.get("success") is True:
|
|
104
102
|
# If warm processes are available in the cache, remove them.
|
|
105
103
|
# This will force a new process to be created with the installed dependencies.
|
|
106
104
|
process_cache.remove_processes_for_handler(handler_name)
|
|
107
|
-
return
|
|
105
|
+
return "", 200
|
|
108
106
|
return http_error(
|
|
109
107
|
500,
|
|
110
|
-
f
|
|
111
|
-
result.get(
|
|
108
|
+
f"Failed to install dependencies for {handler_meta.get('title', handler_name)}",
|
|
109
|
+
result.get("error_message", "unknown error"),
|
|
112
110
|
)
|
|
113
111
|
|
|
114
112
|
|
|
@@ -122,24 +120,24 @@ def prepare_formdata():
|
|
|
122
120
|
params[name] = value
|
|
123
121
|
|
|
124
122
|
def on_file(file):
|
|
125
|
-
|
|
126
|
-
|
|
123
|
+
file_name = file.field_name.decode()
|
|
124
|
+
if file_name not in ("code", "modules"):
|
|
125
|
+
raise ValueError(f"Wrong field name: {file_name}")
|
|
126
|
+
params[file_name] = file.file_object
|
|
127
|
+
file_names.append(file_name)
|
|
127
128
|
|
|
128
|
-
temp_dir_path =
|
|
129
|
-
prefix='mindsdb_byom_file_',
|
|
130
|
-
dir=Config().paths['tmp']
|
|
131
|
-
)
|
|
129
|
+
temp_dir_path = tempfile.mkdtemp(prefix="mindsdb_file_")
|
|
132
130
|
|
|
133
131
|
parser = multipart.create_form_parser(
|
|
134
132
|
headers=request.headers,
|
|
135
133
|
on_field=on_field,
|
|
136
134
|
on_file=on_file,
|
|
137
135
|
config={
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
}
|
|
136
|
+
"UPLOAD_DIR": temp_dir_path.encode(), # bytes required
|
|
137
|
+
"UPLOAD_KEEP_FILENAME": True,
|
|
138
|
+
"UPLOAD_KEEP_EXTENSIONS": True,
|
|
139
|
+
"MAX_MEMORY_FILE_SIZE": float("inf"),
|
|
140
|
+
},
|
|
143
141
|
)
|
|
144
142
|
|
|
145
143
|
while True:
|
|
@@ -151,32 +149,33 @@ def prepare_formdata():
|
|
|
151
149
|
parser.close()
|
|
152
150
|
|
|
153
151
|
for file_name in file_names:
|
|
152
|
+
file_path = os.path.join(temp_dir_path, file_name)
|
|
153
|
+
with open(file_path, "wb") as f:
|
|
154
|
+
params[file_name].seek(0)
|
|
155
|
+
f.write(params[file_name].read())
|
|
154
156
|
params[file_name].close()
|
|
157
|
+
params[file_name] = file_path
|
|
155
158
|
|
|
156
159
|
return params
|
|
157
160
|
|
|
158
161
|
|
|
159
|
-
@ns_conf.route(
|
|
160
|
-
@ns_conf.param(
|
|
162
|
+
@ns_conf.route("/byom/<name>")
|
|
163
|
+
@ns_conf.param("name", "Name of the model")
|
|
161
164
|
class BYOMUpload(Resource):
|
|
162
|
-
@ns_conf.doc(
|
|
163
|
-
@api_endpoint_metrics(
|
|
165
|
+
@ns_conf.doc("post_file")
|
|
166
|
+
@api_endpoint_metrics("POST", "/handlers/byom/handler")
|
|
164
167
|
def post(self, name):
|
|
165
168
|
params = prepare_formdata()
|
|
166
169
|
|
|
167
|
-
code_file_path = params[
|
|
170
|
+
code_file_path = params["code"]
|
|
168
171
|
try:
|
|
169
|
-
module_file_path = params[
|
|
172
|
+
module_file_path = params["modules"]
|
|
170
173
|
except AttributeError:
|
|
171
|
-
module_file_path = Path(code_file_path).parent /
|
|
174
|
+
module_file_path = Path(code_file_path).parent / "requirements.txt"
|
|
172
175
|
module_file_path.touch()
|
|
173
176
|
module_file_path = str(module_file_path)
|
|
174
177
|
|
|
175
|
-
connection_args = {
|
|
176
|
-
'code': code_file_path,
|
|
177
|
-
'modules': module_file_path,
|
|
178
|
-
'type': params.get('type')
|
|
179
|
-
}
|
|
178
|
+
connection_args = {"code": code_file_path, "modules": module_file_path, "type": params.get("type")}
|
|
180
179
|
|
|
181
180
|
session = SessionController()
|
|
182
181
|
|
|
@@ -185,48 +184,39 @@ class BYOMUpload(Resource):
|
|
|
185
184
|
|
|
186
185
|
engine_storage = HandlerStorage(base_ml_handler.integration_id)
|
|
187
186
|
|
|
188
|
-
engine_versions = [
|
|
189
|
-
int(x) for x in engine_storage.get_connection_args()['versions'].keys()
|
|
190
|
-
]
|
|
187
|
+
engine_versions = [int(x) for x in engine_storage.get_connection_args()["versions"].keys()]
|
|
191
188
|
|
|
192
|
-
return {
|
|
193
|
-
'last_engine_version': max(engine_versions),
|
|
194
|
-
'engine_versions': engine_versions
|
|
195
|
-
}
|
|
189
|
+
return {"last_engine_version": max(engine_versions), "engine_versions": engine_versions}
|
|
196
190
|
|
|
197
|
-
@ns_conf.doc(
|
|
198
|
-
@api_endpoint_metrics(
|
|
191
|
+
@ns_conf.doc("put_file")
|
|
192
|
+
@api_endpoint_metrics("PUT", "/handlers/byom/handler")
|
|
199
193
|
def put(self, name):
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
194
|
+
"""upload new model
|
|
195
|
+
params in FormData:
|
|
196
|
+
- code
|
|
197
|
+
- modules
|
|
198
|
+
"""
|
|
205
199
|
|
|
206
200
|
params = prepare_formdata()
|
|
207
201
|
|
|
208
|
-
code_file_path = params[
|
|
202
|
+
code_file_path = params["code"]
|
|
209
203
|
try:
|
|
210
|
-
module_file_path = params[
|
|
204
|
+
module_file_path = params["modules"]
|
|
211
205
|
except KeyError:
|
|
212
|
-
module_file_path = Path(code_file_path).parent /
|
|
206
|
+
module_file_path = Path(code_file_path).parent / "requirements.txt"
|
|
213
207
|
module_file_path.touch()
|
|
214
208
|
module_file_path = str(module_file_path)
|
|
215
209
|
|
|
216
210
|
connection_args = {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
211
|
+
"code": code_file_path,
|
|
212
|
+
"modules": module_file_path,
|
|
213
|
+
"mode": params.get("mode"),
|
|
214
|
+
"type": params.get("type"),
|
|
221
215
|
}
|
|
222
216
|
|
|
223
|
-
ast_query = CreateMLEngine(
|
|
224
|
-
name=Identifier(name),
|
|
225
|
-
handler='byom',
|
|
226
|
-
params=connection_args
|
|
227
|
-
)
|
|
217
|
+
ast_query = CreateMLEngine(name=Identifier(name), handler="byom", params=connection_args)
|
|
228
218
|
sql_session = SessionController()
|
|
229
219
|
command_executor = ExecuteCommands(sql_session)
|
|
230
220
|
command_executor.execute_command(ast_query)
|
|
231
221
|
|
|
232
|
-
return
|
|
222
|
+
return "", 200
|
mindsdb/api/http/start.py
CHANGED
|
@@ -26,15 +26,16 @@ gc.enable()
|
|
|
26
26
|
logger = log.getLogger(__name__)
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
def start(verbose,
|
|
29
|
+
def start(verbose, app: Flask = None):
|
|
30
30
|
db.init()
|
|
31
31
|
init_lexer_parsers()
|
|
32
32
|
|
|
33
33
|
if app is None:
|
|
34
|
-
app = initialize_app(
|
|
34
|
+
app = initialize_app()
|
|
35
35
|
|
|
36
36
|
port = config["api"]["http"]["port"]
|
|
37
37
|
host = config["api"]["http"]["host"]
|
|
38
|
+
|
|
38
39
|
process_cache.init()
|
|
39
40
|
|
|
40
41
|
routes = []
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
autogluon
|
|
2
|
-
type_infer==0.0.
|
|
2
|
+
type_infer==0.0.25
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
auto-sklearn
|
|
2
|
-
type_infer==0.0.
|
|
2
|
+
type_infer==0.0.25
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
flaml<=1.2.3
|
|
2
|
-
type_infer==0.0.
|
|
2
|
+
type_infer==0.0.25
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
lightfm==1.17
|
|
2
|
-
dataprep_ml==
|
|
2
|
+
dataprep_ml==0.0.25
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
lightwood>=25.
|
|
2
|
-
lightwood[extra]>=25.
|
|
3
|
-
lightwood[xai]>=25.
|
|
4
|
-
type_infer==0.0.
|
|
1
|
+
lightwood>=25.9.1.0
|
|
2
|
+
lightwood[extra]>=25.9.1.0
|
|
3
|
+
lightwood[xai]>=25.9.1.0
|
|
4
|
+
type_infer==0.0.25
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
tpot<=0.11.7
|
|
2
|
-
type_infer==0.0.
|
|
2
|
+
type_infer==0.0.25
|
|
@@ -113,3 +113,18 @@ class WriterConfig(BaseLLMConfig):
|
|
|
113
113
|
writer_api_key: Optional[str] = Field(default=None)
|
|
114
114
|
writer_org_id: Optional[str] = Field(default=None)
|
|
115
115
|
base_url: Optional[str] = Field(default=None)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
# https://api.python.langchain.com/en/latest/llms/langchain_aws.llms.bedrock.BedrockLLM.html#langchain_aws.llms.bedrock.BedrockLLM
|
|
119
|
+
class BedrockConfig(BaseLLMConfig):
|
|
120
|
+
model_id: str
|
|
121
|
+
aws_access_key_id: Optional[str] = Field(default=None)
|
|
122
|
+
aws_secret_access_key: Optional[str] = Field(default=None)
|
|
123
|
+
aws_session_token: Optional[str] = Field(default=None)
|
|
124
|
+
region_name: Optional[str] = Field(default=None)
|
|
125
|
+
credentials_profile_name: Optional[str] = Field(default=None)
|
|
126
|
+
endpoint_url: Optional[str] = Field(default=None)
|
|
127
|
+
stop: Optional[List[str]] = Field(default=None)
|
|
128
|
+
temperature: Optional[float] = Field(default=0.7)
|
|
129
|
+
max_tokens: Optional[int] = Field(default=None)
|
|
130
|
+
model_kwargs: Optional[Dict[str, Any]] = Field(default=None)
|
|
@@ -16,6 +16,7 @@ from mindsdb.integrations.libs.llm.config import (
|
|
|
16
16
|
NvidiaNIMConfig,
|
|
17
17
|
MindsdbConfig,
|
|
18
18
|
WriterConfig,
|
|
19
|
+
BedrockConfig,
|
|
19
20
|
)
|
|
20
21
|
from mindsdb.utilities.config import config
|
|
21
22
|
from langchain_text_splitters import Language, RecursiveCharacterTextSplitter
|
|
@@ -222,6 +223,20 @@ def get_llm_config(provider: str, args: Dict) -> BaseLLMConfig:
|
|
|
222
223
|
writer_org_id=args.get("writer_org_id", None),
|
|
223
224
|
base_url=args.get("base_url", None),
|
|
224
225
|
)
|
|
226
|
+
if provider == "bedrock":
|
|
227
|
+
return BedrockConfig(
|
|
228
|
+
model_id=args.get("model_name"),
|
|
229
|
+
temperature=temperature,
|
|
230
|
+
max_tokens=args.get("max_tokens", None),
|
|
231
|
+
stop=args.get("stop", None),
|
|
232
|
+
base_url=args.get("endpoint_url", None),
|
|
233
|
+
aws_access_key_id=args.get("aws_access_key_id", None),
|
|
234
|
+
aws_secret_access_key=args.get("aws_secret_access_key", None),
|
|
235
|
+
aws_session_token=args.get("aws_session_token", None),
|
|
236
|
+
region_name=args.get("aws_region_name", None),
|
|
237
|
+
credentials_profile_name=args.get("credentials_profile_name", None),
|
|
238
|
+
model_kwargs=args.get("model_kwargs", None),
|
|
239
|
+
)
|
|
225
240
|
|
|
226
241
|
raise ValueError(f"Provider {provider} is not supported.")
|
|
227
242
|
|
|
@@ -40,6 +40,7 @@ from .mindsdb_chat_model import ChatMindsdb
|
|
|
40
40
|
from .callback_handlers import LogCallbackHandler, ContextCaptureCallback
|
|
41
41
|
from .langfuse_callback_handler import LangfuseCallbackHandler, get_skills
|
|
42
42
|
from .safe_output_parser import SafeOutputParser
|
|
43
|
+
from .providers import get_bedrock_chat_model
|
|
43
44
|
|
|
44
45
|
from mindsdb.interfaces.agents.constants import (
|
|
45
46
|
OPEN_AI_CHAT_MODELS,
|
|
@@ -176,6 +177,9 @@ def create_chat_model(args: Dict):
|
|
|
176
177
|
return ChatGoogleGenerativeAI(**model_kwargs)
|
|
177
178
|
if args["provider"] == "writer":
|
|
178
179
|
return ChatWriter(**model_kwargs)
|
|
180
|
+
if args["provider"] == "bedrock":
|
|
181
|
+
ChatBedrock = get_bedrock_chat_model()
|
|
182
|
+
return ChatBedrock(**model_kwargs)
|
|
179
183
|
if args["provider"] == "mindsdb":
|
|
180
184
|
return ChatMindsdb(**model_kwargs)
|
|
181
185
|
raise ValueError(f"Unknown provider: {args['provider']}")
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import importlib.util
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def get_bedrock_chat_model():
|
|
5
|
+
try:
|
|
6
|
+
from langchain_aws.chat_models import ChatBedrock
|
|
7
|
+
except ModuleNotFoundError:
|
|
8
|
+
raise RuntimeError("bedrock connector is not installed. Please install it with `pip install langchain-aws`")
|
|
9
|
+
|
|
10
|
+
if not importlib.util.find_spec("transformers"):
|
|
11
|
+
raise RuntimeError(
|
|
12
|
+
"`transformers` module is required for bedrock to count tokens. Please install it with `pip install transformers`"
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
class ChatBedrockPatched(ChatBedrock):
|
|
16
|
+
def _prepare_input_and_invoke(self, *args, **kwargs):
|
|
17
|
+
kwargs.pop("stop_sequences", None)
|
|
18
|
+
return super()._prepare_input_and_invoke(*args, **kwargs)
|
|
19
|
+
|
|
20
|
+
return ChatBedrockPatched
|