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.

Files changed (27) hide show
  1. mindsdb/__about__.py +1 -1
  2. mindsdb/__main__.py +1 -1
  3. mindsdb/api/executor/utilities/mysql_to_duckdb_functions.py +466 -18
  4. mindsdb/api/executor/utilities/sql.py +9 -31
  5. mindsdb/api/http/initialize.py +21 -28
  6. mindsdb/api/http/namespaces/file.py +9 -3
  7. mindsdb/api/http/namespaces/handlers.py +77 -87
  8. mindsdb/api/http/start.py +3 -2
  9. mindsdb/integrations/handlers/autogluon_handler/requirements.txt +1 -1
  10. mindsdb/integrations/handlers/autosklearn_handler/requirements.txt +1 -1
  11. mindsdb/integrations/handlers/flaml_handler/requirements.txt +1 -1
  12. mindsdb/integrations/handlers/lightfm_handler/requirements.txt +1 -1
  13. mindsdb/integrations/handlers/lightwood_handler/requirements.txt +4 -4
  14. mindsdb/integrations/handlers/tpot_handler/requirements.txt +1 -1
  15. mindsdb/integrations/libs/llm/config.py +15 -0
  16. mindsdb/integrations/libs/llm/utils.py +15 -0
  17. mindsdb/interfaces/agents/langchain_agent.py +4 -0
  18. mindsdb/interfaces/agents/providers.py +20 -0
  19. mindsdb/interfaces/knowledge_base/controller.py +22 -6
  20. mindsdb/migrations/env.py +1 -7
  21. mindsdb/utilities/config.py +15 -8
  22. mindsdb/utilities/render/sqlalchemy_render.py +7 -1
  23. {mindsdb-25.9.1.0.dist-info → mindsdb-25.9.1.2.dist-info}/METADATA +281 -281
  24. {mindsdb-25.9.1.0.dist-info → mindsdb-25.9.1.2.dist-info}/RECORD +27 -26
  25. {mindsdb-25.9.1.0.dist-info → mindsdb-25.9.1.2.dist-info}/WHEEL +0 -0
  26. {mindsdb-25.9.1.0.dist-info → mindsdb-25.9.1.2.dist-info}/licenses/LICENSE +0 -0
  27. {mindsdb-25.9.1.0.dist-info → mindsdb-25.9.1.2.dist-info}/top_level.txt +0 -0
@@ -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 Config
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
- # ignore versions like '23.9.2.2'
200
- if current_gui_version_lv is not None and len(current_gui_version_lv.release) < 3:
201
- if current_gui_version_lv == last_gui_version_lv:
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(config, no_studio):
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
- if no_studio is False and (config["gui"]["autoupdate"] is True or gui_exists is False):
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 not no_studio and init_static_thread is not None:
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, no_studio)
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, no_studio):
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
- kwargs = {}
383
- if no_studio is not True:
384
- static_path = os.path.join(config["paths"]["static"], "static/")
385
- if os.path.isabs(static_path) is False:
386
- static_path = os.path.join(os.getcwd(), static_path)
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
- # NOTE rewrite it, that hotfix to see GUI link
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
- data["file"] = file.file_name.decode()
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": True,
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 '{data['file']}' already exists",
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('handlers_list')
28
- @api_endpoint_metrics('GET', '/handlers')
26
+ @ns_conf.doc("handlers_list")
27
+ @api_endpoint_metrics("GET", "/handlers")
29
28
  def get(self):
30
- '''List all db handlers'''
29
+ """List all db handlers"""
31
30
 
32
- if request.args.get('lazy') == '1':
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 ['utilities', 'dummy_data']:
40
- row = {'name': handler_type}
38
+ if handler_type not in ["utilities", "dummy_data"]:
39
+ row = {"name": handler_type}
41
40
  row.update(handler_meta)
42
- del row['path']
41
+ del row["path"]
43
42
  result.append(row)
44
43
  return result
45
44
 
46
45
 
47
- @ns_conf.route('/<handler_name>/icon')
46
+ @ns_conf.route("/<handler_name>/icon")
48
47
  class HandlerIcon(Resource):
49
- @ns_conf.param('handler_name', 'Handler name')
50
- @api_endpoint_metrics('GET', '/handlers/handler/icon')
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, 'Icon not found', f'Icon for {handler_name} not found')
56
- icon_name = handler_meta['icon']['name']
57
- handler_folder = handler_meta['import']['folder']
58
- mindsdb_path = Path(importlib.util.find_spec('mindsdb').origin).parent
59
- icon_path = mindsdb_path.joinpath('integrations/handlers').joinpath(handler_folder).joinpath(icon_name)
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, 'Icon not found', f'Icon for {handler_name} 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('/<handler_name>')
67
+ @ns_conf.route("/<handler_name>")
69
68
  class HandlerInfo(Resource):
70
- @ns_conf.param('handler_name', 'Handler name')
71
- @api_endpoint_metrics('GET', '/handlers/handler')
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 = {'name': handler_name}
73
+ row = {"name": handler_name}
76
74
  row.update(handler_meta)
77
- del row['path']
78
- del row['icon']
75
+ del row["path"]
76
+ del row["icon"]
79
77
  return row
80
78
 
81
79
 
82
- @ns_conf.route('/<handler_name>/install')
80
+ @ns_conf.route("/<handler_name>/install")
83
81
  class InstallDependencies(Resource):
84
- @ns_conf.param('handler_name', 'Handler name')
85
- @api_endpoint_metrics('POST', '/handlers/handler/install')
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'Unknown handler: {handler_name}', 400
88
+ return f"Unknown handler: {handler_name}", 400
91
89
 
92
- if handler_meta.get('import', {}).get('success', False) is True:
93
- return 'Installed', 200
90
+ if handler_meta.get("import", {}).get("success", False) is True:
91
+ return "Installed", 200
94
92
 
95
- dependencies = handler_meta['import']['dependencies']
93
+ dependencies = handler_meta["import"]["dependencies"]
96
94
  if len(dependencies) == 0:
97
- return 'Installed', 200
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('success') is True:
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 '', 200
105
+ return "", 200
108
106
  return http_error(
109
107
  500,
110
- f'Failed to install dependencies for {handler_meta.get("title", handler_name)}',
111
- result.get('error_message', 'unknown error')
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
- params[file.field_name.decode()] = file.file_object
126
- file_names.append(file.field_name.decode())
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 = temp_dir_path = tempfile.mkdtemp(
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
- 'UPLOAD_DIR': temp_dir_path.encode(), # bytes required
139
- 'UPLOAD_KEEP_FILENAME': True,
140
- 'UPLOAD_KEEP_EXTENSIONS': True,
141
- 'MAX_MEMORY_FILE_SIZE': 0
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('/byom/<name>')
160
- @ns_conf.param('name', "Name of the model")
162
+ @ns_conf.route("/byom/<name>")
163
+ @ns_conf.param("name", "Name of the model")
161
164
  class BYOMUpload(Resource):
162
- @ns_conf.doc('post_file')
163
- @api_endpoint_metrics('POST', '/handlers/byom/handler')
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['code'].name.decode()
170
+ code_file_path = params["code"]
168
171
  try:
169
- module_file_path = params['modules'].name.decode()
172
+ module_file_path = params["modules"]
170
173
  except AttributeError:
171
- module_file_path = Path(code_file_path).parent / 'requirements.txt'
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('put_file')
198
- @api_endpoint_metrics('PUT', '/handlers/byom/handler')
191
+ @ns_conf.doc("put_file")
192
+ @api_endpoint_metrics("PUT", "/handlers/byom/handler")
199
193
  def put(self, name):
200
- ''' upload new model
201
- params in FormData:
202
- - code
203
- - modules
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['code'].name.decode()
202
+ code_file_path = params["code"]
209
203
  try:
210
- module_file_path = params['modules'].name.decode()
204
+ module_file_path = params["modules"]
211
205
  except KeyError:
212
- module_file_path = Path(code_file_path).parent / 'requirements.txt'
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
- 'code': code_file_path,
218
- 'modules': module_file_path,
219
- 'mode': params.get('mode'),
220
- 'type': params.get('type')
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 '', 200
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, no_studio, app: Flask = None):
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(config, no_studio)
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.23
2
+ type_infer==0.0.25
@@ -1,2 +1,2 @@
1
1
  auto-sklearn
2
- type_infer==0.0.23
2
+ type_infer==0.0.25
@@ -1,2 +1,2 @@
1
1
  flaml<=1.2.3
2
- type_infer==0.0.23
2
+ type_infer==0.0.25
@@ -1,2 +1,2 @@
1
1
  lightfm==1.17
2
- dataprep_ml==24.5.1.2
2
+ dataprep_ml==0.0.25
@@ -1,4 +1,4 @@
1
- lightwood>=25.7.5.1
2
- lightwood[extra]>=25.7.5.1
3
- lightwood[xai]>=25.7.5.1
4
- type_infer==0.0.23
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.23
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