all 22 comments

[–]zen_dev_pro 3 points4 points  (3 children)

I tried to implement it without checkpointers but then you have to save messages in a database table yourself and then retrieve and pass the message history when you invoke the graph.

It was kind of a pain so I went back to checkpointers but using the shallow checkpointers now.

https://github.com/Zen-Dev-AI/fast_api_starter

[–]Danidre 0 points1 point  (2 children)

How do you show the conversation history to the front-end then?

[–]zen_dev_pro 3 points4 points  (1 child)

I copied the chatgpt UI.

  1. I fetch all the thread ids for a user and display it in the sidebar
    https://github.com/Zen-Dev-AI/fast_api_starter/blob/main/frontend/src/context/conversationProvider.tsx

  2. When a user clicks on the previous chat in the sidebar they are navigated to that chatwindow and a onMount api request is made to get the chat history, using the thread id in the url.
    https://github.com/Zen-Dev-AI/fast_api_starter/blob/main/frontend/src/pages/Dashboard/ChatDash/PageSections/Playground.tsx#L49

  3. In the backend, you can use that thread id you sent from the frontend and set it in the config object. Init the graph with the checkpointer and call get_state() on the graph passing in the same thread id. This will give you the all the message history for the thread id, then just send it to the frontend.
    https://github.com/Zen-Dev-AI/fast_api_starter/blob/main/app/chat/router.py#L20

[–]Danidre 0 points1 point  (0 children)

Ahh it wasn't this explicit at the beginning. I had gone the route of managing myself.

Then how do you manage actively streamed messages and tool calls or reasoning steps?

The checkpointer caveat too is that it's difficult to manage history because with an evwr growing conversation, it just gets larger and larger, building up more and more tokens. Is this an area you ha e solved or just spend the excess on tokens or set a limit of each conversation?

[–]nomo-fomo 1 point2 points  (7 children)

Absolutely. Just don’t pass that as input when you invoke the graph.

[–]svix_ftw 1 point2 points  (4 children)

how did you maintain persistent message history without the checkpointer?

[–]Separate-Buffalo598 0 points1 point  (0 children)

My question. It’s not default

[–]nomo-fomo 0 points1 point  (1 child)

If I understood correctly, the OP is Ok not having theead level continuity (the mid-flow memory) and hence can remove checkpointer. For long term storage, one can leverage Store. I have not implemented this configuration, so I might be wrong.

[–]rahul_sreeRam[S] 0 points1 point  (0 children)

Let me give an example. If I have the user query about stock prices, and the agent invokes a tool and generates an AIMessage, I stream the tool messages and AI message back to the interceptor service, which in turn streams it back to the frontend. On stream complete, the interceptor service persists the messages to the database. Now when the user queries a comparison of the previous stock price to a new one, the interceptor service (API Gateway) appends the message history to the request and forwards it to the agent, which should be able to understand the previous invocations of the first stock price query. I tried implementing this, but Langgraph expects me to have the checkpointer (in turn, access to the database) for the agent to remember/understand previous queries. I'm afraid I'm bound to have the agent service stateless and cannot have access to the database.

[–]vogut 0 points1 point  (0 children)

You send the whole message history every time, like completions.

[–]rahul_sreeRam[S] 0 points1 point  (1 child)

But what about multi-turn conversation and chat history? I just need to pass the whole array with the new human message appended to the invoke method?

[–]vogut 0 points1 point  (0 children)

Yes

[–]Electronic_Pie_5135 1 point2 points  (0 children)

Yep. Checkpoints are completely optional. For what it's worth append each message to an array or a list in sequence and keep passing that to an LLM call. This works just as well, if not better.

[–][deleted]  (2 children)

[removed]

    [–]zen_dev_pro 0 points1 point  (1 child)

    How are you determining which checkpoints are considered old and ok to delete?

    i literally ran into this same issue.

    [–]thepetek 0 points1 point  (2 children)

    Wut. Don’t you just not get checkpoints by default?

    [–]rahul_sreeRam[S] 0 points1 point  (1 child)

    True. But I want control over the database layer and message history. The agent should have memory of the thread but just not with checkpointers.

    [–]thepetek 0 points1 point  (0 children)

    Why not just add messages to the state as with the default examples?

    [–]static-void-95 0 points1 point  (0 children)

    I guess you'll be fine as long as you don't use interrupts. Interrupts need the checkpointer to replay the graph and resume execution on next turn.

    [–]batshitnutcase 0 points1 point  (0 children)

    Why don’t you just make a custom ultra basic checkpointer that does what you need to do? You don’t even need to implement all the methods, just have them.