Python v2 → v3

Python v2 → v3

Python SDK v2를 사용 중이라면 최신 메이저인 v4로 직접 업그레이드할 것을 권장해요. Python v3 → v4 마이그레이션 가이드를 참고하세요. 아래의 v2 → v3 변경 사항이 여전히 적용되므로 먼저 완료한 뒤 v3 → v4 가이드를 따르세요.

출처: 문서

본문

Python SDK v3은 레거시 v2 SDK에 비해 상당한 개선과 변경을 도입해요. 완전히 하위 호환되지는 않아요. 이 포괄적인 가이드는 현재 통합 방식에 따라 마이그레이션을 도와줘요.

v2 SDK 문서 스냅샷은 계속 제공돼요.

중요: 업그레이드 전에 제3자 OpenTelemetry span 검토하기

Langfuse SDK는 이제 OpenTelemetry 네이티브예요. 업그레이드 후 Langfuse는 애플리케이션의 다른 OpenTelemetry 계측 라이브러리가 내보낸 span(데이터베이스, HTTP, 프레임워크 계측 등)도 캡처할 수 있어요.

이로 인해 LLM 관찰성과 관련 없는 인프라 span이 많이 추가되어 Langfuse 비용이 크게 늘 수 있어요. 업그레이드를 널리 배포하기 전에 트레이스를 검토하고 계측 범위 필터링 가이드를 사용해 원치 않는 span을 계측 범위별로 걸러내세요.

SDK v2의 핵심 변경 사항:

  • OpenTelemetry 기반: v3은 OpenTelemetry 표준 위에 구축됨
  • 트레이스 입력/출력: 이제 기본적으로 루트 observation에서 파생
  • 트레이스 속성 (user_id, session_id 등): 둘러싸는 span에서 설정하거나 통합의 metadata 필드(OpenAI 호출, Langchain 호출)로 직접 설정할 수 있음
  • 컨텍스트 관리: 자동 OTEL 컨텍스트 전파

통합 유형별 마이그레이션 경로

@observe 데코레이터 사용자

v2 패턴:

from langfuse.decorators import langfuse_context, observe

@observe()
def my_function():
    # This was the trace
    langfuse_context.update_current_trace(user_id="user_123")
    return "result"

v3 마이그레이션:

from langfuse import observe, get_client # new import

@observe()
def my_function():
    # This is now the root span, not the trace
    langfuse = get_client()

    # Update trace explicitly
    langfuse.update_current_trace(user_id="user_123")
    return "result"

OpenAI 통합

v2 패턴:

from langfuse.openai import openai

response = openai.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hello"}],
    # Trace attributes directly on the call
    user_id="user_123",
    session_id="session_456",
    tags=["chat"],
    metadata={"source": "app"}
)

v3 마이그레이션:

추가 트레이스 속성을 설정하지 않는다면 변경이 필요 없어요.

추가 트레이스 속성을 설정한다면 두 가지 옵션이 있어요:

옵션 1: metadata 필드 사용(가장 간단한 마이그레이션):

from langfuse.openai import openai

response = openai.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hello"}],
    metadata={
        "langfuse_user_id": "user_123",
        "langfuse_session_id": "session_456",
        "langfuse_tags": ["chat"],
        "source": "app"  # Regular metadata still works
    }
)

옵션 2: 둘러싸는 span 사용(더 많은 제어):

from langfuse import get_client, propagate_attributes
from langfuse.openai import openai

langfuse = get_client()

with langfuse.start_as_current_observation(as_type="span", name="chat-request") as span:

    with propagate_attributes(
        user_id="user_123",
        session_id="session_456",
        tags=["chat"],
    ):

        response = openai.chat.completions.create(
            model="gpt-4o",
            messages=[{"role": "user", "content": "Hello"}],
            metadata={"source": "app"}
        )

        # Set trace input and output explicitly
        span.update_trace(
            output={"response": response.choices[0].message.content},
            input={"query": "Hello"},
            )

update_trace()는 Python SDK v4에서 deprecated예요. v3 → v4 마이그레이션 가이드를 참고하세요.

LangChain 통합

v2 패턴:

from langfuse.callback import CallbackHandler

handler = CallbackHandler(
    user_id="user_123",
    session_id="session_456",
    tags=["langchain"]
)

response = chain.invoke({"input": "Hello"}, config={"callbacks": [handler]})

v3 마이그레이션:

트레이스 속성을 설정하는 두 가지 옵션이 있어요:

옵션 1: chain 호출에서 metadata 필드 사용(가장 간단한 마이그레이션):

from langfuse.langchain import CallbackHandler

handler = CallbackHandler()

response = chain.invoke(
    {"input": "Hello"},
    config={
        "callbacks": [handler],
        "metadata": {
            "langfuse_user_id": "user_123",
            "langfuse_session_id": "session_456",
            "langfuse_tags": ["langchain"]
        }
    }
)

옵션 2: 둘러싸는 span 사용(더 많은 제어):

from langfuse import get_client, propagate_attributes
from langfuse.langchain import CallbackHandler

langfuse = get_client()

with langfuse.start_as_current_observation(as_type="span", name="langchain-request") as span:

    with propagate_attributes(
        user_id="user_123",
        session_id="session_456",
        tags=["langchain"],
    ):

        handler = CallbackHandler()
        response = chain.invoke({"input": "Hello"}, config={"callbacks": [handler]})

        # Set trace input and output explicitly
        span.update_trace(
            input={"query": "Hello"},
            output={"response": response}
            )

update_trace()는 Python SDK v4에서 deprecated예요. v3 → v4 마이그레이션 가이드를 참고하세요.

LlamaIndex 통합 사용자

v2 패턴:

from langfuse.llama_index import LlamaIndexCallbackHandler

handler = LlamaIndexCallbackHandler()
Settings.callback_manager = CallbackManager([handler])

response = index.as_query_engine().query("Hello")

v3 마이그레이션:

from langfuse import get_client, propagate_attributes
from openinference.instrumentation.llama_index import LlamaIndexInstrumentor

# Use third-party OTEL instrumentation
LlamaIndexInstrumentor().instrument()

langfuse = get_client()

with langfuse.start_as_current_observation(as_type="span", name="llamaindex-query") as span:

    with propagate_attributes(
        user_id="user_123",
    ):
        response = index.as_query_engine().query("Hello")

    span.update_trace(
        input={"query": "Hello"},
        output={"response": str(response)}
        )

update_trace()는 Python SDK v4에서 deprecated예요. v3 → v4 마이그레이션 가이드를 참고하세요.

Low-Level SDK 사용자

v2 패턴:

from langfuse import Langfuse

langfuse = Langfuse()

trace = langfuse.trace(
    name="my-trace",
    user_id="user_123",
    input={"query": "Hello"}
)

generation = trace.generation(
    name="llm-call",
    model="gpt-4o"
)
generation.end(output="Response")

v3 마이그레이션:

v3에서는 모든 span / generation이 반환된 객체에서 .end()를 호출해 종료되어야 해요.

from langfuse import get_client, propagate_attributes

langfuse = get_client()

# Use context managers instead of manual objects
with langfuse.start_as_current_observation(
    as_type="span",
    name="my-trace",
    input={"query": "Hello"}  # Becomes trace input automatically
) as root_span:

    # Propagate trace attributes to all child observations
    with propagate_attributes(
        user_id="user_123",
    ):

        with langfuse.start_as_current_observation(
            as_type="generation",
            name="llm-call",
            model="gpt-4o"
        ) as generation:
            generation.update(output="Response")

        # If needed, override trace output
        root_span.update_trace(
            input={"query": "Hello"},
            output={"response": "Response"}
            )

update_trace()는 Python SDK v4에서 deprecated예요. v3 → v4 마이그레이션 가이드를 참고하세요.

핵심 마이그레이션 체크리스트

  • Import 업데이트:

    • 환경 변수로 구성된 전역 클라이언트 인스턴스에 접근하려면 from langfuse import get_client 사용
    • 생성자 파라미터로 구성된 새 클라이언트 인스턴스를 만들려면 from langfuse import Langfuse 사용
    • observe 데코레이터를 import하려면 from langfuse import observe 사용
    • 통합 import 업데이트: from langfuse.langchain import CallbackHandler
  • 트레이스 속성 패턴:

    • 옵션 1: 통합 호출에서 metadata 필드(langfuse_user_id, langfuse_session_id, langfuse_tags) 직접 사용
    • 옵션 2: user_id, session_id, tags를 propagate_attributes()로 이동
  • 트레이스 입력/출력:

    • LLM-as-a-judge에 중요: 트레이스 입력/출력 명시적 설정
    • 특정 값이 필요하면 루트 observation에서의 자동 파생에 의존하지 마세요
  • 컨텍스트 매니저:

    • 사용하려면 수동 langfuse.trace(), trace.span()을 컨텍스트 매니저로 교체
    • 대신 with langfuse.start_as_current_observation() 사용
  • LlamaIndex 마이그레이션:

    • Langfuse 콜백을 제3자 OTEL 계측으로 교체
    • 설치: pip install openinference-instrumentation-llama-index
  • ID 관리:

    • 커스텀 observation ID 없음: v3은 W3C Trace Context 표준을 사용하므로 커스텀 observation ID를 설정할 수 없음
    • 트레이스 ID 형식: 32자 소문자 16진수(16바이트)여야 함
    • 외부 ID 상관관계: Langfuse.create_trace_id(seed=external_id)를 사용해 외부 시스템에서 결정적 트레이스 ID 생성
from langfuse import Langfuse, observe

# v3: Generate deterministic trace ID from external system
external_request_id = "req_12345"
trace_id = Langfuse.create_trace_id(seed=external_request_id)

@observe(langfuse_trace_id=trace_id)
def my_function():
    # This trace will have the deterministic ID
    pass
  • 초기화:

    • 생성자 파라미터 교체:
      • enabledtracing_enabled
      • threadsmedia_upload_thread_count
  • 데이터셋:

    • 데이터셋 아이템 객체의 link 메서드는 데이터셋 아이템의 run 메서드로 접근할 수 있는 컨텍스트 매니저로 대체됐어요. 이는 트레이스 생성과 데이터셋 아이템-결과 트레이스 연결을 관리하는 더 높은 수준의 추상화예요.
    • 자세한 내용은 데이터셋 문서를 참고하세요.

상세 변경 요약

  • 핵심 변경: OpenTelemetry 기반

    • 더 나은 생태계 호환성을 위해 OpenTelemetry 표준 위에 구축
  • 트레이스 입력/출력 동작:

    • v2: 통합이 트레이스 입력/출력을 직접 설정할 수 있음
    • v3: 트레이스 입력/출력이 기본적으로 루트 observation에서 파생
    • 마이그레이션: span.update_trace(input=..., output=...)로 명시적 설정
  • 트레이스 속성 위치:

    • v2: 통합 호출에서 직접 설정할 수 있음
    • v3: 둘러싸는 span에서 설정해야 함
    • 마이그레이션: 통합 호출을 langfuse.start_as_current_observation()로 감싸기
  • Observation 생성:

    • v2: langfuse.trace(), langfuse.span(), langfuse.generation()
    • v3: langfuse.start_as_current_observation()
    • 마이그레이션: 컨텍스트 매니저 사용, .end() 호출 또는 with 문 사용 확인
  • ID 및 컨텍스트:

    • v3: W3C Trace Context 형식, 자동 컨텍스트 전파
    • 마이그레이션: get_trace_id() 대신 langfuse.get_current_trace_id() 사용
    • 이벤트 크기 제한:
      • v2: 이벤트가 1MB로 제한됨
      • v3: 이벤트에 SDK 측 크기 제한 없음

향후 v2 지원

당분간 v2 SDK의 중요 버그 수정과 보안 패치를 계속 지원할 거예요. v2 SDK에 새 기능은 추가하지 않아요. v2 SDK 문서 스냅샷은 계속 제공돼요.

JS/TS SDK v3 → v4

애플리케이션을 v3에서 v4로 업그레이드하려면 아래 각 섹션을 따르세요.

업그레이드 중 질문이나 문제가 생기면 GitHub에 이슈를 올려 주세요.

중요: 업그레이드 전에 제3자 OpenTelemetry span 검토하기

Langfuse SDK는 이제 OpenTelemetry 네이티브예요. 업그레이드 후 Langfuse는 애플리케이션의 다른 OpenTelemetry 계측 라이브러리가 내보낸 span(데이터베이스, HTTP, 프레임워크 계측 등)도 캡처할 수 있어요.

이로 인해 LLM 관찰성과 관련 없는 인프라 span이 많이 추가되어 Langfuse 비용이 크게 늘 수 있어요. 업그레이드를 널리 배포하기 전에 트레이스를 검토하고 계측 범위 필터링 가이드를 사용해 원치 않는 span을 계측 범위별로 걸러내세요.

초기화

Langfuse 기본 URL 환경 변수는 이제 LANGFUSE_BASE_URL이며 더 이상 LANGFUSE_BASEURL이 아니에요. 하위 호환을 위해 후자는 v4에서 여전히 동작하지만 향후 버전에서는 동작하지 않아요.

트레이싱

v4 SDK 트레이싱은 OpenTelemetry 기반의 주요 재작성으로 몇 가지 호환성 파괴 변경을 도입해요.

  • OTEL 기반 아키텍처: SDK가 이제 OpenTelemetry 위에 구축돼요. LangfuseSpanProcessor를 OpenTelemetry NodeSDK에 등록해 OpenTelemetry 설정이 필요해요.
  • 새 트레이싱 함수: langfuse.trace(), langfuse.span(), langfuse.generation() 메서드가 @langfuse/tracing 패키지의 startObservation, startActiveObservation 등으로 대체됐어요.
  • 관심사 분리:
    • @langfuse/tracing@langfuse/otel 패키지는 트레이싱용.
    • @langfuse/client 패키지와 LangfuseClient 클래스는 이제 스코어링, 프롬프트 관리, 데이터셋 같은 비-트레이싱 기능 전용.

각각에 대한 자세한 내용은 SDK v4 문서를 참고하세요.

프롬프트 관리

  • Import: Langfuse 클라이언트의 import는 이제:
import { LangfuseClient } from "@langfuse/client";
  • 사용법: Langfuse 클라이언트의 사용법은 이제:
const langfuse = new LangfuseClient();

const prompt = await langfuse.prompt.get("my-prompt");

const compiledPrompt = prompt.compile({ topic: "developers" });

const response = await openai.chat.completions.create({
  model: "gpt-4o",
  messages: [{ role: "user", content: compiledPrompt }],
});
  • version은 이제 위치 인자가 아니라 langfuse.prompt.get() 옵션 객체의 선택적 속성이에요.
const prompt = await langfuse.prompt.get("my-prompt", { version: "1.0" });

OpenAI 통합

  • Import: OpenAI 통합의 import는 이제:
import { observeOpenAI } from "@langfuse/openai";
  • 이제 LANGFUSE_TRACING_ENVIRONMENTLANGFUSE_TRACING_RELEASE 환경 변수로 environment와 release를 설정할 수 있어요.

Vercel AI SDK

v3와 매우 유사하게 동작하지만, langfuse-vercel의 LangfuseExporter@langfuse/otel의 일반 LangfuseSpanProcessor로 대체해요.

AI SDK와의 사용 예시는 여기를 참고하세요.

LLM에 제공된 도구 정의는 이제 metadata.tools에 매핑되고 더 이상 input.tools에 있지 않아요. generation에 대해 평가를 실행하는 경우 관련돼요.

Langchain 통합

  • Import: Langchain 통합의 import는 이제:
import { CallbackHandler } from "@langfuse/langchain";
  • 이제 LANGFUSE_TRACING_ENVIRONMENTLANGFUSE_TRACING_RELEASE 환경 변수로 environment와 release를 설정할 수 있어요.

  • langfuseClient.getTraceUrl 메서드는 이제 비동기이며 promise를 반환해요.

const traceUrl = await langfuseClient.getTraceUrl(traceId);

스코어링

  • Import: Langfuse 클라이언트의 import는 이제:
import { LangfuseClient } from "@langfuse/client";
  • 사용법: Langfuse 클라이언트의 사용법은 이제:
const langfuse = new LangfuseClient();

await langfuse.score.create({
  traceId: "trace_id_here",
  name: "accuracy",
  value: 0.9,
});

새 스코어링 방법은 커스텀 점수 문서를 참고하세요.

데이터셋

새 데이터셋 메서드는 데이터셋 문서를 참고하세요.

더 알아보기 (Learn more)