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) |