Skip to content

fix(store): add value serialization for LangChain message objects (#128)#129

Merged
bsbodden merged 3 commits intomainfrom
bsb/issue-128
Dec 11, 2025
Merged

fix(store): add value serialization for LangChain message objects (#128)#129
bsbodden merged 3 commits intomainfrom
bsb/issue-128

Conversation

@bsbodden
Copy link
Copy Markdown
Contributor

  • Add value serialization to RedisStore and AsyncRedisStore for handling LangChain message objects
  • Reuse existing JsonPlusRedisSerializer from checkpoint package for consistency
  • Add comprehensive test coverage for message serialization scenarios

RedisStore was passing values directly to redisvl.SearchIndex.load() which
uses standard json.dumps() internally. This caused failures when storing
values containing LangChain message objects (HumanMessage, AIMessage, etc.).

Changes:
- Add _serialize_value() method to BaseRedisStore that uses JsonPlusRedisSerializer
- Add _deserialize_value() method for proper revival of complex objects
- Update _row_to_item() and _row_to_search_item() to accept deserialize function
- Update all call sites in RedisStore and AsyncRedisStore

The serialization is smart: simple JSON-serializable values are stored as-is
for backward compatibility, while complex objects get the serde wrapper.

Closes #128
Add comprehensive test suite for issue #128 covering:
- Single HumanMessage storage and retrieval
- Multiple message types (SystemMessage, HumanMessage, AIMessage)
- Messages with additional kwargs (name, id, additional_kwargs)
- Nested message structures in complex data
- AIMessage with tool_calls
- Search operations with message values
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request fixes a serialization issue where storing LangChain message objects (HumanMessage, AIMessage, etc.) in RedisStore failed because the underlying redisvl library couldn't serialize them with standard JSON. The fix reuses the existing JsonPlusRedisSerializer from the checkpoint package to handle complex object serialization transparently while maintaining backward compatibility with existing plain JSON values.

Key changes:

  • Added automatic value serialization/deserialization for non-JSON-serializable objects using JsonPlusRedisSerializer
  • Values are checked for JSON serializability and only wrapped in the serde format when necessary
  • Updated both sync and async store implementations to apply deserialization when retrieving values

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 11 comments.

File Description
tests/test_issue_128_store_message_serialization.py Comprehensive test suite covering message serialization scenarios including multiple message types, nested structures, tool calls, and search operations (sync only)
langgraph/store/redis/base.py Core serialization logic added to BaseRedisStore with _serialize_value and _deserialize_value methods, plus JsonPlusRedisSerializer initialization and updates to helper functions to accept deserialization callbacks
langgraph/store/redis/aio.py Updated async batch operations to pass deserialize_fn to _row_to_item and _row_to_search_item helper functions
langgraph/store/redis/init.py Updated sync batch operations to pass deserialize_fn to _row_to_item and _row_to_search_item helper functions

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread langgraph/store/redis/base.py Outdated
Comment thread langgraph/store/redis/base.py Outdated
Comment thread langgraph/store/redis/base.py Outdated
Comment thread langgraph/store/redis/base.py Outdated
Comment thread langgraph/store/redis/base.py Outdated
Comment thread langgraph/store/redis/base.py
Comment thread tests/test_issue_128_store_message_serialization.py
Comment thread tests/test_issue_128_store_message_serialization.py
Comment thread langgraph/store/redis/base.py Outdated
Comment thread langgraph/store/redis/base.py
Improvements based on PR #129 review:

- Move json import to top of file for consistency
- Add exact key check (set equality) to prevent collisions with user data
  that might contain __serde_type__ and __serde_data__ keys
- Add comprehensive error handling for deserialization failures with logging
- Add hex validation for non-json type deserialization
- Fix async store to also apply value serialization in _prepare_batch_PUT_queries_async
- Make type handling explicit in serialization (json vs bytes/msgpack)

New tests added:
- Backward compatibility test for plain JSON values (filters continue to work)
- Serde key collision prevention test
- Bytes value serialization test
- Full async store test suite mirroring sync tests
Copy link
Copy Markdown
Contributor

@abrookins abrookins left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Only concern is that if we add the ability for users to specify a custom filter schema, we should more visibly warn them if they then give us data we can't serialize (and thus won't be filterable). But we can should that later, if we add such filtering.

@bsbodden bsbodden merged commit f0ab606 into main Dec 11, 2025
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants