Un tutorial de codificación para ejecutar PrismML Bonsai 1-Bit LLM en CUDA con GGUF, evaluación comparativa, Chat, JSON y RAG
sección(“7 · Q1_0_g128 Cuantización: qué está pasando bajo el capó”) print(textwrap.dedent(“”” ╔═══════════════════════════════ ═══════════════════════════════╗ ║ Bonsái Q1_0_g128 Representación del peso ║ ╠═══════════════════════════════ ═══════════════════════════════╣ ║ Cada peso = 1 bit: 0 → −escala ║ ║ 1 → +escala ║ ║ Cada 128 pesos comparten un factor de escala FP16 ║ ║ ║ ║ Bits efectivos por peso: ║ ║ 1 bit (signo) + 16/128 bits (escala compartida) = 1,125 bpw ║ ║ ║ ║ Comparación de memoria para Bonsai-1.7B: ║ ║ FP16: 3,44 GB (1,0× base) ║ ║ Q1_0_g128: 0,24 GB (¡14,2× más pequeño!) ║ ║ MLX 1-bit g128: 0,27 GB (12,8× más pequeño) ║ ╚═══════════════════════════════ ═══════════════════════════════╝ “””)) print(“📐 Demostración de Python de la lógica de cuantificación Q1_0_g128:\n”) import random random.seed(42) GROUP_SIZE = 128weights_fp16 = [random.gauss(0, 0.1) for _ in range(GROUP_SIZE)]
escala = max(abs(w) para w en pesos_fp16) cuantificado = [1 if w >= 0 else 0 for w in weights_fp16]
descuantificado = [scale if b == 1 else -scale for b in quantized]
mse = suma((a – b) ** 2 para a, b en zip(weights_fp16, descuantizado)) / GROUP_SIZE print(f” Pesos FP16 (primeros 8): {[f'{w:.4f}’ for w in weights_fp16[:8]]}”) print(f” repetición de 1 bit (primeros 8): {cuantizado[:8]}”) print(f” Escala compartida: {scale:.4f}”) print(f” Descuantificado (primeros 8): {[f'{w:.4f}’ for w in dequantized[:8]]}”) print(f” MSE de reconstrucción: {mse:.6f}”) memoria_fp16 = TAMAÑO_GRUPO * 2 memoria_1bit = TAMAÑO_GRUPO / 8 + 2 print(f”\n Memoria: FP16={memory_fp16}B vs Q1_0_g128={memory_1bit:.1f}B ” f”({memory_fp16/memory_1bit:.1f}× reducción)”) sección(“8 · Punto de referencia de rendimiento: tokens por segundo”) def punto de referencia(prompt, n_tokens=128, n_runs=3, **kw): tiempos = []
para i en rango(n_runs): print(f” Ejecutar {i+1}/{n_runs} …”, end=” “, flush=True) _, transcurrido = infer(prompt, detallado=False, n_predict=n_tokens, **kw) tps = n_tokens / tiempos transcurridos.append(tps) print(f”{tps:.1f} tok/s”) avg = sum(timings) / len(timings) print(f”\n ✅ Promedio: {avg:.1f} tok/s (más de {n_runs} ejecuciones, {n_tokens} tokens cada una)”) return avg print(“📊 Evaluación comparativa de Bonsai-1.7B en su GPU…”) tps = benchmark( “Explique el concepto de retropropagación de redes neuronales paso a paso.”, n_tokens=128, n_runs=3, ) print(“\n Rendimientos de referencia publicados (del documento técnico):”) print(” ┌──────────────────────┬─ ────────┬──────────────┐”) print(” │ Plataforma │ Backend │ TG128 tok/s │”) print(” ├──────────────────────┼─ ────────┼──────────────┤”) print(” │ RTX 4090 │ CUDA │ 674 │”) print(” │ M4 Pro 48 GB │ Metal │ 250 │”) print(f” │ Su GPU (medida) │ CUDA │ {tps:>7.1f} │”) print(” └──────────────────────┴─ ────────┴──────────────┘”) sección(“9 · Chat de varios turnos con acumulación de contexto”) def chat(user_msg, system=”Eres un asistente útil.”, historial=Ninguno, **kw): si el historial es Ninguno: historial = []
History.append((“user”, user_msg)) full = f”<|im_start|>system\n{system}<|im_end|>\n” para rol, mensaje en el historial: full += f”<|im_start|>{role}\n{msg}<|im_end|>\n” full += “<|im_start|>assistant\n” safe = full.replace(‘”‘, ‘\\”‘).replace(‘\n’, ‘\\n’) cmd = ( f'{LLAMA_CLI} -m “{MODEL_PATH}”‘ f’ -p “{safe}” -e’ f’ -n 200 –temp 0.5 –top-p 0.85 –top-k 20′ f’ -ngl 99 -c 4096 –no-display-prompt’ ) resultado = run(cmd, capture=True, check=False) respuesta = resultado.stdout.strip() historial.append((“assistant”, respuesta)) return respuesta, historial print(“🗣 Iniciando una conversación de 3 turnos sobre modelos de 1 bit…\n”) historial = []
vueltas = [
“What is a 1-bit language model?”,
“What are the main trade-offs compared to 4-bit or 8-bit quantization?”,
“How does Bonsai specifically address those trade-offs?”,
]
para i, mensaje en enumerar(turns, 1): print(f”👤 Turn {i}: {msg}”) respuesta, historia = chat(msg, historia=historia) print(f”🤖 Bonsai: {respuesta}\n”) time.sleep(0.5) sección(“10 · Exploración de parámetros de muestreo”) creative_prompt = “Escribe una descripción de una oración de una ciudad futurista impulsada enteramente por IA de 1 bit.” configuraciones = [
(“Precise / Focused”, dict(temp=0.1, top_k=10, top_p=0.70)),
(“Balanced (default)”, dict(temp=0.5, top_k=20, top_p=0.85)),
(“Creative / Varied”, dict(temp=0.9, top_k=50, top_p=0.95)),
(“High entropy”, dict(temp=1.2, top_k=100, top_p=0.98)),
]

print(f’Prompt: “{creative_prompt}”\n’) para etiqueta, parámetros en configuraciones: out, _ = infer(creative_prompt, verbose=False, n_predict=80, **params) print(f” [{label}]”) imprimir(f” temp={parámetros[‘temp’]}, top_k={parámetros[‘top_k’]}, top_p={parámetros[‘top_p’]}”) imprimir(f” → {salir[:200]}\norte”)