❄️

Snowflake で簡単に LLM のファインチューニングをしよう Part2 -AWS 東京リージョンで使ってみよう-

2024/12/22に公開

はじめに

本記事は Snowflake Advent Calendar の22日目です。是非 Snowflake の進化を楽しんでいってください!

本記事は Part2 となります。Snowflake Cortex Fine-tuning の基本的な使い方や教師データ生成アプリの作成については以下 Part1 の記事を最初にご覧ください。(自力で教師データを準備できる方は本記事から開始いただいて問題ございません)

https://zenn.dev/tsubasa_tech/articles/29316f1341391e

本記事では準備した教師データで実際にファインチューニングを行い、そのモデルをチャットアプリに組み込んでみたいと思います。

教師データは Part1 で作成した教師データ生成アプリを活用して、Streamlit in Snowflake に関するナレッジを準備してみました。(これで Streamlit in Snowflake のアプリ作りを更に高速化したい!)

機能概要

今回やること

  • Cortex Fine-tuning を試してみる
  • (Option) 教師データ生成アプリを作成する
  • ★ファインチューニングモデルに対応したチャットアプリを作成する
  • ★ファインチューニングモデルを他のリージョンで使ってみる

★:Part2で実現する範囲

チャットアプリの機能一覧

  • Cortex LLM のベースモデルとファインチューニングモデルの両方から選べる
  • 選んだ LLM のモデルでチャットボットと会話することができる

前提条件

  • Cortex Fine-tuning に対応しているリージョンの Snowflake アカウント
  • 上記とは別の AWS Tokyo リージョンの Snowflake アカウント
  • Streamlit in Snowflake のインストールパッケージ
    • snowflake-ml-python 1.6.4

教師データの確認

まずは教師データの中身を確認していきましょう。
ワークシートで以下のクエリを実行し教師データを確認します。
私は40件ほどのデータを用意してみました。

-- トレーニングデータの確認
SELECT * from finetune_training_data LIMIT 10;


教師データテーブル

ちゃんと prompt 列には質問事項が、completion 列には想定出力結果が入っていますね。前回も申し上げた通り、最低この2つのカラムがあれば良いので、他のカラムは ID や作成日時や更新日時など後で管理しやすいように情報を追加してあります。

ファインチューニングの実行

続いて以下のクエリを実行しトレーニングを開始します。

-- Cortex Fine-tuningでトレーニング実行
SELECT SNOWFLAKE.CORTEX.FINETUNE(
  'CREATE',
  'sis_master_model_v1',
  'llama3.1-70b',
  'SELECT prompt, completion FROM finetune_training_data'
);

ファインチューニングモデルの名前は sis_master_model_v1 としました。教師データテーブルである finetune_training_data からは promptcompletion の2つのカラムだけを渡しています。

ファインチューニングが始まったら以下クエリで状況を確認します。

-- トレーニングジョブの一覧からジョブIDを確認
SELECT SNOWFLAKE.CORTEX.FINETUNE('SHOW');

このクエリで確認したジョブ ID を使って以下クエリで学習の詳細情報を確認します。

-- ジョブIDからトレーニングジョブの詳細確認
SELECT SNOWFLAKE.CORTEX.FINETUNE(
  'DESCRIBE',
  '<ジョブID>'
);

学習が完了すると statusIN_PROGRESS から SUCCESS に変わります。
trained_tokens の値がトレーニングでカウントされたトークン数となりますので、この数値からトレーニングコストを計算することが可能です。今回は 25493 だったため、0.1 クレジット以下でとてもリーズナブルでした!

ファインチューニングモデルのテスト

まずはワークシートでファインチューニングモデルが使えそうかテストしていきたいと思います。前回同様ベースモデルと比較してみましょう。

-- 推論クエリ (ベースモデル)
SELECT SNOWFLAKE.CORTEX.COMPLETE(
  'llama3.1-70b',
  'Streamlit in Snowflakeのサンプルコードを生成してください。'
);

-- 推論クエリ (ファインチューニングモデル)
SELECT SNOWFLAKE.CORTEX.COMPLETE(
  'sis_master_model_v1',
  'Streamlit in Snowflakeのサンプルコードを生成してください。'
);

ベースモデルの出力結果

ベースモデルでは Streamlit in Snowflake ではなく セルフホストの Streamlit のコードが出力されています。

import streamlit as st
import snowflake.connector

# Snowflakeの接続情報
ACCOUNT = 'your_account_name'
USER = 'your_username'
PASSWORD = 'your_password'
WAREHOUSE = 'your_warehouse_name'
DATABASE = 'your_database_name'
SCHEMA = 'your_schema_name'

# Snowflakeに接続
ctx = snowflake.connector.connect(
    user=USER,
    password=PASSWORD,
    account=ACCOUNT,
    warehouse=WAREHOUSE,
    database=DATABASE,
    schema=SCHEMA
)

# カーソルを取得
cs = ctx.cursor()

# Streamlitアプリケーションを作成
st.title('Snowflakeデータの表示')

# Snowflakeからデータを取得
cs.execute("SELECT * FROM your_table_name")
data = cs.fetchall()

# データを表示
st.write(data)

# カーソルと接続を閉じる
cs.close()
ctx.close()

ファインチューニングモデルの出力結果

一方でファインチューニングモデルではシンプルでありながらもちゃんと get_active_session で Snowflake のセッション情報を取得しており Streamlit in Snowflake のコードになっております!これは期待できそうです、、、!

import streamlit as st
import pandas as pd
from snowflake.snowpark.context import get_active_session

# Snowflakeのセッションを取得
session = get_active_session()

# Snowflakeのテーブルからデータを取得
df = session.table("my_table").to_pandas()

# Streamlitのアプリケーションを作成
st.title("My Streamlit App")
st.write(df)

チャットアプリを作成する

さあ、次は Streamlit in Snowflake のチャットアプリでファインチューニングモデルを使ってみましょう。今回もソースコードを用意しましたので、新規で Streamlit in Snowflake のアプリを作成し、前提条件に記載のパッケージ snowflake-ml-python をインストールした上で以下コードをコピー&ペーストで貼り付けて実行してください。

from snowflake.snowpark.context import get_active_session
import streamlit as st
from snowflake.cortex import Complete as CompleteText

# Streamlitのページ設定
st.set_page_config(layout="wide")

# Snowflakeのセッションを取得
snowflake_session = get_active_session()

# Snowflakeアカウント内のファインチューニングモデルを取得
def get_finetuned_models():
    models_df = snowflake_session.sql("SHOW MODELS IN ACCOUNT").collect()

    # ファインチューニングモデルのみをフィルタリング
    finetuned_models = [
        {
            'display_name': row['name'],
            'full_name': f"{row['database_name']}.{row['schema_name']}.{row['name']}"
        }
        for row in models_df
        if row['model_type'] == 'CORTEX_FINETUNED'
    ]
    return finetuned_models

# アプリケーションのタイトル
st.title("Cortex LLM シンプルチャットアプリ")

# AI設定
st.sidebar.title("LLM の設定")

# モデルタイプの選択
model_type = st.sidebar.radio(
    "モデルタイプを選択してください",
    ("標準モデル", "ファインチューニングモデル")
)

if model_type == "標準モデル":
    lang_model = st.sidebar.radio("Cortex AIのモデルを選択してください",
                                ["snowflake-arctic",
                                 "reka-core", "reka-flash",
                                 "mistral-large2", "mistral-large", "mixtral-8x7b", "mistral-7b",
                                 "llama3.2-3b", "llama3.2-1b",
                                 "llama3.1-405b", "llama3.1-70b", "llama3.1-8b",
                                 "llama3-70b", "llama3-8b", "llama2-70b-chat",
                                 "jamba-1.5-large", "jamba-1.5-mini", "jamba-instruct",
                                 "gemma-7b"])
else:
    finetuned_models = get_finetuned_models()
    if finetuned_models:
        display_names = [model['display_name'] for model in finetuned_models]
        name_mapping = {model['display_name']: model['full_name'] for model in finetuned_models}
        
        selected_display_name = st.sidebar.selectbox(
            "ファインチューニングモデルを選択してください",
            display_names
        )
        lang_model = name_mapping[selected_display_name]
    else:
        st.sidebar.error("利用可能なファインチューニングモデルが見つかりません")
        lang_model = None

st.header("自由にチャットしよう!")

# チャット履歴の初期化
if 'messages' not in st.session_state:
    st.session_state.messages = []
    st.session_state.chat_history = ""

# チャット履歴の表示
for message in st.session_state.messages:
    with st.chat_message(message["role"]):
        st.write(message["content"])

# ユーザー入力
if lang_model and (prompt := st.chat_input("文章を入力してください。")):
    # ユーザーメッセージの追加と表示
    st.session_state.messages.append({"role": "user", "content": prompt})
    st.session_state.chat_history += f"User: {prompt}\n"
    with st.chat_message("user"):
        st.write(prompt)

    # AI応答の生成
    try:
        full_prompt = st.session_state.chat_history + "AI: "
        response = CompleteText(lang_model, full_prompt)
        st.session_state.messages.append({"role": "assistant", "content": response})
        st.session_state.chat_history += f"AI: {response}\n"
        with st.chat_message("assistant"):
            st.write(response)
    except Exception as e:
        st.error(f"エラーが発生しました: {str(e)}")

# チャット履歴のクリアボタン
if st.button("チャット履歴をクリア"):
    st.session_state.messages = []
    st.session_state.chat_history = ""
    st.rerun()

チャットアプリを使ってみる

では早速試してみましょう!
Cortex LLM のベースモデルを選ぶこともできるようにしてありますので、目的に応じてベースモデルとファインチューニングモデルを切り替えてチャットすることが可能です。
今回は作成したファインチューニングモデルを使ってみます。

Streamrlit in Snowflake に関するシンプルな質問

まずは Streamlit in Snowflake に関する知識を試してみました。ちょっと怪しいところもありますが概ね Streamlit in Snowflake に調整された出力となっています。


Streamlit in Snowflake の知識チェック

Streamrlit in Snowflake のコード生成

続いて Streamlit in Snowflake のコードを生成させてみました。これはシンプルですが動きそうです!アプリと同じスキーマにあるテーブル名を入力したら、そのテーブルに関する情報が色々と表示されるようなアプリですね。


Streamlit in Snowflake のソースコードが生成できるかチェック

AWS Tokyo リージョンにファインチューニングモデルをレプリケーションして使ってみる

では最後に Cortex Fine-tuning に対応していない AWS Tokyo リージョンの Snowflake アカウントへファインチューニングモデルをレプリケーションして使ってみましょう。

Snowflake では手軽に他のアカウントへ様々なデータベースオブジェクトを複製することができます。直近のアップデートでファインチューニングモデルについても複製できるようになりましたので、それを試してみようと思います。

Snowsight の『管理者』 > 『アカウント』 > 『複製』 > 『+ グループ』ボタンを押下します。


Snowsight からレプリケーションの設定を行います

ターゲットアカウントとして同一 Org 内の AWS Tokyo リージョンの Snowflake アカウントを選択しターゲットアカウントの認証を一度行います。その後『次へ』ボタンを押下します。


レプリケーション先の Snowflake アカウントを選択する

適当なレプリケーショングループ名を付け、ファインチューニングモデルが格納されているデータベースを選択し、複製の頻度を設定した後、『グループの作成』ボタンを押下します。


ファインチューニングモデルが格納されているデータベースを設定する

レプリケーションが始まるのでレプリケーションの完了を待ちます。ステータスが『正常に更新されました』となったらレプリケーションの完了です。


レプリケーションの完了を待ちます

では AWS Tokyo リージョンの Snowflake アカウントにログインしワークシートからクエリを叩いてみましょう。冒頭で実行したクエリと同じクエリを実行してみます。


AWS Tokyo リージョンの Snowflake アカウントでファインチューニングモデルを使ってみる

やりました!ちゃんとファインチューニングモデルを使用した推論ができていますね。Part1 でも記載しましたが、ファインチューニングモデルをレプリケーション先で利用するためには、レプリケーション先の Snowflake 環境でファインチューニングのベースの LLM モデル (今回の場合は llama3.1-70b) が使えることが前提となりますのでご注意ください。

最後に

2回に渡りボリュームのある記事を読んでいただきありがとうございました!普段のチャットアプリでも、ベースモデルとファインチューニングモデルを使い分けできるようにすることで、より業務に最適化した LLM 活用ができるのではないかと思います。

また Snowflake ではクラウドやリージョンを跨ったレプリケーションを簡単かつセキュアに行うことができるため、ある1つのリージョンで作成したファインチューニングモデルを世界中に展開することが現実的な選択肢となります。

是非皆様も Snowflake におけるファインチューニングにチャレンジしてみてください。

宣伝

生成AI Conf 様の Webinar で登壇しました!

『生成AI時代を支えるプラットフォーム』というテーマの Webinar で NVIDIA 様、古巣の AWS 様と共に Snowflake 社員としてデータ*AI をテーマに LTをしました!以下が動画アーカイブとなりますので是非ご視聴いただければ幸いです!

https://www.youtube.com/live/no9WYeLFNaI?si=2r0TVWLkv1F5d4Gs

SNOWFLAKE WORLD TOUR TOKYO のオンデマンド配信中!

Snowflake の最新情報を知ることができる大規模イベント『SNOWFLAKE WORLD TOUR TOKYO』が2024/9/11-12@ANAインターコンチネンタル東京で開催されました。
現在オンデマンド配信中ですので数々の最新のデータ活用事例をご覧ください。
また私が登壇させていただいた『今から知ろう!Snowflakeの基本概要』では、Snowflakeのコアの部分を30分で押さえられますので、Snowflake をイチから知りたい方、最新の Snowflake の特徴を知りたい方は是非ご視聴いただければ嬉しいですmm

https://www.snowflake.com/events/snowflake-world-tour-tokyo/

X で Snowflake の What's new の配信してます

X で Snowflake の What's new の更新情報を配信しておりますので、是非お気軽にフォローしていただければ嬉しいです。

日本語版

Snowflake の What's New Bot (日本語版)
https://x.com/snow_new_jp

English Version

Snowflake What's New Bot (English Version)
https://x.com/snow_new_en

変更履歴

(20241222) 新規投稿

Discussion