langgraph icon indicating copy to clipboard operation
langgraph copied to clipboard

DOC: How to use with langserve playground?

Open russell-dot-js opened this issue 1 year ago • 3 comments

Issue with current documentation:

There doesn't appear to be any documentation anywhere on how to use langgraph with langserve playground. When using the Runnable returned from StateGraph.compile as part of a chain, and calling the langserve stream_log endpoint (this is the behavior of langserve playground), it appears that the graph is invoked a single time - I can see my entrypoint then delegating to a conditional edge, but that conditional edge never continues on to its next edge.

This looks like it might be caused by the error "Trying to load an object that doesn't implement serialization:", thrown by WellKnownLCSerializer.dumps in langserve.serialization. This could be caused by using a TypedDict state that doesn't implement toJSON, but the rabbit hole of errors is pretty difficult to navigate.

Idea or request for content:

Include examples of how to use langgraph with langserve / playground, particular demonstrating how to customize the formatting of response / intermediate steps from your graph's state.

russell-dot-js avatar Feb 20 '24 00:02 russell-dot-js

@russell-dot-js thanks for flagging. It typically does work my exposing the runnable directly graph.compile() , but it looks like there may be some bug in how we're returning the response in stream_events

cc @eyurtsev

hinthornw avatar Feb 21 '24 17:02 hinthornw

Thank you for the response @hinthornw @eyurtsev!

I actually just finished debugging what was going on and got it working. It turns out that astream_log will stop traversing the graph if a node does not return a state update

The TLDR is that I haven't had the time to mess around with nested state / subgraphs just yet, so I'm mutating my nested state manually rather than returning a state update. Adding a no-op field to my state that I increment for each no-op resulted in astream_log running the graph to completion.

My application involves a manager invoking many researchers until a question is answered, the state looks something like this:

StepState
action_taken: str
result: str

ResearchState
purpose: str # purpose of the step
steps: list[StepState] # all the steps taken during this Research - this is what I'm mutating manually instead of using nested state updates / subgraphs
summary: str # summary of the research found in all steps once complete

GraphState
question: str # user's question 
researches: list[ResearchState] # the state of an individual research step taken while answering the question
response: str # final response

So my graph looks something like:

Manager ->
  if not sufficient context:
    Research[n] ->
      Research_Step[k] ->
        if research incomplete:
          Research_Step[k+1]
        else:
           Manager
  else:
    Response

Adding an int for noop_count to GraphState and returning an increment to that field after each Step solved my issue.

It is interesting that I've only seen this behavior when calling astream_log... astream and ainvoke seem to work just fine. Is this a bug, or a nuance of the inner workings of astream_log? Is it a bad practice to have a node that doesn't return state updates, or is this usage acceptable?

russell-dot-js avatar Feb 22 '24 01:02 russell-dot-js

Possibly resolved in https://github.com/langchain-ai/langchain/issues/18741 and related to #136

hinthornw avatar Mar 08 '24 02:03 hinthornw

Going to close as resolved, since no one has added to this thread in 2 months

hinthornw avatar May 15 '24 20:05 hinthornw