mirror of
https://github.com/langchain-ai/langchain.git
synced 2026-10-05 09:25:14 +03:00
feat(core): Allow model name and provider tracing metadata override based on gateway response (#40406)
With custom configs, the actual model name and provider the gateway actually runs are different from what are requested. This reconciles clientside tracing.
This commit is contained in:
1 parent
67ee6cb63d
commit
e0e1557bd6
2 files changed
+96
-1
No files matched your search
@@ -356,6 +356,11 @@ class _TracerCore(ABC):
|
||||
return
|
||||
metadata = run.extra.setdefault("metadata", {})
|
||||
metadata[_GATEWAY_RUN_METADATA_KEY] = gateway_metadata
|
||||
# The resolved gateway identity takes precedence over request-time metadata.
|
||||
for source, target in (("model", "ls_model_name"), ("provider", "ls_provider")):
|
||||
value = gateway_metadata.get(source)
|
||||
if isinstance(value, str) and (value := value.strip()):
|
||||
metadata[target] = value
|
||||
|
||||
def _errored_llm_run(
|
||||
self, error: BaseException, run_id: UUID, response: LLMResult | None = None
|
||||
|
||||
@@ -4,6 +4,8 @@ from __future__ import annotations
|
||||
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from langchain_core.messages import AIMessage
|
||||
from langchain_core.messages.tool import ToolCall
|
||||
from langchain_core.outputs import ChatGeneration, LLMResult
|
||||
@@ -189,7 +191,11 @@ def test_complete_llm_run_attaches_gateway_metadata() -> None:
|
||||
|
||||
completed_run = tracer._complete_llm_run(response=response, run_id=run.id)
|
||||
|
||||
assert completed_run.extra["metadata"]["ls_gateway_info"] == gateway_info
|
||||
assert completed_run.extra["metadata"] == {
|
||||
"ls_gateway_info": gateway_info,
|
||||
"ls_model_name": gateway_info["model"],
|
||||
"ls_provider": gateway_info["provider"],
|
||||
}
|
||||
|
||||
|
||||
def test_complete_llm_run_no_gateway_metadata() -> None:
|
||||
@@ -230,3 +236,87 @@ def test_errored_llm_run_attaches_gateway_metadata() -> None:
|
||||
)
|
||||
|
||||
assert errored_run.extra["metadata"]["ls_gateway_info"] == gateway_info
|
||||
|
||||
|
||||
@pytest.mark.parametrize("errored", [False, True])
|
||||
@pytest.mark.parametrize(
|
||||
("gateway_info", "expected_identity"),
|
||||
[
|
||||
pytest.param(
|
||||
{"model": "resolved-model", "provider": "amazon_bedrock"},
|
||||
{"ls_model_name": "resolved-model", "ls_provider": "amazon_bedrock"},
|
||||
id="resolved-identity",
|
||||
),
|
||||
pytest.param(
|
||||
{"model": "resolved-model", "selected_model": "configured-model"},
|
||||
{"ls_model_name": "resolved-model"},
|
||||
id="model-only",
|
||||
),
|
||||
pytest.param(
|
||||
{"provider": "amazon_bedrock"},
|
||||
{"ls_provider": "amazon_bedrock"},
|
||||
id="provider-only",
|
||||
),
|
||||
pytest.param({}, {}, id="empty"),
|
||||
pytest.param({"error": "rate_limit_exceeded"}, {}, id="error-only"),
|
||||
pytest.param({"selected_model": "configured-model"}, {}, id="selected-only"),
|
||||
pytest.param({"model": None, "provider": None}, {}, id="null"),
|
||||
pytest.param({"model": "", "provider": ""}, {}, id="empty-strings"),
|
||||
pytest.param({"model": " \t\n", "provider": "\n "}, {}, id="whitespace-only"),
|
||||
pytest.param(
|
||||
{"model": " resolved-model\n", "provider": "\tamazon_bedrock "},
|
||||
{"ls_model_name": "resolved-model", "ls_provider": "amazon_bedrock"},
|
||||
id="surrounding-whitespace",
|
||||
),
|
||||
pytest.param({"model": 42, "provider": ["openai"]}, {}, id="invalid-types"),
|
||||
pytest.param(
|
||||
{"model": False, "provider": "amazon_bedrock"},
|
||||
{"ls_provider": "amazon_bedrock"},
|
||||
id="invalid-model-valid-provider",
|
||||
),
|
||||
pytest.param(
|
||||
{"model": "resolved-model", "provider": {}},
|
||||
{"ls_model_name": "resolved-model"},
|
||||
id="valid-model-invalid-provider",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_gateway_metadata_overrides_request_identity(
|
||||
gateway_info: dict[str, object],
|
||||
expected_identity: dict[str, str],
|
||||
*,
|
||||
errored: bool,
|
||||
) -> None:
|
||||
"""Only valid returned identity fields override request-time tracing metadata."""
|
||||
tracer = MockTracerCore()
|
||||
run = _make_run("test-gateway-identity-run-id")
|
||||
original_metadata = {
|
||||
"ls_model_name": "requested-model",
|
||||
"ls_provider": "openai",
|
||||
"custom": "preserved",
|
||||
}
|
||||
run.extra = {"metadata": original_metadata.copy()}
|
||||
tracer.run_map[str(run.id)] = run
|
||||
response = LLMResult(
|
||||
generations=[
|
||||
[
|
||||
ChatGeneration(
|
||||
message=AIMessage(content="Test"),
|
||||
generation_info={GATEWAY_METADATA_RESPONSE_KEY: gateway_info},
|
||||
)
|
||||
]
|
||||
]
|
||||
)
|
||||
|
||||
if errored:
|
||||
completed_run = tracer._errored_llm_run(
|
||||
error=ValueError("boom"), run_id=run.id, response=response
|
||||
)
|
||||
else:
|
||||
completed_run = tracer._complete_llm_run(response=response, run_id=run.id)
|
||||
|
||||
assert completed_run.extra["metadata"] == {
|
||||
**original_metadata,
|
||||
**expected_identity,
|
||||
"ls_gateway_info": gateway_info,
|
||||
}
|
||||
Reference in new issue
Block a user