본 번역은 검증되지 않았습니다. AIP를 통해 영문원문으로부터 번역되었습니다.

추가 라이브러리 지원 추가하기

폐기된 기능

아래 문서는 더 이상 플랫폼에서 사용을 권장하지 않는 foundry_ml 라이브러리에 대해 설명합니다. 대신 palantir_models 라이브러리를 사용하세요.

foundry_ml 라이브러리는 2025년 10월 31일에 제거 될 예정이며, 이는 Python 3.9의 예정된 폐기와 일치합니다.

만약 Foundry의 표준 모델 Functions이 특정 유즈케이스에 대해 불충분하거나 특정 클래스 또는 라이브러리가 지원되지 않는 경우, 일부 함수를 덮어쓰거나 Stage interface에 필요한 것들을 등록할 수 있습니다. 예를 들어, Stage의 사용자 정의 transform 함수를 생성하여 Foundry에 직렬화할 수 있습니다.

세 번째 파티 라이브러리를 지원하려면, Stage의 자체 구현을 생성할 수 있습니다.

예제를 살펴보려면, 기명 엔티티 인식을 위한 사전 학습된 spaCy 모델을 활용하는 방법에 대한 튜토리얼을 참조하세요.

요구사항

이들은 Code Repository 또는 Code Workbook 환경에 추가될 수 있는 공유 Transforms Python 라이브러리에 작성되어야 합니다. 한 번 가져오면, 사용자 정의 Stage 구현은 자동으로 foundry_ml에 통합됩니다.

사용자 정의 구현 옵션은 다음을 설명합니다:

  • model.transform()이 호출될 때 모델이 수행해야 하는 작업은 무엇인가.
  • 모델이 어떻게 직렬화되고 Foundry에 저장되어야 하는가.
  • 모델이 어떻게 역직렬화되어 다운스트림 변환에서 사용될 수 있는가.

Stage 클래스는 역직렬화 시간에 사용 가능해야 하므로, 반드시 Python 환경의 모듈로 사용 가능해야 합니다.

변환 등록하기

모델 클래스를 사용하려면, 클래스에 등록된 변환 함수와 직렬화 형식이 있어야 합니다. CustomModel Stage를 포함하는 모델이 있을 때마다 model.transform()이 호출될 때 적용되는 함수를 정의해야 한다고 가정해 봅시다.

정의된 transform 함수는 Spark 또는 Pandas DataFrame에서 작동해야 합니다.

Copied!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 # foundry_ml.stage.flexible에서 stage_transform, register_stage_transform_for_class 함수를 임포트합니다. from foundry_ml.stage.flexible import stage_transform, register_stage_transform_for_class # CustomModel 클래스를 정의합니다. class CustomModel(object): def __init__(self, name): # 생성자 함수입니다. ... def custom_transform(self, df): # 사용자 정의 데이터 변환 함수입니다. ... # 변환된 데이터 프레임을 반환합니다. return df # 스테이지 간의 모델 및 데이터 전달을 처리하는 함수를 주석 처리합니다. @stage_transform() def _transform(model, df): # 위에서 정의한 모델의 변환 함수를 호출합니다. return model.custom_transform(df) # 이를 호출하여 Foundry ML Stage Registry로 전송하고, force=True를 사용하여 기존에 등록된 변환을 무시합니다. register_stage_transform_for_class(CustomModel, _transform, force=True)

직렬화 및 역직렬화 등록

이제 클래스에 대한 변환 함수를 등록했으므로 Foundry에 모델 코드를 직렬화하고 역직렬화하는 방법을 알려야 합니다. 사용자 정의 모델 스테이지를 사용할 때 스테이지가 공유 Python 라이브러리에 작성되고 종속성으로 가져와져야 합니다.

이것은 Stage 클래스가 역직렬화 시점에서 사용 가능해야 하기 때문입니다. 그렇지 않으면 Code Workbook에서 Stage 클래스를 작성한 후 다른 Code Workbook에서 저장된 모델을 로드하려고 시도하면 모델을 로드할 수 없습니다.

아래 예시는 dill을 사용하여 CustomModel이 피클링 될 수 있다고 가정합니다. 아래 예시에서는 Foundry 도움 함수인 load_datasafe_write_data를 사용하여 파일 시스템의 모델을 안전하게 읽고 쓸 수 있습니다. spaCy 예제에서는 다른 구현을 보여줍니다.

Copied!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import dill from foundry_object.utils import safe_write_data, load_data from foundry_ml.stage.serialization import deserializer, serializer, register_serializer_for_class # Deserializer 데코레이터 @deserializer("custom_model.dill", force=True) def _deserializer(filesystem, path): # 피클 파일 불러오기 return dill.loads(load_data(filesystem, path, True), encoding='latin1') # Serializer 데코레이터 @serializer(_deserializer) def _serializer(filesystem, value): path = 'custom_model.dill' # base64 인코딩을 사용하여 안전하게 데이터 쓰기 safe_write_data(filesystem, path, dill.dumps(value), base64_encode=True) return path # CustomModel 클래스에 대해 직렬화 및 역직렬화 등록 register_serializer_for_class(CustomModel, _serializer, force=True)

이제 CustomModel을 올바르게 등록했으므로, model = Model(Stage(CustomModel(...))) 문법으로 다른 Stage처럼 사용할 수 있으며, model.transform(dataframe)로 실행할 수 있습니다.

모델에서 함수 직렬화하기

일부 모델 단계(특히 시뮬레이션 래퍼)는 메인 변환 함수와 함께 사용자 작성 함수를 포함합니다. 모델을 실행 가능하게 하려면 사용자 작성 함수도 모델 상태에 직렬화되어야 합니다. 내부적으로 파이썬은 함수를 저장하기 위해 pickle 패키지를 사용합니다. pickle 패키지는 함수를 올바르게 직렬화하기 위해 추가 고려사항이 필요합니다.

스테이지를 로드할 때, ModuleNotFoundError: No module named '...'와 같은 오류가 발생할 수 있습니다. 이는 사용자 작성 함수가 참조별로 직렬화되는 대신 값으로 직렬화되었을 때 발생할 수 있습니다. 즉, 파이썬 바이트 코드를 직접 직렬화하는 대신 pickle은 함수의 이름을 직렬화했습니다.

값에 의한 직렬화를 강제하려면 코드를 직접 변환 함수로 이동할 수 있습니다.

예를 들어:

class SimModel(SimulationWrapper):
    def run(self, data, parameters):
        ...
# SimModel은 SimulationWrapper의 하위 클래스입니다.
# run 메소드는 데이터와 매개변수를 받아 처리를 수행합니다.

@transform(...)
def my_model(...):
  return Model(Stage(
        SimModel(parameters)
    ))
# my_model 함수는 transform 데코레이터가 적용된 함수입니다.
# 이 함수는 Model 객체를 반환하는데, 이 Model 객체는 Stage 객체를 포함합니다.
# Stage 객체는 SimModel 인스턴스를 포함하며, 이 인스턴스는 매개변수를 받습니다.

다음과 같이 작성해야 합니다:

Copied!
1 2 3 4 5 6 7 8 9 @transform(...) # @transform 데코레이터를 사용하여 이 함수를 변환합니다. def my_model(...): # my_model 함수를 정의합니다. class SimModel(SimulationWrapper): # SimulationWrapper를 상속받는 SimModel 클래스를 정의합니다. def run(self, data, parameters): # run 메소드를 정의하며, 이 메소드는 data와 parameters를 인자로 받습니다. ... return Model(Stage( # Stage 객체를 생성하고, 이를 Model의 인자로 넣어 Model 객체를 생성하여 반환합니다. SimModel(parameters) # SimModel 클래스의 인스턴스를 생성합니다. 이 때, parameters를 인자로 전달합니다. ))

이 규칙은 사용자 정의 코드에서 호출하는 다른 함수에도 적용됩니다. 직렬화된 함수 또는 클래스에 값으로 직렬화되는 많은 종속성이 있는 경우, 권장되는 경로는 종속성을 Python 라이브러리로 추출하여 모델에 종속성으로 추가하는 것입니다.

공유 라이브러리 설정하기

위의 코드가 모두 model.py에 위치한다고 가정하면, 저장소는 다음과 같은 구조를 가지게 됩니다:

├── README.md               # 프로젝트에 대한 전반적인 설명이 담긴 파일
├── build.gradle            # Gradle 빌드 도구를 활용하기 위한 설정 파일
├── ci.yml                  # 지속적 통합(Continuous Integration)을 위한 설정 파일
├── conda_recipe
│   └── meta.yaml           # Conda 패키지를 만들기 위한 메타데이터 파일
├── gradle.properties       # Gradle 설정 값을 담은 프로퍼티 파일
├── gradlew                 # Gradle Wrapper 실행 파일 (유닉스, 리눅스 용)
├── gradleww                # Gradle Wrapper 실행 파일 (윈도우 용)
├── settings.gradle         # Gradle 프로젝트 설정 파일
├── src                     # 소스 코드 디렉토리
│   ├──custom_plugin        # 사용자 정의 플러그인 디렉토리
│   │   ├── __init__.py     # Python 패키지 초기화 파일
│   │   └── model.py        # 모델 관련 소스 코드 파일
│   ├── setup.cfg           # 패키지 설정 파일
│   └── setup.py            # 패키지 설치를 위한 파이썬 스크립트
└── templateConfig.json     # 템플릿 설정을 담은 JSON 파일

Foundry에서 플러그인을 발견할 수 있도록 하려면 먼저 __init__.py를 수정하여 model.py의 내용을 패키지 최상위로 가져와야 합니다:

Copied!
1 2 # .model 파일에서 모든 것(*)을 가져옵니다. from .model import *

또한, 모델 플러그인 레지스트리가 새로운 플러그인을 발견할 수 있도록 다음을 setup.py에 추가해야 합니다:

Copied!
1 2 # entry_points는 플러그인 등록을 위한 딕셔너리입니다. entry_points={'foundry_ml.plugins': ['plugin = custom_plugin']},

커밋, 빌드, 그리고 릴리즈 태그를 한 후에는 새로운 모델 클래스를 Code Workbook이나 Code Repositories에서 활용할 수 있어야 합니다.

라이브러리 클래스에서 변환 함수 덮어쓰기

Foundry의 표준 함수가 특정 유즈케이스에 충분하지 않은 경우, 기존 모델 클래스에 대한 transform 함수를 덮어쓸 수 있습니다. 단계는 커스텀 클래스에 변환 등록하는 위의 섹션과 동일합니다.

하지만 레지스트리는 클래스 수준에 있습니다. 이는 특정 라이브러리 함수(예를 들어, sklearn의 LogisticRegression)에 대한 transform() 함수를 덮어쓰면, 그 라이브러리 함수의 모든 인스턴스가 덮어쓴 변환 함수를 사용하게 됨을 의미합니다. 덮어쓰기를 포함하는 라이브러리를 임포트할 때마다 이렇게 됩니다.

이런 동작이 원치 않는 경우, 다음 방법으로 해결할 수 있습니다:

  • 라이브러리 함수를 감싸는 래퍼 클래스(예를 들어, LogisticRegressionCustom)를 생성합니다.
  • 위의 단계를 따라 원하는 변환 함수와 함께 등록합니다.

그런 다음, 라이브러리 함수로의 어떤 호출의 동작도 수정하지 않고 이 새 클래스를 사용할 수 있습니다.

문제 해결

스테이지에 대한 stage_transform이 등록되지 않음

직렬화된 모델에서 커스텀 스테이지를 사용하려고 할 때 foundry_ml_core.stage.flexible._flexible_stage.FlexibleStageException: No stage_transform registered for stage type: <class 'NoneType'> 오류가 발생할 수 있습니다.

다음 단계를 통해 이 오류를 해결할 수 있습니다:

  • 커스텀 스테이지를 포함하는 플러그인 패키지가 환경의 일부인지 확인하세요.
  • 패키지가 올바르게 구성되었는지 확인하세요. 특히 패키지가 플러그인으로 등록되었는지 그리고 __init__.py 파일이 위에서 설명한대로 클래스를 임포트하는지 확인하세요.
  • 때때로, Conda는 패키지의 구식 버전을 해결할 수 있습니다. 패키지의 올바른 버전이 사용되도록 하려면, 특정 플러그인 버전을 필요로 하는 Conda 환경을 고정하는 것을 추천합니다.

PyPI 패키지

현재 Foundry 모델에서는 Conda에서 의존성을 해결해야 하므로 PyPI 패키지를 지원하지 않습니다.