File size: 4,840 Bytes
68671d2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
142
143
144
import os
from typing import Optional

import gradio as gr
from huggingface_hub import HfApi

from convert import convert


DATASET_REPO_URL = "https://huggingface.co/datasets/safetensors/conversions"
HF_TOKEN = os.environ.get("HF_TOKEN")  # Bot token (recommended for opening PRs)


def _format_error(msg: str) -> str:
    return f"""
### Error 😢

{msg}
"""


def _format_invalid(msg: str) -> str:
    return f"""
### Invalid input 🐞

{msg}
"""


def run(model_id: str, is_private: bool, token: Optional[str] = None) -> str:
    model_id = (model_id or "").strip()
    token = (token or "").strip() if token else None

    if not model_id:
        return _format_invalid("Please provide a valid `model_id`.")

    # Token policy:
    # - Public model: use bot token if available; otherwise unauthenticated may fail for PR creation.
    # - Private model: must use user-provided token to read; PR should still be created with bot if allowed.
    if is_private and not token:
        return _format_invalid("Private model checked: please provide a read-access HF token.")

    # Default API client:
    # - If private: use user's token to read model info (must have access).
    # - Else: use bot token if available, else try unauthenticated.
    api = HfApi(token=token if is_private else (HF_TOKEN if HF_TOKEN else None))

    try:
        info = api.model_info(repo_id=model_id)
        hf_is_private = bool(getattr(info, "private", False))

        # If user checked "private" but the model is actually public, switch to bot token for PR creation.
        # This mirrors your original intent: PR should be created "on behalf of bot" when possible.
        if is_private and not hf_is_private:
            api = HfApi(token=HF_TOKEN if HF_TOKEN else None)

        # If model is public but we don't have a token, conversion may run but PR creation can fail.
        if (not is_private) and (HF_TOKEN is None):
            # Still attempt, but give a clear warning if it fails.
            pass

        commit_info, errors = convert(api=api, model_id=model_id)

        pr_url = getattr(commit_info, "pr_url", None)
        if not pr_url:
            # Some implementations might return commit URL instead of PR url.
            pr_url = getattr(commit_info, "url", None)

        out = """
### Success 🔥

Yay! This model was successfully converted.
"""
        if pr_url:
            out += f"\nPR/Discussion URL:\n\n[{pr_url}]({pr_url})\n"
        else:
            out += "\n(Conversion succeeded, but no PR URL was returned by `convert()`.)\n"

        if errors:
            out += "\n\n### Conversion warnings\n"
            out += "\n".join(
                f"- `{filename}`: {e} (skipped)"
                for filename, e in errors
            )

        # Helpful note if bot token is missing
        if (not is_private) and (HF_TOKEN is None):
            out += "\n\n⚠️ Note: `HF_TOKEN` is not set. If PR creation fails, set `HF_TOKEN` in the environment."

        return out

    except Exception as e:
        return _format_error(str(e))


DESCRIPTION = """
The steps are the following:

- (Optional) Set `HF_TOKEN` as an environment variable for your bot/account token to open PRs reliably.
- If the model is private, paste a read-access token from hf.co/settings/tokens.
- Input a model id from the Hub (e.g. `org/model_name`)
- Click "Submit"
- You'll get the URL of the opened PR (or discussion) if successful.

⚠️ For now only `pytorch_model.bin` files are supported but we’ll extend in the future.
"""

title = "Convert any model to Safetensors and open a PR"


def toggle_token_visibility(is_private: bool):
    # Update component configuration (visibility) the Gradio-recommended way.
    return gr.Textbox(visible=is_private)


with gr.Blocks(title=title) as demo:
    gr.Markdown(f"# {title}")
    gr.Markdown(DESCRIPTION)

    with gr.Row():
        with gr.Column():
            model_id = gr.Textbox(label="model_id", placeholder="e.g. bigscience/bloom", max_lines=1)
            is_private = gr.Checkbox(label="Private model", value=False)

            token = gr.Textbox(
                label="your_hf_token",
                placeholder="hf_...",
                max_lines=1,
                type="password",
                visible=False,
            )

            with gr.Row():
                submit = gr.Button("Submit", variant="primary")
                # ClearButton should be instantiated with components to clear
                clean = gr.ClearButton([model_id, is_private, token])

        with gr.Column():
            output = gr.Markdown()

    is_private.change(fn=toggle_token_visibility, inputs=is_private, outputs=token)
    submit.click(fn=run, inputs=[model_id, is_private, token], outputs=output, concurrency_limit=1)

demo.queue(max_size=10).launch(show_api=True)