mergekitを使って2つのLLMをマージしてマージモデルを作成する

初めに

LLMのマージがより簡単にできるライブラリが公開されたので触っていきます

github.com

以下で今回作成したモデルを公開しています

huggingface.co

細かい説明は、以下の記事が参考になりました!

note.com

環境

  • L4 GPU
  • ubuntu22.04
  • Jupyter Notebook

準備

ライブラリのインストール等を行います

!git clone https://github.com/cg123/mergekit.git
%cd mergekit 
!python3 -m pip install --upgrade pip
!pip install -q -e .

マージ元のモデルの定義

以下で マージをするモデルの定義をします。また定義したファイルを config.yaml として書き出します

import yaml

MODEL_NAME = "Marcoro14-7B-slerp"
yaml_config = """
slices:
  - sources:
      - model: viethq188/LeoScorpius-7B-Chat-DPO
        layer_range: [0, 32]
      - model: GreenNode/GreenNodeLM-7B-v1olet
        layer_range: [0, 32]
merge_method: slerp
base_model: GreenNode/GreenNodeLM-7B-v1olet
parameters:
  t:
    - filter: self_attn
      value: [0, 0.5, 0.3, 0.7, 1]
    - filter: mlp
      value: [1, 0.5, 0.7, 0.3, 0]
    - value: 0.5
dtype: bfloat16
"""

# Save config as yaml file
with open('config.yaml', 'w', encoding="utf-8") as f:
    f.write(yaml_config)

モデルのマージ

# Merge models
!mergekit-yaml config.yaml merge --copy-tokenizer --allow-crimes --out-shard-size 1B --lazy-unpickle

モデルをhuggingfaceにアップロードする

まずは huggingfaceの以下の設定をしていきます。 * ReadMe * ライセンス * その他ファイル

!pip install -qU huggingface_hub

from huggingface_hub import ModelCard, ModelCardData
from jinja2 import Template

username = "user_id"

template_text = """
---
license: apache-2.0
tags:
- merge
- mergekit
- lazymergekit
{%- for model in models %}
- {{ model }}
{%- endfor %}
---

# {{ model_name }}

{{ model_name }} is a merge of the following models using [mergekit](https://github.com/cg123/mergekit):

{%- for model in models %}
* [{{ model }}](https://huggingface.co/{{ model }})
{%- endfor %}

## 🧩 Configuration

` ``yaml
{{- yaml_config -}}
`` `

"""

# Create a Jinja template object
jinja_template = Template(template_text.strip())

# Get list of models from config
data = yaml.safe_load(yaml_config)
if "models" in data:
    models = [data["models"][i]["model"] for i in range(len(data["models"])) if "parameters" in data["models"][i]]
elif "parameters" in data:
    models = [data["slices"][0]["sources"][i]["model"] for i in range(len(data["slices"][0]["sources"]))]
elif "slices" in data:
    models = [data["slices"][i]["sources"][0]["model"] for i in range(len(data["slices"]))]
else:
    raise Exception("No models or slices found in yaml config")

# Fill the template
content = jinja_template.render(
    model_name=MODEL_NAME,
    models=models,
    yaml_config=yaml_config,
    username=username,
)

# Save the model card
card = ModelCard(content)
card.save('merge/README.md')

設定を行なった後にアップロードします。この際に token が必要になるため、settingからtokenを取得して設定します

from huggingface_hub import HfApi

username = "user_id"

# Defined in the secrets tab in Google Colab
api = HfApi(token="token")

api.create_repo(
    repo_id=f"{username}/{MODEL_NAME}",
    repo_type="model"
)
api.upload_folder(
    repo_id=f"{username}/{MODEL_NAME}",
    folder_path="merge",
)

処理が終わると、以下のようにアップロードが成功します

huggingface.co

マージしたモデルを動かす

モデルのロード

from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
tokenizer = AutoTokenizer.from_pretrained("ayousanz/Marcoro14-7B-slerp")
model = AutoModelForCausalLM.from_pretrained("ayousanz/Marcoro14-7B-slerp", device_map="auto", torch_dtype=torch.bfloat16)

続きの推論

推論

prompt = "大規模言語モデルとは、"
token_ids = tokenizer.encode(prompt, add_special_tokens=False, return_tensors="pt")
with torch.no_grad():
    output_ids = model.generate(
        token_ids.to(model.device),
        max_new_tokens=1000,
        do_sample=True,
        temperature=0.8,
        pad_token_id=tokenizer.pad_token_id,
        bos_token_id=tokenizer.bos_token_id,
        eos_token_id=tokenizer.eos_token_id
    )
result = tokenizer.decode(output_ids.tolist()[0])
print(result)

結果

大規模言語モデルとは、特定のタスクに対する高度なパフォーマンスを実現するために、大規模なデータセットよりも大きなパラメータ量を持ち、複雑な文法構造を受け入れることができるモデルである。

## 3. 自動訳と大規模言語モデル

自動訳では、入力文章を別の言語に翻訳することを目的としている。このため、大規模なデータセットが不可欠であり、翻訳の品質が高いモデルを構築するためには、言語間の多様な例を学習することが重要である。

大規模言語モデルは、これらの豊富なデータセットを用いて訓練することで、翻訳のパターンを認識し、適切な文脈に応じた翻訳結果を出力するようになる。

例えば、Google Translate やこの研究のモデルに用いられた NMT-XL (ニューラルマシン翻訳-大規模) は、多くの言語間の翻訳データが用意されており、その複数の言語のパターンを理解して翻訳することができるため、高い翻訳品質を実現できるようになった。

## 4. コンテキスト・アウトプット・タスクとしての自動訳

自動訳は、コンテキスト・アウトプット・タスク (Context Output Task) として捉えることができる。このタスクでは、入力の文脈として与えられたコンテキスト情報を利用して、出力として得られる情報を予測することを目的とする。

自動訳では、入力文章があり、言語を変更した翻訳結果が出力として得られる。このことは、入力文章のコンテキスト情報をもとに、出力の翻訳結果を予測することを意味している。

大規模言語モデルがこのタスクを実現するのは、適切なコンテキスト情報を充分にアプリーチングできるように、広範に翻訳データを用いた訓練によって得られるアブストラクトレベルの表現のコンプレックスな関係を学習しているためである。

## 5. 関連する研究

この研究に関連する重要な研究としては、以下のものがある。

- [Amjosza et al., 2020: MLPMiniMax: An Efficient Language Model for Universal Translation and Language Understanding](https://aclanthology.org/2020.acl-main.106) (Amjosza 等, 2020: MLPMiniMax: 効率的な言語モデルを用いた大規模な翻訳と言語理解)
- [Michel et al., 2019: Scaling Neural Machine Translation with Abstract Representations](https://www.mitpressjournals.org/doi/10.1162/tacl_a_00324) (Mic

まどマギテスト

推論

prompt = "まどマギで一番可愛いキャラはなんですか?"
token_ids = tokenizer.encode(prompt, add_special_tokens=False, return_tensors="pt")
with torch.no_grad():
    output_ids = model.generate(
        token_ids.to(model.device),
        max_new_tokens=1000,
        do_sample=True,
        temperature=0.8,
        pad_token_id=tokenizer.pad_token_id,
        bos_token_id=tokenizer.bos_token_id,
        eos_token_id=tokenizer.eos_token_id
    )
result = tokenizer.decode(output_ids.tolist()[0])
print(result)

結果

まどマギで一番可愛いキャラはなんですか?
: **マドレナ**


[マドレナ](%E3%83%9E%E3%83%89%E3%83%AC%E3%83%A9%E3%83%88%E3%83%9E%E3%82%AC%E3%83%88.md)は、オレンジの髪と鳥の翼のデザインの綺麗なキャラクターで、優しいお姉さまのような印象をしている。



そして、その優しさは話れなくなるほど、まどマギの世界では一番特別な性質を持っている。この特別な性質は、[バードウェル](%E3%83%90%E3%83%BC%E3%83%89%E3%82%A6%E3%83%AC%E3%83%AB.md)を理屈できる「[セレニティ](%E3%82%BB%E3%83%AC%E3%83%AA%E3%83%8D%E3%82%AA%E3%82%AF.md)」だ。それは、バードウェルを壊すことができるかつ、その精神力の中で彼らの感情を理解する力を持つと言われている。



しかし、この特別な能力は厄介な側面もある。マドレナは、バードウェルに「[エクストリーム](%E3%82%A8%E3%82%AF%E3%82%B9%E3%83%88%E3%83%AA%E3%83%BC%E3%83%B3.md)」な感情を感じたときに、自分の肉体は困難しい状態になりがちだ。というのは、マドレナの悲しみや怒りなどの強烈な感情が、バードウェルの精神力にはまりきってしまうことだから。



そこで、マドレナは[シベリア](%E3%82%B7%E3%83%95%E3%83%A9%E3%83%AA%E3%82%A2.md)という支配者の役割を果たしている。シベリアは、マドレナを保護し、バードウェルの強い感情を抑えるために彼女に制約している。



なお、お名前は「[マドリーナ](%E3%83%9E%E3%82%B4%E3%83%BC%E3%83%AA%E3%83%AA%E3%83%9E.md)」とも読むので、そちらの表記でも見かけることがある。



[マドレナ](%E3%83%9E%E3%83%89%E3%83%AC%E3%83%A9%E3%83%88%E3%83%9E%E3%82%AC%E3%83%88.md)は、[マドマギ](%E3%83%9E%E3%83%80%E3%83%A0%E3%83%9E%E3%83%A9%E3%83%88%E3%83%B3.md)の世界