MindsDB 25.1.2.0__py3-none-any.whl → 25.1.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-25.1.2.0.dist-info → MindsDB-25.1.5.0.dist-info}/METADATA +258 -255
- {MindsDB-25.1.2.0.dist-info → MindsDB-25.1.5.0.dist-info}/RECORD +98 -85
- {MindsDB-25.1.2.0.dist-info → MindsDB-25.1.5.0.dist-info}/WHEEL +1 -1
- mindsdb/__about__.py +1 -1
- mindsdb/__main__.py +5 -3
- mindsdb/api/executor/__init__.py +0 -1
- mindsdb/api/executor/command_executor.py +2 -1
- mindsdb/api/executor/data_types/answer.py +1 -1
- mindsdb/api/executor/datahub/datanodes/datanode.py +1 -1
- mindsdb/api/executor/datahub/datanodes/information_schema_datanode.py +1 -1
- mindsdb/api/executor/datahub/datanodes/integration_datanode.py +8 -3
- mindsdb/api/executor/datahub/datanodes/project_datanode.py +9 -26
- mindsdb/api/executor/sql_query/__init__.py +1 -0
- mindsdb/api/executor/sql_query/result_set.py +36 -21
- mindsdb/api/executor/sql_query/steps/apply_predictor_step.py +1 -1
- mindsdb/api/executor/sql_query/steps/join_step.py +4 -4
- mindsdb/api/executor/sql_query/steps/map_reduce_step.py +6 -39
- mindsdb/api/executor/utilities/sql.py +2 -10
- mindsdb/api/http/namespaces/agents.py +3 -1
- mindsdb/api/http/namespaces/knowledge_bases.py +3 -3
- mindsdb/api/http/namespaces/sql.py +3 -1
- mindsdb/api/mysql/mysql_proxy/executor/mysql_executor.py +2 -1
- mindsdb/api/mysql/mysql_proxy/mysql_proxy.py +7 -0
- mindsdb/api/postgres/postgres_proxy/executor/executor.py +2 -1
- mindsdb/integrations/handlers/chromadb_handler/chromadb_handler.py +2 -2
- mindsdb/integrations/handlers/chromadb_handler/requirements.txt +1 -1
- mindsdb/integrations/handlers/databricks_handler/requirements.txt +1 -1
- mindsdb/integrations/handlers/file_handler/file_handler.py +1 -1
- mindsdb/integrations/handlers/file_handler/requirements.txt +0 -4
- mindsdb/integrations/handlers/file_handler/tests/test_file_handler.py +17 -1
- mindsdb/integrations/handlers/jira_handler/jira_handler.py +15 -1
- mindsdb/integrations/handlers/jira_handler/jira_table.py +52 -31
- mindsdb/integrations/handlers/langchain_embedding_handler/fastapi_embeddings.py +82 -0
- mindsdb/integrations/handlers/langchain_embedding_handler/langchain_embedding_handler.py +8 -1
- mindsdb/integrations/handlers/langchain_handler/requirements.txt +1 -1
- mindsdb/integrations/handlers/ms_one_drive_handler/ms_one_drive_handler.py +1 -1
- mindsdb/integrations/handlers/ms_one_drive_handler/ms_one_drive_tables.py +8 -0
- mindsdb/integrations/handlers/pgvector_handler/pgvector_handler.py +49 -12
- mindsdb/integrations/handlers/pinecone_handler/pinecone_handler.py +123 -72
- mindsdb/integrations/handlers/pinecone_handler/requirements.txt +1 -1
- mindsdb/integrations/handlers/postgres_handler/postgres_handler.py +12 -6
- mindsdb/integrations/handlers/ray_serve_handler/ray_serve_handler.py +5 -3
- mindsdb/integrations/handlers/slack_handler/slack_handler.py +13 -2
- mindsdb/integrations/handlers/slack_handler/slack_tables.py +21 -1
- mindsdb/integrations/handlers/web_handler/requirements.txt +0 -1
- mindsdb/integrations/libs/ml_handler_process/learn_process.py +2 -2
- mindsdb/integrations/utilities/files/__init__.py +0 -0
- mindsdb/integrations/utilities/files/file_reader.py +258 -0
- mindsdb/integrations/utilities/handlers/api_utilities/microsoft/ms_graph_api_utilities.py +2 -1
- mindsdb/integrations/utilities/handlers/auth_utilities/microsoft/ms_graph_api_auth_utilities.py +8 -3
- mindsdb/integrations/utilities/rag/chains/map_reduce_summarizer_chain.py +5 -9
- mindsdb/integrations/utilities/rag/loaders/vector_store_loader/pgvector.py +76 -27
- mindsdb/integrations/utilities/rag/loaders/vector_store_loader/vector_store_loader.py +18 -1
- mindsdb/integrations/utilities/rag/pipelines/rag.py +84 -20
- mindsdb/integrations/utilities/rag/rag_pipeline_builder.py +16 -1
- mindsdb/integrations/utilities/rag/rerankers/reranker_compressor.py +166 -108
- mindsdb/integrations/utilities/rag/retrievers/__init__.py +3 -0
- mindsdb/integrations/utilities/rag/retrievers/multi_hop_retriever.py +85 -0
- mindsdb/integrations/utilities/rag/retrievers/retriever_factory.py +57 -0
- mindsdb/integrations/utilities/rag/retrievers/sql_retriever.py +117 -48
- mindsdb/integrations/utilities/rag/settings.py +190 -17
- mindsdb/integrations/utilities/sql_utils.py +1 -1
- mindsdb/interfaces/agents/agents_controller.py +18 -8
- mindsdb/interfaces/agents/constants.py +1 -0
- mindsdb/interfaces/agents/langchain_agent.py +124 -157
- mindsdb/interfaces/agents/langfuse_callback_handler.py +4 -37
- mindsdb/interfaces/agents/mindsdb_database_agent.py +21 -13
- mindsdb/interfaces/chatbot/chatbot_controller.py +7 -11
- mindsdb/interfaces/chatbot/chatbot_task.py +16 -5
- mindsdb/interfaces/chatbot/memory.py +58 -13
- mindsdb/interfaces/database/integrations.py +5 -1
- mindsdb/interfaces/database/projects.py +55 -16
- mindsdb/interfaces/database/views.py +12 -25
- mindsdb/interfaces/knowledge_base/controller.py +38 -9
- mindsdb/interfaces/knowledge_base/preprocessing/document_loader.py +7 -26
- mindsdb/interfaces/model/functions.py +15 -4
- mindsdb/interfaces/model/model_controller.py +4 -7
- mindsdb/interfaces/skills/custom/text2sql/mindsdb_sql_toolkit.py +51 -40
- mindsdb/interfaces/skills/retrieval_tool.py +10 -3
- mindsdb/interfaces/skills/skill_tool.py +97 -54
- mindsdb/interfaces/skills/skills_controller.py +7 -3
- mindsdb/interfaces/skills/sql_agent.py +127 -41
- mindsdb/interfaces/storage/db.py +1 -1
- mindsdb/migrations/versions/2025-01-15_c06c35f7e8e1_project_company.py +88 -0
- mindsdb/utilities/cache.py +7 -4
- mindsdb/utilities/context.py +11 -1
- mindsdb/utilities/langfuse.py +279 -0
- mindsdb/utilities/log.py +20 -2
- mindsdb/utilities/otel/__init__.py +206 -0
- mindsdb/utilities/otel/logger.py +25 -0
- mindsdb/utilities/otel/meter.py +19 -0
- mindsdb/utilities/otel/metric_handlers/__init__.py +25 -0
- mindsdb/utilities/otel/tracer.py +16 -0
- mindsdb/utilities/partitioning.py +52 -0
- mindsdb/utilities/render/sqlalchemy_render.py +7 -1
- mindsdb/utilities/utils.py +34 -0
- mindsdb/utilities/otel.py +0 -72
- {MindsDB-25.1.2.0.dist-info → MindsDB-25.1.5.0.dist-info}/LICENSE +0 -0
- {MindsDB-25.1.2.0.dist-info → MindsDB-25.1.5.0.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from typing import List
|
|
2
|
+
from textwrap import dedent
|
|
2
3
|
|
|
3
4
|
from langchain_community.agent_toolkits.sql.toolkit import SQLDatabaseToolkit
|
|
4
5
|
from langchain_community.tools import ListSQLDatabaseTool, InfoSQLDatabaseTool, QuerySQLDataBaseTool
|
|
@@ -11,57 +12,67 @@ class MindsDBSQLToolkit(SQLDatabaseToolkit):
|
|
|
11
12
|
|
|
12
13
|
def get_tools(self, prefix='') -> List[BaseTool]:
|
|
13
14
|
"""Get the tools in the toolkit."""
|
|
14
|
-
list_sql_database_tool = ListSQLDatabaseTool(
|
|
15
|
+
list_sql_database_tool = ListSQLDatabaseTool(
|
|
16
|
+
name=f'sql_db_list_tables{prefix}',
|
|
17
|
+
db=self.db,
|
|
18
|
+
description=(
|
|
19
|
+
"Input is an empty string, output is a comma-separated list of tables in the database. "
|
|
20
|
+
"Each table name in the list may be in one of two formats: database_name.table_name or "
|
|
21
|
+
"database_name.schema_name.table_name."
|
|
22
|
+
"If the table name is enclosed in backticks marks, then always use the table name with backticks marks in subsequent queries."
|
|
23
|
+
)
|
|
24
|
+
)
|
|
15
25
|
|
|
16
26
|
info_sql_database_tool_description = (
|
|
17
|
-
"Input: A comma-separated list of tables
|
|
27
|
+
"Input: A comma-separated list of tables enclosed between the symbols $START$ and $END$. Output: Schema and sample rows for those tables. "
|
|
18
28
|
f"Ensure tables exist by calling {list_sql_database_tool.name} first. "
|
|
19
29
|
"Use this tool to investigate table schemas for needed columns. "
|
|
20
30
|
"Get sample data with 'SELECT * FROM table LIMIT 3' before answering questions. "
|
|
21
|
-
"Example Input: table1, table2, table3"
|
|
31
|
+
"Example Input: $START$ table1, table2, table3 $END$"
|
|
22
32
|
)
|
|
23
33
|
info_sql_database_tool = InfoSQLDatabaseTool(
|
|
24
34
|
name=f'sql_db_schema{prefix}',
|
|
25
35
|
db=self.db, description=info_sql_database_tool_description
|
|
26
36
|
)
|
|
27
37
|
|
|
28
|
-
query_sql_database_tool_description = (
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
38
|
+
query_sql_database_tool_description = dedent(f"""\
|
|
39
|
+
Input: A detailed SQL query.
|
|
40
|
+
Output: Database result or error message. For errors, rewrite and retry the query. For 'Unknown column' errors, use '{info_sql_database_tool.name}' to check table fields.
|
|
41
|
+
This system is a highly intelligent and reliable PostgreSQL SQL skill designed to work with databases.
|
|
42
|
+
Follow these instructions with utmost precision:
|
|
43
|
+
1. Query Output Format:
|
|
44
|
+
- Always return results in well-formatted **Markdown tables**.
|
|
45
|
+
- Ensure clarity and proper structure for easy readability.
|
|
46
|
+
2. Sample Data:
|
|
47
|
+
- Before answering a question, if you don't have sample data about a table, **always** get sample data using `SELECT * FROM table LIMIT 3` from the tables you believe are relevant to formulating your answers.
|
|
48
|
+
3. Categorical Data:
|
|
49
|
+
- Whenever working with a column where values seem categorical, especially when filtering with `WHERE col = 'value'`, `WHERE col IN (list of values)`, or `WHERE col NOT IN (list of values)`, **always** retrieve the distinct values first.
|
|
50
|
+
- Before writing your main query, always run `SELECT DISTINCT col` to fetch a list of unique values from that column. This step is mandatory to ensure accurate queries and responses.
|
|
51
|
+
4. Result Limiting and Counting:
|
|
52
|
+
- Unless instructed otherwise by the user, always run a count on the final query first using `SELECT COUNT(*)`.
|
|
53
|
+
- If the count is greater than 10, limit the query to return only 10 results initially.
|
|
54
|
+
- **Always** inform the user of the total number of results available and specify that you are providing the first 10 results.
|
|
55
|
+
- Let the user know they can request additional results and/or specify how they would like the results ordered or grouped.
|
|
56
|
+
5. Date Handling:
|
|
57
|
+
- **Always** use PostgreSQL-compatible `CURRENT_DATE` or `NOW()` functions when working with dates—never assume or guess the current date.
|
|
58
|
+
- For any date-related comparisons in the query, *always* ensure that your query casts the column being compared using `column_name::DATE [operator] ..`
|
|
59
|
+
- Do not compare date values without casting columns to date.
|
|
60
|
+
- For date interval operations, use Interval units as keywords. You can use keywords to specify units like days, hours, months, years, etc., directly without quotes. Examples:
|
|
61
|
+
SELECT NOW() + INTERVAL 5 DAY;
|
|
62
|
+
SELECT NOW() - INTERVAL 3 HOUR;
|
|
63
|
+
SELECT NOW() + INTERVAL 2 MONTH + INTERVAL 3 DAY;
|
|
64
|
+
SELECT NOW() - INTERVAL 1 YEAR;
|
|
65
|
+
6. Query Best Practices:
|
|
66
|
+
- Always send only one query at a time.
|
|
67
|
+
- The input SQL query must end with a semicolon.
|
|
68
|
+
- Query only necessary columns, not all.
|
|
69
|
+
- Use only existing column names from correct tables.
|
|
70
|
+
- Use database-specific syntax for date operations.
|
|
71
|
+
7. Error Handling:
|
|
72
|
+
- For errors, rewrite and retry the query.
|
|
73
|
+
- For 'Unknown column' errors, check table fields using info_sql_database_tool.
|
|
74
|
+
Adhere to these guidelines for all queries and responses. Ask for clarification if needed.
|
|
75
|
+
""")
|
|
65
76
|
|
|
66
77
|
query_sql_database_tool = QuerySQLDataBaseTool(
|
|
67
78
|
name=f'sql_db_query{prefix}',
|
|
@@ -43,10 +43,17 @@ def build_retrieval_tool(tool: dict, pred_args: dict, skill: db.Skills):
|
|
|
43
43
|
raise ValueError(f"Knowledge base not found: {kb_name}")
|
|
44
44
|
|
|
45
45
|
kb_table = executor.session.kb_controller.get_table(kb.name, kb.project_id)
|
|
46
|
+
vector_store_config = {
|
|
47
|
+
'kb_table': kb_table
|
|
48
|
+
}
|
|
49
|
+
is_sparse = tools_config.pop('is_sparse', None)
|
|
50
|
+
vector_size = tools_config.pop('vector_size', None)
|
|
51
|
+
if is_sparse is not None:
|
|
52
|
+
vector_store_config['is_sparse'] = is_sparse
|
|
53
|
+
if vector_size is not None:
|
|
54
|
+
vector_store_config['vector_size'] = vector_size
|
|
46
55
|
kb_params = {
|
|
47
|
-
'vector_store_config':
|
|
48
|
-
'kb_table': kb_table
|
|
49
|
-
}
|
|
56
|
+
'vector_store_config': vector_store_config
|
|
50
57
|
}
|
|
51
58
|
|
|
52
59
|
# Get embedding model from knowledge base table
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import enum
|
|
2
|
-
|
|
3
|
-
from typing import List, Optional
|
|
2
|
+
import inspect
|
|
4
3
|
from dataclasses import dataclass
|
|
4
|
+
from collections import defaultdict
|
|
5
|
+
from typing import List, Dict, Optional
|
|
5
6
|
|
|
6
7
|
from langchain_core.embeddings import Embeddings
|
|
7
8
|
from langchain_core.language_models import BaseChatModel
|
|
8
9
|
from mindsdb_sql_parser.ast import Select, BinaryOperation, Identifier, Constant, Star
|
|
9
10
|
|
|
10
|
-
from mindsdb.integrations.libs.vectordatabase_handler import TableField
|
|
11
|
-
from mindsdb.interfaces.skills.sql_agent import SQLAgent
|
|
12
|
-
from mindsdb.interfaces.storage import db
|
|
13
11
|
from mindsdb.utilities import log
|
|
14
12
|
from mindsdb.utilities.cache import get_cache
|
|
13
|
+
from mindsdb.interfaces.storage import db
|
|
14
|
+
from mindsdb.interfaces.skills.sql_agent import SQLAgent
|
|
15
|
+
from mindsdb.integrations.libs.vectordatabase_handler import TableField
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
_DEFAULT_TOP_K_SIMILARITY_SEARCH = 5
|
|
@@ -45,27 +46,54 @@ class SkillData:
|
|
|
45
46
|
agent_tables_list: Optional[List[str]]
|
|
46
47
|
|
|
47
48
|
@property
|
|
48
|
-
def
|
|
49
|
-
"""
|
|
50
|
-
The result list is a combination of skill's and agent's tables lists.
|
|
49
|
+
def restriction_on_tables(self) -> Optional[Dict[str, set]]:
|
|
50
|
+
"""Schemas and tables which agent+skill may use. The result is intersections of skill's and agent's tables lists.
|
|
51
51
|
|
|
52
52
|
Returns:
|
|
53
|
-
|
|
53
|
+
Optional[Dict[str, set]]: allowed schemas and tables. Schemas - are keys in dict, tables - are values.
|
|
54
|
+
if result is None, then there are no restrictions
|
|
54
55
|
|
|
55
56
|
Raises:
|
|
56
57
|
ValueError: if there is no intersection between skill's and agent's list.
|
|
57
58
|
This means that all tables restricted for use.
|
|
58
59
|
"""
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
60
|
+
def list_to_map(input: List) -> Dict:
|
|
61
|
+
agent_tables_map = defaultdict(set)
|
|
62
|
+
for x in input:
|
|
63
|
+
if isinstance(x, str):
|
|
64
|
+
table_name = x
|
|
65
|
+
schema_name = None
|
|
66
|
+
elif isinstance(x, dict):
|
|
67
|
+
table_name = x['table']
|
|
68
|
+
schema_name = x.get('schema')
|
|
69
|
+
else:
|
|
70
|
+
raise ValueError(f'Unexpected value in tables list: {x}')
|
|
71
|
+
agent_tables_map[schema_name].add(table_name)
|
|
72
|
+
return agent_tables_map
|
|
73
|
+
|
|
74
|
+
agent_tables_map = list_to_map(self.agent_tables_list or [])
|
|
75
|
+
skill_tables_map = list_to_map(self.params.get('tables', []))
|
|
76
|
+
|
|
77
|
+
if len(agent_tables_map) > 0 and len(skill_tables_map) > 0:
|
|
78
|
+
if len(set(agent_tables_map) & set(skill_tables_map)) == 0:
|
|
79
|
+
raise ValueError("Skill's and agent's allowed tables list have no shared schemas.")
|
|
80
|
+
|
|
81
|
+
intersection_tables_map = defaultdict(set)
|
|
82
|
+
has_intersection = False
|
|
83
|
+
for schema_name in agent_tables_map:
|
|
84
|
+
if schema_name not in skill_tables_map:
|
|
85
|
+
continue
|
|
86
|
+
intersection_tables_map[schema_name] = agent_tables_map[schema_name] & skill_tables_map[schema_name]
|
|
87
|
+
if len(intersection_tables_map[schema_name]) > 0:
|
|
88
|
+
has_intersection = True
|
|
89
|
+
if has_intersection is False:
|
|
90
|
+
raise ValueError("Skill's and agent's allowed tables list have no shared tables.")
|
|
91
|
+
return intersection_tables_map
|
|
92
|
+
if len(skill_tables_map) > 0:
|
|
93
|
+
return skill_tables_map
|
|
94
|
+
if len(agent_tables_map) > 0:
|
|
95
|
+
return agent_tables_map
|
|
96
|
+
return None
|
|
69
97
|
|
|
70
98
|
|
|
71
99
|
class SkillToolController:
|
|
@@ -83,22 +111,6 @@ class SkillToolController:
|
|
|
83
111
|
self.command_executor = ExecuteCommands(sql_session)
|
|
84
112
|
return self.command_executor
|
|
85
113
|
|
|
86
|
-
def get_sql_agent(
|
|
87
|
-
self,
|
|
88
|
-
database: str,
|
|
89
|
-
include_tables: Optional[List[str]] = None,
|
|
90
|
-
ignore_tables: Optional[List[str]] = None,
|
|
91
|
-
sample_rows_in_table_info: int = 3,
|
|
92
|
-
):
|
|
93
|
-
return SQLAgent(
|
|
94
|
-
self.get_command_executor(),
|
|
95
|
-
database,
|
|
96
|
-
include_tables,
|
|
97
|
-
ignore_tables,
|
|
98
|
-
sample_rows_in_table_info,
|
|
99
|
-
cache=get_cache('agent', max_size=_MAX_CACHE_SIZE)
|
|
100
|
-
)
|
|
101
|
-
|
|
102
114
|
def _make_text_to_sql_tools(self, skills: List[db.Skills], llm) -> List:
|
|
103
115
|
'''
|
|
104
116
|
Uses SQLAgent to execute tool
|
|
@@ -112,19 +124,47 @@ class SkillToolController:
|
|
|
112
124
|
raise ImportError(
|
|
113
125
|
'To use the text-to-SQL skill, please install langchain with `pip install mindsdb[langchain]`')
|
|
114
126
|
|
|
127
|
+
command_executor = self.get_command_executor()
|
|
128
|
+
|
|
115
129
|
tables_list = []
|
|
116
130
|
for skill in skills:
|
|
117
131
|
database = skill.params['database']
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
132
|
+
restriction_on_tables = skill.restriction_on_tables
|
|
133
|
+
if restriction_on_tables is None:
|
|
134
|
+
handler = command_executor.session.integration_controller.get_data_handler(database)
|
|
135
|
+
if 'all' in inspect.signature(handler.get_tables).parameters:
|
|
136
|
+
response = handler.get_tables(all=True)
|
|
137
|
+
else:
|
|
138
|
+
response = handler.get_tables()
|
|
139
|
+
# no restrictions
|
|
140
|
+
if 'table_schema' in response.data_frame.columns:
|
|
141
|
+
for _, row in response.data_frame.iterrows():
|
|
142
|
+
tables_list.append(f"{database}.{row['table_schema']}.{row['table_name']}")
|
|
143
|
+
else:
|
|
144
|
+
for _, row in response.data_frame.iterrows():
|
|
145
|
+
tables_list.append(f"{database}.{row['table_name']}")
|
|
146
|
+
continue
|
|
147
|
+
for schema_name, tables in restriction_on_tables.items():
|
|
148
|
+
for table in tables:
|
|
149
|
+
if schema_name is None:
|
|
150
|
+
tables_list.append(f'{database}.{table}')
|
|
151
|
+
else:
|
|
152
|
+
tables_list.append(f'{database}.{schema_name}.{table}')
|
|
153
|
+
|
|
154
|
+
sql_agent = SQLAgent(
|
|
155
|
+
command_executor=command_executor,
|
|
156
|
+
databases=list(set(s.params['database'] for s in skills)),
|
|
157
|
+
databases_struct={
|
|
158
|
+
skill.params['database']: skill.restriction_on_tables
|
|
159
|
+
for skill in skills
|
|
160
|
+
},
|
|
161
|
+
include_tables=tables_list,
|
|
162
|
+
ignore_tables=None,
|
|
163
|
+
sample_rows_in_table_info=3,
|
|
164
|
+
cache=get_cache('agent', max_size=_MAX_CACHE_SIZE)
|
|
165
|
+
)
|
|
166
|
+
db = MindsDBSQL.custom_init(
|
|
167
|
+
sql_agent=sql_agent
|
|
128
168
|
)
|
|
129
169
|
|
|
130
170
|
# Users probably don't need to configure this for now.
|
|
@@ -138,14 +178,18 @@ class SkillToolController:
|
|
|
138
178
|
for i, tool in enumerate(sql_database_tools):
|
|
139
179
|
if isinstance(tool, QuerySQLDataBaseTool):
|
|
140
180
|
# Add our own custom description so our agent knows when to query this table.
|
|
141
|
-
tool.description
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
f'
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
f'
|
|
148
|
-
|
|
181
|
+
original_description = tool.description
|
|
182
|
+
tool.description = ''
|
|
183
|
+
if len(descriptions) > 0:
|
|
184
|
+
tool.description += f'Use this tool if you need data about {" OR ".join(descriptions)}.\n'
|
|
185
|
+
tool.description += 'Use the conversation context to decide which table to query.\n'
|
|
186
|
+
if len(tables_list) > 0:
|
|
187
|
+
f'These are the available tables: {",".join(tables_list)}.\n'
|
|
188
|
+
tool.description += (
|
|
189
|
+
'ALWAYS consider these special cases:\n'
|
|
190
|
+
' - For TIMESTAMP type columns, make sure you include the time portion in your query (e.g. WHERE date_column = "2020-01-01 12:00:00")\n'
|
|
191
|
+
'Here are the rest of the instructions:\n'
|
|
192
|
+
f'{original_description}'
|
|
149
193
|
)
|
|
150
194
|
sql_database_tools[i] = tool
|
|
151
195
|
return sql_database_tools
|
|
@@ -175,7 +219,6 @@ class SkillToolController:
|
|
|
175
219
|
return build_retrieval_tool(tool, pred_args, skill)
|
|
176
220
|
|
|
177
221
|
def _get_rag_query_function(self, skill: db.Skills):
|
|
178
|
-
|
|
179
222
|
session_controller = self.get_command_executor().session
|
|
180
223
|
|
|
181
224
|
def _answer_question(question: str) -> str:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import datetime
|
|
2
|
-
from typing import Dict, List
|
|
2
|
+
from typing import Dict, List, Optional
|
|
3
3
|
|
|
4
4
|
from sqlalchemy import null
|
|
5
5
|
from sqlalchemy.orm.attributes import flag_modified
|
|
@@ -16,7 +16,7 @@ class SkillsController:
|
|
|
16
16
|
project_controller = ProjectController()
|
|
17
17
|
self.project_controller = project_controller
|
|
18
18
|
|
|
19
|
-
def get_skill(self, skill_name: str, project_name: str = 'mindsdb') -> db.Skills:
|
|
19
|
+
def get_skill(self, skill_name: str, project_name: str = 'mindsdb') -> Optional[db.Skills]:
|
|
20
20
|
'''
|
|
21
21
|
Gets a skill by name. Skills are expected to have unique names.
|
|
22
22
|
|
|
@@ -25,7 +25,7 @@ class SkillsController:
|
|
|
25
25
|
project_name (str): The name of the containing project
|
|
26
26
|
|
|
27
27
|
Returns:
|
|
28
|
-
skill (db.Skills): The database skill object
|
|
28
|
+
skill (Optional[db.Skills]): The database skill object
|
|
29
29
|
|
|
30
30
|
Raises:
|
|
31
31
|
ValueError: If `project_name` does not exist
|
|
@@ -136,6 +136,8 @@ class SkillsController:
|
|
|
136
136
|
existing_skill = self.get_skill(skill_name, project_name)
|
|
137
137
|
if existing_skill is None:
|
|
138
138
|
raise ValueError(f'Skill with name not found: {skill_name}')
|
|
139
|
+
if isinstance(existing_skill.params, dict) and existing_skill.params.get('is_demo') is True:
|
|
140
|
+
raise ValueError("It is forbidden to change properties of the demo object")
|
|
139
141
|
|
|
140
142
|
if new_name is not None:
|
|
141
143
|
existing_skill.name = new_name
|
|
@@ -171,5 +173,7 @@ class SkillsController:
|
|
|
171
173
|
skill = self.get_skill(skill_name, project_name)
|
|
172
174
|
if skill is None:
|
|
173
175
|
raise ValueError(f"Skill with name doesn't exist: {skill_name}")
|
|
176
|
+
if isinstance(skill.params, dict) and skill.params.get('is_demo') is True:
|
|
177
|
+
raise ValueError("Unable to delete demo object")
|
|
174
178
|
skill.deleted_at = datetime.datetime.now()
|
|
175
179
|
db.session.commit()
|