Je suis Charlie

Autres trucs

Accueil

Seulement les RFC

Seulement les fiches de lecture

Mon livre « Cyberstructure »

Ève

onprem, pour faire tourner facilement des LLM

Première rédaction de cet article le 20 septembre 2023


Vous le savez, accéder à un LLM en ligne soulève de nombreux problèmes de dépendance et de confidentialité. La solution est de le faire tourner en local. Mais les obstacles sont nombreux.

Le premier obstacle est évidemment commercialo-juridique. Tous les modèles ne sont pas récupérables localement. Ainsi, les modèles derrière ChatGPT ou Midjourney ne semblent pas accessibles, et on doit les utiliser en ligne, confiant ses questions (et donc les sujets sur lesquels on travaille) à une entreprise commerciale lointaine. Même quand ils sont téléchargeables, les modèles peuvent avoir des restrictions d'utilisation (plusieurs entreprises affirment que leur modèle est open source, terme qui a toujours été du baratin marketing et c'est de toute façon une question compliquée pour un LLM). Mais il existe plusieurs modèles téléchargeables et utilisables sous une licence plus accessible, ce qui nous amène au deuxième obstacle.

L'IA n'est pas décroissante ! Même si la consommation de ressources est bien plus faible pour faire tourner un modèle que pour l'entrainer, elle reste élevée et vous ne ferez pas tourner un LLM sur votre Raspberry Pi. La plupart du temps, 32 Go de mémoire, un processeur multi-cœurs rapide et, souvent un GPU Nvidia seront nécessaires. Et si vous ne les avez pas ? Des choses pourront tourner mais pas forcément de manière optimale. (Les exemples qui suivent ont été faits sur un PC/Ubuntu de l'année, avec 32 Go de mémoire, 8 cœurs à 3 Ghz, et un GPU Intel, apparemment pas utilisé ; il faut que je creuse cette question.)

Et le troisième obstacle est la difficulté d'utilisation des logiciels qui font tourner un modèle et, en réponse à une question, produisent un résultat. C'est peut-être l'obstacle le moins grave, car les progrès sont rapides. Quand on lit les articles où des pionniers faisaient tourner un LLM sur leur PC il y a un an, et qu'on voit à quel point c'était compliqué, on se réjouit des progrès récents. Ainsi, le premier septembre, a été publiée la première version de onprem, un outil libre pour faire tourner relativement facilement certains LLM. onprem est conçu pour les développeurs Python, et il faudra donc écrire quelques petits scripts (mais d'autres outils, comme open-interpreter, ne nécessitent pas de programmer).

Démonstration. On installe onprem :

% pip install onprem
  

On écrit un tout petit programme trivial :

from onprem import LLM
llm = LLM()
print(llm)
  

Et on le fait tourner :

% python roulemapoule.py
You are about to download the LLM
Wizard-Vicuna-7B-Uncensored.ggmlv3.q4_0.bin to the
/home/stephane/onprem_data folder. Are you sure? (y/N) y
[██████████████████████████████████████████████████]
<onprem.core.LLM object at 0x7f7609a23c50>
  

Ce programme n'a encore rien fait d'utile, je voulais juste vous montrer qu'il gère automatiquement le téléchargement des modèles, s'ils ne sont pas déjà sur votre disque. Par défaut, il utilise une variante du modèle Vicuna à 7 milliards de paramètres, évidemment téléchargée depuis Hugging Face. Soyez patient, il y a 3,6 Go à télécharger, mais cela ne sera fait qu'une fois.

Maintenant, faisons un programme plus utile :

from onprem import LLM
llm = LLM()
answer = llm.prompt("Why should I run a LLM locally and not on line?")

L'exécution nous donnera :

% python roulemapoule.py
llama.cpp: loading model from /home/stephane/onprem_data/Wizard-Vicuna-7B-Uncensored.ggmlv3.q4_0.bin
llama_model_load_internal: format     = ggjt v3 (latest)
llama_model_load_internal: n_vocab    = 32000
llama_model_load_internal: n_ctx      = 2048
llama_model_load_internal: n_embd     = 4096
llama_model_load_internal: n_mult     = 256
llama_model_load_internal: n_head     = 32
llama_model_load_internal: n_layer    = 32
llama_model_load_internal: n_rot      = 128
llama_model_load_internal: ftype      = 2 (mostly Q4_0)
llama_model_load_internal: n_ff       = 11008
llama_model_load_internal: model size = 7B
llama_model_load_internal: ggml ctx size =    0.08 MB
llama_model_load_internal: mem required  = 5407.72 MB (+ 1026.00 MB per state)
llama_new_context_with_model: kv self size  = 1024.00 MB

1. Increased security: Running a LLM locally provides greater security
against potential cyberattacks, as there is no internet connection for
the hacker to exploit.
2. Better performance: Running a LLM locally can improve performance
by reducing latency and improving reliability due to fewer network 
hops.
3. Faster troubleshooting: When running a LLM locally, you have direct 
control over its configuration, making it easier to diagnose and
resolve issues.
4. Increased flexibility: Running a LLM locally allows for greater 
customization and flexibility in configuring the system to meet
specific business requirements.
 

Ma foi, la réponse n'est pas absurde, mais il est amusant de noter que la raison qui me semble la plus importante, la confidentialité, n'est pas citée. Le bla-bla technique au début est dû au moteur sous-jacent utilisé, llama.cpp. Mais en tout cas, vous voyez que c'était très simple à installer et à utiliser, et que vous pouvez donc désormais facilement inclure un LLM dans vos applications écrites en Python.

Pour générer non plus du texte en langue naturelle mais du code, on va indiquer explicitement un modèle prévu pour le code (également dérivé de LLaMA, comme Vicuna) :

from onprem import LLM
llm = LLM("https://huggingface.co/TheBloke/CodeUp-Llama-2-13B-Chat-HF-GGML/resolve/main/codeup-llama-2-13b-chat-hf.ggmlv3.q4_1.bin")
answer = llm.prompt("Write a Python program to output the Fibonacci suite")
  

Et ça nous donne :


% python roulemapoule.py 
You are about to download the LLM codeup-llama-2-13b-chat-hf.ggmlv3.q4_1.bin to the /home/stephane/onprem_data folder. Are you sure? (y/N) y
[██████████████████████████████████████████████████]llama.cpp: loading model from /home/stephane/onprem_data/codeup-llama-2-13b-chat-hf.ggmlv3.q4_1.bin
…
The Fibonacci sequence is a series of numbers in which each number is
the sum of the two preceding numbers, starting from 0 and 1. The first
few terms of the sequence are:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...

Write a Python program to output the Fibonacci sequence up to 10.

Here is an example of how you might do this:
```
def fibonacci(n):
    if n <= 1:
        return n
    else:
        return fibonacci(n-1) + fibonacci(n-2)

for i in range(10):
    print(fibonacci(i+1))
```
Expected output:

0
1
1
2
3
5
8
13
21
34

(Notez la syntaxe Markdown.)

Bon, comme vous le voyez, c'est simple, ça marche et vous pouvez travailler sur des projets confidentiels sans craindre de fuite. Mais il y a des limites :

  • Je n'ai pas réussi à utiliser des modèles comme Bloom (et le message d'erreur est vraiment incompréhensible), sans doute parce que onprem dépend de lama.cpp et qu'il ne fonctionne qu'avec des dérivés de LLaMA (il faut vraiment que je lise la documentation ou que je teste un moteur adapté à Bloom). Idem pour Falcon. Notez aussi qu'onprem demande un format particulier du modèle, GGML (et que les formats changent).
  • J'ai l'impression que mon GPU n'est pas utilisé, il faut que je regarde ça.

Allez, pour se consoler de ces limites, on va faire une jolie image avec Stable Diffusion en local (mais rien à voir avec onprem) :

pip install diffusers transformers scipy torch
sudo apt install git-lfs
git clone https://huggingface.co/runwayml/stable-diffusion-v1-5 
  

(Le git clone prend très longtemps, il y a des dizaines de gigaoctets à charger.) On écrit un programme :

from diffusers import StableDiffusionPipeline
pipe = StableDiffusionPipeline.from_pretrained('.')
# Pour éviter la censure "Potential NSFW content was detected in one
# or more images. A black image will be returned instead. Try again with
# a different prompt and/or seed.": 
pipe.safety_checker = lambda images, clip_input: (images, [False for i in images])
prompt = "A system engineer running to install the last version of BIND to fix yet another security vulnerability, in the style of Philippe Druillet"
image = pipe(prompt).images[0]  
image.save("sysadmin-rush.png")
  

Et voilà : sysadmin-rush.png

(D'autres outils m'ont été signalés mais la plupart non-libres.)

Version PDF de cette page (mais vous pouvez aussi imprimer depuis votre navigateur, il y a une feuille de style prévue pour cela)

Source XML de cette page (cette page est distribuée sous les termes de la licence GFDL)