MindsDB 25.4.5.0__py3-none-any.whl → 25.5.4.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 +215 -185
- mindsdb/api/a2a/__init__.py +0 -0
- mindsdb/api/a2a/__main__.py +114 -0
- mindsdb/api/a2a/a2a_client.py +439 -0
- mindsdb/api/a2a/agent.py +308 -0
- mindsdb/api/a2a/common/__init__.py +0 -0
- mindsdb/api/a2a/common/client/__init__.py +4 -0
- mindsdb/api/a2a/common/client/card_resolver.py +21 -0
- mindsdb/api/a2a/common/client/client.py +86 -0
- mindsdb/api/a2a/common/server/__init__.py +4 -0
- mindsdb/api/a2a/common/server/server.py +164 -0
- mindsdb/api/a2a/common/server/task_manager.py +287 -0
- mindsdb/api/a2a/common/server/utils.py +28 -0
- mindsdb/api/a2a/common/types.py +365 -0
- mindsdb/api/a2a/constants.py +9 -0
- mindsdb/api/a2a/run_a2a.py +129 -0
- mindsdb/api/a2a/task_manager.py +594 -0
- mindsdb/api/executor/command_executor.py +49 -28
- mindsdb/api/executor/datahub/classes/response.py +5 -2
- mindsdb/api/executor/datahub/datanodes/information_schema_datanode.py +8 -0
- mindsdb/api/executor/datahub/datanodes/integration_datanode.py +39 -72
- mindsdb/api/executor/datahub/datanodes/system_tables.py +10 -13
- mindsdb/api/executor/planner/query_planner.py +14 -2
- mindsdb/api/executor/sql_query/result_set.py +185 -52
- mindsdb/api/executor/sql_query/sql_query.py +1 -1
- mindsdb/api/executor/sql_query/steps/apply_predictor_step.py +11 -13
- mindsdb/api/executor/sql_query/steps/fetch_dataframe.py +8 -10
- mindsdb/api/executor/sql_query/steps/fetch_dataframe_partition.py +5 -44
- mindsdb/api/executor/sql_query/steps/insert_step.py +24 -15
- mindsdb/api/executor/sql_query/steps/join_step.py +1 -1
- mindsdb/api/executor/sql_query/steps/project_step.py +1 -1
- mindsdb/api/executor/sql_query/steps/sql_steps.py +1 -1
- mindsdb/api/executor/sql_query/steps/subselect_step.py +4 -8
- mindsdb/api/executor/sql_query/steps/union_step.py +1 -3
- mindsdb/api/http/initialize.py +118 -85
- mindsdb/api/http/namespaces/analysis.py +17 -4
- mindsdb/api/http/namespaces/file.py +8 -2
- mindsdb/api/http/namespaces/sql.py +13 -27
- mindsdb/api/http/namespaces/tree.py +1 -1
- mindsdb/api/http/start.py +7 -2
- mindsdb/api/mcp/start.py +42 -5
- mindsdb/api/mysql/mysql_proxy/data_types/mysql_packet.py +0 -1
- mindsdb/api/mysql/mysql_proxy/data_types/mysql_packets/binary_resultset_row_package.py +52 -19
- mindsdb/api/mysql/mysql_proxy/executor/mysql_executor.py +8 -10
- mindsdb/api/mysql/mysql_proxy/libs/constants/mysql.py +54 -38
- mindsdb/api/mysql/mysql_proxy/mysql_proxy.py +86 -123
- mindsdb/api/mysql/mysql_proxy/utilities/dump.py +351 -0
- mindsdb/api/mysql/mysql_proxy/utilities/exceptions.py +0 -4
- mindsdb/api/postgres/postgres_proxy/executor/executor.py +1 -1
- mindsdb/api/postgres/postgres_proxy/postgres_packets/postgres_message_formats.py +2 -2
- mindsdb/api/postgres/postgres_proxy/postgres_proxy.py +5 -6
- mindsdb/integrations/handlers/altibase_handler/altibase_handler.py +26 -27
- mindsdb/integrations/handlers/altibase_handler/connection_args.py +13 -13
- mindsdb/integrations/handlers/altibase_handler/tests/test_altibase_handler.py +8 -8
- mindsdb/integrations/handlers/altibase_handler/tests/test_altibase_handler_dsn.py +13 -13
- mindsdb/integrations/handlers/anthropic_handler/__init__.py +2 -2
- mindsdb/integrations/handlers/anthropic_handler/anthropic_handler.py +1 -3
- mindsdb/integrations/handlers/aurora_handler/aurora_handler.py +1 -0
- mindsdb/integrations/handlers/autosklearn_handler/autosklearn_handler.py +1 -1
- mindsdb/integrations/handlers/autosklearn_handler/config.py +0 -1
- mindsdb/integrations/handlers/bigquery_handler/bigquery_handler.py +1 -1
- mindsdb/integrations/handlers/bigquery_handler/requirements.txt +1 -0
- mindsdb/integrations/handlers/bigquery_handler/tests/test_bigquery_handler.py +1 -1
- mindsdb/integrations/handlers/binance_handler/binance_handler.py +1 -0
- mindsdb/integrations/handlers/binance_handler/binance_tables.py +3 -4
- mindsdb/integrations/handlers/byom_handler/__init__.py +0 -1
- mindsdb/integrations/handlers/chromadb_handler/requirements.txt +1 -0
- mindsdb/integrations/handlers/ckan_handler/ckan_handler.py +3 -0
- mindsdb/integrations/handlers/clickhouse_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/cloud_spanner_handler/tests/test_cloud_spanner_handler.py +0 -2
- mindsdb/integrations/handlers/cloud_sql_handler/cloud_sql_handler.py +0 -1
- mindsdb/integrations/handlers/cohere_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/cohere_handler/cohere_handler.py +11 -13
- mindsdb/integrations/handlers/confluence_handler/confluence_tables.py +6 -0
- mindsdb/integrations/handlers/databend_handler/connection_args.py +1 -1
- mindsdb/integrations/handlers/databend_handler/databend_handler.py +4 -4
- mindsdb/integrations/handlers/databend_handler/tests/__init__.py +0 -1
- mindsdb/integrations/handlers/databend_handler/tests/test_databend_handler.py +1 -1
- mindsdb/integrations/handlers/derby_handler/connection_args.py +1 -1
- mindsdb/integrations/handlers/derby_handler/derby_handler.py +14 -22
- mindsdb/integrations/handlers/derby_handler/tests/test_derby_handler.py +6 -6
- mindsdb/integrations/handlers/discord_handler/discord_handler.py +5 -5
- mindsdb/integrations/handlers/discord_handler/discord_tables.py +3 -3
- mindsdb/integrations/handlers/discord_handler/tests/test_discord.py +5 -3
- mindsdb/integrations/handlers/dockerhub_handler/dockerhub.py +3 -3
- mindsdb/integrations/handlers/dockerhub_handler/dockerhub_handler.py +2 -2
- mindsdb/integrations/handlers/dockerhub_handler/dockerhub_tables.py +57 -54
- mindsdb/integrations/handlers/dremio_handler/__init__.py +2 -2
- mindsdb/integrations/handlers/druid_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/druid_handler/druid_handler.py +2 -2
- mindsdb/integrations/handlers/edgelessdb_handler/tests/test_edgelessdb_handler.py +9 -9
- mindsdb/integrations/handlers/email_handler/email_client.py +1 -1
- mindsdb/integrations/handlers/email_handler/email_ingestor.py +1 -1
- mindsdb/integrations/handlers/email_handler/email_tables.py +0 -1
- mindsdb/integrations/handlers/email_handler/settings.py +0 -1
- mindsdb/integrations/handlers/eventstoredb_handler/eventstoredb_handler.py +2 -1
- mindsdb/integrations/handlers/firebird_handler/firebird_handler.py +1 -1
- mindsdb/integrations/handlers/flaml_handler/flaml_handler.py +9 -9
- mindsdb/integrations/handlers/frappe_handler/frappe_client.py +5 -5
- mindsdb/integrations/handlers/frappe_handler/frappe_handler.py +6 -5
- mindsdb/integrations/handlers/frappe_handler/frappe_tables.py +2 -2
- mindsdb/integrations/handlers/github_handler/connection_args.py +2 -2
- mindsdb/integrations/handlers/github_handler/github_handler.py +1 -8
- mindsdb/integrations/handlers/github_handler/github_tables.py +13 -24
- mindsdb/integrations/handlers/gitlab_handler/gitlab_handler.py +2 -1
- mindsdb/integrations/handlers/gitlab_handler/gitlab_tables.py +1 -4
- mindsdb/integrations/handlers/gmail_handler/gmail_handler.py +6 -13
- mindsdb/integrations/handlers/gmail_handler/requirements.txt +1 -0
- mindsdb/integrations/handlers/google_analytics_handler/requirements.txt +2 -1
- mindsdb/integrations/handlers/google_books_handler/google_books_handler.py +2 -1
- mindsdb/integrations/handlers/google_books_handler/google_books_tables.py +0 -3
- mindsdb/integrations/handlers/google_books_handler/requirements.txt +1 -1
- mindsdb/integrations/handlers/google_calendar_handler/google_calendar_handler.py +4 -4
- mindsdb/integrations/handlers/google_calendar_handler/google_calendar_tables.py +2 -6
- mindsdb/integrations/handlers/google_calendar_handler/requirements.txt +1 -0
- mindsdb/integrations/handlers/google_content_shopping_handler/google_content_shopping_handler.py +3 -2
- mindsdb/integrations/handlers/google_content_shopping_handler/google_content_shopping_tables.py +0 -3
- mindsdb/integrations/handlers/google_content_shopping_handler/requirements.txt +1 -1
- mindsdb/integrations/handlers/google_fit_handler/google_fit_handler.py +10 -12
- mindsdb/integrations/handlers/google_fit_handler/google_fit_tables.py +11 -13
- mindsdb/integrations/handlers/google_fit_handler/requirements.txt +2 -0
- mindsdb/integrations/handlers/google_search_handler/google_search_handler.py +2 -1
- mindsdb/integrations/handlers/google_search_handler/google_search_tables.py +0 -3
- mindsdb/integrations/handlers/google_search_handler/requirements.txt +1 -1
- mindsdb/integrations/handlers/groq_handler/__init__.py +3 -3
- mindsdb/integrations/handlers/hackernews_handler/hn_handler.py +5 -7
- mindsdb/integrations/handlers/hackernews_handler/hn_table.py +6 -7
- mindsdb/integrations/handlers/hive_handler/tests/test_hive_handler.py +1 -1
- mindsdb/integrations/handlers/hsqldb_handler/connection_args.py +6 -6
- mindsdb/integrations/handlers/hsqldb_handler/hsqldb_handler.py +4 -3
- mindsdb/integrations/handlers/huggingface_api_handler/exceptions.py +1 -1
- mindsdb/integrations/handlers/huggingface_api_handler/huggingface_api_handler.py +1 -8
- mindsdb/integrations/handlers/huggingface_handler/huggingface_handler.py +6 -6
- mindsdb/integrations/handlers/huggingface_handler/requirements.txt +1 -1
- mindsdb/integrations/handlers/huggingface_handler/requirements_cpu.txt +1 -1
- mindsdb/integrations/handlers/ignite_handler/ignite_handler.py +2 -1
- mindsdb/integrations/handlers/impala_handler/impala_handler.py +9 -12
- mindsdb/integrations/handlers/impala_handler/tests/test_impala_handler.py +11 -11
- mindsdb/integrations/handlers/influxdb_handler/influxdb_handler.py +10 -13
- mindsdb/integrations/handlers/influxdb_handler/influxdb_tables.py +20 -20
- mindsdb/integrations/handlers/informix_handler/__about__.py +8 -8
- mindsdb/integrations/handlers/informix_handler/__init__.py +12 -5
- mindsdb/integrations/handlers/informix_handler/informix_handler.py +99 -133
- mindsdb/integrations/handlers/informix_handler/tests/test_informix_handler.py +13 -11
- mindsdb/integrations/handlers/ingres_handler/__about__.py +0 -1
- mindsdb/integrations/handlers/ingres_handler/ingres_handler.py +1 -0
- mindsdb/integrations/handlers/jira_handler/jira_handler.archived.py +75 -0
- mindsdb/integrations/handlers/jira_handler/jira_handler.py +113 -38
- mindsdb/integrations/handlers/jira_handler/jira_tables.py +229 -0
- mindsdb/integrations/handlers/jira_handler/requirements.txt +1 -0
- mindsdb/integrations/handlers/kinetica_handler/__init__.py +0 -1
- mindsdb/integrations/handlers/langchain_handler/langchain_handler.py +4 -4
- mindsdb/integrations/handlers/langchain_handler/tools.py +9 -10
- mindsdb/integrations/handlers/leonardoai_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/lightfm_handler/requirements.txt +1 -0
- mindsdb/integrations/handlers/lightwood_handler/functions.py +2 -2
- mindsdb/integrations/handlers/lightwood_handler/lightwood_handler.py +0 -3
- mindsdb/integrations/handlers/lightwood_handler/requirements.txt +4 -4
- mindsdb/integrations/handlers/lightwood_handler/tests/test_lightwood_handler.py +11 -11
- mindsdb/integrations/handlers/lindorm_handler/requirements.txt +1 -0
- mindsdb/integrations/handlers/llama_index_handler/llama_index_handler.py +4 -4
- mindsdb/integrations/handlers/llama_index_handler/settings.py +10 -9
- mindsdb/integrations/handlers/materialize_handler/tests/test_materialize_handler.py +8 -10
- mindsdb/integrations/handlers/matrixone_handler/matrixone_handler.py +4 -4
- mindsdb/integrations/handlers/matrixone_handler/tests/test_matrixone_handler.py +8 -9
- mindsdb/integrations/handlers/maxdb_handler/connection_args.py +25 -25
- mindsdb/integrations/handlers/maxdb_handler/maxdb_handler.py +1 -0
- mindsdb/integrations/handlers/mediawiki_handler/mediawiki_handler.py +3 -2
- mindsdb/integrations/handlers/mediawiki_handler/mediawiki_tables.py +1 -1
- mindsdb/integrations/handlers/mendeley_handler/__about__.py +1 -1
- mindsdb/integrations/handlers/mendeley_handler/__init__.py +2 -2
- mindsdb/integrations/handlers/mendeley_handler/mendeley_handler.py +48 -56
- mindsdb/integrations/handlers/mendeley_handler/mendeley_tables.py +24 -29
- mindsdb/integrations/handlers/mendeley_handler/tests/test_mendeley_handler.py +19 -17
- mindsdb/integrations/handlers/merlion_handler/merlion_handler.py +5 -4
- mindsdb/integrations/handlers/minds_endpoint_handler/__init__.py +3 -3
- mindsdb/integrations/handlers/mlflow_handler/mlflow_handler.py +58 -36
- mindsdb/integrations/handlers/monetdb_handler/__about__.py +8 -8
- mindsdb/integrations/handlers/monetdb_handler/__init__.py +15 -5
- mindsdb/integrations/handlers/monetdb_handler/connection_args.py +17 -18
- mindsdb/integrations/handlers/monetdb_handler/monetdb_handler.py +40 -57
- mindsdb/integrations/handlers/monetdb_handler/tests/test_monetdb_handler.py +7 -8
- mindsdb/integrations/handlers/monetdb_handler/utils/monet_get_id.py +13 -14
- mindsdb/integrations/handlers/monkeylearn_handler/__about__.py +1 -1
- mindsdb/integrations/handlers/monkeylearn_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/monkeylearn_handler/monkeylearn_handler.py +2 -5
- mindsdb/integrations/handlers/ms_one_drive_handler/ms_graph_api_one_drive_client.py +1 -0
- mindsdb/integrations/handlers/ms_one_drive_handler/ms_one_drive_handler.py +1 -1
- mindsdb/integrations/handlers/ms_one_drive_handler/requirements.txt +2 -0
- mindsdb/integrations/handlers/ms_teams_handler/ms_graph_api_teams_client.py +23 -23
- mindsdb/integrations/handlers/ms_teams_handler/ms_teams_handler.py +3 -3
- mindsdb/integrations/handlers/ms_teams_handler/ms_teams_tables.py +10 -5
- mindsdb/integrations/handlers/ms_teams_handler/requirements.txt +3 -1
- mindsdb/integrations/handlers/mssql_handler/mssql_handler.py +73 -8
- mindsdb/integrations/handlers/mysql_handler/__about__.py +8 -8
- mindsdb/integrations/handlers/mysql_handler/__init__.py +15 -5
- mindsdb/integrations/handlers/mysql_handler/connection_args.py +43 -47
- mindsdb/integrations/handlers/mysql_handler/mysql_handler.py +101 -34
- mindsdb/integrations/handlers/mysql_handler/settings.py +15 -13
- mindsdb/integrations/handlers/neuralforecast_handler/neuralforecast_handler.py +1 -1
- mindsdb/integrations/handlers/newsapi_handler/newsapi_handler.py +1 -1
- mindsdb/integrations/handlers/newsapi_handler/tests/test_newsapi_handler.py +4 -4
- mindsdb/integrations/handlers/nuo_jdbc_handler/connection_args.py +2 -2
- mindsdb/integrations/handlers/nuo_jdbc_handler/nuo_jdbc_handler.py +28 -36
- mindsdb/integrations/handlers/nuo_jdbc_handler/tests/test_nuo_handler.py +5 -5
- mindsdb/integrations/handlers/oceanbase_handler/oceanbase_handler.py +0 -1
- mindsdb/integrations/handlers/oceanbase_handler/tests/test_oceanbase_handler.py +8 -10
- mindsdb/integrations/handlers/ollama_handler/ollama_handler.py +3 -3
- mindsdb/integrations/handlers/openai_handler/openai_handler.py +5 -4
- mindsdb/integrations/handlers/opengauss_handler/tests/test_opengauss_handler.py +1 -2
- mindsdb/integrations/handlers/openstreetmap_handler/__init__.py +7 -7
- mindsdb/integrations/handlers/oracle_handler/connection_args.py +6 -0
- mindsdb/integrations/handlers/oracle_handler/oracle_handler.py +77 -11
- mindsdb/integrations/handlers/orioledb_handler/tests/test_orioledb_handler.py +8 -10
- mindsdb/integrations/handlers/palm_handler/__about__.py +1 -1
- mindsdb/integrations/handlers/palm_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/palm_handler/palm_handler.py +1 -3
- mindsdb/integrations/handlers/paypal_handler/paypal_handler.py +2 -2
- mindsdb/integrations/handlers/paypal_handler/paypal_tables.py +15 -14
- mindsdb/integrations/handlers/pgvector_handler/pgvector_handler.py +53 -10
- mindsdb/integrations/handlers/phoenix_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/phoenix_handler/phoenix_handler.py +1 -0
- mindsdb/integrations/handlers/pinot_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/pinot_handler/pinot_handler.py +3 -2
- mindsdb/integrations/handlers/plaid_handler/plaid_handler.py +13 -13
- mindsdb/integrations/handlers/plaid_handler/plaid_tables.py +10 -12
- mindsdb/integrations/handlers/plaid_handler/utils.py +4 -6
- mindsdb/integrations/handlers/planetscale_handler/planetscale_handler.py +1 -4
- mindsdb/integrations/handlers/portkey_handler/__init__.py +2 -2
- mindsdb/integrations/handlers/postgres_handler/postgres_handler.py +105 -24
- mindsdb/integrations/handlers/postgres_handler/tests/test_postgres_handler.py +11 -6
- mindsdb/integrations/handlers/questdb_handler/questdb_handler.py +1 -2
- mindsdb/integrations/handlers/questdb_handler/tests/test_questdb_handler.py +2 -3
- mindsdb/integrations/handlers/quickbooks_handler/quickbooks_handler.py +6 -8
- mindsdb/integrations/handlers/quickbooks_handler/quickbooks_table.py +10 -10
- mindsdb/integrations/handlers/rag_handler/ingest.py +2 -2
- mindsdb/integrations/handlers/rag_handler/rag_handler.py +1 -1
- mindsdb/integrations/handlers/rag_handler/settings.py +1 -1
- mindsdb/integrations/handlers/reddit_handler/reddit_handler.py +2 -7
- mindsdb/integrations/handlers/reddit_handler/reddit_tables.py +2 -3
- mindsdb/integrations/handlers/replicate_handler/replicate_handler.py +6 -6
- mindsdb/integrations/handlers/rocket_chat_handler/rocket_chat_handler.py +1 -2
- mindsdb/integrations/handlers/rocket_chat_handler/rocket_chat_tables.py +0 -3
- mindsdb/integrations/handlers/rockset_handler/connection_args.py +14 -14
- mindsdb/integrations/handlers/rockset_handler/tests/test_rockset_handler.py +1 -0
- mindsdb/integrations/handlers/scylla_handler/scylla_handler.py +6 -5
- mindsdb/integrations/handlers/sendinblue_handler/sendinblue_handler.py +2 -1
- mindsdb/integrations/handlers/sendinblue_handler/sendinblue_tables.py +16 -16
- mindsdb/integrations/handlers/sentence_transformers_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/sheets_handler/connection_args.py +1 -1
- mindsdb/integrations/handlers/shopify_handler/shopify_handler.py +7 -6
- mindsdb/integrations/handlers/shopify_handler/shopify_tables.py +38 -41
- mindsdb/integrations/handlers/singlestore_handler/__about__.py +1 -1
- mindsdb/integrations/handlers/singlestore_handler/__init__.py +0 -1
- mindsdb/integrations/handlers/singlestore_handler/singlestore_handler.py +1 -0
- mindsdb/integrations/handlers/singlestore_handler/tests/test_singlestore_handler.py +3 -3
- mindsdb/integrations/handlers/slack_handler/__init__.py +3 -3
- mindsdb/integrations/handlers/snowflake_handler/requirements.txt +1 -1
- mindsdb/integrations/handlers/snowflake_handler/snowflake_handler.py +100 -6
- mindsdb/integrations/handlers/solr_handler/connection_args.py +7 -7
- mindsdb/integrations/handlers/solr_handler/solr_handler.py +2 -1
- mindsdb/integrations/handlers/solr_handler/tests/test_solr_handler.py +2 -1
- mindsdb/integrations/handlers/sqlany_handler/sqlany_handler.py +3 -2
- mindsdb/integrations/handlers/sqlite_handler/sqlite_handler.py +1 -0
- mindsdb/integrations/handlers/sqreamdb_handler/connection_args.py +1 -1
- mindsdb/integrations/handlers/sqreamdb_handler/sqreamdb_handler.py +15 -20
- mindsdb/integrations/handlers/sqreamdb_handler/tests/test_sqreamdb_handler.py +4 -4
- mindsdb/integrations/handlers/stabilityai_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/starrocks_handler/starrocks_handler.py +0 -1
- mindsdb/integrations/handlers/starrocks_handler/tests/test_starrocks_handler.py +8 -10
- mindsdb/integrations/handlers/statsforecast_handler/statsforecast_handler.py +2 -2
- mindsdb/integrations/handlers/strava_handler/strava_handler.py +4 -8
- mindsdb/integrations/handlers/strava_handler/strava_tables.py +22 -30
- mindsdb/integrations/handlers/stripe_handler/stripe_handler.py +3 -2
- mindsdb/integrations/handlers/stripe_handler/stripe_tables.py +11 -27
- mindsdb/integrations/handlers/supabase_handler/tests/test_supabase_handler.py +1 -1
- mindsdb/integrations/handlers/surrealdb_handler/surrealdb_handler.py +4 -4
- mindsdb/integrations/handlers/tdengine_handler/tdengine_handler.py +25 -27
- mindsdb/integrations/handlers/tdengine_handler/tests/test_tdengine_handler.py +8 -8
- mindsdb/integrations/handlers/tidb_handler/tests/test_tidb_handler.py +1 -2
- mindsdb/integrations/handlers/timegpt_handler/timegpt_handler.py +5 -5
- mindsdb/integrations/handlers/tpot_handler/tpot_handler.py +21 -26
- mindsdb/integrations/handlers/trino_handler/trino_handler.py +14 -14
- mindsdb/integrations/handlers/twitter_handler/twitter_handler.py +2 -4
- mindsdb/integrations/handlers/unify_handler/tests/test_unify_handler.py +7 -8
- mindsdb/integrations/handlers/unify_handler/unify_handler.py +9 -9
- mindsdb/integrations/handlers/vertex_handler/requirements.txt +1 -0
- mindsdb/integrations/handlers/vertex_handler/vertex_client.py +1 -1
- mindsdb/integrations/handlers/vertica_handler/tests/test_vertica_handler.py +11 -11
- mindsdb/integrations/handlers/vertica_handler/vertica_handler.py +11 -14
- mindsdb/integrations/handlers/vitess_handler/tests/test_vitess_handler.py +9 -11
- mindsdb/integrations/handlers/vitess_handler/vitess_handler.py +0 -1
- mindsdb/integrations/handlers/web_handler/web_handler.py +1 -0
- mindsdb/integrations/handlers/whatsapp_handler/__init__.py +3 -3
- mindsdb/integrations/handlers/writer_handler/evaluate.py +1 -1
- mindsdb/integrations/handlers/writer_handler/settings.py +0 -1
- mindsdb/integrations/handlers/writer_handler/writer_handler.py +1 -0
- mindsdb/integrations/handlers/youtube_handler/requirements.txt +1 -0
- mindsdb/integrations/handlers/youtube_handler/youtube_handler.py +5 -5
- mindsdb/integrations/handlers/youtube_handler/youtube_tables.py +26 -27
- mindsdb/integrations/handlers/yugabyte_handler/tests/test_yugabyte_handler.py +3 -3
- mindsdb/integrations/handlers/yugabyte_handler/yugabyte_handler.py +0 -6
- mindsdb/integrations/libs/response.py +67 -52
- mindsdb/integrations/libs/vectordatabase_handler.py +6 -0
- mindsdb/integrations/utilities/files/file_reader.py +5 -2
- mindsdb/integrations/utilities/handler_utils.py +15 -3
- mindsdb/integrations/utilities/handlers/api_utilities/__init__.py +0 -1
- mindsdb/integrations/utilities/handlers/auth_utilities/__init__.py +0 -2
- mindsdb/integrations/utilities/utils.py +3 -3
- mindsdb/interfaces/agents/agents_controller.py +164 -1
- mindsdb/interfaces/agents/constants.py +29 -2
- mindsdb/interfaces/agents/langchain_agent.py +18 -8
- mindsdb/interfaces/agents/mindsdb_database_agent.py +101 -2
- mindsdb/interfaces/database/projects.py +1 -7
- mindsdb/interfaces/functions/controller.py +11 -14
- mindsdb/interfaces/functions/to_markdown.py +9 -124
- mindsdb/interfaces/knowledge_base/controller.py +47 -19
- mindsdb/interfaces/knowledge_base/preprocessing/document_preprocessor.py +41 -15
- mindsdb/interfaces/knowledge_base/preprocessing/json_chunker.py +434 -0
- mindsdb/interfaces/knowledge_base/preprocessing/models.py +54 -0
- mindsdb/interfaces/knowledge_base/utils.py +10 -15
- mindsdb/interfaces/model/model_controller.py +0 -2
- mindsdb/interfaces/query_context/context_controller.py +66 -10
- mindsdb/interfaces/skills/custom/text2sql/mindsdb_kb_tools.py +190 -0
- mindsdb/interfaces/skills/custom/text2sql/mindsdb_sql_toolkit.py +92 -0
- mindsdb/interfaces/skills/skill_tool.py +202 -57
- mindsdb/interfaces/skills/sql_agent.py +238 -28
- mindsdb/interfaces/storage/fs.py +1 -0
- mindsdb/interfaces/variables/__init__.py +0 -0
- mindsdb/interfaces/variables/variables_controller.py +97 -0
- mindsdb/migrations/env.py +5 -7
- mindsdb/migrations/migrate.py +47 -9
- mindsdb/migrations/versions/2025-05-21_9f150e4f9a05_checkpoint_1.py +360 -0
- mindsdb/utilities/config.py +333 -220
- mindsdb/utilities/context.py +1 -1
- mindsdb/utilities/functions.py +0 -36
- mindsdb/utilities/langfuse.py +19 -10
- mindsdb/utilities/otel/__init__.py +9 -193
- mindsdb/utilities/otel/metric_handlers/__init__.py +5 -1
- mindsdb/utilities/otel/prepare.py +198 -0
- mindsdb/utilities/sql.py +83 -0
- mindsdb/utilities/starters.py +13 -0
- {mindsdb-25.4.5.0.dist-info → mindsdb-25.5.4.0.dist-info}/METADATA +351 -338
- {mindsdb-25.4.5.0.dist-info → mindsdb-25.5.4.0.dist-info}/RECORD +348 -322
- {mindsdb-25.4.5.0.dist-info → mindsdb-25.5.4.0.dist-info}/WHEEL +1 -1
- mindsdb/api/mysql/mysql_proxy/classes/sql_statement_parser.py +0 -151
- mindsdb/integrations/handlers/monkeylearn_handler/requirements.txt +0 -1
- {mindsdb-25.4.5.0.dist-info → mindsdb-25.5.4.0.dist-info}/licenses/LICENSE +0 -0
- {mindsdb-25.4.5.0.dist-info → mindsdb-25.5.4.0.dist-info}/top_level.txt +0 -0
|
@@ -19,9 +19,10 @@ from mindsdb.utilities.exception import EntityExistsError, EntityNotExistsError
|
|
|
19
19
|
from .constants import ASSISTANT_COLUMN, SUPPORTED_PROVIDERS, PROVIDER_TO_MODELS
|
|
20
20
|
from .langchain_agent import get_llm_provider
|
|
21
21
|
|
|
22
|
-
|
|
23
22
|
default_project = config.get('default_project')
|
|
24
23
|
|
|
24
|
+
DEFAULT_TEXT2SQL_DATABASE = 'mindsdb'
|
|
25
|
+
|
|
25
26
|
|
|
26
27
|
class AgentsController:
|
|
27
28
|
'''Handles CRUD operations at the database level for Agents'''
|
|
@@ -158,6 +159,13 @@ class AgentsController:
|
|
|
158
159
|
with one of keys is "name", and other is additional parameters for relationship agent<>skill
|
|
159
160
|
provider (str): The provider of the model
|
|
160
161
|
params (Dict[str, str]): Parameters to use when running the agent
|
|
162
|
+
database: The database to use for text2sql skills (default is 'mindsdb')
|
|
163
|
+
knowledge_base_database: The database to use for knowledge base queries (default is 'mindsdb')
|
|
164
|
+
include_tables: List of tables to include for text2sql skills
|
|
165
|
+
ignore_tables: List of tables to ignore for text2sql skills
|
|
166
|
+
include_knowledge_bases: List of knowledge bases to include for text2sql skills
|
|
167
|
+
ignore_knowledge_bases: List of knowledge bases to ignore for text2sql skills
|
|
168
|
+
<provider>_api_key: API key for the provider (e.g., openai_api_key)
|
|
161
169
|
|
|
162
170
|
Returns:
|
|
163
171
|
agent (db.Agents): The created agent
|
|
@@ -176,6 +184,128 @@ class AgentsController:
|
|
|
176
184
|
|
|
177
185
|
_, provider = self.check_model_provider(model_name, provider)
|
|
178
186
|
|
|
187
|
+
# Extract API key if provided in the format <provider>_api_key
|
|
188
|
+
provider_api_key_param = f"{provider.lower()}_api_key"
|
|
189
|
+
if provider_api_key_param in params:
|
|
190
|
+
# Keep the API key in params for the agent to use
|
|
191
|
+
# It will be picked up by get_api_key() in handler_utils.py
|
|
192
|
+
pass
|
|
193
|
+
|
|
194
|
+
# Extract table and knowledge base parameters from params
|
|
195
|
+
database = params.pop('database', None)
|
|
196
|
+
knowledge_base_database = params.pop('knowledge_base_database', DEFAULT_TEXT2SQL_DATABASE)
|
|
197
|
+
include_tables = params.pop('include_tables', None)
|
|
198
|
+
ignore_tables = params.pop('ignore_tables', None)
|
|
199
|
+
include_knowledge_bases = params.pop('include_knowledge_bases', None)
|
|
200
|
+
ignore_knowledge_bases = params.pop('ignore_knowledge_bases', None)
|
|
201
|
+
|
|
202
|
+
# Save the extracted parameters back to params for API responses only if they were explicitly provided
|
|
203
|
+
# or if they're needed for skills
|
|
204
|
+
need_params = include_tables or ignore_tables or include_knowledge_bases or ignore_knowledge_bases
|
|
205
|
+
|
|
206
|
+
if 'database' in params or need_params:
|
|
207
|
+
params['database'] = database
|
|
208
|
+
|
|
209
|
+
if 'knowledge_base_database' in params or include_knowledge_bases or ignore_knowledge_bases:
|
|
210
|
+
params['knowledge_base_database'] = knowledge_base_database
|
|
211
|
+
|
|
212
|
+
if include_tables is not None:
|
|
213
|
+
params['include_tables'] = include_tables
|
|
214
|
+
if ignore_tables is not None:
|
|
215
|
+
params['ignore_tables'] = ignore_tables
|
|
216
|
+
if include_knowledge_bases is not None:
|
|
217
|
+
params['include_knowledge_bases'] = include_knowledge_bases
|
|
218
|
+
if ignore_knowledge_bases is not None:
|
|
219
|
+
params['ignore_knowledge_bases'] = ignore_knowledge_bases
|
|
220
|
+
|
|
221
|
+
# Convert string parameters to lists if needed
|
|
222
|
+
if isinstance(include_tables, str):
|
|
223
|
+
include_tables = [t.strip() for t in include_tables.split(',')]
|
|
224
|
+
if isinstance(ignore_tables, str):
|
|
225
|
+
ignore_tables = [t.strip() for t in ignore_tables.split(',')]
|
|
226
|
+
if isinstance(include_knowledge_bases, str):
|
|
227
|
+
include_knowledge_bases = [kb.strip() for kb in include_knowledge_bases.split(',')]
|
|
228
|
+
if isinstance(ignore_knowledge_bases, str):
|
|
229
|
+
ignore_knowledge_bases = [kb.strip() for kb in ignore_knowledge_bases.split(',')]
|
|
230
|
+
|
|
231
|
+
# Auto-create SQL skill if no skills are provided but include_tables or include_knowledge_bases params are provided
|
|
232
|
+
if not skills and (include_tables or include_knowledge_bases):
|
|
233
|
+
# Determine database to use (default to 'mindsdb')
|
|
234
|
+
db_name = database
|
|
235
|
+
kb_db_name = knowledge_base_database
|
|
236
|
+
|
|
237
|
+
# If database is not explicitly provided but tables are, try to extract the database name from the first table
|
|
238
|
+
if not database and include_tables and len(include_tables) > 0:
|
|
239
|
+
parts = include_tables[0].split('.')
|
|
240
|
+
if len(parts) >= 2:
|
|
241
|
+
db_name = parts[0]
|
|
242
|
+
elif not database and ignore_tables and len(ignore_tables) > 0:
|
|
243
|
+
parts = ignore_tables[0].split('.')
|
|
244
|
+
if len(parts) >= 2:
|
|
245
|
+
db_name = parts[0]
|
|
246
|
+
|
|
247
|
+
# Create a default SQL skill
|
|
248
|
+
skill_name = f"{name}_sql_skill"
|
|
249
|
+
skill_params = {
|
|
250
|
+
'type': 'sql',
|
|
251
|
+
'database': db_name,
|
|
252
|
+
'description': f'Auto-generated SQL skill for agent {name}'
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
# Add knowledge base database if provided
|
|
256
|
+
if knowledge_base_database:
|
|
257
|
+
skill_params['knowledge_base_database'] = knowledge_base_database
|
|
258
|
+
|
|
259
|
+
# Add knowledge base parameters if provided
|
|
260
|
+
if include_knowledge_bases:
|
|
261
|
+
skill_params['include_knowledge_bases'] = include_knowledge_bases
|
|
262
|
+
if ignore_knowledge_bases:
|
|
263
|
+
skill_params['ignore_knowledge_bases'] = ignore_knowledge_bases
|
|
264
|
+
|
|
265
|
+
try:
|
|
266
|
+
# Check if skill already exists
|
|
267
|
+
existing_skill = self.skills_controller.get_skill(skill_name, project_name)
|
|
268
|
+
if existing_skill is None:
|
|
269
|
+
# Create the skill
|
|
270
|
+
skill_type = skill_params.pop('type')
|
|
271
|
+
self.skills_controller.add_skill(
|
|
272
|
+
name=skill_name,
|
|
273
|
+
project_name=project_name,
|
|
274
|
+
type=skill_type,
|
|
275
|
+
params=skill_params
|
|
276
|
+
)
|
|
277
|
+
else:
|
|
278
|
+
# Update the skill if parameters have changed
|
|
279
|
+
params_changed = False
|
|
280
|
+
|
|
281
|
+
# Check if database has changed
|
|
282
|
+
if existing_skill.params.get('database') != db_name:
|
|
283
|
+
existing_skill.params['database'] = db_name
|
|
284
|
+
params_changed = True
|
|
285
|
+
|
|
286
|
+
# Check if knowledge base database has changed
|
|
287
|
+
if knowledge_base_database and existing_skill.params.get('knowledge_base_database') != kb_db_name:
|
|
288
|
+
existing_skill.params['knowledge_base_database'] = kb_db_name
|
|
289
|
+
params_changed = True
|
|
290
|
+
|
|
291
|
+
# Check if knowledge base parameters have changed
|
|
292
|
+
if include_knowledge_bases and existing_skill.params.get('include_knowledge_bases') != include_knowledge_bases:
|
|
293
|
+
existing_skill.params['include_knowledge_bases'] = include_knowledge_bases
|
|
294
|
+
params_changed = True
|
|
295
|
+
|
|
296
|
+
if ignore_knowledge_bases and existing_skill.params.get('ignore_knowledge_bases') != ignore_knowledge_bases:
|
|
297
|
+
existing_skill.params['ignore_knowledge_bases'] = ignore_knowledge_bases
|
|
298
|
+
params_changed = True
|
|
299
|
+
|
|
300
|
+
# Update the skill if needed
|
|
301
|
+
if params_changed:
|
|
302
|
+
flag_modified(existing_skill, 'params')
|
|
303
|
+
db.session.commit()
|
|
304
|
+
|
|
305
|
+
skills = [skill_name]
|
|
306
|
+
except Exception as e:
|
|
307
|
+
raise ValueError(f"Failed to auto-create or update SQL skill: {str(e)}")
|
|
308
|
+
|
|
179
309
|
agent = db.Agents(
|
|
180
310
|
name=name,
|
|
181
311
|
project_id=project.id,
|
|
@@ -193,10 +323,43 @@ class AgentsController:
|
|
|
193
323
|
else:
|
|
194
324
|
parameters = skill.copy()
|
|
195
325
|
skill_name = parameters.pop('name')
|
|
326
|
+
|
|
196
327
|
existing_skill = self.skills_controller.get_skill(skill_name, project_name)
|
|
197
328
|
if existing_skill is None:
|
|
198
329
|
db.session.rollback()
|
|
199
330
|
raise ValueError(f'Skill with name does not exist: {skill_name}')
|
|
331
|
+
|
|
332
|
+
# Add table restrictions if this is a text2sql skill
|
|
333
|
+
if existing_skill.type == 'sql' and (include_tables or ignore_tables):
|
|
334
|
+
parameters['tables'] = include_tables or ignore_tables
|
|
335
|
+
|
|
336
|
+
# Add knowledge base restrictions if this is a text2sql skill
|
|
337
|
+
if existing_skill.type == 'sql':
|
|
338
|
+
# Pass database parameter if provided
|
|
339
|
+
if database and 'database' not in parameters:
|
|
340
|
+
parameters['database'] = database
|
|
341
|
+
|
|
342
|
+
# Pass knowledge base database parameter if provided
|
|
343
|
+
if knowledge_base_database and 'knowledge_base_database' not in parameters:
|
|
344
|
+
parameters['knowledge_base_database'] = knowledge_base_database
|
|
345
|
+
|
|
346
|
+
# Add knowledge base parameters to both the skill and the association parameters
|
|
347
|
+
if include_knowledge_bases:
|
|
348
|
+
parameters['include_knowledge_bases'] = include_knowledge_bases
|
|
349
|
+
if 'include_knowledge_bases' not in existing_skill.params:
|
|
350
|
+
existing_skill.params['include_knowledge_bases'] = include_knowledge_bases
|
|
351
|
+
flag_modified(existing_skill, 'params')
|
|
352
|
+
elif ignore_knowledge_bases:
|
|
353
|
+
parameters['ignore_knowledge_bases'] = ignore_knowledge_bases
|
|
354
|
+
if 'ignore_knowledge_bases' not in existing_skill.params:
|
|
355
|
+
existing_skill.params['ignore_knowledge_bases'] = ignore_knowledge_bases
|
|
356
|
+
flag_modified(existing_skill, 'params')
|
|
357
|
+
|
|
358
|
+
# Ensure knowledge_base_database is set in the skill's params
|
|
359
|
+
if knowledge_base_database and 'knowledge_base_database' not in existing_skill.params:
|
|
360
|
+
existing_skill.params['knowledge_base_database'] = knowledge_base_database
|
|
361
|
+
flag_modified(existing_skill, 'params')
|
|
362
|
+
|
|
200
363
|
association = db.AgentSkillsAssociation(
|
|
201
364
|
parameters=parameters,
|
|
202
365
|
agent=agent,
|
|
@@ -4,8 +4,20 @@ from langchain.agents import AgentType
|
|
|
4
4
|
from langchain_openai import OpenAIEmbeddings
|
|
5
5
|
|
|
6
6
|
from types import MappingProxyType
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
|
|
8
|
+
# the same as
|
|
9
|
+
# from mindsdb.integrations.handlers.openai_handler.constants import CHAT_MODELS
|
|
10
|
+
OPEN_AI_CHAT_MODELS = (
|
|
11
|
+
'gpt-3.5-turbo',
|
|
12
|
+
'gpt-3.5-turbo-16k',
|
|
13
|
+
'gpt-3.5-turbo-instruct',
|
|
14
|
+
'gpt-4',
|
|
15
|
+
'gpt-4-32k',
|
|
16
|
+
'gpt-4-1106-preview',
|
|
17
|
+
'gpt-4-0125-preview',
|
|
18
|
+
'gpt-4o',
|
|
19
|
+
'o3-mini',
|
|
20
|
+
'o1-mini'
|
|
9
21
|
)
|
|
10
22
|
|
|
11
23
|
SUPPORTED_PROVIDERS = {
|
|
@@ -190,3 +202,18 @@ DEFAULT_EMBEDDINGS_MODEL_PROVIDER = "openai"
|
|
|
190
202
|
DEFAULT_EMBEDDINGS_MODEL_CLASS = OpenAIEmbeddings
|
|
191
203
|
DEFAULT_TIKTOKEN_MODEL_NAME = os.getenv('DEFAULT_TIKTOKEN_MODEL_NAME', 'gpt-4')
|
|
192
204
|
AGENT_CHUNK_POLLING_INTERVAL_SECONDS = os.getenv('AGENT_CHUNK_POLLING_INTERVAL_SECONDS', 1.0)
|
|
205
|
+
DEFAULT_TEXT2SQL_DATABASE = "mindsdb"
|
|
206
|
+
DEFAULT_AGENT_SYSTEM_PROMPT = """
|
|
207
|
+
You are an AI assistant powered by MindsDB. When answering questions, follow these guidelines:
|
|
208
|
+
|
|
209
|
+
1. For factual questions about specific topics, use the knowledge base tools in this sequence:
|
|
210
|
+
- First use kb_list_tool to see available knowledge bases
|
|
211
|
+
- Then use kb_info_tool to understand the structure of relevant knowledge bases
|
|
212
|
+
- Finally use kb_query_tool to query the knowledge base for specific information
|
|
213
|
+
|
|
214
|
+
2. For questions about database tables and their contents:
|
|
215
|
+
- Use the sql_tool to query the tables directly
|
|
216
|
+
- You can join tables if needed to get comprehensive information
|
|
217
|
+
|
|
218
|
+
For factual questions, ALWAYS use the available tools to look up information rather than relying on your internal knowledge.
|
|
219
|
+
"""
|
|
@@ -24,9 +24,6 @@ from langchain_core.messages.base import BaseMessage
|
|
|
24
24
|
from langchain_core.prompts import PromptTemplate
|
|
25
25
|
from langchain_core.tools import Tool
|
|
26
26
|
|
|
27
|
-
from mindsdb.integrations.handlers.openai_handler.constants import (
|
|
28
|
-
CHAT_MODELS as OPEN_AI_CHAT_MODELS,
|
|
29
|
-
)
|
|
30
27
|
from mindsdb.integrations.libs.llm.utils import get_llm_config
|
|
31
28
|
from mindsdb.integrations.utilities.handler_utils import get_api_key
|
|
32
29
|
from mindsdb.integrations.utilities.rag.settings import DEFAULT_RAG_PROMPT_TEMPLATE
|
|
@@ -42,7 +39,8 @@ from .callback_handlers import LogCallbackHandler, ContextCaptureCallback
|
|
|
42
39
|
from .langfuse_callback_handler import LangfuseCallbackHandler, get_skills
|
|
43
40
|
from .safe_output_parser import SafeOutputParser
|
|
44
41
|
|
|
45
|
-
from .constants import (
|
|
42
|
+
from mindsdb.interfaces.agents.constants import (
|
|
43
|
+
OPEN_AI_CHAT_MODELS,
|
|
46
44
|
DEFAULT_AGENT_TIMEOUT_SECONDS,
|
|
47
45
|
DEFAULT_AGENT_TYPE,
|
|
48
46
|
DEFAULT_EMBEDDINGS_MODEL_PROVIDER,
|
|
@@ -56,7 +54,8 @@ from .constants import (
|
|
|
56
54
|
NVIDIA_NIM_CHAT_MODELS,
|
|
57
55
|
USER_COLUMN,
|
|
58
56
|
ASSISTANT_COLUMN,
|
|
59
|
-
CONTEXT_COLUMN, TRACE_ID_COLUMN
|
|
57
|
+
CONTEXT_COLUMN, TRACE_ID_COLUMN,
|
|
58
|
+
DEFAULT_AGENT_SYSTEM_PROMPT
|
|
60
59
|
)
|
|
61
60
|
from mindsdb.interfaces.skills.skill_tool import skill_tool, SkillData
|
|
62
61
|
from langchain_anthropic import ChatAnthropic
|
|
@@ -175,6 +174,10 @@ def create_chat_model(args: Dict):
|
|
|
175
174
|
|
|
176
175
|
def prepare_prompts(df, base_template, input_variables, user_column=USER_COLUMN):
|
|
177
176
|
empty_prompt_ids = np.where(df[input_variables].isna().all(axis=1).values)[0]
|
|
177
|
+
|
|
178
|
+
# Combine system prompt with user-provided template
|
|
179
|
+
base_template = f"{DEFAULT_AGENT_SYSTEM_PROMPT}\n\n{base_template}"
|
|
180
|
+
|
|
178
181
|
base_template = base_template.replace('{{', '{').replace('}}', '}')
|
|
179
182
|
prompts = []
|
|
180
183
|
|
|
@@ -196,8 +199,9 @@ def prepare_callbacks(self, args):
|
|
|
196
199
|
return callbacks, context_callback
|
|
197
200
|
|
|
198
201
|
|
|
199
|
-
def handle_agent_error(e):
|
|
200
|
-
error_message
|
|
202
|
+
def handle_agent_error(e, error_message=None):
|
|
203
|
+
if error_message is None:
|
|
204
|
+
error_message = f"An error occurred during agent execution: {str(e)}"
|
|
201
205
|
logger.error(error_message, exc_info=True)
|
|
202
206
|
return error_message
|
|
203
207
|
|
|
@@ -526,7 +530,13 @@ AI: {response}"""
|
|
|
526
530
|
output = result['output'] if isinstance(result, dict) and 'output' in result else str(result)
|
|
527
531
|
return {CONTEXT_COLUMN: captured_context, ASSISTANT_COLUMN: output}
|
|
528
532
|
except Exception as e:
|
|
529
|
-
|
|
533
|
+
error_message = str(e)
|
|
534
|
+
# Special handling for API key errors
|
|
535
|
+
if "API key" in error_message and ("not found" in error_message or "missing" in error_message):
|
|
536
|
+
# Format API key error more clearly
|
|
537
|
+
logger.error(f"API Key Error: {error_message}")
|
|
538
|
+
error_message = f"API Key Error: {error_message}"
|
|
539
|
+
return {CONTEXT_COLUMN: [], ASSISTANT_COLUMN: handle_agent_error(e, error_message)}
|
|
530
540
|
|
|
531
541
|
completions = []
|
|
532
542
|
contexts = []
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Wrapper around MindsDB's executor and integration controller following the implementation of the original
|
|
3
3
|
langchain.sql_database.SQLDatabase class to partly replicate its behavior.
|
|
4
4
|
"""
|
|
5
|
+
import traceback
|
|
5
6
|
from typing import Any, Iterable, List, Optional
|
|
6
7
|
|
|
7
8
|
from mindsdb.utilities import log
|
|
@@ -57,8 +58,20 @@ class MindsDBSQL(SQLDatabase):
|
|
|
57
58
|
"""Information about all tables in the database."""
|
|
58
59
|
return self._sql_agent.get_table_info()
|
|
59
60
|
|
|
61
|
+
@property
|
|
62
|
+
def kb_info(self) -> str:
|
|
63
|
+
"""Information about all knowledge bases in the database."""
|
|
64
|
+
return self._sql_agent.get_knowledge_base_info()
|
|
65
|
+
|
|
60
66
|
def get_usable_table_names(self) -> Iterable[str]:
|
|
61
|
-
|
|
67
|
+
"""Information about all tables in the database."""
|
|
68
|
+
try:
|
|
69
|
+
return self._sql_agent.get_usable_table_names()
|
|
70
|
+
except Exception as e:
|
|
71
|
+
# If there's an error accessing tables through the integration, handle it gracefully
|
|
72
|
+
logger.warning(f"Error getting usable table names: {str(e)}")
|
|
73
|
+
# Return an empty list instead of raising an exception
|
|
74
|
+
return []
|
|
62
75
|
|
|
63
76
|
def get_table_info_no_throw(self, table_names: Optional[List[str]] = None) -> str:
|
|
64
77
|
for i in range(len(table_names)):
|
|
@@ -66,5 +79,91 @@ class MindsDBSQL(SQLDatabase):
|
|
|
66
79
|
return self._sql_agent.get_table_info_safe(table_names)
|
|
67
80
|
|
|
68
81
|
def run_no_throw(self, command: str, fetch: str = "all") -> str:
|
|
82
|
+
"""Execute a SQL command and return the result as a string.
|
|
83
|
+
|
|
84
|
+
This method catches any exceptions and returns an error message instead of raising an exception.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
command: The SQL command to execute
|
|
88
|
+
fetch: Whether to fetch 'all' results or just 'one'
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
A string representation of the result or an error message
|
|
92
|
+
"""
|
|
69
93
|
command = extract_essential(command)
|
|
70
|
-
|
|
94
|
+
|
|
95
|
+
try:
|
|
96
|
+
|
|
97
|
+
# Log the query for debugging
|
|
98
|
+
logger.info(f"Executing SQL query: {command}")
|
|
99
|
+
|
|
100
|
+
# remove backticks
|
|
101
|
+
command = command.replace('`', '')
|
|
102
|
+
|
|
103
|
+
# Parse the SQL string to an AST object first
|
|
104
|
+
from mindsdb_sql_parser import parse_sql
|
|
105
|
+
ast_query = parse_sql(command)
|
|
106
|
+
|
|
107
|
+
# Now execute the parsed query
|
|
108
|
+
result = self._sql_agent.skill_tool.get_command_executor().execute_command(ast_query, database_name="mindsdb")
|
|
109
|
+
|
|
110
|
+
# Convert ExecuteAnswer to a DataFrame for easier manipulation
|
|
111
|
+
df = None
|
|
112
|
+
if hasattr(result, 'data') and hasattr(result.data, 'data_frame'):
|
|
113
|
+
df = result.data.data_frame
|
|
114
|
+
else:
|
|
115
|
+
# Fallback to to_df when data_frame attr not available
|
|
116
|
+
try:
|
|
117
|
+
df = result.data.to_df()
|
|
118
|
+
except Exception:
|
|
119
|
+
df = None
|
|
120
|
+
|
|
121
|
+
# Default behaviour (string)
|
|
122
|
+
if df is not None:
|
|
123
|
+
if not df.empty:
|
|
124
|
+
return df.to_string(index=False)
|
|
125
|
+
else:
|
|
126
|
+
return "Query executed successfully, but returned no data."
|
|
127
|
+
|
|
128
|
+
return str(result)
|
|
129
|
+
|
|
130
|
+
except Exception as e:
|
|
131
|
+
logger.error(f"Error executing SQL command: {str(e)}\n{traceback.format_exc()}")
|
|
132
|
+
# If this is a knowledge base query, provide a more helpful error message
|
|
133
|
+
if "knowledge_base" in command.lower() or any(kb in command for kb in self._sql_agent.get_usable_knowledge_base_names()):
|
|
134
|
+
return f"Error executing knowledge base query: {str(e)}. Please check that the knowledge base exists and your query syntax is correct."
|
|
135
|
+
return f"Error: {str(e)}"
|
|
136
|
+
|
|
137
|
+
# def run_no_throw(self, command: str, fetch: str = "all") -> str:
|
|
138
|
+
# """Execute a SQL command and return the result as a string.
|
|
139
|
+
#
|
|
140
|
+
# This method catches any exceptions and returns an error message instead of raising an exception.
|
|
141
|
+
#
|
|
142
|
+
# Args:
|
|
143
|
+
# command: The SQL command to execute
|
|
144
|
+
# fetch: Whether to fetch 'all' results or just 'one'
|
|
145
|
+
#
|
|
146
|
+
# Returns:
|
|
147
|
+
# A string representation of the result or an error message
|
|
148
|
+
# """
|
|
149
|
+
# command = extract_essential(command)
|
|
150
|
+
# try:
|
|
151
|
+
# return self._sql_agent.query_safe(command)
|
|
152
|
+
# except Exception as e:
|
|
153
|
+
# logger.error(f"Error executing SQL command: {str(e)}")
|
|
154
|
+
# # If this is a knowledge base query, provide a more helpful error message
|
|
155
|
+
# if "knowledge_base" in command.lower() or any(kb in command for kb in self._sql_agent.get_usable_knowledge_base_names()):
|
|
156
|
+
# return f"Error executing knowledge base query: {str(e)}. Please check that the knowledge base exists and your query syntax is correct."
|
|
157
|
+
# return f"Error: {str(e)}"
|
|
158
|
+
|
|
159
|
+
def get_usable_knowledge_base_names(self) -> List[str]:
|
|
160
|
+
"""Get a list of usable knowledge base names.
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
A list of knowledge base names that can be used in queries
|
|
164
|
+
"""
|
|
165
|
+
try:
|
|
166
|
+
return self._sql_agent.get_usable_knowledge_base_names()
|
|
167
|
+
except Exception as e:
|
|
168
|
+
logger.error(f"Error getting usable knowledge base names: {str(e)}")
|
|
169
|
+
return []
|
|
@@ -4,7 +4,6 @@ from typing import List, Optional
|
|
|
4
4
|
from collections import OrderedDict
|
|
5
5
|
|
|
6
6
|
import sqlalchemy as sa
|
|
7
|
-
from sqlalchemy.orm.attributes import flag_modified
|
|
8
7
|
import numpy as np
|
|
9
8
|
|
|
10
9
|
from mindsdb_sql_parser.ast.base import ASTNode
|
|
@@ -457,7 +456,7 @@ class ProjectController:
|
|
|
457
456
|
project.create(name=name)
|
|
458
457
|
return project
|
|
459
458
|
|
|
460
|
-
def update(self, id: Optional[int] = None, name: Optional[str] = None, new_name: str = None
|
|
459
|
+
def update(self, id: Optional[int] = None, name: Optional[str] = None, new_name: str = None) -> Project:
|
|
461
460
|
if id is not None and name is not None:
|
|
462
461
|
raise ValueError("Both 'id' and 'name' can't be provided at the same time")
|
|
463
462
|
|
|
@@ -470,10 +469,5 @@ class ProjectController:
|
|
|
470
469
|
project.name = new_name
|
|
471
470
|
project.record.name = new_name
|
|
472
471
|
|
|
473
|
-
if new_metadata is not None:
|
|
474
|
-
project.metadata = new_metadata
|
|
475
|
-
project.record.metadata_ = new_metadata
|
|
476
|
-
flag_modified(project.record, 'metadata_')
|
|
477
|
-
|
|
478
472
|
db.session.commit()
|
|
479
473
|
return project
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import copy
|
|
2
3
|
|
|
3
4
|
from duckdb.typing import BIGINT, DOUBLE, VARCHAR, BLOB, BOOLEAN
|
|
4
|
-
from mindsdb.interfaces.functions.to_markdown import ToMarkdown
|
|
5
5
|
from mindsdb.interfaces.storage.model_fs import HandlerStorage
|
|
6
6
|
from mindsdb.utilities.config import config
|
|
7
7
|
|
|
@@ -159,31 +159,28 @@ class FunctionController(BYOMFunctionsController):
|
|
|
159
159
|
return meta
|
|
160
160
|
|
|
161
161
|
def to_markdown_call_function(self, node):
|
|
162
|
+
# load on-demand because lib is heavy
|
|
163
|
+
from mindsdb.interfaces.functions.to_markdown import ToMarkdown
|
|
162
164
|
name = node.op.lower()
|
|
163
165
|
|
|
164
166
|
if name in self.callbacks:
|
|
165
167
|
return self.callbacks[name]
|
|
166
168
|
|
|
167
|
-
def callback(file_path_or_url
|
|
169
|
+
def callback(file_path_or_url):
|
|
168
170
|
chat_model_params = self._parse_chat_model_params('TO_MARKDOWN_FUNCTION_')
|
|
169
171
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
llm = create_chat_model(chat_model_params)
|
|
175
|
-
llm_client = llm.root_client
|
|
176
|
-
llm_model = llm.model_name
|
|
177
|
-
except Exception:
|
|
178
|
-
pass
|
|
172
|
+
params_copy = copy.deepcopy(chat_model_params)
|
|
173
|
+
params_copy['model'] = params_copy.pop('model_name')
|
|
174
|
+
params_copy.pop('api_keys')
|
|
175
|
+
params_copy.pop('provider')
|
|
179
176
|
|
|
180
|
-
to_markdown = ToMarkdown(
|
|
181
|
-
return to_markdown.call(file_path_or_url)
|
|
177
|
+
to_markdown = ToMarkdown()
|
|
178
|
+
return to_markdown.call(file_path_or_url, **params_copy)
|
|
182
179
|
|
|
183
180
|
meta = {
|
|
184
181
|
'name': name,
|
|
185
182
|
'callback': callback,
|
|
186
|
-
'input_types': ['str'
|
|
183
|
+
'input_types': ['str'],
|
|
187
184
|
'output_type': 'str'
|
|
188
185
|
}
|
|
189
186
|
self.callbacks[name] = meta
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import base64
|
|
2
1
|
from io import BytesIO
|
|
3
2
|
import os
|
|
4
3
|
from typing import Union
|
|
5
4
|
from urllib.parse import urlparse
|
|
6
5
|
|
|
7
|
-
import
|
|
8
|
-
from markitdown import MarkItDown
|
|
6
|
+
from aipdf import ocr
|
|
9
7
|
import mimetypes
|
|
10
|
-
from openai import OpenAI
|
|
11
8
|
import requests
|
|
12
9
|
|
|
13
10
|
|
|
@@ -15,41 +12,22 @@ class ToMarkdown:
|
|
|
15
12
|
"""
|
|
16
13
|
Extracts the content of documents of various formats in markdown format.
|
|
17
14
|
"""
|
|
18
|
-
def __init__(self
|
|
15
|
+
def __init__(self):
|
|
19
16
|
"""
|
|
20
17
|
Initializes the ToMarkdown class.
|
|
21
18
|
"""
|
|
22
|
-
# If use_llm is True, llm_client and llm_model must be provided.
|
|
23
|
-
if use_llm and (llm_client is None or llm_model is None):
|
|
24
|
-
raise ValueError('LLM client and model must be provided when use_llm is True.')
|
|
25
19
|
|
|
26
|
-
|
|
27
|
-
if not use_llm:
|
|
28
|
-
llm_client = None
|
|
29
|
-
llm_model = None
|
|
30
|
-
|
|
31
|
-
# Only OpenAI is supported for now.
|
|
32
|
-
# TODO: Add support for other LLMs.
|
|
33
|
-
if llm_client is not None and not isinstance(llm_client, OpenAI):
|
|
34
|
-
raise ValueError('Only OpenAI models are supported at the moment.')
|
|
35
|
-
|
|
36
|
-
self.use_llm = use_llm
|
|
37
|
-
self.llm_client = llm_client
|
|
38
|
-
self.llm_model = llm_model
|
|
39
|
-
|
|
40
|
-
def call(self, file_path_or_url: str) -> str:
|
|
20
|
+
def call(self, file_path_or_url: str, **kwargs) -> str:
|
|
41
21
|
"""
|
|
42
22
|
Converts a file to markdown.
|
|
43
23
|
"""
|
|
44
24
|
file_extension = self._get_file_extension(file_path_or_url)
|
|
45
|
-
|
|
25
|
+
file_content = self._get_file_content(file_path_or_url)
|
|
46
26
|
|
|
47
27
|
if file_extension == '.pdf':
|
|
48
|
-
return self._pdf_to_markdown(
|
|
49
|
-
elif file_extension in ['.jpg', '.jpeg', '.png', '.gif']:
|
|
50
|
-
return self._image_to_markdown(file)
|
|
28
|
+
return self._pdf_to_markdown(file_content, **kwargs)
|
|
51
29
|
else:
|
|
52
|
-
|
|
30
|
+
raise ValueError(f"Unsupported file type: {file_extension}.")
|
|
53
31
|
|
|
54
32
|
def _get_file_content(self, file_path_or_url: str) -> str:
|
|
55
33
|
"""
|
|
@@ -90,105 +68,12 @@ class ToMarkdown:
|
|
|
90
68
|
else:
|
|
91
69
|
return os.path.splitext(file_path_or_url)[1]
|
|
92
70
|
|
|
93
|
-
def _pdf_to_markdown(self, file_content: Union[requests.Response, bytes]) -> str:
|
|
71
|
+
def _pdf_to_markdown(self, file_content: Union[requests.Response, bytes], **kwargs) -> str:
|
|
94
72
|
"""
|
|
95
73
|
Converts a PDF file to markdown.
|
|
96
74
|
"""
|
|
97
|
-
if self.llm_client is None:
|
|
98
|
-
return self._pdf_to_markdown_no_llm(file_content)
|
|
99
|
-
else:
|
|
100
|
-
return self._pdf_to_markdown_llm(file_content)
|
|
101
|
-
|
|
102
|
-
def _pdf_to_markdown_llm(self, file_content: Union[requests.Response, BytesIO]) -> str:
|
|
103
|
-
"""
|
|
104
|
-
Converts a PDF file to markdown using LLM.
|
|
105
|
-
The LLM is used mainly for the purpose of generating descriptions of any images in the PDF.
|
|
106
|
-
"""
|
|
107
75
|
if isinstance(file_content, requests.Response):
|
|
108
76
|
file_content = BytesIO(file_content.content)
|
|
109
77
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
markdown_content = []
|
|
113
|
-
for page_num in range(len(document)):
|
|
114
|
-
page = document.load_page(page_num)
|
|
115
|
-
|
|
116
|
-
# Get text blocks with coordinates.
|
|
117
|
-
page_content = []
|
|
118
|
-
blocks = page.get_text("blocks")
|
|
119
|
-
for block in blocks:
|
|
120
|
-
x0, y0, x1, y1, text, _, _ = block
|
|
121
|
-
if text.strip(): # Skip empty or whitespace blocks.
|
|
122
|
-
page_content.append((y0, text.strip()))
|
|
123
|
-
|
|
124
|
-
# Extract images from the page.
|
|
125
|
-
image_list = page.get_images(full=True)
|
|
126
|
-
for img_index, img in enumerate(image_list):
|
|
127
|
-
xref = img[0]
|
|
128
|
-
base_image = document.extract_image(xref)
|
|
129
|
-
image_bytes = base_image["image"]
|
|
130
|
-
|
|
131
|
-
# Use actual image y-coordinate if available.
|
|
132
|
-
y0 = float(base_image.get("y", 0))
|
|
133
|
-
image_description = self._generate_image_description(image_bytes)
|
|
134
|
-
page_content.append((y0, f""))
|
|
135
|
-
|
|
136
|
-
# Sort the content by y0 coordinate
|
|
137
|
-
page_content.sort(key=lambda x: x[0])
|
|
138
|
-
|
|
139
|
-
# Add sorted content to the markdown
|
|
140
|
-
for _, text in page_content:
|
|
141
|
-
markdown_content.append(text)
|
|
142
|
-
markdown_content.append("\n")
|
|
143
|
-
|
|
144
|
-
document.close()
|
|
145
|
-
|
|
146
|
-
return "\n".join(markdown_content)
|
|
147
|
-
|
|
148
|
-
def _generate_image_description(self, image_bytes: bytes) -> str:
|
|
149
|
-
"""
|
|
150
|
-
Generates a description of the image using LLM.
|
|
151
|
-
"""
|
|
152
|
-
image_base64 = base64.b64encode(image_bytes).decode("utf-8")
|
|
153
|
-
|
|
154
|
-
response = self.llm_client.chat.completions.create(
|
|
155
|
-
model=self.llm_model,
|
|
156
|
-
messages=[
|
|
157
|
-
{
|
|
158
|
-
"role": "user",
|
|
159
|
-
"content": [
|
|
160
|
-
{"type": "text", "text": "Describe this image"},
|
|
161
|
-
{"type": "image_url", "image_url": {"url": f"data:image/png;base64,{image_base64}"}},
|
|
162
|
-
],
|
|
163
|
-
}
|
|
164
|
-
],
|
|
165
|
-
)
|
|
166
|
-
description = response.choices[0].message.content
|
|
167
|
-
return description
|
|
168
|
-
|
|
169
|
-
def _pdf_to_markdown_no_llm(self, file_content: Union[requests.Response, BytesIO]) -> str:
|
|
170
|
-
"""
|
|
171
|
-
Converts a PDF file to markdown without using LLM.
|
|
172
|
-
"""
|
|
173
|
-
md = MarkItDown(enable_plugins=True)
|
|
174
|
-
result = md.convert(file_content)
|
|
175
|
-
return result.markdown
|
|
176
|
-
|
|
177
|
-
def _image_to_markdown(self, file_content: Union[requests.Response, BytesIO]) -> str:
|
|
178
|
-
"""
|
|
179
|
-
Converts images to markdown.
|
|
180
|
-
"""
|
|
181
|
-
if not self.use_llm or self.llm_client is None:
|
|
182
|
-
raise ValueError('LLM client must be enabled to convert images to markdown.')
|
|
183
|
-
|
|
184
|
-
md = MarkItDown(llm_client=self.llm_client, llm_model=self.llm_model, enable_plugins=True)
|
|
185
|
-
result = md.convert(file_content)
|
|
186
|
-
return result.markdown
|
|
187
|
-
|
|
188
|
-
def _other_to_markdown(self, file_content: Union[requests.Response, BytesIO]) -> str:
|
|
189
|
-
"""
|
|
190
|
-
Converts other file formats to markdown.
|
|
191
|
-
"""
|
|
192
|
-
md = MarkItDown(enable_plugins=True)
|
|
193
|
-
result = md.convert(file_content)
|
|
194
|
-
return result.markdown
|
|
78
|
+
markdown_pages = ocr(file_content, **kwargs)
|
|
79
|
+
return "\n\n---\n\n".join(markdown_pages)
|