Spaces:
Sleeping
Sleeping
File size: 5,523 Bytes
ab07a82 23ccecc ab07a82 23ccecc ab07a82 23ccecc ab07a82 23ccecc ab07a82 23ccecc 608dc33 23ccecc ab07a82 23ccecc ab07a82 23ccecc ab07a82 23ccecc ab07a82 23ccecc 608dc33 23ccecc ab07a82 23ccecc 608dc33 23ccecc ab07a82 23ccecc ab07a82 23ccecc ab07a82 23ccecc ab07a82 23ccecc ab07a82 23ccecc ab07a82 608dc33 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | import gradio as gr
from huggingface_hub import HfApi, CommitOperationDelete
def fetch_files(source_repo, hf_token):
# Input validation
if not hf_token.strip():
yield gr.update(), gr.update(), "Error: Hugging Face Access Token is required.", []
return
if not source_repo.strip():
yield gr.update(), gr.update(), "Error: Source repository name is required.", []
return
api = HfApi(token=hf_token.strip())
try:
# Initial status update before fetching
yield gr.update(), gr.update(), f"Status: Fetching file list from '{source_repo}'...", []
# Fetch the flat list of files from the repository
files = api.list_repo_files(repo_id=source_repo.strip(), repo_type="model")
files.sort()
# Build a visual Linux-like tree representation for the CheckboxGroup
choices = []
for f in files:
parts = f.split('/')
if len(parts) == 1:
display = f"π {f}"
else:
folder_path = "/".join(parts[:-1])
display = f"π {folder_path}/ βββ π {parts[-1]}"
# Gradio allows (display_name, value) tuples for CheckboxGroup choices
choices.append((display, f))
yield (
gr.update(visible=True),
gr.update(choices=choices, value=files),
f"Success: Fetched {len(files)} files. Uncheck the ones you do not want to copy.",
files
)
except Exception as e:
yield gr.update(visible=False), gr.update(), f"An error occurred: {str(e)}", []
def clone_repository(source_repo, target_repo, hf_token, selected_files, all_files):
if not target_repo.strip():
yield "Error: Target repository name is required."
return
api = HfApi(token=hf_token.strip())
try:
yield f"Status: Initiating server-side clone of '{source_repo}' to '{target_repo}'..."
# 1. Duplicate the entire repo first (Server-side, almost instant, 0 disk space)
api.duplicate_repo(
from_id=source_repo.strip(),
to_id=target_repo.strip(),
repo_type="model"
)
# 2. Determine which files to delete based on what the user unchecked
files_to_delete = set(all_files) - set(selected_files)
if files_to_delete:
yield f"Status: Deleting {len(files_to_delete)} unselected files from '{target_repo}'..."
# Use 'path_in_repo' instead of 'path' to comply with the HF SDK
operations = [CommitOperationDelete(path_in_repo=f) for f in files_to_delete]
# Execute deletion in a single commit natively on HF servers
api.create_commit(
repo_id=target_repo.strip(),
repo_type="model",
operations=operations,
commit_message="Clean up: Remove unselected files during selective clone"
)
yield f"Success! Selective clone completed. View your model here: https://huggingface.co/{target_repo.strip()}"
except Exception as e:
yield f"An error occurred: {str(e)}"
# Notice: The 'theme' parameter has been removed from Blocks to satisfy Gradio 6.0 specs
with gr.Blocks(title="Selective HF Model Cloner") as demo:
gr.Markdown("# π Selective Hugging Face Model Cloner")
gr.Markdown("Fetch files from a model repository, uncheck what you don't need, and clone via high-speed server-side duplication.")
with gr.Row():
hf_token = gr.Textbox(
label="Hugging Face Access Token",
placeholder="hf_...",
type="password",
info="Requires 'Write' permissions."
)
with gr.Row():
source_repo = gr.Textbox(
label="Source Model Repository",
placeholder="e.g., meta-llama/Llama-3.2-1B"
)
fetch_btn = gr.Button("1. Fetch Files", variant="secondary")
# We use a Gradio State to quietly keep track of the complete list of files fetched
all_files_state = gr.State([])
# This group remains hidden until files are successfully fetched
with gr.Group(visible=False) as selection_group:
gr.Markdown("### ποΈ Repository Files")
gr.Markdown("*All files are selected by default. Uncheck any files you do **not** want to carry over.*")
file_checkboxes = gr.CheckboxGroup(label="Repository Tree", interactive=True)
target_repo = gr.Textbox(
label="Target Model Repository",
placeholder="e.g., your-username/my-custom-llama"
)
clone_btn = gr.Button("2. Clone Selected Files", variant="primary")
output_logs = gr.Textbox(label="Execution Status / Logs", interactive=False)
# Trigger Step 1: File Fetching
fetch_btn.click(
fn=fetch_files,
inputs=[source_repo, hf_token],
outputs=[selection_group, file_checkboxes, output_logs, all_files_state]
)
# Trigger Step 2: Cloning Process
clone_btn.click(
fn=clone_repository,
inputs=[source_repo, target_repo, hf_token, file_checkboxes, all_files_state],
outputs=output_logs
)
if __name__ == "__main__":
# The theme parameter is now passed into launch() per Gradio 6.0 rules
demo.queue().launch(theme=gr.themes.Soft()) |