From 615f8b0d47f2476d011b143d6da93549bfcea0b1 Mon Sep 17 00:00:00 2001 From: Bagatur Date: Tue, 3 Sep 2024 16:33:35 -0700 Subject: [PATCH 01/18] openai[major]: switch to pydantic v2 --- .../langchain_openai/chat_models/azure.py | 70 ++++++------ .../langchain_openai/chat_models/base.py | 108 +++++++++--------- .../langchain_openai/embeddings/azure.py | 58 +++++----- .../langchain_openai/embeddings/base.py | 73 ++++++------ .../openai/langchain_openai/llms/azure.py | 68 +++++------ .../openai/langchain_openai/llms/base.py | 56 ++++----- .../chat_models/test_base.py | 2 +- .../tests/unit_tests/chat_models/test_base.py | 2 +- .../openai/tests/unit_tests/fake/callbacks.py | 2 +- .../openai/tests/unit_tests/test_load.py | 8 +- .../openai/tests/unit_tests/test_secrets.py | 2 +- .../unit_tests/chat_models.py | 2 +- .../unit_tests/embeddings.py | 2 +- 13 files changed, 228 insertions(+), 225 deletions(-) diff --git a/libs/partners/openai/langchain_openai/chat_models/azure.py b/libs/partners/openai/langchain_openai/chat_models/azure.py index 23b9dd3d2e95a..e5ae0550fd7ff 100644 --- a/libs/partners/openai/langchain_openai/chat_models/azure.py +++ b/libs/partners/openai/langchain_openai/chat_models/azure.py @@ -31,7 +31,7 @@ PydanticToolsParser, ) from langchain_core.outputs import ChatResult -from langchain_core.pydantic_v1 import BaseModel, Field, SecretStr, root_validator +from pydantic import BaseModel, Field, SecretStr, model_validator from langchain_core.runnables import Runnable, RunnableMap, RunnablePassthrough from langchain_core.tools import BaseTool from langchain_core.utils import from_env, secret_from_env @@ -39,6 +39,8 @@ from langchain_core.utils.pydantic import is_basemodel_subclass from langchain_openai.chat_models.base import BaseChatOpenAI +from typing_extensions import Self + logger = logging.getLogger(__name__) @@ -494,7 +496,7 @@ class Joke(BaseModel): default_factory=from_env("OPENAI_API_VERSION", default=None), ) """Automatically inferred from env var `OPENAI_API_VERSION` if not provided.""" - # Check OPENAI_KEY for backwards compatibility. + # Check OPENAI_API_KEY for backwards compatibility. # TODO: Remove OPENAI_API_KEY support to avoid possible conflict when using # other forms of azure credentials. openai_api_key: Optional[SecretStr] = Field( @@ -565,31 +567,31 @@ def lc_secrets(self) -> Dict[str, str]: def is_lc_serializable(cls) -> bool: return 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 api key and python package exists in environment.""" - if values["n"] < 1: + if self.n < 1: raise ValueError("n must be at least 1.") - if values["n"] > 1 and values["streaming"]: + if self.n > 1 and self.streaming: raise ValueError("n must be 1 when streaming.") # Check OPENAI_ORGANIZATION for backwards compatibility. - values["openai_organization"] = ( - values["openai_organization"] + self.openai_organization = ( + self.openai_organization or os.getenv("OPENAI_ORG_ID") or os.getenv("OPENAI_ORGANIZATION") ) # For backwards compatibility. Before openai v1, no distinction was made # between azure_endpoint and base_url (openai_api_base). - openai_api_base = values["openai_api_base"] - if openai_api_base and values["validate_base_url"]: + openai_api_base = self.openai_api_base + if openai_api_base and self.validate_base_url: if "/openai" not in openai_api_base: raise ValueError( "As of openai>=1.0.0, Azure endpoints should be specified via " "the `azure_endpoint` param not `openai_api_base` " "(or alias `base_url`)." ) - if values["deployment_name"]: + if self.deployment_name: raise ValueError( "As of openai>=1.0.0, if `azure_deployment` (or alias " "`deployment_name`) is specified then " @@ -603,38 +605,38 @@ def validate_environment(cls, values: Dict) -> Dict: 'base_url="https://xxx.openai.azure.com/openai/deployments/my-deployment"' ) client_params = { - "api_version": values["openai_api_version"], - "azure_endpoint": values["azure_endpoint"], - "azure_deployment": values["deployment_name"], + "api_version": self.openai_api_version, + "azure_endpoint": self.azure_endpoint, + "azure_deployment": self.deployment_name, "api_key": ( - values["openai_api_key"].get_secret_value() - if values["openai_api_key"] + self.openai_api_key.get_secret_value() + if self.openai_api_key else None ), "azure_ad_token": ( - values["azure_ad_token"].get_secret_value() - if values["azure_ad_token"] + self.azure_ad_token.get_secret_value() + if self.azure_ad_token else None ), - "azure_ad_token_provider": values["azure_ad_token_provider"], - "organization": values["openai_organization"], - "base_url": values["openai_api_base"], - "timeout": values["request_timeout"], - "max_retries": values["max_retries"], - "default_headers": values["default_headers"], - "default_query": values["default_query"], + "azure_ad_token_provider": self.azure_ad_token_provider, + "organization": self.openai_organization, + "base_url": self.openai_api_base, + "timeout": self.request_timeout, + "max_retries": self.max_retries, + "default_headers": self.default_headers, + "default_query": self.default_query, } - if not values.get("client"): - sync_specific = {"http_client": values["http_client"]} - values["root_client"] = openai.AzureOpenAI(**client_params, **sync_specific) - values["client"] = values["root_client"].chat.completions - if not values.get("async_client"): - async_specific = {"http_client": values["http_async_client"]} - values["root_async_client"] = openai.AsyncAzureOpenAI( + if not (self.client or None): + sync_specific = {"http_client": self.http_client} + self.root_client = openai.AzureOpenAI(**client_params, **sync_specific) + self.client = self.root_client.chat.completions + if not (self.async_client or None): + async_specific = {"http_client": self.http_async_client} + self.root_async_client = openai.AsyncAzureOpenAI( **client_params, **async_specific ) - values["async_client"] = values["root_async_client"].chat.completions - return values + self.async_client = self.root_async_client.chat.completions + return self def bind_tools( self, diff --git a/libs/partners/openai/langchain_openai/chat_models/base.py b/libs/partners/openai/langchain_openai/chat_models/base.py index 66b7e75edecf6..018d8febefbb3 100644 --- a/libs/partners/openai/langchain_openai/chat_models/base.py +++ b/libs/partners/openai/langchain_openai/chat_models/base.py @@ -73,15 +73,11 @@ parse_tool_call, ) from langchain_core.outputs import ChatGeneration, ChatGenerationChunk, ChatResult -from langchain_core.pydantic_v1 import BaseModel, Field, SecretStr, root_validator +from pydantic import BaseModel, Field, model_validator, SecretStr from langchain_core.runnables import Runnable, RunnableMap, RunnablePassthrough, chain from langchain_core.runnables.config import run_in_executor from langchain_core.tools import BaseTool -from langchain_core.utils import ( - convert_to_secret_str, - get_from_dict_or_env, - get_pydantic_field_names, -) +from langchain_core.utils import get_from_dict_or_env, get_pydantic_field_names from langchain_core.utils.function_calling import ( convert_to_openai_function, convert_to_openai_tool, @@ -91,7 +87,10 @@ TypeBaseModel, is_basemodel_subclass, ) -from langchain_core.utils.utils import build_extra_kwargs +from langchain_core.utils.utils import build_extra_kwargs, from_env, secret_from_env +from pydantic import ConfigDict +from typing_extensions import Self + logger = logging.getLogger(__name__) @@ -361,15 +360,19 @@ class BaseChatOpenAI(BaseChatModel): """What sampling temperature to use.""" model_kwargs: Dict[str, Any] = Field(default_factory=dict) """Holds any model parameters valid for `create` call not explicitly specified.""" - openai_api_key: Optional[SecretStr] = Field(default=None, alias="api_key") - """Automatically inferred from env var `OPENAI_API_KEY` if not provided.""" + openai_api_key: Optional[SecretStr] = Field( + alias="api_key", + default_factory=secret_from_env("OPENAI_API_KEY", default=None), + ) openai_api_base: Optional[str] = Field(default=None, alias="base_url") """Base URL path for API requests, leave blank if not using a proxy or service emulator.""" openai_organization: Optional[str] = Field(default=None, alias="organization") """Automatically inferred from env var `OPENAI_ORG_ID` if not provided.""" # to support explicit proxy for OpenAI - openai_proxy: Optional[str] = None + openai_proxy: Optional[str] = Field( + default_factory=from_env("OPENAI_PROXY", default=None) + ) request_timeout: Union[float, Tuple[float, float], Any, None] = Field( default=None, alias="timeout" ) @@ -428,13 +431,11 @@ class BaseChatOpenAI(BaseChatModel): include_response_headers: bool = False """Whether to include response headers in the output message response_metadata.""" - class Config: - """Configuration for this pydantic object.""" - - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True,) - @root_validator(pre=True) - def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]: + @model_validator(mode="before") + @classmethod + def build_extra(cls, values: Dict[str, Any]) -> Any: """Build extra kwargs from additional params that were passed in.""" all_required_field_names = get_pydantic_field_names(cls) extra = values.get("model_kwargs", {}) @@ -443,56 +444,49 @@ def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]: ) return values - @root_validator(pre=False, skip_on_failure=True, allow_reuse=True) - def validate_environment(cls, values: Dict) -> Dict: + @model_validator(mode="after") + def validate_environment(self) -> Self: """Validate that api key and python package exists in environment.""" - if values["n"] < 1: + if self.n < 1: raise ValueError("n must be at least 1.") - if values["n"] > 1 and values["streaming"]: + if self.n > 1 and self.streaming: raise ValueError("n must be 1 when streaming.") - values["openai_api_key"] = convert_to_secret_str( - get_from_dict_or_env(values, "openai_api_key", "OPENAI_API_KEY") - ) # Check OPENAI_ORGANIZATION for backwards compatibility. - values["openai_organization"] = ( - values["openai_organization"] + self.openai_organization = ( + self.openai_organization or os.getenv("OPENAI_ORG_ID") or os.getenv("OPENAI_ORGANIZATION") ) - values["openai_api_base"] = values["openai_api_base"] or os.getenv( + self.openai_api_base = self.openai_api_base or os.getenv( "OPENAI_API_BASE" ) - values["openai_proxy"] = get_from_dict_or_env( - values, "openai_proxy", "OPENAI_PROXY", default="" - ) - client_params = { "api_key": ( - values["openai_api_key"].get_secret_value() - if values["openai_api_key"] + self.openai_api_key.get_secret_value() + if self.openai_api_key else None ), - "organization": values["openai_organization"], - "base_url": values["openai_api_base"], - "timeout": values["request_timeout"], - "max_retries": values["max_retries"], - "default_headers": values["default_headers"], - "default_query": values["default_query"], + "organization": self.openai_organization, + "base_url": self.openai_api_base, + "timeout": self.request_timeout, + "max_retries": self.max_retries, + "default_headers": self.default_headers, + "default_query": self.default_query, } - if values["openai_proxy"] and ( - values["http_client"] or values["http_async_client"] + if self.openai_proxy and ( + self.http_client or self.http_async_client ): - openai_proxy = values["openai_proxy"] - http_client = values["http_client"] - http_async_client = values["http_async_client"] + openai_proxy = self.openai_proxy + http_client = self.http_client + http_async_client = self.http_async_client raise ValueError( "Cannot specify 'openai_proxy' if one of " "'http_client'/'http_async_client' is already specified. Received:\n" f"{openai_proxy=}\n{http_client=}\n{http_async_client=}" ) - if not values.get("client"): - if values["openai_proxy"] and not values["http_client"]: + if not (self.client or None): + if self.openai_proxy and not self.http_client: try: import httpx except ImportError as e: @@ -500,12 +494,12 @@ def validate_environment(cls, values: Dict) -> Dict: "Could not import httpx python package. " "Please install it with `pip install httpx`." ) from e - values["http_client"] = httpx.Client(proxy=values["openai_proxy"]) - sync_specific = {"http_client": values["http_client"]} - values["root_client"] = openai.OpenAI(**client_params, **sync_specific) - values["client"] = values["root_client"].chat.completions - if not values.get("async_client"): - if values["openai_proxy"] and not values["http_async_client"]: + self.http_client = httpx.Client(proxy=self.openai_proxy) + sync_specific = {"http_client": self.http_client} + self.root_client = openai.OpenAI(**client_params, **sync_specific) + self.client = self.root_client.chat.completions + if not (self.async_client or None): + if self.openai_proxy and not self.http_async_client: try: import httpx except ImportError as e: @@ -513,15 +507,15 @@ def validate_environment(cls, values: Dict) -> Dict: "Could not import httpx python package. " "Please install it with `pip install httpx`." ) from e - values["http_async_client"] = httpx.AsyncClient( - proxy=values["openai_proxy"] + self.http_async_client = httpx.AsyncClient( + proxy=self.openai_proxy ) - async_specific = {"http_client": values["http_async_client"]} - values["root_async_client"] = openai.AsyncOpenAI( + async_specific = {"http_client": self.http_async_client} + self.root_async_client = openai.AsyncOpenAI( **client_params, **async_specific ) - values["async_client"] = values["root_async_client"].chat.completions - return values + self.async_client = self.root_async_client.chat.completions + return self @property def _default_params(self) -> Dict[str, Any]: diff --git a/libs/partners/openai/langchain_openai/embeddings/azure.py b/libs/partners/openai/langchain_openai/embeddings/azure.py index 3725a7662858f..6697cee53926e 100644 --- a/libs/partners/openai/langchain_openai/embeddings/azure.py +++ b/libs/partners/openai/langchain_openai/embeddings/azure.py @@ -5,10 +5,12 @@ from typing import Callable, Dict, Optional, Union import openai -from langchain_core.pydantic_v1 import Field, SecretStr, root_validator +from pydantic import Field, SecretStr, root_validator, model_validator from langchain_core.utils import from_env, secret_from_env from langchain_openai.embeddings.base import OpenAIEmbeddings +from typing_extensions import Self + class AzureOpenAIEmbeddings(OpenAIEmbeddings): @@ -153,21 +155,21 @@ class AzureOpenAIEmbeddings(OpenAIEmbeddings): chunk_size: int = 2048 """Maximum number of texts to embed in each batch""" - @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 api key and python package exists in environment.""" # For backwards compatibility. Before openai v1, no distinction was made # between azure_endpoint and base_url (openai_api_base). - openai_api_base = values["openai_api_base"] - if openai_api_base and values["validate_base_url"]: + openai_api_base = self.openai_api_base + if openai_api_base and self.validate_base_url: if "/openai" not in openai_api_base: - values["openai_api_base"] += "/openai" + self.openai_api_base += "/openai" raise ValueError( "As of openai>=1.0.0, Azure endpoints should be specified via " "the `azure_endpoint` param not `openai_api_base` " "(or alias `base_url`). " ) - if values["deployment"]: + if self.deployment: raise ValueError( "As of openai>=1.0.0, if `deployment` (or alias " "`azure_deployment`) is specified then " @@ -176,38 +178,38 @@ def validate_environment(cls, values: Dict) -> Dict: "and `azure_endpoint`." ) client_params = { - "api_version": values["openai_api_version"], - "azure_endpoint": values["azure_endpoint"], - "azure_deployment": values["deployment"], + "api_version": self.openai_api_version, + "azure_endpoint": self.azure_endpoint, + "azure_deployment": self.deployment, "api_key": ( - values["openai_api_key"].get_secret_value() - if values["openai_api_key"] + self.openai_api_key.get_secret_value() + if self.openai_api_key else None ), "azure_ad_token": ( - values["azure_ad_token"].get_secret_value() - if values["azure_ad_token"] + self.azure_ad_token.get_secret_value() + if self.azure_ad_token else None ), - "azure_ad_token_provider": values["azure_ad_token_provider"], - "organization": values["openai_organization"], - "base_url": values["openai_api_base"], - "timeout": values["request_timeout"], - "max_retries": values["max_retries"], - "default_headers": values["default_headers"], - "default_query": values["default_query"], + "azure_ad_token_provider": self.azure_ad_token_provider, + "organization": self.openai_organization, + "base_url": self.openai_api_base, + "timeout": self.request_timeout, + "max_retries": self.max_retries, + "default_headers": self.default_headers, + "default_query": self.default_query, } - if not values.get("client"): - sync_specific = {"http_client": values["http_client"]} - values["client"] = openai.AzureOpenAI( + if not (self.client or None): + sync_specific = {"http_client": self.http_client} + self.client = openai.AzureOpenAI( **client_params, **sync_specific ).embeddings - if not values.get("async_client"): - async_specific = {"http_client": values["http_async_client"]} - values["async_client"] = openai.AsyncAzureOpenAI( + if not (self.async_client or None): + async_specific = {"http_client": self.http_async_client} + self.async_client = openai.AsyncAzureOpenAI( **client_params, **async_specific ).embeddings - return values + return self @property def _llm_type(self) -> str: diff --git a/libs/partners/openai/langchain_openai/embeddings/base.py b/libs/partners/openai/langchain_openai/embeddings/base.py index 1a6a3a0417d7e..e6294d32ac2a2 100644 --- a/libs/partners/openai/langchain_openai/embeddings/base.py +++ b/libs/partners/openai/langchain_openai/embeddings/base.py @@ -20,8 +20,12 @@ import openai import tiktoken from langchain_core.embeddings import Embeddings -from langchain_core.pydantic_v1 import BaseModel, Field, SecretStr, root_validator +from pydantic import BaseModel, Field, SecretStr, root_validator, model_validator from langchain_core.utils import from_env, get_pydantic_field_names, secret_from_env +from pydantic import ConfigDict +from typing_extensions import Self + + logger = logging.getLogger(__name__) @@ -263,14 +267,11 @@ class OpenAIEmbeddings(BaseModel, Embeddings): """Whether to check the token length of inputs and automatically split inputs longer than embedding_ctx_length.""" - class Config: - """Configuration for this pydantic object.""" + model_config = ConfigDict(extra="forbid",populate_by_name=True,) - extra = "forbid" - allow_population_by_field_name = True - - @root_validator(pre=True) - def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]: + @model_validator(mode="before") + @classmethod + def build_extra(cls, values: Dict[str, Any]) -> Any: """Build extra kwargs from additional params that were passed in.""" all_required_field_names = get_pydantic_field_names(cls) extra = values.get("model_kwargs", {}) @@ -295,41 +296,41 @@ def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]: values["model_kwargs"] = extra return values - @root_validator(pre=False, skip_on_failure=True, allow_reuse=True) - def validate_environment(cls, values: Dict) -> Dict: + @model_validator(mode="after") + def validate_environment(self) -> Self: """Validate that api key and python package exists in environment.""" - if values["openai_api_type"] in ("azure", "azure_ad", "azuread"): + if self.openai_api_type in ("azure", "azure_ad", "azuread"): raise ValueError( "If you are using Azure, " "please use the `AzureOpenAIEmbeddings` class." ) client_params = { "api_key": ( - values["openai_api_key"].get_secret_value() - if values["openai_api_key"] + self.openai_api_key.get_secret_value() + if self.openai_api_key else None ), - "organization": values["openai_organization"], - "base_url": values["openai_api_base"], - "timeout": values["request_timeout"], - "max_retries": values["max_retries"], - "default_headers": values["default_headers"], - "default_query": values["default_query"], + "organization": self.openai_organization, + "base_url": self.openai_api_base, + "timeout": self.request_timeout, + "max_retries": self.max_retries, + "default_headers": self.default_headers, + "default_query": self.default_query, } - if values["openai_proxy"] and ( - values["http_client"] or values["http_async_client"] + if self.openai_proxy and ( + self.http_client or self.http_async_client ): - openai_proxy = values["openai_proxy"] - http_client = values["http_client"] - http_async_client = values["http_async_client"] + openai_proxy = self.openai_proxy + http_client = self.http_client + http_async_client = self.http_async_client raise ValueError( "Cannot specify 'openai_proxy' if one of " "'http_client'/'http_async_client' is already specified. Received:\n" f"{openai_proxy=}\n{http_client=}\n{http_async_client=}" ) - if not values.get("client"): - if values["openai_proxy"] and not values["http_client"]: + if not (self.client or None): + if self.openai_proxy and not self.http_client: try: import httpx except ImportError as e: @@ -337,13 +338,13 @@ def validate_environment(cls, values: Dict) -> Dict: "Could not import httpx python package. " "Please install it with `pip install httpx`." ) from e - values["http_client"] = httpx.Client(proxy=values["openai_proxy"]) - sync_specific = {"http_client": values["http_client"]} - values["client"] = openai.OpenAI( + self.http_client = httpx.Client(proxy=self.openai_proxy) + sync_specific = {"http_client": self.http_client} + self.client = openai.OpenAI( **client_params, **sync_specific ).embeddings - if not values.get("async_client"): - if values["openai_proxy"] and not values["http_async_client"]: + if not (self.async_client or None): + if self.openai_proxy and not self.http_async_client: try: import httpx except ImportError as e: @@ -351,14 +352,14 @@ def validate_environment(cls, values: Dict) -> Dict: "Could not import httpx python package. " "Please install it with `pip install httpx`." ) from e - values["http_async_client"] = httpx.AsyncClient( - proxy=values["openai_proxy"] + self.http_async_client = httpx.AsyncClient( + proxy=self.openai_proxy ) - async_specific = {"http_client": values["http_async_client"]} - values["async_client"] = openai.AsyncOpenAI( + async_specific = {"http_client": self.http_async_client} + self.async_client = openai.AsyncOpenAI( **client_params, **async_specific ).embeddings - return values + return self @property def _invocation_params(self) -> Dict[str, Any]: diff --git a/libs/partners/openai/langchain_openai/llms/azure.py b/libs/partners/openai/langchain_openai/llms/azure.py index 0d091b325f520..e48b1380ff79f 100644 --- a/libs/partners/openai/langchain_openai/llms/azure.py +++ b/libs/partners/openai/langchain_openai/llms/azure.py @@ -5,10 +5,12 @@ import openai from langchain_core.language_models import LangSmithParams -from langchain_core.pydantic_v1 import Field, SecretStr, root_validator +from pydantic import Field, SecretStr, root_validator, model_validator from langchain_core.utils import from_env, secret_from_env from langchain_openai.llms.base import BaseOpenAI +from typing_extensions import Self + logger = logging.getLogger(__name__) @@ -100,29 +102,29 @@ def is_lc_serializable(cls) -> bool: """Return whether this model can be serialized by Langchain.""" return True - @root_validator(pre=False, skip_on_failure=True, allow_reuse=True) - def validate_environment(cls, values: Dict) -> Dict: + @model_validator(mode="after") + def validate_environment(self) -> Self: """Validate that api key and python package exists in environment.""" - if values["n"] < 1: + if self.n < 1: raise ValueError("n must be at least 1.") - if values["streaming"] and values["n"] > 1: + if self.streaming and self.n > 1: raise ValueError("Cannot stream results when n > 1.") - if values["streaming"] and values["best_of"] > 1: + if self.streaming and self.best_of > 1: raise ValueError("Cannot stream results when best_of > 1.") # For backwards compatibility. Before openai v1, no distinction was made # between azure_endpoint and base_url (openai_api_base). - openai_api_base = values["openai_api_base"] - if openai_api_base and values["validate_base_url"]: + openai_api_base = self.openai_api_base + if openai_api_base and self.validate_base_url: if "/openai" not in openai_api_base: - values["openai_api_base"] = ( - values["openai_api_base"].rstrip("/") + "/openai" + self.openai_api_base = ( + self.openai_api_base.rstrip("/") + "/openai" ) raise ValueError( "As of openai>=1.0.0, Azure endpoints should be specified via " "the `azure_endpoint` param not `openai_api_base` " "(or alias `base_url`)." ) - if values["deployment_name"]: + if self.deployment_name: raise ValueError( "As of openai>=1.0.0, if `deployment_name` (or alias " "`azure_deployment`) is specified then " @@ -130,37 +132,37 @@ def validate_environment(cls, values: Dict) -> Dict: "Instead use `deployment_name` (or alias `azure_deployment`) " "and `azure_endpoint`." ) - values["deployment_name"] = None + self.deployment_name = None client_params = { - "api_version": values["openai_api_version"], - "azure_endpoint": values["azure_endpoint"], - "azure_deployment": values["deployment_name"], - "api_key": values["openai_api_key"].get_secret_value() - if values["openai_api_key"] + "api_version": self.openai_api_version, + "azure_endpoint": self.azure_endpoint, + "azure_deployment": self.deployment_name, + "api_key": self.openai_api_key.get_secret_value() + if self.openai_api_key else None, - "azure_ad_token": values["azure_ad_token"].get_secret_value() - if values["azure_ad_token"] + "azure_ad_token": self.azure_ad_token.get_secret_value() + if self.azure_ad_token else None, - "azure_ad_token_provider": values["azure_ad_token_provider"], - "organization": values["openai_organization"], - "base_url": values["openai_api_base"], - "timeout": values["request_timeout"], - "max_retries": values["max_retries"], - "default_headers": values["default_headers"], - "default_query": values["default_query"], + "azure_ad_token_provider": self.azure_ad_token_provider, + "organization": self.openai_organization, + "base_url": self.openai_api_base, + "timeout": self.request_timeout, + "max_retries": self.max_retries, + "default_headers": self.default_headers, + "default_query": self.default_query, } - if not values.get("client"): - sync_specific = {"http_client": values["http_client"]} - values["client"] = openai.AzureOpenAI( + if not (self.client or None): + sync_specific = {"http_client": self.http_client} + self.client = openai.AzureOpenAI( **client_params, **sync_specific ).completions - if not values.get("async_client"): - async_specific = {"http_client": values["http_async_client"]} - values["async_client"] = openai.AsyncAzureOpenAI( + if not (self.async_client or None): + async_specific = {"http_client": self.http_async_client} + self.async_client = openai.AsyncAzureOpenAI( **client_params, **async_specific ).completions - return values + return self @property def _identifying_params(self) -> Mapping[str, Any]: diff --git a/libs/partners/openai/langchain_openai/llms/base.py b/libs/partners/openai/langchain_openai/llms/base.py index 464b40e2ba919..0db987c5e0d5a 100644 --- a/libs/partners/openai/langchain_openai/llms/base.py +++ b/libs/partners/openai/langchain_openai/llms/base.py @@ -26,9 +26,13 @@ ) from langchain_core.language_models.llms import BaseLLM from langchain_core.outputs import Generation, GenerationChunk, LLMResult -from langchain_core.pydantic_v1 import Field, SecretStr, root_validator +from pydantic import Field, SecretStr, root_validator, model_validator from langchain_core.utils import get_pydantic_field_names from langchain_core.utils.utils import build_extra_kwargs, from_env, secret_from_env +from pydantic import ConfigDict +from typing_extensions import Self + + logger = logging.getLogger(__name__) @@ -152,13 +156,11 @@ class BaseOpenAI(BaseLLM): """Optional additional JSON properties to include in the request parameters when making requests to OpenAI compatible APIs, such as vLLM.""" - class Config: - """Configuration for this pydantic object.""" - - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True,) - @root_validator(pre=True) - def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]: + @model_validator(mode="before") + @classmethod + def build_extra(cls, values: Dict[str, Any]) -> Any: """Build extra kwargs from additional params that were passed in.""" all_required_field_names = get_pydantic_field_names(cls) extra = values.get("model_kwargs", {}) @@ -167,41 +169,41 @@ def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]: ) return values - @root_validator(pre=False, skip_on_failure=True, allow_reuse=True) - def validate_environment(cls, values: Dict) -> Dict: + @model_validator(mode="after") + def validate_environment(self) -> Self: """Validate that api key and python package exists in environment.""" - if values["n"] < 1: + if self.n < 1: raise ValueError("n must be at least 1.") - if values["streaming"] and values["n"] > 1: + if self.streaming and self.n > 1: raise ValueError("Cannot stream results when n > 1.") - if values["streaming"] and values["best_of"] > 1: + if self.streaming and self.best_of > 1: raise ValueError("Cannot stream results when best_of > 1.") client_params = { "api_key": ( - values["openai_api_key"].get_secret_value() - if values["openai_api_key"] + self.openai_api_key.get_secret_value() + if self.openai_api_key else None ), - "organization": values["openai_organization"], - "base_url": values["openai_api_base"], - "timeout": values["request_timeout"], - "max_retries": values["max_retries"], - "default_headers": values["default_headers"], - "default_query": values["default_query"], + "organization": self.openai_organization, + "base_url": self.openai_api_base, + "timeout": self.request_timeout, + "max_retries": self.max_retries, + "default_headers": self.default_headers, + "default_query": self.default_query, } - if not values.get("client"): - sync_specific = {"http_client": values["http_client"]} - values["client"] = openai.OpenAI( + if not (self.client or None): + sync_specific = {"http_client": self.http_client} + self.client = openai.OpenAI( **client_params, **sync_specific ).completions - if not values.get("async_client"): - async_specific = {"http_client": values["http_async_client"]} - values["async_client"] = openai.AsyncOpenAI( + if not (self.async_client or None): + async_specific = {"http_client": self.http_async_client} + self.async_client = openai.AsyncOpenAI( **client_params, **async_specific ).completions - return values + return self @property def _default_params(self) -> Dict[str, Any]: diff --git a/libs/partners/openai/tests/integration_tests/chat_models/test_base.py b/libs/partners/openai/tests/integration_tests/chat_models/test_base.py index 2e235421f9348..6f2a39bffdb57 100644 --- a/libs/partners/openai/tests/integration_tests/chat_models/test_base.py +++ b/libs/partners/openai/tests/integration_tests/chat_models/test_base.py @@ -20,7 +20,7 @@ ) from langchain_core.outputs import ChatGeneration, ChatResult, LLMResult from langchain_core.prompts import ChatPromptTemplate -from langchain_core.pydantic_v1 import BaseModel, Field +from pydantic import BaseModel, Field from langchain_standard_tests.integration_tests.chat_models import ( _validate_tool_call_message, ) diff --git a/libs/partners/openai/tests/unit_tests/chat_models/test_base.py b/libs/partners/openai/tests/unit_tests/chat_models/test_base.py index 4e959f005990d..493ca5abeffe5 100644 --- a/libs/partners/openai/tests/unit_tests/chat_models/test_base.py +++ b/libs/partners/openai/tests/unit_tests/chat_models/test_base.py @@ -17,7 +17,7 @@ ToolMessage, ) from langchain_core.messages.ai import UsageMetadata -from langchain_core.pydantic_v1 import BaseModel +from pydantic import BaseModel from langchain_openai import ChatOpenAI from langchain_openai.chat_models.base import ( diff --git a/libs/partners/openai/tests/unit_tests/fake/callbacks.py b/libs/partners/openai/tests/unit_tests/fake/callbacks.py index 2beee4a2ddef0..e786601aaa764 100644 --- a/libs/partners/openai/tests/unit_tests/fake/callbacks.py +++ b/libs/partners/openai/tests/unit_tests/fake/callbacks.py @@ -6,7 +6,7 @@ from langchain_core.callbacks.base import AsyncCallbackHandler, BaseCallbackHandler from langchain_core.messages import BaseMessage -from langchain_core.pydantic_v1 import BaseModel +from pydantic import BaseModel class BaseFakeCallbackHandler(BaseModel): diff --git a/libs/partners/openai/tests/unit_tests/test_load.py b/libs/partners/openai/tests/unit_tests/test_load.py index 059a10b4bf988..d25b00a0b87e2 100644 --- a/libs/partners/openai/tests/unit_tests/test_load.py +++ b/libs/partners/openai/tests/unit_tests/test_load.py @@ -9,7 +9,7 @@ def test_loads_openai_llm() -> None: llm_string = dumps(llm) llm2 = loads(llm_string, secrets_map={"OPENAI_API_KEY": "hello"}) - assert llm2 == llm + assert llm2.dict() == llm.dict() llm_string_2 = dumps(llm2) assert llm_string_2 == llm_string assert isinstance(llm2, OpenAI) @@ -20,7 +20,7 @@ def test_load_openai_llm() -> None: llm_obj = dumpd(llm) llm2 = load(llm_obj, secrets_map={"OPENAI_API_KEY": "hello"}) - assert llm2 == llm + assert llm2.dict() == llm.dict() assert dumpd(llm2) == llm_obj assert isinstance(llm2, OpenAI) @@ -30,7 +30,7 @@ def test_loads_openai_chat() -> None: llm_string = dumps(llm) llm2 = loads(llm_string, secrets_map={"OPENAI_API_KEY": "hello"}) - assert llm2 == llm + assert llm2.dict() == llm.dict() llm_string_2 = dumps(llm2) assert llm_string_2 == llm_string assert isinstance(llm2, ChatOpenAI) @@ -41,6 +41,6 @@ def test_load_openai_chat() -> None: llm_obj = dumpd(llm) llm2 = load(llm_obj, secrets_map={"OPENAI_API_KEY": "hello"}) - assert llm2 == llm + assert llm2.dict() == llm.dict() assert dumpd(llm2) == llm_obj assert isinstance(llm2, ChatOpenAI) diff --git a/libs/partners/openai/tests/unit_tests/test_secrets.py b/libs/partners/openai/tests/unit_tests/test_secrets.py index 0fb13e35b2811..2c88858056c9b 100644 --- a/libs/partners/openai/tests/unit_tests/test_secrets.py +++ b/libs/partners/openai/tests/unit_tests/test_secrets.py @@ -2,7 +2,7 @@ import pytest from langchain_core.load import dumpd -from langchain_core.pydantic_v1 import SecretStr +from pydantic import SecretStr from pytest import CaptureFixture, MonkeyPatch from langchain_openai import ( diff --git a/libs/standard-tests/langchain_standard_tests/unit_tests/chat_models.py b/libs/standard-tests/langchain_standard_tests/unit_tests/chat_models.py index f3a49b6c341ec..e7786e580bb24 100644 --- a/libs/standard-tests/langchain_standard_tests/unit_tests/chat_models.py +++ b/libs/standard-tests/langchain_standard_tests/unit_tests/chat_models.py @@ -6,7 +6,7 @@ import pytest from langchain_core.language_models import BaseChatModel -from langchain_core.pydantic_v1 import BaseModel, Field, SecretStr +from pydantic import BaseModel, Field, SecretStr from langchain_core.runnables import RunnableBinding from langchain_core.tools import tool diff --git a/libs/standard-tests/langchain_standard_tests/unit_tests/embeddings.py b/libs/standard-tests/langchain_standard_tests/unit_tests/embeddings.py index 0a6e793c06327..4638af51745be 100644 --- a/libs/standard-tests/langchain_standard_tests/unit_tests/embeddings.py +++ b/libs/standard-tests/langchain_standard_tests/unit_tests/embeddings.py @@ -5,7 +5,7 @@ import pytest from langchain_core.embeddings import Embeddings -from langchain_core.pydantic_v1 import SecretStr +from pydantic import SecretStr from langchain_standard_tests.base import BaseStandardTests From 5f5287c3b00a477ee96f7786f74625c21b084624 Mon Sep 17 00:00:00 2001 From: Bagatur Date: Tue, 3 Sep 2024 16:48:53 -0700 Subject: [PATCH 02/18] fmt --- .../langchain_openai/chat_models/azure.py | 20 +++++------ .../langchain_openai/chat_models/base.py | 34 +++++++------------ .../langchain_openai/embeddings/azure.py | 29 +++++++--------- .../langchain_openai/embeddings/base.py | 28 +++++---------- .../openai/langchain_openai/llms/azure.py | 15 ++++---- .../openai/langchain_openai/llms/base.py | 20 ++++------- .../chat_models/test_base.py | 2 +- .../openai/tests/unit_tests/fake/callbacks.py | 4 +-- 8 files changed, 60 insertions(+), 92 deletions(-) diff --git a/libs/partners/openai/langchain_openai/chat_models/azure.py b/libs/partners/openai/langchain_openai/chat_models/azure.py index e5ae0550fd7ff..b3f09333c20a3 100644 --- a/libs/partners/openai/langchain_openai/chat_models/azure.py +++ b/libs/partners/openai/langchain_openai/chat_models/azure.py @@ -31,16 +31,15 @@ PydanticToolsParser, ) from langchain_core.outputs import ChatResult -from pydantic import BaseModel, Field, SecretStr, model_validator from langchain_core.runnables import Runnable, RunnableMap, RunnablePassthrough from langchain_core.tools import BaseTool from langchain_core.utils import from_env, secret_from_env from langchain_core.utils.function_calling import convert_to_openai_tool from langchain_core.utils.pydantic import is_basemodel_subclass - -from langchain_openai.chat_models.base import BaseChatOpenAI +from pydantic import BaseModel, Field, SecretStr, model_validator from typing_extensions import Self +from langchain_openai.chat_models.base import BaseChatOpenAI logger = logging.getLogger(__name__) @@ -604,19 +603,15 @@ def validate_environment(self) -> Self: "Or you can equivalently specify:\n\n" 'base_url="https://xxx.openai.azure.com/openai/deployments/my-deployment"' ) - client_params = { + client_params: dict = { "api_version": self.openai_api_version, "azure_endpoint": self.azure_endpoint, "azure_deployment": self.deployment_name, "api_key": ( - self.openai_api_key.get_secret_value() - if self.openai_api_key - else None + self.openai_api_key.get_secret_value() if self.openai_api_key else None ), "azure_ad_token": ( - self.azure_ad_token.get_secret_value() - if self.azure_ad_token - else None + self.azure_ad_token.get_secret_value() if self.azure_ad_token else None ), "azure_ad_token_provider": self.azure_ad_token_provider, "organization": self.openai_organization, @@ -628,12 +623,13 @@ def validate_environment(self) -> Self: } if not (self.client or None): sync_specific = {"http_client": self.http_client} - self.root_client = openai.AzureOpenAI(**client_params, **sync_specific) + self.root_client = openai.AzureOpenAI(**client_params, **sync_specific) # type: ignore[arg-type] self.client = self.root_client.chat.completions if not (self.async_client or None): async_specific = {"http_client": self.http_async_client} self.root_async_client = openai.AsyncAzureOpenAI( - **client_params, **async_specific + **client_params, + **async_specific, # type: ignore[arg-type] ) self.async_client = self.root_async_client.chat.completions return self diff --git a/libs/partners/openai/langchain_openai/chat_models/base.py b/libs/partners/openai/langchain_openai/chat_models/base.py index 018d8febefbb3..f21670d5c2f88 100644 --- a/libs/partners/openai/langchain_openai/chat_models/base.py +++ b/libs/partners/openai/langchain_openai/chat_models/base.py @@ -73,11 +73,10 @@ parse_tool_call, ) from langchain_core.outputs import ChatGeneration, ChatGenerationChunk, ChatResult -from pydantic import BaseModel, Field, model_validator, SecretStr from langchain_core.runnables import Runnable, RunnableMap, RunnablePassthrough, chain from langchain_core.runnables.config import run_in_executor from langchain_core.tools import BaseTool -from langchain_core.utils import get_from_dict_or_env, get_pydantic_field_names +from langchain_core.utils import get_pydantic_field_names from langchain_core.utils.function_calling import ( convert_to_openai_function, convert_to_openai_tool, @@ -88,10 +87,9 @@ is_basemodel_subclass, ) from langchain_core.utils.utils import build_extra_kwargs, from_env, secret_from_env -from pydantic import ConfigDict +from pydantic import BaseModel, ConfigDict, Field, SecretStr, model_validator from typing_extensions import Self - logger = logging.getLogger(__name__) @@ -361,8 +359,7 @@ class BaseChatOpenAI(BaseChatModel): model_kwargs: Dict[str, Any] = Field(default_factory=dict) """Holds any model parameters valid for `create` call not explicitly specified.""" openai_api_key: Optional[SecretStr] = Field( - alias="api_key", - default_factory=secret_from_env("OPENAI_API_KEY", default=None), + alias="api_key", default_factory=secret_from_env("OPENAI_API_KEY", default=None) ) openai_api_base: Optional[str] = Field(default=None, alias="base_url") """Base URL path for API requests, leave blank if not using a proxy or service @@ -431,7 +428,7 @@ class BaseChatOpenAI(BaseChatModel): include_response_headers: bool = False """Whether to include response headers in the output message response_metadata.""" - model_config = ConfigDict(populate_by_name=True,) + model_config = ConfigDict(populate_by_name=True) @model_validator(mode="before") @classmethod @@ -458,14 +455,10 @@ def validate_environment(self) -> Self: or os.getenv("OPENAI_ORG_ID") or os.getenv("OPENAI_ORGANIZATION") ) - self.openai_api_base = self.openai_api_base or os.getenv( - "OPENAI_API_BASE" - ) - client_params = { + self.openai_api_base = self.openai_api_base or os.getenv("OPENAI_API_BASE") + client_params: dict = { "api_key": ( - self.openai_api_key.get_secret_value() - if self.openai_api_key - else None + self.openai_api_key.get_secret_value() if self.openai_api_key else None ), "organization": self.openai_organization, "base_url": self.openai_api_base, @@ -474,9 +467,7 @@ def validate_environment(self) -> Self: "default_headers": self.default_headers, "default_query": self.default_query, } - if self.openai_proxy and ( - self.http_client or self.http_async_client - ): + if self.openai_proxy and (self.http_client or self.http_async_client): openai_proxy = self.openai_proxy http_client = self.http_client http_async_client = self.http_async_client @@ -496,7 +487,7 @@ def validate_environment(self) -> Self: ) from e self.http_client = httpx.Client(proxy=self.openai_proxy) sync_specific = {"http_client": self.http_client} - self.root_client = openai.OpenAI(**client_params, **sync_specific) + self.root_client = openai.OpenAI(**client_params, **sync_specific) # type: ignore[arg-type] self.client = self.root_client.chat.completions if not (self.async_client or None): if self.openai_proxy and not self.http_async_client: @@ -507,12 +498,11 @@ def validate_environment(self) -> Self: "Could not import httpx python package. " "Please install it with `pip install httpx`." ) from e - self.http_async_client = httpx.AsyncClient( - proxy=self.openai_proxy - ) + self.http_async_client = httpx.AsyncClient(proxy=self.openai_proxy) async_specific = {"http_client": self.http_async_client} self.root_async_client = openai.AsyncOpenAI( - **client_params, **async_specific + **client_params, + **async_specific, # type: ignore[arg-type] ) self.async_client = self.root_async_client.chat.completions return self diff --git a/libs/partners/openai/langchain_openai/embeddings/azure.py b/libs/partners/openai/langchain_openai/embeddings/azure.py index 6697cee53926e..a5e600b662b7b 100644 --- a/libs/partners/openai/langchain_openai/embeddings/azure.py +++ b/libs/partners/openai/langchain_openai/embeddings/azure.py @@ -2,15 +2,14 @@ from __future__ import annotations -from typing import Callable, Dict, Optional, Union +from typing import Callable, Optional, Union import openai -from pydantic import Field, SecretStr, root_validator, model_validator from langchain_core.utils import from_env, secret_from_env +from pydantic import Field, SecretStr, model_validator +from typing_extensions import Self, cast from langchain_openai.embeddings.base import OpenAIEmbeddings -from typing_extensions import Self - class AzureOpenAIEmbeddings(OpenAIEmbeddings): @@ -163,7 +162,7 @@ def validate_environment(self) -> Self: openai_api_base = self.openai_api_base if openai_api_base and self.validate_base_url: if "/openai" not in openai_api_base: - self.openai_api_base += "/openai" + self.openai_api_base = cast(str, self.openai_api_base) + "/openai" raise ValueError( "As of openai>=1.0.0, Azure endpoints should be specified via " "the `azure_endpoint` param not `openai_api_base` " @@ -177,19 +176,15 @@ def validate_environment(self) -> Self: "Instead use `deployment` (or alias `azure_deployment`) " "and `azure_endpoint`." ) - client_params = { + client_params: dict = { "api_version": self.openai_api_version, "azure_endpoint": self.azure_endpoint, "azure_deployment": self.deployment, "api_key": ( - self.openai_api_key.get_secret_value() - if self.openai_api_key - else None + self.openai_api_key.get_secret_value() if self.openai_api_key else None ), "azure_ad_token": ( - self.azure_ad_token.get_secret_value() - if self.azure_ad_token - else None + self.azure_ad_token.get_secret_value() if self.azure_ad_token else None ), "azure_ad_token_provider": self.azure_ad_token_provider, "organization": self.openai_organization, @@ -200,14 +195,16 @@ def validate_environment(self) -> Self: "default_query": self.default_query, } if not (self.client or None): - sync_specific = {"http_client": self.http_client} + sync_specific: dict = {"http_client": self.http_client} self.client = openai.AzureOpenAI( - **client_params, **sync_specific + **client_params, # type: ignore[arg-type] + **sync_specific, ).embeddings if not (self.async_client or None): - async_specific = {"http_client": self.http_async_client} + async_specific: dict = {"http_client": self.http_async_client} self.async_client = openai.AsyncAzureOpenAI( - **client_params, **async_specific + **client_params, # type: ignore[arg-type] + **async_specific, ).embeddings return self diff --git a/libs/partners/openai/langchain_openai/embeddings/base.py b/libs/partners/openai/langchain_openai/embeddings/base.py index e6294d32ac2a2..f58471d4bab8e 100644 --- a/libs/partners/openai/langchain_openai/embeddings/base.py +++ b/libs/partners/openai/langchain_openai/embeddings/base.py @@ -20,13 +20,10 @@ import openai import tiktoken from langchain_core.embeddings import Embeddings -from pydantic import BaseModel, Field, SecretStr, root_validator, model_validator from langchain_core.utils import from_env, get_pydantic_field_names, secret_from_env -from pydantic import ConfigDict +from pydantic import BaseModel, ConfigDict, Field, SecretStr, model_validator from typing_extensions import Self - - logger = logging.getLogger(__name__) @@ -267,7 +264,7 @@ class OpenAIEmbeddings(BaseModel, Embeddings): """Whether to check the token length of inputs and automatically split inputs longer than embedding_ctx_length.""" - model_config = ConfigDict(extra="forbid",populate_by_name=True,) + model_config = ConfigDict(extra="forbid", populate_by_name=True) @model_validator(mode="before") @classmethod @@ -304,11 +301,9 @@ def validate_environment(self) -> Self: "If you are using Azure, " "please use the `AzureOpenAIEmbeddings` class." ) - client_params = { + client_params: dict = { "api_key": ( - self.openai_api_key.get_secret_value() - if self.openai_api_key - else None + self.openai_api_key.get_secret_value() if self.openai_api_key else None ), "organization": self.openai_organization, "base_url": self.openai_api_base, @@ -318,9 +313,7 @@ def validate_environment(self) -> Self: "default_query": self.default_query, } - if self.openai_proxy and ( - self.http_client or self.http_async_client - ): + if self.openai_proxy and (self.http_client or self.http_async_client): openai_proxy = self.openai_proxy http_client = self.http_client http_async_client = self.http_async_client @@ -340,9 +333,7 @@ def validate_environment(self) -> Self: ) from e self.http_client = httpx.Client(proxy=self.openai_proxy) sync_specific = {"http_client": self.http_client} - self.client = openai.OpenAI( - **client_params, **sync_specific - ).embeddings + self.client = openai.OpenAI(**client_params, **sync_specific).embeddings # type: ignore[arg-type] if not (self.async_client or None): if self.openai_proxy and not self.http_async_client: try: @@ -352,12 +343,11 @@ def validate_environment(self) -> Self: "Could not import httpx python package. " "Please install it with `pip install httpx`." ) from e - self.http_async_client = httpx.AsyncClient( - proxy=self.openai_proxy - ) + self.http_async_client = httpx.AsyncClient(proxy=self.openai_proxy) async_specific = {"http_client": self.http_async_client} self.async_client = openai.AsyncOpenAI( - **client_params, **async_specific + **client_params, + **async_specific, # type: ignore[arg-type] ).embeddings return self diff --git a/libs/partners/openai/langchain_openai/llms/azure.py b/libs/partners/openai/langchain_openai/llms/azure.py index e48b1380ff79f..973fd9c271e63 100644 --- a/libs/partners/openai/langchain_openai/llms/azure.py +++ b/libs/partners/openai/langchain_openai/llms/azure.py @@ -5,12 +5,11 @@ import openai from langchain_core.language_models import LangSmithParams -from pydantic import Field, SecretStr, root_validator, model_validator from langchain_core.utils import from_env, secret_from_env +from pydantic import Field, SecretStr, model_validator +from typing_extensions import Self, cast from langchain_openai.llms.base import BaseOpenAI -from typing_extensions import Self - logger = logging.getLogger(__name__) @@ -117,7 +116,7 @@ def validate_environment(self) -> Self: if openai_api_base and self.validate_base_url: if "/openai" not in openai_api_base: self.openai_api_base = ( - self.openai_api_base.rstrip("/") + "/openai" + cast(str, self.openai_api_base).rstrip("/") + "/openai" ) raise ValueError( "As of openai>=1.0.0, Azure endpoints should be specified via " @@ -133,7 +132,7 @@ def validate_environment(self) -> Self: "and `azure_endpoint`." ) self.deployment_name = None - client_params = { + client_params: dict = { "api_version": self.openai_api_version, "azure_endpoint": self.azure_endpoint, "azure_deployment": self.deployment_name, @@ -154,12 +153,14 @@ def validate_environment(self) -> Self: if not (self.client or None): sync_specific = {"http_client": self.http_client} self.client = openai.AzureOpenAI( - **client_params, **sync_specific + **client_params, + **sync_specific, # type: ignore[arg-type] ).completions if not (self.async_client or None): async_specific = {"http_client": self.http_async_client} self.async_client = openai.AsyncAzureOpenAI( - **client_params, **async_specific + **client_params, + **async_specific, # type: ignore[arg-type] ).completions return self diff --git a/libs/partners/openai/langchain_openai/llms/base.py b/libs/partners/openai/langchain_openai/llms/base.py index 0db987c5e0d5a..248e7657466a0 100644 --- a/libs/partners/openai/langchain_openai/llms/base.py +++ b/libs/partners/openai/langchain_openai/llms/base.py @@ -26,14 +26,11 @@ ) from langchain_core.language_models.llms import BaseLLM from langchain_core.outputs import Generation, GenerationChunk, LLMResult -from pydantic import Field, SecretStr, root_validator, model_validator from langchain_core.utils import get_pydantic_field_names from langchain_core.utils.utils import build_extra_kwargs, from_env, secret_from_env -from pydantic import ConfigDict +from pydantic import ConfigDict, Field, SecretStr, model_validator from typing_extensions import Self - - logger = logging.getLogger(__name__) @@ -156,7 +153,7 @@ class BaseOpenAI(BaseLLM): """Optional additional JSON properties to include in the request parameters when making requests to OpenAI compatible APIs, such as vLLM.""" - model_config = ConfigDict(populate_by_name=True,) + model_config = ConfigDict(populate_by_name=True) @model_validator(mode="before") @classmethod @@ -179,11 +176,9 @@ def validate_environment(self) -> Self: if self.streaming and self.best_of > 1: raise ValueError("Cannot stream results when best_of > 1.") - client_params = { + client_params: dict = { "api_key": ( - self.openai_api_key.get_secret_value() - if self.openai_api_key - else None + self.openai_api_key.get_secret_value() if self.openai_api_key else None ), "organization": self.openai_organization, "base_url": self.openai_api_base, @@ -194,13 +189,12 @@ def validate_environment(self) -> Self: } if not (self.client or None): sync_specific = {"http_client": self.http_client} - self.client = openai.OpenAI( - **client_params, **sync_specific - ).completions + self.client = openai.OpenAI(**client_params, **sync_specific).completions # type: ignore[arg-type] if not (self.async_client or None): async_specific = {"http_client": self.http_async_client} self.async_client = openai.AsyncOpenAI( - **client_params, **async_specific + **client_params, + **async_specific, # type: ignore[arg-type] ).completions return self diff --git a/libs/partners/openai/tests/integration_tests/chat_models/test_base.py b/libs/partners/openai/tests/integration_tests/chat_models/test_base.py index 6f2a39bffdb57..96f32c754f68b 100644 --- a/libs/partners/openai/tests/integration_tests/chat_models/test_base.py +++ b/libs/partners/openai/tests/integration_tests/chat_models/test_base.py @@ -20,13 +20,13 @@ ) from langchain_core.outputs import ChatGeneration, ChatResult, LLMResult from langchain_core.prompts import ChatPromptTemplate -from pydantic import BaseModel, Field from langchain_standard_tests.integration_tests.chat_models import ( _validate_tool_call_message, ) from langchain_standard_tests.integration_tests.chat_models import ( magic_function as invalid_magic_function, ) +from pydantic import BaseModel, Field from langchain_openai import ChatOpenAI from tests.unit_tests.fake.callbacks import FakeCallbackHandler diff --git a/libs/partners/openai/tests/unit_tests/fake/callbacks.py b/libs/partners/openai/tests/unit_tests/fake/callbacks.py index e786601aaa764..d4b8d4b2c256b 100644 --- a/libs/partners/openai/tests/unit_tests/fake/callbacks.py +++ b/libs/partners/openai/tests/unit_tests/fake/callbacks.py @@ -188,7 +188,7 @@ def on_retriever_end(self, *args: Any, **kwargs: Any) -> Any: def on_retriever_error(self, *args: Any, **kwargs: Any) -> Any: self.on_retriever_error_common() - def __deepcopy__(self, memo: dict) -> "FakeCallbackHandler": + def __deepcopy__(self, memo: dict) -> "FakeCallbackHandler": # type: ignore[override] return self @@ -266,5 +266,5 @@ async def on_agent_finish(self, *args: Any, **kwargs: Any) -> None: async def on_text(self, *args: Any, **kwargs: Any) -> None: self.on_text_common() - def __deepcopy__(self, memo: dict) -> "FakeAsyncCallbackHandler": + def __deepcopy__(self, memo: dict) -> "FakeAsyncCallbackHandler": # type: ignore[override] return self From 6777106fbe053f53e1d094332bbe98870a61fd6f Mon Sep 17 00:00:00 2001 From: Bagatur Date: Tue, 3 Sep 2024 16:50:17 -0700 Subject: [PATCH 03/18] fmt --- .../openai/langchain_openai/chat_models/azure.py | 10 +++++----- .../openai/langchain_openai/chat_models/base.py | 10 +++++----- libs/partners/openai/scripts/check_pydantic.sh | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/libs/partners/openai/langchain_openai/chat_models/azure.py b/libs/partners/openai/langchain_openai/chat_models/azure.py index b3f09333c20a3..2213b33e80abc 100644 --- a/libs/partners/openai/langchain_openai/chat_models/azure.py +++ b/libs/partners/openai/langchain_openai/chat_models/azure.py @@ -251,7 +251,7 @@ class AzureChatOpenAI(BaseChatOpenAI): Tool calling: .. code-block:: python - from langchain_core.pydantic_v1 import BaseModel, Field + from pydantic import BaseModel, Field class GetWeather(BaseModel): @@ -306,7 +306,7 @@ class GetPopulation(BaseModel): from typing import Optional - from langchain_core.pydantic_v1 import BaseModel, Field + from pydantic import BaseModel, Field class Joke(BaseModel): @@ -733,7 +733,7 @@ def with_structured_output( from typing import Optional from langchain_openai import AzureChatOpenAI - from langchain_core.pydantic_v1 import BaseModel, Field + from pydantic import BaseModel, Field class AnswerWithJustification(BaseModel): @@ -764,7 +764,7 @@ class AnswerWithJustification(BaseModel): .. code-block:: python from langchain_openai import AzureChatOpenAI - from langchain_core.pydantic_v1 import BaseModel + from pydantic import BaseModel class AnswerWithJustification(BaseModel): @@ -851,7 +851,7 @@ class AnswerWithJustification(TypedDict): .. code-block:: from langchain_openai import AzureChatOpenAI - from langchain_core.pydantic_v1 import BaseModel + from pydantic import BaseModel class AnswerWithJustification(BaseModel): answer: str diff --git a/libs/partners/openai/langchain_openai/chat_models/base.py b/libs/partners/openai/langchain_openai/chat_models/base.py index f21670d5c2f88..f753beb40ddd6 100644 --- a/libs/partners/openai/langchain_openai/chat_models/base.py +++ b/libs/partners/openai/langchain_openai/chat_models/base.py @@ -1190,7 +1190,7 @@ def with_structured_output( from typing import Optional from langchain_openai import ChatOpenAI - from langchain_core.pydantic_v1 import BaseModel, Field + from pydantic import BaseModel, Field class AnswerWithJustification(BaseModel): @@ -1221,7 +1221,7 @@ class AnswerWithJustification(BaseModel): .. code-block:: python from langchain_openai import ChatOpenAI - from langchain_core.pydantic_v1 import BaseModel + from pydantic import BaseModel class AnswerWithJustification(BaseModel): @@ -1311,7 +1311,7 @@ class AnswerWithJustification(TypedDict): .. code-block:: from langchain_openai import ChatOpenAI - from langchain_core.pydantic_v1 import BaseModel + from pydantic import BaseModel class AnswerWithJustification(BaseModel): answer: str @@ -1613,7 +1613,7 @@ class ChatOpenAI(BaseChatOpenAI): .. code-block:: python - from langchain_core.pydantic_v1 import BaseModel, Field + from pydantic import BaseModel, Field class GetWeather(BaseModel): @@ -1699,7 +1699,7 @@ class GetPopulation(BaseModel): from typing import Optional - from langchain_core.pydantic_v1 import BaseModel, Field + from pydantic import BaseModel, Field class Joke(BaseModel): diff --git a/libs/partners/openai/scripts/check_pydantic.sh b/libs/partners/openai/scripts/check_pydantic.sh index 06b5bb81ae236..1317f5e53914f 100755 --- a/libs/partners/openai/scripts/check_pydantic.sh +++ b/libs/partners/openai/scripts/check_pydantic.sh @@ -20,8 +20,8 @@ result=$(git -C "$repository_path" grep -E '^import pydantic|^from pydantic') 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 "Please replace the code with an import from pydantic." echo "For example, replace 'from pydantic import BaseModel'" - echo "with 'from langchain_core.pydantic_v1 import BaseModel'" + echo "with 'from pydantic import BaseModel'" exit 1 fi From 5fc1104d00f866b173006f99f7c8601e1a06f7e3 Mon Sep 17 00:00:00 2001 From: Bagatur Date: Tue, 3 Sep 2024 16:51:14 -0700 Subject: [PATCH 04/18] fmt --- .../langchain_standard_tests/unit_tests/chat_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/standard-tests/langchain_standard_tests/unit_tests/chat_models.py b/libs/standard-tests/langchain_standard_tests/unit_tests/chat_models.py index e7786e580bb24..90b051c904625 100644 --- a/libs/standard-tests/langchain_standard_tests/unit_tests/chat_models.py +++ b/libs/standard-tests/langchain_standard_tests/unit_tests/chat_models.py @@ -6,9 +6,9 @@ import pytest from langchain_core.language_models import BaseChatModel -from pydantic import BaseModel, Field, SecretStr from langchain_core.runnables import RunnableBinding from langchain_core.tools import tool +from pydantic import BaseModel, Field, SecretStr from langchain_standard_tests.base import BaseStandardTests from langchain_standard_tests.utils.pydantic import PYDANTIC_MAJOR_VERSION From 9399df7777fcfb42446ba435ee7f5c57c2eba275 Mon Sep 17 00:00:00 2001 From: Bagatur Date: Tue, 3 Sep 2024 16:57:42 -0700 Subject: [PATCH 05/18] fmt --- .../integration_tests/chat_models.py | 27 +++++++--------- .../unit_tests/chat_models.py | 32 +++++++++++-------- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/libs/standard-tests/langchain_standard_tests/integration_tests/chat_models.py b/libs/standard-tests/langchain_standard_tests/integration_tests/chat_models.py index ec7e81af1ed03..171b1936a2cdb 100644 --- a/libs/standard-tests/langchain_standard_tests/integration_tests/chat_models.py +++ b/libs/standard-tests/langchain_standard_tests/integration_tests/chat_models.py @@ -16,10 +16,10 @@ ) from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate -from langchain_core.pydantic_v1 import BaseModel, Field from langchain_core.tools import tool -from pydantic import BaseModel as RawBaseModel -from pydantic import Field as RawField +from pydantic import BaseModel, Field +from pydantic.v1 import BaseModel as BaseModelV1 +from pydantic.v1 import Field as FieldV1 from langchain_standard_tests.unit_tests.chat_models import ( ChatModelTests, @@ -28,8 +28,8 @@ from langchain_standard_tests.utils.pydantic import PYDANTIC_MAJOR_VERSION -class MagicFunctionSchema(RawBaseModel): - input: int = RawField(..., gt=-1000, lt=1000) +class MagicFunctionSchema(BaseModel): + input: int = Field(..., gt=-1000, lt=1000) @tool(args_schema=MagicFunctionSchema) @@ -240,14 +240,11 @@ def test_structured_output(self, model: BaseChatModel) -> None: if not self.has_tool_calling: pytest.skip("Test requires tool calling.") - from pydantic import BaseModel as BaseModelProper - from pydantic import Field as FieldProper - - class Joke(BaseModelProper): + class Joke(BaseModel): """Joke to tell user.""" - setup: str = FieldProper(description="question to set up a joke") - punchline: str = FieldProper(description="answer to resolve the joke") + setup: str = Field(description="question to set up a joke") + punchline: str = Field(description="answer to resolve the joke") # Pydantic class # Type ignoring since the interface only officially supports pydantic 1 @@ -280,11 +277,11 @@ def test_structured_output_pydantic_2_v1(self, model: BaseChatModel) -> None: if not self.has_tool_calling: pytest.skip("Test requires tool calling.") - class Joke(BaseModel): # Uses langchain_core.pydantic_v1.BaseModel + class Joke(BaseModelV1): # Uses langchain_core.pydantic_v1.BaseModel """Joke to tell user.""" - setup: str = Field(description="question to set up a joke") - punchline: str = Field(description="answer to resolve the joke") + setup: str = FieldV1(description="question to set up a joke") + punchline: str = FieldV1(description="answer to resolve the joke") # Pydantic class chat = model.with_structured_output(Joke) @@ -439,7 +436,7 @@ def test_anthropic_inputs(self, model: BaseChatModel) -> None: if not self.supports_anthropic_inputs: return - class color_picker(BaseModel): + class color_picker(BaseModelV1): """Input your fav color and get a random fact about it.""" fav_color: str diff --git a/libs/standard-tests/langchain_standard_tests/unit_tests/chat_models.py b/libs/standard-tests/langchain_standard_tests/unit_tests/chat_models.py index 90b051c904625..723c4c9c8b1de 100644 --- a/libs/standard-tests/langchain_standard_tests/unit_tests/chat_models.py +++ b/libs/standard-tests/langchain_standard_tests/unit_tests/chat_models.py @@ -9,6 +9,15 @@ from langchain_core.runnables import RunnableBinding from langchain_core.tools import tool from pydantic import BaseModel, Field, SecretStr +from pydantic.v1 import ( + BaseModel as BaseModelV1, +) +from pydantic.v1 import ( + Field as FieldV1, +) +from pydantic.v1 import ( + ValidationError as ValidationErrorV1, +) from langchain_standard_tests.base import BaseStandardTests from langchain_standard_tests.utils.pydantic import PYDANTIC_MAJOR_VERSION @@ -25,27 +34,24 @@ def generate_schema_pydantic_v1_from_2() -> Any: """Use to generate a schema from v1 namespace in pydantic 2.""" if PYDANTIC_MAJOR_VERSION != 2: raise AssertionError("This function is only compatible with Pydantic v2.") - from pydantic.v1 import BaseModel, Field - class PersonB(BaseModel): + class PersonB(BaseModelV1): """Record attributes of a person.""" - name: str = Field(..., description="The name of the person.") - age: int = Field(..., description="The age of the person.") + name: str = FieldV1(..., description="The name of the person.") + age: int = FieldV1(..., description="The age of the person.") return PersonB def generate_schema_pydantic() -> Any: """Works with either pydantic 1 or 2""" - from pydantic import BaseModel as BaseModelProper - from pydantic import Field as FieldProper - class PersonA(BaseModelProper): + class PersonA(BaseModel): """Record attributes of a person.""" - name: str = FieldProper(..., description="The name of the person.") - age: int = FieldProper(..., description="The age of the person.") + name: str = Field(..., description="The name of the person.") + age: int = Field(..., description="The age of the person.") return PersonA @@ -199,9 +205,7 @@ def test_with_structured_output( assert model.with_structured_output(schema) is not None def test_standard_params(self, model: BaseChatModel) -> None: - from langchain_core.pydantic_v1 import BaseModel, ValidationError - - class ExpectedParams(BaseModel): + class ExpectedParams(BaseModelV1): ls_provider: str ls_model_name: str ls_model_type: Literal["chat"] @@ -212,7 +216,7 @@ class ExpectedParams(BaseModel): ls_params = model._get_ls_params() try: ExpectedParams(**ls_params) - except ValidationError as e: + except ValidationErrorV1 as e: pytest.fail(f"Validation error: {e}") # Test optional params @@ -222,5 +226,5 @@ class ExpectedParams(BaseModel): ls_params = model._get_ls_params() try: ExpectedParams(**ls_params) - except ValidationError as e: + except ValidationErrorV1 as e: pytest.fail(f"Validation error: {e}") From ec9e8eb71c01852ddbbb3d3e3bac9986654ae19f Mon Sep 17 00:00:00 2001 From: Bagatur Date: Tue, 3 Sep 2024 17:24:24 -0700 Subject: [PATCH 06/18] fmt --- libs/partners/openai/langchain_openai/embeddings/azure.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/partners/openai/langchain_openai/embeddings/azure.py b/libs/partners/openai/langchain_openai/embeddings/azure.py index a5e600b662b7b..6402a24407eda 100644 --- a/libs/partners/openai/langchain_openai/embeddings/azure.py +++ b/libs/partners/openai/langchain_openai/embeddings/azure.py @@ -126,7 +126,8 @@ class AzureOpenAIEmbeddings(OpenAIEmbeddings): ) """Automatically inferred from env var `AZURE_OPENAI_API_KEY` if not provided.""" openai_api_version: Optional[str] = Field( - default_factory=from_env("OPENAI_API_VERSION", default="2023-05-15") + default_factory=from_env("OPENAI_API_VERSION", default="2023-05-15"), + alias="api_version", ) """Automatically inferred from env var `OPENAI_API_VERSION` if not provided. From 49a1f5dd47a0ee5506f4801a8dd3ddec86afbbff Mon Sep 17 00:00:00 2001 From: Bagatur <22008038+baskaryan@users.noreply.github.com> Date: Tue, 3 Sep 2024 23:35:15 -0700 Subject: [PATCH 07/18] Update libs/partners/openai/langchain_openai/chat_models/azure.py --- libs/partners/openai/langchain_openai/chat_models/azure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/partners/openai/langchain_openai/chat_models/azure.py b/libs/partners/openai/langchain_openai/chat_models/azure.py index 2213b33e80abc..bada074530569 100644 --- a/libs/partners/openai/langchain_openai/chat_models/azure.py +++ b/libs/partners/openai/langchain_openai/chat_models/azure.py @@ -621,7 +621,7 @@ def validate_environment(self) -> Self: "default_headers": self.default_headers, "default_query": self.default_query, } - if not (self.client or None): + if not self.client: sync_specific = {"http_client": self.http_client} self.root_client = openai.AzureOpenAI(**client_params, **sync_specific) # type: ignore[arg-type] self.client = self.root_client.chat.completions From 5e31cd91a72c996ee8075b2ef3eb8f1881d72fc2 Mon Sep 17 00:00:00 2001 From: Bagatur <22008038+baskaryan@users.noreply.github.com> Date: Tue, 3 Sep 2024 23:35:21 -0700 Subject: [PATCH 08/18] Update libs/partners/openai/langchain_openai/chat_models/azure.py --- libs/partners/openai/langchain_openai/chat_models/azure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/partners/openai/langchain_openai/chat_models/azure.py b/libs/partners/openai/langchain_openai/chat_models/azure.py index bada074530569..0d89947fb2a74 100644 --- a/libs/partners/openai/langchain_openai/chat_models/azure.py +++ b/libs/partners/openai/langchain_openai/chat_models/azure.py @@ -625,7 +625,7 @@ def validate_environment(self) -> Self: sync_specific = {"http_client": self.http_client} self.root_client = openai.AzureOpenAI(**client_params, **sync_specific) # type: ignore[arg-type] self.client = self.root_client.chat.completions - if not (self.async_client or None): + if not self.async_client: async_specific = {"http_client": self.http_async_client} self.root_async_client = openai.AsyncAzureOpenAI( **client_params, From 5199555c0d0d20ef2bb35ced28f77ad941d552c8 Mon Sep 17 00:00:00 2001 From: Bagatur <22008038+baskaryan@users.noreply.github.com> Date: Tue, 3 Sep 2024 23:35:26 -0700 Subject: [PATCH 09/18] Update libs/partners/openai/langchain_openai/chat_models/base.py --- libs/partners/openai/langchain_openai/chat_models/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/partners/openai/langchain_openai/chat_models/base.py b/libs/partners/openai/langchain_openai/chat_models/base.py index f753beb40ddd6..daaf44d5d08a1 100644 --- a/libs/partners/openai/langchain_openai/chat_models/base.py +++ b/libs/partners/openai/langchain_openai/chat_models/base.py @@ -476,7 +476,7 @@ def validate_environment(self) -> Self: "'http_client'/'http_async_client' is already specified. Received:\n" f"{openai_proxy=}\n{http_client=}\n{http_async_client=}" ) - if not (self.client or None): + if not self.client: if self.openai_proxy and not self.http_client: try: import httpx From 78c454c130ae5fa95283eb32204feca94e48f889 Mon Sep 17 00:00:00 2001 From: Bagatur <22008038+baskaryan@users.noreply.github.com> Date: Tue, 3 Sep 2024 23:35:30 -0700 Subject: [PATCH 10/18] Update libs/partners/openai/langchain_openai/chat_models/base.py --- libs/partners/openai/langchain_openai/chat_models/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/partners/openai/langchain_openai/chat_models/base.py b/libs/partners/openai/langchain_openai/chat_models/base.py index daaf44d5d08a1..8d643fd6b8476 100644 --- a/libs/partners/openai/langchain_openai/chat_models/base.py +++ b/libs/partners/openai/langchain_openai/chat_models/base.py @@ -489,7 +489,7 @@ def validate_environment(self) -> Self: sync_specific = {"http_client": self.http_client} self.root_client = openai.OpenAI(**client_params, **sync_specific) # type: ignore[arg-type] self.client = self.root_client.chat.completions - if not (self.async_client or None): + if not self.async_client: if self.openai_proxy and not self.http_async_client: try: import httpx From d072d592a1cdbced06cd5e5c408ffaec1e5cde49 Mon Sep 17 00:00:00 2001 From: Bagatur <22008038+baskaryan@users.noreply.github.com> Date: Tue, 3 Sep 2024 23:35:35 -0700 Subject: [PATCH 11/18] Update libs/partners/openai/langchain_openai/embeddings/azure.py --- libs/partners/openai/langchain_openai/embeddings/azure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/partners/openai/langchain_openai/embeddings/azure.py b/libs/partners/openai/langchain_openai/embeddings/azure.py index 6402a24407eda..68573df4d991e 100644 --- a/libs/partners/openai/langchain_openai/embeddings/azure.py +++ b/libs/partners/openai/langchain_openai/embeddings/azure.py @@ -195,7 +195,7 @@ def validate_environment(self) -> Self: "default_headers": self.default_headers, "default_query": self.default_query, } - if not (self.client or None): + if not self.client: sync_specific: dict = {"http_client": self.http_client} self.client = openai.AzureOpenAI( **client_params, # type: ignore[arg-type] From 179aaa400774867c0a22e34f915b9f07d9529a52 Mon Sep 17 00:00:00 2001 From: Bagatur <22008038+baskaryan@users.noreply.github.com> Date: Tue, 3 Sep 2024 23:35:43 -0700 Subject: [PATCH 12/18] Update libs/partners/openai/langchain_openai/embeddings/azure.py --- libs/partners/openai/langchain_openai/embeddings/azure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/partners/openai/langchain_openai/embeddings/azure.py b/libs/partners/openai/langchain_openai/embeddings/azure.py index 68573df4d991e..06349e36a5195 100644 --- a/libs/partners/openai/langchain_openai/embeddings/azure.py +++ b/libs/partners/openai/langchain_openai/embeddings/azure.py @@ -201,7 +201,7 @@ def validate_environment(self) -> Self: **client_params, # type: ignore[arg-type] **sync_specific, ).embeddings - if not (self.async_client or None): + if not self.async_client: async_specific: dict = {"http_client": self.http_async_client} self.async_client = openai.AsyncAzureOpenAI( **client_params, # type: ignore[arg-type] From c0448f27bae51396ec54050febd0bb939461f1f9 Mon Sep 17 00:00:00 2001 From: Bagatur <22008038+baskaryan@users.noreply.github.com> Date: Tue, 3 Sep 2024 23:35:51 -0700 Subject: [PATCH 13/18] Update libs/partners/openai/langchain_openai/embeddings/base.py --- libs/partners/openai/langchain_openai/embeddings/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/partners/openai/langchain_openai/embeddings/base.py b/libs/partners/openai/langchain_openai/embeddings/base.py index f58471d4bab8e..1cc19150cb9c0 100644 --- a/libs/partners/openai/langchain_openai/embeddings/base.py +++ b/libs/partners/openai/langchain_openai/embeddings/base.py @@ -322,7 +322,7 @@ def validate_environment(self) -> Self: "'http_client'/'http_async_client' is already specified. Received:\n" f"{openai_proxy=}\n{http_client=}\n{http_async_client=}" ) - if not (self.client or None): + if not self.client: if self.openai_proxy and not self.http_client: try: import httpx From 76572f963b4e4d9d35ced611042b6d9f0d5826b6 Mon Sep 17 00:00:00 2001 From: Bagatur <22008038+baskaryan@users.noreply.github.com> Date: Tue, 3 Sep 2024 23:35:56 -0700 Subject: [PATCH 14/18] Update libs/partners/openai/langchain_openai/embeddings/base.py --- libs/partners/openai/langchain_openai/embeddings/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/partners/openai/langchain_openai/embeddings/base.py b/libs/partners/openai/langchain_openai/embeddings/base.py index 1cc19150cb9c0..02f72542c017c 100644 --- a/libs/partners/openai/langchain_openai/embeddings/base.py +++ b/libs/partners/openai/langchain_openai/embeddings/base.py @@ -334,7 +334,7 @@ def validate_environment(self) -> Self: self.http_client = httpx.Client(proxy=self.openai_proxy) sync_specific = {"http_client": self.http_client} self.client = openai.OpenAI(**client_params, **sync_specific).embeddings # type: ignore[arg-type] - if not (self.async_client or None): + if not self.async_client: if self.openai_proxy and not self.http_async_client: try: import httpx From 78468de2e5211b7f54277fbd1c40b6a67021460d Mon Sep 17 00:00:00 2001 From: Bagatur <22008038+baskaryan@users.noreply.github.com> Date: Tue, 3 Sep 2024 23:36:02 -0700 Subject: [PATCH 15/18] Update libs/partners/openai/langchain_openai/llms/azure.py --- libs/partners/openai/langchain_openai/llms/azure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/partners/openai/langchain_openai/llms/azure.py b/libs/partners/openai/langchain_openai/llms/azure.py index 973fd9c271e63..f9491d789b48a 100644 --- a/libs/partners/openai/langchain_openai/llms/azure.py +++ b/libs/partners/openai/langchain_openai/llms/azure.py @@ -150,7 +150,7 @@ def validate_environment(self) -> Self: "default_headers": self.default_headers, "default_query": self.default_query, } - if not (self.client or None): + if not self.client: sync_specific = {"http_client": self.http_client} self.client = openai.AzureOpenAI( **client_params, From 54d6808c1e480f790d70eadf62a422cb3cda6ebd Mon Sep 17 00:00:00 2001 From: Bagatur <22008038+baskaryan@users.noreply.github.com> Date: Tue, 3 Sep 2024 23:36:08 -0700 Subject: [PATCH 16/18] Update libs/partners/openai/langchain_openai/llms/azure.py --- libs/partners/openai/langchain_openai/llms/azure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/partners/openai/langchain_openai/llms/azure.py b/libs/partners/openai/langchain_openai/llms/azure.py index f9491d789b48a..90c20c9d4d7d0 100644 --- a/libs/partners/openai/langchain_openai/llms/azure.py +++ b/libs/partners/openai/langchain_openai/llms/azure.py @@ -156,7 +156,7 @@ def validate_environment(self) -> Self: **client_params, **sync_specific, # type: ignore[arg-type] ).completions - if not (self.async_client or None): + if not self.async_client: async_specific = {"http_client": self.http_async_client} self.async_client = openai.AsyncAzureOpenAI( **client_params, From c1ff61669d3e0d9558213ecb55bad6d55974de97 Mon Sep 17 00:00:00 2001 From: Bagatur <22008038+baskaryan@users.noreply.github.com> Date: Tue, 3 Sep 2024 23:36:14 -0700 Subject: [PATCH 17/18] Update libs/partners/openai/langchain_openai/llms/base.py --- libs/partners/openai/langchain_openai/llms/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/partners/openai/langchain_openai/llms/base.py b/libs/partners/openai/langchain_openai/llms/base.py index 248e7657466a0..b070de0b28b1f 100644 --- a/libs/partners/openai/langchain_openai/llms/base.py +++ b/libs/partners/openai/langchain_openai/llms/base.py @@ -187,7 +187,7 @@ def validate_environment(self) -> Self: "default_headers": self.default_headers, "default_query": self.default_query, } - if not (self.client or None): + if not self.client: sync_specific = {"http_client": self.http_client} self.client = openai.OpenAI(**client_params, **sync_specific).completions # type: ignore[arg-type] if not (self.async_client or None): From 4c7afb0d6c68b22963055d5fc85d09ec84b758cd Mon Sep 17 00:00:00 2001 From: Bagatur <22008038+baskaryan@users.noreply.github.com> Date: Tue, 3 Sep 2024 23:36:19 -0700 Subject: [PATCH 18/18] Update libs/partners/openai/langchain_openai/llms/base.py --- libs/partners/openai/langchain_openai/llms/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/partners/openai/langchain_openai/llms/base.py b/libs/partners/openai/langchain_openai/llms/base.py index b070de0b28b1f..0c773b347a60b 100644 --- a/libs/partners/openai/langchain_openai/llms/base.py +++ b/libs/partners/openai/langchain_openai/llms/base.py @@ -190,7 +190,7 @@ def validate_environment(self) -> Self: if not self.client: sync_specific = {"http_client": self.http_client} self.client = openai.OpenAI(**client_params, **sync_specific).completions # type: ignore[arg-type] - if not (self.async_client or None): + if not self.async_client: async_specific = {"http_client": self.http_async_client} self.async_client = openai.AsyncOpenAI( **client_params,