Skip to main content
W&B Weave _Threads_를 사용하면 LLM 애플리케이션의 멀티턴 대화를 추적하고 분석할 수 있습니다. Threads는 관련된 Call을 공통 thread_id로 묶어 주므로, 전체 세션을 시각화하고 여러 턴에 걸쳐 대화 수준의 메트릭을 추적할 수 있습니다. 스레드는 코드로 생성할 수 있으며, Weights & Biases UI에서 시각화할 수 있습니다. Threads를 시작하려면 다음 단계를 따르세요.
  1. Threads의 기본 개념을 익히세요.
  2. 일반적인 사용 패턴과 실제 사용 사례를 보여 주는 코드 샘플을 사용해 보세요.

사용 사례

스레드는 다음과 같은 항목을 구성하고 분석할 때 유용합니다.
  • 멀티턴 대화
  • 세션 기반 워크플로
  • 서로 관련된 일련의 오퍼레이션
스레드를 사용하면 컨텍스트별로 Call을 그룹화할 수 있으므로, 시스템이 여러 단계에 걸쳐 어떻게 응답하는지 더 쉽게 파악할 수 있습니다. 예를 들어 단일 사용자 세션, 에이전트의 연쇄적인 의사 결정, 또는 인프라 계층과 비즈니스 로직 계층에 걸친 복잡한 요청을 추적할 수 있습니다. 스레드와 턴으로 애플리케이션을 구성하면 Weights & Biases UI에서 더 깔끔한 메트릭을 얻고 가시성도 높일 수 있습니다. 모든 하위 수준 Op를 일일이 확인할 필요 없이 중요한 상위 수준 단계에 집중할 수 있습니다.

정의

스레드

_스레드_는 공통 대화 컨텍스트를 공유하는 관련 Call을 논리적으로 묶은 그룹입니다. 스레드의 특징은 다음과 같습니다.
  • 고유한 thread_id를 가집니다.
  • 하나 이상의 _턴_으로 구성됩니다.
  • 여러 Call에 걸쳐 컨텍스트를 유지합니다.
  • 하나의 완전한 사용자 세션 또는 상호작용 흐름을 나타냅니다.

턴

_턴_은 스레드 내의 상위 수준 오퍼레이션으로, UI의 스레드 뷰에서 개별 행으로 표시됩니다. 각 턴의 특징은 다음과 같습니다.
  • 대화 또는 워크플로의 논리적 단계 하나를 나타냅니다.
  • 스레드 컨텍스트의 직계 자식이며, 중첩된 하위 수준 Call을 포함할 수 있습니다(이러한 Call은 스레드 수준 통계에 표시되지 않음).

Call

_Call_은 애플리케이션에서 @weave.op 데코레이터가 적용된 함수가 실행되는 각각의 경우를 말합니다.
  • _턴 Call_은 새 턴을 시작하는 최상위 오퍼레이션입니다.
  • _Nested Call_은 턴 안에서 실행되는 하위 수준 오퍼레이션입니다.

트레이스

_트레이스_는 단일 오퍼레이션의 전체 호출 스택을 캡처합니다. 스레드는 동일한 논리적 대화 또는 세션에 속한 트레이스를 하나로 묶습니다. 즉, 스레드는 여러 턴으로 이루어지며, 각 턴은 대화의 한 부분에 해당합니다. 트레이스에 대한 자세한 내용은 트레이싱 개요를 참조하세요.

UI 개요

Weave 프로젝트 사이드바에서 Threads를 선택하면 Threads list view에 액세스할 수 있습니다.
Weave 사이드바의 Threads 아이콘

Threads list view

  • 프로젝트의 최근 스레드 목록을 표시합니다.
  • 열에는 턴 수, 시작 시간, 마지막 업데이트 시간이 있습니다.
  • 행을 클릭하면 해당 스레드의 세부 정보 드로어가 열립니다.
Threads list view

Threads 세부 정보 드로어

  • 행을 클릭하면 해당 행의 세부 정보 드로어가 열립니다.
  • 스레드에 속한 모든 턴을 표시합니다.
  • 턴은 시작된 순서대로 나열됩니다(소요 시간이나 종료 시간이 아닌 시작 시간 기준).
  • Call 수준의 메타데이터(지연 시간, 입력, 출력)가 포함됩니다.
  • 메시지 콘텐츠나 구조화된 데이터가 로깅된 경우 이를 함께 표시할 수 있습니다.
  • 스레드 세부 정보 드로어에서 턴을 열면 해당 턴의 전체 실행을 확인할 수 있습니다. 이를 통해 해당 턴에서 발생한 모든 중첩 오퍼레이션을 자세히 살펴볼 수 있습니다.
  • 턴에 LLM Call에서 추출된 메시지가 있으면 채팅 패널에 표시됩니다. 이러한 메시지는 대개 지원되는 인테그레이션(예: openai.ChatCompletion.create)이 수행한 Call에서 생성되며, 표시되려면 특정 조건을 충족해야 합니다. 자세한 내용은 채팅 뷰 동작을 참조하세요.

채팅 뷰 동작

채팅 패널에는 각 턴에서 발생한 LLM Call에서 추출한 구조화된 메시지 데이터가 표시됩니다. 이 뷰에서는 상호작용이 대화 형식으로 렌더링됩니다.
구조화된 LLM 메시지를 보여주는 Threads 채팅 패널

메시지로 간주되는 항목

Weave는 턴 내의 Call 중 LLM 공급자와 직접 상호작용하는 Call(예: 프롬프트를 보내고 응답을 받는 Call)에서 메시지를 추출합니다. 다른 Call 안에 중첩되지 않은 Call만 메시지로 표시됩니다. 이를 통해 중간 단계나 집계된 내부 로직이 중복으로 표시되지 않도록 합니다. 일반적으로 자동으로 패치되는 서드파티 SDK가 메시지를 생성합니다. 예를 들면 다음과 같습니다.
  • openai.ChatCompletion.create
  • anthropic.Anthropic.completion

메시지가 없는 경우

턴에서 메시지를 내보내지 않으면 채팅 패널에 해당 턴의 메시지 섹션이 빈 상태로 표시됩니다. 이 경우에도 채팅 패널에는 같은 스레드에 속한 다른 턴의 메시지가 표시될 수 있습니다.

턴과 채팅 간 상호 작용

  • 턴을 클릭하면 채팅 패널이 해당 턴의 메시지 위치로 스크롤됩니다(고정 동작).
  • 채팅 패널을 스크롤하면 턴 목록에서 해당하는 턴이 강조 표시됩니다.
턴을 클릭하면 해당 턴의 전체 트레이스를 열 수 있습니다. 왼쪽 상단에 뒤로 가기 버튼이 표시되며, 이 버튼을 클릭하면 스레드 세부 정보 뷰로 돌아갈 수 있습니다. 화면이 전환될 때 Weave는 UI 상태(예: 스크롤 위치)를 유지하지 않습니다.
스레드 뷰로 돌아가는 뒤로 가기 버튼이 있는 Threads 세부 정보 드로어

SDK 사용

다음 섹션에서는 Weave SDK를 사용하여 프로그래밍 방식으로 스레드를 생성하고 관리하는 방법을 설명합니다. 각 예시는 애플리케이션에서 턴과 스레드를 구성하는 서로 다른 전략을 보여줍니다. 대부분의 예시에서는 스텁 함수 안에 사용자의 LLM Call 또는 시스템 동작을 직접 구현해야 합니다.
  • 세션이나 대화를 추적하려면 weave.thread() 컨텍스트 매니저를 사용하세요.
  • 논리적 오퍼레이션을 턴 또는 중첩된 Call로 추적하려면 해당 오퍼레이션에 @weave.op 데코레이터를 적용하세요.
  • thread_id를 전달하면 Weave는 이 ID를 사용하여 해당 블록의 모든 오퍼레이션을 같은 스레드로 그룹화합니다. thread_id를 생략하면 Weave가 고유한 ID를 자동으로 생성합니다.
weave.thread()는 thread_id 속성을 가진 ThreadContext 객체를 반환합니다. 이 ID는 로깅하거나 재사용하거나 다른 시스템에 전달할 수 있습니다. 중첩된 weave.thread() 컨텍스트는 같은 thread_id를 재사용하지 않는 한 항상 새 스레드를 시작합니다. 자식 컨텍스트가 종료되어도 부모 컨텍스트는 중단되거나 덮어써지지 않습니다. 따라서 앱 로직에 따라 분기된 스레드 구조나 계층형 스레드 오케스트레이션을 구성할 수 있습니다.

기본 스레드 생성

다음 코드 샘플은 weave.thread()를 사용하여 하나 이상의 오퍼레이션을 공통 thread_id로 묶는 방법을 보여줍니다. 애플리케이션에서 Threads를 가장 간단하게 시작하는 방법입니다.

에이전트 루프 수동 구현

이 예제는 @weave.op 데코레이터와 weave.thread() 컨텍스트 관리를 사용하여 대화형 에이전트를 수동으로 정의하는 방법을 보여 줍니다. process_user_message를 호출할 때마다 스레드에 새 턴이 생성됩니다. 에이전트 루프를 직접 구축하면서 컨텍스트와 중첩 처리 방식을 전체적으로 제어하고 싶을 때 이 패턴을 사용하세요. 수명이 짧은 상호 작용에는 자동 생성된 스레드 ID를 사용하고, 여러 세션에 걸쳐 스레드 컨텍스트를 유지하려면 맞춤형 세션 ID(예: user_session_123)를 전달하세요.

호출 깊이가 불균형한 수동 에이전트

이 예제는 스레드 컨텍스트를 적용하는 방식에 따라 호출 스택의 서로 다른 깊이에서 턴을 정의할 수 있음을 보여 줍니다. 이 샘플은 두 공급자(OpenAI와 Anthropic)를 사용하며, 공급자마다 턴 경계에 도달하기까지의 호출 깊이가 다릅니다. 모든 턴은 동일한 thread_id를 공유하지만, 턴 경계가 나타나는 스택 수준은 공급자 로직에 따라 달라집니다. 이 방식은 백엔드마다 Call을 다르게 트레이스하면서도 이를 같은 스레드로 묶어야 할 때 유용합니다.

이전 세션 재개

이전에 시작한 세션을 재개하여 같은 스레드에 Call을 계속 추가해야 할 때가 있습니다. 반대로 기존 세션을 재개할 수 없어 새 스레드를 시작해야 할 때도 있습니다. 스레드 재개를 선택적으로 구현할 때는 thread_id 매개변수를 None으로 두지 마세요. 스레드 그룹화가 비활성화됩니다. 대신 항상 유효한 스레드 ID를 제공하세요. 새 스레드를 만들려면 generate_id()와 같은 함수로 고유 식별자를 생성하세요. thread_id를 지정하지 않으면 Weave 내부 구현에서 임의의 UUID v7을 자동으로 생성합니다. 직접 작성한 generate_id() 함수에서 이 동작을 그대로 구현하거나, 원하는 고유 문자열 값을 사용해도 됩니다.

중첩 스레드

이 예제에서는 서로 연계된 여러 스레드를 사용하여 복잡한 애플리케이션을 구성하는 방법을 보여줍니다. 각 계층은 자체 스레드 컨텍스트에서 실행되므로 관심사를 깔끔하게 분리할 수 있습니다. 상위 애플리케이션 스레드는 공유 ThreadContext로 스레드 ID를 설정하여 이러한 계층을 조율합니다. 시스템의 여러 부분을 하나의 공유 세션에 연결해 두면서도 각 부분을 독립적으로 분석하거나 모니터링하려면 이 패턴을 사용하세요.

API 사양

다음 섹션에서는 Threads 쿼리 엔드포인트와 해당 요청 및 응답 스키마, 그리고 프로그래밍 방식으로 스레드 데이터를 조회할 때 사용할 수 있는 일반적인 쿼리 패턴을 설명합니다.

엔드포인트

엔드포인트: POST /threads/query

요청 스키마

응답 스키마

최근 활성 스레드 쿼리

이 예제는 가장 최근에 업데이트된 스레드 50개를 가져옵니다. my-project를 실제 프로젝트 ID로 바꾸세요.

활동 수준별 스레드 쿼리

이 예제는 턴 수를 기준으로 정렬하여 가장 활발한 스레드 20개를 조회합니다.

최근 스레드만 쿼리하기

이 예제는 최근 24시간 이내에 시작된 스레드를 반환합니다. timedelta의 days 값을 조정하여 시간 윈도우를 변경할 수 있습니다.
마지막 수정일 2026년 9월 30일