Spaces:
Running
Running
File size: 4,636 Bytes
9a1014e | 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 145 146 147 148 149 150 151 152 153 154 155 156 157 | """Descarga un modelo Ollama, exporta su GGUF, lo sube a HF y lo elimina localmente."""
from __future__ import annotations
import argparse
import os
import re
import shutil
import subprocess
from pathlib import Path
from huggingface_hub import HfApi
from huggingface_hub.errors import RepositoryNotFoundError
DEFAULT_MODEL = "qwen3:4b-instruct"
DEFAULT_REPO = "AlbertiTechnology/qwen3-4b-instruct-gguf"
MAX_MODEL_BYTES = 3 * 1024**3
def find_ollama() -> str:
executable = shutil.which("ollama")
if executable:
return executable
candidates = [
Path(os.getenv("LOCALAPPDATA", "")) / "Programs" / "Ollama" / "ollama.exe",
Path(os.getenv("LOCALAPPDATA", "")) / "Ollama" / "ollama.exe",
Path(os.getenv("ProgramFiles", "")) / "Ollama" / "ollama.exe",
]
for candidate in candidates:
if candidate.is_file():
return str(candidate)
raise RuntimeError(
"Ollama no esta instalado. Instale Ollama, cierre y abra la terminal, "
"y vuelva a ejecutar este script."
)
def run_ollama(*args: str, capture: bool = False) -> str:
executable = find_ollama()
result = subprocess.run(
[executable, *args],
check=True,
text=True,
capture_output=capture,
encoding="utf-8",
errors="replace",
)
return result.stdout if capture else ""
def model_blob_from_modelfile(modelfile: str) -> Path:
match = re.search(r"^FROM\s+(.+?)\s*$", modelfile, flags=re.MULTILINE)
if not match:
raise RuntimeError("No se encontro la capa GGUF en 'ollama show --modelfile'.")
raw_path = match.group(1).strip().strip('"')
blob_path = Path(raw_path)
if not blob_path.is_file():
raise FileNotFoundError(f"Ollama informo un blob inexistente: {blob_path}")
return blob_path
def exported_modelfile(original: str) -> str:
return re.sub(
r"^FROM\s+.+?$",
"FROM ./model.gguf",
original,
count=1,
flags=re.MULTILINE,
)
def upload_model(model: str, repo_id: str, token: str) -> None:
print(f"Descargando {model} con Ollama...", flush=True)
run_ollama("pull", model)
modelfile = run_ollama("show", "--modelfile", model, capture=True)
blob_path = model_blob_from_modelfile(modelfile)
blob_size = blob_path.stat().st_size
if blob_size > MAX_MODEL_BYTES:
raise RuntimeError(
f"El GGUF ocupa {blob_size / 1024**3:.2f} GiB y supera el limite de 3 GiB."
)
readme = "\n".join(
[
"---",
"library_name: llama.cpp",
"tags:",
"- gguf",
"- ollama",
"- qwen3",
"---",
"",
f"# {model}",
"",
"Modelo GGUF exportado desde Ollama para inferencia local.",
]
)
api = HfApi(token=token)
try:
api.repo_info(repo_id=repo_id, repo_type="model")
print(f"Repositorio existente encontrado: {repo_id}", flush=True)
except RepositoryNotFoundError:
api.create_repo(repo_id=repo_id, repo_type="model")
print(
f"Subiendo directamente el blob de {blob_size / 1024**3:.2f} GiB; "
"no se creara una copia local...",
flush=True,
)
api.upload_file(
path_or_fileobj=blob_path,
path_in_repo="model.gguf",
repo_id=repo_id,
repo_type="model",
commit_message=f"Upload {model} GGUF from Ollama",
)
api.upload_file(
path_or_fileobj=exported_modelfile(modelfile).encode("utf-8"),
path_in_repo="Modelfile",
repo_id=repo_id,
repo_type="model",
)
api.upload_file(
path_or_fileobj=readme.encode("utf-8"),
path_in_repo="README.md",
repo_id=repo_id,
repo_type="model",
)
print(f"Subida completada: https://huggingface.co/{repo_id}", flush=True)
print(f"Eliminando {model} del almacenamiento local de Ollama...", flush=True)
run_ollama("rm", model)
print("Modelo local y archivos temporales eliminados.", flush=True)
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument("--model", default=DEFAULT_MODEL)
parser.add_argument("--repo", default=DEFAULT_REPO)
return parser.parse_args()
def main() -> None:
args = parse_args()
token = os.getenv("HF_TOKEN") or os.getenv("HUGGINGFACEHUB_API_TOKEN")
if not token:
raise RuntimeError("Defina HF_TOKEN con permiso de escritura antes de ejecutar.")
upload_model(args.model, args.repo, token)
if __name__ == "__main__":
main()
|