Skip to content

Commit 6f71401

Browse files
committed
fix(serializer): add dataclass and set serialization support for langmem objects
- Add support for serializing/deserializing dataclass objects (e.g., RunningSummary) - Add special handling for sets in nested structures - Prevent loss of type information when dataclasses are serialized - Fix AttributeError when langmem SummarizationNode stores context in state Changes: - Preprocess dataclass instances to LangChain constructor format before serialization - Add _reconstruct_from_constructor() to rebuild objects from constructor format - Handle sets with special __set_items__ marker to preserve contents - Update _revive_if_needed() to detect when parent reviver returns unchanged dict Tests: - Add comprehensive test suite in test_langmem_serialization.py - Test roundtrip serialization of RunningSummary objects - Test nested dataclasses in dicts and lists - All 382 tests passing Fixes the error in create-react-agent-manage-message-history.ipynb where RunningSummary objects were being deserialized as dicts instead of proper objects, causing AttributeError: 'dict' object has no attribute 'summarized_message_ids'
1 parent 8a382db commit 6f71401

File tree

6 files changed

+735
-49
lines changed

6 files changed

+735
-49
lines changed

examples/create-react-agent-hitl.ipynb

Lines changed: 125 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
},
5454
{
5555
"cell_type": "code",
56-
"execution_count": null,
56+
"execution_count": 1,
5757
"id": "a213e11a-5c62-4ddb-a707-490d91add383",
5858
"metadata": {},
5959
"outputs": [],
@@ -64,10 +64,18 @@
6464
},
6565
{
6666
"cell_type": "code",
67-
"execution_count": null,
67+
"execution_count": 2,
6868
"id": "23a1885c-04ab-4750-aefa-105891fddf3e",
6969
"metadata": {},
70-
"outputs": [],
70+
"outputs": [
71+
{
72+
"name": "stdin",
73+
"output_type": "stream",
74+
"text": [
75+
"OPENAI_API_KEY: ········\n"
76+
]
77+
}
78+
],
7179
"source": [
7280
"import getpass\n",
7381
"import os\n",
@@ -104,10 +112,27 @@
104112
},
105113
{
106114
"cell_type": "code",
107-
"execution_count": null,
115+
"execution_count": 3,
108116
"id": "7a154152-973e-4b5d-aa13-48c617744a4c",
109117
"metadata": {},
110-
"outputs": [],
118+
"outputs": [
119+
{
120+
"name": "stdout",
121+
"output_type": "stream",
122+
"text": [
123+
"0.2.0\n",
124+
"17:25:17 langgraph.checkpoint.redis INFO Redis client is a standalone client\n"
125+
]
126+
},
127+
{
128+
"name": "stderr",
129+
"output_type": "stream",
130+
"text": [
131+
"/tmp/ipykernel_253/104821471.py:41: LangGraphDeprecatedSinceV10: create_react_agent has been moved to `langchain.agents`. Please update your import to `from langchain.agents import create_agent`. Deprecated in LangGraph V1.0 to be removed in V2.0.\n",
132+
" graph = create_react_agent(\n"
133+
]
134+
}
135+
],
111136
"source": [
112137
"# First we initialize the model we want to use.\n",
113138
"from langchain_openai import ChatOpenAI\n",
@@ -164,7 +189,7 @@
164189
},
165190
{
166191
"cell_type": "code",
167-
"execution_count": null,
192+
"execution_count": 4,
168193
"id": "16636975-5f2d-4dc7-ab8e-d0bea0830a28",
169194
"metadata": {},
170195
"outputs": [],
@@ -181,11 +206,35 @@
181206
},
182207
{
183208
"cell_type": "code",
184-
"execution_count": null,
209+
"execution_count": 5,
185210
"id": "9ffff6c3-a4f5-47c9-b51d-97caaee85cd6",
186211
"metadata": {},
187-
"outputs": [],
188-
"source": "import uuid\n\nconfig = {\"configurable\": {\"thread_id\": str(uuid.uuid4())}}\ninputs = {\"messages\": [(\"user\", \"what is the weather in SF, CA?\")]}\n\nprint_stream(graph.stream(inputs, config, stream_mode=\"values\"))"
212+
"outputs": [
213+
{
214+
"name": "stdout",
215+
"output_type": "stream",
216+
"text": [
217+
"================================\u001b[1m Human Message \u001b[0m=================================\n",
218+
"\n",
219+
"what is the weather in SF, CA?\n",
220+
"17:25:18 httpx INFO HTTP Request: POST https://api.openai.com/v1/chat/completions \"HTTP/1.1 200 OK\"\n",
221+
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
222+
"Tool Calls:\n",
223+
" get_weather (call_5pXxdiKNI2XosSX5Vt9sbuBv)\n",
224+
" Call ID: call_5pXxdiKNI2XosSX5Vt9sbuBv\n",
225+
" Args:\n",
226+
" location: SF, CA\n"
227+
]
228+
}
229+
],
230+
"source": [
231+
"import uuid\n",
232+
"\n",
233+
"config = {\"configurable\": {\"thread_id\": str(uuid.uuid4())}}\n",
234+
"inputs = {\"messages\": [(\"user\", \"what is the weather in SF, CA?\")]}\n",
235+
"\n",
236+
"print_stream(graph.stream(inputs, config, stream_mode=\"values\"))"
237+
]
189238
},
190239
{
191240
"cell_type": "markdown",
@@ -197,10 +246,19 @@
197246
},
198247
{
199248
"cell_type": "code",
200-
"execution_count": null,
249+
"execution_count": 6,
201250
"id": "3decf001-7228-4ed5-8779-2b9ed98a74ea",
202251
"metadata": {},
203-
"outputs": [],
252+
"outputs": [
253+
{
254+
"name": "stdout",
255+
"output_type": "stream",
256+
"text": [
257+
"17:25:18 langgraph WARNING Ignoring invalid packet type <class 'dict'> in pending sends\n",
258+
"Next step: ()\n"
259+
]
260+
}
261+
],
204262
"source": [
205263
"snapshot = graph.get_state(config)\n",
206264
"print(\"Next step: \", snapshot.next)"
@@ -218,10 +276,24 @@
218276
},
219277
{
220278
"cell_type": "code",
221-
"execution_count": null,
279+
"execution_count": 7,
222280
"id": "740bbaeb",
223281
"metadata": {},
224-
"outputs": [],
282+
"outputs": [
283+
{
284+
"name": "stdout",
285+
"output_type": "stream",
286+
"text": [
287+
"17:25:18 langgraph WARNING Ignoring invalid packet type <class 'dict'> in pending sends\n",
288+
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
289+
"Tool Calls:\n",
290+
" get_weather (call_5pXxdiKNI2XosSX5Vt9sbuBv)\n",
291+
" Call ID: call_5pXxdiKNI2XosSX5Vt9sbuBv\n",
292+
" Args:\n",
293+
" location: SF, CA\n"
294+
]
295+
}
296+
],
225297
"source": [
226298
"print_stream(graph.stream(None, config, stream_mode=\"values\"))"
227299
]
@@ -238,10 +310,31 @@
238310
},
239311
{
240312
"cell_type": "code",
241-
"execution_count": null,
313+
"execution_count": 8,
242314
"id": "1c81ed9f",
243315
"metadata": {},
244-
"outputs": [],
316+
"outputs": [
317+
{
318+
"name": "stdout",
319+
"output_type": "stream",
320+
"text": [
321+
"17:25:18 langgraph WARNING Ignoring invalid packet type <class 'dict'> in pending sends\n",
322+
"17:25:18 langgraph WARNING Ignoring invalid packet type <class 'dict'> in pending sends\n"
323+
]
324+
},
325+
{
326+
"data": {
327+
"text/plain": [
328+
"{'configurable': {'thread_id': '0f79839b-117e-4aa5-901b-5c4939d92005',\n",
329+
" 'checkpoint_ns': '',\n",
330+
" 'checkpoint_id': '1f0c3da6-3615-6dbc-8002-bb5ce3d337c1'}}"
331+
]
332+
},
333+
"execution_count": 8,
334+
"metadata": {},
335+
"output_type": "execute_result"
336+
}
337+
],
245338
"source": [
246339
"state = graph.get_state(config)\n",
247340
"\n",
@@ -253,10 +346,24 @@
253346
},
254347
{
255348
"cell_type": "code",
256-
"execution_count": null,
349+
"execution_count": 9,
257350
"id": "83148e08-63e8-49e5-a08b-02dc907bed1d",
258351
"metadata": {},
259-
"outputs": [],
352+
"outputs": [
353+
{
354+
"name": "stdout",
355+
"output_type": "stream",
356+
"text": [
357+
"17:25:18 langgraph WARNING Ignoring invalid packet type <class 'dict'> in pending sends\n",
358+
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
359+
"Tool Calls:\n",
360+
" get_weather (call_5pXxdiKNI2XosSX5Vt9sbuBv)\n",
361+
" Call ID: call_5pXxdiKNI2XosSX5Vt9sbuBv\n",
362+
" Args:\n",
363+
" location: San Francisco\n"
364+
]
365+
}
366+
],
260367
"source": [
261368
"print_stream(graph.stream(None, config, stream_mode=\"values\"))"
262369
]
@@ -291,4 +398,4 @@
291398
},
292399
"nbformat": 4,
293400
"nbformat_minor": 5
294-
}
401+
}

0 commit comments

Comments
 (0)