UNPKG

@langchain/core

Version:
1 lines 11.4 kB
{"version":3,"file":"serializable.cjs","names":["escapeIfNeeded","mapKeys","keyToJson"],"sources":["../../src/load/serializable.ts"],"sourcesContent":["import { type SerializedFields, keyToJson, mapKeys } from \"./map_keys.js\";\nimport { escapeIfNeeded } from \"./validation.js\";\n\nexport interface BaseSerialized<T extends string> {\n lc: number;\n type: T;\n id: string[];\n name?: string;\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n graph?: Record<string, any>;\n}\n\nexport interface SerializedConstructor extends BaseSerialized<\"constructor\"> {\n kwargs: SerializedFields;\n}\n\nexport interface SerializedSecret extends BaseSerialized<\"secret\"> {}\n\nexport interface SerializedNotImplemented extends BaseSerialized<\"not_implemented\"> {}\n\nexport type Serialized =\n | SerializedConstructor\n | SerializedSecret\n | SerializedNotImplemented;\n\nfunction shallowCopy<T extends object>(obj: T): T {\n return Array.isArray(obj) ? ([...obj] as T) : ({ ...obj } as T);\n}\n\nfunction replaceSecrets(\n root: SerializedFields,\n secretsMap: { [key: string]: string }\n): SerializedFields {\n const result = shallowCopy(root);\n for (const [path, secretId] of Object.entries(secretsMap)) {\n const [last, ...partsReverse] = path.split(\".\").reverse();\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n let current: any = result;\n for (const part of partsReverse.reverse()) {\n if (current[part] === undefined) {\n break;\n }\n current[part] = shallowCopy(current[part]);\n current = current[part];\n }\n if (current[last] !== undefined) {\n current[last] = {\n lc: 1,\n type: \"secret\",\n id: [secretId],\n };\n }\n }\n return result;\n}\n\n/**\n * Get a unique name for the module, rather than parent class implementations.\n * Should not be subclassed, subclass lc_name above instead.\n */\nexport function get_lc_unique_name(\n serializableClass: typeof Serializable\n): string {\n // \"super\" here would refer to the parent class of Serializable,\n // when we want the parent class of the module actually calling this method.\n const parentClass = Object.getPrototypeOf(serializableClass);\n const lcNameIsSubclassed =\n typeof serializableClass.lc_name === \"function\" &&\n (typeof parentClass.lc_name !== \"function\" ||\n serializableClass.lc_name() !== parentClass.lc_name());\n if (lcNameIsSubclassed) {\n return serializableClass.lc_name();\n } else {\n return serializableClass.name;\n }\n}\n\n/**\n * Interface for objects that can be serialized.\n * This is a duck-typed interface to avoid circular imports.\n */\nexport interface SerializableLike {\n lc_serializable: boolean;\n lc_secrets?: Record<string, string>;\n toJSON(): {\n lc: number;\n type: string;\n id: string[];\n kwargs?: Record<string, unknown>;\n };\n}\n\nexport interface SerializableInterface {\n get lc_id(): string[];\n}\n\nexport abstract class Serializable implements SerializableInterface {\n lc_serializable = false;\n\n lc_kwargs: SerializedFields;\n\n /**\n * A path to the module that contains the class, eg. [\"langchain\", \"llms\"]\n * Usually should be the same as the entrypoint the class is exported from.\n */\n abstract lc_namespace: string[];\n\n /**\n * The name of the serializable. Override to provide an alias or\n * to preserve the serialized module name in minified environments.\n *\n * Implemented as a static method to support loading logic.\n */\n static lc_name(): string {\n return this.name;\n }\n\n /**\n * The final serialized identifier for the module.\n */\n get lc_id(): string[] {\n return [\n ...this.lc_namespace,\n get_lc_unique_name(this.constructor as typeof Serializable),\n ];\n }\n\n /**\n * A map of secrets, which will be omitted from serialization.\n * Keys are paths to the secret in constructor args, e.g. \"foo.bar.baz\".\n * Values are the secret ids, which will be used when deserializing.\n */\n get lc_secrets(): { [key: string]: string } | undefined {\n return undefined;\n }\n\n /**\n * A map of additional attributes to merge with constructor args.\n * Keys are the attribute names, e.g. \"foo\".\n * Values are the attribute values, which will be serialized.\n * These attributes need to be accepted by the constructor as arguments.\n */\n get lc_attributes(): SerializedFields | undefined {\n return undefined;\n }\n\n /**\n * A map of aliases for constructor args.\n * Keys are the attribute names, e.g. \"foo\".\n * Values are the alias that will replace the key in serialization.\n * This is used to eg. make argument names match Python.\n */\n get lc_aliases(): { [key: string]: string } | undefined {\n return undefined;\n }\n\n /**\n * A manual list of keys that should be serialized.\n * If not overridden, all fields passed into the constructor will be serialized.\n */\n get lc_serializable_keys(): string[] | undefined {\n return undefined;\n }\n\n constructor(kwargs?: SerializedFields, ..._args: never[]) {\n if (this.lc_serializable_keys !== undefined) {\n this.lc_kwargs = Object.fromEntries(\n Object.entries(kwargs || {}).filter(([key]) =>\n this.lc_serializable_keys?.includes(key)\n )\n );\n } else {\n this.lc_kwargs = kwargs ?? {};\n }\n }\n\n toJSON(): Serialized {\n if (!this.lc_serializable) {\n return this.toJSONNotImplemented();\n }\n if (\n // oxlint-disable-next-line no-instanceof/no-instanceof\n this.lc_kwargs instanceof Serializable ||\n typeof this.lc_kwargs !== \"object\" ||\n Array.isArray(this.lc_kwargs)\n ) {\n // We do not support serialization of classes with arg not a POJO\n // I'm aware the check above isn't as strict as it could be\n return this.toJSONNotImplemented();\n }\n\n const aliases: { [key: string]: string } = {};\n const secrets: { [key: string]: string } = {};\n const kwargs = Object.keys(this.lc_kwargs).reduce((acc, key) => {\n acc[key] = key in this ? this[key as keyof this] : this.lc_kwargs[key];\n return acc;\n }, {} as SerializedFields);\n // get secrets, attributes and aliases from all superclasses\n for (\n let current = Object.getPrototypeOf(this);\n current;\n current = Object.getPrototypeOf(current)\n ) {\n Object.assign(aliases, Reflect.get(current, \"lc_aliases\", this));\n Object.assign(secrets, Reflect.get(current, \"lc_secrets\", this));\n Object.assign(kwargs, Reflect.get(current, \"lc_attributes\", this));\n }\n\n // include all secrets used, even if not in kwargs,\n // will be replaced with sentinel value in replaceSecrets\n Object.keys(secrets).forEach((keyPath) => {\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n let read: any = this;\n\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n let write: any = kwargs;\n\n const [last, ...partsReverse] = keyPath.split(\".\").reverse();\n for (const key of partsReverse.reverse()) {\n if (!(key in read) || read[key] === undefined) return;\n if (!(key in write) || write[key] === undefined) {\n if (typeof read[key] === \"object\" && read[key] != null) {\n write[key] = {};\n } else if (Array.isArray(read[key])) {\n write[key] = [];\n }\n }\n\n read = read[key];\n write = write[key];\n }\n\n if (last in read && read[last] !== undefined) {\n write[last] = write[last] || read[last];\n }\n });\n\n const escapedKwargs: SerializedFields = {};\n // Track current path to detect circular references (but not shared references)\n // The Serializable object itself stays in the path to detect self-references in kwargs\n const pathSet = new WeakSet<object>();\n pathSet.add(this);\n for (const [key, value] of Object.entries(kwargs)) {\n escapedKwargs[key] = escapeIfNeeded(value, pathSet);\n }\n\n // Now add secret markers - these are added AFTER escaping so they won't be escaped\n const kwargsWithSecrets = Object.keys(secrets).length\n ? replaceSecrets(escapedKwargs, secrets)\n : escapedKwargs;\n\n // Finally transform keys to JSON format\n const processedKwargs = mapKeys(kwargsWithSecrets, keyToJson, aliases);\n\n return {\n lc: 1,\n type: \"constructor\",\n id: this.lc_id,\n kwargs: processedKwargs,\n };\n }\n\n toJSONNotImplemented(): SerializedNotImplemented {\n return {\n lc: 1,\n type: \"not_implemented\",\n id: this.lc_id,\n };\n }\n}\n"],"mappings":"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"}