스팬 타입 구성

스팬 타입 구성 (Configure Span Types)

스팬을 타입별로 분류하고 타입별 속성을 설정하는 방법을 다루는 페이지예요. confident-trace의 init()이 지원하는 통합으로 잡은 호출에는 이미 올바른 스팬 타입을 할당해주지만, 직접 만드는 스팬의 타입을 고를 때는 이 페이지를 참고하면 된답니다. 타입을 분류하면 Confident AI에서 더 맞춤화된 UI를 만들 수 있어요.

출처: 문서

본문

confident-trace의 init()은 지원하는 통합으로 잡은 호출에 이미 올바른 스팬 타입을 할당해요. 이 페이지는 직접 만드는 스팬의 타입을 고를 때를 위한 것이에요.

개요 (Overview)

스팬 타입은 선택 사항이지만 AI 앱에서 가장 흔한 구성 요소 유형을 분류할 수 있게 해줘요:

  • LLMs: 사용한 모델과 프로바이더, 토큰 사용량, 토큰당 비용을 추적해요.
  • Retrievers: 검색 컨텍스트(벡터 저장소나 지식 베이스에서 반환된 청크)를 추적해요.
  • Tools: 함수 호출 동작 — 어떤 툴이, 어떤 인자로, 무엇을 반환했는지 — 를 추적해요.
  • Agents: 요청·에이전트 실행·핸드오프 주위의 오케스트레이션을 그룹화해서 중첩된 LLM·리트리버·툴 스팬이 그 아래로 합쳐지게 해요.

이것은 스팬을 만들 때 type 파라미터로 설정해요. 스팬 타입을 분류하면 Confident AI에서 더 맞춤화된 UI를 만들 수 있고, 각 스팬 타입에 특화된 온라인 평가를 보거나, 일반적인 metadata 대신 타입별 속성을 설정할 수 있어요.

Type Use for Type-specific fields
agent Request handlers, orchestration, agent runs —
llm Model calls not covered by an integration model, provider, input_token_count, output_token_count, cost_per_*_token
retriever Search, vector lookups, document fetches retrieval_context
tool Function or API execution Also sets the GenAI tool operation and name
custom Anything else (the default) —

모든 타입은 공유 필드 input, output, metadata, context, retrieval_context, expected_output, tools_called, expected_tools를 받아들여요. 모든 타입에 대해 하나의 update_span() / updateSpan()이 있어요 — 타입마다 다른 업데이트 함수가 필요하지 않아요.

Confident AI는 UI에서 스팬 타입별 맞춤 표시를 제공해요. 예를 들어 LLM에는 프롬프트를, 리트리버에는 검색된 청크를 표시하죠.

Span Types on Confident AI

타입 있는 스팬 만들기 (Create Typed Spans)

스팬을 만들 때 type을 전달해요. 전체 함수를 감싸거나(데코레이터 또는 재사용 가능한 래퍼로) 인라인 코드 블록을 추적할 수 있어요 — 둘 다 현재 활성인 것 아래에 중첩된 스팬을 만들어요.

Python

from confident_trace import init, span, shutdown

init()

@span(type="tool", name="lookup-order")
def lookup_order(order_id: str):
    return {"order_id": order_id, "status": "shipped"}

def handle_request(order_id: str):
    with span("support-request", type="agent"):
        return lookup_order(order_id)

try:
    handle_request("order-42")
finally:
    shutdown()

TypeScript

import { init, span, withSpan } from "confident-trace";

const runtime = init();

const lookupOrder = span(
  { name: "lookup-order", type: "tool" },
  (orderId: string) => ({ orderId, status: "shipped" }),
);

const handleRequest = async (orderId: string) =>
  withSpan({ name: "support-request", type: "agent" }, async () => lookupOrder(orderId));

try {
  await handleRequest("order-42");
} finally {
  await runtime.shutdown();
}

패키지가 로드될 때 통합이 연결되도록 Node preload로 진입점을 실행하는 걸 잊지 마세요.

데코레이터와 래퍼는 함수의 인자를 스팬 input으로, 반환값을 스팬 output으로 캡처해요. withSpan 콜백은 반환값만 캡처해요. update_span() / updateSpan()으로 명시적으로 설정한 것은 항상 자동 캡처된 것을 이기고, 단일 스팬에 대해 capture_content=False / captureContent: false로 자동 캡처를 끌 수 있어요.

추적된 작업 전에 시작 시 init()을 한 번 호출하세요. @span, span(), withSpan()은 그 자체로는 스팬을 만들지도 내보내지도 않아요 — 초기화된 런타임이 없으면 데코레이팅된 함수는 그냥 변경되지 않고 실행되며 업데이트 헬퍼는 아무것도 하지 않아요. 타입 있는 스팬이 나타나지 않는다면 제일 먼저 이것을 확인하세요. initialize once를 참고해요.

아래 단원은 각 타입을 다뤄요. 예시는 간결함을 위해 init() / shutdown()을 생략했어요 — 실제 앱에서는 위와 정확히 같이 진입점에서 한 번, 종료 시 한 번 실행돼요.

LLM 스팬 (LLM Spans)

LLM 스팬은 언어 모델에 대한 호출을 나타내요. 호출의 입력·출력·모델·토큰 사용량을 추적하며, 이것이 Confident AI의 비용 추적을 가능하게 해요.

모델 호출에는 가능하면 프로바이더 통합(provider integration)을 선호하세요. 통합은 메시지·모델·사용량을 자동으로 기록하고, 같은 호출 주위에 두 번째 llm 스팬을 추가하면 UI에서 중복으로 표시되거든요. type="llm"은 통합이 다루지 않는 모델 호출 — 자체 호스팅 모델, 커스텀 게이트웨이 등 — 에만 직접 사용하세요.

Python

from confident_trace import span, update_span

@span(type="llm", name="custom-model", model="my-model", provider="custom")
def call_model(prompt: str) -> str:
    completion = my_gateway.generate(prompt)
    update_span(
        input=prompt, output=completion.text,
        input_token_count=completion.usage.input_tokens,
        output_token_count=completion.usage.output_tokens,
        cost_per_input_token=0.000001, cost_per_output_token=0.000002,
    )
    return completion.text

LLM 전용 선택 필드는 다섯(FIVE) 개가 있고, @span(...)에 전달하거나 update_span()에 전달할 수 있어요:

  • [Optional] model: 사용된 모델, 타입 str.
  • [Optional] provider: 모델의 프로바이더, 타입 str.
  • [Optional] input_token_count: 입력의 토큰 수, 타입 int.
  • [Optional] output_token_count: 생성된 응답의 토큰 수, 타입 int.
  • [Optional] cost_per_input_token / cost_per_output_token: 토큰당 USD(백만 당이 아님)로 표시하는 토큰당 비용, 타입 float.

TypeScript

import { span, updateSpan } from "confident-trace";

const callModel = span(
  { name: "custom-model", type: "llm", model: "my-model", provider: "custom" },
  async (prompt: string) => {
    const completion = await myGateway.generate(prompt);
    updateSpan({
      input: prompt, output: completion.text,
      inputTokenCount: completion.usage.inputTokens,
      outputTokenCount: completion.usage.outputTokens,
      costPerInputToken: 0.000001, costPerOutputToken: 0.000002,
    });
    return completion.text;
  },
);

LLM 전용 선택 필드는 다섯(FIVE) 개가 있고, span 옵션이나 updateSpan()에 전달할 수 있어요:

  • [Optional] model: 사용된 모델, 타입 string.
  • [Optional] provider: 모델의 프로바이더, 타입 string.
  • [Optional] inputTokenCount: 입력의 토큰 수, 타입 number.
  • [Optional] outputTokenCount: 생성된 응답의 토큰 수, 타입 number.
  • [Optional] costPerInputToken / costPerOutputToken: 토큰당 USD(백만 당이 아님)로 표시하는 토큰당 비용, 타입 number.

토큰당 비용이 설정되지 않으면, 토큰 수만 제공해도 그쪽의 비용이 계산되지 않아요 — Confident AI는 대신 프로젝트의 모델 비용(model costs)이나 자동 가격 조회로 폴백해요. 입력과 출력은 독립적으로 결정돼요.

LLM 필드는 LLM 스팬에서만 의미가 있어요. 다른 스팬 타입이 활성인 동안 update_span()에 전달하면 일반 필드(input, output, metadata, …)는 여전히 적용되지만 LLM 필드는 일회성 경고와 함께 건너뛰어져요. 토큰 비용 추적에 대한 자세한 내용은 여기를 클릭하세요.

리트리버 스팬 (Retriever Spans)

리트리버(Retriever) 스팬은 벡터 저장소나 지식 베이스에서 관련 정보를 가져오는 컴포넌트를 나타내요. RAG(Retrieval-Augmented Generation) 파이프라인의 핵심 부분이고, 무엇을 검색했는지 기록하는 것이 나중에 스팬에서 contextual relevancy·faithfulness 같은 메트릭을 실행할 수 있게 해줘요.

Python

from confident_trace import span, update_span

@span(type="retriever", name="search-docs")
def search_docs(query: str) -> list[str]:
    documents = vector_store.similarity_search(query, k=3)
    update_span(input=query, retrieval_context=documents)
    return documents

리트리버 전용 선택 필드는 하나(ONE)예요:

  • [Optional] retrieval_context: 검색된 청크, 타입 list[str].

TypeScript

import { span, updateSpan } from "confident-trace";

const searchDocs = span(
  { name: "search-docs", type: "retriever" },
  async (query: string) => {
    const documents = await vectorStore.similaritySearch(query, 3);
    updateSpan({ input: query, retrievalContext: documents });
    return documents;
  },
);

리트리버 전용 선택 필드는 하나(ONE)예요:

  • [Optional] retrievalContext: 검색된 청크, 타입 string[].

retrieval_context / retrievalContext를 일반 문자열 리스트로 전달하세요 — 청크당 한 항목 — 그러면 Confident AI가 각 청크를 별도로 표시하고 RAG 메트릭에 그대로 공급할 수 있어요.

툴 스팬 (Tool Spans)

툴(Tool) 스팬은 에이전트가 특정 작업을 수행하기 위해 호출할 수 있는 함수를 나타내요. LLM 애플리케이션의 함수 호출(function calling)에 흔히 쓰여요. 툴 스팬은 스팬 이름에서 GenAI execute_tool 연산과 툴 이름도 설정하므로, UI에서 툴 호출로 렌더링돼요.

Python

from confident_trace import span, update_span, update_trace

@span(type="tool", name="lookup-order")
def lookup_order(order_id: str) -> dict:
    result = orders_db.get(order_id)
    update_span(input={"order_id": order_id}, output=result)
    update_trace(tools_called=[{"name": "lookup-order", "input": {"order_id": order_id}, "output": result}])
    return result

TypeScript

import { span, updateSpan, updateTrace } from "confident-trace";

const lookupOrder = span(
  { name: "lookup-order", type: "tool" },
  async (orderId: string) => {
    const result = await ordersDb.get(orderId);
    updateSpan({ input: { orderId }, output: result });
    updateTrace({ toolsCalled: [{ name: "lookup-order", input: { orderId }, output: result }] });
    return result;
  },
);

툴 스팬 타입에는 필수 파라미터 하나와 선택 파라미터 하나가 있어요:

  • type: 스팬의 타입. 툴 스팬에는 "tool"이어야 해요.
  • [Optional] name: Confident AI(그리고 GenAI 툴 이름)의 표시 이름을 지정하는 문자열. 래핑된 함수의 이름이 기본값이에요.

input과 output을 툴의 인자와 결과로 설정하세요. 에이전트가 어떤 툴을 트레이스 레벨에서 호출했는지 — 툴 정확성 메트릭이 읽는 것 — 도 기록하고 싶다면, 위처럼 tools_called / toolsCalled를 일반 JSON 객체로 update_trace() / updateTrace()에 전달하세요.

에이전트 스팬 (Agent Spans)

에이전트(Agent) 스팬은 결정을 내리고 다른 컴포넌트와 상호작용할 수 있는 자율적 주체를 나타내요. 추론 에이전트(thinking agents)나 멀티에이전트 시스템을 구현할 때 특히 유용하고, 모든 LLM·리트리버·툴 스팬이 그 아래 중첩되도록 요청의 가장 바깥쪽 스팬으로 자연스러운 타입이에요.

Python

from confident_trace import span, update_span

@span(type="agent", name="support-agent")
def support_agent(query: str) -> str:
    update_span(input=query, metadata={"channel": "web"})
    context = search_docs(query)
    answer = generate(query, context)
    update_span(output=answer)
    return answer

TypeScript

import { span, updateSpan } from "confident-trace";

const supportAgent = span(
  { name: "support-agent", type: "agent" },
  async (query: string) => {
    updateSpan({ input: query, metadata: { channel: "web" } });
    const context = await searchDocs(query);
    const answer = await generate(query, context);
    updateSpan({ output: answer });
    return answer;
  },
);

에이전트 스팬 타입에는 필수 파라미터 하나와 선택 파라미터 하나가 있어요:

  • type: 스팬의 타입. 에이전트 스팬에는 "agent"이어야 해요.
  • [Optional] name: Confident AI의 표시 이름을 지정하는 문자열. 래핑된 함수의 이름이 기본값이에요.

에이전트는 다른 에이전트 안에 중첩될 수 있어서, 계층적 에이전트 아키텍처를 구현하는 데 유용해요. 예를 들어 "supervisor" 에이전트가 전문 에이전트 간의 통신을 조정할 수 있어요 — 각각이 supervisor 아래 중첩된 하나의 agent 스팬이죠.

커스텀 스팬 (Custom Spans)

모든 타입 중 가장 유연한 type(그리고 type을 제공하지 않을 때의 기본 타입)인 커스텀 스팬은 계층 구조를 만들거나 관련 스팬을 함께 그룹화하는 데 필수적이에요. 추적 데이터를 조직하는 데 유연성을 제공하고 공유 필드만 받아들여요.

Python

from confident_trace import span, update_span

@span(name="postprocess")
def postprocess(answer: str) -> str:
    cleaned = strip_citations(answer)
    update_span(output=cleaned, metadata={"step": "postprocess"})
    return cleaned

TypeScript

import { span, updateSpan } from "confident-trace";

const postprocess = span({ name: "postprocess" }, (answer: string) => {
  const cleaned = stripCitations(answer);
  updateSpan({ output: cleaned, metadata: { step: "postprocess" } });
  return cleaned;
});

커스텀 스팬 타입에는 선택 파라미터 하나가 있어요:

  • [Optional] name: 이 커스텀 스팬이 Confident AI에서 어떻게 표시되는지 지정하는 문자열. 래핑된 함수의 이름이 기본값이에요.

커스텀 스팬의 input과 output은 기본적으로 함수의 입력 인자와 반환값이지만, 동적으로 설정할 수도 있어요.

활성 스팬 업데이트 (Update the Active Span)

update_span() / updateSpan()은 현재 활성인 스팬에 쓰므로, 스팬 본문 안에서 호출하세요. 원하는 만큼 여러 번 호출할 수 있어요 — 생략된 필드는 그대로 유지되는데 한 가지 예외는, 공급된 metadata 객체는 병합하는 대신 이전 것을 대체한다는 점이에요.

두 업데이트 헬퍼 모두 쓸 활성 스팬이 필요해요 — 스팬 밖(또는 스팬이 끝난 후)에서는 조용히 아무것도 하지 않으므로, 필드가 나타나지 않으면 호출이 스팬 본문 안에 있는지 확인하세요. update_trace를 호출할 스팬이 없다면 대신 호출 주위에 trace_context / traceContext를 열어요. set trace attributes without a span를 참고하세요.

트레이스 레벨 필드 (Trace-Level Fields)

update_span()은 절대 트레이스 필드를 쓰지 않아요. name, tags, user_id or user, customer_id or customer, thread_id and turn_id, environment, 그리고 트레이스 레벨 input / output과 평가 필드에는 update_trace() / updateTrace()를 사용해요. 이것은 현재 트레이스의 진입 스팬을 겨냥하므로 어떤 중첩 스팬에서도 호출할 수 있어요. 자세한 내용은 input and output을 참고하세요.

다음 단계 (Next Steps)

스팬 타입을 분류했다면, 프롬프트 추적과 커스텀 I/O로 더욱 풍부하게 만들어요.

Log Prompts

버전화된 프롬프트를 LLM 스팬에 기록해서 프로덕션의 각 호출에 어떤 프롬프트가 사용됐는지 추적해요.

Set Input/Output

더 나은 시각화와 평가를 위해 트레이스와 스팬의 기본 입력·출력을 재정의해요.

더 알아보기