diff --git a/.github/DISCUSSION_TEMPLATE/q-a.yml b/.github/DISCUSSION_TEMPLATE/q-a.yml index ba63d7250d067..d0229b2d7bd10 100644 --- a/.github/DISCUSSION_TEMPLATE/q-a.yml +++ b/.github/DISCUSSION_TEMPLATE/q-a.yml @@ -96,22 +96,27 @@ body: - type: textarea id: system-info attributes: + label: System Info description: | - Please share your system info with us. Do NOT skip this step and please don't trim - the output. Most users don't include enough information here and it makes it harder - for us to help you. + Please share your system info with us. - Run the following command in your terminal and paste the output here: + "pip freeze | grep langchain" + platform (windows / linux / mac) + python version - python -m langchain_core.sys_info + OR if you're on a recent version of langchain-core you can paste the output of: - or if you have an existing python interpreter running: + python -m langchain_core.sys_info + placeholder: | + "pip freeze | grep langchain" + platform + python version - from langchain_core import sys_info - sys_info.print_sys_info() + Alternatively, if you're on a recent version of langchain-core you can paste the output of: - alternatively, put the entire output of `pip freeze` here. - placeholder: | python -m langchain_core.sys_info + + These will only surface LangChain packages, don't forget to include any other relevant + packages you're using (if you're not sure what's relevant, you can paste the entire output of `pip freeze`). validations: required: true diff --git a/libs/core/langchain_core/load/load.py b/libs/core/langchain_core/load/load.py index ba150a5a0095b..0fe91975c469b 100644 --- a/libs/core/langchain_core/load/load.py +++ b/libs/core/langchain_core/load/load.py @@ -19,6 +19,17 @@ "langchain_anthropic", "langchain_groq", "langchain_google_genai", + "langchain_aws", + "langchain_openai", + "langchain_google_vertexai", + "langchain_mistralai", + "langchain_fireworks", +] +# Namespaces for which only deserializing via the SERIALIZABLE_MAPPING is allowed. +# Load by path is not allowed. +DISALLOW_LOAD_FROM_PATH = [ + "langchain_community", + "langchain", ] ALL_SERIALIZABLE_MAPPINGS = { @@ -103,40 +114,31 @@ def __call__(self, value: dict[str, Any]) -> Any: and value.get("id", None) is not None ): [*namespace, name] = value["id"] + mapping_key = tuple(value["id"]) if namespace[0] not in self.valid_namespaces: raise ValueError(f"Invalid namespace: {value}") - - # The root namespace "langchain" is not a valid identifier. - if len(namespace) == 1 and namespace[0] == "langchain": + # The root namespace ["langchain"] is not a valid identifier. + elif namespace == ["langchain"]: raise ValueError(f"Invalid namespace: {value}") - - # If namespace is in known namespaces, try to use mapping - key = tuple(namespace + [name]) - if namespace[0] in DEFAULT_NAMESPACES: - # Get the importable path - if key not in self.import_mappings: - raise ValueError( - "Trying to deserialize something that cannot " - "be deserialized in current version of langchain-core: " - f"{key}" - ) - import_path = self.import_mappings[key] + # Has explicit import path. + elif mapping_key in self.import_mappings: + import_path = self.import_mappings[mapping_key] # Split into module and name - import_dir, import_obj = import_path[:-1], import_path[-1] + import_dir, name = import_path[:-1], import_path[-1] # Import module mod = importlib.import_module(".".join(import_dir)) - # Import class - cls = getattr(mod, import_obj) - # Otherwise, load by path + elif namespace[0] in DISALLOW_LOAD_FROM_PATH: + raise ValueError( + "Trying to deserialize something that cannot " + "be deserialized in current version of langchain-core: " + f"{mapping_key}." + ) + # Otherwise, treat namespace as path. else: - if key in self.additional_import_mappings: - import_path = self.import_mappings[key] - mod = importlib.import_module(".".join(import_path[:-1])) - name = import_path[-1] - else: - mod = importlib.import_module(".".join(namespace)) - cls = getattr(mod, name) + mod = importlib.import_module(".".join(namespace)) + + cls = getattr(mod, name) # The class must be a subclass of Serializable. if not issubclass(cls, Serializable): diff --git a/libs/core/langchain_core/load/mapping.py b/libs/core/langchain_core/load/mapping.py index 17e50947f3ca5..d3863e65759ea 100644 --- a/libs/core/langchain_core/load/mapping.py +++ b/libs/core/langchain_core/load/mapping.py @@ -1026,4 +1026,24 @@ "image", "ImagePromptTemplate", ), + ("langchain", "chat_models", "bedrock", "ChatBedrock"): ( + "langchain_aws", + "chat_models", + "ChatBedrock", + ), + ("langchain", "chat_models", "google_genai", "ChatGoogleGenerativeAI"): ( + "langchain_google_genai", + "chat_models", + "ChatGoogleGenerativeAI", + ), + ("langchain", "chat_models", "groq", "ChatGroq"): ( + "langchain_groq", + "chat_models", + "ChatGroq", + ), + ("langchain", "chat_models", "bedrock", "BedrockChat"): ( + "langchain_aws", + "chat_models", + "ChatBedrock", + ), } diff --git a/libs/core/pyproject.toml b/libs/core/pyproject.toml index bdece6d32d1f6..62e4c463b1ce9 100644 --- a/libs/core/pyproject.toml +++ b/libs/core/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "langchain-core" -version = "0.3.1" +version = "0.3.2" description = "Building applications with LLMs through composability" authors = [] license = "MIT" @@ -18,6 +18,9 @@ disallow_untyped_defs = "True" module = [ "numpy", "pytest",] ignore_missing_imports = true +[tool.ruff] +target-version = "py39" + [tool.poetry.urls] "Source Code" = "https://github.com/langchain-ai/langchain/tree/master/libs/core" "Release Notes" = "https://github.com/langchain-ai/langchain/releases?q=tag%3A%22langchain-core%3D%3D0%22&expanded=true" @@ -40,20 +43,9 @@ python = ">=3.12.4" [tool.poetry.extras] -[tool.ruff] -target-version = "py39" - [tool.ruff.lint] -select = ["B", "E", "F", "I", "N", "T201", "UP"] -ignore = ["UP007"] - -[tool.ruff.lint.pep8-naming] -classmethod-decorators = [ - "classmethod", - "langchain_core.utils.pydantic.pre_init", - "pydantic.field_validator", - "pydantic.v1.root_validator", -] +select = [ "B", "E", "F", "I", "N", "T201", "UP",] +ignore = [ "UP007",] [tool.coverage.run] omit = [ "tests/*",] @@ -79,6 +71,9 @@ optional = true [tool.poetry.group.test_integration] optional = true +[tool.ruff.lint.pep8-naming] +classmethod-decorators = [ "classmethod", "langchain_core.utils.pydantic.pre_init", "pydantic.field_validator", "pydantic.v1.root_validator",] + [tool.ruff.lint.per-file-ignores] "tests/unit_tests/prompts/test_chat.py" = [ "E501",] "tests/unit_tests/runnables/test_runnable.py" = [ "E501",]