Journal décrire une une image avec une iA locale

20
8
mai
2024

Aujourd'hui c'est fourien™, petit tuto sans prétention!

Pour décrire des images en utilisant une iA localement j'utilise LLaVA qui fait partie de LLaMA C++ (llama.cpp)

prérequis :

  • créer un dossier image_summary et ses sous dossiers
    mkdir -p image_summary/bin image_summary/models image_summary/data/img image_summary/data/txt

  • créer un venv (j'utilise Python 3.10.6)
    python -m venv ./image_summary/venv/

  • activer l'environnement
    source ./image_summary/venv/bin/activate

  • mettre à jour pip
    pip install --upgrade pip

  • installer les dépendances
    pip install 'glob2==0.7'

  • désactiver l'environnement
    deactivate

  • télécharger le code source de llama.cpp de cette release (llava a été temporairement retiré afin de refactoriser le code)

  • décompresser l'archive du code source dans un répertoire
    mkdir llama.cpp-b2356 && tar -zvxf llama.cpp-b2356.tar.gz --strip-components=1 -C ./llama.cpp-b2356/

  • compiler les binaires de llama.cpp pour avoir llava-cli
    cd llama.cpp-b2356
    cmake -Bbuild # basique CPU + RAM
    cmake -Bbuild -DLLAMA_CUBLAS=ON # pour utiliser CUDA avec une carte NViDiA
    cmake --build build --config Release

  • copier ./build/bin/llava-cli dans image_summary/bin/

  • télécharger les fichiers mmjprog et ggml
    ggml-model-q4_k.gguf (LLM 4Go) et mmproj-model-f16.gguf (la partie multimodale qui "voit" 600Mo) dans image_summary/models/

  • placer ce script python dans image_summary/image_summary.py

# mon ""code"" python avec coloration syntaxique
# (désolé je suis pas un grand codeur j'accepte les pull requests ^^)
from pathlib import Path
import glob
import subprocess
import os

LLAVA_EXEC_PATH = "./bin/llava-cli"
MODEL_PATH = "./models/ggml-model-f16.gguf"
MMPROJ_PATH = "./models/mmproj-model-f16.gguf"

DATA_DIR = "data"
IMAGE_DIR = Path(DATA_DIR, "img")
TXT_DIR = Path(DATA_DIR, "txt")

types = ('*.jpg', '*.png') # the tuple of file types
image_paths = []
for files in types:
        image_paths.extend(sorted(glob.glob(str(IMAGE_DIR.joinpath(files)))))
#print(image_paths)

txt_paths = sorted(glob.glob(str(TXT_DIR.joinpath("*.txt"))))

TEMP = 0.1
## for llava 1.5
PROMPT = "You are an assistant who perfectly describes images."

bash_command = f"{LLAVA_EXEC_PATH} -m {MODEL_PATH} --mmproj {MMPROJ_PATH} --temp {TEMP} -p '{PROMPT}' --ctx-size 0"
#print(bash_command)
# Bash command output
# ./bin/llava-cli -m ./models/ggml-model-f16.gguf --mmproj ./models/mmproj-model-f16.gguf --temp 0.1 -p "Describe the image." --ctx-size 0

for image_path in image_paths:
    image_name = Path(image_path).stem
    image_summary_path = TXT_DIR.joinpath(image_name + ".txt")

    if not os.path.exists(image_summary_path):
        print(f"Processing {image_path}")
        # add input image and output txt filenames to bash command
        bash_command_cur = f"{bash_command} --image '{image_path}' > '{image_summary_path}'"
        print(bash_command_cur)

        # run the bash command
        process = subprocess.Popen(
            bash_command_cur, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
        )

        # get the output and error from the command
        output, error = process.communicate()

        # commment output and error for less verbose output
#        print("Output:")
#        print(output.decode("utf-8"))

#        print("Error:")
#        print(error.decode("utf-8"))

        # return the code of the command 
        return_code = process.returncode
#        print(f"Return code: {return_code}")
#        print()

        print("Done")

        # clean txt files
        bash_command_sed = f"sed -i '/_/d' '{image_summary_path}' && sed -i '/^[[:space:]]*$/d' '{image_summary_path}'"
        print(bash_command_sed)

        # run the bash command
        process = subprocess.Popen(
            bash_command_sed, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
        )

        print("txt files cleaned")

    else:
        print(f"Already processed {image_summary_path}")
  • placer 2 ou 3 images dans image_summary/img/ pour tester

  • lancer le script
    ./image_summary/venv/bin/python image_summary.py

  • profit
    dans image_summary/txt/ le résultat, ça prend environ 1 minute par image sur mon processeur i5-12600K (beaucoup moins avec CUDA)

références :
https://github.com/ggerganov/llama.cpp
https://huggingface.co/mys/ggml_tree/main
https://plainenglish.io/community/generate-a-summary-of-an-image-with-an-llm-in-python-0fc069

  • # Quelques exemples ?

    Posté par  (site web personnel) . Évalué à 8 (+6/-0).

    Impossible de prétendre que la démarche ne soit pas bien détaillée et apparemment reproductible. Mais on reste sur sa faim côté exemples, et conclusion. Dommage et merci, beau journal.

    « IRAFURORBREVISESTANIMUMREGEQUINISIPARETIMPERAT » — Odes — Horace

    • [^] # Re: Quelques exemples ?

      Posté par  (site web personnel) . Évalué à 10 (+15/-0).

      Ah oui c'est pas bête des exemples!

      Logo linuxfr.org

      The image features a group of three cartoon animals, including two cats and one dog. They are all lying down on the grass, possibly enjoying a sunny day outdoors. Each animal has distinct facial expressions, with one cat looking sleepy, another looking sad, and the third cat appearing to be smiling. The scene is set in an open field where the animals can relax and enjoy each other's company.
      (NDR : Pas le meilleur, image assez petite)

      Manchot empereur

      The image features a large penguin standing on the snow, with its head turned to the side. It appears to be looking at something off-camera, possibly observing its surroundings or searching for food. The penguin's posture suggests that it is comfortable and relaxed in the cold environment.

      Linus Torvalds

      The image features a man wearing a gray shirt and standing with his arms crossed. He appears to be smiling, possibly posing for the camera or simply enjoying himself in the moment. The man's attire suggests that he might be dressed casually or professionally, depending on the context of the situation.

      wind0w$ suxX, GNU/Linux roxX!

  • # enthousiasme

    Posté par  (Mastodon) . Évalué à 7 (+6/-2). Dernière modification le 08 mai 2024 à 12:29.

    J'ai du mal à être enthousiaste par les IA. Les seules fois où j'ai interrogé des chatbots comme chatGPT je n'ai reçu que des grosses généralités, des trucs qui ne répondaient pas à la question en tournant autour et des mensonges. Et bien évidemment il refusait de donner ses sources.

    Du coup s'il faut passer tout son temps à creuser ou vérifier derrière je n'ai pas l'impression que ça a un réel intérêt. Je ne comprends pas ceux qui utilisent ça pour développer, il me semble que ce serait comme copier/coller des réponses prises au hasard sur stackoverflow.

    EDIT: et les exemples ci-dessus montrent que oui quand il n'est pas complètement à la ramasse comme pour la première image, le résultat est assez bof ou trop vague.

    • [^] # Re: enthousiasme

      Posté par  (site web personnel) . Évalué à 9 (+6/-0). Dernière modification le 08 mai 2024 à 12:49.

      Disons que si on demande à une personne lambda, le résultat ne sera pas forcément mieux, je parierai sur :

      • « un pingouin, un chat et un taureau allongés sur l'herbe avec l'air béat, sous une adresse LInUX.ORg »
      • « un manchot debout sur la banquise ensoleillée, peut-être assoupi car il a les yeux fermés ou noirs »
      • « un gars en polo gris les bras croisés, qui sourit, entre 45 et 55 ans, châtain, peau claire »

      (pardon aux familles, tout ça…)

      C'est probablement assez différent de la réponse d'un visiteur lambda du site :).

    • [^] # Re: enthousiasme

      Posté par  . Évalué à 3 (+3/-0).

      Vu que le pour le moment, on est sur de la (super) génération de suite de texte, la notion de sources est abstraite.

      L'IA actuelle est non déterministe dans le sens ou on ne cherche pas à avoir un résultat de 100%, mais à se rapprocher de quelque chose de significatif voir supérieur aux autres solutions. Après, est-ce que l'IA doit être utilisé à la place d'autre solution algorithmique déterministe, c'est une autre question.

      • [^] # Re: enthousiasme

        Posté par  (Mastodon) . Évalué à 10 (+7/-0).

        Oui c'est ce que j'ai compris aussi, mais au final ce que j'ai tendance à en conclure, c'est que c'est surtout utile à des entités qui ont besoin de générer du contenu à peu près crédible à grande vitesse…et je n'y vois que des usages concrets malhonnêtes ou détrimentaux à notre société.

        Alors que l'IA comme outil de travail bof. Un outil n'est bon que s'il donne des résultats fiables et déterminés. Si tu foires une vis ne serait-ce que 10% du temps avec ton tournevis ce n'est pas un bon outil.

        • [^] # Re: enthousiasme

          Posté par  . Évalué à 1 (+1/-0).

          Je comprends et effectivement, c'est ce que je pense aussi, mais :
          On peut utiliser pour de la traduction et de la correction (pas forcément orthographique) de texte qui toujours dans son approximation est très performante par rapport aux systèmes actuels. Faire des résumés de textes ou reformulation.
          Utiliser en mode moteur de recherche n'est à mon avis pas la bonne solution.
          La génération d'images permet des illustrations et d'avoir des idées que l'on n'aurait pas eu.
          Retour au journal, la description d'image peut être utiles pour le mal voyant "écoutant" des articles avec un TTS, mais ne voie pas des images d’illustrations sans description.

          Plus une technologie est simple, plus c'est utilisable par des personnes mal intentionné.

        • [^] # Re: enthousiasme

          Posté par  . Évalué à 0 (+0/-0).

          J'ai pas mal cherché aussi à quoi ça peux servir d'utiliser l'IA. Les exemples qu'on trouve sur internet sont pas top.
          Déjà, tu as un problème, tu lui pose une question, il peut te donner la bonne réponse. Ca dépend de la question, et de ce qu'il connait.

          Des exemples de choses utiles à faire avec une IA :
          -résumé de texte. Par exemple tu peux lui demander un résumé d'un livre. Tu veux avoir un résumé de quelques phrases sur un livre trés connu, si l'ia le connais il te fera un résumé. Apres, tu peux faire un résumé par chapitre, ou même directement savoir la fin sans avoir à lire le livre. Cela te permet d'augmenter la culture général. Ca peut marché aussi pour un livre dans une langue qui n'existe pas en français.
          -tu cherche quelque chose de plus poussé que ce que peux faire google. Par exemple si tu veux un film sur les courses automobiles qui a une bonne critique, mais qui n'est pas très connu et qui dure moins de deux heures. Ou si tu cherche un roman qui n'est pas sur plusieurs tomes, et qui parle de programmation.
          -tu veux installer un logiciel, avant, il faut vérifier la licence. Tu peux lui demander de te faire un résumé. Et s'il y a une modification, tu peux lui demander les différences.

          Apres au niveau codage, c'est en général moins de 15% de code juste, pour les meilleurs, mais souvent ça peut servir de base.

          • [^] # Re: enthousiasme

            Posté par  (site web personnel) . Évalué à 8 (+6/-0).

            Apres, tu peux faire un résumé par chapitre, ou même directement savoir la fin sans avoir à lire le livre. Cela te permet d'augmenter la culture général.

            Ça c'est exactement l'usage pour lequel l'AI est très mauvaise. Si elle ne connaît pas le livre dont tu lui parle, elle t'inventera quelque chose de crédible mais complètement faux.
            Au lieu d'augmenter ta culture générale, tu la diminueras.

            Par exemple ChatGPT (version gratuite) n'est jamais parvenu à me donner un résumé correct des Animaux malades de la peste (c'est pas aller chercher trop loin). Mais comme il sait que c'est de La Fontaine, il invente à chaque fois une nouvelle fable qui met en scène des animaux qui cherchent à faire face à une épidémie de peste. Ce que ChatGPT invente est à chaque fois une fable que La Fontaine aurait pu écrire.

            • [^] # Re: enthousiasme

              Posté par  . Évalué à 6 (+3/-0).

              Pour un résumé, c'est comme pour une traductio, l'approche c'est de lui fournir le texte à résumé. Tu ne demandes pas à piocher les infos en allant à la pèche dans la mémoire du llm, tu lui fournis les infos et il n'a qu'a les manipuler, c'est beaucoup plus fiable.

              Et ca s'explique bien, le prompting est un art, l'art de mettre le llm dans un état, lui donner du contexte, pour maximiser ses chances de donner la bonne réponse, d'aller la chevher quelque pary dans les enchainements de gazillions de paramètres, d'après les spécialiste. Par exemple il est connu que quand ils ont réussi à en faire jouer un plutôt bien aux échec fallait lui filer en prompt des en-têtes de fichier de parties, ce qui le mettai dans le bon contexte pour débloquer les circuits, alors que d'autres approches style "joue aux échec avec moi" n'aurait pas bien fonctionnées. Ça explique aussi le succès descprompts en olusieurs étapes ou tu lui demandes de détailler les étapes, ça permet de mettre dans les bons contextes et d'aller chercher pkus d'infos au passage, comme un gamin à qui on dirait de réfléchir un peu plus. Ça rend potentiellement un peu compliqué sur les gros réseau l'évaluation des capacités, ptete qu'il n'a pasxla capacité de faire un truc qu'on essaye de lui faire faire, ou qu'on a juste pas trouvé la bonne manière de prompter. Les benchmarks ont été nitoirement plutôt instables.

              En lui donnant toute l'info à résumé il a d'office le bon contexte et on n'utilise à la fois les capacité linguistiques et "au mieux" ses éventuelles "connaissances" générales.

              • [^] # Re: enthousiasme

                Posté par  (site web personnel) . Évalué à 2 (+0/-0).

                d'aller la chevher quelque pary

                WDYT ?!

                • [^] # Re: enthousiasme

                  Posté par  . Évalué à 4 (+1/-0).

                  Chercher quelque part. J'ai tenté l'expérience de clavier alternatif sur téléphone, pas tellement concluant /o\

              • [^] # Re: enthousiasme

                Posté par  (site web personnel) . Évalué à 3 (+0/-0).

                Pour un résumé, c'est comme pour une traductio, l'approche c'est de lui fournir le texte à résumé. Tu ne demandes pas à piocher les infos en allant à la pèche dans la mémoire du llm, tu lui fournis les infos et il n'a qu'a les manipuler, c'est beaucoup plus fiable.

                Même si c'est plus fiable, il faut quand même vérifier qu'il n'a pas dit de conneries quand même.
                Si tu n'as pas trop confiance dans ses capacités, le temps gagné est finalement vite perdu.

                D'où le fait que pour l'instant les usages concrets sont plus limités que présentés et servent avant tout à des gens ayant une expertise pour pouvoir vérifier rapidement s'il y a des conneries ou pas.

                Et ca s'explique bien, le prompting est un art, l'art de mettre le llm dans un état, lui donner du contexte, pour maximiser ses chances de donner la bonne réponse, d'aller la chevher quelque pary dans les enchainements de gazillions de paramètres, d'après les spécialiste.

                Le soucis du prompt c'est que déjà ce n'est pas fixe dans le temps. Un prompt qui fonctionne bien pour ChatGPT ne fonctionnera pas pour Mistral (ou pas aussi bien, faudra formuler autrement pour avoir un meilleur résultat), et même entre deux versions d'un même modèle cela peut évoluer.

                Par exemple le cas des échecs que tu cites de Mr Phi ne fonctionne que pour ChatGPT 3.5 turbo (il le dit lui même), avec les autres versions ou variantes cela ne fonctionne pas aussi bien avec ces prompts là.

                C'est donc finalement assez fragile car on fait reposer la manipulation de ces outils aux capacités très variables sur des connaissances pour les manipuler qui évoluent assez rapidement. Rien ne dit que l'art de faire du prompt en 2023 aura un quelconque intérêt en 2025 et que les bonnes astuces d'une époque ne fonctionnent plus plus tard.

    • [^] # Re: enthousiasme

      Posté par  (site web personnel) . Évalué à 2 (+0/-0).

      Je suis prof sur un curriculum IB, ou on a un cours dit TOK (Theory of Knowledge) qui est souvent comparé à de la philo appliqué. Je dirais plutôt qu’il faut regarder le but qui est de questionner ce qu’on sait.
      Les élèves doivent donc faire des essais sur des questions diverses et on se bat avec les IAs. Il y a les simples que ne font que réécrire ce que l’étudiant à fait lui même, genre Grammarly, et il y à les génératives qui font tout.

      Pour différencier les deux (la première n’est pas vraiment condamnable, la deuxième utilisée en copier/coller est considéré comme du plagiat), on regarde justement si le texte est creux ou s’il y a des idées. C’est ce qu’on a trouvé de mieux comme méthode d’identification. Ça en dit long sur la pertinence.

    • [^] # Re: enthousiasme

      Posté par  (site web personnel) . Évalué à 2 (+0/-0).

      J'étais assez peu enthousiaste aussi jusqu'à ce que je découvre, grâce à Mr Phi* les résultats autour de la question "Les LLMs ont ils un modèle du monde?"

      *Cette vidéo pour être précis : https://youtu.be/6D1XIbkm4JE?si=ZoqfDnZTo2r2pVql

      • [^] # Re: enthousiasme

        Posté par  (site web personnel) . Évalué à 1 (+0/-1).

        les résultats autour de la question "Les LLMs ont ils un modèle du monde ?"

        et donc, pour celleux qui ne veulent/peuvent pas voir la vidéo ?

      • [^] # Re: enthousiasme

        Posté par  . Évalué à 2 (+0/-0).

        Ah ouai ? Ça ne m'a pas du tout impressionné. Il a bouffé pleins de parties plutôt de qualité et il sort des coups un peu comme l’intelligence collective.

        'fin pas plus que tout le reste que j'ai pu voir, c'est impressionnant d'arriver à faire ça avec la méthodologie, mais en déduire "qu'il a un modèle du monde". Il ne calcul pas un meilleur coup, il ne sait même pas ce que c'est de gagner, il sort juste des coûts et son apprentissage sur des parties compétitives fait qu'il sort plutôt des bon coups quand on lui a pas inculqué à être un bot conversationnel. Je sais que ça se rapporte à sa vidéo où il parlait de parler sans connaitre la langue que ça interroge ce qu'est le savoir ou ce genre de chose. 1800 d'elo c'est un joueur de compétition c'est à dire ce sur qu'il a pu lire (bon clairement il a dû lire des parie 2200 et plus, mais il y en a moins).

        C'est moins il a un modèle du monde que ce que l'on a formalisé textuellement et dont on lui donne suffisamment de contenu il saura le reproduire (en même temps ça a était fait pour ça).

        https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

        • [^] # Re: enthousiasme

          Posté par  . Évalué à 3 (+0/-0).

          C'est moins il a un modèle du monde que ce que l'on a formalisé textuellement et dont on lui donne suffisamment de contenu il saura le reproduire (en même temps ça a était fait pour ça).

          Ben trivialement non puisque si c'était simplement ça il n'y aurait rien qui ressorte en dehors de son corpus original, juste de l'apprentissage par coeur. Donc si il ressort des trucs qui ne sont pas dans son corpus c'est parce qu'il y a une forme de généralisation, plus ou moins poussée. Les échecs montrent qu'il est largement capable, cf. Mr. Phi justement, de sortir des parties correctes avec des coups qui ne sont pas dans son corpus, donc il généralise, et c'est un début de modèle des échecs, faut compresser l'info dans quelque chose qui ressemblent àdes règles dans le réseau pour faire ça (je suis pas en train de dire qu'il est capable de jouer juste avec une description textuelle des règles ou qu'il peut sortir une description textuelle quand il avale pleins de parties)

          Pou la formalisation textuelle, oui c'est le principe des modèles de langue, mais on peut capturer beaucoup du monde avec des textes. Après le problème de correspondance image / description textuelle, donc si on imagine qu'il a quelque representation du monde "linguistique" et celui de la représentation des images c'est intéressant et pas forcément concluant de ce que j'ai pu voir.

          On suppute qu'il a, pour les images, en interne, des modèles hiérarchiques des objets a dessiner (ça permet de gérer l'affichage à différentes échelles avec plus ou moins de détails), on sait qu'il y a correspondance avec des étiquettes linguistiques, faut voir jusqu'où on peut combiner une généralisation de structure linguistique genre "la robe de la femme est rouge" ou le réseau a tout a fait pu apprendre qu'elle aurait pu être verte ou que les deux sont des couleurs, avec ce que le reseau d'image a pu apprendre de comment structurer une image. il sait probablement colorer des objets. Pour aller beaucoup plus loin et avoir des descriptions riches faut généraliser des informations de positions, les combiner avec des infos de couleur et des informations culturelles, d'époque …) souplesse que permet le langage facilement, pouvoir combiner des prompts, avec des combinaisons a l'infini. Un réseau qui généralise correctement aura "compris" ou au moins isolé toutes ces caractéristique et saura faire des combinaisons. Voire évaluer les combinaisons les plus plausibles.

    • [^] # Re: enthousiasme

      Posté par  . Évalué à 3 (+1/-0).

      L'autre jour j'ai fais un essai : je lui ai demandé un mot de vocabulaire que je n'arrivai pas à retrouvé via les dictionnaires de synonymes et ça a plutôt bien marché. J'aurais mis 2 ans à trouver une utilité. Bon je suis pas sûr que ça valait le coup.

      https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

    • [^] # Re: enthousiasme

      Posté par  (Mastodon) . Évalué à 6 (+3/-0).

      J'ai du mal à être enthousiaste par les IA

      Pour une fois qu'on donne un bon exemple concret d'utilisation… Grâce à ce truc tu vas pouvoir faire des recherche dans tes photos c'est pas mal non ? S'y retrouver dans ses propres photos est toujours un sujet d'actualité.

      En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.

  • # llama.cpp cuda et aussi les autres

    Posté par  . Évalué à 6 (+6/-0).

    A savoir que llama.cpp est aussi compatible avec les API d'accélération GPU autre que Nvidia
    - Metal (Apple)
    - SYCL (Intel)
    - Cuda (Nvidia)
    - hipBLAS (via ROCm, AMD, similaire à Cuda)
    - CLBlast (via OpenCL, générique)
    - Vulkan (générique)

    • [^] # Re: llama.cpp cuda et aussi les autres

      Posté par  (site web personnel, Mastodon) . Évalué à 2 (+0/-0).

      Oh, merci pour l'info, j'avais entendu parlé de cuda et opencl, mais je ne me doutais pas que Vulkan pouvait aussi être utilisé pour travailler avec le GPU.

      Je pensais bêtement que, étant le successeur d'opengl, c'était un outil dédié au graphisme.

      Vulkan est en concurrence avec OpenCl pour une implémentation open source d'outil pour calculer sur GPU ?

  • # typo

    Posté par  (site web personnel) . Évalué à 2 (+1/-0).

    Un modérateur pourrait rectifier au début du code python svp?

    IMAGE_DIR = Path(DATA_DIR, "image")

    en

    IMAGE_DIR = Path(DATA_DIR, "img")

    wind0w$ suxX, GNU/Linux roxX!

  • # merci, cela donne envie d'essayer

    Posté par  . Évalué à 4 (+3/-0).

    Mon poste de travail est equipé d'un rk3588 qui dispose d'un NPU.
    Est-ce que cette application peut en tirer parti ?
    J'avoue qu'en la matière je suis totalement largué.

    "Si tous les cons volaient, il ferait nuit" F. Dard

  • # Pourrait-il apprendre ?

    Posté par  . Évalué à 3 (+2/-0).

    Bonjour,

    Est-ce que ce système pourrait apprendre en même temps, en combinant avec de la reconnaissance de visage ? Et sortir des descriptions du genre "Tonton Arthur dans un jardin" "Bidule au bord de la mer" ?

Envoyer un commentaire

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.