[docs]classReviver:"""Reviver for JSON objects."""
[docs]def__init__(self,secrets_map:Optional[Dict[str,str]]=None,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_envself.secrets_map=secrets_mapordict()# By default only support langchain, but user can pass in additional namespacesself.valid_namespaces=([*DEFAULT_NAMESPACES,*valid_namespaces]ifvalid_namespaceselseDEFAULT_NAMESPACES)
def__call__(self,value:Dict[str,Any])->Any:if(value.get("lc",None)==1andvalue.get("type",None)=="secret"andvalue.get("id",None)isnotNone):[key]=value["id"]ifkeyinself.secrets_map:returnself.secrets_map[key]else:ifself.secrets_from_envandkeyinos.environandos.environ[key]:returnos.environ[key]raiseKeyError(f'Missing key "{key}" in load(secrets_map)')if(value.get("lc",None)==1andvalue.get("type",None)=="not_implemented"andvalue.get("id",None)isnotNone):raiseNotImplementedError("Trying to load an object that doesn't implement "f"serialization: {value}")if(value.get("lc",None)==1andvalue.get("type",None)=="constructor"andvalue.get("id",None)isnotNone):[*namespace,name]=value["id"]ifnamespace[0]notinself.valid_namespaces:raiseValueError(f"Invalid namespace: {value}")# The root namespace "langchain" is not a valid identifier.iflen(namespace)==1andnamespace[0]=="langchain":raiseValueError(f"Invalid namespace: {value}")# If namespace is in known namespaces, try to use mappingifnamespace[0]inDEFAULT_NAMESPACES:# Get the importable pathkey=tuple(namespace+[name])ifkeynotinALL_SERIALIZABLE_MAPPINGS:raiseValueError("Trying to deserialize something that cannot ""be deserialized in current version of langchain-core: "f"{key}")import_path=ALL_SERIALIZABLE_MAPPINGS[key]# Split into module and nameimport_dir,import_obj=import_path[:-1],import_path[-1]# Import modulemod=importlib.import_module(".".join(import_dir))# Import classcls=getattr(mod,import_obj)# Otherwise, load by pathelse:mod=importlib.import_module(".".join(namespace))cls=getattr(mod,name)# The class must be a subclass of Serializable.ifnotissubclass(cls,Serializable):raiseValueError(f"Invalid namespace: {value}")# We don't need to recurse on kwargs# as json.loads will do that for us.kwargs=value.get("kwargs",dict())returncls(**kwargs)returnvalue
[docs]@beta()defloads(text:str,*,secrets_map:Optional[Dict[str,str]]=None,valid_namespaces:Optional[List[str]]=None,secrets_from_env:bool=True,)->Any:"""Revive a LangChain class from a JSON string. Equivalent to `load(json.loads(text))`. Args: text: The string 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. Defaults to None. secrets_from_env: Whether to load secrets from the environment. Defaults to True. Returns: Revived LangChain objects. """returnjson.loads(text,object_hook=Reviver(secrets_map,valid_namespaces,secrets_from_env))
[docs]@beta()defload(obj:Any,*,secrets_map:Optional[Dict[str,str]]=None,valid_namespaces:Optional[List[str]]=None,secrets_from_env:bool=True,)->Any:"""Revive a LangChain class from a JSON object. Use this if you already have a parsed JSON object, eg. from `json.load` or `orjson.loads`. Args: obj: The object 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. Defaults to None. secrets_from_env: Whether to load secrets from the environment. Defaults to True. Returns: Revived LangChain objects. """reviver=Reviver(secrets_map,valid_namespaces,secrets_from_env)def_load(obj:Any)->Any:ifisinstance(obj,dict):# Need to revive leaf nodes before reviving this nodeloaded_obj={k:_load(v)fork,vinobj.items()}returnreviver(loaded_obj)ifisinstance(obj,list):return[_load(o)foroinobj]returnobjreturn_load(obj)