mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-08-17 21:25:46 +02:00
Remove Checkpoint.writes
- This has been superseded by saving the individual writes of each task through put_writes() - Removing this speeds up checkpoint operations as it was duplicating data saved elsewhere already
This commit is contained in:
@@ -181,11 +181,11 @@ class PostgresSaver(BasePostgresSaver):
|
||||
"checkpoint_id": value["checkpoint_id"],
|
||||
}
|
||||
},
|
||||
self._load_checkpoint(
|
||||
value["checkpoint"],
|
||||
value["channel_values"],
|
||||
),
|
||||
self._load_metadata(value["metadata"]),
|
||||
{
|
||||
**value["checkpoint"],
|
||||
"channel_values": self._load_blobs(value["channel_values"]),
|
||||
},
|
||||
value["metadata"],
|
||||
(
|
||||
{
|
||||
"configurable": {
|
||||
@@ -277,11 +277,11 @@ class PostgresSaver(BasePostgresSaver):
|
||||
"checkpoint_id": value["checkpoint_id"],
|
||||
}
|
||||
},
|
||||
self._load_checkpoint(
|
||||
value["checkpoint"],
|
||||
value["channel_values"],
|
||||
),
|
||||
self._load_metadata(value["metadata"]),
|
||||
{
|
||||
**value["checkpoint"],
|
||||
"channel_values": self._load_blobs(value["channel_values"]),
|
||||
},
|
||||
value["metadata"],
|
||||
(
|
||||
{
|
||||
"configurable": {
|
||||
@@ -361,8 +361,8 @@ class PostgresSaver(BasePostgresSaver):
|
||||
checkpoint_ns,
|
||||
checkpoint["id"],
|
||||
checkpoint_id,
|
||||
Jsonb(self._dump_checkpoint(copy)),
|
||||
self._dump_metadata(get_checkpoint_metadata(config, metadata)),
|
||||
Jsonb(copy),
|
||||
Jsonb(get_checkpoint_metadata(config, metadata)),
|
||||
),
|
||||
)
|
||||
return next_config
|
||||
|
||||
@@ -168,12 +168,11 @@ class AsyncPostgresSaver(BasePostgresSaver):
|
||||
"checkpoint_id": value["checkpoint_id"],
|
||||
}
|
||||
},
|
||||
await asyncio.to_thread(
|
||||
self._load_checkpoint,
|
||||
value["checkpoint"],
|
||||
value["channel_values"],
|
||||
),
|
||||
self._load_metadata(value["metadata"]),
|
||||
{
|
||||
**value["checkpoint"],
|
||||
"channel_values": self._load_blobs(value["channel_values"]),
|
||||
},
|
||||
value["metadata"],
|
||||
(
|
||||
{
|
||||
"configurable": {
|
||||
@@ -245,12 +244,11 @@ class AsyncPostgresSaver(BasePostgresSaver):
|
||||
"checkpoint_id": value["checkpoint_id"],
|
||||
}
|
||||
},
|
||||
await asyncio.to_thread(
|
||||
self._load_checkpoint,
|
||||
value["checkpoint"],
|
||||
value["channel_values"],
|
||||
),
|
||||
self._load_metadata(value["metadata"]),
|
||||
{
|
||||
**value["checkpoint"],
|
||||
"channel_values": self._load_blobs(value["channel_values"]),
|
||||
},
|
||||
value["metadata"],
|
||||
(
|
||||
{
|
||||
"configurable": {
|
||||
@@ -320,8 +318,8 @@ class AsyncPostgresSaver(BasePostgresSaver):
|
||||
checkpoint_ns,
|
||||
checkpoint["id"],
|
||||
checkpoint_id,
|
||||
Jsonb(self._dump_checkpoint(copy)),
|
||||
self._dump_metadata(get_checkpoint_metadata(config, metadata)),
|
||||
Jsonb(copy),
|
||||
Jsonb(get_checkpoint_metadata(config, metadata)),
|
||||
),
|
||||
)
|
||||
return next_config
|
||||
|
||||
@@ -9,11 +9,8 @@ from langgraph.checkpoint.base import (
|
||||
WRITES_IDX_MAP,
|
||||
BaseCheckpointSaver,
|
||||
ChannelVersions,
|
||||
Checkpoint,
|
||||
CheckpointMetadata,
|
||||
get_checkpoint_id,
|
||||
)
|
||||
from langgraph.checkpoint.serde.jsonplus import JsonPlusSerializer
|
||||
from langgraph.checkpoint.serde.types import TASKS
|
||||
|
||||
MetadataInput = Optional[dict[str, Any]]
|
||||
@@ -150,7 +147,6 @@ class BasePostgresSaver(BaseCheckpointSaver[str]):
|
||||
UPSERT_CHECKPOINT_WRITES_SQL = UPSERT_CHECKPOINT_WRITES_SQL
|
||||
INSERT_CHECKPOINT_WRITES_SQL = INSERT_CHECKPOINT_WRITES_SQL
|
||||
|
||||
jsonplus_serde = JsonPlusSerializer()
|
||||
supports_pipeline: bool
|
||||
|
||||
def _migrate_pending_sends(
|
||||
@@ -173,19 +169,6 @@ class BasePostgresSaver(BaseCheckpointSaver[str]):
|
||||
else self.get_next_version(None)
|
||||
)
|
||||
|
||||
def _load_checkpoint(
|
||||
self,
|
||||
checkpoint: dict[str, Any],
|
||||
channel_values: list[tuple[bytes, bytes, bytes]],
|
||||
) -> Checkpoint:
|
||||
return {
|
||||
**checkpoint,
|
||||
"channel_values": self._load_blobs(channel_values),
|
||||
}
|
||||
|
||||
def _dump_checkpoint(self, checkpoint: Checkpoint) -> dict[str, Any]:
|
||||
return checkpoint
|
||||
|
||||
def _load_blobs(
|
||||
self, blob_values: list[tuple[bytes, bytes, bytes]]
|
||||
) -> dict[str, Any]:
|
||||
@@ -261,14 +244,6 @@ class BasePostgresSaver(BaseCheckpointSaver[str]):
|
||||
for idx, (channel, value) in enumerate(writes)
|
||||
]
|
||||
|
||||
def _load_metadata(self, metadata: dict[str, Any]) -> CheckpointMetadata:
|
||||
return self.jsonplus_serde.loads(self.jsonplus_serde.dumps(metadata))
|
||||
|
||||
def _dump_metadata(self, metadata: CheckpointMetadata) -> str:
|
||||
serialized_metadata = self.jsonplus_serde.dumps(metadata)
|
||||
# NOTE: we're using JSON serializer (not msgpack), so we need to remove null characters before writing
|
||||
return serialized_metadata.decode().replace("\\u0000", "")
|
||||
|
||||
def get_next_version(self, current: Optional[str]) -> str:
|
||||
if current is None:
|
||||
current_v = 0
|
||||
|
||||
@@ -45,11 +45,6 @@ class CheckpointMetadata(TypedDict, total=False):
|
||||
0 for the first "loop" checkpoint.
|
||||
... for the nth checkpoint afterwards.
|
||||
"""
|
||||
writes: dict[str, Any]
|
||||
"""The writes that were made between the previous checkpoint and this one.
|
||||
|
||||
Mapping from node name to writes emitted by that node.
|
||||
"""
|
||||
parents: dict[str, str]
|
||||
"""The IDs of the parent checkpoints.
|
||||
|
||||
@@ -377,7 +372,10 @@ def get_checkpoint_metadata(
|
||||
config: RunnableConfig, metadata: CheckpointMetadata
|
||||
) -> CheckpointMetadata:
|
||||
"""Get checkpoint metadata in a backwards-compatible manner."""
|
||||
metadata = metadata.copy()
|
||||
metadata = {
|
||||
k: v.replace("\u0000", "") if isinstance(v, str) else v
|
||||
for k, v in metadata.items()
|
||||
}
|
||||
for obj in (config.get("metadata"), config.get("configurable")):
|
||||
if not obj:
|
||||
continue
|
||||
@@ -385,8 +383,10 @@ def get_checkpoint_metadata(
|
||||
if key in metadata or key in EXCLUDED_METADATA_KEYS or key.startswith("__"):
|
||||
continue
|
||||
v = obj[key]
|
||||
if isinstance(v, (str, int, bool, float)):
|
||||
metadata[key] = v # type: ignore[literal-required]
|
||||
if isinstance(v, str):
|
||||
metadata[key] = v.replace("\u0000", "")
|
||||
elif isinstance(v, (int, bool, float)):
|
||||
metadata[key] = v
|
||||
return metadata
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ from langgraph.checkpoint.base import (
|
||||
CheckpointMetadata,
|
||||
)
|
||||
from langgraph.checkpoint.memory import InMemorySaver
|
||||
from tests.checkpoint_utils import ( # type: ignore[import-untyped]
|
||||
from tests.checkpoint_utils import (
|
||||
create_checkpoint,
|
||||
empty_checkpoint,
|
||||
)
|
||||
|
||||
@@ -1559,7 +1559,6 @@ class Pregel(PregelProtocol):
|
||||
**checkpoint_metadata,
|
||||
"source": "update",
|
||||
"step": step + 1,
|
||||
"writes": {},
|
||||
"parents": saved.metadata.get("parents", {}) if saved else {},
|
||||
},
|
||||
{},
|
||||
@@ -1583,7 +1582,6 @@ class Pregel(PregelProtocol):
|
||||
**checkpoint_metadata,
|
||||
"source": "update",
|
||||
"step": step + 1,
|
||||
"writes": {},
|
||||
"parents": saved.metadata.get("parents", {}) if saved else {},
|
||||
},
|
||||
{},
|
||||
@@ -1621,7 +1619,6 @@ class Pregel(PregelProtocol):
|
||||
**checkpoint_metadata,
|
||||
"source": "input",
|
||||
"step": next_step,
|
||||
"writes": dict(input_writes),
|
||||
},
|
||||
get_new_channel_versions(
|
||||
checkpoint_previous_versions,
|
||||
@@ -1813,7 +1810,6 @@ class Pregel(PregelProtocol):
|
||||
**checkpoint_metadata,
|
||||
"source": "update",
|
||||
"step": step + 1,
|
||||
"writes": {as_node: values for as_node, values in valid_updates},
|
||||
"parents": saved.metadata.get("parents", {}) if saved else {},
|
||||
},
|
||||
get_new_channel_versions(
|
||||
@@ -1974,7 +1970,6 @@ class Pregel(PregelProtocol):
|
||||
**checkpoint_metadata,
|
||||
"source": "update",
|
||||
"step": step + 1,
|
||||
"writes": {},
|
||||
"parents": saved.metadata.get("parents", {}) if saved else {},
|
||||
},
|
||||
{},
|
||||
@@ -1998,7 +1993,6 @@ class Pregel(PregelProtocol):
|
||||
**checkpoint_metadata,
|
||||
"source": "update",
|
||||
"step": step + 1,
|
||||
"writes": {},
|
||||
"parents": saved.metadata.get("parents", {}) if saved else {},
|
||||
},
|
||||
{},
|
||||
@@ -2036,7 +2030,6 @@ class Pregel(PregelProtocol):
|
||||
**checkpoint_metadata,
|
||||
"source": "input",
|
||||
"step": next_step,
|
||||
"writes": dict(input_writes),
|
||||
},
|
||||
get_new_channel_versions(
|
||||
checkpoint_previous_versions,
|
||||
@@ -2226,7 +2219,6 @@ class Pregel(PregelProtocol):
|
||||
**checkpoint_metadata,
|
||||
"source": "update",
|
||||
"step": step + 1,
|
||||
"writes": {as_node: values for as_node, values in valid_updates},
|
||||
"parents": saved.metadata.get("parents", {}) if saved else {},
|
||||
},
|
||||
get_new_channel_versions(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from collections import Counter
|
||||
from collections.abc import Iterator, Mapping, Sequence
|
||||
from typing import Any, Literal, Optional, TypeVar, Union
|
||||
from typing import Any, Literal, Optional, Union
|
||||
|
||||
from langgraph.channels.base import BaseChannel, EmptyChannelError
|
||||
from langgraph.constants import (
|
||||
@@ -172,11 +172,3 @@ def map_output_updates(
|
||||
if cached:
|
||||
grouped["__metadata__"] = {"cached": cached}
|
||||
yield grouped
|
||||
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
def single(iter: Iterator[T]) -> Optional[T]:
|
||||
for item in iter:
|
||||
return item
|
||||
|
||||
@@ -112,7 +112,6 @@ from langgraph.pregel.io import (
|
||||
map_output_updates,
|
||||
map_output_values,
|
||||
read_channels,
|
||||
single,
|
||||
)
|
||||
from langgraph.pregel.read import PregelNode
|
||||
from langgraph.pregel.utils import get_new_channel_versions, is_xxh3_128_hexdigest
|
||||
@@ -520,17 +519,7 @@ class PregelLoop:
|
||||
# "not skip_done_tasks" only applies to first tick after resuming
|
||||
self.skip_done_tasks = True
|
||||
# save checkpoint
|
||||
self._put_checkpoint(
|
||||
{
|
||||
"source": "loop",
|
||||
"writes": single(
|
||||
map_output_updates(
|
||||
self.output_keys,
|
||||
[(t, t.writes) for t in self.tasks.values()],
|
||||
)
|
||||
),
|
||||
}
|
||||
)
|
||||
self._put_checkpoint({"source": "loop"})
|
||||
# after execution, check if we should interrupt
|
||||
if self.interrupt_after and should_interrupt(
|
||||
self.checkpoint, self.interrupt_after, self.tasks.values()
|
||||
@@ -760,7 +749,7 @@ class PregelLoop:
|
||||
self.trigger_to_nodes,
|
||||
)
|
||||
# save input checkpoint
|
||||
self._put_checkpoint({"source": "input", "writes": dict(input_writes)})
|
||||
self._put_checkpoint({"source": "input"})
|
||||
# set flag
|
||||
if (
|
||||
self.input_model is not None
|
||||
|
||||
@@ -44,7 +44,6 @@ def get_expected_history(*, exc_task_results: int = 0) -> list[StateSnapshot]:
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": {"qa": {"answer": "doc1,doc2,doc3,doc4"}},
|
||||
"step": 4,
|
||||
"parents": {},
|
||||
"thread_id": "1",
|
||||
@@ -75,7 +74,6 @@ def get_expected_history(*, exc_task_results: int = 0) -> list[StateSnapshot]:
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": {"retriever_one": {"docs": ["doc1", "doc2"]}},
|
||||
"step": 3,
|
||||
"parents": {},
|
||||
"thread_id": "1",
|
||||
@@ -134,10 +132,6 @@ def get_expected_history(*, exc_task_results: int = 0) -> list[StateSnapshot]:
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": {
|
||||
"analyzer_one": {"query": "analyzed: query: what is weather in sf"},
|
||||
"retriever_two": {"docs": ["doc3", "doc4"]},
|
||||
},
|
||||
"step": 2,
|
||||
"parents": {},
|
||||
"thread_id": "1",
|
||||
@@ -175,7 +169,6 @@ def get_expected_history(*, exc_task_results: int = 0) -> list[StateSnapshot]:
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": {"rewrite_query": {"query": "query: what is weather in sf"}},
|
||||
"step": 1,
|
||||
"parents": {},
|
||||
"thread_id": "1",
|
||||
@@ -226,7 +219,6 @@ def get_expected_history(*, exc_task_results: int = 0) -> list[StateSnapshot]:
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": None,
|
||||
"step": 0,
|
||||
"parents": {},
|
||||
"thread_id": "1",
|
||||
@@ -266,7 +258,6 @@ def get_expected_history(*, exc_task_results: int = 0) -> list[StateSnapshot]:
|
||||
},
|
||||
metadata={
|
||||
"source": "input",
|
||||
"writes": {"__start__": {"query": "what is weather in sf"}},
|
||||
"step": -1,
|
||||
"parents": {},
|
||||
"thread_id": "1",
|
||||
@@ -353,7 +344,6 @@ SAVED_CHECKPOINTS = {
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": {"qa": {"answer": "doc1,doc2,doc3,doc4"}},
|
||||
"step": 4,
|
||||
"parents": {},
|
||||
"thread_id": "1",
|
||||
@@ -415,7 +405,6 @@ SAVED_CHECKPOINTS = {
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": {"retriever_one": {"docs": ["doc1", "doc2"]}},
|
||||
"step": 3,
|
||||
"parents": {},
|
||||
"thread_id": "1",
|
||||
@@ -492,10 +481,6 @@ SAVED_CHECKPOINTS = {
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": {
|
||||
"analyzer_one": {"query": "analyzed: query: what is weather in sf"},
|
||||
"retriever_two": {"docs": ["doc3", "doc4"]},
|
||||
},
|
||||
"step": 2,
|
||||
"parents": {},
|
||||
"thread_id": "1",
|
||||
@@ -548,7 +533,6 @@ SAVED_CHECKPOINTS = {
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": {"rewrite_query": {"query": "query: what is weather in sf"}},
|
||||
"step": 1,
|
||||
"parents": {},
|
||||
"thread_id": "1",
|
||||
@@ -604,7 +588,6 @@ SAVED_CHECKPOINTS = {
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": None,
|
||||
"step": 0,
|
||||
"parents": {},
|
||||
"thread_id": "1",
|
||||
@@ -654,7 +637,6 @@ SAVED_CHECKPOINTS = {
|
||||
},
|
||||
metadata={
|
||||
"source": "input",
|
||||
"writes": {"__start__": {"query": "what is weather in sf"}},
|
||||
"step": -1,
|
||||
"parents": {},
|
||||
"thread_id": "1",
|
||||
@@ -741,7 +723,6 @@ SAVED_CHECKPOINTS = {
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": {"qa": {"answer": "doc1,doc2,doc3,doc4"}},
|
||||
"thread_id": "1",
|
||||
"step": 4,
|
||||
"parents": {},
|
||||
@@ -804,7 +785,6 @@ SAVED_CHECKPOINTS = {
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": {"retriever_one": {"docs": ["doc1", "doc2"]}},
|
||||
"thread_id": "1",
|
||||
"step": 3,
|
||||
"parents": {},
|
||||
@@ -884,10 +864,6 @@ SAVED_CHECKPOINTS = {
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": {
|
||||
"analyzer_one": {"query": "analyzed: query: what is weather in sf"},
|
||||
"retriever_two": {"docs": ["doc3", "doc4"]},
|
||||
},
|
||||
"thread_id": "1",
|
||||
"step": 2,
|
||||
"parents": {},
|
||||
@@ -944,7 +920,6 @@ SAVED_CHECKPOINTS = {
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": {"rewrite_query": {"query": "query: what is weather in sf"}},
|
||||
"thread_id": "1",
|
||||
"step": 1,
|
||||
"parents": {},
|
||||
@@ -1005,7 +980,6 @@ SAVED_CHECKPOINTS = {
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": None,
|
||||
"thread_id": "1",
|
||||
"step": 0,
|
||||
"parents": {},
|
||||
@@ -1055,7 +1029,6 @@ SAVED_CHECKPOINTS = {
|
||||
},
|
||||
metadata={
|
||||
"source": "input",
|
||||
"writes": {"__start__": {"query": "what is weather in sf"}},
|
||||
"thread_id": "1",
|
||||
"step": -1,
|
||||
"parents": {},
|
||||
@@ -1142,7 +1115,6 @@ SAVED_CHECKPOINTS = {
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": {"qa": {"answer": "doc1,doc2,doc3,doc4"}},
|
||||
"thread_id": "1",
|
||||
"step": 4,
|
||||
"parents": {},
|
||||
@@ -1205,7 +1177,6 @@ SAVED_CHECKPOINTS = {
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": {"retriever_one": {"docs": ["doc1", "doc2"]}},
|
||||
"thread_id": "1",
|
||||
"step": 3,
|
||||
"parents": {},
|
||||
@@ -1285,10 +1256,6 @@ SAVED_CHECKPOINTS = {
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": {
|
||||
"analyzer_one": {"query": "analyzed: query: what is weather in sf"},
|
||||
"retriever_two": {"docs": ["doc3", "doc4"]},
|
||||
},
|
||||
"thread_id": "1",
|
||||
"step": 2,
|
||||
"parents": {},
|
||||
@@ -1345,7 +1312,6 @@ SAVED_CHECKPOINTS = {
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": {"rewrite_query": {"query": "query: what is weather in sf"}},
|
||||
"thread_id": "1",
|
||||
"step": 1,
|
||||
"parents": {},
|
||||
@@ -1406,7 +1372,6 @@ SAVED_CHECKPOINTS = {
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": None,
|
||||
"thread_id": "1",
|
||||
"step": 0,
|
||||
"parents": {},
|
||||
@@ -1456,7 +1421,6 @@ SAVED_CHECKPOINTS = {
|
||||
},
|
||||
metadata={
|
||||
"source": "input",
|
||||
"writes": {"__start__": {"query": "what is weather in sf"}},
|
||||
"thread_id": "1",
|
||||
"step": -1,
|
||||
"parents": {},
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
from collections.abc import Iterator
|
||||
|
||||
from langgraph.pregel.io import single
|
||||
|
||||
|
||||
def test_single() -> None:
|
||||
closed = False
|
||||
|
||||
def myiter() -> Iterator[int]:
|
||||
try:
|
||||
yield 1
|
||||
yield 2
|
||||
finally:
|
||||
nonlocal closed
|
||||
closed = True
|
||||
|
||||
assert single(myiter()) == 1
|
||||
assert closed
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1071,7 +1071,6 @@ def test_pending_writes_resume(
|
||||
"parents": {},
|
||||
"source": "loop",
|
||||
"step": 0,
|
||||
"writes": None,
|
||||
"thread_id": "1",
|
||||
}
|
||||
# get_state with checkpoint_id should not apply any pending writes
|
||||
@@ -1162,7 +1161,6 @@ def test_pending_writes_resume(
|
||||
"parents": {},
|
||||
"step": 1,
|
||||
"source": "loop",
|
||||
"writes": {"one": {"value": 2}, "two": {"value": 3}},
|
||||
"thread_id": "1",
|
||||
},
|
||||
parent_config={
|
||||
@@ -1211,7 +1209,6 @@ def test_pending_writes_resume(
|
||||
"parents": {},
|
||||
"step": 0,
|
||||
"source": "loop",
|
||||
"writes": None,
|
||||
"thread_id": "1",
|
||||
},
|
||||
parent_config={
|
||||
@@ -1264,7 +1261,6 @@ def test_pending_writes_resume(
|
||||
"parents": {},
|
||||
"step": -1,
|
||||
"source": "input",
|
||||
"writes": {"__start__": {"value": 1}},
|
||||
"thread_id": "1",
|
||||
},
|
||||
parent_config=None,
|
||||
@@ -2273,7 +2269,6 @@ def test_in_one_fan_out_state_graph_waiting_edge(
|
||||
"parents": {},
|
||||
"source": "update",
|
||||
"step": 4,
|
||||
"writes": {"retriever_one": {"docs": ["doc5"]}},
|
||||
"thread_id": "2",
|
||||
},
|
||||
parent_config=expected_parent_config,
|
||||
@@ -2544,7 +2539,6 @@ def test_in_one_fan_out_state_graph_defer_node(
|
||||
"parents": {},
|
||||
"source": "update",
|
||||
"step": 4,
|
||||
"writes": {"analyzer_one": {"docs": ["doc5"]}},
|
||||
"thread_id": "2",
|
||||
},
|
||||
parent_config=expected_parent_config,
|
||||
@@ -2814,7 +2808,6 @@ def test_in_one_fan_out_state_graph_then_defer_node(
|
||||
"parents": {},
|
||||
"source": "update",
|
||||
"step": 4,
|
||||
"writes": {"retriever_one": {"docs": ["doc5"]}},
|
||||
"thread_id": "2",
|
||||
},
|
||||
parent_config=expected_parent_config,
|
||||
@@ -5265,11 +5258,6 @@ def test_parent_command(sync_checkpointer: BaseCheckpointSaver) -> None:
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": {
|
||||
"alice": {
|
||||
"user_name": "Meow",
|
||||
}
|
||||
},
|
||||
"thread_id": "1",
|
||||
"step": 1,
|
||||
"parents": {},
|
||||
@@ -5984,11 +5972,6 @@ def test_falsy_return_from_task(
|
||||
"parents": {},
|
||||
"source": "input",
|
||||
"step": -1,
|
||||
"writes": {
|
||||
"__start__": {
|
||||
"a": 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
"next": [
|
||||
"graph",
|
||||
@@ -6097,11 +6080,6 @@ def test_falsy_return_from_task(
|
||||
"source": "input",
|
||||
"step": -1,
|
||||
"thread_id": AnyStr(),
|
||||
"writes": {
|
||||
"__start__": {
|
||||
"a": 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
"next": [
|
||||
"graph",
|
||||
@@ -6191,10 +6169,6 @@ def test_falsy_return_from_task(
|
||||
"parents": {},
|
||||
"source": "loop",
|
||||
"step": 0,
|
||||
"writes": {
|
||||
"falsy_task": False,
|
||||
"graph": None,
|
||||
},
|
||||
},
|
||||
"next": [],
|
||||
"parent_config": {
|
||||
@@ -8035,11 +8009,6 @@ def test_bulk_state_updates(
|
||||
# Check if there are only two checkpoints
|
||||
checkpoints = list(sync_checkpointer.list(config))
|
||||
assert len(checkpoints) == 2
|
||||
assert checkpoints[0].metadata["writes"] == {
|
||||
"node_a": {"foo": "updated"},
|
||||
"node_b": {"baz": "new"},
|
||||
}
|
||||
assert checkpoints[1].metadata["writes"] == {"node_a": {"foo": "bar"}}
|
||||
|
||||
# perform multiple steps at the same time
|
||||
config = {"configurable": {"thread_id": "2"}}
|
||||
@@ -8062,11 +8031,6 @@ def test_bulk_state_updates(
|
||||
|
||||
checkpoints = list(sync_checkpointer.list(config))
|
||||
assert len(checkpoints) == 2
|
||||
assert checkpoints[0].metadata["writes"] == {
|
||||
"node_a": {"foo": "updated"},
|
||||
"node_b": {"baz": "new"},
|
||||
}
|
||||
assert checkpoints[1].metadata["writes"] == {"node_a": {"foo": "bar"}}
|
||||
|
||||
# Should raise error if updating without as_node
|
||||
with pytest.raises(InvalidUpdateError):
|
||||
|
||||
@@ -588,14 +588,12 @@ async def test_dynamic_interrupt(async_checkpointer: BaseCheckpointSaver) -> Non
|
||||
"parents": {},
|
||||
"source": "loop",
|
||||
"step": 0,
|
||||
"writes": None,
|
||||
"thread_id": "1",
|
||||
},
|
||||
{
|
||||
"parents": {},
|
||||
"source": "input",
|
||||
"step": -1,
|
||||
"writes": {"__start__": {"my_key": "value ⛰️", "market": "DE"}},
|
||||
"thread_id": "1",
|
||||
},
|
||||
]
|
||||
@@ -623,7 +621,6 @@ async def test_dynamic_interrupt(async_checkpointer: BaseCheckpointSaver) -> Non
|
||||
"parents": {},
|
||||
"source": "loop",
|
||||
"step": 0,
|
||||
"writes": None,
|
||||
"thread_id": "1",
|
||||
},
|
||||
parent_config=(
|
||||
@@ -652,7 +649,6 @@ async def test_dynamic_interrupt(async_checkpointer: BaseCheckpointSaver) -> Non
|
||||
"parents": {},
|
||||
"source": "update",
|
||||
"step": 1,
|
||||
"writes": {},
|
||||
"thread_id": "1",
|
||||
},
|
||||
parent_config=(
|
||||
@@ -773,14 +769,12 @@ async def test_dynamic_interrupt_subgraph(
|
||||
"parents": {},
|
||||
"source": "loop",
|
||||
"step": 0,
|
||||
"writes": None,
|
||||
"thread_id": "1",
|
||||
},
|
||||
{
|
||||
"parents": {},
|
||||
"source": "input",
|
||||
"step": -1,
|
||||
"writes": {"__start__": {"my_key": "value ⛰️", "market": "DE"}},
|
||||
"thread_id": "1",
|
||||
},
|
||||
]
|
||||
@@ -814,7 +808,6 @@ async def test_dynamic_interrupt_subgraph(
|
||||
"parents": {},
|
||||
"source": "loop",
|
||||
"step": 0,
|
||||
"writes": None,
|
||||
"thread_id": "1",
|
||||
},
|
||||
parent_config=(
|
||||
@@ -845,7 +838,6 @@ async def test_dynamic_interrupt_subgraph(
|
||||
"parents": {},
|
||||
"source": "update",
|
||||
"step": 1,
|
||||
"writes": {},
|
||||
"thread_id": "1",
|
||||
},
|
||||
parent_config=(
|
||||
@@ -965,14 +957,12 @@ async def test_copy_checkpoint(async_checkpointer: BaseCheckpointSaver) -> None:
|
||||
"parents": {},
|
||||
"source": "loop",
|
||||
"step": 0,
|
||||
"writes": None,
|
||||
"thread_id": "1",
|
||||
},
|
||||
{
|
||||
"parents": {},
|
||||
"source": "input",
|
||||
"step": -1,
|
||||
"writes": {"__start__": {"my_key": "value ⛰️", "market": "DE"}},
|
||||
"thread_id": "1",
|
||||
},
|
||||
]
|
||||
@@ -1010,7 +1000,6 @@ async def test_copy_checkpoint(async_checkpointer: BaseCheckpointSaver) -> None:
|
||||
"parents": {},
|
||||
"source": "loop",
|
||||
"step": 0,
|
||||
"writes": None,
|
||||
"thread_id": "1",
|
||||
},
|
||||
parent_config=(
|
||||
@@ -1052,7 +1041,6 @@ async def test_copy_checkpoint(async_checkpointer: BaseCheckpointSaver) -> None:
|
||||
"parents": {},
|
||||
"source": "fork",
|
||||
"step": 1,
|
||||
"writes": None,
|
||||
"thread_id": "1",
|
||||
},
|
||||
parent_config=(
|
||||
@@ -1230,7 +1218,6 @@ async def test_cancel_graph_astream(async_checkpointer: BaseCheckpointSaver) ->
|
||||
"parents": {},
|
||||
"source": "loop",
|
||||
"step": 0,
|
||||
"writes": None,
|
||||
"thread_id": "1",
|
||||
}
|
||||
|
||||
@@ -1306,7 +1293,6 @@ async def test_cancel_graph_astream_events_v2(
|
||||
"parents": {},
|
||||
"source": "loop",
|
||||
"step": 1,
|
||||
"writes": {"alittlewhile": {"value": 2}},
|
||||
"thread_id": "2",
|
||||
}
|
||||
|
||||
@@ -1881,7 +1867,6 @@ async def test_pending_writes_resume(
|
||||
"parents": {},
|
||||
"source": "loop",
|
||||
"step": 0,
|
||||
"writes": None,
|
||||
"thread_id": "1",
|
||||
}
|
||||
# get_state with checkpoint_id should not apply any pending writes
|
||||
@@ -1972,7 +1957,6 @@ async def test_pending_writes_resume(
|
||||
"parents": {},
|
||||
"step": 1,
|
||||
"source": "loop",
|
||||
"writes": {"one": {"value": 2}, "two": {"value": 3}},
|
||||
"thread_id": "1",
|
||||
},
|
||||
parent_config={
|
||||
@@ -2021,7 +2005,6 @@ async def test_pending_writes_resume(
|
||||
"parents": {},
|
||||
"step": 0,
|
||||
"source": "loop",
|
||||
"writes": None,
|
||||
"thread_id": "1",
|
||||
},
|
||||
parent_config={
|
||||
@@ -2070,7 +2053,6 @@ async def test_pending_writes_resume(
|
||||
"parents": {},
|
||||
"step": -1,
|
||||
"source": "input",
|
||||
"writes": {"__start__": {"value": 1}},
|
||||
"thread_id": "1",
|
||||
},
|
||||
parent_config=None,
|
||||
@@ -2671,7 +2653,6 @@ async def test_send_dedupe_on_resume(
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": {"3": ["3"]},
|
||||
"thread_id": "1",
|
||||
"step": 4,
|
||||
"parents": {},
|
||||
@@ -2708,7 +2689,6 @@ async def test_send_dedupe_on_resume(
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": {"2": ["2|3"], "3": ["3"], "flaky": ["flaky|4"]},
|
||||
"thread_id": "1",
|
||||
"step": 3,
|
||||
"parents": {},
|
||||
@@ -2752,13 +2732,6 @@ async def test_send_dedupe_on_resume(
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": {
|
||||
"2": [
|
||||
["2|Command(goto=Send(node='2', arg=3))"],
|
||||
["2|Command(goto=Send(node='flaky', arg=4))"],
|
||||
],
|
||||
"3.1": ["3.1"],
|
||||
},
|
||||
"thread_id": "1",
|
||||
"step": 2,
|
||||
"parents": {},
|
||||
@@ -2814,7 +2787,6 @@ async def test_send_dedupe_on_resume(
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": {"1": ["1"]},
|
||||
"thread_id": "1",
|
||||
"step": 1,
|
||||
"parents": {},
|
||||
@@ -2870,7 +2842,6 @@ async def test_send_dedupe_on_resume(
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": None,
|
||||
"thread_id": "1",
|
||||
"step": 0,
|
||||
"parents": {},
|
||||
@@ -2908,7 +2879,6 @@ async def test_send_dedupe_on_resume(
|
||||
},
|
||||
metadata={
|
||||
"source": "input",
|
||||
"writes": {"__start__": ["0"]},
|
||||
"thread_id": "1",
|
||||
"step": -1,
|
||||
"parents": {},
|
||||
@@ -3087,22 +3057,6 @@ async def test_send_react_interrupt(async_checkpointer: BaseCheckpointSaver) ->
|
||||
metadata={
|
||||
"step": 1,
|
||||
"source": "loop",
|
||||
"writes": {
|
||||
"agent": {
|
||||
"messages": AIMessage(
|
||||
content="",
|
||||
id="ai1",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "foo",
|
||||
"args": {"hi": [1, 2, 3]},
|
||||
"id": "",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
}
|
||||
},
|
||||
"parents": {},
|
||||
"thread_id": "2",
|
||||
},
|
||||
@@ -3157,14 +3111,6 @@ async def test_send_react_interrupt(async_checkpointer: BaseCheckpointSaver) ->
|
||||
metadata={
|
||||
"step": 2,
|
||||
"source": "update",
|
||||
"writes": {
|
||||
"agent": {
|
||||
"messages": _AnyIdAIMessage(
|
||||
content="Bye now",
|
||||
tool_calls=[],
|
||||
)
|
||||
}
|
||||
},
|
||||
"parents": {},
|
||||
"thread_id": "2",
|
||||
},
|
||||
@@ -3243,22 +3189,6 @@ async def test_send_react_interrupt(async_checkpointer: BaseCheckpointSaver) ->
|
||||
metadata={
|
||||
"step": 1,
|
||||
"source": "loop",
|
||||
"writes": {
|
||||
"agent": {
|
||||
"messages": AIMessage(
|
||||
content="",
|
||||
id="ai1",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "foo",
|
||||
"args": {"hi": [1, 2, 3]},
|
||||
"id": "",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
}
|
||||
},
|
||||
"parents": {},
|
||||
"thread_id": "3",
|
||||
},
|
||||
@@ -3334,21 +3264,6 @@ async def test_send_react_interrupt(async_checkpointer: BaseCheckpointSaver) ->
|
||||
metadata={
|
||||
"step": 2,
|
||||
"source": "update",
|
||||
"writes": {
|
||||
"agent": {
|
||||
"messages": _AnyIdAIMessage(
|
||||
content="",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "foo",
|
||||
"args": {"hi": [4, 5, 6]},
|
||||
"id": "tool1",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
}
|
||||
},
|
||||
"parents": {},
|
||||
"thread_id": "3",
|
||||
},
|
||||
@@ -3547,22 +3462,6 @@ async def test_send_react_interrupt_control(
|
||||
metadata={
|
||||
"step": 1,
|
||||
"source": "loop",
|
||||
"writes": {
|
||||
"agent": {
|
||||
"messages": AIMessage(
|
||||
content="",
|
||||
id="ai1",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "foo",
|
||||
"args": {"hi": [1, 2, 3]},
|
||||
"id": "",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
}
|
||||
},
|
||||
"parents": {},
|
||||
"thread_id": "2",
|
||||
},
|
||||
@@ -3617,14 +3516,6 @@ async def test_send_react_interrupt_control(
|
||||
metadata={
|
||||
"step": 2,
|
||||
"source": "update",
|
||||
"writes": {
|
||||
"agent": {
|
||||
"messages": _AnyIdAIMessage(
|
||||
content="Bye now",
|
||||
tool_calls=[],
|
||||
)
|
||||
}
|
||||
},
|
||||
"parents": {},
|
||||
"thread_id": "2",
|
||||
},
|
||||
@@ -4698,7 +4589,6 @@ async def test_in_one_fan_out_state_graph_waiting_edge_custom_state_class(
|
||||
metadata={
|
||||
"parents": {},
|
||||
"source": "loop",
|
||||
"writes": {"qa": {"answer": "doc1,doc2,doc3,doc4"}},
|
||||
"step": 4,
|
||||
"thread_id": "1",
|
||||
},
|
||||
@@ -6386,11 +6276,6 @@ async def test_parent_command(async_checkpointer: BaseCheckpointSaver) -> None:
|
||||
},
|
||||
metadata={
|
||||
"source": "loop",
|
||||
"writes": {
|
||||
"alice": {
|
||||
"user_name": "Meow",
|
||||
}
|
||||
},
|
||||
"thread_id": "1",
|
||||
"step": 1,
|
||||
"parents": {},
|
||||
@@ -8347,11 +8232,6 @@ async def test_bulk_state_updates(async_checkpointer: BaseCheckpointSaver) -> No
|
||||
c async for c in async_checkpointer.alist({"configurable": {"thread_id": "1"}})
|
||||
]
|
||||
assert len(checkpoints) == 2
|
||||
assert checkpoints[0].metadata["writes"] == {
|
||||
"node_a": {"foo": "updated"},
|
||||
"node_b": {"baz": "new"},
|
||||
}
|
||||
assert checkpoints[1].metadata["writes"] == {"node_a": {"foo": "bar"}}
|
||||
|
||||
# perform multiple steps at the same time
|
||||
config = {"configurable": {"thread_id": "2"}}
|
||||
@@ -8376,11 +8256,6 @@ async def test_bulk_state_updates(async_checkpointer: BaseCheckpointSaver) -> No
|
||||
c async for c in async_checkpointer.alist({"configurable": {"thread_id": "1"}})
|
||||
]
|
||||
assert len(checkpoints) == 2
|
||||
assert checkpoints[0].metadata["writes"] == {
|
||||
"node_a": {"foo": "updated"},
|
||||
"node_b": {"baz": "new"},
|
||||
}
|
||||
assert checkpoints[1].metadata["writes"] == {"node_a": {"foo": "bar"}}
|
||||
|
||||
# Should raise error if updating without as_node
|
||||
with pytest.raises(InvalidUpdateError):
|
||||
|
||||
@@ -90,7 +90,6 @@ def test_no_prompt(sync_checkpointer: BaseCheckpointSaver, version: str) -> None
|
||||
assert saved.metadata == {
|
||||
"parents": {},
|
||||
"source": "loop",
|
||||
"writes": {"agent": {"messages": [AIMessage(content="hi?", id="0")]}},
|
||||
"step": 1,
|
||||
"thread_id": "123",
|
||||
}
|
||||
@@ -118,7 +117,6 @@ async def test_no_prompt_async(async_checkpointer: BaseCheckpointSaver) -> None:
|
||||
assert saved.metadata == {
|
||||
"parents": {},
|
||||
"source": "loop",
|
||||
"writes": {"agent": {"messages": [AIMessage(content="hi?", id="0")]}},
|
||||
"step": 1,
|
||||
"thread_id": "123",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user