langchain-ai / langgraph

Build resilient language agents as graphs.
https://langchain-ai.github.io/langgraph/
MIT License
5.99k stars 945 forks source link

The difference between the use of configurable and metadata in RunnableConfig? #963

Closed gbaian10 closed 3 months ago

gbaian10 commented 3 months ago

Checked other resources

Example Code

from langchain_core.messages import AIMessage
from langchain_core.runnables import RunnableConfig
from langgraph.graph import StateGraph, MessagesState

def print_config(state: MessagesState, config: RunnableConfig) -> MessagesState:
    print(config["metadata"])  # The value of container type does not appear here
    # These values must be use configurable to get
    print(config["configurable"]["cherries"])
    print(config["configurable"]["dates"])
    print(config["configurable"]["egg"])
    return {"messages": [AIMessage(content="foo")]}

graph_builder = StateGraph(MessagesState)
graph_builder.set_entry_point("foo")
graph_builder.add_node("foo", print_config)
graph_builder.set_finish_point("foo")

config = {
    "configurable": {
        "apple": 1,
        "banana": "two",
        "cherries": [3, "four", 5.0],
        "dates": {"Alice": 6, "Bob": "seven"},
        "egg": (1, 2),
    },
}

app = graph_builder.compile()
app.invoke({"messages": [("human", "Hello World!")]}, config)

Error Message and Stack Trace (if applicable)

`config["metadata"]` cannot retrieve some of the data entered from `configurable`

Description

When I use

{
    "configurable": {
        "apple": 1,
        "banana": "two",
        "cherries": [3, "four", 5.0],
        "dates": {"Alice": 6, "Bob": "seven"},
        "egg": (1, 2),
    },
}

config["metadata"] seems to only save basic types of content?

Is this normal output? What is the principle of saving metadata? When should I use metadata or configurable?

configurable contains a lot of information, while metadata is much cleaner. I encountered this problem when trying to use metadata to get some of my own data.


When I use metadata to input, all values ​​can be obtained normally.

{
    "metadata": {
        "apple": 1,
        "banana": "two",
        "cherries": [3, "four", 5.0],
        "dates": {"Alice": 6, "Bob": "seven"},
        "egg": (1, 2),
    },
}

System Info

langgraph == 0.1.5 langchain == 0.2.6 python version == 3.10.12

hinthornw commented 3 months ago

Metadata was designed for tracing (instrumentation) rather than control flow.

Configurable parameters are meant for actual configuration of the graph / runnable execution.

We log primitive values as metadata since that's useful for observability.

But I do see how that's non-obvious just by looking at the config

gbaian10 commented 3 months ago

Because I observed before that the metadata has the Configurable I entered, and its contents are very clean.

It was easy for me to find all the values ​​I passed in, until I discovered that it seemed to only save the contents of the basic type.

In short, metadata should be an attribute used for langchain internal program tracking.

If the user passes some data to Node and want to use it in Node, should it always be through Configurable?

hinthornw commented 3 months ago

The input would either be in the configuration or the state. Typically configuration is things like IDs, selecting the model type, etc., whereas state is things like messages, documents, database connection, etc.

gbaian10 commented 3 months ago

Thank you for your answer, I will close this issue.