|
7 | 7 | from collections.abc import Sequence |
8 | 8 | from dataclasses import asdict, is_dataclass |
9 | 9 | from datetime import date, datetime |
| 10 | +from functools import lru_cache |
10 | 11 | from json import JSONEncoder |
11 | 12 | from logging import getLogger |
12 | 13 | from pathlib import Path |
13 | | -from typing import Any |
| 14 | +from typing import Any, Optional, Type |
14 | 15 | from uuid import UUID |
15 | 16 |
|
16 | 17 | from pydantic import BaseModel |
17 | 18 |
|
18 | 19 | from langfuse.media import LangfuseMedia |
19 | 20 |
|
20 | | -# Attempt to import Serializable |
21 | | -try: |
22 | | - from langchain_core.load.serializable import Serializable |
23 | | -except ImportError: |
24 | | - # If Serializable is not available, set it to a placeholder type |
25 | | - class Serializable: # type: ignore |
26 | | - pass |
| 21 | + |
| 22 | +@lru_cache(maxsize=1) |
| 23 | +def _get_langchain_serializable_type() -> Optional[Type[Any]]: |
| 24 | + """Best-effort lookup of LangChain's Serializable base class. |
| 25 | +
|
| 26 | + Import lazily to avoid import-time side effects from optional langchain |
| 27 | + dependencies, including Python 3.14 warning-as-error failures triggered by |
| 28 | + transitive `pydantic.v1` imports. |
| 29 | + """ |
| 30 | + |
| 31 | + try: |
| 32 | + from langchain_core.load.serializable import Serializable |
| 33 | + |
| 34 | + return Serializable |
| 35 | + except Exception: |
| 36 | + return None |
27 | 37 |
|
28 | 38 |
|
29 | 39 | # Attempt to import numpy |
@@ -109,8 +119,8 @@ def default(self, obj: Any) -> Any: |
109 | 119 | if isinstance(obj, Path): |
110 | 120 | return str(obj) |
111 | 121 |
|
112 | | - # if langchain is not available, the Serializable type is NoneType |
113 | | - if Serializable is not type(None) and isinstance(obj, Serializable): # type: ignore |
| 122 | + serializable_type = _get_langchain_serializable_type() |
| 123 | + if serializable_type is not None and isinstance(obj, serializable_type): |
114 | 124 | return obj.to_json() |
115 | 125 |
|
116 | 126 | # 64-bit integers might overflow the JavaScript safe integer range. |
|
0 commit comments