Узнайте, как развернуть предварительно обученные большие языковые модели из Hugging Face в Snowflake с помощью векторизованных пользовательских функций Python.

Отказ от ответственности. Содержание этой статьи было первоначально опубликовано в публикации Snowflake Medium. Ссылку на оригинал статьи можно найти здесь.

Модели больших языков (LLM), такие как ChatGPT, приобрели популярность благодаря своей способности генерировать ответы, подобные человеческим, на текстовый ввод. Однако ChatGPT — лишь одна из многих LLM, добившихся впечатляющих результатов за последние годы.

LLM с открытым исходным кодом, такие как BERT (представления двунаправленного кодировщика от трансформаторов), созданные исследователями Google в 2018 году, или RoBERTa (надежно оптимизированный подход BERT), разработанный исследователями Facebook AI Research (FAIR) в 2019 году, также преуспели в решении различных задач, таких как как извлечение признаков, обобщение, классификация текста, сходство предложений и многое другое.

Некоторые из преимуществ использования LLM с открытым исходным кодом в качестве альтернативы ChatGPT:

  1. Гибкость: LLM с открытым исходным кодом можно использовать для различных задач обработки естественного языка и на нескольких языках.
  2. Прозрачность: LLM с открытым исходным кодом обеспечивают прозрачность благодаря открытому коду и данным для проверки и модификации.
  3. Стоимость: LLM с открытым исходным кодом часто доступны по более низкой цене или бесплатно по сравнению с проприетарными моделями, такими как ChatGPT.
  4. Поддержка сообщества: LLM с открытым исходным кодом поддерживаются сообществом разработчиков и исследователей, которые предоставляют ресурсы, инструменты и поддержку.

Hugging Face, популярное сообщество искусственного интеллекта с открытым исходным кодом, предоставляет хорошо документированную и простую в использовании библиотеку для взаимодействия со многими из этих замечательных LLM с открытым исходным кодом. Используя эту библиотеку, мы можем развернуть эти LLM непосредственно в Snowflake, предлагая многочисленные преимущества, включая повышение эффективности за счет устранения перемещения данных, анализа в реальном времени, масштабируемости, расширенных функций безопасности и потенциальной экономии средств.

В этой статье мы расскажем вам, как развернуть предварительно обученные модели LLM в Snowflake с использованием векторизованных пользовательских функций Python для пакетной обработки. К концу этой статьи у вас будут инструменты, чтобы начать раскрывать потенциал этих моделей в вашей организации.

Библиотека Hugging Face Transformer

Библиотека Hugging Face Transformer — это библиотека Python с открытым исходным кодом для задач обработки естественного языка (NLP). Он предоставляет набор современных предварительно обученных LLM для различных задач, таких как классификация текста, ответы на вопросы, генерация текста и многое другое.

Библиотека построена на основе PyTorch и TensorFlow 2.0 (по умолчанию библиотека использует Pytorch). Он предоставляет единый API для работы с различными предварительно обученными моделями из разных источников.

В этой статье речь пойдет об одном конкретном случае использования этой библиотеки — классификации Zero-Shot. Этот метод включает в себя классификацию текста по заранее определенным категориям без использования помеченных обучающих данных. Другими словами, нулевая классификация позволяет нам классифицировать текст по категориям, на которых модель явно не обучалась.

Например, мы можем классифицировать отзывы клиентов по темам, относящимся к разным частям вашего бизнеса, а затем использовать эту классификацию для определения областей, требующих улучшения, и получения ценной информации. Это можно сделать в Python, выполнив следующий код:

from transformers import pipeline
classifier = pipeline(
    "zero-shot-classification",
    model="Facebook/bart-large-mnli"
)
sequence_to_classify = "The interface gets frozen very often"
candidate_labels = ['customer support', 'product experience', 'account issues']
classifier(sequence_to_classify, candidate_labels)

Модель присваивает вероятность каждой из категорий в зависимости от того, насколько текст связан с меткой. Чтобы получить прогноз, нам нужно выбрать категорию с наибольшей вероятностью.

Это просто? Да, это. Все, что нам нужно сделать, это выбрать нужную модель и категории, которые будут использоваться в качестве меток-кандидатов. Процесс использования других моделей для таких задач, как анализ тональности, суммирование текста и извлечение признаков, столь же прост.

Теперь, как мы можем сделать эту функциональность доступной непосредственно в Snowflake?

Снежинки векторизованные пользовательские функции (определяемые пользователем функции)

Векторизованные пользовательские функции (определяемые пользователем функции) — это мощная функция Snowflake, обеспечивающая более эффективную и высокопроизводительную обработку данных. По сравнению с традиционными скалярными пользовательскими функциями, которые обрабатывают данные по одной строке за раз, векторизованные пользовательские функции могут обрабатывать несколько строк данных в одном пакете, что повышает производительность запросов и сокращает перемещение данных.

Кроме того, векторизованные пользовательские функции используют более простой синтаксис, более тесно связанный с SQL, что упрощает для разработчиков написание и поддержку кода. Эта функция также предназначена для бесперебойной работы с существующим синтаксисом и типами данных SQL Snowflake, что упрощает интеграцию с существующими инструментами и приложениями. Кроме того, векторизованные пользовательские функции легко масштабируются, что позволяет быстро и эффективно обрабатывать большие наборы данных.

В этом случае эта функция очень полезна, потому что мы можем создать функцию, которую нужно вызвать только один раз, чтобы делать прогнозы для всех отзывов клиентов. Это сокращает время вывода по сравнению с вызовом функции для каждого обзора по отдельности. Таким образом, мы собираемся развернуть наши модели Hugging Face как векторизованные пользовательские функции.

Развертывание модели в Snowflake

Первым шагом в этом процессе является создание этапа Snowflake для хранения векторизованной пользовательской функции. Назовем этот этап ZERO_SHOT_CLASSIFICATION.

CREATE STAGE IF NOT EXISTS {your db}.{your schema}.ZERO_SHOT_CLASSIFICATION;

При первом вызове библиотеки преобразователя для конкретной модели модель загружается и сохраняется локально. Однако пользовательские функции Snowflake не позволяют вызывать внешние URL-адреса внутри функции из-за ограничений безопасности, что делает этот процесс несовместимым.

К счастью, библиотека позволяет загружать модель с локального пути, поэтому, чтобы решить проблему внешнего доступа, мы сожмем модель и загрузим ее на внутреннюю сцену, которую мы создали ранее. При прогнозировании мы будем загружать модель из внутреннего этапа, кэшировать результат и использовать модель. Это позволяет нам использовать одни и те же библиотеки и минимизировать время отклика прогноза.

Чтобы сжать модель, мы можем использовать модель Python joblib, как показано ниже.

import joblib
joblib.dump(classifier, 'bart-large-mnli.joblib')

Далее мы будем использовать Snowpark для переноса модели на внутреннюю сцену. Для этого мы создадим сеанс Snowpark и воспользуемся командой put, чтобы загрузить модель на сцену. Стоит отметить, что мы не будем сжимать файл на этапе, поскольку он уже сжат.

from snowflake.snowpark import Session
session = Session.builder.configs({your connection parameters}).create()
session.file.put(
   'bart-large-mnli.joblib',
   stage_location = f'@{your db}.{your schema}.ZERO_SHOT_CLASSIFICATION',
   overwrite=True,
   auto_compress=False
)

Когда нам нужно использовать модель, мы должны сначала распаковать ее, что может занять много времени. Чтобы ускорить этот процесс, мы можем использовать библиотеку Python cachetools. Эта библиотека хранит результаты вызовов функций в кэше и извлекает их при повторном использовании тех же входных данных. Мы можем создать функцию, используя эту библиотеку, следующим образом:

# Caching the model
import cachetools
Import sys
@cachetools.cached(cache={})
def read_model():
   import_dir = sys._xoptions.get("snowflake_import_directory")
   if import_dir:
       # Load the model
       return joblib.load(f'{import_dir}/bart-large-mnli.joblib'

Теперь мы можем написать векторизованную UDF-функцию, чтобы использовать модель

from snowflake.snowpark.functions import pandas_udf
from snowflake.snowpark.types import StringType, PandasSeriesType
@pandas_udf(  
       name='{your db}.{your schema}.get_review_classification',
       session=session,
       is_permanent=True,
       replace=True,
       imports=[
           f'@{your db}.{your schema}.ZERO_SHOT_CLASSIFICATION/bart-large-mnli.joblib'
       ],
       input_types=[PandasSeriesType(StringType())],
       return_type=PandasSeriesType(StringType()),
       stage_location='@{your db}.{your schema}.ZERO_SHOT_CLASSIFICATION',
       packages=['cachetools==4.2.2', 'transformers==4.14.1']
   )
def get_review_classification(sentences: pd.Series) -> pd.Series:
   # Classify using the available categories
   candidate_labels = ['customer support', 'product experience', 'account issues']
   classifier = read_model()
   # Apply the model
   predictions = []
   for sentence in sentences:
       result = classifier(sentence, candidate_labels)
       if 'scores' in result and 'labels' in result:
           category_idx = pd.Series(result['scores']).idxmax()
           predictions.append(result['labels'][category_idx])
       else:
           predictions.append(None)
   return pd.Series(predictions)

Некоторые важные подробности о функции:

  • Даже если функция и модель находятся на одном этапе, необходимо явно импортировать файл, сжатый моделью, в функцию.
  • Входные и возвращаемые типы являются обязательными для векторизованных пользовательских функций Snowflake.
  • При использовании функции важно перечислить все используемые пакеты вместе с их соответствующими версиями. Это важная практика для обеспечения ясности и организации кода. Стоит отметить, что Anaconda уже управляет объявлением зависимостей для пользователей Snowflake. Поэтому нет необходимости в предварительном шаге для загрузки и выгрузки этих или их транзитивных зависимостей перед созданием пользовательской функции.
  • В этом случае мы вызываем функцию прогнозирования один раз для каждой записи. Есть некоторые модели, которые позволяют прогнозировать в пакетном режиме, что улучшает процесс выполнения.

Вот и все! Функция теперь полностью функциональна и может быть легко вызвана непосредственно с помощью SQL. Наконец, давайте создадим несколько примеров данных для проверки функциональности.

WITH cs AS (
   SELECT value AS customer_review
   FROM (
   VALUES
       ('Nobody was able to solve my issues with the system'),
       ('The interface gets frozen very often'),
       ('I was charged two in the same period’)
   ) AS t(value)
)
SELECT
   cs.customer_review,
  {your database}.{your schema}.get_review_classification(
       customer_review::VARCHAR
   ) AS category_prediction
FROM cs;

Важные соображения

  • Чтобы обеспечить совместимость и избежать потенциальных проблем при использовании пользовательских функций Snowflake, настоятельно рекомендуется явно указывать версии пакетов при создании локальных сред conda и во время регистрации пользовательских функций. Таким образом, вы можете убедиться, что в вашей локальной среде установлена ​​та же версия библиотеки, что и в среде Python UDF. Эта передовая практика может сэкономить вам драгоценное время и силы при устранении любых проблем совместимости, которые могут возникнуть. Вы можете ознакомиться с доступными версиями библиотек Snowflake, выполнив следующий код SQL.
SELECT * FROM {your db}.information_schema.packages
WHERE (
   package_name LIKE '%cachetools%' OR
   package_name LIKE '%transformers%'
)
AND LANGUAGE = 'python';
  • По умолчанию библиотека-трансформер использует PyTorch. Однако, если вы предпочитаете использовать Tensorflow, могут возникнуть проблемы с библиотекой сериализации joblib. Чтобы решить эту проблему, загрузите всю папку модели, а не только файл {model}.joblib, и импортируйте все файлы внутри пользовательской функции.
  • Работая над этой статьей, я обнаружил, что библиотека sentence_transformers недоступна в среде Snowflake Python. Однако аналогичную функциональность можно получить, используя стандартную библиотеку Transformer.
  • При создании первой версии модели описанной выше процедуры развертывания будет достаточно. Когда вы будете готовы к развертыванию в рабочей среде и вводу в эксплуатацию, вы можете загрузить архив предварительно обученной модели непосредственно перед регистрацией UDF, что необходимо сделать только один раз. Для будущих запусков загрузка необходима только в том случае, если архив модели изменился.

Заключение

Таким образом, LLM с открытым исходным кодом предлагают впечатляющий набор функций, которые делают их ценным активом в различных задачах обработки естественного языка и привлекательной альтернативой проприетарным моделям, таким как ChatGPT. Кроме того, благодаря таким платформам, как Hugging Face, предоставляющим доступные и полные библиотеки, интеграция и использование этих моделей стали значительно проще, даже в таких сложных средах, как Snowflake.

Возможность развертывания этих моделей непосредственно в Snowflake открывает новые возможности для анализа в реальном времени, масштабируемости и расширенных функций безопасности без необходимости перемещения данных. Независимо от того, являетесь ли вы специалистом по данным, разработчиком или бизнес-лидером, понимание и использование этих LLM с открытым исходным кодом может открыть новые возможности для принятия решений на основе данных, повышения эффективности и потенциальной экономии средств.

Я Фабиан Эрнандес, архитектор данных в Infostrux Solutions. Спасибо, что прочитали мой пост в блоге. Вы можете подписаться на меня в LinkedIn и подписаться на Infostrux Medium Blogs, чтобы быть в курсе самых интересных новостей Data Engineering и Snowflake. Пожалуйста, дайте нам знать ваши мысли об этом подходе в разделе комментариев.