From 388a9643a575b73029ee8d17eae6c0bb4f6c449c Mon Sep 17 00:00:00 2001 From: Isaac Francisco <78627776+isahers1@users.noreply.github.com> Date: Thu, 15 Aug 2024 11:19:18 -0700 Subject: [PATCH] [docs]: copying threads (#1350) * wip * wip * wip * vadym comments --- docs/docs/cloud/how-tos/copy_threads.md | 132 ++++++++++++++++++++++++ docs/docs/cloud/how-tos/index.md | 3 +- docs/mkdocs.yml | 1 + 3 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 docs/docs/cloud/how-tos/copy_threads.md diff --git a/docs/docs/cloud/how-tos/copy_threads.md b/docs/docs/cloud/how-tos/copy_threads.md new file mode 100644 index 000000000..9a27282b2 --- /dev/null +++ b/docs/docs/cloud/how-tos/copy_threads.md @@ -0,0 +1,132 @@ +# Copying Threads + +You may wish to copy (i.e. "fork") an existing thread in order to keep the existing thread's history and create independent runs that do not affect the original thread. This guide shows how you can do that. + +## Setup + +This code assumes you already have a thread to copy. You can read about what a thread is [here](https://langchain-ai.github.io/langgraph/cloud/concepts/api/#threads) and learn how to stream a run on a thread in [these how-to guides](https://langchain-ai.github.io/langgraph/cloud/how-tos/#streaming). + +### SDK initialization + +First, we need to setup our client so that we can communicate with our hosted graph: + +=== "Python" + + ```python + from langgraph_sdk import get_client + client = get_client(url="") + assistant_id = "agent" + thread = await client.threads.create() + ``` + +=== "Javascript" + + ```js + import { Client } from "@langchain/langgraph-sdk"; + + const client = new Client({ apiUrl:"" }); + const assistantId = agent; + const thread = await client.threads.create(); + ``` + +=== "CURL" + + ```bash + curl --request POST \ + --url /threads \ + --header 'Content-Type: application/json' \ + --data '{ + "metadata": {} + }' + ``` + +## Copying a thread + +The code below assumes that a thread you'd like to copy already exists. + +Copying a thread will create a new thread with the same history as the existing thread, and then allow you to continue executing runs. + +### Create copy + +=== "Python" + + ```python + copied_thread = await client.threads.copy() + ``` + +=== "Javascript" + + ```js + let copiedThread = await client.threads.copy(); + ``` + +=== "CURL" + + ```bash + curl --request POST --url /threads//copy \ + --header 'Content-Type: application/json' + ``` + +### Verify copy + +We can verify that the history from the prior thread did indeed copy over correctly: + +=== "Python" + + ```python + def remove_thread_id(d): + if 'metadata' in d and 'thread_id' in d['metadata']: + del d['metadata']['thread_id'] + return d + + original_thread_history = list(map(remove_thread_id,await client.threads.get_history())) + copied_thread_history = list(map(remove_thread_id,await client.threads.get_history(copied_thread['thread_id']))) + + # Compare the two histories + assert original_thread_history == copied_thread_history + # if we made it here the assertion passed! + print("The histories are the same.") + ``` + +=== "Javascript" + + ```js + function removeThreadId(d) { + if (d.metadata && d.metadata.thread_id) { + delete d.metadata.thread_id; + } + return d; + } + + // Assuming `client.threads.getHistory(threadId)` is an async function that returns a list of dicts + async function compareThreadHistories(threadId, copiedThreadId) { + const originalThreadHistory = (await client.threads.getHistory(threadId)).map(removeThreadId); + const copiedThreadHistory = (await client.threads.getHistory(copiedThreadId)).map(removeThreadId); + + // Compare the two histories + console.assert(JSON.stringify(originalThreadHistory) === JSON.stringify(copiedThreadHistory)) + // if we made it here the assertion passed! + console.log("The histories are the same."); + } + + // Example usage + compareThreadHistories(, copiedThread.thread_id); + ``` + +=== "CURL" + + ```bash + if diff <( + curl --request GET --url /threads//history | jq -S 'map(del(.metadata.thread_id))' + ) <( + curl --request GET --url /threads//history | jq -S 'map(del(.metadata.thread_id))' + ) >/dev/null; then + echo "The histories are the same." + else + echo "The histories are different." + fi + ``` + +Output: + + The histories are the same. \ No newline at end of file diff --git a/docs/docs/cloud/how-tos/index.md b/docs/docs/cloud/how-tos/index.md index 59db860da..255490d32 100644 --- a/docs/docs/cloud/how-tos/index.md +++ b/docs/docs/cloud/how-tos/index.md @@ -73,4 +73,5 @@ Other guides that may prove helpful! - [How to configure agents](cloud_examples/configuration_cloud.ipynb) - [How to convert LangGraph calls to LangGraph cloud calls](cloud_examples/langgraph_to_langgraph_cloud.ipynb) - [How to integrate webhooks](cloud_examples/webhooks.ipynb) -- [How to check status of your threads](./check_thread_status.md) \ No newline at end of file +- [How to copy threads](./copy_threads.md) +- [How to check status of your threads](./check_thread_status.md) diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 7daf741f7..d4c24a322 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -231,6 +231,7 @@ nav: - Configure Agents: "cloud/how-tos/cloud_examples/configuration_cloud.ipynb" - Convert LangGraph calls to LangGraph Cloud calls: "cloud/how-tos/cloud_examples/langgraph_to_langgraph_cloud.ipynb" - Integrate Webhooks: 'cloud/how-tos/cloud_examples/webhooks.ipynb' + - Copy Threads: 'cloud/how-tos/copy_threads.md' - Check Status of Threads: "cloud/how-tos/check_thread_status.md" - Conceptual Guides: - API Concepts: "cloud/concepts/api.md"