Técnicas de one-liner em Bash para LLMs
(justine.lol)- 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
.llamafilebaseado em LLaVA produz descrições de imagem na saída padrão só com--imagee um prompt, embora possa exigir preparação específica por sistema operacional, como Xcode,binfmt_miscou o sufixo.exe - Ao colocar isso em automações, é preciso restringir a saída com gramática BNF,
--temp 0e limite de tokens com-n, além de evitar saídas imprevisíveis e errosENAMETOOLONGna geração de nomes de arquivo - O resumo de URLs funciona convertendo HTML em texto com
linkse 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
.llamafilepré-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
- O modelo usado é
Resumo de imagens: chamando o LLaVA pela saída padrão
llava-v1.5-7b-q4.llamafileusa 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?sobrelemurs.jpge usa--temp 0para 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
--grammarpermite 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
sedpara trocar espaços por underscores e acrescentar.jpg
- Exemplo:
- 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 erroENAMETOOLONG - 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 combrew install links- Também é oferecido um binário APE pré-compilado para quem não tiver gerenciador de pacotes
linksv2.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
- Primeiro imprime
- 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 500ajuda a evitar reflow de parágrafos e reduz quebras de linha desnecessáriassed 's/ */ /g'pode reduzir espaços repetidosdd bs=1 count=80000pode 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
curlparahttp://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-turbono campomodele um array de mensagenssystemeuser - A resposta de exemplo inclui uma mensagem
assistantexplicando recursão em forma de poema, além do uso decompletion_tokens,prompt_tokensetotal_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
- É mostrado o fluxo
- 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
ResearchereDigital Athena
- Na execução interativa, são usados
--interactive,--color,--ctx_size 4096e--reverse-prompt 'Researcher:' --temp 0faz 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 loopforque copiasizedesrcparadste retornadst - 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
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
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
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
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
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/nullno one-linerDepois, 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 zshTambé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
shantes 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
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.
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.
--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.
Você baixa o llamafile, roda
chmod +xe 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.
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.
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.
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.
Fico me perguntando se é preciso fazer algo para rodar llamafile no Windows 10.
Quando executo
llava-v1.5-7b-q4-server.llamafileno 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.
cmd.exeou PowerShell?Também dá para passar as flags
--straceou, se possível,--ftracepara ver o que está acontecendo..llamafilebaixado para.exe..llamafilepara.exe.