1 pontos por GN⁺ 2023-12-15 | 1 comentários | Compartilhar no WhatsApp
  • Usando o llamafile, projeto open source criado com a Mozilla, como se fosse uma ferramenta de shell, é possível executar LLMs locais em um único executável e processar tarefas com imagens, páginas web, APIs, chat, código e e-mail com one-liners em Bash
  • Um .llamafile baseado em LLaVA produz descrições de imagem na saída padrão só com --image e um prompt, embora possa exigir preparação específica por sistema operacional, como Xcode, binfmt_misc ou o sufixo .exe
  • Ao colocar isso em automações, é preciso restringir a saída com gramática BNF, --temp 0 e limite de tokens com -n, além de evitar saídas imprevisíveis e erros ENAMETOOLONG na geração de nomes de arquivo
  • O resumo de URLs funciona convertendo HTML em texto com links e depois enviando por pipe para um llamafile Mistral 7B; no exemplo, uma página de 3.774 palavras vira um resumo de 129 palavras
  • Também dá para usar API local compatível com OpenAI, chatbot de terminal, conclusão de código e redação de e-mails, mas LLMs para programação ainda têm limitações em matemática e validação, então é mais seguro tratá-los como ferramentas auxiliares para explorar temas desconhecidos

Usando o llamafile como ferramenta de shell para LLM local

  • llamafile é um projeto open source desenvolvido com a Mozilla que permite executar LLMs diretamente no computador do usuário
  • O projeto alcançou 8.3k stars no GitHub, 1073 upvotes no Hacker News e também foi coberto pelo Hackaday
  • A release usada como referência nos exemplos é a 0.8.12, e o texto mostra o que é possível fazer com essa versão
  • O começo é baixar um .llamafile pré-compilado no Hugging Face e dar permissão de execução
    • O modelo usado é llava-v1.5-7b-q4.llamafile, da versão multimodal de visão LLaVA
    • Ele pode ser executado em MacOS, Linux, Windows e BSD
    • Se houver problemas, é preciso verificar a seção Gotchas do README; no MacOS pode ser necessário Xcode, no Linux o interpretador binfmt_misc, e no Windows o sufixo .exe

Resumo de imagens: chamando o LLaVA pela saída padrão

  • llava-v1.5-7b-q4.llamafile usa por padrão um modelo multimodal de visão, e esse comportamento muda se for passado --mmproj ''
  • A imagem é fornecida com a flag --image GRAPHIC, aceitando arquivos jpeg, png, tga, bmp, psd, gif, hdr, pic e pnm
  • A pergunta é passada como --silent-prompt -p PROMPT, e a resposta sai na saída padrão
  • O one-liner de exemplo pergunta What do you see? sobre lemurs.jpg e usa --temp 0 para obter uma saída determinística
  • Para offloading na GPU, é necessário -ngl 999
  • O mesmo comando de resumo de imagem pode ter tempos de execução muito diferentes dependendo do hardware
    • Mac Studio: 4 segundos, preço de US$ 8.300, M2 Ultra, largura de banda de memória de 800 GB/s, 60 GPU cores
    • PC com Windows: 10 segundos, NVIDIA GeForce RTX 2080 Ti de 4 anos de uso, com preço de US$ 500 a US$ 1.000 na Amazon na época
    • Hewlett Packard ProDesk 600 G5: 45 segundos, US$ 1.653, Intel Core i9-9900, 2667 MT/s ou 19.8 GB/s de largura de banda de memória, sem GPU
  • A saída de exemplo descreve uma lêmure fêmea segurando dois de seus três filhotes, oferecendo proteção e calor em um ambiente verde

Geração segura de nomes de arquivo: restrição por gramática e limite de tokens

  • Ao criar nomes de arquivo de imagem com LLaVA, o principal risco é que a saída de um LLM é, em geral, imprevisível
  • --grammar permite limitar os tokens possíveis de saída com Backus-Naur Form
    • Exemplo: root ::= "yes" | "no" força a saída a ser apenas "yes\n" ou "no\n"
    • No exemplo de nome de arquivo, faz-se a saída conter apenas palavras minúsculas e espaços, depois usa-se sed para trocar espaços por underscores e acrescentar .jpg
  • O one-liner para gerar nomes de arquivo usa --grammar 'root ::= [a-z]+ (" " [a-z]+)+' junto com -n 16
  • Se o máximo de tokens gerados não for limitado com -n 16, o LLM pode produzir texto longo demais e causar erro ENAMETOOLONG
  • A gramática precisa combinar em alguma medida com o tipo de saída que o modelo normalmente geraria
    • O LLaVA não foi treinado para gerar frases com underscores, então colocar underscores diretamente na BNF pode produzir saídas inconsistentes
    • Saída em minúsculas estava dentro do comportamento esperado do LLaVA
    • Formatos muito presentes na web, como JSON, podem servir como guardrail via restrição gramatical para reduzir erros sintáticos em JSON alucinado
  • Em uma forma mais completa, há o script rename-pictures.sh, com exemplo de execução sobre ~/Pictures

Resumo de URL: combinação de links com Mistral 7B

  • O Mistral 7B instruct llamafile pode ser usado para resumir URLs HTML recebendo por pipe a saída do comando links
  • links é um navegador web de linha de comando e, no MacOS, normalmente pode ser instalado com brew install links
  • Também é oferecido um binário APE pré-compilado para quem não tiver gerenciador de pacotes
    • links v2.29, 7.7MB
    • Para AMD64+ARM64, Linux+Windows+FreeBSD+NetBSD+OpenBSD
  • O one-liner de resumo de URL funciona com o seguinte fluxo
    • Primeiro imprime [INST]Summarize the following text:
    • Converte a página web em texto com links -codepage utf-8 -force-html -width 500 -dump URL
    • Limpa alguns caracteres com sed 's/*/ /g'
    • Acrescenta [/INST] e então envia ao llamafile do Mistral com -f /dev/stdin
  • A página “Real Programmers Don’t Use Pascal”, usada no exemplo, foi reduzida de 3.774 palavras para um resumo de 129 palavras
  • O mesmo método também permite fazer perguntas arbitrárias sobre um texto
    • No exemplo, o autor pergunta se o escritor parece mentalmente instável, e o Mistral leva em conta que há exagero e hipérbole, mas que se trata de um texto satírico de 1983
    • Com --grammar 'root ::= "yes" | "no"', a resposta pode ser limitada a um formato YES/NO fácil de usar em scripts
  • A limitação mais importante é não ultrapassar o contexto de 32k tokens do Mistral v0.2
    • -width 500 ajuda a evitar reflow de parágrafos e reduz quebras de linha desnecessárias
    • sed 's/ */ /g' pode reduzir espaços repetidos
    • dd bs=1 count=80000 pode cortar páginas muito longas de forma grosseira como última linha de defesa

API local compatível com OpenAI

  • O llamafile do tipo “server” fornece localmente um endpoint compatível com a API da OpenAI
  • O exemplo usa o Mixtral 8x7B e requer uma GPU potente capaz de rodar um modelo de 30 gibibytes
  • O servidor é iniciado com mixtral-8x7b-instruct-v0.1.Q5_K_M-server.llamafile --nobrowser
  • Em outro terminal, a requisição é feita com curl para http://localhost:8080/v1/chat/completions, e o JSON retornado é formatado em Python para melhor leitura
  • O JSON da requisição segue o formato do OpenAI Chat Completions, usando gpt-3.5-turbo no campo model e um array de mensagens system e user
  • A resposta de exemplo inclui uma mensagem assistant explicando recursão em forma de poema, além do uso de completion_tokens, prompt_tokens e total_tokens

Chatbot de terminal: prompt Digital Athena

  • O llamafile pode ser usado como um comando UNIX padrão, baixando o binário compactado da página de releases ou compilando a partir do código-fonte
    • É mostrado o fluxo git clone, make -j8, sudo make install, man llamafile
  • Essa forma facilita o uso com GGUF weights do Hugging Face
  • O exemplo de chatbot usa o modelo LLaMA original, publicado pelo Facebook para fins de pesquisa
  • É importante estruturar o prompt para que o modelo não seja personificado e fale em tom acadêmico
    • O nome Digital Athena vem de Atena, a deusa grega da sabedoria e do conhecimento
    • A conversa começa no formato de diálogo entre Researcher e Digital Athena
  • Na execução interativa, são usados --interactive, --color, --ctx_size 4096 e --reverse-prompt 'Researcher:'
  • --temp 0 faz a saída ser determinística e reproduzível
    • Sem isso, o llamafile usa o nível de aleatoriedade da versão 0.8.12 e gera respostas diferentes a cada execução
  • Se a intenção for um chatbot personificado, o modelo LLaMA original pode ser difícil de lidar porque sua tendência padrão é tratar o usuário como um estranho do Reddit

Conclusão de código: usando Wizard Coder

  • Baixando o Wizard Coder llamafile, é possível usá-lo em Emacs ou Vim para autocompletar a linha atual
  • O modelo de exemplo foi ajustado principalmente para Python, mas gera uma implementação em C de memcpy()
  • O prompt inclui apenas o início de um bloco de código Markdown e a assinatura da função, sem explicação em inglês
    • Sem escrever em inglês, diminui a chance de o modelo anexar longas explicações sobre o código
    • Usar um bloco de código Markdown aumenta a chance de aparecer o token de reverse prompt definido com -r, encerrando no momento adequado
    • Para garantir ainda mais a parada, é possível limitar a resposta a 100 tokens com -n 100
  • A saída de exemplo implementa memcpy() com um loop for que copia size de src para dst e retorna dst
  • LLMs para programação têm limitações claras
    • Entendem bem linguagem humana, mas são fracos em matemática
    • Escrevem código que parece plausível, mas raramente resiste a uma revisão rigorosa
    • Pode ser útil pensar neles como ferramentas que repetem respostas do Stack Overflow em várias linguagens
    • Para ter uma boa experiência, é melhor esperar ajuda para explorar temas desconhecidos

Redação de e-mail: gerando respostas com modelos pequenos

  • O exemplo de redação de e-mail mostra um Raspberry Pi de US$ 50 respondendo e-mails corporativos para ajudar na venda de produtos
  • O Rocket 3B usa uma sintaxe de prompt um pouco diferente e, nesse caso, a temperature pode ajudar a imitar improvisação
  • O exemplo supõe uma configuração em que um servidor PHP injeta solicitações de suporte no prompt e envia a saída por pipe para sendmail
  • O prompt de sistema instrui o modelo a ajudar o usuário, mas também a conduzir a conversa para a compra de picles
  • No exemplo em que o usuário diz que encontrou ventos fortes em Long Island Sound e precisa ser resgatado, o modelo gera uma resposta com empatia e depois recomenda Bill Pickle’s Gourmet Dill Pickles
  • O último exemplo tem intenção humorística e não deve ser interpretado como recomendação ou endosso, por parte da Mozilla, de qualquer modelo, licença, dataset ou prática

1 comentários

 
GN⁺ 2023-12-15
Comentários do Hacker News
  • Há alguns meses venho explorando com prazer a combinação de LLMs com utilitários de CLI, e os dois realmente combinam muito bem
    A forma de encadear várias ferramentas com pipes da filosofia Unix também se encaixa muito bem com a maneira como os LLMs funcionam
    Experimentei principalmente com a ferramenta de CLI https://llm.datasette.io/, e também há ferramentas pontuais como https://github.com/simonw/blip-caption e https://github.com/simonw/ospeak
    É divertido a ponto de ser estranho que mais gente não esteja explorando mais a fundo esse espaço de LLM+CLI

    • Nos últimos 9 meses, 70% da primeira página do Hacker News e do Twitter era papo sobre todo tipo de LLM CLI
      Foi a exploração de área técnica mais barulhenta que já vi, a ponto de eu não precisar ouvir mais sobre isso, e sim menos
    • No trabalho uso bastante https://github.com/go-go-golems/geppetto, que tem modo CLI e modo de chat em TUI
      Ele expõe templates de prompt como se fossem verbos de linha de comando, e pode carregá-los de vários “repositórios”
      Mantemos um conjunto de prompts para cada repositório em que estamos trabalhando, junto com scripts personalizados “prompto” https://github.com/go-go-golems/prompto que geram contexto dinâmico de prompt
      Também fizemos bastante coisa para bibliotecas de terceiros, em https://github.com/go-go-golems/promptos
      Alguns prompts públicos podem ser vistos em https://github.com/go-go-golems/geppetto/tree/main/cmd/pinoc..., e agora estamos criando um framework declarativo de agentes
    • Ótimos links. Eu estava usando https://github.com/npiv/chatblade e https://github.com/tbckr/sgpt, e concordo totalmente que LLM+CLI é uma combinação perfeita
      Recentemente montei uma base de conhecimento específica de 278 mil tokens com httrack + w3m dump + sgpt images + GPT vision, e construí o RAG com um hack customizado em Perl que preserva a estrutura de tópicos do conhecimento
      Fico curioso se alguém já viu ferramentas para processamento de entrada e RAG local que combinem tão bem com a filosofia Unix
      Acrescentando: vi que o autor do post original já fez bastante trabalho relacionado, resumido em https://simonwillison.net/2023/Oct/23/embeddings/
      O ponto em que estou travando agora é a cadeia de ferramentas para fazer o chunking do conteúdo a ser transformado em embeddings. Seria bom se detectasse contexto de localização no texto, como “2.1 Failover” ou “Chapter 8: The dream”, desfizesse quebras de linha de fontes com largura de 80 caracteres e fizesse divisões inteligentes preservando os parágrafos
    • Parece que o entusiasmo com workflows centrados em CLI está diminuindo aos poucos
      Acho que a principal razão é o VS Code, e os desenvolvedores que eu apoio também querem mais apontar e clicar do que terminal e CLI
  • Aqui vão alguns posts relacionados recentes
    Llamafile – The easiest way to run LLMs locally on your Mac - https://news.ycombinator.com/item?id=38522636 - dezembro de 2023, 17 comentários
    Llamafile is the new best way to run a LLM on your own computer - https://news.ycombinator.com/item?id=38489533 - dezembro de 2023, 47 comentários
    Llamafile lets you distribute and run LLMs with a single file - https://news.ycombinator.com/item?id=38464057 - novembro de 2023, 287 comentários

  • Muito legal. Gostei especialmente do exemplo de renomear arquivos de imagem com nomes descritivos usando LLM

  • Testei em um desktop Windows com NVIDIA GeForce RTX 3080 Ti, e houve alguns obstáculos até conseguir fazer funcionar
    No WSL apareceu o erro error: APE is running on WIN32 inside WSL. You need to run: sudo sh -c 'echo -1 > /proc/sys/fs/binfmt_misc/WSLInterop', que fica oculto pelo /dev/null no one-liner
    Depois, no zsh, apareceu zsh: exec format error: ./llava-v1.5-7b-q4-main.llamafile, então precisei executar no bash. O título diz bash, mas ainda assim parece estranho não funcionar no zsh
    Também aparece um aviso dizendo que GPU offloading não é suportado, provavelmente por causa do WSL. Nesta máquina Windows eu não faço programação de GPU

    • No zsh dá para resolver colocando sh antes do comando: sh ./llava-v1.5-7b-q4-main.llamafile
      É um comportamento peculiar do zsh com APE, e há conteúdo relacionado em https://justine.lol/ape.html
    • Isso era um bug do ZSH e foi corrigido alguns meses atrás. Parece que você está usando um ZSH antigo
    • Eu estava pensando em testar numa máquina Windows com RTX 4070, mas pelo visto a GPU não é usada no WSL
      Fico curioso se, usando só CPU, os testes ficaram muito lentos ou não
  • Dei uma busca rápida no Hugging Face e vi alguns Llamafile do TinyLlama na faixa de ~1B.
    Somando aos 3 llamafiles que já existiam, dá um total de 6, mas fico curioso se há outros llamafiles por aí na natureza.

    • Não sei a resposta da pergunta, mas você sabia que é possível baixar o executável autônomo llamafile-server e usá-lo com qualquer modelo gguf?
  • Fico curioso sobre como o HN enxerga llamafile e modelfile(https://github.com/jmorganca/ollama/blob/main/docs/modelfile...).
    Os dois lembram uma experiência parecida com Dockerfile. O Modelfile parece diretamente um Dockerfile, mas o llamafile parece mais difícil de escrever e sua forma real não fica imediatamente clara. Fico me perguntando se é uma sequência de comandos executados no terminal.
    Em teoria, também fico me perguntando por que simplesmente não usar um Dockerfile.

    • A funcionalidade principal é a opção --grammar, e ela é ótima para scripts bash que fazem todo tipo de tarefa de classificação de processamento de linguagem natural ao restringir os logits da saída do LLM.
      Fora isso, se eu preciso de um LLM local uso ollama, quando alugo um servidor com GPU uso vllm, e quando só preciso do melhor modelo uso a API da OpenAI.
    • https://news.ycombinator.com/item?id=38464057
    • llamafile não usa Docker. É só um executável.
      Você baixa o llamafile, roda chmod +x e depois executa com ./run.
      Ainda assim, também dá para combinar Docker + llamafile. Há uma configuração de Dockerfile bem boa em https://github.com/ajbouh/cosmos.
  • Queria saber quais são os prós e contras do llamafile usado no post original em comparação com o ollama.

    • O llamafile é basicamente mais próximo do llama.cpp sem precisar compilar nada manualmente.
      Então você consegue usar todo tipo de ajuste com o mínimo de esforço. Em especial, se baixar o llamafile “server”, ele vira a forma mais rápida de subir um LLM local em uma aba do navegador.
      https://huggingface.co/jartine/llava-v1.5-7B-GGUF/tree/main
      O llamafile também consegue funcionar como chatbot de linha de comando, mas para esse uso o ollama oferece uma experiência bem mais limpa e polida.
  • Quero confirmar se entendi direito. Se eu usar o llamafile em um script de shell para algo como renomear arquivos em um diretório, então ele vai ter que abrir e carregar o executável toda vez que um novo nome de arquivo entrar, certo?
    Nesse caso, essa memória é carregada e descarregada toda vez, ou existe algum cache esperto que eu não conheço?
    Quando rodei o exemplo de legenda de imagem no M1 Pro pela primeira vez, levou 13 segundos; na segunda, 8 segundos; e as execuções seguintes continuaram levando mais ou menos esse mesmo tempo.
    Se eu fosse processar um volume muito grande de arquivos, parece que realmente seria necessário carregar os pesos uma única vez e mantê-los enquanto o processo roda em loop.
    Ainda assim, continua sendo muito útil e interessante.

    • O modelo é mapeado em memória a partir do disco, então o kernel cuida de trazê-lo para a memória.
      A menos que outra coisa precise daquela RAM, essas páginas permanecem em cache na memória mesmo entre chamadas do comando.
      Em uma workstation com 128 GB, mesmo usando vários modelos 7B na CPU, todos permanecem em cache.
    • Há uma diferença razoável entre executar o main do llama.cpp e usar server + requisições POST HTTP, mas nada que vire o mundo de cabeça para baixo.
      Em um modelo com 8 GB de VRAM, para completar algumas linhas dá algo como 6 segundos contra 2 segundos, e em uma 3090 com 96 GB de RAM toda a inferência está rodando na GPU.
      Se você realmente estiver fazendo processamento em lote, com certeza vale mais a pena manter o modelo carregado entre as conclusões.
      Por outro lado, isso tem a desvantagem de te prender ao modelo carregado no server. Se carregar sob demanda, você pode trocar de modelo quando precisar.
      Isso é importante para consultas multimodais com imagem, porque outros modelos não entendem os tokens de imagem projetados.
  • Há a seguinte etapa no processo de instalação, e fico me perguntando se isso é 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"  
    
  • Fico me perguntando se é preciso fazer algo para rodar llamafile no Windows 10.
    Quando executo llava-v1.5-7b-q4-server.llamafile no git bash, ele cai imediatamente com “Segmentation fault”, e no cmd não aparece saída nenhuma.
    Também tentei baixar o llamafile e o modelo separadamente e rodar llamafile.exe -m llava-v1.5-7b-Q4_K.gguf, mas o mesmo problema continua.
    Não consegui encontrar problemas parecidos e, pelo que vejo, também não parece ser problema de antivírus.

    • Você já tentou executar via cmd.exe ou PowerShell?
      Também dá para passar as flags --strace ou, se possível, --ftrace para ver o que está acontecendo.
    • No Windows, é preciso renomear o .llamafile baixado para .exe.
    • No Windows, você precisa renomear .llamafile para .exe.