Ops·Calls·Traces 이해하기

Ops·Calls·Traces 이해하기 (Weave 트레이싱 기초)

LLM 애플리케이션을 운영하다 보면 "이 호출 하나가 왜 이렇게 느렸지?", "프롬프트를 바꾸니 결과가 달라진 이유가 뭘까?" 같은 질문이 꼭 생기게 돼요. W&B Weave의 트레이싱 시스템은 바로 그런 질문에 답하기 위한 네 가지 개념, Ops, Calls, Traces, Threads 위에 만들어져 있어요. 이 페이지에서는 각 개념이 무엇이고 서로 어떻게 연결되는지 짚어볼게요.

출처: Understand Ops, Calls, and Traces — W&B Weave 공식 문서

Ops (연산)

Op는 버전이 붙어 추적되는 함수예요. 함수에 @weave.op() 데코레이터를 붙이거나(Python), weave.op()로 감싸면(TypeScript) Weave가 자동으로 그 함수의 코드·입력·출력·실행 메타데이터를 잡아줘요. Ops는 트레이싱, 평가 스코어러, 그리고 추적되는 모든 연산의 기본 재료가 됩니다.

@weave.op
async def my_function(){
  ...  }
// @noErrors
function myFunction() {
    ...
}

const myFunctionOp = weave.op(myFunction)

Calls (호출)

Call은 Op가 한 번 실행된 기록이에요. Op가 실행될 때마다 Weave는 다음 정보를 담는 Call을 만들어요.

  • 입력 인자
  • 출력 값
  • 소요 시간과 지연(latency)
  • 부모-자식 관계 (중첩 호출용)
  • 발생한 에러

이 Call들은 Weave UI에서 Traces로 보이게 되고, 디버깅·분석·평가의 데이터가 됩니다. Call 객체의 전체 구조와 속성은 Call 스키마 참조 문서에서 확인할 수 있어요.

Call은 OpenTelemetry 데이터 모델의 span과 비슷하다고 볼 수 있어요. Call은:

  • 같은 실행 컨텍스트를 공유하는 Call들의 묶음인 Trace에 속할 수 있고,
  • 부모 Call과 자식 Call을 가질 수 있어 나무(tree) 구조를 이룹니다.

Traces (트레이스)

Trace는 같은 실행 컨텍스트를 공유하는 Call 전체의 나무 구조예요. 각 Trace는 trace_id라는 ID를 가지는데, 이 ID로 Call들의 전체 트리를 조회할 수 있어요. 만약 Call의 ID로 정보를 가져오면 그 특정 Call 하나의 데이터만 돌아오고, 자식 Call들은 포함되지 않아요.

Threads (스레드)

Thread는 하나의 세션(session)이나 대화에 관련된 Trace들의 모음이에요. 개별 Call이 아니라 대화 전체를 분석하거나 채점하고 싶을 때 Thread를 씁니다. Threads, Traces, Calls의 관계를 그림으로 보면 이렇게 돼요.

Thread: "session-abc"
  ├── Turn 1 (trace_id: aaa) -> user says "Hi"
  │     ├── LLM call
  │     └── format response
  ├── Turn 2 (trace_id: bbb) -> user says "What is the capital of France?"
  │     ├── RAG retrieval
  │     ├── LLM call
  │     └── format response
  └── Turn 3 (trace_id: ccc) -> user says "Thanks"
        └── LLM call

더 알아보기