Snowpark Container Services에서 모델 제공

참고

이 항목에 설명된 Snowpark Container Services(SPCS)에서 모델을 실행하는 기능은 snowflake-ml-python 버전 1.6.4 이상에서 사용할 수 있습니다.

Snowflake Model Registry 를 사용하면 Model Serving을 통해 웨어하우스(기본값)에서 모델을 실행하거나 Snowpark Container Services(SPCS) 컴퓨팅 풀에서 모델을 실행할 수 있습니다. 웨어하우스에서 모델을 실행하면 사용할 수 있는 모델의 크기와 종류에 몇 가지 제한이 있습니다(특히, Snowflake conda 채널에서 제공되는 패키지로 종속성을 충족할 수 있는 Small~Medium 크기의 CPU 전용 모델).

Snowpark Container Services(SPCS)에서 모델을 실행하면 이러한 제한이 완화되거나 완전히 제거됩니다. Python Package Index(PyPI) 또는 기타 소스에서 제공하는 패키지를 포함하여 원하는 모든 패키지를 사용할 수 있습니다. Large 모델은 분산 클러스터 GPUs 상에서 실행할 수 있습니다. 사용자는 Docker나 Kubernetes와 같은 컨테이너 기술에 대해 전혀 몰라도 됩니다. Snowflake Model Serving이 모든 세부 사항을 처리합니다.

핵심 개념

Snowflake Model Serving 추론 아키텍처의 간략한 개요는 다음과 같습니다.

Snowpark Container Services 아키텍처의 모델 추론

아키텍처의 주요 구성 요소는 다음과 같습니다.

  • 추론 서버: 모델을 실행하고 예측을 제공하는 서버입니다. 추론 서버는 여러 추론 프로세스를 사용하여 노드의 기능을 최대한 활용할 수 있습니다. 모델에 대한 요청은 메모리 부족 상태를 피하기 위해 유입 요청 큐를 관리하여 서버에서 과부하가 발생하면 클라이언트를 거부하는 수신 제어를 통해 전송됩니다. 현재 Snowflake는 모든 유형의 모델에 대해 추론을 실행할 수 있는 단순하고 유연한 Python 기반 추론 서버를 제공합니다. Snowflake는 향후에 특정 모델 유형에 최적화된 추론 서버를 제공할 계획입니다.

  • 모델별 Python 환경: 종속성을 다운로드하고 모델을 로드하는 데 필요한 시간 등 모델을 시작할 때 지연 시간을 줄이기 위해 Snowflake는 특정 모델의 종속성을 캡슐화하는 컨테이너를 빌드합니다. 이를 위해서는 컨테이너 빌드 프로세스가 pip 또는 conda 를 사용하여 필요한 종속성을 다운로드할 수 있도록 외부 액세스 통합 이 필요할 수 있습니다.

    참고

    외부 액세스 통합은 conda-forge 또는 PyPI 같은 외부 리포지토리에서 종속성을 다운로드해야 하는 경우에만 필요합니다. Snowflake는 향후 릴리스에서 이 요구 사항을 제거할 예정입니다.

  • 서비스 함수: 웨어하우스에서 실행 중인 코드에서 추론 서버와 통신하기 위해, Snowflake Model Serving은 모델과 동일한 서명을 갖지만 대신 외부 함수 프로토콜 을 통해 추론 서버를 호출하는 함수를 빌드합니다.

  • 수신 엔드포인트: Snowflake 외부의 애플리케이션이 모델을 호출할 수 있도록 Snowflake Model Serving은 공용 인터넷에 액세스할 수 있는 선택적 HTTP 엔드포인트 를 프로비저닝할 수 있습니다.

어떻게 작동하나요?

다음 다이어그램은 Snowflake Model Serving이 웨어하우스 또는 SPCS에서 모델을 배포하고 서비스하는 방법을 보여줍니다.

Snowpark Container Services에서 모델 배포

이와 같이, SPCS 배포 경로는 웨어하우스 배포 경로보다 더 복잡하지만, 모델과 해당 종속성이 있는 컨테이너 이미지를 구축하고 모델을 실행하는 추론 서버를 생성하는 등 Snowflake Model Serving이 모든 작업을 자동으로 수행합니다.

전제 조건

시작하기 전에 다음이 있는지 확인하십시오.

  • 모든 상업용 AWS 리전의 Snowflake 계정. Gov 리전은 지원되지 않습니다. 귀하의 계정이 Azure에 위치한 경우 계정 담당자에게 문의하십시오.

  • snowflake-ml-python Python 패키지 버전 1.6.4 이상.

  • Snowpark Container Services에서 실행할 모델.

  • Snowflake Model Registry 에 익숙해야 함.

  • Snowpark Container Services 에 익숙해야 함. 특히, 컴퓨팅 풀, 이미지 리포지토리 및 관련 권한에 대해 이해해야 합니다.

컴퓨팅 풀 만들기

Snowpark Container Services(SPCS)는 컴퓨팅 풀에서 컨테이너 이미지를 실행합니다. 적합한 컴퓨팅 풀이 아직 없으면 다음과 같이 생성합니다.

CREATE COMPUTE POOL IF NOT EXISTS mypool
    MIN_NODES = 2
    MAX_NODES = 4
    INSTANCE_FAMILY = 'CPU_X64_M'
    AUTO_RESUME = TRUE;
Copy

유효한 인스턴스 패밀리 목록은 패밀리 이름 테이블 을 참조하십시오.

모델을 실행할 역할이 컴퓨팅 풀의 소유자이거나 풀에 대한 USAGE 또는 OPERATE 권한이 있는지 확인합니다.

이미지 리포지토리 만들기

Snowflake Model Serving은 모델과 해당 종속성을 보관하는 컨테이너 이미지를 빌드합니다. 이 이미지를 저장하려면 이미지 리포지토리가 필요합니다. 아직 없다면 다음과 같이 생성합니다.

CREATE IMAGE REPOSITORY IF NOT EXISTS my_inference_images
Copy

소유하지 않은 이미지 리포지토리를 사용하려는 경우 컨테이너 이미지를 빌드할 역할에 리포지토리에 대한 SERVICE READ, SERVICE WRITE, READ 및 WRITE 권한이 있어야 합니다. 다음과 같이 이러한 권한을 부여합니다.

GRANT WRITE ON IMAGE REPOSITORY my_inference_images TO ROLE myrole;
GRANT READ ON IMAGE REPOSITORY my_inference_images TO ROLE myrole;
GRANT SERVICE WRITE ON IMAGE REPOSITORY my_inference_images TO ROLE myrole;
GRANT SERVICE READ ON IMAGE REPOSITORY my_inference_images TO ROLE myrole;
Copy

외부 액세스 통합 만들기

컨테이너 빌드 프로세스에서는 다양한 인터넷 사이트에 접속하여 conda-forge, PyPI 또는 기타 리포지토리나 사이트에서 종속 파일을 다운로드해야 합니다. 이는 ACCOUNTADMIN 역할에 의해 외부 액세스 통합(EAIs)으로 설정되어야 합니다.

참고

외부 액세스 통합은 conda-forge 또는 PyPI 같은 외부 리포지토리에서 종속성을 다운로드해야 하는 경우에만 필요합니다. Snowflake는 향후 릴리스에서 이 요구 사항을 제거할 예정입니다.

외부 액세스 통합은 계정 수준 오브젝트이므로 공유할 수 없습니다.

먼저, 필요한 네트워크 규칙을 생성합니다. conda-forge에 대한 액세스는 항상 필요합니다. 다른 패키지 리포지토리에 대한 액세스가 필요하지 않은 경우 이 규칙을 생성하십시오.

CREATE OR REPLACE NETWORK RULE conda_forge_rule
    MODE = 'EGRESS'
    TYPE = 'HOST_PORT'
    VALUE_LIST = ('conda.anaconda.org:443')
Copy

참고

snowflake conda 채널은 Snowpark Container Services와 함께 사용할 수 없습니다. 모든 conda 패키지는 SPCS 컨테이너 이미지를 빌드할 때 conda-forge에서 설치됩니다.

PyPI에서 패키지를 설치해야 하는 경우 다음 규칙도 생성합니다. 목록에 있는 호스트 4개가 모두 있어야 pip 가 작동합니다.

CREATE OR REPLACE NETWORK RULE pypi_rule
    MODE = 'EGRESS'
    TYPE = 'HOST_PORT'
    VALUE_LIST = ('pypi.org:443', 'pypi.python.org:443', 'pythonhosted.org:443',
                  'files.pythonhosted.org:443');
Copy

다른 여러 사이트에 액세스해야 하는 경우 인터넷에 대한 광범위한 액세스를 허용하는 규칙을 생성할 수 있습니다. 이 규칙이 컨테이너 이미지를 빌드하는 데 사용되는 역할에만 적용되는 한 보안 위험은 거의 없습니다.

CREATE OR REPLACE NETWORK RULE all_access_rule
    MODE = 'EGRESS'
    TYPE = 'HOST_PORT'
    VALUE_LIST = ('0.0.0.0:443', '0.0.0.0:80')
Copy

하나 이상의 규칙을 사용하여 외부 액세스 통합을 생성합니다. 아래 예제에서는 앞서 정의한 conda_forge_rulepypi_rule 을 모두 사용하여 conda-forge 및 PyPI에 대한 액세스만 허용합니다.

CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION model_service_build_access
    ALLOWED_NETWORK_RULES = (conda_forge_rule, pypi_rule)
    ENABLED = true;
Copy

마지막으로 컨테이너 이미지를 빌드할 역할에 EAI에 대한 USAGE를 부여합니다.

GRANT USAGE ON INTEGRATION model_service_build_access TO ROLE model_users;
Copy

제한 사항

이 기능은 아직 미리 보기 단계이므로 다음과 같은 제한이 적용됩니다. Snowflake는 일반 공급 이전에 이러한 제한을 해결할 계획입니다.

  • 모델 소유자만 모델을 Snowpark Container Services에 배포할 수 있습니다.

  • 컴퓨팅 클러스터의 크기는 자동으로 조정되지 않습니다. ALTER SERVICE myservice MIN_INSTANCES = n 을 사용하여 런타임 시에 인스턴스 수를 수동으로 변경할 수 있습니다. 일부 경우, 이로 인해 기존 노드가 실패합니다.

  • 서비스 및 컴퓨팅 풀의 확장 속도가 예상보다 느립니다. 이 문제는 일반 공급 이전에 개선될 예정입니다.

  • 컨테이너 서비스의 자동 일시 중단은 지원되지 않습니다. 드물게 사용할 것으로 예상되는 경우, 사용할 때마다 수동으로 서비스를 일시 중단하는 것이 좋습니다.

  • create_service Python 메서드에서는 여러 외부 액세스 통합(EAIs)을 지정할 수 없습니다. 모델에 conda와 pip가 모두 필요한 경우 둘 모두를 모두 허용하는 단일 EAI를 생성합니다. (참고로 여러 네트워크 규칙이 포함된 EAI를 생성할 수 있습니다)

  • 이미지 빌드 소요되는 시간이 1시간을 초과하면 실패합니다.

  • 테이블 함수는 지원되지 않습니다. 일반 함수가 없는 모델은 현재 Snowpark Container Services에 배포할 수 없습니다.

모델을 SPCS에 배포하기

새 모델 버전을 기록 (reg.log_model 사용)하거나 기존 모델 버전에 대한 참조를 획득 (reg.get_model(...).version())합니다. 두 경우 모두에서 ModelVersion 오브젝트를 참조합니다.

모델 종속성 및 적합성

모델의 종속성은 웨어하우스에서 실행할 수 있는지, SPCS 서비스에서 실행할 수 있는지 또는 둘 다에서 실행할 수 있는지에 따라 결정됩니다. 필요한 경우, 의도적으로 종속성을 지정하여 해당 환경 중 하나에서 모델을 실행할 수 없도록 할 수 있습니다.

Snowflake conda 채널은 웨어하우스에서만 사용할 수 있으며 웨어하우스 종속성에 대한 유일한 소스입니다. 기본적으로 SPCS 모델에 대한 conda 종속성은 conda-forge에서 종속성을 가져옵니다.

모델 버전을 기록하면 모델의 conda 종속성은 Snowflake conda 채널에 대해 검증됩니다. 모델의 모든 conda 종속성이 해당 위치에서 사용 가능한 경우 해당 모델은 웨어하우스에서 실행할 수 있는 것으로 간주됩니다. 또한 서비스를 생성할 때까지는 확인되지 않지만 모든 종속성을 conda-forge에서 사용할 수 있는 경우 SPCS 서비스에서 실행할 수 있습니다.

PyPI 종속성으로 기록된 모델은 SPCS에서 실행해야 합니다. 1개 이상의 PyPI 종속성을 지정하는 것은 모델을 웨어하우스에서 실행할 수 없게 만드는 한 가지 방법입니다. 모델에 conda 종속성만 있는 경우 다음 예제와 같이 명시적 채널(conda-forge도 가능)을 사용하여 1개 이상을 지정하십시오.

reg.log_model(
    model_name="my_model",
    version_name="v1",
    model=model,
    conda_dependencies=["conda-forge::scikit-learn"])
Copy

SPCS 배포 모델에 대해, conda 종속성이 있는 경우 먼저 설치한 다음 pip 를 사용하여 모든 PyPI 종속성을 conda 환경에 설치합니다.

서비스를 만듭니다.

SPCS 서비스를 생성하고 여기에 모델을 배포하려면 다음 예제와 같이 모델 버전의 create_service 메서드를 호출합니다.

mv.create_service(service_name="myservice",
              service_compute_pool="my_compute_pool",
              image_repo="mydb.myschema.my_image_repo",
              build_external_access_integration="my_external_access",
              ingress_enabled=True,
              gpu_requests=None)
Copy

create_service 의 필수 인자는 다음과 같습니다.

  • service_name: 생성할 서비스의 이름입니다. 이 이름은 계정 내에서 고유해야 합니다.

  • service_compute_pool: 모델을 실행하는 데 사용할 컴퓨팅 풀의 이름입니다. 컴퓨팅 풀은 기존에 있어야 합니다.

  • image_repo: 컨테이너 이미지를 저장하는 데 사용할 이미지 리포지토리의 이름입니다. 리포지토리가 이미 있어야 하며 사용자에게 SERVICE WRITE 권한(또는 OWNERSHIP)이 있어야 합니다.

  • build_external_access_integration: 종속성을 다운로드할 때 사용할 외부 액세스 통합의 이름입니다. 이 EA는 항상 conda-forge에 대한 액세스를 허용해야 하며, pip 와 함께 종속성이 설치된 경우 PyPI 호스트도 포함되어야 합니다.

  • ingress_enabled: True이면 HTTP 엔드포인트를 통해 서비스에 액세스할 수 있습니다. 엔드포인트를 생성하려면 사용자에게 BIND SERVICE ENDPOINT 권한이 있어야 합니다.

  • gpu_requests: GPUs의 개수를 지정하는 문자열입니다. CPU 또는 GPU에서 실행할 수 있는 모델의 경우 이 인자에 따라 모델이 CPU에서 또는 GPUs에서 실행될지가 결정됩니다. 모델이 CPU에서만 실행할 수 있는 알려진 유형(예: scikit-learn 모델)인 경우, GPUs가 요청되면 이미지 빌드가 실패합니다.

이 예제에서는 필수적이고 가장 일반적으로 사용되는 인자만 보여줍니다. 전체 인자 목록은 ModelVersion API 참조 섹션을 참조하십시오.

기본 서비스 구성

기본적으로 CPU 기반 모델은 2배의 CPUs 수 및 1개의 워커 프로세스를 사용합니다. GPU 기반 모델은 1개의 워커 프로세스를 사용합니다. num_workers 인자를 사용하여 이를 재정의할 수 있습니다.

일부 모델은 스레드로부터 안전하지 않습니다. 따라서 서비스는 각 워커 프로세스에 대해 별도의 모델 복사본을 로드합니다. 이로 인해 대규모 모델의 경우 리소스 고갈이 발생할 수 있습니다.

기본적으로 추론 서버는 각 노드의 모든 CPU와 메모리를 최대한 활용하기 위해 한 번에 1개의 추론을 실행하도록 최적화되어 있습니다.

컨테이너 이미지 빌드 동작

기본적으로 Snowflake Model Serving은 모델을 실행하는 데 사용되는 것과 동일한 컴퓨팅 풀을 사용하여 컨테이너 이미지를 빌드합니다. 이 추론 컴퓨팅 풀로 인해 이 작업에 대해 과부하가 발생할 수 있습니다(예: 컨테이너 이미지 빌드에 GPUs가 사용되지 않음). 대부분의 경우 이는 컴퓨팅 비용에 큰 영향을 미치지 않지만, 우려되는 경우 image_build_compute_pool 인자를 지정하여 이미지 빌드에 덜 강력한 컴퓨팅 풀을 선택할 수 있습니다.

create_service 는 멱등 함수입니다. 여러 번 호출한다고 해서 매번 이미지 생성이 트리거되는 것은 아닙니다. 그러나 컨테이너 이미지는 종속 패키지의 취약점 수정 등 추론 서비스가 업데이트될 때 다시 빌드될 수 있습니다. 이 경우 create_service 는 자동으로 이미지 재구성을 트리거합니다. 따라서 create_service 를 처음 호출한 후에는 외부 액세스 통합을 비활성화하지 않아야 합니다.

SPCS에 배포된 모델 사용하기

모델 메서드는 SQL, Python 또는 HTTP 엔드포인트를 사용하여 호출할 수 있습니다.

SQL

Snowflake Model Serving은 모델을 SPCS에 배포할 때 서비스 함수를 생성합니다. 이러한 함수는 SQL에서 SPCS 컴퓨팅 풀에서 실행되는 모델로 연결되는 가교의 역할을 합니다. 모델의 각 메소드마다 1개의 서비스 함수가 생성되며, model_name_method_name 같은 이름이 지정됩니다. 예를 들어, 모델에 PREDICTEXPLAIN 이라는 2개의 메서드가 있고 MY_SERVICE 라는 서비스에 배포되는 경우 결과 서비스 함수는 MY_SERVICE_PREDICTMY_SERVICE_EXPLAIN 입니다.

참고

서비스 함수는 서비스 내에 포함되어 있습니다. 이러한 이유로 서비스 함수는 단일 액세스 제어 지점, 즉 서비스만을 갖습니다. 단일 서비스 내에서 각 함수에 대해 서로 다른 액세스 제어 권한을 가질 수 없습니다.

모델의 SQL 형식 서비스 함수를 호출하려면 다음과 같은 코드를 사용합니다.

SELECT MY_SERVICE_PREDICT(...) FROM ...;
Copy

Python

메서드가 실행될 서비스를 지정하는 service_name 인자가 포함된 모델 버전 오브젝트의 run 메서드를 사용하여 서비스의 메서드를 호출합니다. 예:

service_prediction = mv.run(
    test_df,
    function_name="predict",
    service_name="my_service")
Copy

service_name 인자를 포함시키지 않으면 모델이 웨어하우스에서 실행됩니다.

HTTP 엔드포인트

수신이 활성화된 서비스를 배포하면 서비스에 새 HTTP 엔드포인트를 사용할 수 있습니다. ShOW ENDPOINTS IN SERVICE 명령을 사용하여 엔드포인트를 찾을 수 있습니다.

SHOW ENDPOINTS IN SERVICE my_service;
Copy

ingress_url 열을 기록해 둡니다. 이 열은 random_str-account-id.snowflakecomputing.app 과 유사해야 합니다.

이 엔드포인트 사용에 대해 자세히 알아보려면 SPCS 자습서인 Snowpark Container Services 서비스 만들기 및 개발자 가이드의 Snowflake 외부에서 서비스 사용하기 항목을 참조하십시오. 필수 데이터 형식에 대한 자세한 내용은 원격 서비스 입력 및 출력 데이터 타입 섹션을 참조하십시오.

모델 서비스 HTTP 엔드포인트 사용과 관련한 예제는 GPU 기반 추론을 위한 Hugging Face 문장 변환기 배포하기 섹션을 참조하십시오.

서비스 관리하기

Snowpark Container Services는 서비스 관리를 위한 SQL 인터페이스를 제공합니다. 다른 SPCS 서비스를 관리할 때와 마찬가지로 Snowflake Model Serving에서 생성한 SPCS 서비스에도 DESCRIBE SERVICEALTER SERVICE 명령을 사용할 수 있습니다. 예를 들어 다음을 할 수 있습니다.

  • 서비스의 MIN_INSTANCES 및 기타 속성 변경하기

  • 서비스 삭제

  • 다른 계정에 서비스 공유

  • 서비스 소유권 변경(새로운 소유자는 모델에 액세스할 수 있어야 함)

참고

서비스 소유자가 어떤 이유로든 기본 모델에 대한 액세스 권한을 상실하면 다시 시작한 후 서비스가 작동을 멈춥니다. 작동 멈춤은 다시 시작할 때까지 계속 유지됩니다.

재현성과 디버깅 가능성을 보장하기 위해 사용자는 기존 추론 서비스의 사양을 변경할 수 없습니다. 하지만 사용자는 사양을 복사하고 사용자 지정한 다음, 사용자 지정 사양을 사용하여 모델을 호스팅하는 자체 서비스를 생성할 수 있습니다. 하지만 이를 통해 기본 모델이 삭제되는 것을 방지할 수는 없습니다. 일반적으로 Snowflake Model Serving이 서비스를 생성하도록 허용하는 것이 가장 좋습니다.

서비스 일시 중단

모델 사용이 끝나거나, 더 이상 사용하지 않을 경우 비용을 절감하기 위해 서비스를 일시 중단하는 것이 좋습니다. 이 작업은 ALTER SERVICE 명령을 사용하여 수행할 수 있습니다.

ALTER SERVICE my_service SUSPEND;
Copy

서비스는 요청을 받으면 자동으로 다시 시작되지만, 스케줄링 및 시작 지연이 있을 수 있습니다. 스케줄링 지연은 컴퓨팅 풀의 가용성에 따라 달라지며, 시작 지연은 모델의 크기에 따라 달라집니다.

모델 삭제하기

서비스에서 사용 중인 모델 또는 모델 버전(실행 중 또는 일시 중단)은 삭제할 수 없다는 제한이 있지만, SQL 인터페이스 또는 Python API를 사용하여 평소와 같이 모델 및 모델 버전을 관리할 수 있습니다. 모델이나 모델 버전을 삭제하려면 먼저 서비스를 삭제하십시오.

이러한 예제에서는 이미 컴퓨팅 풀, 이미지 리포지토리, 외부 액세스 통합을 생성했으며 필요에 따라 권한을 부여한 것으로 가정합니다. 자세한 내용은 전제 조건 섹션을 참조하십시오.

CPU 기반 추론을 위한 XGBoost 모델 배포하기

다음 코드는 SPCS에서 추론을 위해 XGBoost 모델을 배포한 다음 배포된 모델을 추론에 사용하는 주요 단계를 보여줍니다. 이 예제에 대한 노트북은 사용 가능합니다.

from snowflake.ml.registry import registry
from snowflake.ml.utils.connection_params import SnowflakeLoginOptions
from snowflake.snowpark import Session
from snowflake.ml.modeling.xgboost import XGBRegressor

# your model training code here output of which is a trained xgb_model

# Open model registry
reg = registry.Registry(session=session, database_name='my_registry_db', schema_name='my_registry_schema')

# Log the model in Snowflake Model Registry
model_ref = reg.log_model(
    model_name="my_xgb_forecasting_model",
    version_name="v1",
    model=xgb_model,
    conda_dependencies=["scikit-learn","xgboost"],
    sample_input_data=train,
    comment="XGBoost model for forecasting customer demand"
)

# Deploy the model to SPCS
reg_model.create_service(
    service_name="ForecastModelServicev1",
    service_compute_pool="my_cpu_pool",
    image_repo="my_db.data.my_images",
    build_external_access_integration="my_egress_access_integration_for_conda_pip",
    ingress_enabled=True)

# See all services running a model
reg_model.list_services()

# Run on SPCS
reg_model.run(input_data, function_name="predict", service_name="ForecastModelServicev1")

# Delete the service
reg_model.delete_service("ForecastModelServicev1")
Copy

GPU 기반 추론을 위한 Hugging Face 문장 변환기 배포하기

이 코드는 HTTP 엔드포인트를 포함한 Hugging Face 문장 변환기를 훈련시키고 배포합니다.

from snowflake.ml.registry import registry
from snowflake.ml.utils.connection_params import SnowflakeLoginOptions
from snowflake.snowpark import Session
from sentence_transformers import SentenceTransformer

session = Session.builder.configs(SnowflakeLoginOptions("connection_name")).create()
reg = registry.Registry(session=session, database_name='my_registry_db', schema_name='my_registry_schema')

# Take an example sentence transformer from HF
embed_model = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2')

# Have some sample input data
input_data = [
    "This is the first sentence.",
    "Here's another sentence for testing.",
    "The quick brown fox jumps over the lazy dog.",
    "I love coding and programming.",
    "Machine learning is an exciting field.",
    "Python is a popular programming language.",
    "I enjoy working with data.",
    "Deep learning models are powerful.",
    "Natural language processing is fascinating.",
    "I want to improve my NLP skills.",
]

# Log the model with pip dependencies
pip_model = reg.log_model(
    embed_model,
    model_name="sentence_transformer_minilm",
    version_name='pip',
    sample_input_data=input_data,  # Needed for determining signature of the model
pip_requirements=["sentence-transformers", "torch", "transformers"], # If you want to run this model in the Warehouse, you can use conda_dependencies instead
)

# Force Snowflake to not try to check warehouse
conda_forge_model = reg.log_model(
    embed_model,
    model_name="sentence_transformer_minilm",
    version_name='conda_forge_force',
    sample_input_data=input_data,
    # setting any package from conda-forge is sufficient to know that it can't be run in warehouse
    conda_dependencies=["sentence-transformers", "conda-forge::pytorch", "transformers"]
)

# Deploy the model to SPCS
pip_model.create_service(
    service_name="my_minilm_service",
    service_compute_pool="my_gpu_pool",  # Using GPU_NV_S - smallest GPU node that can run the model
    image_repo="my_db.data.my_images",
    ingress_enabled=True,
    build_external_access_integration="my_egress_access_integration_for_conda_pip",
    gpu_requests="1", # Model fits in GPU memory; only needed for GPU pool
    max_instances=4, # 4 instances were able to run 10M inferences from an XS warehouse
)

# See all services running a model
pip_model.list_services()

# Run on SPCS
pip_model.run(input_data, function_name="encode", service_name="my_minilm_service")

# Delete the service
pip_model.delete_service("my_minilm_service")
Copy

이 모델은 수신이 활성화되어 있으므로 HTTP 엔드포인트를 다음과 같이 호출할 수 있습니다.

import json
from pprint import pprint
import requests
import snowflake.connector

# Generate right header
# Note that, ideally user should use key-pair authentication for API access (see this).
def initiate_snowflake_connection():
    connection_parameters = SnowflakeLoginOptions("connection_name")
    connection_parameters["session_parameters"] = {"PYTHON_CONNECTOR_QUERY_RESULT_FORMAT": "json"}
    snowflake_conn = snowflake.connector.connect(**connection_parameters)
    return snowflake_conn

def get_headers(snowflake_conn):
    token = snowflake_conn._rest._token_request('ISSUE')
    headers = {'Authorization': f'Snowflake Token=\"{token["data"]["sessionToken"]}\"'}
    return headers

headers = get_headers(initiate_snowflake_connection())

# Put the endpoint url with method name
URL='https://<random_str>-<account>.snowflakecomputing.app/encode'

# Prepare data to be sent
data = {
    'data': []
}
for idx, x in enumerate(input_data):
    data['data'].append([idx, x])

# Send over HTTP
def send_request(data: dict):
    output = requests.post(URL, json=data, headers=headers)
    assert (output.status_code == 200), f"Failed to get response from the service. Status code: {output.status_code}"
    return output.content

# Test
results = send_request(data=data)
pprint(json.loads(results))
Copy

GPU 기반 추론을 위한 PyTorch 모델 배포하기

GPU 추론을 위해 PyTorch 딥러닝 추천 모델(DLRM)을 훈련시키고 SPCS에 배포하는 예제는 이 빠른 시작 을 참조하십시오.

모범 사례

이미지 리포지토리 공유하기

여러 사용자 또는 역할이 동일한 모델을 사용하는 것은 일반적입니다. 단일 이미지 리포지토리를 사용하면 이미지를 한 번만 빌드하여 모든 사용자가 재사용할 수 있어 시간과 비용을 절약할 수 있습니다. 리포지토리를 사용할 모든 역할에는 리포지토리에 대한 SERVICE READ, SERVICE WRITE, READ, WRITE 권한이 필요합니다. 종속성을 업데이트하기 위해 이미지를 다시 빌드해야 할 수 있으므로 쓰기 권한을 유지해야 하며, 이미지를 처음 빌드한 후에는 취소하지 마십시오.

추론 서비스 크기 조정하기

Snowpark Container Services 자동 크기 조정은 매우 보수적이며 대부분의 ML 워크로드에 대해 충분히 빠르게 확장하거나 축소하지 않습니다. 따라서 Snowflake는 일반적인 워크로드에 필요한 성능을 얻기 위해 MIN_INSTANCES 및 MAX_INSTANCES를 모두 같은 값으로 설정하고 이 값을 선택하는 것을 권장합니다. 다음과 같은 SQL을 사용합니다.

ALTER SERVICE myservice
    SET MIN_INSTANCES = <new_num>
        MAX_INSTANCES = <new_num>;
Copy

동일한 이유로, 처음에 Python API를 사용하여 서비스를 생성할 때 create_service 메서드는 max_instances 만 허용하고 min_instances 에는 동일한 값을 사용합니다.

노드 유형 및 인스턴스 수 선택하기

모델이 메모리에 들어갈 수 있는 가장 작은 GPU 노드를 사용하십시오. 더 큰 GPU 노드에서 num_workers 를 늘리는 것과 반대로 인스턴스 수를 늘리는 방식으로 크기를 조정합니다. 예를 들어, 모델이 GPU_NV_S 인스턴스 유형에 맞는 경우 더 큰 GPU 인스턴스에서 gpu_requestsnum_workers 를 조합하여 사용하는 대신 gpu_requests=1 를 사용하고 max_instances 를 늘려 확장합니다.

웨어하우스 크기 선택하기

웨어하우스가 클수록 더 많은 병렬 요청이 추론 서버로 전송됩니다. 추론은 비용이 많이 드는 작업이므로 가능하면 작은 규모의 웨어하우스를 사용하십시오. Medium보다 큰 웨어하우스 크기를 사용하면 쿼리 성능이 가속화되지 않고 추가 비용이 발생합니다.

모델 배포를 위한 별도 스키마

서비스를 생성하면 여러 개의 스키마 수준 오브젝트(서비스 자체 및 모델 함수당 1개의 서비스 함수)가 생성됩니다. 혼란을 피하려면 모델 저장(Snowflake Model Registry)과 배포(Snowflake Model Serving)에 별도의 스키마를 사용하십시오.

문제 해결하기

SPCS 배포 모니터링

다음 SQL 쿼리를 사용하여 실행 중인 서비스를 검사하여 배포를 모니터링할 수 있습니다.

SHOW SERVICES IN COMPUTE POOL my_compute_pool;
Copy

다음의 두 작업이 시작됩니다.

  • MODEL_BUILD_xxxxx: 이름이 충돌하는 것을 방지하기 위해 이름의 마지막 글자는 무작위로 지정됩니다. 이 작업은 이미지를 빌드하고 이미지가 빌드된 후 종료됩니다. 이미지가 이미 있으면 작업을 건너뜁니다.

    로그는 패키지 종속성의 충돌이나 패키지 리포지토리에 대한 액세스를 방해하는 외부 액세스 통합 문제 등 다른 잠재적인 문제를 디버깅하는 데 유용합니다. 이 작업의 로그를 보려면 아래 SQL를 실행하고 마지막 문자를 동일하게 사용해야 합니다.

    CALL SYSTEM$GET_SERVICE_LOGS('MODEL_BUILD_xxxxx', 0, 'model-build');
    
    Copy
  • MYSERVICE: create_service 에 대한 호출에 지정된 서비스 이름입니다. 이 작업은 MODEL_BUILD 작업이 성공하거나 건너뛰면 시작됩니다. 이 작업의 로그를 보려면 아래 SQL을 실행합니다.

    CALL SYSTEM$GET_SERVICE_LOGS('MYSERVICE', 0, 'model-inference');
    
    Copy

패키지 충돌

서비스 컨테이너에 설치되는 패키지는 두 가지 시스템, 즉 모델 자체와 추론 서버에 의해 결정됩니다. 모델의 종속성으로 인한 충돌을 최소화하기 위해 추론 서버에는 다음 패키지만 필요합니다.

  • gunicorn<24.0.0

  • starlette<1.0.0

  • uvicorn-standard<1.0.0

위와 함께 모델 종속성이 사용자가 사용하는 pip 또는 conda 에 의해 해결되어야 합니다.

모델에 conda_dependenciespip_requirements 가 모두 설정되어 있는 경우 conda를 통해 다음과 같이 설치됩니다.

채널:

  • conda-forge

  • nodefaults

종속성:

  • all_conda_packages

  • pip:
    • all_pip_packages

Snowflake conda 채널은 웨어하우스에서 사용할 수 있고 defaults 채널에서는 사용자가 Anaconda 이용 약관에 동의해야 하므로, 기본적으로 Snowflake는 Anaconda 패키지에 conda-forge를 사용합니다. 기본 채널에서 패키지를 지정하려면 패키지 이름 defaults::pkg_name 을 포함하십시오.

서비스 메모리 부족

일부 모델은 스레드에 안전하지 않으므로 Snowflake는 각 작업자 프로세스에 대해 모델의 복사본을 메모리에 로드합니다. 이로 인해 워커의 수가 많은 대규모 모델의 경우 메모리 부족 조건이 발생할 수 있습니다. num_workers 를 줄여보십시오.

쿼리 성능이 만족스럽지 않음

일반적으로 추론은 추론 서비스의 인스턴스 수에 따라 병목 현상이 발생합니다. 모델을 배포하는 동안 max_instances 에 대한 더 높은 값을 전달해 보십시오.

서비스 사양 변경 불가

모델 빌드 및 추론 서비스의 사양은 ALTER SERVICE를 사용하여 변경할 수 없습니다. TAG, MIN_INSTANCES 등의 특성만 변경할 수 있습니다.

그러나 이미지가 이미지 리포지토리에 게시되어 있으므로 사양을 복사하고 수정한 후 수동으로 시작할 수 있는 새 서비스를 생성할 수 있습니다.