Ensinando a LLM uma linguagem que nem você conhece
FatScript é uma linguagem de programação mais educacional feita pelo brasileiro Antonio Prates, e sem explicar muito, eu gosto bastante dela (mesmo que faça meses que eu não faço nada com ela). E a um (bom) tempo atrás o Antonio fez uma live no youtube programando em Fat usando o ChatGPT, usando um pequeno prompt dando um overview da linguagem, e enviando ele no começo de toda conversa
Junto a isso, eu tinha criado uma conta no Mistral, uma empresa de IA LLM francesa, que lança uns modelos opensource¹ bem conhecidos, como o Mixtral 8x7b, mas que também tem modelos proprietários que são servidos pela sua API e chat. E uma coisa que me chamou muita a atenção é a possibilidade de criar agentes² e bibliotecas (Leve em consideração que esse experimento foi feito a alguns meses, e a função de biblioteca mesmo tinha sido lançada durante a criação desse Frankenstein). Nunca fui usuário de ChatGPT, então eu não sei se essas funcionalidades também são disponíveis por lá, mas poder criar um agente de IA que eu posso selecionar o modelo em especifico e a temperatura me soou massa de mais!
- Fica meio confuso essa questão de opensource para modelos LLMs. Quando eu digo opensource ali é mais que qualquer um pode baixar e rodar na sua máquina
- Desde lá agora tem uma outra funcionalidade de agentes no
le chat
(o nome do chat deles), que tem uma interface bem mais simples para pessoas normais usarem. O que eu usei é a funcionalidade de agentes do console.mistral.ai, que é meio que uma visão mais de desenvolvedor, com outras funcionalidades como fine-tunning. Lá eu criei esse agente e deixei disponível para ser usado pelo chat
E então me deu na telha fazer esse experimento, de ver o quão longe eu consigo ir com esses poderes a mais de um agente
O Agente
A versão final ficou assim. Tá com o modelo nemo, 12B licenciado em Apache 2.0. Eu gostava sempre de experimentar com esses modelos menores, então ficava indo e voltando entre o nemo e o mistral-small
O prompt (Instruções) é em maior parte o que foi feito pelo antonio, mais correções que eu ia identificando que eram comuns entre os testes. Por exemplo
## Incorrect Loop Syntax
Error: Using incorrect loop syntax, such as `length @ _ -> { ... }`. You CANNOT pass a number (in this case the variable 'lenght') to a loop. They will just not run
Resolution: Use the range syntax `0..<length @ _ -> { ... }` to make a range of numbers, and iterate on them.
Example:
Incorrect:
length = 5
length @ _ -> { # Doesn't work!
console.log(_) # Not run!
}
Correct:
length = 5
0..<length @ _ -> {
console.log(_)
}
E depois, uma escolha meio duvidável, de colocar correções na parte de demonstrações. Eu comecei colocando ai, mas depois eu passei a pôr no final do prompt, então é o mesmo tipo de texto
Bibliotecas
E além do agente, também foi extremamente importante a funcionalidade de bibliotecas
Aqui eu botei vários programas em fatscript para ser usado de referência (O .txt é porque tem um filtro de extensões válidas). Uma vez eu fiz uma pergunta e ele marcou como fontes um arquivo da biblioteca. Mas foi a primeira vez que tinha acontecido. Então eu fiquei ‘hummmm, que dizer que antes ele não estava usando a biblioteca’, dai eu fiz um chat sem a biblioteca e ficou uma droga o resultado kkkkkk. Então, mesmo que ele não cite como referência, ele parece usar sim as biblioteca selecionadas.
Usando
Para testes, eu comecei com o desafio ‘99 Bottles of Beer’, que consiste em imprimir um texto com o formato:
99 bottles of beer on the wall, 99 bottles of beer.
Take one down and pass it around, 98 bottles of beer on the wall.
98 bottles of beer on the wall, 98 bottles of beer.
Take one down and pass it around, 97 bottles of beer on the wall.
...
1 bottle of beer on the wall, 1 bottle of beer.
Take one down and pass it around, no more bottles of beer on the wall.
No more bottles of beer on the wall, no more bottles of beer.
Go to the store and buy some more, 99 bottles of beer on the wall.
E para um primeiro resultado, foi até que bom:
_ <- fat.std
bottlesOfBeer = (n: Number) -> {
n > 0 ? {
log("{n} bottles of beer on the wall, {n} bottles of beer.")
log("Take one down, pass it around, {n - 1} bottles of beer on the wall.")
bottlesOfBeer(n - 1)
} : {
log("No more bottles of beer on the wall, no more bottles of beer.")
log("Go to the store and buy some more, 99 bottles of beer on the wall.")
}
}
bottlesOfBeer(99)
Fora não ter funcionado, claro… 😆. Mas foi um erro simples, interpolação de string não funciona com aspas duplas. Ele também escreveu isso de forma recursiva, mas desde que o programa rode, eu vou deixar essa escolha ruim passar
Esse desafio foi tão simpleszinho que eu já escolhi um outro pra testar, um gerador de senhas. Algo simples, que só pega X caracteres aleatório e põe numa string. Mas nossa, já foi uma luta esse
_ <- fat.std
# Function to generate a random password
generatePassword = (length: Number) -> {
characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_=+[]{}|;:,.<>?/`~'
password = []
length @ _ -> {
randomIndex = math.random(0, characters.size - 1)
password.append(characters(randomIndex))
}
password.join('')
}
# Read the password length from command line input
lengthInput = console.input('Enter the desired password length: ')
passwordLength = Number(lengthInput) ?? console.log('Invalid input. Please enter a number.')
passwordLength >= 0 ? {
password = generatePassword(passwordLength)
console.log('Generated Password: {password}')
} : {
console.log('Password length must be a non-negative number.')
}
O loop (length @ _ -> {
) tá errado, não existe .append
, math.random
gera um float e não recebe argumentos. Meu fluxo com esse primeiro desafio foi ir apontando onde ele errou e deixar ele resolver, para no final perguntar todos os erros que ele fez, e gerar perguntas e respostas para usar de few-prompt. A ideia é legal, mas o que ele errou ainda nesse loop não tá escrito
Mas ainda assim, considerando todos os erros que ela teve, ainda foi interessante ver como eu consegui dar tanto conhecimento de uma coisa totalmente grega pra LLM. Não tá em uma estado que daria pra usar a sério mesmo, e nem sei se isso é possível (pelo menos a ponto de ser prático). É chato o quanto ela pega vícios de outras linguagens e tenta usar.
Considerações finais
Infelizmente faz tanto tempo desde que eu fiz isso, que eu não lembro muito mais das experiências. Me restam só algumas anotações que fiz durante os testes, e uns links de chats. Então eu não lembro de como seria usar um modelo maior, por exemplo.
E hoje a funcionalidade de agente que eu usei tá toda quebrada. Talvez seja porque os primeiros 30 dias de uma conta mistral tem 100 dol de créditos. Mas eu não lembro desses experimentos gastarem créditos não
Mas eu geral eu gostei muito de brincar com isso. Até hoje eu uso o chat do mistral, e gosto muito. Esse experimento me faz pensar sobre próximas linguagens de programação. Durante a live do Antonio ele também percebe certos pontos que a IA acha que algo existe, e ele considera adicionar isso a linguagem. Porque, se é algo que a IA pensa que existe, outros devs devem pensar também. Eu não gosto muito disso porque se não tudo vai virar javascript.
E a outra questão também de: será que vão existir novas linguagens em produção? Porque se todos tiverem viciados em IA, não vão escrever numa lang que a IA não conhece, logo, não terá código para ser usado de aprendizado. E também tem o sentido de conteúdo feito por IA não ser bom ser alimentado de volta para o treinamento. As vezes eles já resolveram essa questão e eu não sei.
Mas em geral, será que para emprego sera para sempre o que temos hoje no top 10 linguagens usadas? Até porque o que temos já cobre bastante areas, não acho que faria falta. Eu diria que os Devs de Rust já tem código o suficiente, mas outros como V e Jai vão ficar de fora