From eb387cc946b22a0738171e93c75cf4acf7b3a893 Mon Sep 17 00:00:00 2001 From: Vadym Barda Date: Tue, 27 Aug 2024 09:26:22 -0400 Subject: [PATCH] docs: update cloud time travel docs to pass checkpoint_id correctly (#1483) --- .../how-tos/human_in_the_loop_time_travel.md | 159 ++++++++++-------- 1 file changed, 90 insertions(+), 69 deletions(-) diff --git a/docs/docs/cloud/how-tos/human_in_the_loop_time_travel.md b/docs/docs/cloud/how-tos/human_in_the_loop_time_travel.md index aac3ee566..046bb95a8 100644 --- a/docs/docs/cloud/how-tos/human_in_the_loop_time_travel.md +++ b/docs/docs/cloud/how-tos/human_in_the_loop_time_travel.md @@ -34,7 +34,8 @@ First, we need to setup our client so that we can communicate with our hosted gr ```bash curl --request POST \ --url /threads \ - --header 'Content-Type: application/json' + --header 'Content-Type: application/json' \ + --data {} ``` ## Replay a state @@ -46,7 +47,7 @@ Before replaying a state - we need to create states to replay from! In order to === "Python" ```python - input = { 'messages':[{ "role":"user", "content":"Please search the weather in SF" }] } + input = {"messages": [{"role": "user", "content": "Please search the weather in SF"}]} async for chunk in client.runs.stream( thread["thread_id"], @@ -61,7 +62,7 @@ Before replaying a state - we need to create states to replay from! In order to === "Javascript" ```js - const input = {"messages": [{ "role": "human", "content": "Please search the weather in SF"}] } + const input = { "messages": [{ "role": "human", "content": "Please search the weather in SF" }] } const streamResponse = client.runs.stream( thread["thread_id"], @@ -155,17 +156,23 @@ Output: -To rerun from a state, we need to pass in the `checkpoint_id` into the config of the run like follows: +To rerun from a state, we need first issue an empty update to the thread state. Then we need to pass in the resulting `checkpoint_id` as follows: === "Python" ```python + state_to_replay = states[2] + updated_config = await client.threads.update_state( + thread["thread_id"], + {"messages": []}, + checkpoint_id=state_to_replay["checkpoint_id"] + ) async for chunk in client.runs.stream( thread["thread_id"], assistant_id, # graph_id input=None, stream_mode="updates", - config={"configurable": {"checkpoint_id": state_to_replay['checkpoint_id']}} + checkpoint_id=updated_config["checkpoint_id"] ): if chunk.data and chunk.event != "metadata": print(chunk.data) @@ -174,13 +181,15 @@ To rerun from a state, we need to pass in the `checkpoint_id` into the config of === "Javascript" ```js + const stateToReplay = states[2]; + const config = await client.threads.updateState(thread["thread_id"], { values: {"messages": [] }, checkpointId: stateToReplay["checkpoint_id"] }); const streamResponse = client.runs.stream( thread["thread_id"], assistantId, { input: null, streamMode: "updates", - config: {"configurable": {"checkpoint_id": stateToReplay['checkpoint_id']}}, + checkpointId: config["checkpoint_id"] } ); for await (const chunk of streamResponse) { @@ -193,38 +202,46 @@ To rerun from a state, we need to pass in the `checkpoint_id` into the config of === "CURL" ```bash - curl --request GET --url /threads//history | jq -r '.[2].checkpoint_id' | { - read checkpoint_id - curl --request POST \ - --url /threads//runs/stream \ - --header 'Content-Type: application/json' \ - --data "{ - \"assistant_id\": \"agent\", - \"config\": {\"configurable\": {\"checkpoint_id\": \"$checkpoint_id\"}}, - \"stream_mode\": [ - \"updates\" - ] - }" | \ - sed 's/\r$//' | \ - awk ' - /^event:/ { - if (data_content != "" && event_type != "metadata") { - print data_content "\n" - } - sub(/^event: /, "", $0) - event_type = $0 - data_content = "" - } - /^data:/ { - sub(/^data: /, "", $0) - data_content = $0 - } - END { - if (data_content != "" && event_type != "metadata") { - print data_content "\n" - } + curl --request GET --url /threads//history | jq -c ' + .[2] as $state_to_replay | + { + values: { messages: .[2].values.messages[-1] }, + checkpoint_id: $state_to_replay.checkpoint_id + }' | \ + curl --request POST \ + --url /threads//state \ + --header 'Content-Type: application/json' \ + --data @- | jq .checkpoint_id | \ + curl --request POST \ + --url /threads//runs/stream \ + --header 'Content-Type: application/json' \ + --data "{ + \"assistant_id\": \"agent\", + \"checkpoint_id\": \"$1\", + \"stream_mode\": [ + \"updates\" + ] + }" | \ + sed 's/\r$//' | \ + awk ' + /^event:/ { + if (data_content != "" && event_type != "metadata") { + print data_content "\n" } - ' + sub(/^event: /, "", $0) + event_type = $0 + data_content = "" + } + /^data:/ { + sub(/^data: /, "", $0) + data_content = $0 + } + END { + if (data_content != "" && event_type != "metadata") { + print data_content "\n" + } + } + ' ``` Output: @@ -251,7 +268,7 @@ Let's show how to do this to edit the state at a particular point in time. Let's # Let's now update the args for that tool call last_message['tool_calls'][0]['args'] = {'query': 'current weather in SF'} - new_state = await client.threads.update_state(thread['thread_id'],{"messages":[last_message]},checkpoint_id=state_to_replay['checkpoint_id']) + config = await client.threads.update_state(thread['thread_id'],{"messages":[last_message]},checkpoint_id=state_to_replay['checkpoint_id']) ``` === "Javascript" @@ -262,9 +279,9 @@ Let's show how to do this to edit the state at a particular point in time. Let's let lastMessage = stateToReplay['values']['messages'][-1]; // Let's now update the args for that tool call - lastMessage['tool_calls'][0]['args'] = {'query': 'current weather in SF'}; + lastMessage['tool_calls'][0]['args'] = { 'query': 'current weather in SF' }; - const newState = await client.threads.updateState(thread['thread_id'],{values:{"messages":[lastMessage]},checkpointId:stateToReplay['checkpoint_id']}); + const config = await client.threads.updateState(thread['thread_id'], { values: { "messages": [lastMessage] }, checkpointId: stateToReplay['checkpoint_id'] }); ``` === "CURL" @@ -294,7 +311,7 @@ Now we can rerun our graph with this new config, starting from the `new_state`, assistant["assistant_id"], # graph_id input=None, stream_mode="updates", - config={"configurable": {"checkpoint_id": new_state['configurable']['checkpoint_id']}} + checkpoint_id=config['checkpoint_id'] ): if chunk.data and chunk.event != "metadata": print(chunk.data) @@ -309,7 +326,7 @@ Now we can rerun our graph with this new config, starting from the `new_state`, { input: null, streamMode: "updates", - config: {"configurable": {"checkpoint_id": newState['configurable']['checkpoint_id']}}, + checkpointId: config['checkpoint_id'], } ); for await (const chunk of streamResponse) { @@ -323,33 +340,37 @@ Now we can rerun our graph with this new config, starting from the `new_state`, ```bash curl -s --request GET --url /threads//state | \ - jq -r '.config.configurable.checkpoint_id' | \ - sh -c ' - CHECKPOINT_ID="$1" - curl --request POST \ - --url /threads//runs/stream \ - --header "Content-Type: application/json" \ - --data "{\"assistant_id\": \"agent\", \"config\": {\"configurable\": {\"checkpoint_id\": \"$CHECKPOINT_ID\"}}, \"stream_mode\": [\"updates\"]}" | \ - sed "s/\r$//" | \ - awk " - /^event:/ { - if (data_content != \"\" && event_type != \"metadata\") { - print data_content \"\n\" - } - sub(/^event: /, \"\", \$0) - event_type = \$0 - data_content = \"\" - } - /^data:/ { - sub(/^data: /, \"\", \$0) - data_content = \$0 - } - END { - if (data_content != \"\" && event_type != \"metadata\") { - print data_content \"\n\" - } - }" - ' _ + jq -c '.checkpoint_id' | \ + curl --request POST \ + --url /threads//runs/stream \ + --header 'Content-Type: application/json' \ + --data "{ + \"assistant_id\": \"agent\", + \"checkpoint_id\": \"$1\", + \"stream_mode\": [ + \"updates\" + ] + }" | \ + sed 's/\r$//' | \ + awk ' + /^event:/ { + if (data_content != "" && event_type != "metadata") { + print data_content "\n" + } + sub(/^event: /, "", $0) + event_type = $0 + data_content = "" + } + /^data:/ { + sub(/^data: /, "", $0) + data_content = $0 + } + END { + if (data_content != "" && event_type != "metadata") { + print data_content "\n" + } + } + ' ``` Output: