mirror of
https://github.com/langchain-ai/langchain.git
synced 2026-10-05 09:25:14 +03:00
feat(core): propagate gateway information on error path (#39829)
This PR plumbs through gateway metadata information for exceptions <img width="2380" height="956" alt="image" src="https://github.com/user-attachments/assets/c3b3644e-3022-421c-b447-6ab6603021e4" />
This commit is contained in:
1 parent
d8237e7492
commit
ed0ad742e9
2 files changed
+30
-3
No files matched your search
@@ -87,7 +87,10 @@ from langchain_core.tracers._streaming import (
|
||||
_StreamingCallbackHandler,
|
||||
_V2StreamingCallbackHandler,
|
||||
)
|
||||
from langchain_core.utils._gateway import GATEWAY_METADATA_RESPONSE_KEY
|
||||
from langchain_core.utils._gateway import (
|
||||
GATEWAY_METADATA_RESPONSE_KEY,
|
||||
_parse_gateway_metadata,
|
||||
)
|
||||
from langchain_core.utils.function_calling import (
|
||||
convert_to_json_schema,
|
||||
convert_to_openai_tool,
|
||||
@@ -110,6 +113,7 @@ def _generate_response_from_error(error: BaseException) -> list[ChatGeneration]:
|
||||
if hasattr(error, "response"):
|
||||
response = error.response
|
||||
metadata: dict[str, Any] = {}
|
||||
generation_info: dict[str, Any] = {}
|
||||
if hasattr(response, "json"):
|
||||
try:
|
||||
metadata["body"] = response.json()
|
||||
@@ -120,7 +124,11 @@ def _generate_response_from_error(error: BaseException) -> list[ChatGeneration]:
|
||||
metadata["body"] = None
|
||||
if hasattr(response, "headers"):
|
||||
try:
|
||||
metadata["headers"] = dict(response.headers)
|
||||
headers = response.headers
|
||||
metadata["headers"] = dict(headers)
|
||||
gateway_metadata = _parse_gateway_metadata(headers)
|
||||
if gateway_metadata is not None:
|
||||
generation_info[GATEWAY_METADATA_RESPONSE_KEY] = gateway_metadata
|
||||
except Exception:
|
||||
metadata["headers"] = None
|
||||
if hasattr(response, "status_code"):
|
||||
@@ -128,7 +136,10 @@ def _generate_response_from_error(error: BaseException) -> list[ChatGeneration]:
|
||||
if hasattr(error, "request_id"):
|
||||
metadata["request_id"] = error.request_id
|
||||
generations = [
|
||||
ChatGeneration(message=AIMessage(content="", response_metadata=metadata))
|
||||
ChatGeneration(
|
||||
message=AIMessage(content="", response_metadata=metadata),
|
||||
generation_info=generation_info or None,
|
||||
)
|
||||
]
|
||||
else:
|
||||
generations = []
|
||||
|
||||
@@ -54,6 +54,7 @@ from langchain_core.tracers.context import collect_runs
|
||||
from langchain_core.tracers.event_stream import _AstreamEventsCallbackHandler
|
||||
from langchain_core.tracers.langchain import LangChainTracer
|
||||
from langchain_core.tracers.schemas import Run
|
||||
from langchain_core.utils._gateway import GATEWAY_METADATA_RESPONSE_KEY
|
||||
from langchain_core.version import VERSION
|
||||
from tests.unit_tests.fake.callbacks import (
|
||||
BaseFakeCallbackHandler,
|
||||
@@ -1730,6 +1731,21 @@ def test_generate_response_from_error_with_valid_json() -> None:
|
||||
assert metadata["status_code"] == 400
|
||||
|
||||
|
||||
def test_generate_response_from_error_surfaces_gateway_metadata() -> None:
|
||||
"""Gateway metadata from an error response is available for tracing."""
|
||||
response = MockResponse(
|
||||
headers={"X-LangSmith-Gateway-Metadata": '{"outcome": "blocked"}'},
|
||||
)
|
||||
|
||||
generations = _generate_response_from_error(
|
||||
MockAPIError("API Error", response=response)
|
||||
)
|
||||
|
||||
assert generations[0].generation_info == {
|
||||
GATEWAY_METADATA_RESPONSE_KEY: {"outcome": "blocked"}
|
||||
}
|
||||
|
||||
|
||||
def test_generate_response_from_error_handles_streaming_response_failure() -> None:
|
||||
# Simulates scenario where accessing response.json() or response.text
|
||||
# raises ResponseNotRead on streaming responses
|
||||
|
||||
Reference in new issue
Block a user