Spaces:
Runtime error
Runtime error
File size: 11,425 Bytes
08e5ef1 d6c19ae 2bede7c 4c4c78d 7edda8b b0086f3 d6c19ae 08e5ef1 2bede7c b0086f3 7686e09 4c4c78d b0086f3 6d814c5 b0086f3 4c4c78d b0086f3 45817bf b0086f3 4c4c78d 36f5cda 4c4c78d 36f5cda 4c4c78d b0086f3 4c4c78d a421ab7 36f5cda b0086f3 184ed3a 3ad22ce 7c74789 b0086f3 3ad22ce b0086f3 7c74789 3ad22ce b0086f3 3ad22ce b0086f3 3ad22ce b0086f3 36f5cda b0086f3 5696fee b0086f3 9781999 b0086f3 7041384 b0086f3 5532bbf 7c74789 b0086f3 7c74789 b0086f3 9781999 4c4c78d d6c19ae 36f5cda b0086f3 4c4c78d b0086f3 d6c19ae b0086f3 3ad22ce b0086f3 9781999 b0086f3 9781999 b0086f3 5696fee b0086f3 5532bbf b0086f3 5532bbf b0086f3 5532bbf b0086f3 36f5cda b0086f3 5532bbf d6c19ae 5532bbf b0086f3 36f5cda d6c19ae 5532bbf b0086f3 5532bbf 36f5cda b0086f3 3218113 d6c19ae 36f5cda b0086f3 9f74a4f 5532bbf 0d63e3d b0086f3 0d63e3d b0086f3 0d63e3d b0086f3 9f74a4f 0d63e3d 9f74a4f b0086f3 0d63e3d b0086f3 0d63e3d d6c19ae 0d63e3d 9f74a4f 0d63e3d b0086f3 7d7a8cb b0086f3 7d7a8cb b0086f3 5110965 b0086f3 |
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 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
import os
import shutil
import subprocess
import signal
import gradio as gr
from huggingface_hub import create_repo, HfApi, snapshot_download, whoami, ModelCard
from gradio_huggingfacehub_search import HuggingfaceHubSearch
from textwrap import dedent
# Obtener el token de Hugging Face desde el entorno
HF_TOKEN = os.getenv("HF_TOKEN", "")
def ensure_valid_token(oauth_token):
"""Verifica si el token es válido."""
if not oauth_token or not oauth_token.strip():
raise ValueError("Debe proporcionar un token válido.")
return oauth_token.strip()
def generate_importance_matrix(model_path, train_data_path):
"""Genera la matriz de importancia usando llama-imatrix."""
imatrix_command = f"./llama-imatrix -m ../{model_path} -f {train_data_path} -ngl 99 --output-frequency 10"
os.chdir("llama.cpp")
if not os.path.isfile(f"../{model_path}"):
raise FileNotFoundError(f"Archivo del modelo no encontrado: {model_path}")
process = subprocess.Popen(imatrix_command, shell=True)
try:
process.wait(timeout=60)
except subprocess.TimeoutExpired:
process.send_signal(signal.SIGINT)
try:
process.wait(timeout=5)
except subprocess.TimeoutExpired:
process.kill()
os.chdir("..")
def split_upload_model(model_path, repo_id, oauth_token, split_max_tensors=256, split_max_size=None):
"""Divide y sube el modelo en partes."""
if not oauth_token or not oauth_token.strip():
raise ValueError("Debe proporcionar un token válido.")
split_cmd = f"llama.cpp/llama-gguf-split --split --split-max-tensors {split_max_tensors}"
if split_max_size:
split_cmd += f" --split-max-size {split_max_size}"
split_cmd += f" {model_path} {model_path.split('.')[0]}"
result = subprocess.run(split_cmd, shell=True, capture_output=True, text=True)
if result.returncode != 0:
raise RuntimeError(f"Error al dividir el modelo: {result.stderr}")
sharded_model_files = [f for f in os.listdir('.') if f.startswith(model_path.split('.')[0])]
if sharded_model_files:
api = HfApi(token=oauth_token)
for file in sharded_model_files:
file_path = os.path.join('.', file)
try:
api.upload_file(
path_or_fileobj=file_path,
path_in_repo=file,
repo_id=repo_id,
)
except Exception as e:
raise RuntimeError(f"Error al subir el archivo {file_path}: {e}")
else:
raise FileNotFoundError("No se encontraron archivos divididos.")
def process_model(model_id, q_method, use_imatrix, imatrix_q_method, private_repo, train_data_file, split_model, split_max_tensors, split_max_size, oauth_token):
"""Procesa el modelo descargado y realiza la conversión y subida."""
token = ensure_valid_token(oauth_token)
model_name = model_id.split('/')[-1]
fp16 = f"{model_name}.fp16.gguf"
try:
api = HfApi(token=token)
dl_pattern = [
"*.safetensors", "*.bin", "*.pt", "*.onnx", "*.h5", "*.tflite",
"*.ckpt", "*.pb", "*.tar", "*.xml", "*.caffemodel",
"*.md", "*.json", "*.model"
]
pattern = (
"*.safetensors"
if any(
file.path.endswith(".safetensors")
for file in api.list_repo_tree(
repo_id=model_id,
recursive=True,
)
)
else "*.bin"
)
dl_pattern += pattern
snapshot_download(repo_id=model_id, local_dir=model_name, local_dir_use_symlinks=False, allow_patterns=dl_pattern)
print("Modelo descargado exitosamente!")
conversion_script = "convert_hf_to_gguf.py"
fp16_conversion = f"python llama.cpp/{conversion_script} {model_name} --outtype f16 --outfile {fp16}"
result = subprocess.run(fp16_conversion, shell=True, capture_output=True)
if result.returncode != 0:
raise RuntimeError(f"Error al convertir a fp16: {result.stderr}")
imatrix_path = "llama.cpp/imatrix.dat"
if use_imatrix:
if train_data_file:
train_data_path = train_data_file.name
else:
train_data_path = "groups_merged.txt"
if not os.path.isfile(train_data_path):
raise FileNotFoundError(f"Archivo de datos de entrenamiento no encontrado: {train_data_path}")
generate_importance_matrix(fp16, train_data_path)
quantized_gguf_name = f"{model_name.lower()}-{imatrix_q_method.lower()}-imat.gguf" if use_imatrix else f"{model_name.lower()}-{q_method.lower()}.gguf"
quantized_gguf_path = quantized_gguf_name
quantise_ggml = f"./llama.cpp/llama-quantize {'--imatrix ' + imatrix_path if use_imatrix else ''} {fp16} {quantized_gguf_path} {imatrix_q_method if use_imatrix else q_method}"
result = subprocess.run(quantise_ggml, shell=True, capture_output=True)
if result.returncode != 0:
raise RuntimeError(f"Error al cuantificar: {result.stderr}")
username = whoami(token)["name"]
new_repo_url = api.create_repo(repo_id=f"{username}/{model_name}-{imatrix_q_method if use_imatrix else q_method}-GGUF", exist_ok=True, private=private_repo)
new_repo_id = new_repo_url.repo_id
try:
card = ModelCard.load(model_id, token=token)
except:
card = ModelCard("")
if card.data.tags is None:
card.data.tags = []
card.data.tags.append("llama-cpp")
card.data.tags.append("gguf-my-repo")
card.data.base_model = model_id
card.text = dedent(
f"""
# {new_repo_id}
Este modelo fue convertido al formato GGUF desde [`{model_id}`](https://huggingface.co/{model_id}) usando llama.cpp a través del espacio GGUF-my-repo.
Consulta el [card del modelo original](https://huggingface.co/{model_id}) para más detalles.
## Uso con llama.cpp
Instala llama.cpp a través de brew (funciona en Mac y Linux)
```bash
brew install llama.cpp
```
Invoca el servidor llama.cpp o la CLI.
### CLI:
```bash
llama-cli --hf-repo {new_repo_id} --hf-file {quantized_gguf_name} -p "El sentido de la vida y el universo es"
```
### Servidor:
```bash
llama-server --hf-repo {new_repo_id} --hf-file {quantized_gguf_name} -c 2048
```
Nota: También puedes usar este punto de control directamente a través de los [pasos de uso](https://github.com/ggerganov/llama.cpp?tab=readme-ov-file#usage) listados en el repositorio llama.cpp.
"""
)
card.save(f"README.md")
if split_model:
split_upload_model(quantized_gguf_path, new_repo_id, token, split_max_tensors, split_max_size)
else:
try:
api.upload_file(
path_or_fileobj=quantized_gguf_path,
path_in_repo=quantized_gguf_name,
repo_id=new_repo_id,
)
except Exception as e:
raise RuntimeError(f"Error al subir el modelo cuantificado: {e}")
if os.path.isfile(imatrix_path):
try:
api.upload_file(
path_or_fileobj=imatrix_path,
path_in_repo="imatrix.dat",
repo_id=new_repo_id,
)
except Exception as e:
raise RuntimeError(f"Error al subir imatrix.dat: {e}")
api.upload_file(
path_or_fileobj=f"README.md",
path_in_repo=f"README.md",
repo_id=new_repo_id,
)
return (
f'Encuentra tu repositorio <a href=\'{new_repo_url}\' target="_blank" style="text-decoration:underline">aquí</a>',
"llama.png",
)
except Exception as e:
return (f"Error: {e}", "error.png")
finally:
shutil.rmtree(model_name, ignore_errors=True)
with gr.Blocks() as app:
gr.Markdown("# Procesamiento de Modelos")
gr.Markdown(
"""
Este panel permite procesar modelos de machine learning, convertirlos al formato GGUF, y cargarlos en un repositorio de Hugging Face.
Puedes seleccionar diferentes métodos de cuantización y personalizar la conversión usando matrices de importancia.
"""
)
with gr.Row():
model_id = gr.Textbox(
label="ID del Modelo",
placeholder="username/model-name",
info="Introduce el ID del modelo en Hugging Face que deseas procesar.",
)
q_method = gr.Dropdown(
["IQ3_M", "IQ3_XXS", "Q4_K_M", "Q4_K_S", "IQ4_NL", "IQ4_XS", "Q5_K_M", "Q5_K_S"],
label="Método de Cuantización",
info="Selecciona el método de cuantización que deseas aplicar al modelo."
)
use_imatrix = gr.Checkbox(
label="Usar Matriz de Importancia",
info="Marca esta opción si deseas usar una matriz de importancia para la cuantización."
)
imatrix_q_method = gr.Dropdown(
["IQ3_M", "IQ3_XXS", "Q4_K_M", "Q4_K_S", "IQ4_NL", "IQ4_XS", "Q5_K_M", "Q5_K_S"],
label="Método de Matriz de Importancia",
info="Selecciona el método de cuantización para la matriz de importancia.",
visible=False # Solo visible si se marca 'use_imatrix'
)
private_repo = gr.Checkbox(
label="Repositorio Privado",
info="Marca esta opción si deseas que el repositorio creado sea privado."
)
train_data_file = gr.File(
label="Archivo de Datos de Entrenamiento",
type="filepath",
info="Selecciona el archivo que contiene los datos de entrenamiento necesarios para generar la matriz de importancia.",
)
split_model = gr.Checkbox(
label="Dividir Modelo",
info="Marca esta opción para dividir el modelo en partes más pequeñas antes de subirlo."
)
split_max_tensors = gr.Number(
label="Max Tensors (para división)",
value=256,
info="Especifica el número máximo de tensores por parte si estás dividiendo el modelo.",
)
split_max_size = gr.Number(
label="Max Tamaño (para división)",
value=None,
info="Especifica el tamaño máximo de cada parte si estás dividiendo el modelo.",
)
oauth_token = gr.Textbox(
label="Token de Hugging Face",
type="password",
info="Introduce tu token de autenticación de Hugging Face. Asegúrate de que el token sea válido para acceder a los repositorios."
)
with gr.Row():
result = gr.HTML(label="Resultado")
img = gr.Image(label="Imagen")
process_button = gr.Button("Procesar Modelo")
process_button.click(
process_model,
inputs=[model_id, q_method, use_imatrix, imatrix_q_method, private_repo, train_data_file, split_model, split_max_tensors, split_max_size, oauth_token],
outputs=[result, img]
)
app.launch()
|