Skip to content

Commit

Permalink
Move to langgraph.utils.fields
Browse files Browse the repository at this point in the history
  • Loading branch information
dqbd committed Dec 10, 2024
1 parent b4f1192 commit 1f68bd0
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 42 deletions.
41 changes: 1 addition & 40 deletions libs/langgraph/langgraph/pregel/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,13 @@
AsyncIterator,
Callable,
Dict,
Generator,
Iterator,
Mapping,
Optional,
Sequence,
Type,
Union,
cast,
get_type_hints,
overload,
)
from uuid import UUID, uuid5
Expand Down Expand Up @@ -118,6 +116,7 @@
patch_config,
patch_configurable,
)
from langgraph.utils.fields import get_enhanced_type_hints
from langgraph.utils.pydantic import create_model
from langgraph.utils.queue import AsyncQueue, SyncQueue # type: ignore[attr-defined]

Expand Down Expand Up @@ -309,44 +308,6 @@ def validate(self) -> Self:

@property
def config_specs(self) -> list[ConfigurableFieldSpec]:
# TODO: shouldn't this be in langchain_core?
def get_enhanced_type_hints(
type: Type[Any],
) -> Generator[tuple[str, Any, Any, Optional[str]], None]:
"""Attempt to extract default values and descriptions from provided config spec"""
for name, typ in get_type_hints(type).items():
default = None
description = None

# Pydantic models
try:
if hasattr(type, "__fields__") and name in type.__fields__:
field = type.__fields__[name]

if (
hasattr(field, "description")
and field.description is not None
):
description = field.description

if hasattr(field, "default") and field.default is not None:
default = field.default

except (AttributeError, KeyError, TypeError):
pass

# TypedDict, dataclass
try:
if hasattr(type, "__dict__"):
type_dict = getattr(type, "__dict__")

if name in type_dict:
default = type_dict[name]
except (AttributeError, KeyError, TypeError):
pass

yield name, typ, default, description

return [
spec
for spec in get_unique_config_specs(
Expand Down
2 changes: 1 addition & 1 deletion libs/langgraph/langgraph/pregel/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Optional
from typing import Any, Generator, Optional, Type, get_type_hints

from langchain_core.runnables import RunnableLambda, RunnableSequence
from langchain_core.runnables.utils import get_function_nonlocals
Expand Down
37 changes: 36 additions & 1 deletion libs/langgraph/langgraph/utils/fields.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import dataclasses
from typing import Any, Optional, Type, Union
from typing import Any, Generator, Optional, Type, Union, get_type_hints

from typing_extensions import Annotated, NotRequired, ReadOnly, Required, get_origin

Expand Down Expand Up @@ -106,3 +106,38 @@ def get_field_default(name: str, type_: Any, schema: Type[Any]) -> Any:
if _is_optional_type(type_):
return None
return ...


def get_enhanced_type_hints(
type: Type[Any],
) -> Generator[tuple[str, Any, Any, Optional[str]], None]:
"""Attempt to extract default values and descriptions from provided type, used for config schema."""
for name, typ in get_type_hints(type).items():
default = None
description = None

# Pydantic models
try:
if hasattr(type, "__fields__") and name in type.__fields__:
field = type.__fields__[name]

if hasattr(field, "description") and field.description is not None:
description = field.description

if hasattr(field, "default") and field.default is not None:
default = field.default

except (AttributeError, KeyError, TypeError):
pass

# TypedDict, dataclass
try:
if hasattr(type, "__dict__"):
type_dict = getattr(type, "__dict__")

if name in type_dict:
default = type_dict[name]
except (AttributeError, KeyError, TypeError):
pass

yield name, typ, default, description

0 comments on commit 1f68bd0

Please sign in to comment.