Hjgugugjhuhjggg commited on
Commit
75d1ef3
·
verified ·
1 Parent(s): 2469ee5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +75 -72
app.py CHANGED
@@ -27,100 +27,71 @@ The fastest way to perform a model merge 🔥
27
  Specify a YAML configuration file (see examples below) and a HF token and this app will perform the merge and upload the merged model to your user profile.
28
  """
29
 
30
- MARKDOWN_ARTICLE = """
31
- ___
32
- ## Merge Configuration
33
- [Mergekit](https://github.com/arcee-ai/mergekit) configurations are YAML documents specifying the operations to perform in order to produce your merged model.
34
- Below are the primary elements of a configuration file:
35
- - `merge_method`: Specifies the method to use for merging models. See [Merge Methods](https://github.com/arcee-ai/mergekit#merge-methods) for a list.
36
- - `slices`: Defines slices of layers from different models to be used. This field is mutually exclusive with `models`.
37
- - `models`: Defines entire models to be used for merging. This field is mutually exclusive with `slices`.
38
- - `base_model`: Specifies the base model used in some merging methods.
39
- - `parameters`: Holds various parameters such as weights and densities, which can also be specified at different levels of the configuration.
40
- - `dtype`: Specifies the data type used for the merging operation.
41
- - `tokenizer_source`: Determines how to construct a tokenizer for the merged model.
42
- ## Merge Methods
43
- A quick overview of the currently supported merge methods:
44
- | Method | `merge_method` value | Multi-Model | Uses base model |
45
- | -------------------------------------------------------------------------------------------- | -------------------- | ----------- | --------------- |
46
- | Linear ([Model Soups](https://arxiv.org/abs/2203.05482)) | `linear` | ✅ | ❌ |
47
- | SLERP | `slerp` | ❌ | ✅ |
48
- | [Task Arithmetic](https://arxiv.org/abs/2212.04089) | `task_arithmetic` | ✅ | ✅ |
49
- | [TIES](https://arxiv.org/abs/2306.01708) | `ties` | ✅ | ✅ |
50
- | [DARE](https://arxiv.org/abs/2311.03099) [TIES](https://arxiv.org/abs/2306.01708) | `dare_ties` | ✅ | ✅ |
51
- | [DARE](https://arxiv.org/abs/2311.03099) [Task Arithmetic](https://arxiv.org/abs/2212.04089) | `dare_linear` | ✅ | ✅ |
52
- | Passthrough | `passthrough` | ❌ | ❌ |
53
- | [Model Stock](https://arxiv.org/abs/2403.19522) | `model_stock` | ✅ | ✅ |
54
- ## Citation
55
- This GUI is powered by [Arcee's MergeKit](https://arxiv.org/abs/2403.13257).
56
- If you use it in your research, please cite the following paper:
57
- ```
58
- @article{goddard2024arcee,
59
- title={Arcee's MergeKit: A Toolkit for Merging Large Language Models},
60
- author={Goddard, Charles and Siriwardhana, Shamane and Ehghaghi, Malikeh and Meyers, Luke and Karpukhin, Vlad and Benedict, Brian and McQuade, Mark and Solawetz, Jacob},
61
- journal={arXiv preprint arXiv:2403.13257},
62
- year={2024}
63
- }
64
- ```
65
- This Space is heavily inspired by LazyMergeKit by Maxime Labonne (see [Colab](https://colab.research.google.com/drive/1obulZ1ROXHjYLn6PPZJwRR6GzgQogxxb)).
66
- """
67
-
68
  examples = [[str(f)] for f in pathlib.Path("examples").glob("*.yaml")]
69
  COMMUNITY_HF_TOKEN = os.getenv("COMMUNITY_HF_TOKEN")
70
 
71
- def merge(yaml_config: str, hf_token: str, repo_name: str, profile_name: str) -> Iterable[List[Log]]:
72
  runner = LogsViewRunner()
73
 
74
  if not yaml_config:
75
  yield runner.log("Empty yaml, pick an example below", level="ERROR")
76
  return
 
77
  try:
78
  merge_config = MergeConfiguration.model_validate(yaml.safe_load(yaml_config))
79
  except Exception as e:
80
  yield runner.log(f"Invalid yaml {e}", level="ERROR")
81
  return
82
 
83
- is_community_model = False
84
- if not hf_token:
85
- if "/" in repo_name and not repo_name.startswith("mergekit-community/"):
86
- yield runner.log(
87
- f"Cannot upload merge model to namespace {repo_name.split('/')[0]}: you must provide a valid token.",
88
- level="ERROR",
89
- )
90
- return
91
- yield runner.log(
92
- "No HF token provided. Your merged model will be uploaded to the https://huggingface.co/mergekit-community organization."
93
- )
94
- is_community_model = True
95
- if not COMMUNITY_HF_TOKEN:
96
- raise gr.Error("Cannot upload to community org: community token not set by Space owner.")
97
- hf_token = COMMUNITY_HF_TOKEN
98
 
99
- api = huggingface_hub.HfApi(token=hf_token)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
 
101
  with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as tmpdirname:
102
  tmpdir = pathlib.Path(tmpdirname)
103
  merged_path = tmpdir / "merged"
104
  merged_path.mkdir(parents=True, exist_ok=True)
105
  config_path = merged_path / "config.yaml"
106
- config_path.write_text(yaml_config)
107
- yield runner.log(f"Merge configuration saved in {config_path}")
108
 
109
  if not repo_name:
110
- yield runner.log("No repo name provided. Generating a random one.")
111
- repo_name = f"{profile_name}/mergekit-{merge_config.merge_method}" if profile_name else f"mergekit-{merge_config.merge_method}"
112
  repo_name += "-" + "".join(random.choices(string.ascii_lowercase, k=7))
113
  repo_name = repo_name.replace("/", "-").strip("-")
114
 
115
- if is_community_model and not repo_name.startswith("mergekit-community/"):
116
- repo_name = f"mergekit-community/{repo_name}"
117
-
118
  try:
119
- yield runner.log(f"Creating repo {repo_name}")
120
- repo_url = api.create_repo(repo_name, exist_ok=True)
121
- yield runner.log(f"Repo created: {repo_url}")
122
  except Exception as e:
123
- yield runner.log(f"Error creating repo {e}", level="ERROR")
124
  return
125
 
126
  tmp_env = os.environ.copy()
@@ -129,17 +100,49 @@ def merge(yaml_config: str, hf_token: str, repo_name: str, profile_name: str) ->
129
  yield from runner.run_command(full_cli.split(), cwd=merged_path, env=tmp_env)
130
 
131
  if runner.exit_code != 0:
132
- yield runner.log("Merge failed. Deleting repo as no model is uploaded.", level="ERROR")
133
- api.delete_repo(repo_url.repo_id)
134
  return
135
 
136
- yield runner.log("Model merged successfully. Uploading to HF.")
137
  yield from runner.run_python(
138
- api.upload_folder,
139
  repo_id=repo_url.repo_id,
140
  folder_path=merged_path / "merge",
141
  )
142
- yield runner.log(f"Model successfully uploaded to HF: {repo_url.repo_id}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
 
144
  with gr.Blocks() as demo:
145
  gr.Markdown(MARKDOWN_DESCRIPTION)
@@ -190,4 +193,4 @@ def _garbage_collect_every_hour():
190
  pool = ThreadPoolExecutor()
191
  pool.submit(_garbage_collect_every_hour)
192
 
193
- demo.queue(default_concurrency_limit=2).launch()
 
27
  Specify a YAML configuration file (see examples below) and a HF token and this app will perform the merge and upload the merged model to your user profile.
28
  """
29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  examples = [[str(f)] for f in pathlib.Path("examples").glob("*.yaml")]
31
  COMMUNITY_HF_TOKEN = os.getenv("COMMUNITY_HF_TOKEN")
32
 
33
+ def merge_multiple_methods(yaml_config: str, hf_token: str, repo_name: str, profile_name: str) -> Iterable[List[Log]]:
34
  runner = LogsViewRunner()
35
 
36
  if not yaml_config:
37
  yield runner.log("Empty yaml, pick an example below", level="ERROR")
38
  return
39
+
40
  try:
41
  merge_config = MergeConfiguration.model_validate(yaml.safe_load(yaml_config))
42
  except Exception as e:
43
  yield runner.log(f"Invalid yaml {e}", level="ERROR")
44
  return
45
 
46
+ methods_to_merge = ['dare_ties', 'slerp', 'ties']
47
+ current_yaml_config = yaml_config
48
+ merged_model_path = None
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
+ for method in methods_to_merge:
51
+ yield from run_merge_for_method(method, current_yaml_config, hf_token, repo_name, profile_name, runner)
52
+ current_yaml_config = get_merged_yaml(current_yaml_config, method)
53
+ yield runner.log(f"Model merged with {method}. Proceeding to next method...")
54
+
55
+ merged_model_path = "final_merged_model" # Placeholder, adjust based on your process
56
+
57
+ if merged_model_path:
58
+ yield runner.log(f"Model successfully merged using all methods. Saving unified model to {merged_model_path}")
59
+ # Save final YAML
60
+ example_yaml = generate_example_yaml(methods_to_merge)
61
+ yield runner.log(f"Generated example YAML: {example_yaml}")
62
+
63
+ # Here, you could potentially upload the final merged model
64
+ # Upload logic goes here if needed
65
+
66
+ def get_merged_yaml(original_yaml: str, method: str) -> str:
67
+ yaml_data = yaml.safe_load(original_yaml)
68
+ yaml_data['merge_method'] = method
69
+ return yaml.dump(yaml_data)
70
+
71
+ def run_merge_for_method(method: str, yaml_config: str, hf_token: str, repo_name: str, profile_name: str, runner: LogsViewRunner):
72
+ yaml_data = yaml.safe_load(yaml_config)
73
+ yaml_data['merge_method'] = method
74
+ new_yaml_config = yaml.dump(yaml_data)
75
 
76
  with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as tmpdirname:
77
  tmpdir = pathlib.Path(tmpdirname)
78
  merged_path = tmpdir / "merged"
79
  merged_path.mkdir(parents=True, exist_ok=True)
80
  config_path = merged_path / "config.yaml"
81
+ config_path.write_text(new_yaml_config)
82
+ yield runner.log(f"Merge configuration saved for {method} in {config_path}")
83
 
84
  if not repo_name:
85
+ repo_name = f"{profile_name}/mergekit-{method}" if profile_name else f"mergekit-{method}"
 
86
  repo_name += "-" + "".join(random.choices(string.ascii_lowercase, k=7))
87
  repo_name = repo_name.replace("/", "-").strip("-")
88
 
 
 
 
89
  try:
90
+ yield runner.log(f"Creating repo for {method} {repo_name}")
91
+ repo_url = huggingface_hub.HfApi(token=hf_token).create_repo(repo_name, exist_ok=True)
92
+ yield runner.log(f"Repo created for {method}: {repo_url}")
93
  except Exception as e:
94
+ yield runner.log(f"Error creating repo for {method}: {e}", level="ERROR")
95
  return
96
 
97
  tmp_env = os.environ.copy()
 
100
  yield from runner.run_command(full_cli.split(), cwd=merged_path, env=tmp_env)
101
 
102
  if runner.exit_code != 0:
103
+ yield runner.log(f"Merge for {method} failed. Deleting repo as no model is uploaded.", level="ERROR")
104
+ huggingface_hub.HfApi(token=hf_token).delete_repo(repo_url.repo_id)
105
  return
106
 
107
+ yield runner.log(f"Model merged with {method}. Uploading to HF.")
108
  yield from runner.run_python(
109
+ huggingface_hub.HfApi(token=hf_token).upload_folder,
110
  repo_id=repo_url.repo_id,
111
  folder_path=merged_path / "merge",
112
  )
113
+ yield runner.log(f"Model successfully uploaded to HF with {method}: {repo_url.repo_id}")
114
+
115
+ def generate_example_yaml(methods: List[str]) -> str:
116
+ """Genera un archivo YAML de ejemplo que refleja la secuencia de métodos de fusión aplicados"""
117
+ example_yaml = {
118
+ 'merge_method': 'linear', # O el método final que decidas usar
119
+ 'models': ['model1', 'model2', 'model3'], # Ejemplo de modelos a fusionar
120
+ 'slices': None, # Puedes agregar slices si es necesario
121
+ 'parameters': {
122
+ 'normalize': False,
123
+ 'weight': 0.5
124
+ },
125
+ 'tokenizer_source': 'union', # Definir el tokenizer
126
+ }
127
+ # Agregar los métodos de fusión aplicados
128
+ example_yaml['merge_method_sequence'] = methods
129
+
130
+ return yaml.dump(example_yaml)
131
+
132
+ def merge(yaml_config: str, hf_token: str, repo_name: str, profile_name: str) -> Iterable[List[Log]]:
133
+ runner = LogsViewRunner()
134
+
135
+ if not yaml_config:
136
+ yield runner.log("Empty yaml, pick an example below", level="ERROR")
137
+ return
138
+
139
+ try:
140
+ merge_config = MergeConfiguration.model_validate(yaml.safe_load(yaml_config))
141
+ except Exception as e:
142
+ yield runner.log(f"Invalid yaml {e}", level="ERROR")
143
+ return
144
+
145
+ yield from merge_multiple_methods(yaml_config, hf_token, repo_name, profile_name)
146
 
147
  with gr.Blocks() as demo:
148
  gr.Markdown(MARKDOWN_DESCRIPTION)
 
193
  pool = ThreadPoolExecutor()
194
  pool.submit(_garbage_collect_every_hour)
195
 
196
+ demo.queue(default_concurrency_limit=2).launch()