MLflow code analysis

Let’s analize mlflow source code
1. Initialize
Mlflow uses so many large sized 3rd party libs, so it imports lazily when module is called. (singleton of global context)
|
|
LazyLoader
inherits types.ModuleType
to initialize instance as module type.
|
|
- __init__에서 global() namespace를 받아 저장하고, module.__name__을 init하게 되고 LazyLoader 타입으로 부모 context(global context)에 모듈이 등록됩니다.
- getattr 시점에, _load를 호출하여, 모듈이 import되지 않았을 경우, dynamic하게 import하여, global context에 이 module을 등록합니다.
- 이때 부모의 global context에 LazyLoader로 등록되어있던 모듈을 실제 import한 모듈로 overwrite합니다. 이를 통해서 최초 getattr 이후로는 실제 import된 module이 LazyLoader를 대체하게 됩니다.
sys.modules
는 Python이 모든 로드된 모듈을 추적하는 데 사용하는 내부 캐시입니다. 모듈이 로드될 때, 이 캐시에 모듈을 등록하면, Python은 동일한 모듈을 재로드하는 대신 이미 로드된 모듈을 재사용합니다.
문득 코드를 읽다, self._module를 저장하는 이유가 궁금해서 (내가 생각할 때는 불필요한 것 같은데) discussion을 남겨두었다.
2. Run
init 이후, __main__.py
을 통해서 호출된 cli 모듈을 통해서 명령어에 대한 처리가 시작됩니다. cli.py에서는 크게 4가지의 명령어가 존재하며, 다음과 같습니다.
run()
: Run an MLflow project from the given URI.server()
: Run the MLflow tracking server.gc()
: Permanently delete runs in thedeleted
lifecycle stage.doctor()
: Prints out useful information for debugging issues with MLflow.
기능 적인 측면에서 보면 크게 run, server 2가지만 파악하면 될 것같습니다. 이외에도 import를 통해서 나머지 명령어들을 불러옵니다. 최종적인 mlflow의 cli는 아래와 같습니다.
- load additional cli
|
|
- FYI, suppress는 에러 ignore를 한줄로 사용하기 위해 사용됩니다.
|
|
2.2. Start a Local Mlflow Server
Mlflow 코드를 분석하기 위해서는, 실제 UI상에서 experiment들이 어떻게 진행되어야 하는지 파악하는게 우선이라 생각되어 local에서 mlflow pull 받아서 확인해보았습니다.
2.3. Getting Started with MLflow
대략 mlflow를 local에서 실행해보고 났으니, 구체적으로 mlflow의 구성요소들을 정리해 보겠습니다.
3. Concepts
3.1. MLflow Tracking
Runs
: Executions of some piece of code- Each run records metrics, parameter, start ~ end times, artifacts(model weights, images, etc)
Experiments
: Group of runs, for a specific task
|
|
Tracking Components
- Tracking APIs: Tracking Server와 interact할 수 있는 인터페이스
- 내 생각에는 이게, python, REST등의 client형식으로 관리 될 것 같다.(auth가 필요하니)
- Backend Store: metadata for each Run (i.g. run ID, metrics ..)
- Default
/mlruns/**
(file based) - Databaed-based (db …)
- Default
- Artifact Store:
- input data files, model weight, images 따위
- svn과 연동한다면 Artifact에서 작업이 되어야 할 것.
- Parquet, S3 등으로 대체 가능
- Tracking Server
- standalone HTTP server that provides REST API for accessing backend/artifact store.
Deployment 코드를 보다가 아래와 같은 패턴을 발견습니다. 이렇게 데코레이터에서 원본으로 wraps을 하는 이유는
__name__
,__module__
함수 이름/모듈 보존: 로깅 / 디버깅 시 wrapper func가 원본 함수 이름을 물려 받을 수있음__doc__
repr 보존: 원본 함수의 주석이 그대로 보존 될 수 있어, wrapper가 되더라도 주석을 wrapper에 쓰는 것이 아니라, 실제 기능하는 코드에 주석을 넣어둘 수 있습니다.
오픈소스에서 @functools.wraps(fn)
를 쓰는 이유는 딱 위의 2가지 이유 정도 있을 것 같습니다.
|
|
3.2. Mlflow Projects
Mlflow Project란 소스 코드를 재사용 가능하게 패키징화 시킨 컴포넌트입니다.
- API, CLI entrypoint를 가지고 있습니다.
- chainning으로 multi-step workflows에 추가시킬 수 있습니다.
- Conda env나 MLproject (yaml file)를 통해서 properties들을 추가할 수 있습니다.
Project는 Git URI 또는 local directory에서 mlflow run
command를 사용해서 실행 가능합니다. 코드 상에서는 mlflow.projects.run()
을 통해 python api로 실행가능합니다. 이 api는 k8s나 databricks 환경에서 remote로 실행 가능합니다.
Project가 실행되는 환경을 구성하기 위해서는 아래 4가지 구성이 옵션들이 가능합니다.
- Virtualenv (preferred)
- Docker container
- Conda
- System environment
여기에서는 Viertualenv 세팅 위주로 살펴보겠습니다.
MLflow Project (Virtualenv
)
이 세팅을 구성한다면, mlflow는 pyenv를 활용해 isolated environment를 만들고, virtualenv를 통해 dependencies들을 포함시킵니다. 또한 mlflow 코드를 실행시키기 전에(prior to running the project code), 이 isolated env를 activate 시킵니다.
이 세팅을 활용하기 위해서는 2개의 파일 세팅이 필요합니다.
MLproject
: 시작 지점python_env.yaml
: virtualenv environment description
MLProject example
|
|
python_env example
|
|
이후 project를 실행하기 위해서는, MLproject 파일이 있는 디렉토리에서 아래 코들르 사용하면 됩니다.
|
|
이렇게 명령어를 `작성하게 되면 cli상에서 mlflow는 projects 패키지를 호출하며, 실제 코드에서는 아래 부분이 호출 됩니다.
- load_project에서 python_env.yaml을 읽어, Project 객체를 생성합니다.
- Project는 Entrypoint와 Parameter를 init하고 이를 통해 source code 파일들을 link 또는 remote의 경우 storage_dir로 download합니다.
- 이후 projects.run을 통해 아래 코드가 호출되어 local 또는 databricks 같은 remote에 존재하는 코드들을 실행합니다. code
- 이후 projects.backend.local.py의 run이 호출되어 새로운 process가 동작합니다. 코드
mlflow project를 실행해보다가, examples/llms/summarization을 실행해보는데, dep 에러가 발생해서 contribute했다. langchain이 워낙 빠르게 변화하는 open source다 보니까, dependency 관리가 쉽지 않나 보다. FIx llm example tiktoken dependency error #10989
3.3. MLflow LLMs
Mlflow introduce Deployment
(previously AI Gateway) that simplifies interactions with multiple LLM provides.
- Support multiple llm providers
- Integrate to mlflow model serving
- Centralized scattered API keys
- Seamless Provider swapping
Mlflow LLM는 아래와 같은 core concept들을 가지고 있습니다.
- Deployments
- Evaluation
- Prompt UI
- Flavors
- OpenAI
- Langchain
- Transformer / BERT
- Tracking
문득 Document를 보다가, 현재 페이지를 tracking 제대로 하지 못해, 이 부분 고쳐서 pr 올렸는데,
[pr] MLflow doc page가 현재 current doc을 제대로 표시하지 못해, 불편했었는데, 이 부분 fix하여 pr을 올렸다. https://github.com/mlflow/mlflow/pull/10999
ci 쪽 에러들이 block되어 추가로 2개 pr들을 더 올렸다.
[pr] MLflow 오픈소스가 여러모로 dependency 버그가 좀 있었는데, 이 부분에 MLflow의 dev dependency 관련된 세팅을 처리했고, bug fix를 contribute했다. https://github.com/mlflow/mlflow/pull/10998
[pr] https://github.com/mlflow/mlflow/pull/11003 , keras related build fix.
말은 open source인데, contributor들에게 여러모로 너무 불편한 상황인듯. pr을 아무도 관리하지 않는다는거나, issue관리 그리고 ci/cd 파이프라인이 막혀있는데 몇일째 아무도 신경 쓰지 않았다는 것 등;; Databricks분들은 바로 바로 merge 시키는데, 이걸 보면 그냥 기업 코드를 오픈시킨 databricks 홍보용 레포 같다.
24.02.07, 5일이 지나고 나서야 드디어 merge되었다. 다행이다.