diff --git a/libs/core/langchain_core/language_models/base.py b/libs/core/langchain_core/language_models/base.py index 2d185392310..41c29fd23c9 100644 --- a/libs/core/langchain_core/language_models/base.py +++ b/libs/core/langchain_core/language_models/base.py @@ -183,8 +183,8 @@ class BaseLanguageModel( """Pydantic V2 lifecycle hook called automatically after `__init__`. Seeds `metadata["versions"]` with the installed `langchain-core` - version so that every LLM trace carries the package version that - produced it. + (and `langchain`, if installed) versions so that every LLM trace + carries the package versions that produced it. Partner packages should **not** override this method. Instead, they should define a `@model_validator(mode="after")` that calls @@ -206,6 +206,13 @@ class BaseLanguageModel( self._add_version("langchain-core", VERSION) + try: + from importlib.metadata import version as pkg_version # noqa: PLC0415 + + self._add_version("langchain", pkg_version("langchain")) + except Exception: # noqa: S110 + pass + def _add_version(self, pkg: str, version: str) -> None: """Record a package version in `metadata.versions` for tracing. @@ -216,7 +223,13 @@ class BaseLanguageModel( Example resulting metadata: ```python - {"versions": {"langchain-core": "1.x.x", "langchain-openai": "1.x.x"}} + { + "versions": { + "langchain-core": "1.x.x", + "langchain": "1.x.x", + "langchain-openai": "1.x.x", + } + } ``` Args: diff --git a/libs/core/tests/unit_tests/language_models/chat_models/test_base.py b/libs/core/tests/unit_tests/language_models/chat_models/test_base.py index 99d481e182a..516d8c3646d 100644 --- a/libs/core/tests/unit_tests/language_models/chat_models/test_base.py +++ b/libs/core/tests/unit_tests/language_models/chat_models/test_base.py @@ -1312,6 +1312,36 @@ def test_add_version_with_non_dict_versions() -> None: assert "langchain-core" in llm.metadata["versions"] +def test_langchain_version_in_metadata(monkeypatch: pytest.MonkeyPatch) -> None: + """When `langchain` is installed, its version appears in metadata.""" + monkeypatch.setattr( + "importlib.metadata.version", + lambda pkg: ( + "1.2.13" + if pkg == "langchain" + else (_ for _ in ()).throw(Exception(f"not found: {pkg}")) + ), + ) + llm = FakeListChatModel(responses=["x"]) + assert llm.metadata is not None + assert llm.metadata["versions"]["langchain"] == "1.2.13" + assert "langchain-core" in llm.metadata["versions"] + + +def test_langchain_version_missing_when_not_installed( + monkeypatch: pytest.MonkeyPatch, +) -> None: + """When `langchain` is not installed, metadata.versions has no entry.""" + monkeypatch.setattr( + "importlib.metadata.version", + lambda pkg: (_ for _ in ()).throw(Exception(f"not found: {pkg}")), + ) + llm = FakeListChatModel(responses=["x"]) + assert llm.metadata is not None + assert "langchain" not in llm.metadata["versions"] + assert "langchain-core" in llm.metadata["versions"] + + def test_model_profiles() -> None: model = GenericFakeChatModel(messages=iter([])) assert model.profile is None