langchain-ai / langgraph-studio

Desktop app for prototyping and debugging LangGraph applications locally.
https://github.com/langchain-ai/langgraph-studio
1.41k stars 93 forks source link

Incorrect graph visual in Studio #8

Open paullen opened 1 month ago

paullen commented 1 month ago

Here is my graph code:

graph_builder = StateGraph(State)

graph_builder.add_node(PRESENTER, presenter)
graph_builder.add_node(CODE_CHECKER, code_checker)
graph_builder.add_node(API_RETRIEVER, api_retriever_tool)
graph_builder.add_node(COMPONENT_METADATA_RETRIEVER, component_metadata_retriever_tool)

graph_builder.add_edge(START, PRESENTER)

def choose_presenter_next(state: State):
    last_message = state["messages"][-1]

    if hasattr(last_message, "tool_calls") and len(last_message.tool_calls) > 0:
        return [tool_call["name"] for tool_call in last_message.tool_calls]

    return CODE_CHECKER

graph_builder.add_conditional_edges(PRESENTER, choose_presenter_next)
graph_builder.add_edge(API_RETRIEVER, PRESENTER)
graph_builder.add_edge(COMPONENT_METADATA_RETRIEVER, PRESENTER)

def choose_code_checker_next(state: State) -> str:
    last_message = state["messages"][-1]

    last_message_json = json.loads(last_message.content)

    if last_message_json[CORRECT] == "true":
        return END
    return CODE_CHECKER

graph_builder.add_conditional_edges(CODE_CHECKER, choose_code_checker_next)

presenter_graph = graph_builder.compile()

This is the graph I'm being shown in the Studio:

Screenshot 2024-08-02 at 2 55 09 AM

Issues

paullen commented 1 month ago

Update: After I explicitly pass the path_map argument to the the add_conditional_edges function, I get the correct visual.

This reduces my usability of the Studio since I have to edit all of my old code to add path maps and update each path_map everytime I add new nodes to my graph

hwchase17 commented 1 month ago

@paullen unfortunately I don't think there's a great way to fix this... how would you determine this programatically without the manual path map?

paullen commented 1 month ago

@hwchase17 You're right. My pain point was more with the user flow rather than the actual syntax. The studio showed me an incorrect graph without warnings, when I could've taken steps to resolve it, had I known. Here's a couple of things that can help users:

I would personally go for the second option. What do you think?

hwchase17 commented 1 month ago

yes thats a good callout! i think that makes sense. thanks for the suggestion

dqbd commented 1 month ago

Hello @paullen!

Alternatively, you can change the return type of the conditional edge functions to denote which target edges can be returned by the function.

from typing import Literal

def choose_code_checker_next(state: State) -> Literal["END", "CODE_CHECKER"]:
    last_message = state["messages"][-1]

    last_message_json = json.loads(last_message.content)

    if last_message_json[CORRECT] == "true":
        return "END"
    return "CODE_CHECKER"
paullen commented 1 month ago

@dqbd Thanks! However I'm using literals for my node names and can't seem to find a way to convert them to str. Going with the path maps strategy.

hwchase17 commented 1 month ago

@dqbd Thanks! However I'm using literals for my node names and can't seem to find a way to convert them to str. Going with the path maps strategy.

could you elaborate on this, not sure i understand, but would love to figure out how to support