langgraph: handle pydantic updates consistently in Command

This commit is contained in:
vbarda
2025-04-11 17:51:56 -04:00
parent d6f2f0c90d
commit dc6fa9ed30
2 changed files with 31 additions and 3 deletions
+2 -2
View File
@@ -764,14 +764,14 @@ class CompiledStateGraph(CompiledGraph):
updates.extend(_get_updates(i) or ())
return updates
elif (t := type(input)) and get_type_hints(t):
# Pydantic v2
# Pydantic v1
if isinstance(input, BaseModelV1):
keep: Optional[set[str]] = input.__fields_set__
defaults = {k: v.default for k, v in t.__fields__.items()}
# Pydantic v2
elif isinstance(input, BaseModel):
keep = input.model_fields_set
defaults = {k: v.default for k, v in input.model_fields.items()}
# Pydantic v1
else:
keep = None
defaults = {}
+29 -1
View File
@@ -20,6 +20,8 @@ from typing import (
)
from langchain_core.runnables import Runnable, RunnableConfig
from pydantic import BaseModel
from pydantic.v1 import BaseModel as BaseModelV1
from typing_extensions import Self
from langgraph.checkpoint.base import BaseCheckpointSaver, CheckpointMetadata
@@ -69,6 +71,11 @@ else:
_DC_KWARGS = {"frozen": True}
# NOTE: this is redefined here separately from langgraph.constants
# to avoid a circular import
MISSING = object()
def default_retry_on(exc: Exception) -> bool:
import httpx
import requests
@@ -318,7 +325,28 @@ class Command(Generic[N], ToolOutputMixin):
):
return self.update
elif hints := get_type_hints(type(self.update)):
return [(k, getattr(self.update, k)) for k in hints]
# Pydantic v1
if isinstance(self.update, BaseModelV1):
keep: Optional[set[str]] = self.update.__fields_set__
defaults = {k: v.default for k, v in self.update.__fields__.items()}
# Pydantic v2
elif isinstance(self.update, BaseModel):
keep = self.update.model_fields_set
defaults = {k: v.default for k, v in self.update.model_fields.items()}
else:
keep = None
defaults = {}
return [
(k, value)
for k in hints
if (value := getattr(self.update, k, MISSING)) is not MISSING
and (
value is not None
or defaults.get(k, MISSING) is not None
or (keep is not None and k in keep)
)
]
elif self.update is not None:
return [("__root__", self.update)]
else: