diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d7d723f0e..f311b3796 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -49,7 +49,7 @@ gain understanding of concepts and how they interact by showing one way to achie They should **avoid** giving multiple permutations of ways to achieve that goal in-depth. Choice is burdensome. Instead, they should guide a new user through a recommended path to accomplishing a concrete goal. While the end result of a tutorial does not necessarily need to -be completely production-ready, it should be useful and practically satisfy the the goal that you clearly stated in the tutorial's introduction. +be completely production-ready, it should be useful and practically satisfy the goal that you clearly stated in the tutorial's introduction. To quote the Diataxis website: diff --git a/docs/docs/cloud/how-tos/configuration_cloud.md b/docs/docs/cloud/how-tos/configuration_cloud.md index 9b2f2091d..8954d966f 100644 --- a/docs/docs/cloud/how-tos/configuration_cloud.md +++ b/docs/docs/cloud/how-tos/configuration_cloud.md @@ -83,7 +83,7 @@ We can now call `.get_schemas` to get schemas associated with this graph: assistant_id=assistant["assistant_id"] ) # There are multiple types of schemas - # We can get the `config_schema` to look at the the configurable parameters + # We can get the `config_schema` to look at the configurable parameters print(schemas["config_schema"]) ``` @@ -94,7 +94,7 @@ We can now call `.get_schemas` to get schemas associated with this graph: assistant["assistant_id"] ); // There are multiple types of schemas - // We can get the `config_schema` to look at the the configurable parameters + // We can get the `config_schema` to look at the configurable parameters console.log(schemas.config_schema); ``` diff --git a/docs/docs/concepts/human_in_the_loop.md b/docs/docs/concepts/human_in_the_loop.md index f253c5ddb..8728d4ba5 100644 --- a/docs/docs/concepts/human_in_the_loop.md +++ b/docs/docs/concepts/human_in_the_loop.md @@ -120,7 +120,7 @@ See [our guide](../how-tos/human_in_the_loop/breakpoints.ipynb) for a detailed h Sometimes we want to review and edit the agent's state. -As with approval, we can interrupt our agent at a [breakpoint](./low_level.md#breakpoints) prior the the step we want to check. +As with approval, we can interrupt our agent at a [breakpoint](./low_level.md#breakpoints) prior to the step we want to check. We can surface the current state to a user and allow the user to edit the agent state. @@ -170,7 +170,7 @@ With editing, the user makes a decision about whether or not to edit the graph s With input, we explicitly define a node in our graph for collecting human input! -The the state update with the human input then runs *as this node*. +The state update with the human input then runs *as this node*. ```python # Compile our graph with a checkpoitner and a breakpoint before the step to to collect human input diff --git a/docs/docs/concepts/persistence.md b/docs/docs/concepts/persistence.md index d5ccd6d15..c6ad10a12 100644 --- a/docs/docs/concepts/persistence.md +++ b/docs/docs/concepts/persistence.md @@ -224,7 +224,7 @@ A [state schema](low_level.md#schema) specifies a set of keys that are populated But, what if we want to retrain some information *across threads*? Consider the case of a chatbot where we want to retain specific information about the user across *all* chat conversations (e.g., threads) with that user! -With checkpointers alone, we cannot share information across threads. This motivates the need for the `Store` interface. As an illustration, we can define an `InMemoryStore` to store information about a user across threads. We simply compile our graph with a checkpointer, as before, and will our new `in_memory_store`. +With checkpointers alone, we cannot share information across threads. This motivates the need for the `Store` interface. As an illustration, we can define an `InMemoryStore` to store information about a user across threads. We simply compile our graph with a checkpointer, as before, and with our new `in_memory_store` variable. First, let's showcase this in isolation without using LangGraph. ```python @@ -239,7 +239,7 @@ user_id = "1" namespace_for_memory = (user_id, "memories") ``` -We use the `store.put` to save memories to our namespace in the store. When we do this, we specify the namespace, as defined above, and a key-value pair for the memory: the key is simply a unique identifier for the memory (`memory_id`) and the value (a dictionary) is the memory itself. +We use the `store.put` method to save memories to our namespace in the store. When we do this, we specify the namespace, as defined above, and a key-value pair for the memory: the key is simply a unique identifier for the memory (`memory_id`) and the value (a dictionary) is the memory itself. ```python memory_id = str(uuid.uuid4()) @@ -247,7 +247,7 @@ memory = {"food_preference" : "I like pizza"} in_memory_store.put(namespace_for_memory, memory_id, memory) ``` -We can read out memories in our namespace using `store.search`, which will return all memories for a given user as a list. The most recent memory is the last in the list. +We can read out memories in our namespace using the `store.search` method, which will return all memories for a given user as a list. The most recent memory is the last in the list. ```python memories = in_memory_store.search(namespace_for_memory) @@ -259,16 +259,16 @@ memories[-1].dict() 'updated_at': '2024-10-02T17:22:31.590605+00:00'} ``` -Each memory type is a Python class with certain attributes. We can access it as a dictionary by converting via `.dict` as above. +Each memory type is a Python class ([`Item`](https://langchain-ai.github.io/langgraph/reference/store/#langgraph.store.base.Item)) with certain attributes. We can access it as a dictionary by converting via `.dict` as above. The attributes it has are: - `value`: The value (itself a dictionary) of this memory -- `key`: The UUID for this memory in this namespace +- `key`: A unique key for this memory in this namespace - `namespace`: A list of strings, the namespace of this memory type - `created_at`: Timestamp for when this memory was created - `updated_at`: Timestamp for when this memory was updated -With this all in place, we use the `in_memory_store` in LangGraph. The `in_memory_store` works hand-in-hand with the checkpointer: the checkpointer saves state to threads, as discussed above, and the the `in_memory_store` allows us to store arbitrary information for access *across* threads. We compile the graph with both the checkpointer and the `in_memory_store` as follows. +With this all in place, we use the `in_memory_store` in LangGraph. The `in_memory_store` works hand-in-hand with the checkpointer: the checkpointer saves state to threads, as discussed above, and the `in_memory_store` allows us to store arbitrary information for access *across* threads. We compile the graph with both the checkpointer and the `in_memory_store` as follows. ```python from langgraph.checkpoint.memory import MemorySaver @@ -317,7 +317,7 @@ def update_memory(state: MessagesState, config: RunnableConfig, *, store: BaseSt ``` -As we showed above, we can also access the store in any node and use `search` to get memories. Recall the the memories are returned as a list of objects that can be converted to a dictionary. +As we showed above, we can also access the store in any node and use the `store.search` method to get memories. Recall the the memories are returned as a list of objects that can be converted to a dictionary. ```python memories[-1].dict() @@ -405,4 +405,4 @@ Lastly, checkpointing also provides fault-tolerance and error recovery: if one o #### Pending writes -Additionally, when a graph node fails mid-execution at a given superstep, LangGraph stores pending checkpoint writes from any other nodes that completed successfully at that superstep, so that whenever we resume graph execution from that superstep we don't re-run the successful nodes. \ No newline at end of file +Additionally, when a graph node fails mid-execution at a given superstep, LangGraph stores pending checkpoint writes from any other nodes that completed successfully at that superstep, so that whenever we resume graph execution from that superstep we don't re-run the successful nodes.