포스트

MLflow 해부 (7) 응용: 3.x tracing으로 LLM 호출 기록

MLflow 3.x의 tracing으로 LLM 호출의 입력, 출력, 지연 시간을 trace와 span 단위로 기록합니다. autolog 연동과 커스텀 함수 추적, 실험 추적과의 관계를 정리하며 시리즈를 마칩니다.

MLflow 해부 (7) 응용: 3.x tracing으로 LLM 호출 기록

MLflow 해부 시리즈의 마지막, 7편입니다. 전체 목차는 0편에 있습니다.

실험 추적과 tracing의 차이

1편부터 6편까지의 기록 단위는 run이었습니다. 학습 한 번에 파라미터와 지표가 한 세트로 남는 구조는 “실행이 끝나면 결과가 확정되는” 학습 작업에 맞는 모델입니다.

LLM 애플리케이션의 관심사는 다릅니다. 요청 하나가 들어오면 프롬프트 구성, LLM 호출, 도구 호출, 후처리가 이어지고, 문제가 생겼을 때 필요한 것은 “이 요청이 각 단계에서 무엇을 주고받았나”입니다. 이 요청 단위 기록이 trace이고, 그 안의 단계 하나하나가 span입니다. MLflow 3.x가 이 tracing을 실험 추적과 같은 서버, 같은 UI에 추가했습니다.

autolog로 시작

지원 라이브러리는 한 줄로 켜집니다.

1
2
3
4
5
6
7
8
9
10
11
12
import mlflow

mlflow.set_experiment("llm-demo")
mlflow.openai.autolog()

from openai import OpenAI

client = OpenAI()
response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "서울의 오늘 날씨를 한 문장으로"}],
)

이 호출 이후 UI의 Traces 탭에 요청별 trace가 쌓입니다. 기록되는 것은 입력 메시지, 응답, 모델명, 토큰 수, 지연 시간입니다. LangChain 등도 같은 방식의 autolog를 지원합니다.

커스텀 함수 추적

직접 짠 파이프라인 단계는 데코레이터로 span이 됩니다.

1
2
3
4
5
6
7
8
@mlflow.trace
def retrieve(query: str) -> list[str]:
    return search_documents(query)

@mlflow.trace
def answer(query: str) -> str:
    docs = retrieve(query)
    return call_llm(query, docs)

answer를 호출하면 trace 하나가 생기고, 그 안에 retrieve와 LLM 호출(autolog가 잡은 것)이 중첩된 span으로 들어갑니다. 함수 호출 구조가 그대로 trace 트리가 되는 방식이라, RAG 파이프라인에서 “검색이 느린가, 생성이 느린가”와 “검색 결과가 이상해서 답이 틀렸나”를 한 화면에서 확인할 수 있습니다.

UI에서 보는 것

  • Traces 탭: 요청별 trace 목록. 지연 시간과 상태로 정렬해 느린 요청과 실패 요청을 찾습니다
  • trace 상세: span 트리와 각 span의 입력, 출력. 프롬프트에 무엇이 실제로 들어갔는지 확인하는 자리입니다

토큰 수가 span에 남기 때문에 요청당 비용 추정도 이 데이터로 만듭니다.

어디까지 MLflow로 할 것인가

tracing 영역에는 전문 도구(LangSmith, Langfuse)가 따로 있습니다. 이미 MLflow 서버를 운영하고 있다면 도구를 늘리지 않고 같은 곳에서 시작할 수 있다는 것이 MLflow tracing의 위치입니다. 평가(LLM-as-a-judge), 프롬프트 버전 관리까지 필요해지면 그 시점에 전문 도구와 비교하면 됩니다.

시리즈를 마치며

일곱 편의 요약입니다.

  • 기록은 backend store와 artifact store로 갈라지고, 이 구조가 로컬에서 운영까지 그대로 이어집니다 (1편, 6편)
  • 기본 동선은 experiment 지정, run 기록, UI 비교입니다. autolog로 시작하고 커스텀 지표만 수동으로 보강합니다 (2편, 3편)
  • 배포는 models:/이름@alias를 바라보게 하고, 승격과 롤백은 alias 이동으로 처리합니다 (4편)
  • search_runs와 MlflowClient로 “champion보다 좋을 때만 승격”하는 자동화를 만듭니다 (5편)
  • LLM 애플리케이션은 run 대신 trace로 기록합니다 (7편)

같은 글감의 오케스트레이션 도구 편은 Airflow 해부 시리즈입니다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.