동시 실행 인터럽트하기

동시 실행 인터럽트하기 (Interrupt concurrent)

이 가이드는 더블-텍스팅(double-texting)이 무엇인지 알고 있다고 가정해요. 자세한 내용은 더블-텍스팅 개념 가이드에서 배울 수 있습니다.

이 가이드는 더블 텍스팅에 대한 interrupt 옵션을 다룹니다. 이 옵션은 그래프의 이전 실행을 인터럽트하고 더블 텍스트로 새 실행을 시작합니다. 이 옵션은 첫 번째 실행을 삭제하지 않지만, 데이터베이스에 유지하면서 상태를 interrupted로 설정합니다. 아래는 interrupt 옵션을 사용하는 빠른 예시입니다.

출처: 문서

본문

설정 (Setup)

먼저 JS와 cURL 모델 출력을 출력하기 위한 간단한 헬퍼 함수를 정의하겠습니다 (Python을 사용한다면 건너뛸 수 있어요):

function prettyPrint(m) {
  const padded = " " + m['type'] + " ";
  const sepLen = Math.floor((80 - padded.length) / 2);
  const sep = "=".repeat(sepLen);
  const secondSep = sep + (padded.length % 2 ? "=" : "");

  console.log(`${sep}${padded}${secondSep}`);
  console.log("\n\n");
  console.log(m.content);
}
# PLACE THIS IN A FILE CALLED pretty_print.sh
pretty_print() {
  local type="$1"
  local content="$2"
  local padded=" $type "
  local total_width=80
  local sep_len=$(( (total_width - ${#padded}) / 2 ))
  local sep=$(printf '=%.0s' $(eval "echo {1.."${sep_len}"}"))
  local second_sep=$sep
  if (( (total_width - ${#padded}) % 2 )); then
    second_sep="${second_sep}="
  fi

  echo "${sep}${padded}${second_sep}"
  echo
  echo "$content"
}

이제 필요한 패키지를 가져오고 클라이언트, 어시스턴트, 스레드를 인스턴스화하겠습니다.

import asyncio

from langchain_core.messages import convert_to_messages
from langgraph_sdk import get_client

client = get_client(url=<DEPLOYMENT_URL>)
# "agent"라는 이름으로 배포된 그래프를 사용
assistant_id = "agent"
thread = await client.threads.create()
import { Client } from "@langchain/langgraph-sdk";

const client = new Client({ apiUrl: <DEPLOYMENT_URL> });
// "agent"라는 이름으로 배포된 그래프를 사용
const assistantId = "agent";
const thread = await client.threads.create();
curl --request POST \
  --url <DEPLOYMENT_URL>/threads \
  --header 'Content-Type: application/json' \
  --data '{}'

실행 생성 (Create runs)

이제 두 개의 실행을 시작하고 두 번째 실행이 완료될 때까지 조인할 수 있습니다:

# 첫 번째 실행은 인터럽트될 것
interrupted_run = await client.runs.create(
    thread["thread_id"],
    assistant_id,
    input={"messages": [{"role": "user", "content": "what's the weather in sf?"}]},
)
# 첫 번째 실행의 부분 출력을 얻기 위해 잠시 대기
await asyncio.sleep(2)
run = await client.runs.create(
    thread["thread_id"],
    assistant_id,
    input={"messages": [{"role": "user", "content": "what's the weather in nyc?"}]},
    multitask_strategy="interrupt",
)
# 두 번째 실행이 완료될 때까지 대기
await client.runs.join(thread["thread_id"], run["run_id"])
// 첫 번째 실행은 인터럽트될 것
let interruptedRun = await client.runs.create(
  thread["thread_id"],
  assistantId,
  { input: { messages: [{ role: "human", content: "what's the weather in sf?" }] } }
);
// 첫 번째 실행의 부분 출력을 얻기 위해 잠시 대기
await new Promise(resolve => setTimeout(resolve, 2000));

let run = await client.runs.create(
  thread["thread_id"],
  assistantId,
  {
    input: { messages: [{ role: "human", content: "what's the weather in nyc?" }] },
    multitaskStrategy: "interrupt"
  }
);

// 두 번째 실행이 완료될 때까지 대기
await client.runs.join(thread["thread_id"], run["run_id"]);
curl --request POST \
--url <DEPLOY<ENT_URL>>/threads/<THREAD_ID>/runs \
--header 'Content-Type: application/json' \
--data "{
  \"assistant_id\": \"agent\",
  \"input\": {\"messages\": [{\"role\": \"human\", \"content\": \"what\'s the weather in sf?\"}]},
}" && sleep 2 && curl --request POST \
--url <DEPLOY<ENT_URL>>/threads/<THREAD_ID>/runs \
--header 'Content-Type: application/json' \
--data "{
  \"assistant_id\": \"agent\",
  \"input\": {\"messages\": [{\"role\": \"human\", \"content\": \"what\'s the weather in nyc?\"}]},
  \"multitask_strategy\": \"interrupt\"
}" && curl --request GET \
--url <DEPLOYMENT_URL>/threads/<THREAD_ID>/runs/<RUN_ID>/join

실행 결과 보기 (View run results)

스레드에 첫 번째 실행의 부분 데이터 + 두 번째 실행의 데이터가 있는 것을 볼 수 있습니다.

state = await client.threads.get_state(thread["thread_id"])

for m in convert_to_messages(state["values"]["messages"]):
    m.pretty_print()
const state = await client.threads.getState(thread["thread_id"]);

for (const m of state['values']['messages']) {
  prettyPrint(m);
}
source pretty_print.sh && curl --request GET \
--url <DEPLOYMENT_URL>/threads/<THREAD_ID>/state | \
jq -c '.values.messages[]' | while read -r element; do
    type=$(echo "$element" | jq -r '.type')
    content=$(echo "$element" | jq -r '.content | if type == "array" then tostring else . end')
    pretty_print "$type" "$content"
done

출력:

================================ Human Message =================================

what's the weather in sf?
================================== Ai Message ==================================

[{'id': 'toolu_01MjNtVJwEcpujRGrf3x6Pih', 'input': {'query': 'weather in san francisco'}, 'name': 'tavily_search_results_json', 'type': 'tool_use'}]
Tool Calls:
tavily_search_results_json (toolu_01MjNtVJwEcpujRGrf3x6Pih)
Call ID: toolu_01MjNtVJwEcpujRGrf3x6Pih
Args:
query: weather in san francisco
================================= Tool Message =================================
Name: tavily_search_results_json

[{"url": "https://www.wunderground.com/hourly/us/ca/san-francisco/KCASANFR2002/date/2024-6-18", "content": "High 64F. Winds W at 10 to 20 mph. A few clouds from time to time. Low 49F. Winds W at 10 to 20 mph. Temp. San Francisco Weather Forecasts. Weather Underground provides local & long-range weather ..."}]
================================ Human Message =================================

what's the weather in nyc?
================================== Ai Message ==================================

[{'id': 'toolu_01KtE1m1ifPLQAx4fQLyZL9Q', 'input': {'query': 'weather in new york city'}, 'name': 'tavily_search_results_json', 'type': 'tool_use'}]
Tool Calls:
tavily_search_results_json (toolu_01KtE1m1ifPLQAx4fQLyZL9Q)
Call ID: toolu_01KtE1m1ifPLQAx4fQLyZL9Q
Args:
query: weather in new york city
================================= Tool Message =================================
Name: tavily_search_results_json

[{"url": "https://www.accuweather.com/en/us/new-york/10021/june-weather/349727", "content": "Get the monthly weather forecast for New York, NY, including daily high/low, historical averages, to help you plan ahead."}]
================================== Ai Message ==================================

The search results provide weather forecasts and information for New York City. Based on the top result from AccuWeather, here are some key details about the weather in NYC:

* This is a monthly weather forecast for New York City for the month of June.
* It includes daily high and low temperatures to help plan ahead.
* Historical averages for June in NYC are also provided as a reference point.
* More detailed daily or hourly forecasts with precipitation chances, humidity, wind, etc. can be found by visiting the AccuWeather page.

In summary, the search provides a convenient overview of the expected weather conditions in New York City over the next month to give you an idea of what to prepare for if traveling or making plans there. Let me know if you need any other details!

원래 인터럽트된 실행이 실제로 인터럽트되었는지 확인합니다.

print((await client.runs.get(thread["thread_id"], interrupted_run["run_id"]))["status"])
console.log((await client.runs.get(thread['thread_id'], interruptedRun["run_id"]))["status"])

출력:

'interrupted'

더 알아보기 (Learn more)