langgraph icon indicating copy to clipboard operation
langgraph copied to clipboard

how update graph state

Open linpan opened this issue 1 year ago • 2 comments

eg: # Define the agent def run_agent(data): agent_outcome = agent_runnable.invoke(data) logger.warning(f"Agent outcome: {data}") data['define state attr'] = "" return {"agent_outcome": agent_outcome}

linpan avatar Jan 22 '24 08:01 linpan

Hi @linpan , tl;dr, each node can return a dictionary. If a key in the dictionary matches a key in the state, a state update will be performed. Other keys will be ignored.

The state update by default is to overwrite the existing state. You can update that behavior via type annotations on the state.

So if you're defining your graph like this:

def run_agent(data): 
    agent_outcome = agent_runnable.invoke(data)
    logger.warning(f"Agent outcome: {data}") 
    data['define state  attr'] = "" 
    return {"agent_outcome": agent_outcome} 

from langgraph.graph import StateGraph, END
from typing import TypedDict, Any

class MyGraphState(TypedDict):
    messages: List[BaseMessage]
    agent_outcome: Any
    
builder = StateGraph(state)
builder.add_node("agent", run_agent)
builder.set_entry_point("agent")
...

chain = builder.compile()
chain.invoke(...)

any time run_agent returns, the agent_outcome variables is updated to whatever is returned by agent_runnable.invoke()

You can update this behavior to be e.g., append only by using Annotated attribution on the graph state.

hinthornw avatar Jan 22 '24 22:01 hinthornw

thks.

linpan avatar Feb 22 '24 07:02 linpan

Hi @hinthornw,

What if I want to update the state values with the tool call? Is there a way to do it? My understanding was if a tool call returns a dict() with a key present in the state, then it would automatically be updated in the state values? Am I wrong in my understanding here?

Thank you in advance, Vishwas

VishwasSomasekhariah avatar May 20 '24 14:05 VishwasSomasekhariah

Hi @hinthornw,

What if I want to update the state values with the tool call? Is there a way to do it? My understanding was if a tool call returns a dict() with a key present in the state, then it would automatically be updated in the state values? Am I wrong in my understanding here?

Thank you in advance, Vishwas

Yes. You can also decide whether you want to replace or add to an existing list.

SMAntony avatar Jun 27 '24 12:06 SMAntony

@hinthornw is it possible to initialise a state value while defining it? I tried doing value: str = 'abc' but when I test it, I get an empty object

ManishAradwad avatar Jul 29 '24 06:07 ManishAradwad

Is it possible to modify multiple state value using a single node/function?

mahimairaja avatar Jul 29 '24 17:07 mahimairaja

Hi @hinthornw, What if I want to update the state values with the tool call? Is there a way to do it? My understanding was if a tool call returns a dict() with a key present in the state, then it would automatically be updated in the state values? Am I wrong in my understanding here? Thank you in advance, Vishwas

Yes. You can also decide whether you want to replace or add to an existing list.

I tested this out with a custom tool like below, it seems there's no way around returning the tool message 'content' or 'content, artifact'. If I was to return a dictionary, it would just return the whole dictionary as the tool message content.

Is a custom subclass base tool like this what you also meant? If not, any idea how we could update state in a custom tool like this?

The only thing that comes to mind is InjectedState but 1) that seems like an ugly anti pattern like weirdly mutating state that no one knows about. 2) The docs only show how to use InjectedState with @tools, not the subclass base tool, although I could probably get this to work with enough tinkering, still doesn't solve 1.

I'm thinking if you want to do this you need to call all your tools as functions, like have a switch statement in should_continue with the tool names and then just run the tool from a function. Then you are directly returning state, although it doesn't seem as clean as being able to integrate with LangChain custom tools classes.

class CustomBaseTool(BaseTool): """Custom Tool."""

name: str = "custom_tool"
description: str = """this is a custom tool."""
response_format: str = "content_and_artifact"
args_schema: Type[BaseModel] = _CustomBaseTool

slittlec avatar Jul 30 '24 02:07 slittlec

Is it possible to modify multiple state value using a single node/function?

Yes, it is.

SMAntony avatar Aug 01 '24 01:08 SMAntony