Skip to main content

자동 계측 vs 수동 계측 — 상세 비교

자동 계측 (Autolog)의 동작 원리

Autolog는 대상 프레임워크의 핵심 메서드를 몽키패치(Monkey Patch) 하여 호출 전후에 Span 생성/종료 코드를 주입합니다.
# 내부 동작 의사 코드 (실제 구현은 더 복잡)
original_create = openai.ChatCompletion.create

def patched_create(*args, **kwargs):
    with mlflow.start_span(name="ChatCompletion", span_type="LLM") as span:
        span.set_inputs({"messages": kwargs.get("messages")})
        result = original_create(*args, **kwargs)
        span.set_outputs({"response": result.choices[0].message.content})
        span.set_attributes({
            "token_usage.input": result.usage.prompt_tokens,
            "token_usage.output": result.usage.completion_tokens,
            "model": kwargs.get("model")
        })
        return result

openai.ChatCompletion.create = patched_create

자동 vs 수동 계측 선택 가이드

기준자동 계측수동 계측
설정 난이도한 줄 (mlflow.xxx.autolog())각 함수에 데코레이터/컨텍스트 추가
커버리지프레임워크 내부 호출만비즈니스 로직 포함 전체
커스텀 속성제한적 (프레임워크가 제공하는 정보만)자유롭게 추가 가능
오버헤드매우 낮음매우 낮음
권장 사용빠른 프로토타이핑, 표준 파이프라인프로덕션, 세밀한 제어 필요 시
💡 실무 패턴: 자동 계측과 수동 계측을 함께 사용 하는 것이 가장 효과적입니다. 프레임워크 호출은 Autolog로 자동 추적하고, 비즈니스 로직(전처리, 후처리, 캐시 확인 등)은 수동으로 Span을 추가합니다.
# 자동 + 수동 혼합 패턴
mlflow.langchain.autolog()  # LangChain 호출은 자동 추적

@mlflow.trace(name="rag_with_cache", span_type="CHAIN")
def rag_pipeline(question: str) -> str:
    # 수동: 캐시 확인 (자동 추적 대상 아님)
    with mlflow.start_span(name="cache_check") as span:
        cached = check_cache(question)
        span.set_attributes({"cache_hit": cached is not None})
        if cached:
            return cached

    # 자동: LangChain 호출은 autolog가 추적
    result = chain.invoke({"question": question})

    # 수동: 응답 품질 검증 (자동 추적 대상 아님)
    with mlflow.start_span(name="quality_check") as span:
        quality = validate_response(result)
        span.set_attributes({"quality_score": quality})

    return result

LangChain/LlamaIndex 통합 상세

LangChain 통합

LangChain의 모든 주요 컴포넌트가 자동으로 추적됩니다.
컴포넌트Span Type추적 내용
ChatModel (ChatOpenAI 등)LLM프롬프트, 응답, 토큰 수, 모델명, 온도
Retriever (VectorStoreRetriever)RETRIEVER쿼리, 검색 결과, 문서 수, 점수
ToolTOOL도구명, 입력, 출력, 실행 시간
Chain (RunnableSequence)CHAIN체인 구성, 각 단계 입출력
Agent (AgentExecutor)AGENT추론 과정, 도구 선택 이유, 반복 횟수
# LangChain LCEL 파이프라인의 자동 추적
mlflow.langchain.autolog()

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

chain = (
    ChatPromptTemplate.from_template("Translate to Korean: {text}")
    | ChatOpenAI(model="gpt-4o")
    | StrOutputParser()
)

# 호출 시 자동으로 3개 Span 생성:
# 1. ChatPromptTemplate (CHAIN)
# 2. ChatOpenAI (LLM) - 토큰, 지연시간 포함
# 3. StrOutputParser (PARSER)
result = chain.invoke({"text": "Hello, world!"})

LlamaIndex 통합

mlflow.llama_index.autolog()

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader

# 인덱스 생성 시 임베딩 호출이 자동 추적됨
documents = SimpleDirectoryReader("data").load_data()
index = VectorStoreIndex.from_documents(documents)

# 쿼리 시 전체 파이프라인 자동 추적
# Retrieval → Reranking → LLM Generation
query_engine = index.as_query_engine()
response = query_engine.query("데이터 레이크하우스란 무엇인가요?")