From 77f5fc3d5520360214ebb98e7ce2bae36becdf84 Mon Sep 17 00:00:00 2001 From: Leonid Ganeline Date: Fri, 5 Jul 2024 09:23:19 -0700 Subject: [PATCH] core: docstrings `load` (#23787) Added missed docstrings. Formatted docstrings to the consistent form. --- libs/core/langchain_core/load/dump.py | 19 ++++-- libs/core/langchain_core/load/load.py | 27 ++++++-- libs/core/langchain_core/load/serializable.py | 67 +++++++++++++++---- 3 files changed, 93 insertions(+), 20 deletions(-) diff --git a/libs/core/langchain_core/load/dump.py b/libs/core/langchain_core/load/dump.py index 941be0ae253..df21f13b978 100644 --- a/libs/core/langchain_core/load/dump.py +++ b/libs/core/langchain_core/load/dump.py @@ -6,7 +6,14 @@ from langchain_core.load.serializable import Serializable, to_json_not_implement def default(obj: Any) -> Any: """Return a default value for a Serializable object or - a SerializedNotImplemented object.""" + a SerializedNotImplemented object. + + Args: + obj: The object to serialize to json if it is a Serializable object. + + Returns: + A json serializable object or a SerializedNotImplemented object. + """ if isinstance(obj, Serializable): return obj.to_json() else: @@ -17,13 +24,17 @@ def dumps(obj: Any, *, pretty: bool = False, **kwargs: Any) -> str: """Return a json string representation of an object. Args: - obj: The object to dump + obj: The object to dump. pretty: Whether to pretty print the json. If true, the json will be - indented with 2 spaces (if no indent is provided as part of kwargs) + indented with 2 spaces (if no indent is provided as part of kwargs). + Default is False. **kwargs: Additional arguments to pass to json.dumps Returns: - A json string representation of the object + A json string representation of the object. + + Raises: + ValueError: If `default` is passed as a kwarg. """ if "default" in kwargs: raise ValueError("`default` should not be passed to dumps") diff --git a/libs/core/langchain_core/load/load.py b/libs/core/langchain_core/load/load.py index ec5c67f2a08..f7db2ff6f02 100644 --- a/libs/core/langchain_core/load/load.py +++ b/libs/core/langchain_core/load/load.py @@ -36,6 +36,17 @@ class Reviver: valid_namespaces: Optional[List[str]] = None, secrets_from_env: bool = True, ) -> None: + """Initialize the reviver. + + Args: + secrets_map: A map of secrets to load. If a secret is not found in + the map, it will be loaded from the environment if `secrets_from_env` + is True. Defaults to None. + valid_namespaces: A list of additional namespaces (modules) + to allow to be deserialized. Defaults to None. + secrets_from_env: Whether to load secrets from the environment. + Defaults to True. + """ self.secrets_from_env = secrets_from_env self.secrets_map = secrets_map or dict() # By default only support langchain, but user can pass in additional namespaces @@ -130,9 +141,13 @@ def loads( Args: text: The string to load. - secrets_map: A map of secrets to load. + secrets_map: A map of secrets to load. If a secret is not found in + the map, it will be loaded from the environment if `secrets_from_env` + is True. Defaults to None. valid_namespaces: A list of additional namespaces (modules) - to allow to be deserialized. + to allow to be deserialized. Defaults to None. + secrets_from_env: Whether to load secrets from the environment. + Defaults to True. Returns: Revived LangChain objects. @@ -155,9 +170,13 @@ def load( Args: obj: The object to load. - secrets_map: A map of secrets to load. + secrets_map: A map of secrets to load. If a secret is not found in + the map, it will be loaded from the environment if `secrets_from_env` + is True. Defaults to None. valid_namespaces: A list of additional namespaces (modules) - to allow to be deserialized. + to allow to be deserialized. Defaults to None. + secrets_from_env: Whether to load secrets from the environment. + Defaults to True. Returns: Revived LangChain objects. diff --git a/libs/core/langchain_core/load/serializable.py b/libs/core/langchain_core/load/serializable.py index badc7ed0f06..0035a604ca4 100644 --- a/libs/core/langchain_core/load/serializable.py +++ b/libs/core/langchain_core/load/serializable.py @@ -16,7 +16,14 @@ from langchain_core.pydantic_v1 import BaseModel class BaseSerialized(TypedDict): - """Base class for serialized objects.""" + """Base class for serialized objects. + + Parameters: + lc: The version of the serialization format. + id: The unique identifier of the object. + name: The name of the object. Optional. + graph: The graph of the object. Optional. + """ lc: int id: List[str] @@ -25,20 +32,34 @@ class BaseSerialized(TypedDict): class SerializedConstructor(BaseSerialized): - """Serialized constructor.""" + """Serialized constructor. + + Parameters: + type: The type of the object. Must be "constructor". + kwargs: The constructor arguments. + """ type: Literal["constructor"] kwargs: Dict[str, Any] class SerializedSecret(BaseSerialized): - """Serialized secret.""" + """Serialized secret. + + Parameters: + type: The type of the object. Must be "secret". + """ type: Literal["secret"] class SerializedNotImplemented(BaseSerialized): - """Serialized not implemented.""" + """Serialized not implemented. + + Parameters: + type: The type of the object. Must be "not_implemented". + repr: The representation of the object. Optional. + """ type: Literal["not_implemented"] repr: Optional[str] @@ -50,10 +71,13 @@ def try_neq_default(value: Any, key: str, model: BaseModel) -> bool: Args: value: The value. key: The key. - model: The model. + model: The pydantic model. Returns: Whether the value is different from the default. + + Raises: + Exception: If the key is not in the model. """ try: return model.__fields__[key].get_default() != value @@ -69,23 +93,31 @@ class Serializable(BaseModel, ABC): It relies on the following methods and properties: - `is_lc_serializable`: Is this class serializable? - By design even if a class inherits from Serializable, it is not serializable by + By design, even if a class inherits from Serializable, it is not serializable by default. This is to prevent accidental serialization of objects that should not be serialized. - `get_lc_namespace`: Get the namespace of the langchain object. - During de-serialization this namespace is used to identify + During deserialization, this namespace is used to identify the correct class to instantiate. Please see the `Reviver` class in `langchain_core.load.load` for more details. - During de-serialization an additional mapping is handle + During deserialization an additional mapping is handle classes that have moved or been renamed across package versions. - `lc_secrets`: A map of constructor argument names to secret ids. - `lc_attributes`: List of additional attribute names that should be included - as part of the serialized representation.. + as part of the serialized representation. """ @classmethod def is_lc_serializable(cls) -> bool: - """Is this class serializable?""" + """Is this class serializable? + + By design, even if a class inherits from Serializable, it is not serializable by + default. This is to prevent accidental serialization of objects that should not + be serialized. + + Returns: + Whether the class is serializable. Default is False. + """ return False @classmethod @@ -111,6 +143,7 @@ class Serializable(BaseModel, ABC): """List of attribute names that should be included in the serialized kwargs. These attributes must be accepted by the constructor. + Default is an empty dictionary. """ return {} @@ -120,6 +153,8 @@ class Serializable(BaseModel, ABC): The unique identifier is a list of strings that describes the path to the object. + For example, for the class `langchain.llms.openai.OpenAI`, the id is + ["langchain", "llms", "openai", "OpenAI"]. """ return [*cls.get_lc_namespace(), cls.__name__] @@ -134,6 +169,11 @@ class Serializable(BaseModel, ABC): ] def to_json(self) -> Union[SerializedConstructor, SerializedNotImplemented]: + """Serialize the object to JSON. + + Returns: + A json serializable object or a SerializedNotImplemented object. + """ if not self.is_lc_serializable(): return self.to_json_not_implemented() @@ -209,7 +249,10 @@ def _is_field_useful(inst: Serializable, key: str, value: Any) -> bool: value: The value. Returns: - Whether the field is useful. + Whether the field is useful. If the field is required, it is useful. + If the field is not required, it is useful if the value is not None. + If the field is not required and the value is None, it is useful if the + default value is different from the value. """ field = inst.__fields__.get(key) if not field: @@ -242,7 +285,7 @@ def to_json_not_implemented(obj: object) -> SerializedNotImplemented: """Serialize a "not implemented" object. Args: - obj: object to serialize + obj: object to serialize. Returns: SerializedNotImplemented