MindsDB 25.4.4.0__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/api/executor/command_executor.py +12 -2
- mindsdb/api/executor/datahub/datanodes/mindsdb_tables.py +2 -1
- mindsdb/api/executor/planner/query_plan.py +1 -0
- mindsdb/api/executor/planner/query_planner.py +5 -0
- mindsdb/api/executor/sql_query/sql_query.py +24 -8
- mindsdb/api/executor/sql_query/steps/apply_predictor_step.py +20 -3
- mindsdb/api/executor/sql_query/steps/fetch_dataframe_partition.py +3 -1
- mindsdb/api/http/namespaces/config.py +19 -11
- mindsdb/integrations/handlers/openai_handler/helpers.py +3 -5
- mindsdb/integrations/handlers/openai_handler/openai_handler.py +20 -8
- 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/utilities/handler_utils.py +4 -0
- mindsdb/integrations/utilities/rag/rerankers/base_reranker.py +360 -0
- mindsdb/integrations/utilities/rag/rerankers/reranker_compressor.py +6 -346
- mindsdb/interfaces/functions/controller.py +3 -2
- mindsdb/interfaces/knowledge_base/controller.py +89 -75
- mindsdb/interfaces/query_context/context_controller.py +55 -15
- mindsdb/interfaces/query_context/query_task.py +19 -0
- 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 +12 -1
- mindsdb/utilities/context.py +1 -0
- {mindsdb-25.4.4.0.dist-info → mindsdb-25.4.5.0.dist-info}/METADATA +229 -226
- {mindsdb-25.4.4.0.dist-info → mindsdb-25.4.5.0.dist-info}/RECORD +37 -26
- {mindsdb-25.4.4.0.dist-info → mindsdb-25.4.5.0.dist-info}/WHEEL +1 -1
- {mindsdb-25.4.4.0.dist-info → mindsdb-25.4.5.0.dist-info}/licenses/LICENSE +0 -0
- {mindsdb-25.4.4.0.dist-info → mindsdb-25.4.5.0.dist-info}/top_level.txt +0 -0
|
@@ -27,7 +27,7 @@ from mindsdb.integrations.libs.vectordatabase_handler import (
|
|
|
27
27
|
from mindsdb.integrations.utilities.rag.rag_pipeline_builder import RAG
|
|
28
28
|
from mindsdb.integrations.utilities.rag.config_loader import load_rag_config
|
|
29
29
|
from mindsdb.integrations.utilities.handler_utils import get_api_key
|
|
30
|
-
from mindsdb.integrations.handlers.langchain_embedding_handler.langchain_embedding_handler import construct_model_from_args
|
|
30
|
+
from mindsdb.integrations.handlers.langchain_embedding_handler.langchain_embedding_handler import construct_model_from_args
|
|
31
31
|
|
|
32
32
|
from mindsdb.interfaces.agents.constants import DEFAULT_EMBEDDINGS_MODEL_CLASS
|
|
33
33
|
from mindsdb.interfaces.agents.langchain_agent import create_chat_model, get_llm_provider
|
|
@@ -37,11 +37,12 @@ from mindsdb.interfaces.knowledge_base.preprocessing.document_preprocessor impor
|
|
|
37
37
|
from mindsdb.interfaces.model.functions import PredictorRecordNotFound
|
|
38
38
|
from mindsdb.utilities.exception import EntityExistsError, EntityNotExistsError
|
|
39
39
|
from mindsdb.integrations.utilities.sql_utils import FilterCondition, FilterOperator
|
|
40
|
+
from mindsdb.utilities.config import config
|
|
40
41
|
from mindsdb.utilities.context import context as ctx
|
|
41
42
|
|
|
42
43
|
from mindsdb.api.executor.command_executor import ExecuteCommands
|
|
43
44
|
from mindsdb.utilities import log
|
|
44
|
-
from mindsdb.integrations.utilities.rag.rerankers.
|
|
45
|
+
from mindsdb.integrations.utilities.rag.rerankers.base_reranker import BaseLLMReranker
|
|
45
46
|
|
|
46
47
|
logger = log.getLogger(__name__)
|
|
47
48
|
|
|
@@ -52,6 +53,18 @@ KB_TO_VECTORDB_COLUMNS = {
|
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
|
|
56
|
+
def get_model_params(model_params: dict, default_config_key: str):
|
|
57
|
+
"""
|
|
58
|
+
Get model parameters by combining default config with user provided parameters.
|
|
59
|
+
"""
|
|
60
|
+
combined_model_params = copy.deepcopy(config.get(default_config_key, {}))
|
|
61
|
+
|
|
62
|
+
if model_params:
|
|
63
|
+
combined_model_params.update(model_params)
|
|
64
|
+
|
|
65
|
+
return combined_model_params
|
|
66
|
+
|
|
67
|
+
|
|
55
68
|
def get_embedding_model_from_params(embedding_model_params: dict):
|
|
56
69
|
"""
|
|
57
70
|
Create embedding model from parameters.
|
|
@@ -89,7 +102,7 @@ def get_reranking_model_from_params(reranking_model_params: dict):
|
|
|
89
102
|
params_copy["api_key"] = get_api_key(provider, params_copy, strict=False)
|
|
90
103
|
params_copy['model'] = params_copy.pop('model_name', None)
|
|
91
104
|
|
|
92
|
-
return
|
|
105
|
+
return BaseLLMReranker(**params_copy)
|
|
93
106
|
|
|
94
107
|
|
|
95
108
|
class KnowledgeBaseTable:
|
|
@@ -215,7 +228,7 @@ class KnowledgeBaseTable:
|
|
|
215
228
|
def add_relevance(self, df, query_text, relevance_threshold=None):
|
|
216
229
|
relevance_column = TableField.RELEVANCE.value
|
|
217
230
|
|
|
218
|
-
reranking_model_params = self._kb.params.get("reranking_model")
|
|
231
|
+
reranking_model_params = get_model_params(self._kb.params.get("reranking_model"), "default_llm")
|
|
219
232
|
if reranking_model_params and query_text and len(df) > 0:
|
|
220
233
|
# Use reranker for relevance score
|
|
221
234
|
try:
|
|
@@ -657,47 +670,34 @@ class KnowledgeBaseTable:
|
|
|
657
670
|
if df.empty:
|
|
658
671
|
return pd.DataFrame([], columns=[TableField.EMBEDDINGS.value])
|
|
659
672
|
|
|
660
|
-
# keep only content
|
|
661
|
-
df = df[[TableField.CONTENT.value]]
|
|
662
|
-
|
|
663
673
|
model_id = self._kb.embedding_model_id
|
|
664
|
-
if model_id:
|
|
665
|
-
# get the input columns
|
|
666
|
-
model_rec = db.session.query(db.Predictor).filter_by(id=model_id).first()
|
|
667
|
-
|
|
668
|
-
assert model_rec is not None, f"Model not found: {model_id}"
|
|
669
|
-
model_project = db.session.query(db.Project).filter_by(id=model_rec.project_id).first()
|
|
670
|
-
|
|
671
|
-
project_datanode = self.session.datahub.get(model_project.name)
|
|
672
674
|
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
if input_col is None:
|
|
676
|
-
input_col = model_using.get('input_column')
|
|
675
|
+
# get the input columns
|
|
676
|
+
model_rec = db.session.query(db.Predictor).filter_by(id=model_id).first()
|
|
677
677
|
|
|
678
|
-
|
|
679
|
-
|
|
678
|
+
assert model_rec is not None, f"Model not found: {model_id}"
|
|
679
|
+
model_project = db.session.query(db.Project).filter_by(id=model_rec.project_id).first()
|
|
680
680
|
|
|
681
|
-
|
|
682
|
-
model_name=model_rec.name,
|
|
683
|
-
df=df,
|
|
684
|
-
params=self.model_params
|
|
685
|
-
)
|
|
681
|
+
project_datanode = self.session.datahub.get(model_project.name)
|
|
686
682
|
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
683
|
+
model_using = model_rec.learn_args.get('using', {})
|
|
684
|
+
input_col = model_using.get('question_column')
|
|
685
|
+
if input_col is None:
|
|
686
|
+
input_col = model_using.get('input_column')
|
|
691
687
|
|
|
692
|
-
|
|
693
|
-
|
|
688
|
+
if input_col is not None and input_col != TableField.CONTENT.value:
|
|
689
|
+
df = df.rename(columns={TableField.CONTENT.value: input_col})
|
|
694
690
|
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
691
|
+
df_out = project_datanode.predict(
|
|
692
|
+
model_name=model_rec.name,
|
|
693
|
+
df=df,
|
|
694
|
+
params=self.model_params
|
|
695
|
+
)
|
|
698
696
|
|
|
699
|
-
|
|
700
|
-
|
|
697
|
+
target = model_rec.to_predict[0]
|
|
698
|
+
if target != TableField.EMBEDDINGS.value:
|
|
699
|
+
# adapt output for vectordb
|
|
700
|
+
df_out = df_out.rename(columns={target: TableField.EMBEDDINGS.value})
|
|
701
701
|
|
|
702
702
|
df_out = df_out[[TableField.EMBEDDINGS.value]]
|
|
703
703
|
|
|
@@ -728,14 +728,15 @@ class KnowledgeBaseTable:
|
|
|
728
728
|
"""
|
|
729
729
|
# Get embedding model from knowledge base
|
|
730
730
|
embeddings_model = None
|
|
731
|
+
embedding_model_params = get_model_params(self._kb.params.get('embedding_model', {}), 'default_embedding_model')
|
|
731
732
|
if self._kb.embedding_model:
|
|
732
733
|
# Extract embedding model args from knowledge base table
|
|
733
734
|
embedding_args = self._kb.embedding_model.learn_args.get('using', {})
|
|
734
735
|
# Construct the embedding model directly
|
|
735
736
|
embeddings_model = construct_model_from_args(embedding_args)
|
|
736
737
|
logger.debug(f"Using knowledge base embedding model with args: {embedding_args}")
|
|
737
|
-
elif
|
|
738
|
-
embeddings_model = get_embedding_model_from_params(
|
|
738
|
+
elif embedding_model_params:
|
|
739
|
+
embeddings_model = get_embedding_model_from_params(embedding_model_params)
|
|
739
740
|
logger.debug(f"Using knowledge base embedding model from params: {self._kb.params['embedding_model']}")
|
|
740
741
|
else:
|
|
741
742
|
embeddings_model = DEFAULT_EMBEDDINGS_MODEL_CLASS()
|
|
@@ -869,35 +870,33 @@ class KnowledgeBaseController:
|
|
|
869
870
|
return kb
|
|
870
871
|
raise EntityExistsError("Knowledge base already exists", name)
|
|
871
872
|
|
|
872
|
-
|
|
873
|
-
reranking_model_params = params.get('reranking_model', None)
|
|
873
|
+
embedding_params = copy.deepcopy(config.get('default_embedding_model', {}))
|
|
874
874
|
|
|
875
|
+
model_name = None
|
|
876
|
+
model_project = project
|
|
875
877
|
if embedding_model:
|
|
876
878
|
model_name = embedding_model.parts[-1]
|
|
879
|
+
if len(embedding_model.parts) > 1:
|
|
880
|
+
model_project = self.session.database_controller.get_project(embedding_model.parts[-2])
|
|
877
881
|
|
|
878
|
-
elif
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
882
|
+
elif 'embedding_model' in params:
|
|
883
|
+
if isinstance(params['embedding_model'], str):
|
|
884
|
+
# it is model name
|
|
885
|
+
model_name = params['embedding_model']
|
|
886
|
+
else:
|
|
887
|
+
# it is params for model
|
|
888
|
+
embedding_params.update(params['embedding_model'])
|
|
884
889
|
|
|
885
|
-
|
|
886
|
-
model_name = self.
|
|
890
|
+
if model_name is None:
|
|
891
|
+
model_name = self._create_embedding_model(
|
|
887
892
|
project.name,
|
|
888
|
-
params=
|
|
893
|
+
params=embedding_params,
|
|
894
|
+
kb_name=name,
|
|
889
895
|
)
|
|
890
|
-
params['
|
|
891
|
-
|
|
892
|
-
model_project = None
|
|
893
|
-
if embedding_model is not None and len(embedding_model.parts) > 1:
|
|
894
|
-
# model project is set
|
|
895
|
-
model_project = self.session.database_controller.get_project(embedding_model.parts[-2])
|
|
896
|
-
elif not embedding_model_params:
|
|
897
|
-
model_project = project
|
|
896
|
+
params['created_embedding_model'] = model_name
|
|
898
897
|
|
|
899
898
|
embedding_model_id = None
|
|
900
|
-
if
|
|
899
|
+
if model_name is not None:
|
|
901
900
|
model = self.session.model_controller.get_model(
|
|
902
901
|
name=model_name,
|
|
903
902
|
project_name=model_project.name
|
|
@@ -905,6 +904,7 @@ class KnowledgeBaseController:
|
|
|
905
904
|
model_record = db.Predictor.query.get(model['id'])
|
|
906
905
|
embedding_model_id = model_record.id
|
|
907
906
|
|
|
907
|
+
reranking_model_params = get_model_params(params.get('reranking_model', {}), 'default_llm')
|
|
908
908
|
if reranking_model_params:
|
|
909
909
|
# Get reranking model from params.
|
|
910
910
|
# This is called here to check validaity of the parameters.
|
|
@@ -989,38 +989,52 @@ class KnowledgeBaseController:
|
|
|
989
989
|
self.session.integration_controller.add(vector_store_name, engine, connection_args)
|
|
990
990
|
return vector_store_name
|
|
991
991
|
|
|
992
|
-
def
|
|
992
|
+
def _create_embedding_model(self, project_name, engine="openai", params: dict = None, kb_name=''):
|
|
993
993
|
"""create a default embedding model for knowledge base, if not specified"""
|
|
994
|
-
model_name = "
|
|
994
|
+
model_name = f"kb_embedding_{kb_name}"
|
|
995
995
|
|
|
996
|
-
#
|
|
996
|
+
# drop if exists - parameters can be different
|
|
997
997
|
try:
|
|
998
998
|
model = self.session.model_controller.get_model(model_name, project_name=project_name)
|
|
999
999
|
if model is not None:
|
|
1000
|
-
|
|
1000
|
+
self.session.model_controller.delete_model(model_name, project_name)
|
|
1001
1001
|
except PredictorRecordNotFound:
|
|
1002
1002
|
pass
|
|
1003
1003
|
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
if engine == '
|
|
1008
|
-
|
|
1009
|
-
|
|
1004
|
+
if 'provider' in params:
|
|
1005
|
+
engine = params.pop('provider').lower()
|
|
1006
|
+
|
|
1007
|
+
if engine == 'azure_openai':
|
|
1008
|
+
engine = 'openai'
|
|
1009
|
+
params['provider'] = 'azure'
|
|
1010
|
+
|
|
1011
|
+
if engine == 'openai':
|
|
1012
|
+
if 'question_column' not in params:
|
|
1013
|
+
params['question_column'] = 'content'
|
|
1014
|
+
if 'api_key' in params:
|
|
1015
|
+
params[f"{engine}_api_key"] = params.pop('api_key')
|
|
1016
|
+
if 'base_url' in params:
|
|
1017
|
+
params['api_base'] = params.pop('base_url')
|
|
1018
|
+
|
|
1019
|
+
params['engine'] = engine
|
|
1020
|
+
params['join_learn_process'] = True
|
|
1021
|
+
params['mode'] = 'embedding'
|
|
1010
1022
|
|
|
1011
1023
|
# Include API key if provided.
|
|
1012
|
-
using_args.update({k: v for k, v in params.items() if 'api_key' in k})
|
|
1013
1024
|
statement = CreatePredictor(
|
|
1014
1025
|
name=Identifier(parts=[project_name, model_name]),
|
|
1015
|
-
using=
|
|
1026
|
+
using=params,
|
|
1016
1027
|
targets=[
|
|
1017
1028
|
Identifier(parts=[TableField.EMBEDDINGS.value])
|
|
1018
1029
|
]
|
|
1019
1030
|
)
|
|
1020
1031
|
|
|
1021
1032
|
command_executor = ExecuteCommands(self.session)
|
|
1022
|
-
command_executor.answer_create_predictor(statement, project_name)
|
|
1023
|
-
|
|
1033
|
+
resp = command_executor.answer_create_predictor(statement, project_name)
|
|
1034
|
+
# check model status
|
|
1035
|
+
record = resp.data.records[0]
|
|
1036
|
+
if record['STATUS'] == 'error':
|
|
1037
|
+
raise ValueError('Embedding model error:' + record['ERROR'])
|
|
1024
1038
|
return model_name
|
|
1025
1039
|
|
|
1026
1040
|
def delete(self, name: str, project_name: int, if_exists: bool = False) -> None:
|
|
@@ -1054,9 +1068,9 @@ class KnowledgeBaseController:
|
|
|
1054
1068
|
self.session.integration_controller.delete(kb.params['default_vector_storage'])
|
|
1055
1069
|
except EntityNotExistsError:
|
|
1056
1070
|
pass
|
|
1057
|
-
if '
|
|
1071
|
+
if 'created_embedding_model' in kb.params:
|
|
1058
1072
|
try:
|
|
1059
|
-
self.session.model_controller.delete_model(kb.params['
|
|
1073
|
+
self.session.model_controller.delete_model(kb.params['created_embedding_model'], project_name)
|
|
1060
1074
|
except EntityNotExistsError:
|
|
1061
1075
|
pass
|
|
1062
1076
|
|
|
@@ -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()
|
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
|
@@ -230,7 +230,9 @@ class Config:
|
|
|
230
230
|
"tasks": {
|
|
231
231
|
"disable": False
|
|
232
232
|
},
|
|
233
|
-
"default_project": "mindsdb"
|
|
233
|
+
"default_project": "mindsdb",
|
|
234
|
+
"default_llm": {},
|
|
235
|
+
"default_embedding_model": {}
|
|
234
236
|
}
|
|
235
237
|
# endregion
|
|
236
238
|
|
|
@@ -369,6 +371,15 @@ class Config:
|
|
|
369
371
|
if os.environ.get('MINDSDB_DEFAULT_PROJECT', '') != '':
|
|
370
372
|
self._env_config['default_project'] = os.environ['MINDSDB_DEFAULT_PROJECT'].lower()
|
|
371
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
|
+
|
|
372
383
|
def parse_cmd_args(self) -> None:
|
|
373
384
|
"""Collect cmd args to self._cmd_args (accessable as self.cmd_args)
|
|
374
385
|
"""
|