MindsDB 25.4.3.2__py3-none-any.whl → 25.4.5.0__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 +18 -4
- mindsdb/api/executor/command_executor.py +12 -2
- mindsdb/api/executor/data_types/response_type.py +1 -0
- mindsdb/api/executor/datahub/classes/tables_row.py +3 -10
- mindsdb/api/executor/datahub/datanodes/datanode.py +7 -2
- mindsdb/api/executor/datahub/datanodes/information_schema_datanode.py +44 -10
- mindsdb/api/executor/datahub/datanodes/integration_datanode.py +57 -38
- mindsdb/api/executor/datahub/datanodes/mindsdb_tables.py +2 -1
- mindsdb/api/executor/datahub/datanodes/project_datanode.py +39 -7
- mindsdb/api/executor/datahub/datanodes/system_tables.py +116 -109
- mindsdb/api/executor/planner/query_plan.py +1 -0
- mindsdb/api/executor/planner/query_planner.py +15 -1
- mindsdb/api/executor/planner/steps.py +8 -2
- mindsdb/api/executor/sql_query/sql_query.py +24 -8
- mindsdb/api/executor/sql_query/steps/apply_predictor_step.py +25 -8
- mindsdb/api/executor/sql_query/steps/fetch_dataframe_partition.py +4 -2
- mindsdb/api/executor/sql_query/steps/insert_step.py +2 -1
- mindsdb/api/executor/sql_query/steps/prepare_steps.py +2 -3
- mindsdb/api/http/namespaces/config.py +19 -11
- mindsdb/api/litellm/start.py +82 -0
- mindsdb/api/mysql/mysql_proxy/libs/constants/mysql.py +133 -0
- mindsdb/integrations/handlers/chromadb_handler/chromadb_handler.py +7 -2
- mindsdb/integrations/handlers/chromadb_handler/settings.py +1 -0
- mindsdb/integrations/handlers/mssql_handler/mssql_handler.py +13 -4
- mindsdb/integrations/handlers/mysql_handler/mysql_handler.py +14 -5
- mindsdb/integrations/handlers/openai_handler/helpers.py +3 -5
- mindsdb/integrations/handlers/openai_handler/openai_handler.py +20 -8
- mindsdb/integrations/handlers/oracle_handler/oracle_handler.py +14 -4
- mindsdb/integrations/handlers/pgvector_handler/pgvector_handler.py +34 -19
- mindsdb/integrations/handlers/postgres_handler/postgres_handler.py +21 -18
- mindsdb/integrations/handlers/snowflake_handler/snowflake_handler.py +14 -4
- mindsdb/integrations/handlers/togetherai_handler/__about__.py +9 -0
- mindsdb/integrations/handlers/togetherai_handler/__init__.py +20 -0
- mindsdb/integrations/handlers/togetherai_handler/creation_args.py +14 -0
- mindsdb/integrations/handlers/togetherai_handler/icon.svg +15 -0
- mindsdb/integrations/handlers/togetherai_handler/model_using_args.py +5 -0
- mindsdb/integrations/handlers/togetherai_handler/requirements.txt +2 -0
- mindsdb/integrations/handlers/togetherai_handler/settings.py +33 -0
- mindsdb/integrations/handlers/togetherai_handler/togetherai_handler.py +234 -0
- mindsdb/integrations/handlers/web_handler/urlcrawl_helpers.py +1 -1
- mindsdb/integrations/libs/response.py +80 -32
- mindsdb/integrations/utilities/handler_utils.py +4 -0
- mindsdb/integrations/utilities/rag/rerankers/base_reranker.py +360 -0
- mindsdb/integrations/utilities/rag/rerankers/reranker_compressor.py +8 -153
- mindsdb/interfaces/agents/litellm_server.py +345 -0
- mindsdb/interfaces/agents/mcp_client_agent.py +252 -0
- mindsdb/interfaces/agents/run_mcp_agent.py +205 -0
- mindsdb/interfaces/functions/controller.py +3 -2
- mindsdb/interfaces/knowledge_base/controller.py +106 -82
- mindsdb/interfaces/query_context/context_controller.py +55 -15
- mindsdb/interfaces/query_context/query_task.py +19 -0
- mindsdb/interfaces/skills/skill_tool.py +7 -1
- mindsdb/interfaces/skills/sql_agent.py +8 -3
- mindsdb/interfaces/storage/db.py +2 -2
- mindsdb/interfaces/tasks/task_monitor.py +5 -1
- mindsdb/interfaces/tasks/task_thread.py +6 -0
- mindsdb/migrations/versions/2025-04-22_53502b6d63bf_query_database.py +27 -0
- mindsdb/utilities/config.py +20 -2
- mindsdb/utilities/context.py +1 -0
- mindsdb/utilities/starters.py +7 -0
- {mindsdb-25.4.3.2.dist-info → mindsdb-25.4.5.0.dist-info}/METADATA +226 -221
- {mindsdb-25.4.3.2.dist-info → mindsdb-25.4.5.0.dist-info}/RECORD +67 -53
- {mindsdb-25.4.3.2.dist-info → mindsdb-25.4.5.0.dist-info}/WHEEL +1 -1
- mindsdb/integrations/handlers/snowflake_handler/tests/test_snowflake_handler.py +0 -230
- /mindsdb/{integrations/handlers/snowflake_handler/tests → api/litellm}/__init__.py +0 -0
- {mindsdb-25.4.3.2.dist-info → mindsdb-25.4.5.0.dist-info}/licenses/LICENSE +0 -0
- {mindsdb-25.4.3.2.dist-info → mindsdb-25.4.5.0.dist-info}/top_level.txt +0 -0
|
@@ -15,6 +15,7 @@ from mindsdb.utilities.cache import get_cache
|
|
|
15
15
|
|
|
16
16
|
from mindsdb.interfaces.storage import db
|
|
17
17
|
from mindsdb.utilities.context import context as ctx
|
|
18
|
+
from mindsdb.utilities.config import config
|
|
18
19
|
|
|
19
20
|
from .last_query import LastQuery
|
|
20
21
|
|
|
@@ -24,9 +25,12 @@ class RunningQuery:
|
|
|
24
25
|
Query in progres
|
|
25
26
|
"""
|
|
26
27
|
|
|
28
|
+
OBJECT_TYPE = 'query'
|
|
29
|
+
|
|
27
30
|
def __init__(self, record: db.Queries):
|
|
28
31
|
self.record = record
|
|
29
32
|
self.sql = record.sql
|
|
33
|
+
self.database = record.database or config.get('default_project')
|
|
30
34
|
|
|
31
35
|
def get_partition_query(self, step_num: int, query: Select) -> Select:
|
|
32
36
|
"""
|
|
@@ -67,6 +71,44 @@ class RunningQuery:
|
|
|
67
71
|
|
|
68
72
|
return query
|
|
69
73
|
|
|
74
|
+
def get_info(self):
|
|
75
|
+
record = self.record
|
|
76
|
+
return {
|
|
77
|
+
'id': record.id,
|
|
78
|
+
'sql': record.sql,
|
|
79
|
+
'database': record.database,
|
|
80
|
+
'started_at': record.started_at,
|
|
81
|
+
'finished_at': record.finished_at,
|
|
82
|
+
'parameters': record.parameters,
|
|
83
|
+
'context': record.context,
|
|
84
|
+
'processed_rows': record.processed_rows,
|
|
85
|
+
'error': record.error,
|
|
86
|
+
'updated_at': record.updated_at,
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
def add_to_task(self):
|
|
90
|
+
|
|
91
|
+
task_record = db.Tasks(
|
|
92
|
+
company_id=ctx.company_id,
|
|
93
|
+
user_class=ctx.user_class,
|
|
94
|
+
|
|
95
|
+
object_type=self.OBJECT_TYPE,
|
|
96
|
+
object_id=self.record.id,
|
|
97
|
+
)
|
|
98
|
+
db.session.add(task_record)
|
|
99
|
+
db.session.commit()
|
|
100
|
+
|
|
101
|
+
def remove_from_task(self):
|
|
102
|
+
task = db.Tasks.query.filter(
|
|
103
|
+
db.Tasks.object_type == self.OBJECT_TYPE,
|
|
104
|
+
db.Tasks.object_id == self.record.id,
|
|
105
|
+
db.Tasks.company_id == ctx.company_id,
|
|
106
|
+
).first()
|
|
107
|
+
|
|
108
|
+
if task is not None:
|
|
109
|
+
db.session.delete(task)
|
|
110
|
+
db.session.commit()
|
|
111
|
+
|
|
70
112
|
def set_params(self, params: dict):
|
|
71
113
|
"""
|
|
72
114
|
Store parameters of the step which is about to be split into partitions
|
|
@@ -126,14 +168,21 @@ class RunningQuery:
|
|
|
126
168
|
|
|
127
169
|
db.session.commit()
|
|
128
170
|
|
|
129
|
-
def
|
|
171
|
+
def mark_as_run(self):
|
|
130
172
|
"""
|
|
131
|
-
|
|
173
|
+
Mark query as running and reset error of the query
|
|
132
174
|
"""
|
|
175
|
+
if self.record.finished_at is not None:
|
|
176
|
+
raise RuntimeError('The query already finished')
|
|
133
177
|
|
|
134
|
-
if self.record.
|
|
178
|
+
if self.record.started_at is None:
|
|
179
|
+
self.record.started_at = dt.datetime.now()
|
|
180
|
+
db.session.commit()
|
|
181
|
+
elif self.record.error is not None:
|
|
135
182
|
self.record.error = None
|
|
136
183
|
db.session.commit()
|
|
184
|
+
else:
|
|
185
|
+
raise RuntimeError('The query might be running already')
|
|
137
186
|
|
|
138
187
|
def get_state(self) -> dict:
|
|
139
188
|
"""
|
|
@@ -448,7 +497,7 @@ class QueryContextController:
|
|
|
448
497
|
raise RuntimeError(f'Query not found: {query_id}')
|
|
449
498
|
return RunningQuery(rec)
|
|
450
499
|
|
|
451
|
-
def create_query(self, query: ASTNode) -> RunningQuery:
|
|
500
|
+
def create_query(self, query: ASTNode, database: str = None) -> RunningQuery:
|
|
452
501
|
"""
|
|
453
502
|
Create a new running query from AST query
|
|
454
503
|
"""
|
|
@@ -463,6 +512,7 @@ class QueryContextController:
|
|
|
463
512
|
|
|
464
513
|
rec = db.Queries(
|
|
465
514
|
sql=str(query),
|
|
515
|
+
database=database,
|
|
466
516
|
company_id=ctx.company_id,
|
|
467
517
|
)
|
|
468
518
|
|
|
@@ -479,17 +529,7 @@ class QueryContextController:
|
|
|
479
529
|
db.Queries.company_id == ctx.company_id
|
|
480
530
|
)
|
|
481
531
|
return [
|
|
482
|
-
|
|
483
|
-
'id': record.id,
|
|
484
|
-
'sql': record.sql,
|
|
485
|
-
'started_at': record.started_at,
|
|
486
|
-
'finished_at': record.finished_at,
|
|
487
|
-
'parameters': record.parameters,
|
|
488
|
-
'context': record.context,
|
|
489
|
-
'processed_rows': record.processed_rows,
|
|
490
|
-
'error': record.error,
|
|
491
|
-
'updated_at': record.updated_at,
|
|
492
|
-
}
|
|
532
|
+
RunningQuery(record).get_info()
|
|
493
533
|
for record in query
|
|
494
534
|
]
|
|
495
535
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from mindsdb.api.executor.sql_query import SQLQuery
|
|
2
|
+
from mindsdb.interfaces.query_context.context_controller import query_context_controller
|
|
3
|
+
from mindsdb.api.executor.controllers.session_controller import SessionController
|
|
4
|
+
from mindsdb.interfaces.tasks.task import BaseTask
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class QueryTask(BaseTask):
|
|
8
|
+
def __init__(self, *args, **kwargs):
|
|
9
|
+
super().__init__(*args, **kwargs)
|
|
10
|
+
self.query_id = self.object_id
|
|
11
|
+
|
|
12
|
+
def run(self, stop_event):
|
|
13
|
+
|
|
14
|
+
try:
|
|
15
|
+
session = SessionController()
|
|
16
|
+
SQLQuery(None, query_id=self.query_id, session=session, stop_event=stop_event)
|
|
17
|
+
finally:
|
|
18
|
+
# clear task
|
|
19
|
+
query_context_controller.get_query(self.query_id).remove_from_task()
|
|
@@ -243,7 +243,13 @@ class SkillToolController:
|
|
|
243
243
|
kb_table = session_controller.kb_controller.get_table(knowledge_base_name, skill.project_id)
|
|
244
244
|
|
|
245
245
|
res = kb_table.select_query(query)
|
|
246
|
-
|
|
246
|
+
# Handle both chunk_content and content column names
|
|
247
|
+
if hasattr(res, 'chunk_content'):
|
|
248
|
+
return '\n'.join(res.chunk_content)
|
|
249
|
+
elif hasattr(res, 'content'):
|
|
250
|
+
return '\n'.join(res.content)
|
|
251
|
+
else:
|
|
252
|
+
return "No content or chunk_content found in knowledge base response"
|
|
247
253
|
|
|
248
254
|
return _answer_question
|
|
249
255
|
|
|
@@ -12,6 +12,7 @@ from mindsdb_sql_parser.ast import Select, Show, Describe, Explain, Identifier
|
|
|
12
12
|
from mindsdb.utilities import log
|
|
13
13
|
from mindsdb.utilities.context import context as ctx
|
|
14
14
|
from mindsdb.integrations.utilities.query_traversal import query_traversal
|
|
15
|
+
from mindsdb.integrations.libs.response import INF_SCHEMA_COLUMNS_NAMES
|
|
15
16
|
|
|
16
17
|
logger = log.getLogger(__name__)
|
|
17
18
|
|
|
@@ -275,9 +276,13 @@ class SQLAgent:
|
|
|
275
276
|
dn = self._command_executor.session.datahub.get(integration)
|
|
276
277
|
|
|
277
278
|
fields, dtypes = [], []
|
|
278
|
-
for
|
|
279
|
-
|
|
280
|
-
|
|
279
|
+
for df in dn.get_table_columns_df(table_name, schema_name):
|
|
280
|
+
df_records = df.to_dict(orient='records')
|
|
281
|
+
fields.append(df_records[INF_SCHEMA_COLUMNS_NAMES.COLUMN_NAME])
|
|
282
|
+
if df_records[INF_SCHEMA_COLUMNS_NAMES.MYSQL_DATA_TYPE] is not None:
|
|
283
|
+
dtypes.append(df_records[INF_SCHEMA_COLUMNS_NAMES.MYSQL_DATA_TYPE].value)
|
|
284
|
+
else:
|
|
285
|
+
dtypes.append(df_records[INF_SCHEMA_COLUMNS_NAMES.DATA_TYPE])
|
|
281
286
|
|
|
282
287
|
info = f'Table named `{table_str}`:\n'
|
|
283
288
|
info += f"\nSample with first {self._sample_rows_in_table_info} rows from table {table_str} in CSV format (dialect is 'excel'):\n"
|
mindsdb/interfaces/storage/db.py
CHANGED
|
@@ -571,9 +571,9 @@ class Queries(Base):
|
|
|
571
571
|
company_id: int = Column(Integer, nullable=True)
|
|
572
572
|
|
|
573
573
|
sql: str = Column(String, nullable=False)
|
|
574
|
-
|
|
574
|
+
database: str = Column(String, nullable=True)
|
|
575
575
|
|
|
576
|
-
started_at: datetime.datetime = Column(DateTime
|
|
576
|
+
started_at: datetime.datetime = Column(DateTime)
|
|
577
577
|
finished_at: datetime.datetime = Column(DateTime)
|
|
578
578
|
|
|
579
579
|
parameters = Column(JSON, default={})
|
|
@@ -2,6 +2,7 @@ import datetime as dt
|
|
|
2
2
|
import os
|
|
3
3
|
import socket
|
|
4
4
|
import time
|
|
5
|
+
from threading import Event
|
|
5
6
|
|
|
6
7
|
import sqlalchemy as sa
|
|
7
8
|
|
|
@@ -22,7 +23,7 @@ class TaskMonitor:
|
|
|
22
23
|
def __init__(self):
|
|
23
24
|
self._active_tasks = {}
|
|
24
25
|
|
|
25
|
-
def start(self):
|
|
26
|
+
def start(self, stop_event: Event = None):
|
|
26
27
|
config = Config()
|
|
27
28
|
db.init()
|
|
28
29
|
self.config = config
|
|
@@ -42,6 +43,9 @@ class TaskMonitor:
|
|
|
42
43
|
logger.error(e)
|
|
43
44
|
db.session.rollback()
|
|
44
45
|
|
|
46
|
+
if stop_event is not None and stop_event.is_set():
|
|
47
|
+
return
|
|
48
|
+
|
|
45
49
|
def stop_all_tasks(self):
|
|
46
50
|
|
|
47
51
|
active_tasks = list(self._active_tasks.keys())
|
|
@@ -6,6 +6,7 @@ from mindsdb.utilities import log
|
|
|
6
6
|
|
|
7
7
|
from mindsdb.interfaces.triggers.trigger_task import TriggerTask
|
|
8
8
|
from mindsdb.interfaces.chatbot.chatbot_task import ChatBotTask
|
|
9
|
+
from mindsdb.interfaces.query_context.query_task import QueryTask
|
|
9
10
|
|
|
10
11
|
logger = log.getLogger(__name__)
|
|
11
12
|
|
|
@@ -28,6 +29,7 @@ class TaskThread(threading.Thread):
|
|
|
28
29
|
ctx.company_id = task_record.company_id
|
|
29
30
|
if task_record.user_class is not None:
|
|
30
31
|
ctx.user_class = task_record.user_class
|
|
32
|
+
ctx.task_id = task_record.id
|
|
31
33
|
|
|
32
34
|
self.object_type = task_record.object_type
|
|
33
35
|
self.object_id = task_record.object_id
|
|
@@ -43,6 +45,10 @@ class TaskThread(threading.Thread):
|
|
|
43
45
|
bot = ChatBotTask(self.task_id, self.object_id)
|
|
44
46
|
bot.run(self._stop_event)
|
|
45
47
|
|
|
48
|
+
elif self.object_type == 'query':
|
|
49
|
+
query = QueryTask(self.task_id, self.object_id)
|
|
50
|
+
query.run(self._stop_event)
|
|
51
|
+
|
|
46
52
|
except Exception:
|
|
47
53
|
logger.error(traceback.format_exc())
|
|
48
54
|
task_record.last_error = str(traceback.format_exc())
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""query_database
|
|
2
|
+
|
|
3
|
+
Revision ID: 53502b6d63bf
|
|
4
|
+
Revises: fda503400e43
|
|
5
|
+
Create Date: 2025-04-22 16:30:15.139978
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
from alembic import op
|
|
9
|
+
import sqlalchemy as sa
|
|
10
|
+
import mindsdb.interfaces.storage.db # noqa
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# revision identifiers, used by Alembic.
|
|
14
|
+
revision = '53502b6d63bf'
|
|
15
|
+
down_revision = 'fda503400e43'
|
|
16
|
+
branch_labels = None
|
|
17
|
+
depends_on = None
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def upgrade():
|
|
21
|
+
with op.batch_alter_table('queries', schema=None) as batch_op:
|
|
22
|
+
batch_op.add_column(sa.Column('database', sa.String(), nullable=True))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def downgrade():
|
|
26
|
+
with op.batch_alter_table('queries', schema=None) as batch_op:
|
|
27
|
+
batch_op.drop_column('database')
|
mindsdb/utilities/config.py
CHANGED
|
@@ -209,6 +209,10 @@ class Config:
|
|
|
209
209
|
"restart_on_failure": True,
|
|
210
210
|
"max_restart_count": 1,
|
|
211
211
|
"max_restart_interval_seconds": 60
|
|
212
|
+
},
|
|
213
|
+
"litellm": {
|
|
214
|
+
"host": "0.0.0.0", # API server binds to all interfaces by default
|
|
215
|
+
"port": "8000"
|
|
212
216
|
}
|
|
213
217
|
},
|
|
214
218
|
"cache": {
|
|
@@ -226,7 +230,9 @@ class Config:
|
|
|
226
230
|
"tasks": {
|
|
227
231
|
"disable": False
|
|
228
232
|
},
|
|
229
|
-
"default_project": "mindsdb"
|
|
233
|
+
"default_project": "mindsdb",
|
|
234
|
+
"default_llm": {},
|
|
235
|
+
"default_embedding_model": {}
|
|
230
236
|
}
|
|
231
237
|
# endregion
|
|
232
238
|
|
|
@@ -365,6 +371,15 @@ class Config:
|
|
|
365
371
|
if os.environ.get('MINDSDB_DEFAULT_PROJECT', '') != '':
|
|
366
372
|
self._env_config['default_project'] = os.environ['MINDSDB_DEFAULT_PROJECT'].lower()
|
|
367
373
|
|
|
374
|
+
if os.environ.get('MINDSDB_DEFAULT_LLM_API_KEY', '') != '':
|
|
375
|
+
self._env_config['default_llm'] = {
|
|
376
|
+
'api_key': os.environ['MINDSDB_DEFAULT_LLM_API_KEY']
|
|
377
|
+
}
|
|
378
|
+
if os.environ.get('MINDSDB_DEFAULT_EMBEDDING_MODEL_API_KEY', '') != '':
|
|
379
|
+
self._env_config['default_embedding_model'] = {
|
|
380
|
+
'api_key': os.environ['MINDSDB_DEFAULT_EMBEDDING_MODEL_API_KEY']
|
|
381
|
+
}
|
|
382
|
+
|
|
368
383
|
def parse_cmd_args(self) -> None:
|
|
369
384
|
"""Collect cmd args to self._cmd_args (accessable as self.cmd_args)
|
|
370
385
|
"""
|
|
@@ -378,7 +393,8 @@ class Config:
|
|
|
378
393
|
):
|
|
379
394
|
self._cmd_args = argparse.Namespace(
|
|
380
395
|
api=None, config=None, install_handlers=None, verbose=False,
|
|
381
|
-
no_studio=False, version=False, ml_task_queue_consumer=None
|
|
396
|
+
no_studio=False, version=False, ml_task_queue_consumer=None,
|
|
397
|
+
agent=None, project=None
|
|
382
398
|
)
|
|
383
399
|
return
|
|
384
400
|
|
|
@@ -390,6 +406,8 @@ class Config:
|
|
|
390
406
|
parser.add_argument('--no_studio', action='store_true')
|
|
391
407
|
parser.add_argument('-v', '--version', action='store_true')
|
|
392
408
|
parser.add_argument('--ml_task_queue_consumer', action='store_true', default=None)
|
|
409
|
+
parser.add_argument('--agent', type=str, default=None, help='Name of the agent to use with litellm APIs')
|
|
410
|
+
parser.add_argument('--project', type=str, default=None, help='Project containing the agent (default: mindsdb)')
|
|
393
411
|
self._cmd_args = parser.parse_args()
|
|
394
412
|
|
|
395
413
|
def fetch_auto_config(self) -> bool:
|
mindsdb/utilities/context.py
CHANGED
mindsdb/utilities/starters.py
CHANGED
|
@@ -38,3 +38,10 @@ def start_mcp(*args, **kwargs):
|
|
|
38
38
|
from mindsdb.api.mcp.start import start
|
|
39
39
|
|
|
40
40
|
start(*args, **kwargs)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def start_litellm(*args, **kwargs):
|
|
44
|
+
"""Start the LiteLLM server"""
|
|
45
|
+
from mindsdb.api.litellm.start import start
|
|
46
|
+
|
|
47
|
+
start(*args, **kwargs)
|