rootlocalghost commited on
Commit
23ccecc
Β·
verified Β·
1 Parent(s): 57390c8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +93 -39
app.py CHANGED
@@ -1,65 +1,100 @@
1
- import os
2
- import shutil
3
  import gradio as gr
4
- from huggingface_hub import HfApi, snapshot_download
5
 
6
- def clone_repository(source_repo, target_repo, hf_token):
 
7
  if not hf_token.strip():
8
- return "Error: Hugging Face Access Token is required."
9
- if not source_repo.strip() or not target_repo.strip():
10
- return "Error: Both source and target repository names are required."
 
 
11
 
12
  api = HfApi(token=hf_token.strip())
13
- local_dir = "temp_clone_dir"
14
 
15
  try:
16
- # 1. Create the target repository on your account
17
- yield f"Status: Creating target repository '{target_repo}'..."
18
- api.create_repo(repo_id=target_repo.strip(), repo_type="model", exist_ok=True)
19
 
20
- # 2. Clean up any leftover temporary directories from previous runs
21
- if os.path.exists(local_dir):
22
- shutil.rmtree(local_dir)
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
- # 3. Download the source repository files
25
- yield f"Status: Downloading files from '{source_repo}' (this may take some time depending on the model size)..."
26
- downloaded_dir = snapshot_download(
27
- repo_id=source_repo.strip(),
28
- local_dir=local_dir,
29
- token=hf_token.strip(),
30
- max_workers=4
31
  )
32
 
33
- # 4. Upload the files to your target repository
34
- yield f"Status: Uploading files to '{target_repo}'..."
35
- api.upload_folder(
36
- folder_path=downloaded_dir,
37
- repo_id=target_repo.strip(),
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  repo_type="model"
39
  )
40
 
41
- # 5. Clean up local storage
42
- shutil.rmtree(local_dir)
43
 
44
- yield f"Success! Model successfully cloned to: https://huggingface.co/{target_repo.strip()}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
  except Exception as e:
47
- # Ensure cleanup happens even if an error occurs
48
- if os.path.exists(local_dir):
49
- shutil.rmtree(local_dir)
50
  yield f"An error occurred: {str(e)}"
51
 
 
52
  # Build the Gradio Interface using the .Soft theme
53
- with gr.Blocks(theme=gr.themes.Soft(), title="HF Model Cloner") as demo:
54
- gr.Markdown("# πŸ“‘ Hugging Face Model Cloner")
55
- gr.Markdown("Clone any public or accessible model repository to your own Hugging Face account under a custom name.")
56
 
57
  with gr.Row():
58
  hf_token = gr.Textbox(
59
  label="Hugging Face Access Token",
60
  placeholder="hf_...",
61
  type="password",
62
- info="Requires 'Write' permissions to create and upload to your repository."
63
  )
64
 
65
  with gr.Row():
@@ -67,18 +102,37 @@ with gr.Blocks(theme=gr.themes.Soft(), title="HF Model Cloner") as demo:
67
  label="Source Model Repository",
68
  placeholder="e.g., meta-llama/Llama-3.2-1B"
69
  )
 
 
 
 
 
 
 
 
 
 
 
 
70
  target_repo = gr.Textbox(
71
  label="Target Model Repository",
72
  placeholder="e.g., your-username/my-custom-llama"
73
  )
 
74
 
75
- clone_btn = gr.Button("Start Cloning Process", variant="primary")
76
  output_logs = gr.Textbox(label="Execution Status / Logs", interactive=False)
77
 
78
- # Use streaming output (yield) to show live progress updates
 
 
 
 
 
 
 
79
  clone_btn.click(
80
  fn=clone_repository,
81
- inputs=[source_repo, target_repo, hf_token],
82
  outputs=output_logs
83
  )
84
 
 
 
 
1
  import gradio as gr
2
+ from huggingface_hub import HfApi, CommitOperationDelete
3
 
4
+ def fetch_files(source_repo, hf_token):
5
+ # Input validation
6
  if not hf_token.strip():
7
+ yield gr.update(), gr.update(), "Error: Hugging Face Access Token is required.", []
8
+ return
9
+ if not source_repo.strip():
10
+ yield gr.update(), gr.update(), "Error: Source repository name is required.", []
11
+ return
12
 
13
  api = HfApi(token=hf_token.strip())
 
14
 
15
  try:
16
+ # Initial status update before fetching
17
+ yield gr.update(), gr.update(), f"Status: Fetching file list from '{source_repo}'...", []
 
18
 
19
+ # Fetch the flat list of files from the repository
20
+ files = api.list_repo_files(repo_id=source_repo.strip(), repo_type="model")
21
+ files.sort()
22
+
23
+ # Build a visual Linux-like tree representation for the CheckboxGroup
24
+ choices = []
25
+ for f in files:
26
+ parts = f.split('/')
27
+ if len(parts) == 1:
28
+ display = f"πŸ“„ {f}"
29
+ else:
30
+ folder_path = "/".join(parts[:-1])
31
+ display = f"πŸ“ {folder_path}/ β”œβ”€β”€ πŸ“„ {parts[-1]}"
32
+
33
+ # Gradio 4.0+ allows (display_name, value) tuples for CheckboxGroup choices
34
+ choices.append((display, f))
35
 
36
+ yield (
37
+ gr.update(visible=True),
38
+ gr.update(choices=choices, value=files),
39
+ f"Success: Fetched {len(files)} files. Uncheck the ones you do not want to copy.",
40
+ files
 
 
41
  )
42
 
43
+ except Exception as e:
44
+ yield gr.update(visible=False), gr.update(), f"An error occurred: {str(e)}", []
45
+
46
+
47
+ def clone_repository(source_repo, target_repo, hf_token, selected_files, all_files):
48
+ if not target_repo.strip():
49
+ yield "Error: Target repository name is required."
50
+ return
51
+
52
+ api = HfApi(token=hf_token.strip())
53
+
54
+ try:
55
+ yield f"Status: Initiating server-side clone of '{source_repo}' to '{target_repo}'..."
56
+
57
+ # 1. Duplicate the entire repo first (Server-side, almost instant, 0 disk space)
58
+ api.duplicate_repo(
59
+ from_id=source_repo.strip(),
60
+ to_id=target_repo.strip(),
61
  repo_type="model"
62
  )
63
 
64
+ # 2. Determine which files to delete based on what the user unchecked
65
+ files_to_delete = set(all_files) - set(selected_files)
66
 
67
+ if files_to_delete:
68
+ yield f"Status: Deleting {len(files_to_delete)} unselected files from '{target_repo}'..."
69
+
70
+ # Create a list of deletion operations
71
+ operations = [CommitOperationDelete(path=f) for f in files_to_delete]
72
+
73
+ # Execute deletion in a single commit natively on HF servers
74
+ api.create_commit(
75
+ repo_id=target_repo.strip(),
76
+ repo_type="model",
77
+ operations=operations,
78
+ commit_message="Clean up: Remove unselected files during selective clone"
79
+ )
80
+
81
+ yield f"Success! Selective clone completed. View your model here: https://huggingface.co/{target_repo.strip()}"
82
 
83
  except Exception as e:
 
 
 
84
  yield f"An error occurred: {str(e)}"
85
 
86
+
87
  # Build the Gradio Interface using the .Soft theme
88
+ with gr.Blocks(theme=gr.themes.Soft(), title="Selective HF Model Cloner") as demo:
89
+ gr.Markdown("# πŸ“‘ Selective Hugging Face Model Cloner")
90
+ gr.Markdown("Fetch files from a model repository, uncheck what you don't need, and clone via high-speed server-side duplication.")
91
 
92
  with gr.Row():
93
  hf_token = gr.Textbox(
94
  label="Hugging Face Access Token",
95
  placeholder="hf_...",
96
  type="password",
97
+ info="Requires 'Write' permissions."
98
  )
99
 
100
  with gr.Row():
 
102
  label="Source Model Repository",
103
  placeholder="e.g., meta-llama/Llama-3.2-1B"
104
  )
105
+ fetch_btn = gr.Button("1. Fetch Files", variant="secondary")
106
+
107
+ # We use a Gradio State to quietly keep track of the complete list of files fetched
108
+ all_files_state = gr.State([])
109
+
110
+ # This group remains hidden until files are successfully fetched
111
+ with gr.Group(visible=False) as selection_group:
112
+ gr.Markdown("### πŸ—‚οΈ Repository Files")
113
+ gr.Markdown("*All files are selected by default. Uncheck any files you do **not** want to carry over.*")
114
+
115
+ file_checkboxes = gr.CheckboxGroup(label="Repository Tree", interactive=True)
116
+
117
  target_repo = gr.Textbox(
118
  label="Target Model Repository",
119
  placeholder="e.g., your-username/my-custom-llama"
120
  )
121
+ clone_btn = gr.Button("2. Clone Selected Files", variant="primary")
122
 
 
123
  output_logs = gr.Textbox(label="Execution Status / Logs", interactive=False)
124
 
125
+ # Trigger Step 1: File Fetching
126
+ fetch_btn.click(
127
+ fn=fetch_files,
128
+ inputs=[source_repo, hf_token],
129
+ outputs=[selection_group, file_checkboxes, output_logs, all_files_state]
130
+ )
131
+
132
+ # Trigger Step 2: Cloning Process
133
  clone_btn.click(
134
  fn=clone_repository,
135
+ inputs=[source_repo, target_repo, hf_token, file_checkboxes, all_files_state],
136
  outputs=output_logs
137
  )
138