-
Notifications
You must be signed in to change notification settings - Fork 80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Creating an Upstash Redis Checkpoint Saver #435
Comments
Should we be using checkpoint ts or checkpoint id as the row keyyou should use the checkpoint id. They're implemented using UUID v6, which is highly collision resistant and maintains chronological sort compatibility. It should meet your needs out of the box. What's the suggested approach for serializing / deserializing the dataThe binary data you're seeing is the raw bytes of a stringified JSON representation of the data. Here's an example from a postgres checkpointer I wrote where the stringified JSON is put into a node buffer. To deserialize, you'll want to use In your checkpointer implementation you can skip the conversion to byte arrays / buffers, instead reading and writing a raw string in redis. Still make sure you use the |
@Masstronaut your implementation was super helpful! It looks like a newer version of LangGraph added support for
|
Hi @brandon-pereira @Masstronaut! Do any of you have a way of explaining the Checkpointers to me? I've been pulling my hair out looking through the docs and (JS) code for the MemorySaver, the MongoDB and Postgres version, and I need to set one up for SurrealDB instead. I'm very confused as to what is being stored where. Is there a simple breakdown of what the data Type(s) are that is stored on the DB? With Checkpointers, I need to retain all that stuff, but I'm lost understanding where data transformations are occurring, what's being duplicated, where etc. , what Data Type needs to be stored, what Data Type is retrieved (or "assembled" upon retrieval). Anyone able to help with an overview of this? I'm currently trying to mirror whats happening in the MemorySaver version (with SERDE gutted from it) but my data looks very different. *I hope this is not too much of a noob question. |
EDIT: I think I have found my saving grace - the Sqlite Saver.. I'm just following through the code and swapping parts out. I think it might be at least be good starting point 🤷🏾♂️?? Any gotcha's I should be weary of? (hoping to setup the Checkpointer for Production use eventually) |
Hey yes the SQLite one is a good place to start - definitely need better docs around the mechanics. There's still a few improvements around structure from the Python library to port over but what's there should work just fine. |
🤞🏾I'm still making my way through it. I noticed the code on Github contains all the Types for reference so this has helped! (When clicking through the Class that is inside of the node module the Types are not available << not sure if this is a normal in the code of a package) |
@jacoblee93 I've refactored my code down but the Looking through the Sqlite Memory Saver, what are the Types for const transaction = this.db.transaction((rows) => { ? Sqlite putWrites code: async putWrites(
config: RunnableConfig,
writes: PendingWrite[],
taskId: string
): Promise<void> {
debugLog(debug_checkpointer, `${serviceName} putWrites▶`)
const stmt = this.db.prepare(`
INSERT OR REPLACE INTO writes
(thread_id, checkpoint_ns, checkpoint_id, task_id, idx, channel, type, value)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
`);
const transaction = this.db.transaction((rows) => {
for (const row of rows) {
stmt.run(...row);
}
});
const rows = writes.map((write, idx) => {
const [type, serializedWrite] = this.serde.dumpsTyped(write[1]);
return [
config.configurable?.thread_id,
config.configurable?.checkpoint_ns,
config.configurable?.checkpoint_id,
taskId,
idx,
write[0],
type,
serializedWrite,
];
});
transaction(rows);
}
} I'm trying to translate this code to and SurrealDB query |
We are using langchainjs / langgraphjs in a NextJS web app for building an AI Agent.
We want to store the state / history, but since the app runs on Vercel, we cannot use Memory Saver.
So we are trying to implement a Redis Checkpoint saver using Upstash Redis.
We have 2 questions -
or
Some of the samples suggest using checkpoint ts where as others use checkpoint_id.
We tried logging the checkpoint_id but it looked like a UUID which wouldn't allow sorting to retrieve the latest checkpoint from a list. Yes, we could override the way checkpoint_id is generated, but we would like to minimize the customization.
We used the default serde, which may be using
JsonPlusSerializer
but the data dumped to redis is binary encoded.This makes it difficult to understand and debug what's going on. Is there a way to store plain-text (JSON or Stringify-ed JSON) as a value in Redis and retrieve it back?
The text was updated successfully, but these errors were encountered: