MindsDB 25.5.3.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 +127 -79
- 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 +47 -27
- mindsdb/api/executor/datahub/classes/response.py +5 -2
- mindsdb/api/executor/datahub/datanodes/integration_datanode.py +39 -72
- mindsdb/api/executor/planner/query_planner.py +10 -1
- 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 +9 -12
- 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 +99 -83
- mindsdb/api/http/namespaces/analysis.py +3 -3
- mindsdb/api/http/namespaces/file.py +8 -2
- mindsdb/api/http/namespaces/sql.py +13 -27
- 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 +82 -115
- mindsdb/api/mysql/mysql_proxy/utilities/dump.py +351 -0
- mindsdb/api/postgres/postgres_proxy/executor/executor.py +1 -1
- 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/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/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/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_calendar_handler/google_calendar_handler.py +4 -4
- mindsdb/integrations/handlers/google_calendar_handler/google_calendar_tables.py +2 -6
- 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_fit_handler/google_fit_handler.py +10 -12
- mindsdb/integrations/handlers/google_fit_handler/google_fit_tables.py +11 -13
- 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/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.py +4 -4
- mindsdb/integrations/handlers/jira_handler/jira_tables.py +9 -9
- 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/lightwood_handler/functions.py +2 -2
- mindsdb/integrations/handlers/lightwood_handler/lightwood_handler.py +0 -1
- mindsdb/integrations/handlers/lightwood_handler/tests/test_lightwood_handler.py +11 -11
- 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_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/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/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/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/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/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/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 +15 -0
- mindsdb/interfaces/agents/langchain_agent.py +16 -4
- mindsdb/interfaces/agents/mindsdb_database_agent.py +101 -2
- mindsdb/interfaces/knowledge_base/controller.py +25 -0
- mindsdb/interfaces/knowledge_base/preprocessing/document_preprocessor.py +13 -10
- mindsdb/interfaces/knowledge_base/preprocessing/json_chunker.py +434 -0
- mindsdb/interfaces/knowledge_base/preprocessing/models.py +54 -0
- 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 +205 -17
- 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 -7
- mindsdb/migrations/versions/2025-05-21_9f150e4f9a05_checkpoint_1.py +360 -0
- mindsdb/utilities/config.py +331 -219
- mindsdb/utilities/starters.py +13 -0
- {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.0.dist-info}/METADATA +641 -695
- {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.0.dist-info}/RECORD +309 -288
- {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.0.dist-info}/WHEEL +1 -1
- mindsdb/integrations/handlers/monkeylearn_handler/requirements.txt +0 -1
- {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.0.dist-info}/licenses/LICENSE +0 -0
- {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.0.dist-info}/top_level.txt +0 -0
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
from mindsdb_sql_parser import parse_sql
|
|
2
2
|
import pandas as pd
|
|
3
3
|
from mendeley import Mendeley
|
|
4
|
-
from mindsdb.integrations.libs.api_handler import APIHandler
|
|
4
|
+
from mindsdb.integrations.libs.api_handler import APIHandler
|
|
5
5
|
from mendeley.session import MendeleySession
|
|
6
|
-
from mindsdb.integrations.handlers.mendeley_handler.mendeley_tables import CatalogSearchTable
|
|
6
|
+
from mindsdb.integrations.handlers.mendeley_handler.mendeley_tables import CatalogSearchTable
|
|
7
7
|
from mindsdb.utilities import log
|
|
8
8
|
from typing import Dict
|
|
9
9
|
from mindsdb.integrations.libs.response import (
|
|
10
|
-
HandlerStatusResponse as StatusResponse
|
|
11
|
-
HandlerResponse as Response,
|
|
12
|
-
RESPONSE_TYPE
|
|
10
|
+
HandlerStatusResponse as StatusResponse
|
|
13
11
|
)
|
|
14
12
|
|
|
15
13
|
logger = log.getLogger(__name__)
|
|
16
14
|
|
|
17
|
-
class MendeleyHandler(APIHandler):
|
|
18
15
|
|
|
19
|
-
|
|
16
|
+
class MendeleyHandler(APIHandler):
|
|
20
17
|
|
|
18
|
+
def __init__(self, name, **kwargs):
|
|
21
19
|
""" constructor
|
|
22
20
|
Args:
|
|
23
21
|
name (str): the handler name
|
|
@@ -25,16 +23,16 @@ class MendeleyHandler(APIHandler):
|
|
|
25
23
|
super().__init__(name)
|
|
26
24
|
|
|
27
25
|
self.connection_args = kwargs.get('connection_data', {})
|
|
28
|
-
|
|
26
|
+
|
|
29
27
|
self.client_id = self.connection_args.get('client_id', None)
|
|
30
28
|
self.client_secret = self.connection_args.get('client_secret', None)
|
|
31
29
|
self.session = self.connect()
|
|
32
30
|
|
|
33
31
|
self.session = None
|
|
34
32
|
self.is_connected = False
|
|
35
|
-
|
|
33
|
+
|
|
36
34
|
catalog_search_data = CatalogSearchTable(self)
|
|
37
|
-
self.catalog_search_data = catalog_search_data
|
|
35
|
+
self.catalog_search_data = catalog_search_data
|
|
38
36
|
self._register_table('catalog_search_data', catalog_search_data)
|
|
39
37
|
|
|
40
38
|
def connect(self) -> MendeleySession:
|
|
@@ -47,7 +45,7 @@ class MendeleyHandler(APIHandler):
|
|
|
47
45
|
Returns:
|
|
48
46
|
HandlerStatusResponse """
|
|
49
47
|
|
|
50
|
-
if self.is_connected
|
|
48
|
+
if self.is_connected:
|
|
51
49
|
return self.session
|
|
52
50
|
|
|
53
51
|
mendeley = Mendeley(self.client_id, self.client_secret)
|
|
@@ -56,9 +54,8 @@ class MendeleyHandler(APIHandler):
|
|
|
56
54
|
|
|
57
55
|
self.is_connected = True
|
|
58
56
|
return self.session
|
|
59
|
-
|
|
60
|
-
def check_connection(self) -> StatusResponse:
|
|
61
57
|
|
|
58
|
+
def check_connection(self) -> StatusResponse:
|
|
62
59
|
""" The check_connection method checks the connection to the handler
|
|
63
60
|
Returns:
|
|
64
61
|
HandlerStatusResponse
|
|
@@ -77,7 +74,6 @@ class MendeleyHandler(APIHandler):
|
|
|
77
74
|
return response
|
|
78
75
|
|
|
79
76
|
def native_query(self, query_string: str):
|
|
80
|
-
|
|
81
77
|
"""The native_query method receives raw query and acts upon it.
|
|
82
78
|
Args:
|
|
83
79
|
query_string (str): query in native format
|
|
@@ -86,9 +82,9 @@ class MendeleyHandler(APIHandler):
|
|
|
86
82
|
"""
|
|
87
83
|
ast = parse_sql(query_string)
|
|
88
84
|
return self.query(ast)
|
|
89
|
-
|
|
90
|
-
def get_authors(self,data):
|
|
91
|
-
"""The get_authors method receives the data - a specific document returned by the API, gets the names of the authors
|
|
85
|
+
|
|
86
|
+
def get_authors(self, data):
|
|
87
|
+
"""The get_authors method receives the data - a specific document returned by the API, gets the names of the authors
|
|
92
88
|
and combines them in a string, so as to allow the use of DataFrame.
|
|
93
89
|
Args:
|
|
94
90
|
data (CatalogDocument): document returned by API
|
|
@@ -97,18 +93,18 @@ class MendeleyHandler(APIHandler):
|
|
|
97
93
|
"""
|
|
98
94
|
authors = ""
|
|
99
95
|
sum = 0
|
|
100
|
-
if data.authors
|
|
96
|
+
if data.authors is not None:
|
|
101
97
|
for x in data.authors:
|
|
102
|
-
if sum + 1 == len(data.authors) and x.first_name
|
|
98
|
+
if sum + 1 == len(data.authors) and x.first_name is not None and x.last_name is not None:
|
|
103
99
|
authors = authors + x.first_name + " " + x.last_name
|
|
104
100
|
else:
|
|
105
|
-
if x.first_name
|
|
101
|
+
if x.first_name is not None and x.last_name is not None:
|
|
106
102
|
authors = authors + x.first_name + " " + x.last_name + ", "
|
|
107
103
|
sum = sum + 1
|
|
108
104
|
return authors
|
|
109
105
|
|
|
110
|
-
def get_keywords(self,data):
|
|
111
|
-
"""The get_keywords method receives the data-a specific document returned by the API, gets the specified keywords
|
|
106
|
+
def get_keywords(self, data):
|
|
107
|
+
"""The get_keywords method receives the data-a specific document returned by the API, gets the specified keywords
|
|
112
108
|
and combines them in a string, so as to allow the use of DataFrame.
|
|
113
109
|
Args:
|
|
114
110
|
data (CatalogDocument) : document returned by the API
|
|
@@ -117,18 +113,17 @@ class MendeleyHandler(APIHandler):
|
|
|
117
113
|
"""
|
|
118
114
|
keywords = ""
|
|
119
115
|
sum = 0
|
|
120
|
-
if data.keywords
|
|
116
|
+
if data.keywords is not None:
|
|
121
117
|
for x in data.keywords:
|
|
122
118
|
if sum + 1 == len(data.keywords):
|
|
123
|
-
keywords = keywords
|
|
119
|
+
keywords = keywords + x + " "
|
|
124
120
|
else:
|
|
125
|
-
if x
|
|
121
|
+
if x is not None:
|
|
126
122
|
keywords = keywords + x + ", "
|
|
127
123
|
sum = sum + 1
|
|
128
124
|
return keywords
|
|
129
|
-
|
|
130
|
-
def create_dict(self,data):
|
|
131
125
|
|
|
126
|
+
def create_dict(self, data):
|
|
132
127
|
"""The create_dict method receives the data-a specific document returned by the API, gets the resources-fields of the document,
|
|
133
128
|
as specified in Mendley documentation, and puts them in a dictionary.
|
|
134
129
|
|
|
@@ -142,7 +137,7 @@ class MendeleyHandler(APIHandler):
|
|
|
142
137
|
dict["type"] = data.type
|
|
143
138
|
dict["source"] = data.source
|
|
144
139
|
dict["year"] = data.year
|
|
145
|
-
if data.identifiers
|
|
140
|
+
if data.identifiers is not None:
|
|
146
141
|
dict["pmid"] = data.identifiers.get("pmid")
|
|
147
142
|
dict["sgr"] = data.identifiers.get("sgr")
|
|
148
143
|
dict["issn"] = data.identifiers.get("issn")
|
|
@@ -150,16 +145,15 @@ class MendeleyHandler(APIHandler):
|
|
|
150
145
|
dict["doi"] = data.identifiers.get("doi")
|
|
151
146
|
dict["pui"] = data.identifiers.get("pui")
|
|
152
147
|
dict["authors"] = self.get_authors(data)
|
|
153
|
-
if data.keywords
|
|
148
|
+
if data.keywords is not None:
|
|
154
149
|
dict["keywords"] = self.get_keywords(data)
|
|
155
150
|
else:
|
|
156
151
|
dict["keywords"] = None
|
|
157
152
|
dict["link"] = data.link
|
|
158
153
|
dict["id"] = data.id
|
|
159
154
|
return dict
|
|
160
|
-
|
|
155
|
+
|
|
161
156
|
def call_mendeley_api(self, method_name: str, params: Dict) -> pd.DataFrame:
|
|
162
|
-
|
|
163
157
|
"""The method call_mendeley_api is used to communicate with Mendeley. Depending on the method used there are three different types
|
|
164
158
|
of search conducted.
|
|
165
159
|
The advanced_search results in a CatalogSearch resource, which, depending on the parameters used, could either be a number of different documents (CatalogDocument),
|
|
@@ -174,28 +168,28 @@ class MendeleyHandler(APIHandler):
|
|
|
174
168
|
DataFrame
|
|
175
169
|
"""
|
|
176
170
|
|
|
177
|
-
self.session= self.connect()
|
|
171
|
+
self.session = self.connect()
|
|
178
172
|
|
|
179
173
|
if method_name == 'advanced_search':
|
|
180
174
|
search_params = {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
175
|
+
'title': params.get("title"),
|
|
176
|
+
'author': params.get("author"),
|
|
177
|
+
'source': params.get("source"),
|
|
178
|
+
'abstract': params.get("abstract"),
|
|
179
|
+
'min_year': params.get("min_year"),
|
|
180
|
+
'max_year': params.get("max_year"),
|
|
181
|
+
'open_access': params.get("open_access")
|
|
188
182
|
}
|
|
189
183
|
data = self.session.catalog.advanced_search(**search_params)
|
|
190
184
|
sum = 0
|
|
191
185
|
df = pd.DataFrame()
|
|
192
186
|
for x in data.list(page_size=params["limit"]).items:
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
187
|
+
if sum == 0:
|
|
188
|
+
df = pd.DataFrame(self.create_dict(x), index=[0])
|
|
189
|
+
sum += 1
|
|
190
|
+
else:
|
|
191
|
+
df = df.append(self.create_dict(x), ignore_index=True)
|
|
192
|
+
sum += 1
|
|
199
193
|
if df.empty:
|
|
200
194
|
raise NotImplementedError(('Insufficient or wrong input given'))
|
|
201
195
|
else:
|
|
@@ -203,23 +197,21 @@ class MendeleyHandler(APIHandler):
|
|
|
203
197
|
|
|
204
198
|
elif method_name == 'identifier_search':
|
|
205
199
|
search_params = {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
200
|
+
'arxiv': params.get("arxiv"),
|
|
201
|
+
'doi': params.get("doi"),
|
|
202
|
+
'isbn': params.get("isbn"),
|
|
203
|
+
'issn': params.get("issn"),
|
|
204
|
+
'pmid': params.get("pmid"),
|
|
205
|
+
'scopus': params.get("scopus"),
|
|
206
|
+
'filehash': params.get("filehash")
|
|
213
207
|
}
|
|
214
208
|
data = self.session.catalog.by_identifier(**search_params)
|
|
215
|
-
df = pd.DataFrame(self.create_dict(data),index=[0])
|
|
209
|
+
df = pd.DataFrame(self.create_dict(data), index=[0])
|
|
216
210
|
return df
|
|
217
211
|
|
|
218
212
|
elif method_name == 'get':
|
|
219
213
|
data = self.session.catalog.get(params.get("id"))
|
|
220
|
-
df = pd.DataFrame(self.create_dict(data),index=[0])
|
|
214
|
+
df = pd.DataFrame(self.create_dict(data), index=[0])
|
|
221
215
|
return df
|
|
222
216
|
|
|
223
217
|
raise NotImplementedError('Method name {} not supported by Mendeley API Handler'.format(method_name))
|
|
224
|
-
|
|
225
|
-
|
|
@@ -3,25 +3,25 @@ import pandas as pd
|
|
|
3
3
|
from mindsdb.integrations.libs.api_handler import APITable
|
|
4
4
|
from mindsdb.integrations.utilities.sql_utils import extract_comparison_conditions
|
|
5
5
|
|
|
6
|
+
|
|
6
7
|
class CatalogSearchTable(APITable):
|
|
7
8
|
|
|
8
9
|
def select(self, query: ast.Select) -> pd.DataFrame:
|
|
9
|
-
|
|
10
10
|
"""The select method implements the mappings from the ast.Select and calls the actual API through the call_mendeley_api.
|
|
11
11
|
Firstly, it is used to put the parameters specified in the query in a dictionary, which is then used when calling the method call_mendeley_api.
|
|
12
12
|
If no conditions are specified, an error is raised since the search cannot be conducted.
|
|
13
13
|
|
|
14
14
|
Args:
|
|
15
|
-
query (ast.Select): query used to specify the wanted results
|
|
15
|
+
query (ast.Select): query used to specify the wanted results
|
|
16
16
|
Returns:
|
|
17
17
|
result (DataFrame): the result of the query
|
|
18
18
|
"""
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
conditions = extract_comparison_conditions(query.where)
|
|
21
|
-
|
|
22
|
-
params = {}
|
|
23
21
|
|
|
24
|
-
|
|
22
|
+
params = {}
|
|
23
|
+
|
|
24
|
+
# Since there are three different types of search, and each of them takes different parameters, we use the parameters that lead
|
|
25
25
|
# to the most specific results. For example, in the case of the user specifying the title and the doi of a document, priority is given to
|
|
26
26
|
# the doi.
|
|
27
27
|
|
|
@@ -30,7 +30,7 @@ class CatalogSearchTable(APITable):
|
|
|
30
30
|
else:
|
|
31
31
|
params['limit'] = 30
|
|
32
32
|
|
|
33
|
-
for op,arg1,arg2 in conditions:
|
|
33
|
+
for op, arg1, arg2 in conditions:
|
|
34
34
|
|
|
35
35
|
if arg1 in ['arxiv', 'doi', 'isbn', 'issn', 'pmid', 'scopus', 'filehash']:
|
|
36
36
|
|
|
@@ -39,8 +39,8 @@ class CatalogSearchTable(APITable):
|
|
|
39
39
|
params[arg1] = arg2
|
|
40
40
|
|
|
41
41
|
result = self.handler.call_mendeley_api(
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
method_name='identifier_search',
|
|
43
|
+
params=params)
|
|
44
44
|
|
|
45
45
|
break
|
|
46
46
|
|
|
@@ -50,52 +50,50 @@ class CatalogSearchTable(APITable):
|
|
|
50
50
|
params['id'] = arg2
|
|
51
51
|
|
|
52
52
|
result = self.handler.call_mendeley_api(
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
method_name='get',
|
|
54
|
+
params=params)
|
|
55
55
|
|
|
56
56
|
break
|
|
57
57
|
|
|
58
|
-
elif "title" or "author" or"source" or "abstract" or "min_year" or "max_year" or "open_access" or "view" in conditions:
|
|
58
|
+
elif "title" or "author" or "source" or "abstract" or "min_year" or "max_year" or "open_access" or "view" in conditions:
|
|
59
59
|
|
|
60
60
|
if arg1 == 'title':
|
|
61
61
|
if op != '=':
|
|
62
62
|
raise NotImplementedError
|
|
63
63
|
params['title'] = arg2
|
|
64
|
-
|
|
64
|
+
|
|
65
65
|
elif arg1 == 'author':
|
|
66
66
|
if op != '=':
|
|
67
67
|
raise NotImplementedError
|
|
68
68
|
params['author'] = arg2
|
|
69
|
-
|
|
69
|
+
|
|
70
70
|
elif arg1 == 'source':
|
|
71
71
|
if op != '=':
|
|
72
72
|
raise NotImplementedError
|
|
73
73
|
params['source'] = arg2
|
|
74
|
-
|
|
74
|
+
|
|
75
75
|
elif arg1 == 'abstract':
|
|
76
76
|
if op != '=':
|
|
77
77
|
raise NotImplementedError
|
|
78
78
|
params['abstract'] = arg2
|
|
79
|
-
|
|
79
|
+
|
|
80
80
|
elif arg1 == 'min_year':
|
|
81
81
|
params['min_year'] = arg2
|
|
82
|
-
|
|
82
|
+
|
|
83
83
|
elif arg1 == 'max_year':
|
|
84
84
|
params['max_year'] = arg2
|
|
85
|
-
|
|
85
|
+
|
|
86
86
|
elif arg1 == 'open_access':
|
|
87
87
|
if op != '=':
|
|
88
88
|
raise NotImplementedError
|
|
89
89
|
params['open_access'] = arg2
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
|
|
92
91
|
result = self.handler.call_mendeley_api(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if conditions==[]:
|
|
92
|
+
method_name='advanced_search',
|
|
93
|
+
params=params)
|
|
94
|
+
|
|
95
|
+
if conditions == []:
|
|
97
96
|
raise ValueError('Please give input for the search to be conducted.')
|
|
98
|
-
|
|
99
97
|
|
|
100
98
|
columns = []
|
|
101
99
|
|
|
@@ -107,10 +105,9 @@ class CatalogSearchTable(APITable):
|
|
|
107
105
|
columns.append(target.parts[-1])
|
|
108
106
|
else:
|
|
109
107
|
raise ValueError(f"Unknown query target {type(target)}")
|
|
110
|
-
|
|
111
108
|
|
|
112
109
|
return result[columns]
|
|
113
|
-
|
|
110
|
+
|
|
114
111
|
def get_columns(self):
|
|
115
112
|
""" get_columns method returns the columns returned by the API"""
|
|
116
113
|
return [
|
|
@@ -130,5 +127,3 @@ class CatalogSearchTable(APITable):
|
|
|
130
127
|
'link',
|
|
131
128
|
'id'
|
|
132
129
|
]
|
|
133
|
-
|
|
134
|
-
|
|
@@ -3,13 +3,14 @@ import unittest
|
|
|
3
3
|
from mindsdb.integrations.handlers.mendeley_handler.mendeley_handler import MendeleyHandler
|
|
4
4
|
from mindsdb.api.executor.data_types.response_type import RESPONSE_TYPE
|
|
5
5
|
|
|
6
|
+
|
|
6
7
|
class MendeleyHandlerTest(unittest.TestCase):
|
|
7
8
|
@classmethod
|
|
8
9
|
def setUpClass(cls):
|
|
9
10
|
cls.kwargs = {
|
|
10
|
-
"connection_data":{"client_id":15253,"client_secret":"BxmSvbrRW5iYEIQR"}
|
|
11
|
+
"connection_data": {"client_id": 15253, "client_secret": "BxmSvbrRW5iYEIQR"}
|
|
11
12
|
}
|
|
12
|
-
cls.handler = MendeleyHandler("test_mendeley_handler"
|
|
13
|
+
cls.handler = MendeleyHandler("test_mendeley_handler", **cls.kwargs)
|
|
13
14
|
|
|
14
15
|
def test_0_connect(self):
|
|
15
16
|
self.handler.connect()
|
|
@@ -26,56 +27,56 @@ class MendeleyHandlerTest(unittest.TestCase):
|
|
|
26
27
|
query = "SELECT * FROM catalog_search_data WHERE id='af1a0408-7409-3a8b-ad91-8accd4f8849a'"
|
|
27
28
|
result = self.handler.native_query(query)
|
|
28
29
|
assert result.type is RESPONSE_TYPE.TABLE
|
|
29
|
-
|
|
30
|
+
|
|
30
31
|
def test_4_select(self):
|
|
31
32
|
query = "SELECT * FROM catalog_search_data WHERE title='The American Mineralogist crystal structure database'"
|
|
32
33
|
result = self.handler.native_query(query)
|
|
33
34
|
assert result.type is RESPONSE_TYPE.TABLE
|
|
34
|
-
|
|
35
|
+
|
|
35
36
|
def test_5_select(self):
|
|
36
37
|
query = "SELECT * FROM catalog_search_data WHERE id='8e86b541-84fd-30ef-9eed-e8c9af847ca3' AND doi='10.1093/ajcn/77.1.71'"
|
|
37
38
|
result = self.handler.native_query(query)
|
|
38
39
|
assert result.type is RESPONSE_TYPE.TABLE
|
|
39
|
-
|
|
40
|
+
|
|
40
41
|
def test_6_select(self):
|
|
41
42
|
query = "SELECT * FROM catalog_search_data WHERE issn='15570878'"
|
|
42
43
|
result = self.handler.native_query(query)
|
|
43
44
|
assert result.type is RESPONSE_TYPE.TABLE
|
|
44
|
-
|
|
45
|
+
|
|
45
46
|
def test_7_select(self):
|
|
46
47
|
query = "SELECT * FROM catalog_search_data WHERE source='American Journal of Clinical Nutrition'"
|
|
47
48
|
result = self.handler.native_query(query)
|
|
48
49
|
assert result.type is RESPONSE_TYPE.TABLE
|
|
49
|
-
|
|
50
|
+
|
|
50
51
|
def test_8_select(self):
|
|
51
52
|
query = "SELECT * FROM catalog_search_data WHERE source='American Journal of Clinical Nutrition'AND id='4eeda257-8db4-3dad-80c8-6912356d3887'"
|
|
52
53
|
result = self.handler.native_query(query)
|
|
53
54
|
assert result.type is RESPONSE_TYPE.TABLE
|
|
54
|
-
|
|
55
|
+
|
|
55
56
|
def test_9_select(self):
|
|
56
57
|
query = "SELECT * FROM catalog_search_data WHERE source='American Journal of Clinical Nutrition'AND max_year='2020'"
|
|
57
58
|
result = self.handler.native_query(query)
|
|
58
59
|
assert result.type is RESPONSE_TYPE.TABLE
|
|
59
|
-
|
|
60
|
+
|
|
60
61
|
def test_10_call_mendeley_api_invalid_method_name(self):
|
|
61
62
|
with self.assertRaises(NotImplementedError):
|
|
62
|
-
|
|
63
|
+
self.handler.call_mendeley_api("method1", None)
|
|
63
64
|
|
|
64
65
|
def test_11_select_invalid_condition_name(self):
|
|
65
66
|
with self.assertRaises(NotImplementedError):
|
|
66
67
|
query = "SELECT * FROM catalog_search_data WHERE name='American Journal of Clinical Nutrition'"
|
|
67
|
-
|
|
68
|
+
self.handler.native_query(query)
|
|
68
69
|
|
|
69
70
|
def test_12_select_invalid_operator(self):
|
|
70
71
|
with self.assertRaises(NotImplementedError):
|
|
71
72
|
query = "SELECT * FROM catalog_search_data WHERE source>'American Journal of Clinical Nutrition'AND max_year='2020' "
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
self.handler.native_query(query)
|
|
74
|
+
|
|
74
75
|
def test_13_select_invalid_column_name(self):
|
|
75
76
|
with self.assertRaises(KeyError):
|
|
76
77
|
query = "SELECT name FROM catalog_search_data WHERE source='American Journal of Clinical Nutrition'AND max_year='2020' "
|
|
77
|
-
|
|
78
|
-
|
|
78
|
+
self.handler.native_query(query)
|
|
79
|
+
|
|
79
80
|
def test_14_get_columns(self):
|
|
80
81
|
columns = self.handler.catalog_search_data.get_columns()
|
|
81
82
|
|
|
@@ -98,11 +99,12 @@ class MendeleyHandlerTest(unittest.TestCase):
|
|
|
98
99
|
]
|
|
99
100
|
|
|
100
101
|
self.assertListEqual(columns, expected_columns)
|
|
101
|
-
|
|
102
|
+
|
|
102
103
|
def test_15_select_invalid_condition_name(self):
|
|
103
104
|
with self.assertRaises(ValueError):
|
|
104
105
|
query = "SELECT * FROM catalog_search_data"
|
|
105
|
-
|
|
106
|
+
self.handler.native_query(query)
|
|
107
|
+
|
|
106
108
|
|
|
107
109
|
if __name__ == "__main__":
|
|
108
110
|
unittest.main()
|
|
@@ -14,6 +14,7 @@ from .adapters import BaseMerlionForecastAdapter, DefaultForecasterAdapter, Merl
|
|
|
14
14
|
|
|
15
15
|
logger = log.getLogger(__name__)
|
|
16
16
|
|
|
17
|
+
|
|
17
18
|
class DetectorModelType(Enum):
|
|
18
19
|
default = DefaultDetectorAdapter
|
|
19
20
|
isolation = IsolationForestDetectorAdapter
|
|
@@ -36,7 +37,7 @@ class TaskType(Enum):
|
|
|
36
37
|
def is_invalid_type(name: str, type_class: Enum) -> bool:
|
|
37
38
|
if name is None:
|
|
38
39
|
return True
|
|
39
|
-
return not
|
|
40
|
+
return name not in type_class._member_names_
|
|
40
41
|
|
|
41
42
|
|
|
42
43
|
def enum_to_str(type_class: Enum) -> str:
|
|
@@ -194,12 +195,12 @@ class MerlionHandler(BaseMLEngine):
|
|
|
194
195
|
# check task_type
|
|
195
196
|
try:
|
|
196
197
|
task_enum = TaskType[task]
|
|
197
|
-
except Exception
|
|
198
|
+
except Exception:
|
|
198
199
|
raise Exception("wrong using.task: " + task + ", valid options: " + enum_to_str(TaskType))
|
|
199
200
|
# check and get model class
|
|
200
201
|
try:
|
|
201
202
|
adapter_class = task_enum.value[model_type].value
|
|
202
203
|
except Exception as e:
|
|
203
|
-
raise Exception("Wrong using.model_type: " + model_type + ", valid options: "
|
|
204
|
-
enum_to_str(task_enum.value) + ", " + str(e))
|
|
204
|
+
raise Exception("Wrong using.model_type: " + model_type + ", valid options: "
|
|
205
|
+
+ enum_to_str(task_enum.value) + ", " + str(e))
|
|
205
206
|
return adapter_class
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
from .__about__ import __version__ as version
|
|
2
|
+
from .__about__ import __description__ as description
|
|
1
3
|
from mindsdb.integrations.libs.const import HANDLER_TYPE
|
|
2
4
|
from mindsdb.utilities import log
|
|
3
5
|
|
|
4
6
|
logger = log.getLogger(__name__)
|
|
5
7
|
|
|
6
|
-
from .__about__ import __description__ as description
|
|
7
|
-
from .__about__ import __version__ as version
|
|
8
8
|
|
|
9
9
|
try:
|
|
10
10
|
from .minds_endpoint_handler import MindsEndpointHandler as Handler
|
|
@@ -20,4 +20,4 @@ type = HANDLER_TYPE.ML
|
|
|
20
20
|
icon_path = 'icon.svg'
|
|
21
21
|
permanent = False
|
|
22
22
|
|
|
23
|
-
__all__ = ["Handler", "version", "name", "type", "title", "description", "import_error", "icon_path"]
|
|
23
|
+
__all__ = ["Handler", "version", "name", "type", "title", "description", "import_error", "icon_path"]
|
|
@@ -18,66 +18,88 @@ class MLflowHandler(BaseMLEngine):
|
|
|
18
18
|
1. Run `mlflow server -p 5001 --backend-store-uri sqlite:////path/to/mlflow.db --default-artifact-root ./artifacts --host 0.0.0.0`
|
|
19
19
|
2. Run `mlflow models serve --model-uri ./model_path`
|
|
20
20
|
3. Run MindsDB
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
Note: above, `artifacts` is a folder to store artifacts for new experiments that do not specify an artifact store.
|
|
23
23
|
""" # noqa
|
|
24
24
|
|
|
25
|
-
name =
|
|
25
|
+
name = "mlflow"
|
|
26
26
|
|
|
27
|
-
def create(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
def create(
|
|
28
|
+
self,
|
|
29
|
+
target: str,
|
|
30
|
+
df: Optional[pd.DataFrame] = None,
|
|
31
|
+
args: Optional[Dict] = None,
|
|
32
|
+
) -> None:
|
|
33
|
+
args = args["using"] # ignore the rest of the problem definition
|
|
34
|
+
connection = MlflowClient(args["mlflow_server_url"], args["mlflow_server_path"])
|
|
35
|
+
model_name = args["model_name"]
|
|
31
36
|
mlflow_models = [model.name for model in connection.search_registered_models()]
|
|
32
37
|
|
|
33
38
|
if model_name not in mlflow_models:
|
|
34
|
-
raise Exception(
|
|
39
|
+
raise Exception(
|
|
40
|
+
f"Error: model '{model_name}' not found in mlflow. Check serving and try again."
|
|
41
|
+
)
|
|
35
42
|
|
|
36
|
-
args[
|
|
37
|
-
self._check_model_url(args[
|
|
38
|
-
self.model_storage.json_set(
|
|
43
|
+
args["target"] = target
|
|
44
|
+
self._check_model_url(args["predict_url"])
|
|
45
|
+
self.model_storage.json_set("args", args)
|
|
39
46
|
|
|
40
47
|
def predict(self, df, args=None):
|
|
41
|
-
args = self.model_storage.json_get(
|
|
42
|
-
self._check_model_url(args[
|
|
43
|
-
resp = requests.post(
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
args = self.model_storage.json_get("args") # override any incoming args for now
|
|
49
|
+
self._check_model_url(args["predict_url"])
|
|
50
|
+
resp = requests.post(
|
|
51
|
+
args["predict_url"],
|
|
52
|
+
data=df.to_json(orient="records"),
|
|
53
|
+
headers={"content-type": "application/json; format=pandas-records"},
|
|
54
|
+
)
|
|
46
55
|
answer = resp.json()
|
|
47
|
-
predictions = pd.DataFrame({args[
|
|
56
|
+
predictions = pd.DataFrame({args["target"]: answer})
|
|
48
57
|
return predictions
|
|
49
58
|
|
|
50
59
|
def describe(self, key: Optional[str] = None) -> pd.DataFrame:
|
|
51
|
-
if key ==
|
|
52
|
-
args = self.model_storage.json_get(
|
|
53
|
-
connection = MlflowClient(
|
|
54
|
-
|
|
60
|
+
if key == "info":
|
|
61
|
+
args = self.model_storage.json_get("args")
|
|
62
|
+
connection = MlflowClient(
|
|
63
|
+
args["mlflow_server_url"], args["self.mlflow_server_path"]
|
|
64
|
+
)
|
|
65
|
+
models = {
|
|
66
|
+
model.name: model for model in connection.search_registered_models()
|
|
67
|
+
}
|
|
55
68
|
model = models[key]
|
|
56
69
|
latest_version = model.latest_versions[-1]
|
|
57
70
|
description = {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
71
|
+
"NAME": [model.name],
|
|
72
|
+
"USER_DESCRIPTION": [model.description],
|
|
73
|
+
"LAST_STATUS": [latest_version.status],
|
|
74
|
+
"CREATED_AT": [
|
|
75
|
+
datetime.fromtimestamp(model.creation_timestamp // 1000).strftime(
|
|
76
|
+
"%m/%d/%Y, %H:%M:%S"
|
|
77
|
+
)
|
|
78
|
+
],
|
|
79
|
+
"LAST_UPDATED": [
|
|
80
|
+
datetime.fromtimestamp(
|
|
81
|
+
model.last_updated_timestamp // 1000
|
|
82
|
+
).strftime("%m/%d/%Y, %H:%M:%S")
|
|
83
|
+
],
|
|
84
|
+
"TAGS": [model.tags],
|
|
85
|
+
"LAST_RUN_ID": [latest_version.run_id],
|
|
86
|
+
"LAST_SOURCE_PATH": [latest_version.source],
|
|
87
|
+
"LAST_USER_ID": [latest_version.user_id],
|
|
88
|
+
"LAST_VERSION": [latest_version.version],
|
|
68
89
|
}
|
|
69
90
|
return pd.DataFrame.from_dict(description)
|
|
70
91
|
else:
|
|
71
|
-
tables = [
|
|
72
|
-
return pd.DataFrame(tables, columns=[
|
|
73
|
-
|
|
92
|
+
tables = ["info"]
|
|
93
|
+
return pd.DataFrame(tables, columns=["tables"])
|
|
74
94
|
|
|
75
95
|
@staticmethod
|
|
76
96
|
def _check_model_url(url):
|
|
77
|
-
"""
|
|
97
|
+
"""try post without data, check status code not in (not_found, method_not_allowed)"""
|
|
78
98
|
try:
|
|
79
99
|
resp = requests.post(url)
|
|
80
100
|
if resp.status_code in (404, 405):
|
|
81
|
-
raise Exception(
|
|
101
|
+
raise Exception(
|
|
102
|
+
f"Model url is incorrect, status_code: {resp.status_code}"
|
|
103
|
+
)
|
|
82
104
|
except requests.RequestException as e:
|
|
83
|
-
raise Exception(f
|
|
105
|
+
raise Exception(f"Model url is incorrect: {str(e)}")
|