From fa2f6eceea7686a0db7140107187a2d8f3295576 Mon Sep 17 00:00:00 2001 From: Spectual Date: Fri, 8 May 2026 23:05:49 -0700 Subject: [PATCH] fix(langchain): read AzureOpenAI API version from openai_api_version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `_extract_model_name` for `AzureOpenAI` checks `serialized_kwargs["openai_api_version"]` to decide whether a version is available, then reads the value from `serialized_kwargs["deployment_version"]` (`langfuse/langchain/utils.py:73-74`). LangChain's `AzureOpenAI` doesn't expose a `deployment_version` field — only `openai_api_version` and `deployment_name` — so `deployment_version` is always `None`, the `isinstance(deployment_version, str)` check fails, and the function returns the bare deployment name with no version suffix. Read the value from the same key that gates the branch (`openai_api_version`). Combined with the deduplication logic added in PR #1203, deployments now produce `-` — matching the documented intent of this code path — while still collapsing if the deployment_name already embeds the version. Add `tests/unit/test_extract_model_name.py` with three regression cases: api_version present, api_version absent, and the dedup path from #1203. --- langfuse/langchain/utils.py | 6 +++- tests/unit/test_extract_model_name.py | 47 +++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 tests/unit/test_extract_model_name.py diff --git a/langfuse/langchain/utils.py b/langfuse/langchain/utils.py index 544bcf957..d39562f79 100644 --- a/langfuse/langchain/utils.py +++ b/langfuse/langchain/utils.py @@ -70,8 +70,12 @@ def _extract_model_name( serialized_kwargs = serialized.get("kwargs") if serialized_kwargs and isinstance(serialized_kwargs, dict): + # LangChain's AzureOpenAI exposes the API version under + # `openai_api_version`, not `deployment_version` — the latter + # is never populated, so previously the version suffix was + # dropped from the resulting model name. if serialized_kwargs.get("openai_api_version"): - deployment_version = serialized_kwargs.get("deployment_version") + deployment_version = serialized_kwargs.get("openai_api_version") if serialized_kwargs.get("deployment_name"): deployment_name = serialized_kwargs.get("deployment_name") diff --git a/tests/unit/test_extract_model_name.py b/tests/unit/test_extract_model_name.py new file mode 100644 index 000000000..4f9f0869e --- /dev/null +++ b/tests/unit/test_extract_model_name.py @@ -0,0 +1,47 @@ +"""Unit tests for ``langfuse.langchain.utils._extract_model_name``.""" + +from langfuse.langchain.utils import _extract_model_name + + +def _azure_openai_serialized( + *, deployment_name: str, openai_api_version: str | None +) -> dict: + """Build a minimal ``serialized`` dict mirroring what LangChain emits for AzureOpenAI.""" + kwargs: dict = {"deployment_name": deployment_name} + if openai_api_version is not None: + kwargs["openai_api_version"] = openai_api_version + return {"id": ["langchain", "llms", "openai", "AzureOpenAI"], "kwargs": kwargs} + + +def test_azure_openai_returns_deployment_name_with_api_version_suffix(): + """Regression: ``openai_api_version`` should be appended to the deployment name. + + Previously the code read the value from a non-existent ``deployment_version`` + key after checking that ``openai_api_version`` was set, so the suffix was + silently dropped. + """ + serialized = _azure_openai_serialized( + deployment_name="my-deployment", + openai_api_version="2024-02-15-preview", + ) + assert _extract_model_name(serialized) == "my-deployment-2024-02-15-preview" + + +def test_azure_openai_returns_bare_deployment_name_when_no_api_version(): + serialized = _azure_openai_serialized( + deployment_name="my-deployment", + openai_api_version=None, + ) + assert _extract_model_name(serialized) == "my-deployment" + + +def test_azure_openai_no_duplicate_version_suffix(): + """If the deployment_name already contains the version, don't append it again. + + This guards the existing behavior introduced in PR #1203. + """ + serialized = _azure_openai_serialized( + deployment_name="my-deployment-2024-02-15-preview", + openai_api_version="2024-02-15-preview", + ) + assert _extract_model_name(serialized) == "my-deployment-2024-02-15-preview"