File size: 3,751 Bytes
2a924b8
 
 
ee452e7
2a924b8
ee452e7
 
 
2a924b8
ee452e7
 
2a924b8
ee452e7
 
 
 
 
 
 
 
 
 
2a924b8
ee452e7
 
2a924b8
ee452e7
 
 
 
 
 
 
 
 
 
 
2a924b8
ee452e7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2a924b8
ee452e7
 
 
 
 
2a924b8
 
ee452e7
 
 
 
 
 
 
2a924b8
ee452e7
 
2a924b8
ee452e7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2a924b8
 
 
ee452e7
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
import os
import shutil
import gradio as gr
from huggingface_hub import HfApi, snapshot_download

def fetch_files(source_repo, hf_token):
    if not hf_token.strip() or not source_repo.strip():
        yield gr.update(), gr.update(), "Error: Token and Source Repo required.", []
        return
        
    api = HfApi(token=hf_token.strip())
    try:
        yield gr.update(), gr.update(), f"Fetching files from '{source_repo}'...", []
        files = api.list_repo_files(repo_id=source_repo.strip(), repo_type="model")
        files.sort()
        
        yield (
            gr.update(visible=True), 
            gr.update(choices=files, value=files), 
            f"Success: Fetched {len(files)} files. Uncheck the ones to exclude.",
            files
        )
    except Exception as e:
        yield gr.update(visible=False), gr.update(), f"Error: {str(e)}", []


def clone_gated_model(source_repo, target_repo, hf_token, selected_files, all_files):
    if not target_repo.strip():
        yield "Error: Target repo required."
        return
        
    api = HfApi(token=hf_token.strip())
    local_dir = "./tmp_clone_dir"
    
    # Files the user unchecked will be passed to ignore_patterns
    files_to_ignore = list(set(all_files) - set(selected_files))
    
    try:
        yield f"1. Creating private target repo '{target_repo}'..."
        api.create_repo(repo_id=target_repo.strip(), repo_type="model", private=True, exist_ok=True)
        
        yield f"2. Downloading selected files from '{source_repo}' to Space disk..."
        snapshot_download(
            repo_id=source_repo.strip(),
            repo_type="model",
            local_dir=local_dir,
            token=hf_token.strip(),
            ignore_patterns=files_to_ignore if files_to_ignore else None
        )
        
        yield f"3. Uploading clean files to '{target_repo}'..."
        api.upload_folder(
            folder_path=local_dir,
            repo_id=target_repo.strip(),
            repo_type="model",
            commit_message="Initial commit: Cloned gated model"
        )
        
        yield f"Success! Model cloned. View it here: https://huggingface.co/{target_repo.strip()}"
        
    except Exception as e:
        yield f"An error occurred: {str(e)}"
        
    finally:
        if os.path.exists(local_dir):
            shutil.rmtree(local_dir, ignore_errors=True)


with gr.Blocks(title="Gated Model Cloner") as demo:
    gr.Markdown("# 📑 Clean Gated Model Cloner")
    gr.Markdown("Downloads a gated model to the Space's local disk, then uploads a clean copy to your account.")
    
    with gr.Row():
        hf_token = gr.Textbox(label="HF Token (Write)", type="password")
    
    with gr.Row():
        source_repo = gr.Textbox(label="Source Gated Repo", placeholder="e.g., meta-llama/Llama-3.2-1B")
        fetch_btn = gr.Button("1. Fetch Files", variant="secondary")
        
    all_files_state = gr.State([])
    
    with gr.Group(visible=False) as selection_group:
        file_checkboxes = gr.CheckboxGroup(label="Select files to keep")
        target_repo = gr.Textbox(label="Target Repo", placeholder="e.g., username/clean-llama")
        clone_btn = gr.Button("2. Clone Selected Files", variant="primary")
        
    output_logs = gr.Textbox(label="Status Logs", interactive=False)
    
    fetch_btn.click(
        fn=fetch_files,
        inputs=[source_repo, hf_token],
        outputs=[selection_group, file_checkboxes, output_logs, all_files_state]
    )
    
    clone_btn.click(
        fn=clone_gated_model,
        inputs=[source_repo, target_repo, hf_token, file_checkboxes, all_files_state],
        outputs=output_logs
    )

if __name__ == "__main__":
    demo.queue().launch(theme=gr.themes.Soft())