From 570b6fd00055dcbcf8af2db1b45735bc98288b33 Mon Sep 17 00:00:00 2001 From: Chester Curme Date: Mon, 16 Sep 2024 15:16:24 -0400 Subject: [PATCH 01/13] delete check_pydantic script --- libs/ibm/scripts/check_pydantic.sh | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100755 libs/ibm/scripts/check_pydantic.sh diff --git a/libs/ibm/scripts/check_pydantic.sh b/libs/ibm/scripts/check_pydantic.sh deleted file mode 100755 index 06b5bb8..0000000 --- a/libs/ibm/scripts/check_pydantic.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -# -# This script searches for lines starting with "import pydantic" or "from pydantic" -# in tracked files within a Git repository. -# -# Usage: ./scripts/check_pydantic.sh /path/to/repository - -# Check if a path argument is provided -if [ $# -ne 1 ]; then - echo "Usage: $0 /path/to/repository" - exit 1 -fi - -repository_path="$1" - -# Search for lines matching the pattern within the specified repository -result=$(git -C "$repository_path" grep -E '^import pydantic|^from pydantic') - -# Check if any matching lines were found -if [ -n "$result" ]; then - echo "ERROR: The following lines need to be updated:" - echo "$result" - echo "Please replace the code with an import from langchain_core.pydantic_v1." - echo "For example, replace 'from pydantic import BaseModel'" - echo "with 'from langchain_core.pydantic_v1 import BaseModel'" - exit 1 -fi From 5092c09b8187f6760c565af9c0050c349ffc6699 Mon Sep 17 00:00:00 2001 From: Chester Curme Date: Mon, 16 Sep 2024 15:17:09 -0400 Subject: [PATCH 02/13] extra_migrate --- libs/ibm/langchain_ibm/embeddings.py | 2 +- libs/ibm/langchain_ibm/llms.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/ibm/langchain_ibm/embeddings.py b/libs/ibm/langchain_ibm/embeddings.py index 3566fa2..5f3cbd6 100644 --- a/libs/ibm/langchain_ibm/embeddings.py +++ b/libs/ibm/langchain_ibm/embeddings.py @@ -64,7 +64,7 @@ class WatsonxEmbeddings(BaseModel, LangChainEmbeddings): class Config: """Configuration for this pydantic object.""" - extra = Extra.forbid + extra="forbid" arbitrary_types_allowed = True @root_validator(pre=False, skip_on_failure=True) diff --git a/libs/ibm/langchain_ibm/llms.py b/libs/ibm/langchain_ibm/llms.py index d90fdc5..d56783f 100644 --- a/libs/ibm/langchain_ibm/llms.py +++ b/libs/ibm/langchain_ibm/llms.py @@ -102,7 +102,7 @@ class WatsonxLLM(BaseLLM): class Config: """Configuration for this pydantic object.""" - extra = Extra.forbid + extra="forbid" @classmethod def is_lc_serializable(cls) -> bool: From bf32e2e32a2cfe6245c9b1a697b226129b031b17 Mon Sep 17 00:00:00 2001 From: Chester Curme Date: Mon, 16 Sep 2024 15:17:20 -0400 Subject: [PATCH 03/13] to_pydantic_2 --- libs/ibm/langchain_ibm/chat_models.py | 9 ++++----- libs/ibm/langchain_ibm/embeddings.py | 10 ++++------ libs/ibm/langchain_ibm/llms.py | 9 ++++----- libs/ibm/tests/integration_tests/test_chat_models.py | 2 +- 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/libs/ibm/langchain_ibm/chat_models.py b/libs/ibm/langchain_ibm/chat_models.py index 7d45455..c93c9fd 100644 --- a/libs/ibm/langchain_ibm/chat_models.py +++ b/libs/ibm/langchain_ibm/chat_models.py @@ -58,7 +58,7 @@ ) from langchain_core.outputs import ChatGeneration, ChatGenerationChunk, ChatResult from langchain_core.prompt_values import ChatPromptValue -from langchain_core.pydantic_v1 import BaseModel, Field, SecretStr, root_validator +from pydantic import BaseModel, Field, SecretStr, root_validator from langchain_core.runnables import Runnable, RunnableMap, RunnablePassthrough from langchain_core.tools import BaseTool from langchain_core.utils import convert_to_secret_str, get_from_dict_or_env @@ -66,6 +66,8 @@ convert_to_openai_function, convert_to_openai_tool, ) +from pydantic import ConfigDict + logger = logging.getLogger(__name__) @@ -374,10 +376,7 @@ class ChatWatsonx(BaseChatModel): watsonx_model: ModelInference = Field(default=None, exclude=True) #: :meta private: - class Config: - """Configuration for this pydantic object.""" - - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True,) @classmethod def is_lc_serializable(cls) -> bool: diff --git a/libs/ibm/langchain_ibm/embeddings.py b/libs/ibm/langchain_ibm/embeddings.py index 5f3cbd6..c1e04bc 100644 --- a/libs/ibm/langchain_ibm/embeddings.py +++ b/libs/ibm/langchain_ibm/embeddings.py @@ -4,7 +4,7 @@ from ibm_watsonx_ai import APIClient, Credentials # type: ignore from ibm_watsonx_ai.foundation_models.embeddings import Embeddings # type: ignore from langchain_core.embeddings import Embeddings as LangChainEmbeddings -from langchain_core.pydantic_v1 import ( +from pydantic import ( BaseModel, Extra, Field, @@ -12,6 +12,8 @@ root_validator, ) from langchain_core.utils import convert_to_secret_str, get_from_dict_or_env +from pydantic import ConfigDict + class WatsonxEmbeddings(BaseModel, LangChainEmbeddings): @@ -61,11 +63,7 @@ class WatsonxEmbeddings(BaseModel, LangChainEmbeddings): watsonx_client: APIClient = Field(default=None) #: :meta private: - class Config: - """Configuration for this pydantic object.""" - - extra="forbid" - arbitrary_types_allowed = True + model_config = ConfigDict(extra="forbid",arbitrary_types_allowed=True,) @root_validator(pre=False, skip_on_failure=True) def validate_environment(cls, values: Dict) -> Dict: diff --git a/libs/ibm/langchain_ibm/llms.py b/libs/ibm/langchain_ibm/llms.py index d56783f..c6bc5d3 100644 --- a/libs/ibm/langchain_ibm/llms.py +++ b/libs/ibm/langchain_ibm/llms.py @@ -8,8 +8,10 @@ from langchain_core.callbacks import CallbackManagerForLLMRun from langchain_core.language_models.llms import BaseLLM from langchain_core.outputs import Generation, GenerationChunk, LLMResult -from langchain_core.pydantic_v1 import Extra, Field, SecretStr, root_validator +from pydantic import Extra, Field, SecretStr, root_validator from langchain_core.utils import convert_to_secret_str, get_from_dict_or_env +from pydantic import ConfigDict + logger = logging.getLogger(__name__) textgen_valid_params = [ @@ -99,10 +101,7 @@ class WatsonxLLM(BaseLLM): watsonx_client: APIClient = Field(default=None) #: :meta private: - class Config: - """Configuration for this pydantic object.""" - - extra="forbid" + model_config = ConfigDict(extra="forbid",) @classmethod def is_lc_serializable(cls) -> bool: diff --git a/libs/ibm/tests/integration_tests/test_chat_models.py b/libs/ibm/tests/integration_tests/test_chat_models.py index a30b91e..05cf96d 100644 --- a/libs/ibm/tests/integration_tests/test_chat_models.py +++ b/libs/ibm/tests/integration_tests/test_chat_models.py @@ -12,7 +12,7 @@ SystemMessage, ) from langchain_core.prompts import ChatPromptTemplate -from langchain_core.pydantic_v1 import BaseModel +from pydantic import BaseModel from langchain_ibm import ChatWatsonx From 8e121284c7d04d9d9ae14a0b724e13df84d90d74 Mon Sep 17 00:00:00 2001 From: Chester Curme Date: Mon, 16 Sep 2024 15:17:39 -0400 Subject: [PATCH 04/13] model_after_rewrite --- libs/ibm/langchain_ibm/chat_models.py | 70 ++++++++-------- libs/ibm/langchain_ibm/embeddings.py | 92 ++++++++++----------- libs/ibm/langchain_ibm/llms.py | 112 +++++++++++++------------- 3 files changed, 137 insertions(+), 137 deletions(-) diff --git a/libs/ibm/langchain_ibm/chat_models.py b/libs/ibm/langchain_ibm/chat_models.py index c93c9fd..395b331 100644 --- a/libs/ibm/langchain_ibm/chat_models.py +++ b/libs/ibm/langchain_ibm/chat_models.py @@ -58,7 +58,7 @@ ) from langchain_core.outputs import ChatGeneration, ChatGenerationChunk, ChatResult from langchain_core.prompt_values import ChatPromptValue -from pydantic import BaseModel, Field, SecretStr, root_validator +from pydantic import BaseModel, Field, SecretStr, root_validator, model_validator from langchain_core.runnables import Runnable, RunnableMap, RunnablePassthrough from langchain_core.tools import BaseTool from langchain_core.utils import convert_to_secret_str, get_from_dict_or_env @@ -419,23 +419,23 @@ def lc_secrets(self) -> Dict[str, str]: "instance_id": "WATSONX_INSTANCE_ID", } - @root_validator(pre=False, skip_on_failure=True) - def validate_environment(cls, values: Dict) -> Dict: + @model_validator(mode="after") + def validate_environment(self) -> Self: """Validate that credentials and python package exists in environment.""" - values["url"] = convert_to_secret_str( + self.url = convert_to_secret_str( get_from_dict_or_env(values, "url", "WATSONX_URL") ) - if "cloud.ibm.com" in values.get("url", "").get_secret_value(): - values["apikey"] = convert_to_secret_str( + if "cloud.ibm.com" in self.url.get_secret_value(): + self.apikey = convert_to_secret_str( get_from_dict_or_env(values, "apikey", "WATSONX_APIKEY") ) else: if ( - not values["token"] + not self.token and "WATSONX_TOKEN" not in os.environ - and not values["password"] + and not self.password and "WATSONX_PASSWORD" not in os.environ - and not values["apikey"] + and not self.apikey and "WATSONX_APIKEY" not in os.environ ): raise ValueError( @@ -446,58 +446,58 @@ def validate_environment(cls, values: Dict) -> Dict: " or pass 'token', 'password' or 'apikey'" " as a named parameter." ) - elif values["token"] or "WATSONX_TOKEN" in os.environ: - values["token"] = convert_to_secret_str( + elif self.token or "WATSONX_TOKEN" in os.environ: + self.token = convert_to_secret_str( get_from_dict_or_env(values, "token", "WATSONX_TOKEN") ) - elif values["password"] or "WATSONX_PASSWORD" in os.environ: - values["password"] = convert_to_secret_str( + elif self.password or "WATSONX_PASSWORD" in os.environ: + self.password = convert_to_secret_str( get_from_dict_or_env(values, "password", "WATSONX_PASSWORD") ) - values["username"] = convert_to_secret_str( + self.username = convert_to_secret_str( get_from_dict_or_env(values, "username", "WATSONX_USERNAME") ) - elif values["apikey"] or "WATSONX_APIKEY" in os.environ: - values["apikey"] = convert_to_secret_str( + elif self.apikey or "WATSONX_APIKEY" in os.environ: + self.apikey = convert_to_secret_str( get_from_dict_or_env(values, "apikey", "WATSONX_APIKEY") ) - values["username"] = convert_to_secret_str( + self.username = convert_to_secret_str( get_from_dict_or_env(values, "username", "WATSONX_USERNAME") ) - if not values["instance_id"] or "WATSONX_INSTANCE_ID" not in os.environ: - values["instance_id"] = convert_to_secret_str( + if not self.instance_id or "WATSONX_INSTANCE_ID" not in os.environ: + self.instance_id = convert_to_secret_str( get_from_dict_or_env(values, "instance_id", "WATSONX_INSTANCE_ID") ) credentials = Credentials( - url=values["url"].get_secret_value() if values["url"] else None, - api_key=values["apikey"].get_secret_value() if values["apikey"] else None, - token=values["token"].get_secret_value() if values["token"] else None, + url=self.url.get_secret_value() if self.url else None, + api_key=self.apikey.get_secret_value() if self.apikey else None, + token=self.token.get_secret_value() if self.token else None, password=( - values["password"].get_secret_value() if values["password"] else None + self.password.get_secret_value() if self.password else None ), username=( - values["username"].get_secret_value() if values["username"] else None + self.username.get_secret_value() if self.username else None ), instance_id=( - values["instance_id"].get_secret_value() - if values["instance_id"] + self.instance_id.get_secret_value() + if self.instance_id else None ), - version=values["version"].get_secret_value() if values["version"] else None, - verify=values["verify"], + version=self.version.get_secret_value() if self.version else None, + verify=self.verify, ) watsonx_chat = ModelInference( - model_id=values["model_id"], - deployment_id=values["deployment_id"], + model_id=self.model_id, + deployment_id=self.deployment_id, credentials=credentials, - params=values["params"], - project_id=values["project_id"], - space_id=values["space_id"], + params=self.params, + project_id=self.project_id, + space_id=self.space_id, ) - values["watsonx_model"] = watsonx_chat + self.watsonx_model = watsonx_chat - return values + return self def _generate( self, diff --git a/libs/ibm/langchain_ibm/embeddings.py b/libs/ibm/langchain_ibm/embeddings.py index c1e04bc..6ae853b 100644 --- a/libs/ibm/langchain_ibm/embeddings.py +++ b/libs/ibm/langchain_ibm/embeddings.py @@ -9,7 +9,7 @@ Extra, Field, SecretStr, - root_validator, + root_validator, model_validator, ) from langchain_core.utils import convert_to_secret_str, get_from_dict_or_env from pydantic import ConfigDict @@ -65,35 +65,35 @@ class WatsonxEmbeddings(BaseModel, LangChainEmbeddings): model_config = ConfigDict(extra="forbid",arbitrary_types_allowed=True,) - @root_validator(pre=False, skip_on_failure=True) - def validate_environment(cls, values: Dict) -> Dict: + @model_validator(mode="after") + def validate_environment(self) -> Self: """Validate that credentials and python package exists in environment.""" - if isinstance(values.get("watsonx_client"), APIClient): + if isinstance((self.watsonx_client or None), APIClient): watsonx_embed = Embeddings( - model_id=values["model_id"], - params=values["params"], - api_client=values["watsonx_client"], - project_id=values["project_id"], - space_id=values["space_id"], - verify=values["verify"], + model_id=self.model_id, + params=self.params, + api_client=self.watsonx_client, + project_id=self.project_id, + space_id=self.space_id, + verify=self.verify, ) - values["watsonx_embed"] = watsonx_embed + self.watsonx_embed = watsonx_embed else: - values["url"] = convert_to_secret_str( + self.url = convert_to_secret_str( get_from_dict_or_env(values, "url", "WATSONX_URL") ) - if "cloud.ibm.com" in values.get("url", "").get_secret_value(): - values["apikey"] = convert_to_secret_str( + if "cloud.ibm.com" in self.url.get_secret_value(): + self.apikey = convert_to_secret_str( get_from_dict_or_env(values, "apikey", "WATSONX_APIKEY") ) else: if ( - not values["token"] + not self.token and "WATSONX_TOKEN" not in os.environ - and not values["password"] + and not self.password and "WATSONX_PASSWORD" not in os.environ - and not values["apikey"] + and not self.apikey and "WATSONX_APIKEY" not in os.environ ): raise ValueError( @@ -104,63 +104,63 @@ def validate_environment(cls, values: Dict) -> Dict: " or pass 'token', 'password' or 'apikey'" " as a named parameter." ) - elif values["token"] or "WATSONX_TOKEN" in os.environ: - values["token"] = convert_to_secret_str( + elif self.token or "WATSONX_TOKEN" in os.environ: + self.token = convert_to_secret_str( get_from_dict_or_env(values, "token", "WATSONX_TOKEN") ) - elif values["password"] or "WATSONX_PASSWORD" in os.environ: - values["password"] = convert_to_secret_str( + elif self.password or "WATSONX_PASSWORD" in os.environ: + self.password = convert_to_secret_str( get_from_dict_or_env(values, "password", "WATSONX_PASSWORD") ) - values["username"] = convert_to_secret_str( + self.username = convert_to_secret_str( get_from_dict_or_env(values, "username", "WATSONX_USERNAME") ) - elif values["apikey"] or "WATSONX_APIKEY" in os.environ: - values["apikey"] = convert_to_secret_str( + elif self.apikey or "WATSONX_APIKEY" in os.environ: + self.apikey = convert_to_secret_str( get_from_dict_or_env(values, "apikey", "WATSONX_APIKEY") ) - values["username"] = convert_to_secret_str( + self.username = convert_to_secret_str( get_from_dict_or_env(values, "username", "WATSONX_USERNAME") ) - if not values["instance_id"] or "WATSONX_INSTANCE_ID" not in os.environ: - values["instance_id"] = convert_to_secret_str( + if not self.instance_id or "WATSONX_INSTANCE_ID" not in os.environ: + self.instance_id = convert_to_secret_str( get_from_dict_or_env( values, "instance_id", "WATSONX_INSTANCE_ID" ) ) credentials = Credentials( - url=values["url"].get_secret_value() if values["url"] else None, - api_key=values["apikey"].get_secret_value() - if values["apikey"] + url=self.url.get_secret_value() if self.url else None, + api_key=self.apikey.get_secret_value() + if self.apikey else None, - token=values["token"].get_secret_value() if values["token"] else None, - password=values["password"].get_secret_value() - if values["password"] + token=self.token.get_secret_value() if self.token else None, + password=self.password.get_secret_value() + if self.password else None, - username=values["username"].get_secret_value() - if values["username"] + username=self.username.get_secret_value() + if self.username else None, - instance_id=values["instance_id"].get_secret_value() - if values["instance_id"] + instance_id=self.instance_id.get_secret_value() + if self.instance_id else None, - version=values["version"].get_secret_value() - if values["version"] + version=self.version.get_secret_value() + if self.version else None, - verify=values["verify"], + verify=self.verify, ) watsonx_embed = Embeddings( - model_id=values["model_id"], - params=values["params"], + model_id=self.model_id, + params=self.params, credentials=credentials, - project_id=values["project_id"], - space_id=values["space_id"], + project_id=self.project_id, + space_id=self.space_id, ) - values["watsonx_embed"] = watsonx_embed + self.watsonx_embed = watsonx_embed - return values + return self def embed_documents(self, texts: List[str]) -> List[List[float]]: """Embed search docs.""" diff --git a/libs/ibm/langchain_ibm/llms.py b/libs/ibm/langchain_ibm/llms.py index c6bc5d3..67dde1b 100644 --- a/libs/ibm/langchain_ibm/llms.py +++ b/libs/ibm/langchain_ibm/llms.py @@ -8,7 +8,7 @@ from langchain_core.callbacks import CallbackManagerForLLMRun from langchain_core.language_models.llms import BaseLLM from langchain_core.outputs import Generation, GenerationChunk, LLMResult -from pydantic import Extra, Field, SecretStr, root_validator +from pydantic import Extra, Field, SecretStr, root_validator, model_validator from langchain_core.utils import convert_to_secret_str, get_from_dict_or_env from pydantic import ConfigDict @@ -130,49 +130,49 @@ def lc_secrets(self) -> Dict[str, str]: "instance_id": "WATSONX_INSTANCE_ID", } - @root_validator(pre=False, skip_on_failure=True) - def validate_environment(cls, values: Dict) -> Dict: + @model_validator(mode="after") + def validate_environment(self) -> Self: """Validate that credentials and python package exists in environment.""" - if isinstance(values.get("watsonx_model"), (ModelInference, Model)): - values["model_id"] = getattr(values["watsonx_model"], "model_id") - values["deployment_id"] = getattr( - values["watsonx_model"], "deployment_id", "" + if isinstance((self.watsonx_model or None), (ModelInference, Model)): + self.model_id = getattr(self.watsonx_model, "model_id") + self.deployment_id = getattr( + self.watsonx_model, "deployment_id", "" ) - values["project_id"] = getattr( - getattr(values["watsonx_model"], "_client"), + self.project_id = getattr( + getattr(self.watsonx_model, "_client"), "default_project_id", ) - values["space_id"] = getattr( - getattr(values["watsonx_model"], "_client"), "default_space_id" + self.space_id = getattr( + getattr(self.watsonx_model, "_client"), "default_space_id" ) - values["params"] = getattr(values["watsonx_model"], "params") + self.params = getattr(self.watsonx_model, "params") - elif isinstance(values.get("watsonx_client"), APIClient): + elif isinstance((self.watsonx_client or None), APIClient): watsonx_model = ModelInference( - model_id=values["model_id"], - params=values["params"], - api_client=values["watsonx_client"], - project_id=values["project_id"], - space_id=values["space_id"], - verify=values["verify"], + model_id=self.model_id, + params=self.params, + api_client=self.watsonx_client, + project_id=self.project_id, + space_id=self.space_id, + verify=self.verify, ) - values["watsonx_model"] = watsonx_model + self.watsonx_model = watsonx_model else: - values["url"] = convert_to_secret_str( + self.url = convert_to_secret_str( get_from_dict_or_env(values, "url", "WATSONX_URL") ) - if "cloud.ibm.com" in values.get("url", "").get_secret_value(): - values["apikey"] = convert_to_secret_str( + if "cloud.ibm.com" in self.url.get_secret_value(): + self.apikey = convert_to_secret_str( get_from_dict_or_env(values, "apikey", "WATSONX_APIKEY") ) else: if ( - not values["token"] + not self.token and "WATSONX_TOKEN" not in os.environ - and not values["password"] + and not self.password and "WATSONX_PASSWORD" not in os.environ - and not values["apikey"] + and not self.apikey and "WATSONX_APIKEY" not in os.environ ): raise ValueError( @@ -183,62 +183,62 @@ def validate_environment(cls, values: Dict) -> Dict: " or pass 'token', 'password' or 'apikey'" " as a named parameter." ) - elif values["token"] or "WATSONX_TOKEN" in os.environ: - values["token"] = convert_to_secret_str( + elif self.token or "WATSONX_TOKEN" in os.environ: + self.token = convert_to_secret_str( get_from_dict_or_env(values, "token", "WATSONX_TOKEN") ) - elif values["password"] or "WATSONX_PASSWORD" in os.environ: - values["password"] = convert_to_secret_str( + elif self.password or "WATSONX_PASSWORD" in os.environ: + self.password = convert_to_secret_str( get_from_dict_or_env(values, "password", "WATSONX_PASSWORD") ) - values["username"] = convert_to_secret_str( + self.username = convert_to_secret_str( get_from_dict_or_env(values, "username", "WATSONX_USERNAME") ) - elif values["apikey"] or "WATSONX_APIKEY" in os.environ: - values["apikey"] = convert_to_secret_str( + elif self.apikey or "WATSONX_APIKEY" in os.environ: + self.apikey = convert_to_secret_str( get_from_dict_or_env(values, "apikey", "WATSONX_APIKEY") ) - values["username"] = convert_to_secret_str( + self.username = convert_to_secret_str( get_from_dict_or_env(values, "username", "WATSONX_USERNAME") ) - if not values["instance_id"] or "WATSONX_INSTANCE_ID" not in os.environ: - values["instance_id"] = convert_to_secret_str( + if not self.instance_id or "WATSONX_INSTANCE_ID" not in os.environ: + self.instance_id = convert_to_secret_str( get_from_dict_or_env( values, "instance_id", "WATSONX_INSTANCE_ID" ) ) credentials = Credentials( - url=values["url"].get_secret_value() if values["url"] else None, - api_key=values["apikey"].get_secret_value() - if values["apikey"] + url=self.url.get_secret_value() if self.url else None, + api_key=self.apikey.get_secret_value() + if self.apikey else None, - token=values["token"].get_secret_value() if values["token"] else None, - password=values["password"].get_secret_value() - if values["password"] + token=self.token.get_secret_value() if self.token else None, + password=self.password.get_secret_value() + if self.password else None, - username=values["username"].get_secret_value() - if values["username"] + username=self.username.get_secret_value() + if self.username else None, - instance_id=values["instance_id"].get_secret_value() - if values["instance_id"] + instance_id=self.instance_id.get_secret_value() + if self.instance_id else None, - version=values["version"].get_secret_value() - if values["version"] + version=self.version.get_secret_value() + if self.version else None, - verify=values["verify"], + verify=self.verify, ) watsonx_model = ModelInference( - model_id=values["model_id"], - deployment_id=values["deployment_id"], + model_id=self.model_id, + deployment_id=self.deployment_id, credentials=credentials, - params=values["params"], - project_id=values["project_id"], - space_id=values["space_id"], + params=self.params, + project_id=self.project_id, + space_id=self.space_id, ) - values["watsonx_model"] = watsonx_model + self.watsonx_model = watsonx_model - return values + return self @property def _identifying_params(self) -> Mapping[str, Any]: From a096355171784ccb6636e91d24b8eef7cc4d3891 Mon Sep 17 00:00:00 2001 From: Chester Curme Date: Mon, 16 Sep 2024 15:17:53 -0400 Subject: [PATCH 05/13] Self --- libs/ibm/langchain_ibm/chat_models.py | 2 ++ libs/ibm/langchain_ibm/embeddings.py | 2 ++ libs/ibm/langchain_ibm/llms.py | 2 ++ 3 files changed, 6 insertions(+) diff --git a/libs/ibm/langchain_ibm/chat_models.py b/libs/ibm/langchain_ibm/chat_models.py index 395b331..f85b88e 100644 --- a/libs/ibm/langchain_ibm/chat_models.py +++ b/libs/ibm/langchain_ibm/chat_models.py @@ -67,6 +67,8 @@ convert_to_openai_tool, ) from pydantic import ConfigDict +from typing_extensions import Self + logger = logging.getLogger(__name__) diff --git a/libs/ibm/langchain_ibm/embeddings.py b/libs/ibm/langchain_ibm/embeddings.py index 6ae853b..b11ae90 100644 --- a/libs/ibm/langchain_ibm/embeddings.py +++ b/libs/ibm/langchain_ibm/embeddings.py @@ -13,6 +13,8 @@ ) from langchain_core.utils import convert_to_secret_str, get_from_dict_or_env from pydantic import ConfigDict +from typing_extensions import Self + diff --git a/libs/ibm/langchain_ibm/llms.py b/libs/ibm/langchain_ibm/llms.py index 67dde1b..56e57c2 100644 --- a/libs/ibm/langchain_ibm/llms.py +++ b/libs/ibm/langchain_ibm/llms.py @@ -11,6 +11,8 @@ from pydantic import Extra, Field, SecretStr, root_validator, model_validator from langchain_core.utils import convert_to_secret_str, get_from_dict_or_env from pydantic import ConfigDict +from typing_extensions import Self + logger = logging.getLogger(__name__) From 7574ecdee0294e05b4ddc70f6808e9a4bd16de70 Mon Sep 17 00:00:00 2001 From: Chester Curme Date: Mon, 16 Sep 2024 15:21:44 -0400 Subject: [PATCH 06/13] update deps and increment version --- libs/ibm/poetry.lock | 21 +++++++++++---------- libs/ibm/pyproject.toml | 4 ++-- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/libs/ibm/poetry.lock b/libs/ibm/poetry.lock index a91931e..f78c3b7 100644 --- a/libs/ibm/poetry.lock +++ b/libs/ibm/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "annotated-types" @@ -408,19 +408,19 @@ files = [ [[package]] name = "langchain-core" -version = "0.2.29" +version = "0.3.0" description = "Building applications with LLMs through composability" optional = false -python-versions = ">=3.8.1,<4.0" +python-versions = ">=3.9,<4.0" files = [] develop = false [package.dependencies] jsonpatch = "^1.33" -langsmith = "^0.1.75" +langsmith = "^0.1.117" packaging = ">=23.2,<25" pydantic = [ - {version = ">=1,<3", markers = "python_full_version < \"3.12.4\""}, + {version = ">=2.5.2,<3.0.0", markers = "python_full_version < \"3.12.4\""}, {version = ">=2.7.4,<3.0.0", markers = "python_full_version >= \"3.12.4\""}, ] PyYAML = ">=5.3" @@ -431,21 +431,22 @@ typing-extensions = ">=4.7" type = "git" url = "https://github.com/langchain-ai/langchain.git" reference = "HEAD" -resolved_reference = "d77c7c4236df8e56fbe3acc8e0a71b57b48f1678" +resolved_reference = "a319a0ff1d17057d750f7e4a8fee98aa8f68703c" subdirectory = "libs/core" [[package]] name = "langsmith" -version = "0.1.98" +version = "0.1.121" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langsmith-0.1.98-py3-none-any.whl", hash = "sha256:f79e8a128652bbcee4606d10acb6236973b5cd7dde76e3741186d3b97b5698e9"}, - {file = "langsmith-0.1.98.tar.gz", hash = "sha256:e07678219a0502e8f26d35294e72127a39d25e32fafd091af5a7bb661e9a6bd1"}, + {file = "langsmith-0.1.121-py3-none-any.whl", hash = "sha256:fdb1ac8a671d3904201bfeea197d87bded46a10d08f1034af464211872e29893"}, + {file = "langsmith-0.1.121.tar.gz", hash = "sha256:e9381b82a5bd484af9a51c3e96faea572746b8d617b070c1cda40cbbe48e33df"}, ] [package.dependencies] +httpx = ">=0.23.0,<1" orjson = ">=3.9.14,<4.0.0" pydantic = [ {version = ">=1,<3", markers = "python_full_version < \"3.12.4\""}, @@ -1246,4 +1247,4 @@ test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", [metadata] lock-version = "2.0" python-versions = ">=3.10,<4.0" -content-hash = "1377b3c14ce0358d6ea7103f33f493598cba742b9cc8244f6a37b0b84455bd30" +content-hash = "62b6b86e3d90ca10c505e6fcc7e21d3265ed59475d65514cc1d6d387208f57ac" diff --git a/libs/ibm/pyproject.toml b/libs/ibm/pyproject.toml index fe0b421..dbcee5d 100644 --- a/libs/ibm/pyproject.toml +++ b/libs/ibm/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langchain-ibm" -version = "0.1.12" +version = "0.2.0" description = "An integration package connecting IBM watsonx.ai and LangChain" authors = ["IBM"] readme = "README.md" @@ -12,7 +12,7 @@ license = "MIT" [tool.poetry.dependencies] python = ">=3.10,<4.0" -langchain-core = ">=0.2.2,<0.3" +langchain-core = ">=0.3.0,<0.4" ibm-watsonx-ai = "^1.0.8" [tool.poetry.group.test] From ecc77ba56e76186092f3e3674b5d7d69a70df30d Mon Sep 17 00:00:00 2001 From: Chester Curme Date: Mon, 16 Sep 2024 15:21:58 -0400 Subject: [PATCH 07/13] format --- libs/ibm/langchain_ibm/chat_models.py | 28 ++++++++++----------- libs/ibm/langchain_ibm/embeddings.py | 30 +++++++++------------- libs/ibm/langchain_ibm/llms.py | 36 ++++++++++++--------------- 3 files changed, 42 insertions(+), 52 deletions(-) diff --git a/libs/ibm/langchain_ibm/chat_models.py b/libs/ibm/langchain_ibm/chat_models.py index f85b88e..41fffb0 100644 --- a/libs/ibm/langchain_ibm/chat_models.py +++ b/libs/ibm/langchain_ibm/chat_models.py @@ -58,7 +58,6 @@ ) from langchain_core.outputs import ChatGeneration, ChatGenerationChunk, ChatResult from langchain_core.prompt_values import ChatPromptValue -from pydantic import BaseModel, Field, SecretStr, root_validator, model_validator from langchain_core.runnables import Runnable, RunnableMap, RunnablePassthrough from langchain_core.tools import BaseTool from langchain_core.utils import convert_to_secret_str, get_from_dict_or_env @@ -66,11 +65,16 @@ convert_to_openai_function, convert_to_openai_tool, ) -from pydantic import ConfigDict +from pydantic import ( + BaseModel, + ConfigDict, + Field, + SecretStr, + model_validator, + root_validator, +) from typing_extensions import Self - - logger = logging.getLogger(__name__) @@ -378,7 +382,9 @@ class ChatWatsonx(BaseChatModel): watsonx_model: ModelInference = Field(default=None, exclude=True) #: :meta private: - model_config = ConfigDict(populate_by_name=True,) + model_config = ConfigDict( + populate_by_name=True, + ) @classmethod def is_lc_serializable(cls) -> bool: @@ -474,16 +480,10 @@ def validate_environment(self) -> Self: url=self.url.get_secret_value() if self.url else None, api_key=self.apikey.get_secret_value() if self.apikey else None, token=self.token.get_secret_value() if self.token else None, - password=( - self.password.get_secret_value() if self.password else None - ), - username=( - self.username.get_secret_value() if self.username else None - ), + password=(self.password.get_secret_value() if self.password else None), + username=(self.username.get_secret_value() if self.username else None), instance_id=( - self.instance_id.get_secret_value() - if self.instance_id - else None + self.instance_id.get_secret_value() if self.instance_id else None ), version=self.version.get_secret_value() if self.version else None, verify=self.verify, diff --git a/libs/ibm/langchain_ibm/embeddings.py b/libs/ibm/langchain_ibm/embeddings.py index b11ae90..24e6171 100644 --- a/libs/ibm/langchain_ibm/embeddings.py +++ b/libs/ibm/langchain_ibm/embeddings.py @@ -4,20 +4,19 @@ from ibm_watsonx_ai import APIClient, Credentials # type: ignore from ibm_watsonx_ai.foundation_models.embeddings import Embeddings # type: ignore from langchain_core.embeddings import Embeddings as LangChainEmbeddings +from langchain_core.utils import convert_to_secret_str, get_from_dict_or_env from pydantic import ( BaseModel, + ConfigDict, Extra, Field, SecretStr, - root_validator, model_validator, + model_validator, + root_validator, ) -from langchain_core.utils import convert_to_secret_str, get_from_dict_or_env -from pydantic import ConfigDict from typing_extensions import Self - - class WatsonxEmbeddings(BaseModel, LangChainEmbeddings): """IBM WatsonX.ai embedding models.""" @@ -65,7 +64,10 @@ class WatsonxEmbeddings(BaseModel, LangChainEmbeddings): watsonx_client: APIClient = Field(default=None) #: :meta private: - model_config = ConfigDict(extra="forbid",arbitrary_types_allowed=True,) + model_config = ConfigDict( + extra="forbid", + arbitrary_types_allowed=True, + ) @model_validator(mode="after") def validate_environment(self) -> Self: @@ -133,22 +135,14 @@ def validate_environment(self) -> Self: credentials = Credentials( url=self.url.get_secret_value() if self.url else None, - api_key=self.apikey.get_secret_value() - if self.apikey - else None, + api_key=self.apikey.get_secret_value() if self.apikey else None, token=self.token.get_secret_value() if self.token else None, - password=self.password.get_secret_value() - if self.password - else None, - username=self.username.get_secret_value() - if self.username - else None, + password=self.password.get_secret_value() if self.password else None, + username=self.username.get_secret_value() if self.username else None, instance_id=self.instance_id.get_secret_value() if self.instance_id else None, - version=self.version.get_secret_value() - if self.version - else None, + version=self.version.get_secret_value() if self.version else None, verify=self.verify, ) diff --git a/libs/ibm/langchain_ibm/llms.py b/libs/ibm/langchain_ibm/llms.py index 56e57c2..d5ae205 100644 --- a/libs/ibm/langchain_ibm/llms.py +++ b/libs/ibm/langchain_ibm/llms.py @@ -8,13 +8,17 @@ from langchain_core.callbacks import CallbackManagerForLLMRun from langchain_core.language_models.llms import BaseLLM from langchain_core.outputs import Generation, GenerationChunk, LLMResult -from pydantic import Extra, Field, SecretStr, root_validator, model_validator from langchain_core.utils import convert_to_secret_str, get_from_dict_or_env -from pydantic import ConfigDict +from pydantic import ( + ConfigDict, + Extra, + Field, + SecretStr, + model_validator, + root_validator, +) from typing_extensions import Self - - logger = logging.getLogger(__name__) textgen_valid_params = [ value for key, value in GenTextParamsMetaNames.__dict__.items() if key.isupper() @@ -103,7 +107,9 @@ class WatsonxLLM(BaseLLM): watsonx_client: APIClient = Field(default=None) #: :meta private: - model_config = ConfigDict(extra="forbid",) + model_config = ConfigDict( + extra="forbid", + ) @classmethod def is_lc_serializable(cls) -> bool: @@ -137,9 +143,7 @@ def validate_environment(self) -> Self: """Validate that credentials and python package exists in environment.""" if isinstance((self.watsonx_model or None), (ModelInference, Model)): self.model_id = getattr(self.watsonx_model, "model_id") - self.deployment_id = getattr( - self.watsonx_model, "deployment_id", "" - ) + self.deployment_id = getattr(self.watsonx_model, "deployment_id", "") self.project_id = getattr( getattr(self.watsonx_model, "_client"), "default_project_id", @@ -211,22 +215,14 @@ def validate_environment(self) -> Self: ) credentials = Credentials( url=self.url.get_secret_value() if self.url else None, - api_key=self.apikey.get_secret_value() - if self.apikey - else None, + api_key=self.apikey.get_secret_value() if self.apikey else None, token=self.token.get_secret_value() if self.token else None, - password=self.password.get_secret_value() - if self.password - else None, - username=self.username.get_secret_value() - if self.username - else None, + password=self.password.get_secret_value() if self.password else None, + username=self.username.get_secret_value() if self.username else None, instance_id=self.instance_id.get_secret_value() if self.instance_id else None, - version=self.version.get_secret_value() - if self.version - else None, + version=self.version.get_secret_value() if self.version else None, verify=self.verify, ) From c5a7d0b89d832f855a56af0dd041464f8dcd537a Mon Sep 17 00:00:00 2001 From: Chester Curme Date: Mon, 16 Sep 2024 15:23:06 -0400 Subject: [PATCH 08/13] clean up --- libs/ibm/langchain_ibm/embeddings.py | 2 +- libs/ibm/langchain_ibm/llms.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/ibm/langchain_ibm/embeddings.py b/libs/ibm/langchain_ibm/embeddings.py index 24e6171..4d3a981 100644 --- a/libs/ibm/langchain_ibm/embeddings.py +++ b/libs/ibm/langchain_ibm/embeddings.py @@ -72,7 +72,7 @@ class WatsonxEmbeddings(BaseModel, LangChainEmbeddings): @model_validator(mode="after") def validate_environment(self) -> Self: """Validate that credentials and python package exists in environment.""" - if isinstance((self.watsonx_client or None), APIClient): + if isinstance(self.watsonx_client, APIClient): watsonx_embed = Embeddings( model_id=self.model_id, params=self.params, diff --git a/libs/ibm/langchain_ibm/llms.py b/libs/ibm/langchain_ibm/llms.py index d5ae205..c2165af 100644 --- a/libs/ibm/langchain_ibm/llms.py +++ b/libs/ibm/langchain_ibm/llms.py @@ -141,7 +141,7 @@ def lc_secrets(self) -> Dict[str, str]: @model_validator(mode="after") def validate_environment(self) -> Self: """Validate that credentials and python package exists in environment.""" - if isinstance((self.watsonx_model or None), (ModelInference, Model)): + if isinstance(self.watsonx_model, (ModelInference, Model)): self.model_id = getattr(self.watsonx_model, "model_id") self.deployment_id = getattr(self.watsonx_model, "deployment_id", "") self.project_id = getattr( @@ -153,7 +153,7 @@ def validate_environment(self) -> Self: ) self.params = getattr(self.watsonx_model, "params") - elif isinstance((self.watsonx_client or None), APIClient): + elif isinstance(self.watsonx_client, APIClient): watsonx_model = ModelInference( model_id=self.model_id, params=self.params, From fe190c81e041ca7d38d50acf3806c7ce5f279278 Mon Sep 17 00:00:00 2001 From: Chester Curme Date: Mon, 16 Sep 2024 15:30:25 -0400 Subject: [PATCH 09/13] update model validation to pre --- libs/ibm/langchain_ibm/chat_models.py | 75 ++++++++++++++------------- 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/libs/ibm/langchain_ibm/chat_models.py b/libs/ibm/langchain_ibm/chat_models.py index 41fffb0..97b53b0 100644 --- a/libs/ibm/langchain_ibm/chat_models.py +++ b/libs/ibm/langchain_ibm/chat_models.py @@ -71,9 +71,7 @@ Field, SecretStr, model_validator, - root_validator, ) -from typing_extensions import Self logger = logging.getLogger(__name__) @@ -427,23 +425,24 @@ def lc_secrets(self) -> Dict[str, str]: "instance_id": "WATSONX_INSTANCE_ID", } - @model_validator(mode="after") - def validate_environment(self) -> Self: + @model_validator(mode="before") + @classmethod + def validate_environment(cls, values: Dict) -> Any: """Validate that credentials and python package exists in environment.""" - self.url = convert_to_secret_str( + values["url"] = convert_to_secret_str( get_from_dict_or_env(values, "url", "WATSONX_URL") ) - if "cloud.ibm.com" in self.url.get_secret_value(): - self.apikey = convert_to_secret_str( + if "cloud.ibm.com" in values.get("url", "").get_secret_value(): + values["apikey"] = convert_to_secret_str( get_from_dict_or_env(values, "apikey", "WATSONX_APIKEY") ) else: if ( - not self.token + not values["token"] and "WATSONX_TOKEN" not in os.environ - and not self.password + and not values["password"] and "WATSONX_PASSWORD" not in os.environ - and not self.apikey + and not values["apikey"] and "WATSONX_APIKEY" not in os.environ ): raise ValueError( @@ -454,52 +453,58 @@ def validate_environment(self) -> Self: " or pass 'token', 'password' or 'apikey'" " as a named parameter." ) - elif self.token or "WATSONX_TOKEN" in os.environ: - self.token = convert_to_secret_str( + elif values["token"] or "WATSONX_TOKEN" in os.environ: + values["token"] = convert_to_secret_str( get_from_dict_or_env(values, "token", "WATSONX_TOKEN") ) - elif self.password or "WATSONX_PASSWORD" in os.environ: - self.password = convert_to_secret_str( + elif values["password"] or "WATSONX_PASSWORD" in os.environ: + values["password"] = convert_to_secret_str( get_from_dict_or_env(values, "password", "WATSONX_PASSWORD") ) - self.username = convert_to_secret_str( + values["username"] = convert_to_secret_str( get_from_dict_or_env(values, "username", "WATSONX_USERNAME") ) - elif self.apikey or "WATSONX_APIKEY" in os.environ: - self.apikey = convert_to_secret_str( + elif values["apikey"] or "WATSONX_APIKEY" in os.environ: + values["apikey"] = convert_to_secret_str( get_from_dict_or_env(values, "apikey", "WATSONX_APIKEY") ) - self.username = convert_to_secret_str( + values["username"] = convert_to_secret_str( get_from_dict_or_env(values, "username", "WATSONX_USERNAME") ) - if not self.instance_id or "WATSONX_INSTANCE_ID" not in os.environ: - self.instance_id = convert_to_secret_str( + if not values["instance_id"] or "WATSONX_INSTANCE_ID" not in os.environ: + values["instance_id"] = convert_to_secret_str( get_from_dict_or_env(values, "instance_id", "WATSONX_INSTANCE_ID") ) credentials = Credentials( - url=self.url.get_secret_value() if self.url else None, - api_key=self.apikey.get_secret_value() if self.apikey else None, - token=self.token.get_secret_value() if self.token else None, - password=(self.password.get_secret_value() if self.password else None), - username=(self.username.get_secret_value() if self.username else None), + url=values["url"].get_secret_value() if values["url"] else None, + api_key=values["apikey"].get_secret_value() if values["apikey"] else None, + token=values["token"].get_secret_value() if values["token"] else None, + password=( + values["password"].get_secret_value() if values["password"] else None + ), + username=( + values["username"].get_secret_value() if values["username"] else None + ), instance_id=( - self.instance_id.get_secret_value() if self.instance_id else None + values["instance_id"].get_secret_value() + if values["instance_id"] + else None ), - version=self.version.get_secret_value() if self.version else None, - verify=self.verify, + version=values["version"].get_secret_value() if values["version"] else None, + verify=values["verify"], ) watsonx_chat = ModelInference( - model_id=self.model_id, - deployment_id=self.deployment_id, + model_id=values["model_id"], + deployment_id=values["deployment_id"], credentials=credentials, - params=self.params, - project_id=self.project_id, - space_id=self.space_id, + params=values["params"], + project_id=values["project_id"], + space_id=values["space_id"], ) - self.watsonx_model = watsonx_chat + values["watsonx_model"] = watsonx_chat - return self + return values def _generate( self, From d69e50e4bb49b24057afb588711f2928da2c56bf Mon Sep 17 00:00:00 2001 From: Chester Curme Date: Mon, 16 Sep 2024 15:33:21 -0400 Subject: [PATCH 10/13] update more model_validators to pre --- libs/ibm/langchain_ibm/embeddings.py | 96 +++++++++++----------- libs/ibm/langchain_ibm/llms.py | 114 ++++++++++++++------------- 2 files changed, 112 insertions(+), 98 deletions(-) diff --git a/libs/ibm/langchain_ibm/embeddings.py b/libs/ibm/langchain_ibm/embeddings.py index 4d3a981..5492980 100644 --- a/libs/ibm/langchain_ibm/embeddings.py +++ b/libs/ibm/langchain_ibm/embeddings.py @@ -1,5 +1,5 @@ import os -from typing import Dict, List, Optional, Union +from typing import Any, Dict, List, Optional, Union from ibm_watsonx_ai import APIClient, Credentials # type: ignore from ibm_watsonx_ai.foundation_models.embeddings import Embeddings # type: ignore @@ -8,13 +8,10 @@ from pydantic import ( BaseModel, ConfigDict, - Extra, Field, SecretStr, model_validator, - root_validator, ) -from typing_extensions import Self class WatsonxEmbeddings(BaseModel, LangChainEmbeddings): @@ -69,35 +66,36 @@ class WatsonxEmbeddings(BaseModel, LangChainEmbeddings): arbitrary_types_allowed=True, ) - @model_validator(mode="after") - def validate_environment(self) -> Self: + @model_validator(mode="before") + @classmethod + def validate_environment(cls, values: Dict) -> Any: """Validate that credentials and python package exists in environment.""" - if isinstance(self.watsonx_client, APIClient): + if isinstance(values.get("watsonx_client"), APIClient): watsonx_embed = Embeddings( - model_id=self.model_id, - params=self.params, - api_client=self.watsonx_client, - project_id=self.project_id, - space_id=self.space_id, - verify=self.verify, + model_id=values["model_id"], + params=values["params"], + api_client=values["watsonx_client"], + project_id=values["project_id"], + space_id=values["space_id"], + verify=values["verify"], ) - self.watsonx_embed = watsonx_embed + values["watsonx_embed"] = watsonx_embed else: - self.url = convert_to_secret_str( + values["url"] = convert_to_secret_str( get_from_dict_or_env(values, "url", "WATSONX_URL") ) - if "cloud.ibm.com" in self.url.get_secret_value(): - self.apikey = convert_to_secret_str( + if "cloud.ibm.com" in values.get("url", "").get_secret_value(): + values["apikey"] = convert_to_secret_str( get_from_dict_or_env(values, "apikey", "WATSONX_APIKEY") ) else: if ( - not self.token + not values["token"] and "WATSONX_TOKEN" not in os.environ - and not self.password + and not values["password"] and "WATSONX_PASSWORD" not in os.environ - and not self.apikey + and not values["apikey"] and "WATSONX_APIKEY" not in os.environ ): raise ValueError( @@ -108,55 +106,63 @@ def validate_environment(self) -> Self: " or pass 'token', 'password' or 'apikey'" " as a named parameter." ) - elif self.token or "WATSONX_TOKEN" in os.environ: - self.token = convert_to_secret_str( + elif values["token"] or "WATSONX_TOKEN" in os.environ: + values["token"] = convert_to_secret_str( get_from_dict_or_env(values, "token", "WATSONX_TOKEN") ) - elif self.password or "WATSONX_PASSWORD" in os.environ: - self.password = convert_to_secret_str( + elif values["password"] or "WATSONX_PASSWORD" in os.environ: + values["password"] = convert_to_secret_str( get_from_dict_or_env(values, "password", "WATSONX_PASSWORD") ) - self.username = convert_to_secret_str( + values["username"] = convert_to_secret_str( get_from_dict_or_env(values, "username", "WATSONX_USERNAME") ) - elif self.apikey or "WATSONX_APIKEY" in os.environ: - self.apikey = convert_to_secret_str( + elif values["apikey"] or "WATSONX_APIKEY" in os.environ: + values["apikey"] = convert_to_secret_str( get_from_dict_or_env(values, "apikey", "WATSONX_APIKEY") ) - self.username = convert_to_secret_str( + values["username"] = convert_to_secret_str( get_from_dict_or_env(values, "username", "WATSONX_USERNAME") ) - if not self.instance_id or "WATSONX_INSTANCE_ID" not in os.environ: - self.instance_id = convert_to_secret_str( + if not values["instance_id"] or "WATSONX_INSTANCE_ID" not in os.environ: + values["instance_id"] = convert_to_secret_str( get_from_dict_or_env( values, "instance_id", "WATSONX_INSTANCE_ID" ) ) credentials = Credentials( - url=self.url.get_secret_value() if self.url else None, - api_key=self.apikey.get_secret_value() if self.apikey else None, - token=self.token.get_secret_value() if self.token else None, - password=self.password.get_secret_value() if self.password else None, - username=self.username.get_secret_value() if self.username else None, - instance_id=self.instance_id.get_secret_value() - if self.instance_id + url=values["url"].get_secret_value() if values["url"] else None, + api_key=values["apikey"].get_secret_value() + if values["apikey"] else None, - version=self.version.get_secret_value() if self.version else None, - verify=self.verify, + token=values["token"].get_secret_value() if values["token"] else None, + password=values["password"].get_secret_value() + if values["password"] + else None, + username=values["username"].get_secret_value() + if values["username"] + else None, + instance_id=values["instance_id"].get_secret_value() + if values["instance_id"] + else None, + version=values["version"].get_secret_value() + if values["version"] + else None, + verify=values["verify"], ) watsonx_embed = Embeddings( - model_id=self.model_id, - params=self.params, + model_id=values["model_id"], + params=values["params"], credentials=credentials, - project_id=self.project_id, - space_id=self.space_id, + project_id=values["project_id"], + space_id=values["space_id"], ) - self.watsonx_embed = watsonx_embed + values["watsonx_embed"] = watsonx_embed - return self + return values def embed_documents(self, texts: List[str]) -> List[List[float]]: """Embed search docs.""" diff --git a/libs/ibm/langchain_ibm/llms.py b/libs/ibm/langchain_ibm/llms.py index c2165af..b4e07a9 100644 --- a/libs/ibm/langchain_ibm/llms.py +++ b/libs/ibm/langchain_ibm/llms.py @@ -11,13 +11,10 @@ from langchain_core.utils import convert_to_secret_str, get_from_dict_or_env from pydantic import ( ConfigDict, - Extra, Field, SecretStr, model_validator, - root_validator, ) -from typing_extensions import Self logger = logging.getLogger(__name__) textgen_valid_params = [ @@ -138,47 +135,50 @@ def lc_secrets(self) -> Dict[str, str]: "instance_id": "WATSONX_INSTANCE_ID", } - @model_validator(mode="after") - def validate_environment(self) -> Self: + @model_validator(mode="before") + @classmethod + def validate_environment(cls, values: Dict) -> Any: """Validate that credentials and python package exists in environment.""" - if isinstance(self.watsonx_model, (ModelInference, Model)): - self.model_id = getattr(self.watsonx_model, "model_id") - self.deployment_id = getattr(self.watsonx_model, "deployment_id", "") - self.project_id = getattr( - getattr(self.watsonx_model, "_client"), + if isinstance(values.get("watsonx_model"), (ModelInference, Model)): + values["model_id"] = getattr(values["watsonx_model"], "model_id") + values["deployment_id"] = getattr( + values["watsonx_model"], "deployment_id", "" + ) + values["project_id"] = getattr( + getattr(values["watsonx_model"], "_client"), "default_project_id", ) - self.space_id = getattr( - getattr(self.watsonx_model, "_client"), "default_space_id" + values["space_id"] = getattr( + getattr(values["watsonx_model"], "_client"), "default_space_id" ) - self.params = getattr(self.watsonx_model, "params") + values["params"] = getattr(values["watsonx_model"], "params") - elif isinstance(self.watsonx_client, APIClient): + elif isinstance(values.get("watsonx_client"), APIClient): watsonx_model = ModelInference( - model_id=self.model_id, - params=self.params, - api_client=self.watsonx_client, - project_id=self.project_id, - space_id=self.space_id, - verify=self.verify, + model_id=values["model_id"], + params=values["params"], + api_client=values["watsonx_client"], + project_id=values["project_id"], + space_id=values["space_id"], + verify=values["verify"], ) - self.watsonx_model = watsonx_model + values["watsonx_model"] = watsonx_model else: - self.url = convert_to_secret_str( + values["url"] = convert_to_secret_str( get_from_dict_or_env(values, "url", "WATSONX_URL") ) - if "cloud.ibm.com" in self.url.get_secret_value(): - self.apikey = convert_to_secret_str( + if "cloud.ibm.com" in values.get("url", "").get_secret_value(): + values["apikey"] = convert_to_secret_str( get_from_dict_or_env(values, "apikey", "WATSONX_APIKEY") ) else: if ( - not self.token + not values["token"] and "WATSONX_TOKEN" not in os.environ - and not self.password + and not values["password"] and "WATSONX_PASSWORD" not in os.environ - and not self.apikey + and not values["apikey"] and "WATSONX_APIKEY" not in os.environ ): raise ValueError( @@ -189,54 +189,62 @@ def validate_environment(self) -> Self: " or pass 'token', 'password' or 'apikey'" " as a named parameter." ) - elif self.token or "WATSONX_TOKEN" in os.environ: - self.token = convert_to_secret_str( + elif values["token"] or "WATSONX_TOKEN" in os.environ: + values["token"] = convert_to_secret_str( get_from_dict_or_env(values, "token", "WATSONX_TOKEN") ) - elif self.password or "WATSONX_PASSWORD" in os.environ: - self.password = convert_to_secret_str( + elif values["password"] or "WATSONX_PASSWORD" in os.environ: + values["password"] = convert_to_secret_str( get_from_dict_or_env(values, "password", "WATSONX_PASSWORD") ) - self.username = convert_to_secret_str( + values["username"] = convert_to_secret_str( get_from_dict_or_env(values, "username", "WATSONX_USERNAME") ) - elif self.apikey or "WATSONX_APIKEY" in os.environ: - self.apikey = convert_to_secret_str( + elif values["apikey"] or "WATSONX_APIKEY" in os.environ: + values["apikey"] = convert_to_secret_str( get_from_dict_or_env(values, "apikey", "WATSONX_APIKEY") ) - self.username = convert_to_secret_str( + values["username"] = convert_to_secret_str( get_from_dict_or_env(values, "username", "WATSONX_USERNAME") ) - if not self.instance_id or "WATSONX_INSTANCE_ID" not in os.environ: - self.instance_id = convert_to_secret_str( + if not values["instance_id"] or "WATSONX_INSTANCE_ID" not in os.environ: + values["instance_id"] = convert_to_secret_str( get_from_dict_or_env( values, "instance_id", "WATSONX_INSTANCE_ID" ) ) credentials = Credentials( - url=self.url.get_secret_value() if self.url else None, - api_key=self.apikey.get_secret_value() if self.apikey else None, - token=self.token.get_secret_value() if self.token else None, - password=self.password.get_secret_value() if self.password else None, - username=self.username.get_secret_value() if self.username else None, - instance_id=self.instance_id.get_secret_value() - if self.instance_id + url=values["url"].get_secret_value() if values["url"] else None, + api_key=values["apikey"].get_secret_value() + if values["apikey"] + else None, + token=values["token"].get_secret_value() if values["token"] else None, + password=values["password"].get_secret_value() + if values["password"] + else None, + username=values["username"].get_secret_value() + if values["username"] + else None, + instance_id=values["instance_id"].get_secret_value() + if values["instance_id"] + else None, + version=values["version"].get_secret_value() + if values["version"] else None, - version=self.version.get_secret_value() if self.version else None, - verify=self.verify, + verify=values["verify"], ) watsonx_model = ModelInference( - model_id=self.model_id, - deployment_id=self.deployment_id, + model_id=values["model_id"], + deployment_id=values["deployment_id"], credentials=credentials, - params=self.params, - project_id=self.project_id, - space_id=self.space_id, + params=values["params"], + project_id=values["project_id"], + space_id=values["space_id"], ) - self.watsonx_model = watsonx_model + values["watsonx_model"] = watsonx_model - return self + return values @property def _identifying_params(self) -> Mapping[str, Any]: From cfbbf9e60955a2d9567793e1b09220e59bbcdea1 Mon Sep 17 00:00:00 2001 From: Chester Curme Date: Mon, 16 Sep 2024 15:45:09 -0400 Subject: [PATCH 11/13] get item --> .get() --- libs/ibm/langchain_ibm/chat_models.py | 46 ++++++++++++--------- libs/ibm/langchain_ibm/embeddings.py | 43 +++++++++++--------- libs/ibm/langchain_ibm/llms.py | 57 +++++++++++++++------------ 3 files changed, 82 insertions(+), 64 deletions(-) diff --git a/libs/ibm/langchain_ibm/chat_models.py b/libs/ibm/langchain_ibm/chat_models.py index 97b53b0..fe3b39b 100644 --- a/libs/ibm/langchain_ibm/chat_models.py +++ b/libs/ibm/langchain_ibm/chat_models.py @@ -438,11 +438,11 @@ def validate_environment(cls, values: Dict) -> Any: ) else: if ( - not values["token"] + not values.get("token") and "WATSONX_TOKEN" not in os.environ - and not values["password"] + and not values.get("password") and "WATSONX_PASSWORD" not in os.environ - and not values["apikey"] + and not values.get("apikey") and "WATSONX_APIKEY" not in os.environ ): raise ValueError( @@ -453,54 +453,62 @@ def validate_environment(cls, values: Dict) -> Any: " or pass 'token', 'password' or 'apikey'" " as a named parameter." ) - elif values["token"] or "WATSONX_TOKEN" in os.environ: + elif values.get("token") or "WATSONX_TOKEN" in os.environ: values["token"] = convert_to_secret_str( get_from_dict_or_env(values, "token", "WATSONX_TOKEN") ) - elif values["password"] or "WATSONX_PASSWORD" in os.environ: + elif values.get("password") or "WATSONX_PASSWORD" in os.environ: values["password"] = convert_to_secret_str( get_from_dict_or_env(values, "password", "WATSONX_PASSWORD") ) values["username"] = convert_to_secret_str( get_from_dict_or_env(values, "username", "WATSONX_USERNAME") ) - elif values["apikey"] or "WATSONX_APIKEY" in os.environ: + elif values.get("apikey") or "WATSONX_APIKEY" in os.environ: values["apikey"] = convert_to_secret_str( get_from_dict_or_env(values, "apikey", "WATSONX_APIKEY") ) values["username"] = convert_to_secret_str( get_from_dict_or_env(values, "username", "WATSONX_USERNAME") ) - if not values["instance_id"] or "WATSONX_INSTANCE_ID" not in os.environ: + if not values.get("instance_id") or "WATSONX_INSTANCE_ID" not in os.environ: values["instance_id"] = convert_to_secret_str( get_from_dict_or_env(values, "instance_id", "WATSONX_INSTANCE_ID") ) credentials = Credentials( - url=values["url"].get_secret_value() if values["url"] else None, - api_key=values["apikey"].get_secret_value() if values["apikey"] else None, - token=values["token"].get_secret_value() if values["token"] else None, + url=values["url"].get_secret_value() if values.get("url") else None, + api_key=values["apikey"].get_secret_value() + if values.get("apikey") + else None, + token=values["token"].get_secret_value() if values.get("token") else None, password=( - values["password"].get_secret_value() if values["password"] else None + values["password"].get_secret_value() + if values.get("password") + else None ), username=( - values["username"].get_secret_value() if values["username"] else None + values["username"].get_secret_value() + if values.get("username") + else None ), instance_id=( values["instance_id"].get_secret_value() - if values["instance_id"] + if values.get("instance_id") else None ), - version=values["version"].get_secret_value() if values["version"] else None, + version=values["version"].get_secret_value() + if values.get("version") + else None, verify=values["verify"], ) watsonx_chat = ModelInference( - model_id=values["model_id"], - deployment_id=values["deployment_id"], + model_id=values.get("model_id"), + deployment_id=values.get("deployment_id"), credentials=credentials, - params=values["params"], - project_id=values["project_id"], - space_id=values["space_id"], + params=values.get("params"), + project_id=values.get("project_id"), + space_id=values.get("space_id"), ) values["watsonx_model"] = watsonx_chat diff --git a/libs/ibm/langchain_ibm/embeddings.py b/libs/ibm/langchain_ibm/embeddings.py index 5492980..9403ff7 100644 --- a/libs/ibm/langchain_ibm/embeddings.py +++ b/libs/ibm/langchain_ibm/embeddings.py @@ -91,11 +91,11 @@ def validate_environment(cls, values: Dict) -> Any: ) else: if ( - not values["token"] + not values.get("token") and "WATSONX_TOKEN" not in os.environ - and not values["password"] + and not values.get("password") and "WATSONX_PASSWORD" not in os.environ - and not values["apikey"] + and not values.get("apikey") and "WATSONX_APIKEY" not in os.environ ): raise ValueError( @@ -106,25 +106,28 @@ def validate_environment(cls, values: Dict) -> Any: " or pass 'token', 'password' or 'apikey'" " as a named parameter." ) - elif values["token"] or "WATSONX_TOKEN" in os.environ: + elif values.get("token") or "WATSONX_TOKEN" in os.environ: values["token"] = convert_to_secret_str( get_from_dict_or_env(values, "token", "WATSONX_TOKEN") ) - elif values["password"] or "WATSONX_PASSWORD" in os.environ: + elif values.get("password") or "WATSONX_PASSWORD" in os.environ: values["password"] = convert_to_secret_str( get_from_dict_or_env(values, "password", "WATSONX_PASSWORD") ) values["username"] = convert_to_secret_str( get_from_dict_or_env(values, "username", "WATSONX_USERNAME") ) - elif values["apikey"] or "WATSONX_APIKEY" in os.environ: + elif values.get("apikey") or "WATSONX_APIKEY" in os.environ: values["apikey"] = convert_to_secret_str( get_from_dict_or_env(values, "apikey", "WATSONX_APIKEY") ) values["username"] = convert_to_secret_str( get_from_dict_or_env(values, "username", "WATSONX_USERNAME") ) - if not values["instance_id"] or "WATSONX_INSTANCE_ID" not in os.environ: + if ( + not values.get("instance_id") + or "WATSONX_INSTANCE_ID" not in os.environ + ): values["instance_id"] = convert_to_secret_str( get_from_dict_or_env( values, "instance_id", "WATSONX_INSTANCE_ID" @@ -132,32 +135,34 @@ def validate_environment(cls, values: Dict) -> Any: ) credentials = Credentials( - url=values["url"].get_secret_value() if values["url"] else None, + url=values["url"].get_secret_value() if values.get("url") else None, api_key=values["apikey"].get_secret_value() - if values["apikey"] + if values.get("apikey") + else None, + token=values["token"].get_secret_value() + if values.get("token") else None, - token=values["token"].get_secret_value() if values["token"] else None, password=values["password"].get_secret_value() - if values["password"] + if values.get("password") else None, username=values["username"].get_secret_value() - if values["username"] + if values.get("username") else None, instance_id=values["instance_id"].get_secret_value() - if values["instance_id"] + if values.get("instance_id") else None, version=values["version"].get_secret_value() - if values["version"] + if values.get("version") else None, - verify=values["verify"], + verify=values.get("verify"), ) watsonx_embed = Embeddings( - model_id=values["model_id"], - params=values["params"], + model_id=values.get("model_id"), + params=values.get("params"), credentials=credentials, - project_id=values["project_id"], - space_id=values["space_id"], + project_id=values.get("project_id"), + space_id=values.get("space_id"), ) values["watsonx_embed"] = watsonx_embed diff --git a/libs/ibm/langchain_ibm/llms.py b/libs/ibm/langchain_ibm/llms.py index b4e07a9..b750d82 100644 --- a/libs/ibm/langchain_ibm/llms.py +++ b/libs/ibm/langchain_ibm/llms.py @@ -155,12 +155,12 @@ def validate_environment(cls, values: Dict) -> Any: elif isinstance(values.get("watsonx_client"), APIClient): watsonx_model = ModelInference( - model_id=values["model_id"], - params=values["params"], - api_client=values["watsonx_client"], - project_id=values["project_id"], - space_id=values["space_id"], - verify=values["verify"], + model_id=values.get("model_id"), + params=values.get("params"), + api_client=values.get("watsonx_client"), + project_id=values.get("project_id"), + space_id=values.get("space_id"), + verify=values.get("verify"), ) values["watsonx_model"] = watsonx_model @@ -174,11 +174,11 @@ def validate_environment(cls, values: Dict) -> Any: ) else: if ( - not values["token"] + not values.get("token") and "WATSONX_TOKEN" not in os.environ - and not values["password"] + and not values.get("password") and "WATSONX_PASSWORD" not in os.environ - and not values["apikey"] + and not values.get("apikey") and "WATSONX_APIKEY" not in os.environ ): raise ValueError( @@ -189,58 +189,63 @@ def validate_environment(cls, values: Dict) -> Any: " or pass 'token', 'password' or 'apikey'" " as a named parameter." ) - elif values["token"] or "WATSONX_TOKEN" in os.environ: + elif values.get("token") or "WATSONX_TOKEN" in os.environ: values["token"] = convert_to_secret_str( get_from_dict_or_env(values, "token", "WATSONX_TOKEN") ) - elif values["password"] or "WATSONX_PASSWORD" in os.environ: + elif values.get("password") or "WATSONX_PASSWORD" in os.environ: values["password"] = convert_to_secret_str( get_from_dict_or_env(values, "password", "WATSONX_PASSWORD") ) values["username"] = convert_to_secret_str( get_from_dict_or_env(values, "username", "WATSONX_USERNAME") ) - elif values["apikey"] or "WATSONX_APIKEY" in os.environ: + elif values.get("apikey") or "WATSONX_APIKEY" in os.environ: values["apikey"] = convert_to_secret_str( get_from_dict_or_env(values, "apikey", "WATSONX_APIKEY") ) values["username"] = convert_to_secret_str( get_from_dict_or_env(values, "username", "WATSONX_USERNAME") ) - if not values["instance_id"] or "WATSONX_INSTANCE_ID" not in os.environ: + if ( + not values.get("instance_id") + or "WATSONX_INSTANCE_ID" not in os.environ + ): values["instance_id"] = convert_to_secret_str( get_from_dict_or_env( values, "instance_id", "WATSONX_INSTANCE_ID" ) ) credentials = Credentials( - url=values["url"].get_secret_value() if values["url"] else None, + url=values["url"].get_secret_value() if values.get("url") else None, api_key=values["apikey"].get_secret_value() - if values["apikey"] + if values.get("apikey") + else None, + token=values["token"].get_secret_value() + if values.get("token") else None, - token=values["token"].get_secret_value() if values["token"] else None, password=values["password"].get_secret_value() - if values["password"] + if values.get("password") else None, username=values["username"].get_secret_value() - if values["username"] + if values.get("username") else None, instance_id=values["instance_id"].get_secret_value() - if values["instance_id"] + if values.get("instance_id") else None, version=values["version"].get_secret_value() - if values["version"] + if values.get("version") else None, - verify=values["verify"], + verify=values.get("verify"), ) watsonx_model = ModelInference( - model_id=values["model_id"], - deployment_id=values["deployment_id"], + model_id=values.get("model_id"), + deployment_id=values.get("deployment_id"), credentials=credentials, - params=values["params"], - project_id=values["project_id"], - space_id=values["space_id"], + params=values.get("params"), + project_id=values.get("project_id"), + space_id=values.get("space_id"), ) values["watsonx_model"] = watsonx_model From 0752bd310cca99e7fc65798bd00fb5e9909fc6ba Mon Sep 17 00:00:00 2001 From: Chester Curme Date: Mon, 16 Sep 2024 15:47:13 -0400 Subject: [PATCH 12/13] set protected namespaces on embeddings --- libs/ibm/langchain_ibm/embeddings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/ibm/langchain_ibm/embeddings.py b/libs/ibm/langchain_ibm/embeddings.py index 9403ff7..989cc6c 100644 --- a/libs/ibm/langchain_ibm/embeddings.py +++ b/libs/ibm/langchain_ibm/embeddings.py @@ -64,6 +64,7 @@ class WatsonxEmbeddings(BaseModel, LangChainEmbeddings): model_config = ConfigDict( extra="forbid", arbitrary_types_allowed=True, + protected_namespaces=(), ) @model_validator(mode="before") From eaa1e47e542124ee483b5272fe548a25f5033012 Mon Sep 17 00:00:00 2001 From: Chester Curme Date: Mon, 16 Sep 2024 16:44:27 -0400 Subject: [PATCH 13/13] fix --- libs/ibm/langchain_ibm/chat_models.py | 10 +++++----- libs/ibm/langchain_ibm/embeddings.py | 18 +++++++++--------- libs/ibm/langchain_ibm/llms.py | 14 +++++++------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/libs/ibm/langchain_ibm/chat_models.py b/libs/ibm/langchain_ibm/chat_models.py index fe3b39b..e5efc2a 100644 --- a/libs/ibm/langchain_ibm/chat_models.py +++ b/libs/ibm/langchain_ibm/chat_models.py @@ -499,16 +499,16 @@ def validate_environment(cls, values: Dict) -> Any: version=values["version"].get_secret_value() if values.get("version") else None, - verify=values["verify"], + verify=values.get("verify"), ) watsonx_chat = ModelInference( - model_id=values.get("model_id"), - deployment_id=values.get("deployment_id"), + model_id=values.get("model_id", ""), + deployment_id=values.get("deployment_id", ""), credentials=credentials, params=values.get("params"), - project_id=values.get("project_id"), - space_id=values.get("space_id"), + project_id=values.get("project_id", ""), + space_id=values.get("space_id", ""), ) values["watsonx_model"] = watsonx_chat diff --git a/libs/ibm/langchain_ibm/embeddings.py b/libs/ibm/langchain_ibm/embeddings.py index 989cc6c..078bdc6 100644 --- a/libs/ibm/langchain_ibm/embeddings.py +++ b/libs/ibm/langchain_ibm/embeddings.py @@ -73,12 +73,12 @@ def validate_environment(cls, values: Dict) -> Any: """Validate that credentials and python package exists in environment.""" if isinstance(values.get("watsonx_client"), APIClient): watsonx_embed = Embeddings( - model_id=values["model_id"], - params=values["params"], - api_client=values["watsonx_client"], - project_id=values["project_id"], - space_id=values["space_id"], - verify=values["verify"], + model_id=values.get("model_id", ""), + params=values.get("params"), + api_client=values.get("watsonx_client"), + project_id=values.get("project_id", ""), + space_id=values.get("space_id", ""), + verify=values.get("verify"), ) values["watsonx_embed"] = watsonx_embed @@ -159,11 +159,11 @@ def validate_environment(cls, values: Dict) -> Any: ) watsonx_embed = Embeddings( - model_id=values.get("model_id"), + model_id=values.get("model_id", ""), params=values.get("params"), credentials=credentials, - project_id=values.get("project_id"), - space_id=values.get("space_id"), + project_id=values.get("project_id", ""), + space_id=values.get("space_id", ""), ) values["watsonx_embed"] = watsonx_embed diff --git a/libs/ibm/langchain_ibm/llms.py b/libs/ibm/langchain_ibm/llms.py index b750d82..51779f2 100644 --- a/libs/ibm/langchain_ibm/llms.py +++ b/libs/ibm/langchain_ibm/llms.py @@ -155,11 +155,11 @@ def validate_environment(cls, values: Dict) -> Any: elif isinstance(values.get("watsonx_client"), APIClient): watsonx_model = ModelInference( - model_id=values.get("model_id"), + model_id=values.get("model_id", ""), params=values.get("params"), api_client=values.get("watsonx_client"), - project_id=values.get("project_id"), - space_id=values.get("space_id"), + project_id=values.get("project_id", ""), + space_id=values.get("space_id", ""), verify=values.get("verify"), ) values["watsonx_model"] = watsonx_model @@ -240,12 +240,12 @@ def validate_environment(cls, values: Dict) -> Any: ) watsonx_model = ModelInference( - model_id=values.get("model_id"), - deployment_id=values.get("deployment_id"), + model_id=values.get("model_id", ""), + deployment_id=values.get("deployment_id", ""), credentials=credentials, params=values.get("params"), - project_id=values.get("project_id"), - space_id=values.get("space_id"), + project_id=values.get("project_id", ""), + space_id=values.get("space_id", ""), ) values["watsonx_model"] = watsonx_model