Skip to content

如何在同一线程上运行多个代理

在LangGraph Cloud中,线程并不显式地与特定代理关联。 这意味着你可以在同一个线程上运行多个代理,从而允许不同的代理从初始代理的进度继续进行。

在这个示例中,我们将创建两个代理,然后在同一线程上调用它们。 你会看到,第二个代理将使用第一个代理在线程中生成的检查点中的信息进行响应。

设置

from langgraph_sdk import get_client

client = get_client(url=<DEPLOYMENT_URL>)

openai_assistant = await client.assistants.create(
    graph_id="agent", config={"configurable": {"model_name": "openai"}}
)

# 应该始终有一个没有配置的默认助手
assistants = await client.assistants.search()
default_assistant = [a for a in assistants if not a["config"]][0]
import { Client } from "@langchain/langgraph-sdk";

const client = new Client({ apiUrl: <DEPLOYMENT_URL> });

const openAIAssistant = await client.assistants.create(
  { graphId: "agent", config: {"configurable": {"model_name": "openai"}}}
);

const assistants = await client.assistants.search();
const defaultAssistant = assistants.find(a => !a.config);
curl --request POST \
    --url <DEPLOYMENT_URL>/assistants \
    --header 'Content-Type: application/json' \
    --data '{
        "graph_id": "agent",
        "config": { "configurable": { "model_name": "openai" } }
    }' && \
curl --request POST \
    --url <DEPLOYMENT_URL>/assistants/search \
    --header 'Content-Type: application/json' \
    --data '{
        "limit": 10,
        "offset": 0
    }' | jq -c 'map(select(.config == null or .config == {})) | .[0]'

我们可以看到这些代理是不同的:

print(openai_assistant)
console.log(openAIAssistant);
curl --request GET \
    --url <DEPLOYMENT_URL>/assistants/<OPENAI_ASSISTANT_ID>

输出:

{
    "assistant_id": "db87f39d-b2b1-4da8-ac65-cf81beb3c766",
    "graph_id": "agent",
    "created_at": "2024-08-30T21:18:51.850581+00:00",
    "updated_at": "2024-08-30T21:18:51.850581+00:00",
    "config": {
        "configurable": {
            "model_name": "openai"
        }
    },
    "metadata": {}
}
print(default_assistant)
console.log(defaultAssistant);
curl --request GET \
    --url <DEPLOYMENT_URL>/assistants/<DEFAULT_ASSISTANT_ID>

输出:

{
    "assistant_id": "fe096781-5601-53d2-b2f6-0d3403f7e9ca",
    "graph_id": "agent",
    "created_at": "2024-08-08T22:45:24.562906+00:00",
    "updated_at": "2024-08-08T22:45:24.562906+00:00",
    "config": {},
    "metadata": {
        "created_by": "system"
    }
}

在线程上运行助手

运行OpenAI助手

现在,我们可以在线程上首先运行OpenAI助手。

thread = await client.threads.create()
input = {"messages": [{"role": "user", "content": "谁创造了你?"}]}
async for event in client.runs.stream(
    thread["thread_id"],
    openai_assistant["assistant_id"],
    input=input,
    stream_mode="updates",
):
    print(f"接收事件类型: {event.event}")
    print(event.data)
    print("\n\n")
const thread = await client.threads.create();
let input =  {"messages": [{"role": "user", "content": "谁创造了你?"}]}

const streamResponse = client.runs.stream(
  thread["thread_id"],
  openAIAssistant["assistant_id"],
  {
    input,
    streamMode: "updates"
  }
);
for await (const event of streamResponse) {
  console.log(`接收事件类型: ${event.event}`);
  console.log(event.data);
  console.log("\n\n");
}
thread_id=$(curl --request POST \
    --url <DEPLOYMENT_URL>/threads \
    --header 'Content-Type: application/json' \
    --data '{}' | jq -r '.thread_id') && \
curl --request POST \
    --url "<DEPLOYMENT_URL>/threads/${thread_id}/runs/stream" \
    --header 'Content-Type: application/json' \
    --data '{
        "assistant_id": <OPENAI_ASSISTANT_ID>,
        "input": {
            "messages": [
                {
                    "role": "user",
                    "content": "谁创造了你?"
                }
            ]
        },
        "stream_mode": [
            "updates"
        ]
    }' | \
    sed 's/\r$//' | \
    awk '
    /^event:/ {
        if (data_content != "") {
            print data_content "\n"
        }
        sub(/^event: /, "接收事件类型: ", $0)
        printf "%s...\n", $0
        data_content = ""
    }
    /^data:/ {
        sub(/^data: /, "", $0)
        data_content = $0
    }
    END {
        if (data_content != "") {
            print data_content "\n\n"
        }
    }
'

输出:

接收事件类型: metadata
{'run_id': '1ef671c5-fb83-6e70-b698-44dba2d9213e'}


接收事件类型: updates
{'agent': {'messages': [{'content': '我是由专注于开发和推进人工智能技术的研究组织OpenAI创建的。', 'additional_kwargs': {}, 'response_metadata': {'finish_reason': 'stop', 'model_name': 'gpt-4o-2024-05-13', 'system_fingerprint': 'fp_157b3831f5'}, 'type': 'ai', 'name': None, 'id': 'run-f5735b86-b80d-4c71-8dc3-4782b5a9c7c8', 'example': False, 'tool_calls': [], 'invalid_tool_calls': [], 'usage_metadata': None}]}}

运行默认助手

现在,我们可以在默认助手上运行它,并看到第二个助手意识到初始问题,并能回答“你呢?”这个问题:

input = {"messages": [{"role": "user", "content": "你呢?"}]}
async for event in client.runs.stream(
    thread["thread_id"],
    default_assistant["assistant_id"],
    input=input,
    stream_mode="updates",
):
    print(f"接收事件类型: {event.event}")
    print(event.data)
    print("\n\n")
let input =  {"messages": [{"role": "user", "content": "你呢?"}]}

const streamResponse = client.runs.stream(
  thread["thread_id"],
  defaultAssistant["assistant_id"],
  {
    input,
    streamMode: "updates"
  }
);
for await (const event of streamResponse) {
  console.log(`接收事件类型: ${event.event}`);
  console.log(event.data);
  console.log("\n\n");
}
curl --request POST \
    --url <DEPLOYMENT_URL>/threads/<THREAD_ID>/runs/stream \
    --header 'Content-Type: application/json' \
    --data '{
        "assistant_id": <DEFAULT_ASSISTANT_ID>,
        "input": {
            "messages": [
                {
                    "role": "user",
                    "content": "你呢?"
                }
            ]
        },
        "stream_mode": [
            "updates"
        ]
    }' | \
    sed 's/\r$//' | \
    awk '
    /^event:/ {
        if (data_content != "") {
            print data_content "\n"
        }
        sub(/^event: /, "接收事件类型: ", $0)
        printf "%s...\n", $0
        data_content = ""
    }
    /^data:/ {
        sub(/^data: /, "", $0)
        data_content = $0
    }
    END {
        if (data_content != "") {
            print data_content "\n\n"
        }
    }
'

输出:

接收事件类型: metadata
{'run_id': '1ef6722d-80b3-6fbb-9324-253796b1cd13'}


接收事件类型: updates
{'agent': {'messages': [{'content': [{'text': '我是由Anthropic公司创建的人工智能,而不是由OpenAI创建的。我之前提到OpenAI创建我是错误的。Anthropic公司使用高级语言模型和人工智能技术开发和训练了我。我将在未来更加小心地提供关于我的起源的准确信息。', 'type': 'text', 'index': 0}], 'additional_kwargs': {}, 'response_metadata': {'stop_reason': 'end_turn', 'stop_sequence': None}, 'type': 'ai', 'name': None, 'id': 'run-ebaacf62-9dd9-4165-9535-db432e4793ec', 'example': False, 'tool_calls': [], 'invalid_tool_calls': [], 'usage_metadata': {'input_tokens': 302, 'output_tokens': 72, 'total_tokens': 374}}}]}}

Comments