|

PROJET – Zelen Zajac, Ollama Client IA Partie 2 : Pratique

L’objectif de cette partie est d’expliquer comment déployer l’outil et de mettre en lumière certains choix techniques (ou pas 🙂 je me réserve un article full powershell après réflexion). Celui qui veut faire du reverse engineering avec le code, grand bien lui fasse 🙂

Comme pour les autres gros projets d’envergure, il s’agit là d’un ReadMe dans un format personnel qui jure avec les .txt ou traditionnel wiki.

Prérequis

Avant de rentrer dans le vif du sujet, le déploiement étant multiplateforme, je traiterai les deux sujets de par l’application GUI1 ou CLI2 sur les environnements Windows et GNU/Linux. Il est toutefois primordial d’avoir au minimum la version Powershell.

A ce jour, dans les versions 1.0.1 et 1.0.2, il reste des optimisations de code (refactorisation) à effectuer. Ces versions sont considérées comme stable et non en version Béta :). Néanmoins, je n’ai pas automatisé le déploiement par le biais de package .exe ou .msi.

Pour terminer, il n’y a pas besoin des PRIVILEGES ADMINISTRATEURS pour utiliser l’application.

Configuration

Ayant développé une application client, il n’y a pas de notion FrontEnd ou Backend.

Avant de démarrer le script ou l’application, il est nécessaire de faire un détour par le fichier de configuration présent dans le répertoire config à la racine du projet. Comme pour les autres projets, je vais prendre le temps de décrire chacune des parties de ce fichier.

Le fichier se découpe en 1 partie de 2 sous-parties.

* Une sous-partie globale qui définit les paramètres du script et de son fonctionnement

* Une sous-partie dédiée à l’application Ollama permettant d’établir la connexion à l’API3

* Une sous-partie concernant l’envoie de notification SMTP4

Le fichier de configuration sera amené à évoluer en fonction des suggestions et améliorations à apporter.

Le choix de segmenter les parties ? Faciliter le maintien et l’évolutivité du fichier foutrebleu !

Allez, disséquons le fichier 🙂

DEBUG : Prend la valeur boolean $true ou $false. Ce paramètre permet d’activer dans la console le mode debug.

TRANSACTION_SCRIPT : Prend la valeur boolean $true ou $false. Ce paramètre active ou non la redirection des flux de la console dans un fichier de log. Le fichier est écrasé à chaque exécution du code.

TRANSACTION_SCRIPT_FILE : Prend la valeur une chaine de caractère de type String. Indique le nom du fichier dans lequel toutes les sorties vont être redirigées. Attention ce dernier n’est pris en compte que si et seulement si le paramètre TRANSACTION_SCRIPT est définie à $true.

AUTHOR : Prend la valeur une chaine de caractère de type String. Prend la valeur une chaine de caractère de type String. Le nom du créateur des scripts afin d’afficher l’information dans les différents rendus.

VERSION : Prend la valeur une chaine de caractère de type String. Suivre l’évolution de versionning de l’outil et des scripts.

DATE : Prend la valeur une chaine de caractère de type String. La date de la dernière modification et version disponible.

MODULES : Prend en paramètre un tableau de chaine de caractère de type String. L’ensemble des modules définit dans ce tableau seront chargés au démarrage de l’application. Les modules doivent être présent dans le répertoire module au format .psm1

OLLAMA_NAME : Prend en paramètre une chaine de caractère de type String. Il correspond au nom fqdn de l’appliance ou l’adresse IP du server. C’est à partir de cette valeur que la connexion cherchera a être établi

OLLAMA_PORT : Prend en paramètre en entier de type Integer. Il s’agit du port sur lequel l’API est publiée. Par défaut la valeur est 11434

FROM : Prend la valeur une chaine de caractère de type String. Va contenir l’adresse de l’émetteur. Dans la logique, j’aime à utiliser le nom du serveur ou du rôle, par exemple srv-task01@contoso.com

TO : Prend la valeur une chaine de caractère de type String. Va contenir l’adresse du destinataire qui doit recevoir le mail. Dans la logique, préférer une LD5 ou une BAL6 partagée pour que l’information et la responsabilité ne soit pas porter que par un individu

SERVERNAME : Prend la valeur une chaine de caractère de type String. Le nom du serveur qui fait relai SMTP, pour plus de sécurité, renseigner le FQDN7 en lieu et place d’une IP

PORT : Prend la valeur une chaine de caractère de type String. Préciser le port d’écoute du serveur SMTP. 25, 587, 465. Libre à chacun

J’ai pris en compte la possibilité d’éditer directement le fichier de configuration que ce soit depuis l’interface graphique ou depuis l’interface console. Par sécurité et comme toujours j’ai repris ma fonction de régénération automatique du fichier de configuration en cas de suppression ou de corruption de ce dernier. Encore une fois, j’en ai eu marre de me repalucher le fichier de conf à la mano… Comme ça nous sommes pénards !

Il n’y a en aucun cas besoin d’installer ou d’ajouter des dépendances. L’application a été pensé pour être native (en dehors de Linux naturellement, mais je reviendrai sur ce point dans la sous partie à venir).

Je pense que nous avons maintenant une pleine compréhension du fichier de configuration, nous pouvons passer à l’installation de l’application.

Installation

L’installation sera dissociée en deux parties. Une partie Windows et une partie Linux.

Dans les deux cas, si le serveur OLLAMA n’est pas joignable ou disponible, l’application sera fermée ou l’utilisateur sera invité à réaliser cette opération. Point important que je me devais de souligner.

Réaliser un copier-coller de l’ensemble de l’architecture dans un répertoire. Au pif, ZelenZajac #mainsurlecoeur

Pour des raisons de contrainte lié à la bibliothèque WindowsForms, l’application GUI ainsi que son installation se fera sous Windows. Et par logique, l’application et son installation CLI se fera sous Linux, même si vous êtes libre d’utiliser et d’installer l’application CLI sous Windows (je ne suis pas psychorigide hein ?).

J’ai pour habitude sur les environnements Windows Server de dédier un répertoire scripts sur un disque dédié avec des privilèges strict.

Dans ce cas précis, nous sommes dans un usage utilisateur. Donc il faut s’attendre à ce que celui-ci soit utilisé par un utilisateur (C’est d’une logique déconcertante, je me surprends moi-même). Le script peut être stockées sur le bureau ou dans les documents. Autrement dit dans le profil de l’utilisateur. Un partage réseau pourrait être intéressant, mais dans le cas d’un usage multiple cela pourrait générer des dysfonctionnements (et surtout je n’ai pas testé et envisagé ce mode de fonctionnement).

Lancer le script SS_045_1.0.2_Ollama-GUI_Main.ps1 pour réaliser les opérations d’initialisation et vérification des dépendances.

Une question qui je dirai jusqu’à présent ne faisait plus trop débat. Linux ou Windows ? La guerre ! reprend de plus belle avec la hausse du cout des licences 365, le côté gourmand de Windows 11 et l’obsolescence matériel…

Toutefois, Windows offre depuis Windows 10 (je ne suis pas sûr pour W7 ou W8) la possibilité d’émuler un système UNIX dans son OS8. Il s’avère également qu’il est possible sous UNIX d’utiliser les commandes powershell CORE. Et ça je trouve ça cool de voir qu’officiellement les deux familles se rapprochent <3

Donc pour commencer il va falloir installer powershell sur notre environnement linux.

Puis nous installons le package powershell.

Naturellement et ça va de soi, si votre version est RHEL9 8 ou 10 vous ajouter la bonne version de votre répo… Vous adaptez l’url en conséquence. Non parce que je vois déjà certains lecteurs hurler au scandale.

« Ca fonctionne pas, c’est de la merde… [Autres noms d’oiseaux]« 

Pour démarrer powershell, il suffira de taper la commande pwsh.

Mais revenons à notre projet. De manière sécurisé, nous allons déposer notre répertoire projet dans notre /home/john.doe/ via un client sftp10 (pour ma part WinSCP).

Il va être nécessaire d’installer un petit paquet pour convertir nos scripts qui sont au format dos en au format unix (et oui, j’ai développé sur windows…).

Maintenant, nous sommes parés pour lancer le script.

Simple non ? C’est maintenant l’heure de vous présenter en détail les interfaces 🙂

Présentation

Dans les deux cas, je vais présenter l’ensemble des options.

Il sera plus facile de suivre la description du mode CLI de par son côté procédurale. La présentation du mode GUI lui sera présenté comme suit, d’abord l’interface générale puis les différentes fenêtres et boutons.

GUI sous Windows

Interface Principale

Au lancement de l’application, un test de communication au serveur OLLAMA est réalisé. L’interface graphique va être adapté selon le résultat retourné.

Server UnreachableServer
Reachable


Dans la colonne de gauche, nous sommes dans le cas où le serveur OLLAMA n’est pas disponible (peu importe la raison. Il n’est pas là, T’es là ou T’es pas là ?). L’application se lancera tout de même mais avec aucune possibilité d’action. Contactez votre administrateur <3

Dans la colonne de droite, l’application se lance sans problème. Ce qui signifie que la connexion au server Ollama a été effectué et que les LLMs11 déployés ont pu être récupérés et ce de manière automatique et dynamique. Ces derniers sont chargés dans la liste déroulante. Il est nécessaire de choisir un modèle pour soumettre un prompt.

Il est important de comprendre et pour rappel de la partie théorique que nous avons 3 types d’appel API selon le prompt que nous allons soumettre à OLLAMA.

  • Standard : C’est le mode par défaut. Une fois l’application démarrée et un modèle choisi, vous pouvez soumettre un prompt à OLLAMA.
  • Image : Ce mode nécessite de fournir une image. Cette même image va être converti en base64 afin d’être soumis à OLLAMA. Il est recommandé d’utiliser le modèle llava pour traiter les flux numériques. Naturellement, si le chemin d’une image est renseigné, il n’est pas possible de choisir un fichier.
  • File : Ce mode nécessite de fournir un fichier. Il est alors nécessaire de lire le contenu de cet élément et d’ajouter ce dernier à la suite du prompt. Le point de difficulté réside dans le traitement des fichiers .pdf qui doivent être converti en amont. Fonctionnalité que je n’ai pas traité pour l’instant. Comme pour le mode image, si le chemin d’un fichier est renseigné, il n’est pas possible de choisir une image.

Dans les deux cas afin de faciliter la saisie des chemins d’accès aux items (image ou document) j’ai mis en place l’ouverture de l’explorateur de fichier.

PicturesFiles

Il suffira alors de saisir notre prompt dans le champ prévu à cet effet.

Pour soumettre la requête à notre serveur OLLAMA nous allons devoir passer par les triggers, autrement dit par des événements sur des boutons 🙂

L’action sur ce bouton a pour effet de soumettre la requête saisie par vos soins au serveur OLLAMA en prenant en compte l’ensemble des options et paramètres défini précédemment.

Toutefois, il y a un certain nombre de contrôle :

  • Le TextBox spécifique au prompt ne doit pas être vide
  • Les CheckBoxs spécifique aux choix avancés d’analyse d’image ou de fichier ont elles été cochées ?
    • Les chemins ont-ils une valeurs
  • Le modèle d’IA a-t-il été défini

Bref, autant de contrôle pour s’assurer de ne pas fournir une requête vide au serveur OLLAMA et faire travailler ce dernier inutilement.

Personnellement vous aimez travailler pour des noix sur une décision absurde de votre N+1 ? Je crois que personne n’aime bien ça hein <3

Une fois l’action sur le bouton effectué, un petit message discret « Searching » apparait et vous fait savoir que le travail est en cours.

Avec GPUSans GPU


Vous n’avez pas trop a attendre


Va falloir être patient et ne pas être trop pressé

Bref, au final vous arriverez à ça… C’est cool non ? 🙂

L’action sur ce bouton a pour effet de sauvegarder votre requête au format .txt.

Il y a aussi des conditions sur ce bouton. Il faut que les TextBoxs dédiés à OLLAMA (prompt et answer) ne soient pas vide ou null. Sinon nous sauvegarderions du vent…

N’étant pas sadique, cela va ouvrir une nouvelle fenêtre d’explorateur windows pour sauvegarder votre fichier. Ce dernier contiendra l’heure de l’exécution de votre requête, votre prompt ainsi que la réponse retourner par le modèle présent dans OLLAMA.

L’action sur ce bouton a pour effet d’envoyer par mail le résultat de requête.

Comme pour le bouton de sauvegarde précédent, les conditions sur ce bouton sont les mêmes. Il faut que les TextBoxs dédiés à OLLAMA (prompt et answer) ne soient pas vide ou null. Sinon cette fois ci, nous enverrons du vent…

Un axe d’amélioration serait de prendre en compte des adresses mails multiples. Je garde ça sous la main 🙂

L’action sur ce bouton est soumise à une seule condition de contrôle. Le fichier de configuration doit exister sous le chemin par défaut.

Je me suis dit que ça serait bien de permettre à l’usager de pouvoir modifier le fichier de configuration directement depuis l’application. Attention, car cela ne modifie pas la configuration du code en cas de régénération du dit fichier.

Peux être qu’une fonctionnalité d’export du fichier de configuration pourrait être sympa 🙂

Le bouton debug sert au debug et pour cela je laisse la parole à la sous parti suivante 🙂

Interface Debug

Cette interface permet de lister les interfaces et les services de notre serveur OLLAMA. Naturellement, j’ai poussé le vice un peu plus loin. Si je test le port OLLAMA et le port du server SMTP, j’ai ajouté un petit bonus en plus. En lien avec l’article OpenWeBUI, je test les ports 8080 et 443 en dur.

Je verrai plus tard s’il y a un intérêt à ajouter ou non ces paramètres dans le fichier de configuration.

Bref, cela permet de vérifier les communications et les interfaces de nos différents serveurs.

UnavailableAvailable
Interface About

Que serait-ce une application sans un petit About ? Histoire de laisser son nom à la postérité ? D’un côté c’est de l’orgueil, de l’autre, il me parait normal comme un artiste de signer son art non ?

D’ailleurs, est ce que développeur n’est-il pas un métier de création et donc d’art ? Voyez-vous, je suis une b*te en dessin, un musicien médiocre. Par contre, j’ai des idées de dev et je trouve que ce que je faisais et fais commence à avoir de la gueule non ? Une question qui selon moi ouvre au débat.

Bref, depuis la barre de menu, Help > About et vous retrouverez les informations de notre application. D’ailleurs cela me fait penser que je n’ai pas mis/caché d’Easter egg…

CLI sous Linux (et Windows)

Après réflexion, je vais afficher les captures sous les deux environnements à des fins de comparaison. Mais je mets l’accent sous l’environnement UNIX.

La présentation se fera menu par sous-menu. Je vous renvoie à la partie théorique quant au cycle de vie, algorithme et pseudo code.

Interface Principale

Hormis la banner gigantesque pour marquer les esprits, nous retrouvons un choix de navigation de 6 parties.

Pourtant moi j’en compte 5. Tu sais compter ?

Oui, je vous remercie de vous inquiéter de mon niveau mathématique. Je sais compter et le 6eme choix n’apparait que sur une condition spécifique. 🙂

LinuxWindows

Regardons ce que nous offres les possibilités de navigation :

  • [1] Select LLM : Permet de sélectionner un modèle de moteur IA installé préalablement sur le serveur OLLAMA
  • [2] Prompt Type : Permet de choisir le type de requête que nous souhaitons soumettre Image, Fichier ou simple prompt
  • [3] Settings : Permet d’éditer le fichier de configuration directement depuis la console CLI
  • [4] Tropubleshooting : Permet de lancer un mode debug
  • [5] About Zelen Zajac : Permet d’afficher les informations de l’application
  • [6] Launch Ollama Request : Permet de soumettre un prompt au serveur OLLAMA si et uniquement si un LLM a été préalablement sélectionné.
  • [0] Quit : Pour sortir de l’application proprement et non à la hussard à grand coup de Ctrl+C…
Sélection du LLM

Comme pour l’application GUI, si la connexion au serveur OLLAMA est établi, l’ensemble des modèles présents sur le serveur sont automatiquement listés. Il suffit alors à l’utilisateur de choisir le modèle qui correspond à prompt qu’il souhaite soumettre.

LinuxWindows

Il est important qu’il ne soit pas possible de revenir en arrière. Le dernier choix et le choix qui fait foi. Une fois le moteur sélectionné, cela affichera l’option 6 pour soumettre une requête au serveur OLLAMA.

Sélection du type de prompt

Par défaut et pour éviter toutes erreurs, le type de prompt est défini sur Standard. Toutefois et comme pour l’interface GUI, il sera nécessaire dans la sélection des modes Image ou Document de préciser le chemin des dits éléments à soumettre au serveur.

LinuxWindows
LinuxWindows
LinuxWindows

Si dans le mode GUI j’assiste l’utilisateur avec un explorateur de fichiers pour trouver l’élément, il faudra connaitre ici le chemin de tête. Cela pourra je pense faire office d’une fonctionnalité futur.

En toutes circonstances, il y aura un contrôle des chemins par la suite afin de s’assurer de ne pas charger un élément existant.

Settings

Selon la nature de l’OS, la modification du fichier de configuration ne se fait pas de la même manière.

LinuxWindows

Depuis un terminal (donc pour Linux), il est nécessaire de forcer l’interactivité depuis un client SSH. Sans quoi nous sortons du script, ça plante et nous générons un fichier temporaire. Utilisateur de vim et donc de vi j’ai choisi cet éditeur de texte. Toutefois, je pourrais implémenter la possibilité de choisir entre nano et vi dans le fichier de configuration.

Côté Windows, nous sortons comme pour Linux de ce côté agnostique. Powershell Core, gère dans un processus à part et hors terminal l’application notepad.exe. Nous aurons donc une interface graphique qui s’offre à nous.

Il faudra alors jouer des combinaisons :

  • Linux
    • vim : esc puis :x!
    • vi : esc puis :x!
    • nano : Ctrl+x
  • Windows
    • notepad : Ctrl+s

/!\ Attention : Comme pour le mode GUI je ne modifie pas la configuration dans le code dans le cas de la régénération du fichier de configuration en cas d’altération de ce dernier.

Troubleshooting

Cette sous-interface permet de vérifier si l’interface ou les interfaces de notre serveur OLLAMA et autres serveurs sont bien accessible.

LinuxWindows

Il est important de comprendre qu’il peut y avoir de multiples pour qu’un protocole ou une ressource ne soient pas joignables. Cela peut résulter :

  • Firewall interne au serveur
  • Firewall externe si segmentation des LANs
  • Mauvais paramétrage du SELinux
  • Résolution DNS impossible
  • etc.

Je vous recommande de contacter votre administrateur. Si l’administrateur c’est vous, je vous recommande de vous retrousser les manches ou de changer de métier. Elever des chèvres en Ardèche c’est pas mal aussi 🙂

Pour le fun, j’ai ajouté en dur dans le code, le contrôle des ports 8080/tcp et 443/tcp qui sont les ports de mon daemon OpenWebUI. A voir si cela doit être amélioré ou non.

About

Ce sous menu n’est présent que pour afficher mon nom et laisser ce dernier à la postérité. Et aussi et surtout pour afficher la date de dernière publication de la version.

LinuxWindows

C’est peut-être un détails pour vous, mais pour moi ça veux dire beaucoup !

Launch Ollama

Nous voilà enfin dans le vif du sujet. Bon, je ne vais pas trop m’étendre sur le sujet car cela sera présenté dans la Partie 3 Démonstration. Je présenterai que de manière succincte les étapes du mode standard comme j’ai pu le faire plus haut pour le mode graphique.

Naturellement il faut au préalable avoir sélectionner un modèle de moteur IA et selon le besoin le type de prompt que nous souhaitons soumettre.

Lors de la soumission de la requête, j’ai décidé d’exécuter la tache en dehors du programme principale afin de ne pas bloquer ce dernier durant la soumission de notre requête au serveur OLLAMA.

LinuxWindows

J’ai également ajouté une barre de progression afin d’informer l’utilisateur que le travail est en cours. Pas bête hein ?

Après un moment d’attente toujours pour les mêmes raisons d’absence de GPU, la réponse s’affiche dans le plus beau moment anthropique <3

LinuxWindows

Cela peut étonner, mais l’ensemble des fonctionnalités proposées dans l’application graphique sont présentes dans l’application CLI.

La seule nuance, il n’est pas possible pour l’instant de modifier l’emplacement de sauvegarde des requêtes en mode CLI. Ces dernières se retrouveront dans le répertoire export à la racine du répertoire.

LinuxWindows

Nous retrouvons naturellement le modèle LLM, la date, le prompt, la réponse.

Voilà que je viens me contredire avec mes écrits précédents. Il y a pour l’instant une fonctionnalité qui m’échappe. L’envoi de mail.

Déjà et même si j’ai modernisé ma fonction d’envoi en prenant compte de l’obsolescence Microsoft, l’usage de la bibliothèque [System.Net.Mail.MailMessage] et [System.Net.Mail.SMTPClient] ne fonctionnent pas sur Linux.

Je pourrais développer et utiliser mon script bash pour passer par MUTT. Mais voilà je souhaite garder et aboutir à un script 100% agnostique Linux <-> Windows en powershell donc il est urgent de ne rien faire.

Tout ça pour dire qu’il n’est pas possible d’envoyer un mail sous Linux…

LinuxWindows

Toutefois, rien ne vous empêche de faire un bash avec un cron sur présence d’un fichier dans le répertoire pour faire un envoi automatique. Cela reste de la bidouille, mais dans certains cas cela peut être vu comme une méthode de contournement.

Donc, si je résume sous Linux cela nous donne avec toutes les étapes :

Pour se faire une idée, je vous renvoie à la partie 3 démonstration. Dans une vidéo, je vais traiter des deux modes de mon application.

GitHub

Miaou

(Uniquement sur contact LinkedIn)

Je souhaite vraiment échanger avec vous et vous fournir le lien privé du projet. Ainsi je pense que recueillir vos avis, retours peuvent me permettre de faire évoluer l’application dans le bon sens.

Partie 1 : Théorie
<-
PROJET – Zelen ZajacPartie 3 : Démonstration
->

  1. GUI : Graphical User Interface ↩︎
  2. CLI : Command Line Interface ↩︎
  3. API : Application Programming Interface ↩︎
  4. SMTP : Simple Mail Transfert Protocol ↩︎
  5. LD : Distribution List ↩︎
  6. BAL : Boite Aux Lettres ↩︎
  7. FQDN : Fully Qualified Domain Name ↩︎
  8. OS : Operating System ↩︎
  9. RHEL : RedHat Entreprise Linux ↩︎
  10. SFTP : Secure File Transfert Protocol ↩︎
  11. LLM : Large Language Models ↩︎