Repository: mindsdb/mindsdb
Pull request: Fix pydantic warnings
Fixes #9185

I've had to rename some pydantic model fields to avoid the protected namespace in pydantic v2.

Problem statement:
[Bug]: Pydantic warnings in docker container
### Short description of current behavior

Running the current `main` branch in a docker container produces a number of pydantic warnings:

```
You may be able to resolve this warning by setting `model_config['protected_namespaces'] = ()`.
  warnings.warn(
/usr/local/lib/python3.10/site-packages/pydantic/_internal/_fields.py:160: UserWarning: Field "model_name" has conflict with protected namespace "model_".

You may be able to resolve this warning by setting `model_config['protected_namespaces'] = ()`.
  warnings.warn(
/usr/local/lib/python3.10/site-packages/pydantic/_internal/_fields.py:160: UserWarning: Field "model_kwargs" has conflict with protected namespace "model_".

You may be able to resolve this warning by setting `model_config['protected_namespaces'] = ()`.
  warnings.warn(

/usr/local/lib/python3.10/site-packages/pydantic/_internal/_config.py:334: UserWarning: Valid config keys have changed in V2:
* 'anystr_strip_whitespace' has been renamed to 'str_strip_whitespace'
* 'min_anystr_length' has been renamed to 'str_min_length'
  warnings.warn(message, UserWarning)
/usr/local/lib/python3.10/site-packages/pydantic/_internal/_config.py:334: UserWarning: Valid config keys have changed in V2:
* 'anystr_strip_whitespace' has been renamed to 'str_strip_whitespace'
* 'min_anystr_length' has been renamed to 'str_min_length'
  warnings.warn(message, UserWarning)
/usr/local/lib/python3.10/site-packages/pydantic/_internal/_config.py:334: UserWarning: Valid config keys have changed in V2:
* 'anystr_strip_whitespace' has been renamed to 'str_strip_whitespace'
* 'min_anystr_length' has been renamed to 'str_min_length'
  warnings.warn(message, UserWarning)
/usr/local/lib/python3.10/site-packages/pydantic/_internal/_config.py:334: UserWarning: Valid config keys have changed in V2:
* 'anystr_strip_whitespace' has been renamed to 'str_strip_whitespace'
* 'min_anystr_length' has been renamed to 'str_min_length'
  warnings.warn(message, UserWarning)
```

### Video or screenshots

_No response_

### Expected behavior

_No response_

### How to reproduce the error

_No response_

### Anything else?

_No response_

Hints from issue discussion:

Commit message: Update location of BaseSettings and add annotations

Patch to review:
diff --git a/.github/workflows/test_on_push.yml b/.github/workflows/test_on_push.yml
index ba5c45719fd..616b63316a5 100644
--- a/.github/workflows/test_on_push.yml
+++ b/.github/workflows/test_on_push.yml
@@ -130,6 +130,7 @@ jobs:
           env PYTHONPATH=./ pytest tests/unit/test_mongodb_server.py
           env PYTHONPATH=./ pytest tests/unit/test_cache.py
           env PYTHONPATH=./ pytest tests/unit/test_llm_utils.py
+          env PYTHONPATH=./ pytest tests/unit/ml_handlers/test_mindsdb_inference.py
         fi
     - name: Run Handlers tests and submit Coverage to coveralls
       run: |
diff --git a/mindsdb/integrations/handlers/litellm_handler/settings.py b/mindsdb/integrations/handlers/litellm_handler/settings.py
index 3551d48750c..25381746bc8 100644
--- a/mindsdb/integrations/handlers/litellm_handler/settings.py
+++ b/mindsdb/integrations/handlers/litellm_handler/settings.py
@@ -33,7 +33,7 @@ class CompletionParameters(BaseModel):
     base_url: Optional[str] = None  # Base URL of the API.
     api_version: Optional[str] = None  # Version of the API to be used.
     api_key: str  # API key for authentication.
-    model_list: Optional[List] = None  # List of models, API bases, keys, etc., for dynamic selection.
+    llm_model_list: Optional[List] = None  # List of models, API bases, keys, etc., for dynamic selection.
 
     class Config:
         extra = Extra.forbid
diff --git a/mindsdb/integrations/handlers/mindsdb_inference/settings.py b/mindsdb/integrations/handlers/mindsdb_inference/settings.py
index c0c99e54447..45c653f7e86 100644
--- a/mindsdb/integrations/handlers/mindsdb_inference/settings.py
+++ b/mindsdb/integrations/handlers/mindsdb_inference/settings.py
@@ -1,4 +1,4 @@
-from pydantic import BaseSettings
+from pydantic_settings import BaseSettings
 
 
 class MindsDBInferenceHandlerConfig(BaseSettings):
@@ -12,7 +12,7 @@ class MindsDBInferenceHandlerConfig(BaseSettings):
         Base URL for the MindsDB Inference Endpoints API.
     """
 
-    BASE_URL = "https://llm.mdb.ai/"
+    BASE_URL: str = "https://llm.mdb.ai/"
 
 
 mindsdb_inference_handler_config = MindsDBInferenceHandlerConfig()
diff --git a/mindsdb/integrations/handlers/ms_teams_handler/settings.py b/mindsdb/integrations/handlers/ms_teams_handler/settings.py
index aa5f6a48e82..8ee85597bca 100644
--- a/mindsdb/integrations/handlers/ms_teams_handler/settings.py
+++ b/mindsdb/integrations/handlers/ms_teams_handler/settings.py
@@ -1,5 +1,5 @@
 from typing import List
-from pydantic import BaseSettings
+from pydantic_settings import BaseSettings
 
 
 class MSTeamsHandlerConfig(BaseSettings):
@@ -150,7 +150,7 @@ class MSTeamsHandlerConfig(BaseSettings):
         "eventDetail_initiator_user_tenantId"
     ]
 
-    TEST_CHAT_DATA = {
+    TEST_CHAT_DATA: dict = {
         '@odata.context': 'test_context',
         'id': 'test_id',
         'topic': None,
@@ -183,9 +183,9 @@ class MSTeamsHandlerConfig(BaseSettings):
         }
     }
 
-    TEST_CHATS_DATA = [TEST_CHAT_DATA]
+    TEST_CHATS_DATA: List = [TEST_CHAT_DATA]
 
-    TEST_CHAT_MESSAGE_DATA = {
+    TEST_CHAT_MESSAGE_DATA: dict = {
         '@odata.context': 'test_context', 
         'id': 'test_id', 
         'replyToId': None, 
@@ -239,9 +239,9 @@ class MSTeamsHandlerConfig(BaseSettings):
         }
     }
 
-    TEST_CHAT_MESSAGES_DATA = [TEST_CHAT_MESSAGE_DATA]
+    TEST_CHAT_MESSAGES_DATA: List = [TEST_CHAT_MESSAGE_DATA]
 
-    TEST_CHANNEL_DATA = {
+    TEST_CHANNEL_DATA: dict = {
         '@odata.context': 'test_context', 
         'id': 'test_id', 
         'createdDateTime': '2023-11-17T22:54:33.055Z', 
@@ -255,9 +255,9 @@ class MSTeamsHandlerConfig(BaseSettings):
         'teamId': 'test_team_id'
     }
 
-    TEST_CHANNELS_DATA = [TEST_CHANNEL_DATA]
+    TEST_CHANNELS_DATA: List = [TEST_CHANNEL_DATA]
 
-    TEST_CHANNEL_MESSAGE_DATA = {
+    TEST_CHANNEL_MESSAGE_DATA: dict = {
         '@odata.context': 'test_context', 
         'id': 'test_id', 
         'replyToId': None, 
@@ -322,9 +322,9 @@ class MSTeamsHandlerConfig(BaseSettings):
         }
     }
 
-    TEST_CHANNEL_MESSAGES_DATA = [TEST_CHANNEL_MESSAGE_DATA]
+    TEST_CHANNEL_MESSAGES_DATA: List = [TEST_CHANNEL_MESSAGE_DATA]
 
-    TEST_GROUP_DATA = {
+    TEST_GROUP_DATA: dict = {
         '@odata.context': 'test_context', 
         'value': [
             {
@@ -334,7 +334,7 @@ class MSTeamsHandlerConfig(BaseSettings):
         ]
     }
 
-    TEST_CHANNEL_ID_DATA = {
+    TEST_CHANNEL_ID_DATA: dict = {
         '@odata.context': 'test_context', 
         '@odata.count': 1,
         'value': [
diff --git a/mindsdb/integrations/handlers/mysql_handler/settings.py b/mindsdb/integrations/handlers/mysql_handler/settings.py
index 8a7b14178ae..b275eeb1208 100644
--- a/mindsdb/integrations/handlers/mysql_handler/settings.py
+++ b/mindsdb/integrations/handlers/mysql_handler/settings.py
@@ -42,5 +42,5 @@ def check_db_params(cls, values):
         return values
 
     class Config:
-        min_anystr_length = 1
-        anystr_strip_whitespace = True
+        str_min_length = 1
+        str_strip_whitespace = True
diff --git a/mindsdb/integrations/handlers/twelve_labs_handler/settings.py b/mindsdb/integrations/handlers/twelve_labs_handler/settings.py
index 0afac2cf856..0407978469b 100644
--- a/mindsdb/integrations/handlers/twelve_labs_handler/settings.py
+++ b/mindsdb/integrations/handlers/twelve_labs_handler/settings.py
@@ -1,6 +1,7 @@
 from typing import List, Optional
 
-from pydantic import BaseModel, BaseSettings, Extra, root_validator
+from pydantic import BaseModel, Extra, root_validator
+from pydantic_settings import BaseSettings
 
 from mindsdb.integrations.handlers.utilities.validation_utilities import ParameterValidationUtilities
 
@@ -258,9 +259,9 @@ class TwelveLabsHandlerConfig(BaseSettings):
         Default wait duration when polling video indexing tasks created via the Twelve Labs API.
     """
 
-    BASE_URL = "https://api.twelvelabs.io/v1.2"
-    DEFAULT_ENGINE = "marengo2.5"
-    DEFAULT_WAIT_DURATION = 5
+    BASE_URL: str = "https://api.twelvelabs.io/v1.2"
+    DEFAULT_ENGINE: str = "marengo2.5"
+    DEFAULT_WAIT_DURATION: int = 5
 
 
 twelve_labs_handler_config = TwelveLabsHandlerConfig()
diff --git a/mindsdb/integrations/libs/llm/config.py b/mindsdb/integrations/libs/llm/config.py
index 5d3eff78937..a8427df5d51 100644
--- a/mindsdb/integrations/libs/llm/config.py
+++ b/mindsdb/integrations/libs/llm/config.py
@@ -10,7 +10,7 @@ class BaseLLMConfig(BaseModel):
 # See https://api.python.langchain.com/en/latest/chat_models/langchain_community.chat_models.openai.ChatOpenAI.html#langchain_community.chat_models.openai.ChatOpenAI
 # This config does not have to be exclusively used with Langchain.
 class OpenAIConfig(BaseLLMConfig):
-    model_name: str
+    llm_model_name: str
     temperature: Optional[float]
     max_retries: Optional[int]
     max_tokens: Optional[int]
@@ -38,7 +38,7 @@ class AnthropicConfig(BaseLLMConfig):
 # See https://api.python.langchain.com/en/latest/chat_models/langchain_community.chat_models.anyscale.ChatAnyscale.html
 # This config does not have to be exclusively used with Langchain.
 class AnyscaleConfig(BaseLLMConfig):
-    model_name: str
+    llm_model_name: str
     temperature: Optional[float]
     max_retries: Optional[int]
     max_tokens: Optional[int]
@@ -52,7 +52,7 @@ class AnyscaleConfig(BaseLLMConfig):
 # See https://api.python.langchain.com/en/latest/chat_models/langchain_community.chat_models.litellm.ChatLiteLLM.html
 # This config does not have to be exclusively used with Langchain.
 class LiteLLMConfig(BaseLLMConfig):
-    model_name: str
+    llm_model_name: str
     api_base: Optional[str]
     max_retries: Optional[int]
     max_tokens: Optional[int]
@@ -60,7 +60,7 @@ class LiteLLMConfig(BaseLLMConfig):
     top_k: Optional[int]
     temperature: Optional[float]
     custom_llm_provider: Optional[str]
-    model_kwargs: Optional[Dict[str, Any]]
+    llm_model_kwargs: Optional[Dict[str, Any]]
 
 
 # See https://api.python.langchain.com/en/latest/chat_models/langchain_community.chat_models.ollama.ChatOllama.html
@@ -83,5 +83,5 @@ class OllamaConfig(BaseLLMConfig):
 
 
 class MindsdbConfig(BaseLLMConfig):
-    model_name: str
+    llm_model_name: str
     project_name: str
diff --git a/mindsdb/integrations/libs/llm/utils.py b/mindsdb/integrations/libs/llm/utils.py
index 2d319b24551..5ecd6a1883f 100644
--- a/mindsdb/integrations/libs/llm/utils.py
+++ b/mindsdb/integrations/libs/llm/utils.py
@@ -95,7 +95,7 @@ def get_llm_config(provider: str, config: Dict) -> BaseLLMConfig:
     temperature = min(1.0, max(0.0, config.get('temperature', 0.0)))
     if provider == 'openai':
         return OpenAIConfig(
-            model_name=config.get('model_name', DEFAULT_OPENAI_MODEL),
+            llm_model_name=config.get('model_name', DEFAULT_OPENAI_MODEL),
             temperature=temperature,
             max_retries=config.get('max_retries', DEFAULT_OPENAI_MAX_RETRIES),
             max_tokens=config.get('max_tokens', DEFAULT_OPENAI_MAX_TOKENS),
@@ -117,7 +117,7 @@ def get_llm_config(provider: str, config: Dict) -> BaseLLMConfig:
         )
     if provider == 'anyscale':
         return AnyscaleConfig(
-            model_name=config.get('model_name', DEFAULT_ANYSCALE_MODEL),
+            llm_model_name=config.get('model_name', DEFAULT_ANYSCALE_MODEL),
             temperature=temperature,
             max_retries=config.get('max_retries', DEFAULT_OPENAI_MAX_RETRIES),
             max_tokens=config.get('max_tokens', DEFAULT_OPENAI_MAX_TOKENS),
@@ -136,7 +136,7 @@ def get_llm_config(provider: str, config: Dict) -> BaseLLMConfig:
             'logit_bias': config.get('logit_bias', None),
         }
         return LiteLLMConfig(
-            model_name=config.get('model_name', DEFAULT_LITELLM_MODEL),
+            llm_model_name=config.get('model_name', DEFAULT_LITELLM_MODEL),
             temperature=temperature,
             api_base=config.get('base_url', DEFAULT_LITELLM_BASE_URL),
             max_retries=config.get('max_retries', DEFAULT_OPENAI_MAX_RETRIES),
@@ -144,7 +144,7 @@ def get_llm_config(provider: str, config: Dict) -> BaseLLMConfig:
             top_p=config.get('top_p', None),
             top_k=config.get('top_k', None),
             custom_llm_provider=config.get('custom_llm_provider', DEFAULT_LITELLM_PROVIDER),
-            model_kwargs=model_kwargs
+            llm_model_kwargs=model_kwargs
         )
     if provider == 'ollama':
         return OllamaConfig(
@@ -165,7 +165,7 @@ def get_llm_config(provider: str, config: Dict) -> BaseLLMConfig:
         )
     if provider == 'mindsdb':
         return MindsdbConfig(
-            model_name=config['model_name'],
+            llm_model_name=config['model_name'],
             project_name=config.get('project_name', 'mindsdb'),
         )
     raise ValueError(f'Provider {provider} is not supported.')
diff --git a/requirements/requirements.txt b/requirements/requirements.txt
index 7a17056d160..f237109f8a9 100644
--- a/requirements/requirements.txt
+++ b/requirements/requirements.txt
@@ -19,6 +19,7 @@ flask-compress >= 1.0.0
 appdirs >= 1.0.0
 mindsdb-sql ~= 0.15.0
 pydantic >= 2.0.3
+pydantic-settings >= 2.0.3
 mindsdb-evaluator >= 0.0.7, < 0.1.0
 checksumdir >= 1.2.0
 duckdb == 0.9.1


Code review comments:
diff_hunk: @@ -239,9 +239,9 @@ class MSTeamsHandlerConfig(BaseSettings):
         }
     }
 
-    TEST_CHAT_MESSAGES_DATA = [TEST_CHAT_MESSAGE_DATA]
+    TEST_CHAT_MESSAGES_DATA: List = [TEST_CHAT_MESSAGE_DATA]
path: mindsdb/integrations/handlers/ms_teams_handler/settings.py
text: @user1:
let's go with `List[dict]` instead perhaps