Langfuse 토큰·비용 추적 (Token & Cost Tracking)

Langfuse 토큰·비용 추적 (Token & Cost Tracking)

LLM 애플리케이션을 운영하다 보면 "이번 달 비용이 왜 이렇게 나왔지?"라는 질문이 꼭 나와요. Langfuse는 애플리케이션의 모든 LLM 호출에 대한 사용량과 비용을 추적해서, 모델별·사용 사례별·시간에 따른 지출을 모니터링하게 해줘요.

출처: Langfuse Token & Cost Tracking

비용 데이터로 무엇을 할 수 있나요

사용량·비용을 추적하면 그 데이터를 여러 곳에 활용할 수 있어요. 커스텀 대시보드로 모델·태그·사용자별 비용을 모니터링하고, 알림을 걸어 지출이 임계값을 넘으면 자동으로 통보받고, Metrics API로 애플리케이션 유형·사용자·태그로 필터링한 집계 사용량·비용을 조회해 분석·청구·속도 제한에 쓸 수 있어요.

비용 추적이 작동하는 방식

Langfuse는 LLM generation마다 사용량 상세(usage details)비용 상세(cost details) 두 가지를 기록해요. 둘 다 usage type(예: input·output, 또는 프로바이더에 따라 다른 cached_tokens·audio_tokens 같은 세부 타입)별로 나뉘어요.

  • 사용량 상세: usage type별로 소모된 단위 수
  • 비용 상세: usage type별 USD 비용

둘 다 generation·embedding 타입 관찰에서 캡처되며, 각각 수집(ingested) 또는 추론(inferred) 방식으로 채워져요. 수집은 LLM 응답에서 사용량·비용을 API·SDK·통합으로 직접 보내는 것이고, 추론은 generation의 model 파라미터를 모델 정의와 대조해 Langfuse가 값을 계산하는 거예요. 둘 다 있으면 수집된 값이 우선해요.

모델 정의와 가격

비용을 직접 수집하지 않으면 Langfuse가 추론해요. generation의 model 파라미터가 모델 정의(usage type별 가격을 담은 것)와 매칭돼요. Langfuse는 가격에 그 관찰의 사용량을 곱해 비용을 계산하죠. 응답에 비용이 포함되지 않는 모델 프로바이더나 자체 호스팅 모델에서 특히 유용해요.

Langfuse에는 OpenAI·Anthropic·Google 인기 모델과 토크나이저가 미리 정의돼 있어요. 가격은 Project Settings > Models에서 관리하고, 커스텀 모델 정의를 추가하거나 새 모델 공식 지원을 GitHub 이슈로 요청할 수 있어요.

토크나이저

모델에 토크나이저가 지정돼 있으면, Langfuse가 수집된 generation의 토큰 수를 자동으로 계산해요. 현재 지원되는 토크나이저는 예를 들어 gpt-4oo200k_base(tiktoken 패키지), gpt*cl100k_base(tiktoken), claude*claude(@anthropic-ai/tokenizer)예요. 참고로 Anthropic은 자체 토크나이저가 Claude 3 모델에 정확하지 않다고 하니, 가능하면 API 응답의 토큰을 직접 보내는 게 좋아요.

사용량 타입은 서로 배타적인 버킷

Langfuse는 usage_details의 모든 키를 별개의, 겹치지 않는 버킷으로 취급해요. 즉 각 토큰은 정확히 한 키에만 속해야 해요. inputinput_cached_tokens 같은 input_* 값을 배제하고, outputoutput_reasoning_tokens 같은 output_* 값을 배제해요. total은 버킷들의 합이지 버킷 하나가 아니에요.

버킷이 겹치면 사용량과 추론 비용이 이중으로 계산돼서, Langfuse에 표시되는 비용이 실제 프로바이더 청구보다 높게 나타나요. OpenAI 입력 수치는 캐시 토큰을 포함하는 등 일부 프로바이더 수치는 포함형(inclusive) 이므로, 저장 전에 반드시 배타적 버킷으로 변환해야 해요.

커스텀 모델 정의 추가

자체 호스팅·파인튜닝 모델처럼 Langfuse 유지 목록에 없는 모델은 커스텀 정의를 유연하게 추가할 수 있어요. UI의 Project Settings > Models에서 추가하거나, Models API로 프로그래밍 방식으로 관리할 수 있어요.

GET    /api/public/models
POST   /api/public/models
GET    /api/public/models/{id}
DELETE /api/public/models/{id}

모델은 generation의 model 속성과 모델 정의의 match_pattern(정규식)으로 매칭돼요. 사용자가 만든 모델이 Langfuse 유지 모델보다 우선해요.

사용량·비용 직접 수집

자체 호스팅·커스텀 모델, 비공개 가격, 그대로 기록하고 싶은 정확한 프로바이더 수치 등 경우에 따라 사용량·비용을 직접 수집하고 싶을 수 있어요. SDK의 usage_details·cost_details로 명시할 수 있어요.

from langfuse import get_client
import anthropic

langfuse = get_client()
anthropic_client = anthropic.Anthropic()

with langfuse.start_as_current_observation(
    as_type="generation",
    name="anthropic-completion",
    model="claude-3-opus-20240229",
    input=[{"role": "user", "content": "Hello, Claude"}]
) as generation:
    response = anthropic_client.messages.create(
        model="claude-3-opus-20240229",
        max_tokens=1024,
        messages=[{"role": "user", "content": "Hello, Claude"}]
    )

    generation.update(
        output=response.content[0].text,
        usage_details={
            "input": response.usage.input_tokens,
            "output": response.usage.output_tokens,
            "cache_read_input_tokens": response.usage.cache_read_input_tokens
            # "total": int,  # 설정하지 않으면 모든 usage type의 합으로 유도
        },
        cost_details={
            # input/output 비용을 1 USD, 캐시 토큰은 반값으로 가정
            "input": 1,
            "cache_read_input_tokens": 0.5,
            "output": 1,
            # "total": float,  # 설정하지 않으면 모든 usage type의 합으로 유도
        }
    )

reasoning 모델 비용

OpenAI o1 계열 같은 reasoning 모델은 비용 추론이 지원되지 않아요. LLM 입력·출력을 토크나이징해 비용을 추론하는 방식이라, 토큰 수치가 수집되지 않으면 비용을 추론할 수 없어요. reasoning 모델은 응답에 도달하기까지 여러 단계를 거치고, 각 단계의 reasoning 토큰이 출력 토큰으로 청구되거든요. Langfuse는 reasoning 토큰을 볼 수 없어서 사용량이 없는 generation의 정확한 비용을 계산하지 못해요. 그러니 o1 모델 generation을 수집할 때는 토큰 사용량을 함께 넣어주고, Langfuse OpenAI 래퍼나 LangChain·LlamaIndex·LiteLLM 같은 통합을 쓰면 토큰 사용량이 자동으로 수집돼요.

비용이 보이지 않을 때 확인할 것

  • 사용량이나 비용이 있어야 해요. 사용량이 수집·추론됐거나 토크나이저가 있는 모델일 때만 비용을 추론해요. 둘 다 없고 토크나이저도 없는 모델이면 비용이 계산되지 않아요.
  • 모델이 정의와 매칭돼야 해요. 추론 비용은 generation의 model과 매칭되는 match_pattern이 있는 모델 정의가 필요해요. 없으면 커스텀 모델 정의를 추가하세요.
  • 모델 정의 변경은 새 generation에만 적용돼요. 정의를 바꾸거나 추가해도, 이후 기록되는 generation에만 새 비용이 적용돼요.
  • generation·embedding 관찰만 비용을 추적해요. 다른 관찰 타입은 사용량·비용을 담지 않아요.
  • reasoning 모델은 수집된 사용량이 필요해요. 토큰 수치 없이는 OpenAI o1 같은 reasoning 모델 비용을 추론할 수 없어요.

더 알아보기 (Learn more)