1 puntos por GN⁺ 2023-12-15 | 1 comentarios | Compartir por WhatsApp
  • Usando llamafile, un proyecto open source creado junto con Mozilla, como si fuera una herramienta de shell, se pueden ejecutar LLM locales como un solo ejecutable y resolver tareas de imágenes, páginas web, API, chat, código y correo electrónico con one-liners de Bash
  • Los .llamafile basados en LLaVA generan descripciones de imágenes en la salida estándar solo con --image y un prompt, aunque según el sistema operativo puede hacer falta preparación como Xcode, binfmt_misc o el sufijo .exe
  • Para integrarlo en automatizaciones, conviene acotar la salida con restricciones de gramática BNF, --temp 0 y límites de tokens con -n, y al generar nombres de archivo es importante evitar salidas impredecibles y errores ENAMETOOLONG
  • El resumen de URLs funciona convirtiendo HTML a texto con links y luego canalizándolo a un llamafile de Mistral 7B; en el ejemplo, una página web de 3,774 palabras se reduce a un resumen de 129 palabras
  • También permite usar una API local compatible con OpenAI, un chatbot de terminal, autocompletado de código y redacción de correos, pero los LLM para programación siguen teniendo límites en matemáticas y verificación, así que es más seguro verlos como herramientas de apoyo para explorar temas desconocidos

Usar llamafile como herramienta de shell para LLM locales

  • llamafile es un proyecto open source trabajado junto con Mozilla que permite ejecutar LLM directamente en la computadora del usuario
  • El proyecto consiguió 8.3k stars en GitHub, 1073 upvotes en Hacker News y también fue cubierto por Hackaday
  • La versión de referencia en los ejemplos es la 0.8.12, y el artículo muestra qué se puede hacer con esa versión
  • El inicio consiste en descargar un .llamafile precompilado desde Hugging Face y darle permisos de ejecución
    • El modelo usado es llava-v1.5-7b-q4.llamafile, para el modelo multimodal de visión LLaVA
    • Puede ejecutarse en MacOS, Linux, Windows y BSD
    • Si hay problemas, hay que revisar la sección Gotchas del README; en MacOS puede hacer falta Xcode, en Linux el intérprete binfmt_misc, y en Windows el sufijo .exe

Resumen de imágenes: llamar a LLaVA por salida estándar

  • llava-v1.5-7b-q4.llamafile usa por defecto un modelo multimodal de visión, aunque ese comportamiento cambia si se pasa --mmproj ''
  • Las imágenes se envían con la bandera --image GRAPHIC, y acepta archivos jpeg, png, tga, bmp, psd, gif, hdr, pic y pnm
  • La pregunta se pasa como --silent-prompt -p PROMPT, y la respuesta sale por la salida estándar
  • El one-liner de ejemplo le pregunta What do you see? a lemurs.jpg y usa --temp 0 para obtener una salida determinista
  • Para offloading a GPU hace falta -ngl 999
  • El mismo comando de resumen de imagen puede variar mucho en tiempo de ejecución según el hardware
    • Mac Studio: 4 segundos, precio $8,300, M2 Ultra, ancho de banda de memoria de 800 GB/s, 60 GPU cores
    • Windows PC: 10 segundos, NVIDIA GeForce RTX 2080 Ti de hace 4 años, precio en Amazon en ese momento de $500~$1,000
    • Hewlett Packard ProDesk 600 G5: 45 segundos, $1,653, Intel Core i9-9900, ancho de banda de memoria de 2667 MT/s o 19.8 GB/s, sin GPU
  • La salida de ejemplo describe a una lémur hembra sosteniendo a dos de sus tres crías, brindándoles protección y calor en un entorno verde

Generación segura de nombres de archivo: restricciones gramaticales y límites de tokens

  • Al crear nombres de archivo de imágenes con LLaVA, el riesgo principal es que la salida del LLM suele ser impredecible
  • --grammar restringe los tokens de salida posibles usando Backus-Naur Form
    • Por ejemplo, root ::= "yes" | "no" obliga a que la salida solo sea "yes\n" o "no\n"
    • En el ejemplo de nombres de archivo, primero se hace que solo salgan palabras en minúsculas y espacios, luego sed reemplaza los espacios por guiones bajos y se agrega .jpg
  • El one-liner para generar nombres de archivo usa --grammar 'root ::= [a-z]+ (" " [a-z]+)+' junto con -n 16
  • Si no se limita la cantidad máxima de tokens generados con -n 16, el LLM puede producir texto demasiado largo y provocar un error ENAMETOOLONG
  • La gramática debe coincidir hasta cierto punto con la forma en que el modelo normalmente genera texto
    • LLaVA no fue entrenado para producir frases con guiones bajos, así que si se meten guiones bajos directamente en la BNF pueden aparecer salidas inconsistentes
    • La salida en minúsculas sí estaba dentro del rango natural de LLaVA
    • Formatos muy presentes en la web, como JSON, pueden funcionar como guardrails con restricciones gramaticales para reducir errores sintácticos en JSON alucinado
  • Como versión más completa, se menciona el script rename-pictures.sh, con un ejemplo ejecutado sobre ~/Pictures

Resumen de URLs: combinación de links y Mistral 7B

  • Mistral 7B instruct llamafile puede usarse para resumir URLs HTML canalizando la salida del comando links
  • links es un navegador web de línea de comandos y en MacOS normalmente puede instalarse con brew install links
  • También se ofrece un binario APE precompilado para usar cuando no hay gestor de paquetes
    • links v2.29, 7.7MB
    • Para AMD64+ARM64, Linux+Windows+FreeBSD+NetBSD+OpenBSD
  • El one-liner de resumen de URL funciona con este flujo
    • Primero imprime [INST]Summarize the following text:
    • Convierte la página web a texto con links -codepage utf-8 -force-html -width 500 -dump URL
    • Limpia algunos caracteres con sed 's/*/ /g'
    • Agrega [/INST] y luego lo envía al llamafile de Mistral con -f /dev/stdin
  • La página de ejemplo, “Real Programmers Don’t Use Pascal”, se reduce de 3,774 palabras a un resumen de 129 palabras
  • Con el mismo método también se pueden hacer preguntas arbitrarias sobre un texto
    • En el ejemplo, se pregunta si el autor parece mentalmente inestable, y Mistral responde teniendo en cuenta que, aunque hay exageración e hipérbole, se trata de un texto satírico de 1983
    • Si se usa --grammar 'root ::= "yes" | "no"', la salida puede limitarse a una forma YES/NO más fácil de usar en scripts
  • La restricción importante es no superar el contexto de 32k tokens de Mistral v0.2
    • -width 500 ayuda a evitar la recomposición de párrafos y reduce saltos de línea innecesarios
    • sed 's/ */ /g' puede reducir espacios repetidos
    • dd bs=1 count=80000 puede servir como último recurso para recortar páginas web largas de forma brusca

API local compatible con OpenAI

  • El llamafile “server” ofrece un endpoint local compatible con la API de OpenAI
  • El ejemplo usa Mixtral 8x7B y requiere una GPU potente capaz de ejecutar un modelo de 30 gibibytes
  • El servidor se inicia con mixtral-8x7b-instruct-v0.1.Q5_K_M-server.llamafile --nobrowser
  • En otra terminal, se hace una solicitud con curl a http://localhost:8080/v1/chat/completions y luego se usa Python para imprimir el JSON de respuesta de forma legible
  • El JSON de la solicitud sigue el formato de OpenAI Chat Completions, con model puesto como gpt-3.5-turbo y un arreglo de mensajes system y user
  • La respuesta de ejemplo incluye un mensaje assistant que explica en verso el concepto de recursión, junto con el uso de completion_tokens, prompt_tokens y total_tokens

Chatbot de terminal: prompt Digital Athena

  • llamafile puede usarse como una herramienta estándar de línea de comandos UNIX descargando el binario comprimido desde la página de lanzamientos o compilándolo desde el código fuente
    • Se muestra el flujo git clone, make -j8, sudo make install, man llamafile
  • Esto facilita su uso junto con los GGUF weights de Hugging Face
  • El ejemplo de chatbot usa el modelo LLaMA original publicado por Facebook con fines de investigación
  • Es importante diseñar el prompt para que hable con tono académico y sin antropomorfizar el modelo
    • El nombre Digital Athena viene de Atenea, la diosa griega de la sabiduría y el conocimiento
    • Empieza con un formato de diálogo entre Researcher y Digital Athena
  • Para la ejecución interactiva se usan opciones como --interactive, --color, --ctx_size 4096, --reverse-prompt 'Researcher:'
  • --temp 0 hace que la salida sea determinista y reproducible
    • Si no se usa, llamafile aplica el nivel de aleatoriedad de la versión 0.8.12 y se obtiene una respuesta distinta cada vez
  • Si se quiere un chatbot antropomorfizado, el modelo LLaMA original puede ser difícil de manejar porque su tendencia por defecto es tratar al usuario como si fuera un desconocido en Reddit

Autocompletado de código: uso de Wizard Coder

  • Al descargar Wizard Coder llamafile, se puede usar para autocompletar la línea actual en Emacs o Vim
  • El modelo de ejemplo está ajustado principalmente para Python, pero genera una implementación en C de memcpy()
  • El prompt solo incluye el inicio de un bloque de código Markdown y la firma de la función, sin explicación en inglés
    • Si no se usa inglés, disminuye la probabilidad de que el modelo agregue largas explicaciones sobre el código
    • Si se usan bloques de código Markdown, es más probable que aparezca el token de reverse prompt definido con -r y que termine en el momento adecuado
    • Para forzar una detención más clara, también se puede limitar la respuesta a 100 tokens con -n 100
  • La salida de ejemplo implementa memcpy() con un bucle for que copia size desde src a dst y devuelve dst
  • Los LLM para programación tienen límites evidentes
    • Entienden bien el lenguaje humano, pero son débiles en matemáticas
    • Escriben código que parece convincente, pero muchas veces no resiste una revisión cuidadosa
    • Puede ayudar pensarlos como herramientas que repiten respuestas de Stack Overflow en varios lenguajes
    • Para tener una buena experiencia, conviene usarlos como apoyo para explorar temas desconocidos

Redacción de correos: generar respuestas con modelos pequeños

  • El ejemplo de redacción de correos plantea un escenario donde una Raspberry Pi de $50 responde correos corporativos para ayudar a vender productos
  • Rocket 3B usa una sintaxis de prompt ligeramente distinta y, en este caso, la temperature puede ayudar a imitar cierta improvisación
  • El ejemplo asume una configuración en la que un servidor PHP inyecta solicitudes de soporte en el prompt y canaliza la salida a sendmail
  • El prompt de sistema indica que debe ayudar al usuario, pero llevando la conversación hacia la compra de pepinillos
  • En el ejemplo, cuando un usuario dice que necesita rescate tras encontrarse con vientos fuertes en Long Island Sound, el modelo genera una respuesta empática y luego recomienda Bill Pickle’s Gourmet Dill Pickles
  • El último ejemplo tiene intención humorística y no debe interpretarse como una recomendación o respaldo de Mozilla hacia ningún modelo, licencia, dataset o práctica específicos

1 comentarios

 
GN⁺ 2023-12-15
Opiniones en Hacker News
  • Desde hace varios meses vengo explorando con gusto la combinación de LLM y utilidades de CLI, y realmente encajan muy bien
    La forma de la filosofía Unix de encadenar varias herramientas con pipes también se lleva muy bien con la manera en que funcionan los LLM
    He experimentado principalmente con la herramienta de CLI https://llm.datasette.io/, y también hay herramientas de uso puntual como https://github.com/simonw/blip-caption y https://github.com/simonw/ospeak
    Es tan divertido que me sorprende que más gente no esté explorando a fondo el área de LLM+CLI

    • Durante los últimos 9 meses, el 70% de la portada de Hacker News y Twitter fue sobre todo tipo de LLM CLI
      Ha sido la exploración más ruidosa que he visto hasta ahora en el campo tecnológico, al punto de que no necesito oír más, sino más bien menos
    • En el trabajo uso mucho https://github.com/go-go-golems/geppetto, que tiene un modo CLI y un modo de chat TUI
      Expone plantillas de prompts como verbos de línea de comandos y puede cargarlas desde varios “repositorios”
      Mantengo un conjunto de prompts para cada repositorio en el que trabajo, junto con scripts “prompto” personalizados https://github.com/go-go-golems/prompto que generan contexto dinámico para prompts
      También hice varios para bibliotecas de terceros, que están en https://github.com/go-go-golems/promptos
      Algunos prompts públicos se pueden ver en https://github.com/go-go-golems/geppetto/tree/main/cmd/pinoc..., y ahora estoy creando un framework declarativo de agentes
    • Buenos enlaces. Estaba usando https://github.com/npiv/chatblade y https://github.com/tbckr/sgpt, y estoy totalmente de acuerdo en que LLM+CLI es una combinación perfecta
      Hace poco, con httrack + w3m dump + sgpt images + visión de GPT, construí una base de conocimiento específica de 278 mil tokens, y armé un RAG con un hack personalizado en Perl que preserva la estructura general del conocimiento
      Me pregunto si han visto herramientas que encajen bien con la filosofía Unix para el procesamiento de entrada y RAG local
      Por cierto, veo que el autor del post original ya hizo bastante trabajo relacionado y lo resumió en https://simonwillison.net/2023/Oct/23/embeddings/
      Donde ahora estoy trabado es en una cadena de herramientas para hacer chunking del contenido del que se crearán embeddings. Sería bueno que hiciera cosas como detectar contexto de ubicación en el texto original, tipo “2.1 Failover” o “Chapter 8: The dream”, deshacer saltos de línea de fuentes con ancho de 80 caracteres y dividir de forma inteligente preservando los párrafos
    • El entusiasmo por los flujos de trabajo centrados en la CLI parece estar disminuyendo
      Creo que la causa principal es VS Code, y los desarrolladores a los que doy soporte también prefieren más apuntar y hacer clic que la terminal y la CLI
  • Posts recientes relacionados
    Llamafile – The easiest way to run LLMs locally on your Mac - https://news.ycombinator.com/item?id=38522636 - diciembre de 2023, 17 comentarios
    Llamafile is the new best way to run a LLM on your own computer - https://news.ycombinator.com/item?id=38489533 - diciembre de 2023, 47 comentarios
    Llamafile lets you distribute and run LLMs with a single file - https://news.ycombinator.com/item?id=38464057 - noviembre de 2023, 287 comentarios

  • Muy bueno. Me gustó especialmente el ejemplo de renombrar archivos de imagen de forma descriptiva con un LLM

  • Lo probé en una desktop Windows con una NVIDIA GeForce RTX 3080 Ti, y hubo algunos obstáculos antes de lograr que funcionara
    WSL muestra el error error: APE is running on WIN32 inside WSL. You need to run: sudo sh -c 'echo -1 > /proc/sys/fs/binfmt_misc/WSLInterop', que en el one-liner queda oculto en /dev/null
    Después, en zsh apareció zsh: exec format error: ./llava-v1.5-7b-q4-main.llamafile, así que tuve que ejecutarlo en bash. Es cierto que el título dice bash, pero parece raro que no funcione en zsh
    También aparece una advertencia de que no se admite el offloading a GPU, probablemente por WSL. No hago programación de GPU en esta máquina Windows

    • En zsh se resuelve anteponiendo sh al comando: sh ./llava-v1.5-7b-q4-main.llamafile
      Es un comportamiento particular de zsh y APE, y hay contenido relacionado en https://justine.lol/ape.html
    • Eso era un bug de ZSH y se corrigió hace unos meses. Parece que estás usando un ZSH viejo
    • Estaba por probarlo en una máquina Windows con una RTX 4070, pero suena a que en WSL no se usa la GPU
      Me pregunto si la prueba fue muy lenta usando solo CPU
  • Al buscar rápidamente en Hugging Face, veo varios Llamafile de TinyLlama de alrededor de 1B
    Sumados a los 3 llamafile que ya había, serían 6 en total, pero me pregunto si hay otros llamafile más por ahí

    • No sé la respuesta a la pregunta, pero me pregunto si sabías que puedes descargar el ejecutable independiente llamafile-server y usarlo con cualquier modelo gguf
  • Me pregunto qué opina HN de llamafile y modelfile(https://github.com/jmorganca/ollama/blob/main/docs/modelfile...)
    Ambos me recuerdan a una experiencia tipo Dockerfile. Modelfile se ve directamente como un Dockerfile, pero llamafile parece más difícil de escribir y su forma real no se entiende de inmediato. Me pregunto si es una secuencia de comandos que se ejecutan en la terminal
    En teoría, también me pregunto por qué no simplemente usar un Dockerfile

    • La función clave es la opción --grammar, y es muy buena para scripts bash que hacen todo tipo de tareas de clasificación de procesamiento de lenguaje natural limitando los logits de la salida del LLM
      Fuera de eso, si necesito un LLM local uso ollama; cuando alquilo un servidor con GPU uso vllm; y si solo necesito el mejor modelo uso la API de OpenAI
    • https://news.ycombinator.com/item?id=38464057
    • llamafile no usa Docker. Es simplemente un ejecutable
      Descargas llamafile, haces chmod +x y lo ejecutas con ./run
      Aunque también es posible combinar Docker + llamafile. En https://github.com/ajbouh/cosmos hay una configuración de Dockerfile bastante buena
  • Me dan curiosidad las ventajas y desventajas de llamafile y ollama usados en el post original

    • llamafile es básicamente algo más cercano a llama.cpp que no tienes que compilar tú mismo
      Por eso puedes usar todo tipo de perillas de configuración con un esfuerzo mínimo. En particular, si descargas el llamafile “server”, se convierte en la forma más rápida de levantar un LLM local en una pestaña del navegador
      https://huggingface.co/jartine/llava-v1.5-7B-GGUF/tree/main
      llamafile también puede funcionar como chatbot de línea de comandos, pero para ese uso ollama ofrece una experiencia mucho más limpia y pulida
  • Quiero confirmar si entendí bien. Si uso llamafile desde un script de shell para, por ejemplo, renombrar archivos dentro de un directorio, ¿cada vez que se pase un nuevo nombre de archivo hay que abrir y cargar el ejecutable?
    Entonces me pregunto si esa memoria se carga y descarga cada vez, o si hay algún caché genial que no conozco
    La primera vez que ejecuté el ejemplo de subtitulado de imágenes en un M1 Pro tardó 13 segundos, la segunda 8 segundos, y las ejecuciones posteriores siguieron tardando un tiempo parecido
    Si se procesan muchísimos archivos, realmente parecería necesario cargar los pesos una sola vez y mantenerlos mientras el proceso recorre el bucle
    Aun así, sigue siendo muy útil e interesante

    • El modelo se mapea en memoria desde el disco, así que el kernel se encarga de leerlo a memoria
      Mientras nada más reclame esa RAM, esas páginas permanecen cacheadas en memoria entre invocaciones de comandos
      En una workstation de 128 GB, incluso usando varios modelos 7B en CPU, todos quedan en caché
    • La diferencia entre ejecutar el main de llama.cpp y usar server + solicitudes HTTP POST es bastante grande, pero no como para cambiar el mundo
      En un modelo de 8 GB de VRAM, para completar unas pocas líneas es aproximadamente 6 segundos contra 2 segundos, y en una 3090 con 96 GB de RAM la inferencia corre toda en GPU
      Si realmente haces trabajos por lotes, sin duda conviene mantener el modelo cargado entre completados
      Por otro lado, tiene la desventaja de quedar atado al modelo cargado por el server. Si lo cargas cuando lo necesitas, puedes ir cambiando de modelo
      Esto es importante para consultas multimodales con imágenes, porque otros modelos no entienden los tokens de imagen proyectados
  • En los pasos de instalación aparece el siguiente comando, y me pregunto si es seguro

    sudo wget -O /usr/bin/ape [https://cosmo.zip/pub/cosmos/bin/ape-$(uname](<https://cosmo.zip/pub/cosmos/bin/ape-$(uname>) -m).elf  
    sudo chmod +x /usr/bin/ape  
    sudo sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register"  
    sudo sh -c "echo ':APE-jart:M::jartsr::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register"  
    
  • Me pregunto si hay que hacer algo para ejecutar llamafile en Windows 10
    Cuando ejecuto llava-v1.5-7b-q4-server.llamafile desde git bash, muere de inmediato con “Segmentation fault”, y en cmd no muestra ninguna salida
    También probé descargar llamafile y el modelo por separado y ejecutar llamafile.exe -m llava-v1.5-7b-Q4_K.gguf, pero el mismo problema persiste
    No encontré problemas similares y, por lo que veo, no parece ser un tema del antivirus

    • Me pregunto si lo probaste en cmd.exe o PowerShell
      Puedes pasar el flag --strace o, si es posible, --ftrace para ver qué está pasando
    • En Windows hay que cambiar el nombre del .llamafile descargado a .exe
    • En Windows hay que renombrar .llamafile a .exe