LoginSignup
0
0

N番煎じでXwin-LM-13B-V0.1をDatabricksで動かす

Last updated at Posted at 2023-09-22

N番煎じシリーズです。

下記リンク先で紹介されているXwin-LMをDatabricks上で試してみます。

今回は最初からCTranslate2で変換したモデルを使って推論します。
Transformersそのままでも動くとは思います。

Xwin-LMとは

Xwin-LMは、教師あり微調整(SFT)、報酬モデル(RM)、リジェクトサンプリング、人間のフィードバックからの強化学習(RLHF)など、大規模言語モデルのためのアライメント技術を開発し、オープンソース化することを目指しています。私たちの最初のリリースは、Llama2ベースモデルに基づいて構築され、AlpacaEvalでトップ1にランクされました。特筆すべきは、このベンチマークで初めてGPT-4を上回ったことです。プロジェクトは継続的に更新される予定です。

ということで、AlpacaEvalで70BモデルがGPT-4を超えたようです。
13BモデルでさえClaude 2を超えてるので期待が持てます。

検証環境

Databricks on AWSを使って検証しています。
DBRは13.3ML、CT2のモデル変換はi3.2xlarge、推論時はg5.2xlargeのクラスタを利用しました。
Xwin-LMは7B、13B、70Bと公開されていますが、今回は8bitに量子化した13Bモデルを使います。

モデルの取得と保管

こちらとほぼ同じです。
最終的にUnity CatalogのVolumesに保管します。

%pip install -U -qq transformers accelerate ctranslate2 langchain

dbutils.library.restartPython()
import os
from huggingface_hub import snapshot_download

UC_VOLUME = "/Volumes/モデルの保管場所"

model = "Xwin-LM/Xwin-LM-13B-V0.1"
local_dir = "/tmp/Xwin-LM/Xwin-LM-13B-V0.1"
uc_dir = "/models--Xwin-LM--Xwin-LM-13B-V0.1"

snapshot_location = snapshot_download(
    repo_id=model,
    local_dir=local_dir,
    local_dir_use_symlinks=False,
)

dbutils.fs.cp(f"file:{local_dir}", f"{UC_VOLUME}{uc_dir}", recurse=True)

CTranslate2モデルに変換

これも以前の記事同様です。

UC_VOLUME = "/Volumes/スナップショットの保管場所"
uc_dir = "/models--Xwin-LM--Xwin-LM-13B-V0.1"

src_path = f"{UC_VOLUME}{uc_dir}"
local_output_dir = "/tmp/ctranslate2/models--Xwin-LM--Xwin-LM-13B-V0.1"

UC_CT2_VOLUME = "/Volumes/CT2モデル保管場所"
uc_ct2_dir = "/Xwin-LM/Xwin-LM-13B-V0.1"
!ct2-transformers-converter --model {src_path} --copy_files tokenizer.model tokenizer_config.json special_tokens_map.json --output_dir {local_output_dir} --quantization int8_bfloat16 --force --low_cpu_mem_usage
dbutils.fs.cp("file:"+local_output_dir, f"{UC_CT2_VOLUME}{uc_ct2_dir}", recurse=True)

推論準備

こちらと同じプロンプト+αを実行してみます。
また、推論にあたって、こちらで作成したlangchainのChat Modelを使ってみました。

import ctranslate2
import transformers
import torch

from langchain.schema import (
    AIMessage,
    HumanMessage,
    SystemMessage
)

from ct2chat import ChatCTranslate2

model_path = "/Volumes/CT2モデル保管場所/Xwin-LM/Xwin-LM-13B-V0.1"

# ジェネレーターとトークナイザーの準備
device = "cuda" if torch.cuda.is_available() else "cpu"
generator = ctranslate2.Generator(model_path, device=device)
tokenizer = transformers.AutoTokenizer.from_pretrained(model_path)

llm = ChatCTranslate2(
    generator=generator,
    tokenizer=tokenizer,
    max_length=1024,
    human_message_template="USER: {}",
    ai_message_template="ASSISTANT: {}",
    prompt_line_separator="",
)

推論例

output = llm(
    [
        HumanMessage(content="架空の生き物をデザインし、その特徴や能力について説明してください。"),
        AIMessage(content=""),
    ]
)
print(output.content)
結果
生物名:アストラル・フェニックス

アストラル・フェニックスは、架空の火鳥であり、異世界「エリュシオン」に生息しています。この生物は、炎と風の力を持ち、高い知能と優れた戦闘能力を有しています。

特徴:

1. 炎と風の力: アストラル・フェニックスは、炎と風の力を操ることができます。炎の力を用いて攻撃や移動を行い、風の力を使って自在に飛行することができます。
2. 高い知能: この生物は、人間以上の知能を持っており、言語を理解し、会話も可能です。彼らは複雑な思考や感情を持ち、社会的な関係を形成することができます。
3. 優れた戦闘能力: アストラル・フェニックスは、戦闘でも非常に強力です。炎の攻撃や風の技を駆使し、敵を圧倒することができます。さらに、彼らは素早く、敏捷であり、運動能力も高いため、地形や状況に悩まず戦えます。
4. 長寿: アストラル・フェニックスは、非常に長命です。彼らは数百年以上生存することができ、その期間中に多くの知識と経験を積むことができます。
5. 独立性: この生物は、他の生物から独立して生活できるように設定されています。彼らは自分たちの食料を確保し、生活の場を作ることができます。

アストラル・フェニックスは、異世界「エリュシオン」の独自の生態系に属し、その特徴と能力によって、物語の世界観を彩る貴重な存在となっています。

なかなかに中二くさい。

output = llm(
    [
        HumanMessage(content="ランダムな10個の要素からなるリストを作成してソートするコードをPythonで書いてください。"),
        AIMessage(content=""),
    ]
)
print(output.content)
結果
以下に、ランダムな10個の要素からなるリストを作成してソートするPythonコードを示します。
```python
import random
from typing import List, Tuple

def create_random_list(length: int) -> List[int]:
    return [random.randint(0, 99) for _ in range(length)]

def sort_random_list(list_: List[int]) -> None:
    list_.sort()

# テスト用のコード
if __name__ == "__main__":
    length = 10
    random_list = create_random_list(length)
    sort_random_list(random_list)

    print("Unsorted random list:", random_list)
    print("Sorted random list:", sorted(random_list))
`` `
このコードは、`create_random_list`関数を使ってランダムな長さが指定されたリストを作成し、`sort_random_list`関数を使ってそのリストをソートします。最後に、`sorted()`関数を使ってソートされたリストを表示します。

ちゃんと動くコードが生成されました。

output = llm(
    [
        HumanMessage(
            content="日本国内で観光に行きたいと思っています。東京、名古屋、大阪、京都、福岡の特徴を表にまとめてください。列名は「都道府県」「おすすめスポット」「おすすめグルメ」にしてください。"
        ),
        AIMessage(content=""),
    ]
)
print(output.content)
結果
日本国内で観光に行きたいと思っている方に、東京、名古屋、大阪、京都、福岡の特徴を表にまとめました。列名は「都道府県」「おすすめスポット」「おすすめグルメ」になっています。

| 都道府県 | おすすめスポット | おすすめグルメ |
| --- | --- | --- |
| 東京 | 浅草・雷門 | うなぎ焼き、そば |
| 名古屋 | 名駅地区 | 焼き鳥、うどん |
| 大阪 | 梅田・心斎橋 | たこ焼き、 okonomiyaki |
| 京都 | 烏丸・四条 | 喫茶店、煎餅 |
| 福岡 | 天神地区 | ラーメン、焼きそば |

この表は、各都市の代表的な観光名所や食べ物を簡潔にまとめたものです。各都市の詳細情報や最新情報については、観光局や公式ウェブサイトを参照してください。

お好み焼きは世界ではokonomiyakiなんでしょうか。。。
指示通りではありますが、回答内容はちょっと微妙ですね。

おまけで、コンテキストを与えてJSONで回答を抽出してみます。
コンテキストは適当に作りました。

context="""時は西暦20XX年、世界は犬好きと猫好きで戦が勃発した。
犬軍の対象は犬頭三吉、猫軍の対象は白パンダである。
両軍の対決は15年におよび、結果は引き分けに終わった。この戦は令和合戦と呼ばれている。"""

output = llm(
    [
        SystemMessage(content=f"あなたは優秀な歴史家です。質問に対して、次のコンテキストを使って回答してください。#コンテキスト:{context}"),
        HumanMessage(content="猫軍の対象は誰ですか?json形式で出力してください。"),
        AIMessage(content='答えは{"name":"犬頭三吉"}'),                
        HumanMessage(content="猫軍の対象は誰ですか?json形式で出力してください。"),
        AIMessage(content="答えは"),
    ]
)
print(output.content)
結果
{"name":"白パンダ"}

工夫が要りそうですが、なんとか望むフォーマットで取れますね。

まとめ

GPT-4以上かはわかりませんが、割とクセもなく日本語も出力してくれます。
コンテキスト長が4kなので、In context learning/RAGを使う場合などは注意が必要ですね。
継続的にアップデートされるようなので、YaRNによる128k長モデルとか出してほしい。。。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0