|

PROJET – Zelen Zajac, Ollama Client IA Partie 1 : Théorie

Expression du besoin

Comme nous avons pu le constater et l’étudier dans le précédent article, il existe des solutions qui s’interfacent très bien avec OLLAMA, par exemple la solution OpenWebUI qui propose une interface web depuis un navigateur.

Toutefois, si je souhaite ne pas utiliser de solution orienté serveur pour des raisons de ressources restreintes et ou de cout financier, la présence d’une API1 sur OLLAMA change la donne.

Je souhaiterai donc mettre en place une solution agnostique simple d’utilisateur qui permettrait à un ou plusieurs utilisateurs de soumettre des requêtes à notre service interne OLLAMA le tout de façon sécurisé. Si possible cette même solution doit être compatible pour les environnements Windows et Linux.

Pourquoi d’ailleurs ?

Les couts d’usage et d’acquisition des produits Microsoft s’oriente de plus en plus vers un modèle rental et non plus permanent ce qui sur le moyen et long terme peut vite devenir insupportable sur le plan financier. De plus la consommation des ressources de calcul des ordinateurs à usage professionnelle souffre d’obsolescence matérielle difficilement justifiable. Certaines organisations ont fait le choix de se tourner vers des distributions GNU/Linux professionnel. Donc cela justifie je pense l’argument d’une solution agnostique Windows et Linux 🙂

Bref, au-delà de ça, il faudrait avoir une solution qui puisse être évolu’tif (tiens, cela pourrait être un excellent nom pour un salon de coiffure) dans le temps et qui assurerait un minimum de fonctionnalité que nous pouvons retrouver dans des solutions qui ont pignons sur rue :

  • Export des résultats
  • Envoi des résultats par mail
  • etc (comprendre à détailler)
Surtout et encore une fois avoir une solution simple et sexy. Sinon les utilisateurs ne l’utiliseront pas.
Vous avez dit Sexy ?

Cahier des Charges

Bien, maintenant que nous avons les plans en main, passons à notre checklist pour construire tout cela.

Attention, toujours sans se laisser entrainer par se bon vieux White Rabbit un peu trop adeptes des Jeffersons Airplaine, sinon c’est le bad trip assuré et notre application va pas bien ressembler à grand-chose.

Et bien sachez que pour une fois, j’ai été discipliné. J’ai ces derniers mois eu le temps de reposer mes petites cellules grises et de prendre du recul 🙂

Quel langage vais-je utiliser ? Pour rappel, il faut que ce dernier soit agnostique au SE2 Windows et Linux pour faciliter la gestion de l’application. Je propose d’utiliser Powershell dans sa version 5.

  • Ce choix est motivé par la présence par défaut de cette version sur tous les postes utilisateurs Windows (à ce moment de rédaction de ce billet) et ce dernier est compatible avec Powershell 7
  • Il est possible d’exécuter du code Powershell sous Linux sans à avoir à faire de la bidouille car cela est officiellement supporté, maintenu et mise à disposition par Microsoft
  • Nous pouvons faire des interfaces graphiques et CLI3 donc il y a la possibilité de faire quelques choses de sexy <3. Attention à vérifier la compatibilité de certaines bibliothèques .Net et propre au SE Windows

Comme nous utilisons OLLAMA, je reste sur mon serveur préalablement en production ainsi que les modèles déployés précédemment. Toutefois, il serait bien de pouvoir prendre en compte les nouveaux modèles qui peuvent être amener à être déployer ou mis à jour de manière dynamique.

Pour l’instant, il n’est pas prévu dans l’expression du besoin de mode service donc pas d’utilité de développer un mode ou script dans ce sens. Toutefois, en termes de configuration il serait utile d’avoir un fichier que l’utilisateur puisse modifier ou au mieux l’équipe IT4.

L’exploitation des résultats se fera visuellement dans la console ou l’interface graphique. Nous offrons la possibilité à l’utilisateur d’exporter, sauvegarder le résultat du prompt qu’il a soumis au format TXT5 ou HTML6. Naturellement, il pourra également envoyer ce même résultat par mail.

Concernant l’aspect sécurité, l’application ne nécessitera pas d’élévation de droits d’administration quant à son utilisation. Son usage étant uniquement sur le LAN7, le trafic en HTTP8 sur le port par défaut est toléré. Toutefois, je recommande de communiquer en HTTPS9. La présence du mode Debug est de la possibilité de rediriger l’ensembles des transactions du script dans un fichier permette au-delà du débogage de garder une trace des exécutions.

En conclusion, notre liste de course pour notre application :

  • Langage de développement & Fonctionnalités
    • .NET Framwork à travers Powershell (v5 ou plus)
    • Journalisation de l’exécution du code
    • Export des données en TXT et HTLM
    • Envoie des données par mail
    • Fichier de configuration
    • Mode GUI10 (pour Windows)
    • Mode CLI (pour Windows et GNU/Linux)
  • Sécurité
    • Ne nécessite pas d’élévation de privilège
    • Connexion uniquement sur le LAN (HTTP ou HTTPS)
    • Pas d’authentification à l’API nécessaire

Il est temps de passer à la construction et définissions de nos différents niveaux de topographie d’architecture, applicative et logiciel.

Topographie – Infrastructure

Topographie – Applicative

Encore une fois, je ne suis toujours pas architecte d’application, mais je commence à bien mettre à jours mes restes. C’est bien en forgeant que l’on devient forgeron 🙂

A la racine du répertoire, nous retrouvons les deux fichiers exécutables :

  • SS_045_1.0.2_Ollama-CLI_Main.ps1 : Qui est le fichier d’instanciation de la solution est qui permet également de réaliser toutes les actions en mode manuel que ce soit sur les environnements Windows ou Linux.
  • SS_045_1.0.2_Ollama-GUI_Main.ps1 : Presque le même fichier que le fichier précédent mais dont l’usage est uniquement réservé aux environnements Windows de par son interface graphique.

Si nous regardons en détails les sous répertoires :

  • _archives : Qui est plus ou moins la poubelle du projet dans lequel je garde l’historique des scripts et modules ayant évolués
  • config : Répertoire contenant le fichier de configuration powershell. Afin de palier à toute suppression malencontreuse du fichier de configuration, j’ai développé une fonction pour regénérer ce dernier. Etant un adepte du Alt+Maj+Del, j’ai dû réécrire un certain nombre de fois mon fichier.
  • export : Répertoire qui va contenir les résultats au format texte ou html. Par défaut, en mode CLI les données sont automatiques stockées dans ce répertoire. A l’inverse le mode GUI offre plus de flexibilité et il est possible de choisir dynamiquement un autre emplacement.
  • log : Répertoire qui va contenir la ou les traces d’exécution du code si l’option est activée. Cela à son importance car il permet au petit gars qui à dev l’application dans sa baignoire de corriger les bugs. Le fichier ne prend pas de place et est réinitialiser à chaque lancement.
  • modules : Répertoire contenant les modules powershell développé pour l’application. Aujourd’hui au nombre de trois dissociant la partie OLLAMA, System et HTML.
  • sources : Répertoire qui contient les éléments et dépendances de l’application hors code. Les images, icônes etc.

Cette arborescence est valable pour la version 1.0.x pour l’instant. Cette dernière pourrait être amené à évoluer dans une version mineure ou majeure dans le cas d’implémentation de nouvelle fonctionnalité ou de refactorisation, optimisation de code.

Topographie – Logiciel

Avec cette magnifique transition, parlons peu mais parlons bien. Contrairement aux projets précédents, j’ai repris par nostalgie une approche par logigramme comme à la bonne vieille époque de mon BTS11 IRIS12.

L’approche reste classique dans la phase de développement. Une approche modulaire, unitaire puis la phase d’intégration et d’ajustement et correction.

Naturellement avant de faire de la GUI tout part de la CLI en termes de logique et de fonctionnement.

Le programme est plutôt simple. Ce dernier se décompose en une succession de vérification avant de permettre une interaction de la part de l’utilisateur.

L’utilisateur aura si le serveur OLLAMA est joignable la possibilité d’exécuter l’un des 6 sous-processus suivants :

* Sélectionner un modèle LLM. Sans exécution de cette option il ne sera pas possible d’exécuter de soumettre un prompt à OLLAMA.

* Sélectionner le type de prompt. Par défaut, les requêtes qui seront adressé à OLLAMA ne seront que du texte. Pour interagir avec une image ou un document il faudra changer de mode.

* Settings permet d’afficher le fichier de configuration et de pouvoir modifier ce dernier directement et de sauvegarder les modifications.

* Debugging. Permet de vérifier les connexions avec les différents services SMTP, OLLAMA, OpenWebUI.

* About affiche le numéro de version ainsi que le crédit de l’application

* Start Ollama permet de saisir une requête à soumettre à notre serveur OLLAMA. Il faut préalablement avoir choisi un modèle de moteur IA. Sans cela, l’option n’apparait pas et ne peut être lancé. 13Le programme est plutôt simple. Ce dernier se décompose en une succession de vérification avant de permettre une interaction de la part de l’utilisateur.

L’utilisateur aura si le serveur OLLAMA est joignable la possibilité d’exécuter l’un des 6 sous-processus suivants:

* Sélectionner un modèle LLM. Sans exécution de cette option il ne sera pas possible d’exécuter de soumettre un prompt à OLLAMA.

* Sélectionner le type de prompt. Par défaut, les requêtes qui seront adressé à OLLAMA ne seront que du texte. Pour interagir avec une image ou un document il faudra changer de mode.

* Settings permet d’afficher le fichier de configuration et de pouvoir modifier ce dernier directement et de sauvegarder les modifications.

* Debugging. Permet de vérifier les connexions avec les différents services SMTP, OLLAMA, OpenWebUI.

* About affiche le numéro de version ainsi que le crédit de l’application

* Start Ollama permet de saisir une requête à soumettre à notre serveur OLLAMA. Il faut prélablement avoir choisi un modèle de moteur IA. Sans cela, l’option n’apparait pas et ne peut être lancé.

Je propose de voir chacun des logigrammes des 6 sous processus.

La récupération des différents LLMs installé sur notre serveur OLLAMA se fait par le biais d’un appel API (d’où la vérification en amont de la disponibilité du serveur -_-‘).

Une fois les modèles, récupéré, nous les affichons dans une boucle. L’utilisateur est obligé de sélectionner un modèle. Il n’a pas la possibilité de quitter ce traitement. La condition pour quitter la boucle est de définir une valeur à 100. Condition qui ne peut être atteinte que si un modèle est sélectionné 🙂

Sinon c’est l’infinite loop !
Par défaut, le mode de prompt est défini sur Standard. Le type de prompt n’étant pas cruciale pour soumettre une requête, il n’y a pas lieu de forcer l’utilisateur à choisir un type comme pour le LLM.

Si l’utilisateur choisi un type de prompt Files ou Pictures, il devra saisir le chemin complet de l’élément.

Si l’utilisateur à les doigts palmés alors un message d’erreur s’affichera et le mode standard sera forcé.
Normalement il n’y a pas lieu que notre fichier de configuration soit absent puisqu’il a été vérifié et au besoin regénéré. Mais admettons que quelqu’un l’ait supprimé entre temps ça serait fâcheux (je pense à un AV par exemple ou autre MDR, XDR et j’en passe).

Les éditeurs de texte étant différents entre Linux et Windows, nous ne pouvons pas faire de générique. Il est donc nécessaire de déterminer la nature de l’OS et d’appeler l’éditeur de texte.

Il y a toutefois quelques spécificités pour l’appel de l’éditeur de texte sous Linux et je reviendrai sur ce point dans la partie Sécurité.
Là pour le coup c’est basique de chez basique et je n’ai pas voulu expliquer ma fonction de vérification de port (cf module SS_045_1_System_Network.psm1).

Je vais vérifier à partir des éléments présents dans le fichier de configuration la disponibilité du serveur OLLAMA (11434/tcp14) et du serveur SMTP (25/tcp). En bonus je vérifie en dur dans le code la disponibilité du serveur OpenWebUI (8080/tcp ou 443/tcp). OpenWebUI est purement optionnel. Son état n’a aucun impact sur le script.
Le plus complexe des logigrammes à comprendre…

Enfin quelque chose de plus intéressant. Attention, le logigramme commence à devenir un peu plus complexe. La présentation en tableau est totalement exclue… 🙂

Et en plus le type, ça le fait marrer… Cinglé va ! Tu dis que ça t’amuse en plus de faire ça ? Pour ceux qui vont des logigrammes par plaisir, la peine de mort !

Le logigramme se comprend plutôt bien, je ne vais donc pas décrire le début et la fin du script. Ce qui m’intéresse ici et que je vais développer dans la partie sécurité est l’usage du tache parralèle.

Sans rentrer plus en détail que ça, sans utilisation d’un ScriptBlock notre script va freezer le temps de l’exécution de la requête vers notre serveur OLLAMA. Franchement se taper dans un terminal un « Not Respond » c’est moche. D’où l’utilisation d’une barre de progression pour indiquer à l’utilisateur que le serveur travaille.

Second point important, si nous regardons plus en détail la partie dédiée à l’envoi de mail si le SE est un Linux, nous affichons un message et nous n’envoyons pas de mail. Effectivement et je dirai que c’est pour le moment la seule fonctionnalité qui n’est pas reprise.

Donc pas si agnostique que ça ton outil ?

Je pourrais passer par MUTT par exemple. Mais c’est se compliquer la vie. Le contrôle et le paramétrage des dépendances externes dans le script serait juste un travail dantesque. Toutefois vous pouvez si vous le souhaitez tester 🙂 (sous réserve, spoiler alerte de me contacter au préalable #bisou)

Tout ce cirque parce que [System.Net.Mail.MailMessage] et [System.Net.Mail.SmtpClient] sont pour l’un déprécié et mal reconnu sous Linux…

Bon pas si compliqué que ça 🙂 J’avoue que je suis un peu rouillé en logigramme, mais ça fait du bien par nostalgie de revenir aux bases. Au moins, vous avez ma logique.

Sécurité

Authentification

Admettons que nous devons nous authentifier à l’application OLLAMA où via Nginx, il va de soi que je ressortirai ma méthode devenu un standard chez moi en passant par le CLIXML.

Je garderai naturellement la possibilité de s’authentifier manuellement et également la possibilité de s’authentifier automatiquement en chiffrant le mot de passe via les algorithmes de chiffrement Windows 🙂 Toutefois reste à savoir si cette fonctionnalité est agnostique. A creuser…

Communication

Dans la version 1.0.x l’ensemble des communications entre le client et le serveur sont établies via le protocole http. C’est pas ouf hein ?

Sans surprise, les informations sont en claire dans les trames.

Dans les versions à venir en 1.1.x je pense les échanges via le protocole https. Ce qui est plus propre, néanmoins, il est nécessaire de prendre en compte le cas de figure des certificats autosignés et ça c’est un poil plus pénible en powershell version 5.

En reprenant le port 11444/tcp dédié à la publication d’OLLAMA via le protocole https, il n’y alors plus de doute quant aux tests effectués. Reste plus qu’à implémenter cela.

Parallélisation

Nous parlons beaucoup de sécurité en oubliant d’aborder la sécurité du code, la sécurité logicielle. Dans le cas d’un programme itératif (étape par étape) la sécurité se résume souvent qu’à la gestion des erreurs.

Toutefois dans des programmes qui commencent à établir des connexions ou réaliser des tâches en parallèle du déroulement du programme principal, cela fait comme je l’ai dit plus haut « tâche » de se taper un « Program Not Respond » ou un truc du genre.

Cela va être notre cas. Nous allons soumettre notre requête auprès de notre serveur OLLAMA puis attendre sa réponse. J’ai choisi de recevoir l’intégralité de la réponse et non pas de recevoir la réponse json segmenté, fragmenté.

Vous l’aurez compris, il va donc être nécessaire de réaliser une tâche parallèle. La grosse difficulté de la manipulation entre la tache mère et fille relève encore et toujours dans la portée des variables. Ce qui peut vite décourager des novices.

Pour expliquer et illustrer le principe :

  • Création d’un ScriptBlock : Dans notre script nous définissons une variable qui contient des paramètres et un traitement.
  • Appel de la tâche : Nous récupérons l’état de la tache dans une variable en fournissant en paramètre le code ainsi que les paramètres stockés dans les variables précédents. Il suffira ensuite de jouer avec les différents états de la tâche. Et surtout on n’oublie pas de faire le ménage ! Bande de salopi**d 🙂

Dans le cas du script en interface graphique, la méthode diffère légèrement, mais reste la même. Il faut juste prendre en compte les objets graphiques.

Dépendances

J’ai voulu m’affranchir d’un maximum de dépendance et d’avoir une application « Vanilla » qui puisse être exécutée depuis n’importe quel système sans à avoir à monter une usine à gaz. Donc pas de dépendances, si vous avez besoin d’un relai SMTP, il relève alors d’une problématique standard à n’importe quelles applications à ce jour.

Je pense que nous avons fait le tour de l’ensemble théorique. Et il est temps de passer à la partie pratique. Il va toutefois être difficile d’être cohérent dans le temps car la solution est amenée à évoluer et donc il faudrait que je garde à jour l’ensemble du billet. Là est ce que ça sera toujours un loisir ? Eprouverais je toujours du plaisir ?

To Be Continued… 🙂

PROJET – Zelen ZajacPartie 2 : Pratique
->

Sources

  1. API : Application Programing Interface ↩︎
  2. SE : Système d’Exploitation ↩︎
  3. CLI : Command Line Interface ↩︎
  4. IT : Information Technology ↩︎
  5. TXT : Texte ↩︎
  6. HTML : HyperText Markup Language ↩︎
  7. LAN : Local Area Network ↩︎
  8. HTTP : HyperText Transfer Protocol ↩︎
  9. HTTPS : Secure HyperText Transfer Protocol ↩︎
  10. GUI : Graphic User Interface ↩︎
  11. BTS : Brevet de Technicien Supérieur ↩︎
  12. IRIS : Informatique et Réseaux pour l’Industrie et les Services techniques ↩︎
  13. LLM : Large Language Model ↩︎
  14. TCP : Transmission Control Protocol ↩︎