Implementación de un modelo Bonsai-27B de 1 bit con PrismML llama.cpp y flujos de trabajo de inferencia local compatibles con OpenAI

En este tutorial, implementamos el modelo de lenguaje Bonsai-27B de 1 bit utilizando la bifurcación PrismML de llama.cpp, que proporciona los núcleos CUDA especializados necesarios para decodificar el formato de cuantificación GGUF Q1_0_g128 del modelo. Comenzamos validando el tiempo de ejecución de la GPU, instalando las dependencias de Python requeridas, compilando los archivos binarios de inferencia habilitados para CUDA y descargando los pesos del modelo comprimido de Hugging Face. Luego probamos el modelo a través de llama-cli, iniciamos un servidor de inferencia local compatible con OpenAI e interactuamos con él a través de un cliente Python reutilizable que admite terminaciones estándar, respuestas transmitidas, conversaciones de varios turnos y generación de código. También examinamos configuraciones opcionales para evaluación comparativa de rendimiento, almacenamiento en caché de valores clave cuantificados, inferencia de contexto largo, decodificación especulativa y extensiones multimodales.

importar os importar sys importar hora importar json importarshutil importar subproceso importar multiprocesamiento WORK_DIR = “/content” REPO_URL = “https://github.com/PrismML-Eng/llama.cpp” REPO_DIR = os.path.join(WORK_DIR, “llama.cpp”) BUILD_DIR = os.path.join(REPO_DIR, “build”) BIN_DIR = os.path.join(BUILD_DIR, “bin”) HF_REPO = “prism-ml/Bonsai-27B-gguf” MODEL_FILE = “Bonsai-27B-Q1_0.gguf” MODEL_PATH = os.path.join(WORK_DIR, MODEL_FILE) SERVER_HOST = “127.0.0.1” SERVER_PORT = 8080 SERVER_URL = f”http://{SERVER_HOST}:{SERVER_PORT}” GEN_PARAMS = {“temperature”: 0.7, “top_p”: 0.95, “top_k”: 20} CTX_SIZE = 8192 N_GPU_LAYERS = 99 USE_KV_Q4 = False def sh(cmd, check=True, **kw): “””Ejecutar un comando de shell, transmitiendo la salida al cuaderno.””” print(f”\n$ {cmd}”) return subprocess.run(cmd, shell=True, check=check, **kw) print(“=” * 70) print(“[1/7] Comprobando el entorno”) print(“=” * 70) gpu = subprocess.run(“nvidia-smi –query-gpu=name,memory.total –format=csv,noheader”, shell=True, capture_output=True, text=True) if gpu.returncode != 0: sys.exit(“No se detectó GPU. En Colab: Tiempo de ejecución -> Cambiar tipo de tiempo de ejecución -> GPU (T4).”) print(f”GPU detectada: {gpu.stdout.strip()}”) print(“Bonsai-27B solo necesita ~5,2 GB de pico en contexto 4K; cualquier GPU Colab funciona.”) sh(“pip -q install huggingface_hub request”)

Configuramos el espacio de trabajo de Colab, el repositorio de modelos, el punto final del servidor, los parámetros de inferencia, el tamaño del contexto y las configuraciones de descarga de GPU necesarias a lo largo del tutorial. Definimos una función de comando de shell reutilizable y verificamos que el tiempo de ejecución exponga una GPU NVIDIA compatible antes de continuar. Luego instalamos las dependencias del cliente HTTP y Hugging Face Hub necesarias para la recuperación del modelo y la comunicación API.

imprimir(“=” * 70) imprimir(“[2/7] Construyendo la bifurcación PrismML llama.cpp con CUDA (almacenado en caché después de la primera ejecución)”) print(“=” * 70) if not os.path.isdir(REPO_DIR): sh(f”git clone –profundidad 1 {REPO_URL} {REPO_DIR}”) else: print(“Repo ya clonado – omitiendo.”) cli_bin = os.path.join(BIN_DIR, “llama-cli”) server_bin = os.path.join(BIN_DIR, “llama-server”) bench_bin = os.path.join(BIN_DIR, “llama-bench”) si no (os.path.exists(cli_bin) y os.path.exists(server_bin)): trabajos = multiprocessing.cpu_count() sh(f”cmake -S {REPO_DIR} -B {BUILD_DIR} -DGGML_CUDA=ON -DCMAKE_BUILD_TYPE=Release”) sh(f”cmake –build {BUILD_DIR} -j{jobs} –target llama-cli llama-server llama-bench”) else: print(“Binarios ya creados – saltando.”)

Clonamos la bifurcación PrismML de llama.cpp, que proporciona los núcleos especializados necesarios para el formato de cuantificación Q1_0_g128 del modelo. Configuramos una versión de lanzamiento habilitada para CUDA con CMake y compilamos los ejecutables de línea de comandos, servidor y evaluación comparativa. También reutilizamos archivos binarios generados previamente cuando ya existen, lo que reduce el tiempo de configuración repetida en la misma sesión de Colab.

imprimir(“=” * 70) imprimir(“[3/7] Descargando pesos de Hugging Face”) print(“=” * 70) from huggingface_hub import hf_hub_download if not os.path.exists(MODEL_PATH): descargado = hf_hub_download(repo_id=HF_REPO, filename=MODEL_FILE, local_dir=WORK_DIR) print(f”Descargado en: {descargado}”) else: print(“El modelo ya está en el disco — saltando.”) print(f”Tamaño del modelo en el disco: {os.path.getsize(MODEL_PATH) / 1e9:.2f} GB”)

Nos conectamos al Hugging Face Hub y descargamos el modelo Bonsai-27B GGUF en el espacio de trabajo de Colab. Omitimos la transferencia cuando el archivo del modelo ya está disponible localmente, lo que permite que las ejecuciones posteriores se realicen de manera más eficiente. Luego calculamos y mostramos el tamaño del modelo implementado para confirmar que los pesos comprimidos se almacenan correctamente.

imprimir(“=” * 70) imprimir(“[4/7] Prueba de humo con llama-cli”) print(“=” * 70) sh( f'{cli_bin} -m {MODEL_PATH} ‘ f’-p “Explique en dos oraciones por qué la cuantificación de 1 bit ahorra memoria.” ‘ f’-n 128 -ngl {N_GPU_LAYERS} ‘ f’–temp {GEN_PARAMS[“temperature”]} ‘f’–top-p {GEN_PARAMS[“top_p”]} –top-k {GEN_PARAMS[“top_k”]} ‘ f’-no-cnv 2>/dev/null’, comprobar=Falso, ) print(“=” * 70) print(“[5/7] Iniciando llama-server (API compatible con OpenAI)”) print(“=” * 70) solicitudes de importación kv_flags = “-ctk q4_0 -ctv q4_0” if USE_KV_Q4 else “” server_cmd = ( f”{server_bin} -m {MODEL_PATH} ” f”–host {SERVER_HOST} –port {SERVER_PORT} ” f”-ngl {N_GPU_LAYERS} -c {CTX_SIZE} {kv_flags}” ) print(f”$ {server_cmd} (fondo)”) server_log = open(os.path.join(WORK_DIR, “server.log”), “w”) server_proc = subprocess.Popen(server_cmd, shell=True, stdout=server_log, stderr=server_log) para _ in range(120): intente: if request.get(f”{SERVER_URL}/health”, timeout=2).status_code == 200: print(“El servidor está activo.”) break excepto request.exceptions.RequestException: pase time.sleep(2) else: server_proc.kill() sys.exit(“El servidor no pudo iniciarse; verifique /content/server.log”)

Realizamos una prueba de humo de línea de comandos para verificar que el tiempo de ejecución compilado pueda cargar el modelo cuantificado y generar una respuesta válida. Luego iniciamos llama-server con la descarga completa de la capa de GPU, la ventana de contexto seleccionada y la configuración opcional de caché KV cuantificada. Consultamos repetidamente el punto final de salud hasta que el servicio de inferencia compatible con OpenAI esté listo para las solicitudes de los clientes.

imprimir(“=” * 70) imprimir(“[6/7] Hablando con Bonsai-27B a través de la API compatible con OpenAI”) print(“=” * 70) def chat(messages, stream=False, max_tokens=512, **overrides): “””Cliente de chat mínimo compatible con OpenAI para el servidor llama local.””” payload = { “model”: “bonsai-27b”, “messages”: mensajes, “max_tokens”: max_tokens, “stream”: stream, **GEN_PARAMS, **overrides, } si no stream: r = request.post(f”{SERVER_URL}/v1/chat/completions”, json=payload) r.raise_for_status() return r.json()[“choices”][0][“message”][“content”]

r = request.post(f”{SERVER_URL}/v1/chat/completions”, json=payload, stream=True) r.raise_for_status() completo = []
para línea en r.iter_lines(): si no es línea o no line.startswith(b”data: “): continúa fragmento = línea[len(b”data: “):]
si trozo == b”[DONE]”: romper delta = json.loads(fragmento)[“choices”][0][“delta”].get(“content”, “”) full.append(delta) print(delta, end=””, Flush=True) print() return “”.join(full) SISTEMA = {“role”: “system”, “content”: “Eres un asistente útil”} print(“\n— 6a: finalización básica —“) respuesta = chat([SYSTEM, {“role”: “user”,
“content”: “What is the capital of France? One sentence.”}]) print(respuesta) print(“\n— 6b: razonamiento matemático, transmitido token por token —“) chat([SYSTEM, {“role”: “user”,
“content”: “A train travels 120 km at 80 km/h, then 90 km at ”
“60 km/h. What is its average speed for the whole ”
“trip? Show your reasoning briefly.”}]stream=True, max_tokens=700) print(“\n— 6c: chat multiturno —“) historial = [SYSTEM]
para user_msg en [“My name is Priya and I love graph algorithms.”,
“Suggest one project idea that combines my interest with LLMs.”,
“What was my name again?”]: historia.append({“role”: “usuario”, “content”: user_msg}) respuesta = chat(history, max_tokens=300) historia.append({“role”: “asistente”, “content”: respuesta}) print(f”\nUSUARIO: {user_msg}\nBONSAI: {respuesta}”) print(“\n— 6d: generación de código —“) print(chat([SYSTEM, {“role”: “user”,
“content”: “Write a Python function that returns the n-th ”
“Fibonacci number using memoization. Code only.”}]máximo_tokens=400))

Definimos un cliente de chat Python reutilizable que envía solicitudes compatibles con OpenAI al servidor Bonsai-27B alojado localmente. Admitimos respuestas de transmisión de eventos estándar y enviadas por el servidor mientras aplicamos los parámetros de muestreo configurados de temperatura, top-p y top-k. Luego evaluamos las respuestas fácticas básicas, el razonamiento matemático, la memoria conversacional de múltiples turnos y la generación de código Python.

imprimir(“=” * 70) imprimir(“[7/7] Extras opcionales”) print(“=” * 70) RUN_BENCHMARK = False if RUN_BENCHMARK: sh(f”{bench_bin} -m {MODEL_PATH} -ngl {N_GPU_LAYERS}”, check=False) print(“”” NOTAS Y PRÓXIMOS PASOS —————— * Contexto largo: el modelo admite hasta 262 000 tokens. En Colab, aumente CTX_SIZE y configure USE_KV_Q4 = Verdadero (caché KV de 4 bits): con él, los contextos de 100 000 tokens caben en un pico de aproximadamente 6,8 GB, dentro de los 16 GB de un T4 * Decodificación especulativa: el repositorio incluye un borrador DSpark (Q4_1, ~1,79 GB) que proporciona una velocidad de decodificación sin pérdidas de ~1,37 veces en CUDA. Consulte la bifurcación PrismML llama.cpp. Léame para ver las banderas de publicación y descargue el paquete Drafter desde el mismo repositorio de HF si desea probarlo. * Vision: un paquete mmproj opcional de ~0,63 GB agrega entrada de imagen; solo se carga cuando llega una imagen, por lo que la publicación de solo texto nunca es rentable. ~95% de FP16) es un intercambio directo: simplemente cambie HF_REPO / MODEL_FILE arriba. * Apagar: ejecute server_proc.kill() en una celda posterior para liberar la GPU “””) print(“Listo. El servidor aún está funcionando: llame al chat(.[…]) de células nuevas!”)

Exponemos un interruptor de evaluación comparativa opcional que mide el procesamiento rápido y el rendimiento de generación de tokens con el ejecutable compilado llama-bench. Revisamos opciones de implementación avanzadas, incluida la inferencia de contexto largo, el almacenamiento en caché KV de 4 bits, la decodificación especulativa, el soporte de visión y una variante de modelo ternario de mayor capacidad. Terminamos manteniendo activo el proceso del servidor para que podamos continuar llamando a la función de chat desde celdas adicionales de Colab.

En conclusión, establecimos un flujo de trabajo de inferencia local completo para ejecutar Bonsai-27B. Utilizamos la implementación de PrismML para preservar la compatibilidad con la representación de peso de 1,125 bits altamente comprimida del modelo y al mismo tiempo mantener accesible el proceso de inferencia completo a través de interfaces compatibles con OpenAI y la línea de comandos. Validamos el razonamiento, la memoria conversacional, la generación de streaming y las capacidades de programación, al mismo tiempo que conservamos el control sobre los parámetros de muestreo, la longitud del contexto, la descarga de GPU y la precisión de la caché KV. Esta configuración nos brinda una plataforma para experimentar con modelos de lenguaje grandes de bits bajos, evaluar su eficiencia y calidad de salida e integrarlos en aplicaciones Python sin depender de un servicio de inferencia alojado externo.

Consulte el código completo aquí. Además, no dude en seguirnos en Twitter y no olvide unirse a nuestro SubReddit de más de 150.000 ml y suscribirse a nuestro boletín. ¡Esperar! estas en telegrama? Ahora también puedes unirte a nosotros en Telegram.

¿Necesita asociarse con nosotros para promocionar su repositorio de GitHub O su página principal de Hugging O su lanzamiento de producto O seminario web, etc.? Conéctate con nosotros

A Sana Hassan, pasante de consultoría en Marktechpost y estudiante de doble titulación en IIT Madras, le apasiona aplicar la tecnología y la inteligencia artificial para abordar los desafíos del mundo real. Con un gran interés en resolver problemas prácticos, aporta una nueva perspectiva a la intersección de la IA y las soluciones de la vida real.