有趣的资料:https://huggingface.co/arcee-ai
Paper:https://arxiv.org/abs/2403.13257
在人工智能领域,模型合并是一种将多个大型语言模型(LLM)整合为单一模型的技术。这种方法不仅成本低廉(无需GPU),还能生成性能卓越的模型。本文将介绍如何使用mergekit库来实现模型合并,并详细讲解四种常用的合并方法:SLERP、TIES、DARE和Passthrough。最后,我们将通过实际操作创建一个名为Marcoro14-7B-slerp的模型,并将其上传至Hugging Face Hub。
首先,我们需要安装mergekit库。可以通过以下命令从GitHub直接安装:
bash!git clone https://github.com/cg123/mergekit.git
!cd mergekit && pip install -q -e .
SLERP是一种在两个向量之间平滑插值的方法,适用于高维空间中的向量插值。它能够保持向量的几何特性,避免线性插值带来的向量长度缩减问题。
配置示例:
yamlslices:
- sources:
- model: OpenPipe/mistral-ft-optimized-1218
layer_range: [0, 32]
- model: mlabonne/NeuralHermes-2.5-Mistral-7B
layer_range: [0, 32]
merge_method: slerp
base_model: OpenPipe/mistral-ft-optimized-1218
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
TIES-Merging通过消除冗余参数和解决参数符号冲突,将多个任务特定模型合并为一个多任务模型。
配置示例:
yamlmodels:
- model: mistralai/Mistral-7B-v0.1
- model: OpenPipe/mistral-ft-optimized-1218
parameters:
density: 0.5
weight: 0.5
- model: mlabonne/NeuralHermes-2.5-Mistral-7B
parameters:
density: 0.5
weight: 0.3
merge_method: ties
base_model: mistralai/Mistral-7B-v0.1
parameters:
normalize: true
dtype: float16
DARE通过随机重置微调权重并重缩放权重,将多个模型合并为一个。
配置示例:
yamlmodels:
- model: mistralai/Mistral-7B-v0.1
- model: samir-fama/SamirGPT-v1
parameters:
density: 0.53
weight: 0.4
- model: abacusai/Slerp-CM-mist-dpo
parameters:
density: 0.53
weight: 0.3
- model: EmbeddedLLM/Mistral-7B-Merge-14-v0.2
parameters:
density: 0.53
weight: 0.3
merge_method: dare_ties
base_model: mistralai/Mistral-7B-v0.1
parameters:
int8_mask: true
dtype: bfloat16
Passthrough方法通过拼接不同模型的层,生成参数数量独特的模型。
配置示例:
yamlslices:
- sources:
- model: OpenPipe/mistral-ft-optimized-1218
layer_range: [0, 32]
- sources:
- model: mlabonne/NeuralHermes-2.5-Mistral-7B
layer_range: [24, 32]
merge_method: passthrough
dtype: bfloat16
以下是一个完整的示例,展示如何使用SLERP方法合并两个模型,并将结果上传至Hugging Face Hub。
步骤:
pythonimport yaml
MODEL_NAME = "Marcoro14-7B-slerp"
yaml_config = """
slices:
- sources:
- model: AIDC-ai-business/Marcoroni-7B-v3
layer_range: [0, 32]
- model: EmbeddedLLM/Mistral-7B-Merge-14-v0.1
layer_range: [0, 32]
merge_method: slerp
base_model: AIDC-ai-business/Marcoroni-7B-v3
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
"""
# 保存配置为YAML文件
with open('config.yaml', 'w', encoding="utf-8") as f:
f.write(yaml_config)
bash!mergekit-yaml config.yaml merge --copy-tokenizer --allow-crimes --out-shard-size 1B --lazy-unpickle
python!pip install -qU huggingface_hub
from huggingface_hub import ModelCard, ModelCardData
from jinja2 import Template
username = "mlabonne"
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 -}}
\```
"""
# 创建Jinja模板对象
jinja_template = Template(template_text.strip())
# 从配置中获取模型列表
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")
# 填充模板
content = jinja_template.render(
model_name=MODEL_NAME,
models=models,
yaml_config=yaml_config,
username=username,
)
# 保存模型说明文件
card = ModelCard(content)
card.save('merge/README.md')
# 上传至Hugging Face Hub
from google.colab import userdata
from huggingface_hub import HfApi
username = "mlabonne"
# 在Google Colab的Secrets标签中定义
api = HfApi(token=userdata.get("HF_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",
)
合并完成后,可以通过以下代码在T4 GPU上测试模型:
python!pip install -qU transformers accelerate
from transformers import AutoTokenizer
import transformers
import torch
model = "mlabonne/Marcoro14-7B-slerp"
messages = [{"role": "user", "content": "What is a large language model?"}]
tokenizer = AutoTokenizer.from_pretrained(model)
prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
pipeline = transformers.pipeline(
"text-generation",
model=model,
torch_dtype=torch.float16,
device_map="auto",
)
outputs = pipeline(prompt, max_new_tokens=256, do_sample=True, temperature=0.7, top_k=50, top_p=0.95)
print(outputs[0]["generated_text"])
通过本教程,我们学习了如何使用mergekit库合并大型语言模型,并详细介绍了SLERP、TIES、DARE和Passthrough四种方法。最后,我们创建了一个名为Marcoro14-7B-slerp的模型,并将其上传至Hugging Face Hub。希望这篇教程能帮助你更好地理解和应用模型合并技术!
本文作者:Dong
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!