Introduction

Ce projet est un serveur centralisé d’intelligence artificielle conçu pour être exécuté sur un réseau local (LAN). Il permet aux autres machines du réseau d’envoyer des requêtes vers des modèles d’IA (LLM, Génération d’images, Vision) de manière asynchrone, grâce à une file d’attente FIFO persistante (SQLite).

Fonctionnalités Principales

Dashboard Web Complet

Le serveur intègre une interface web riche et ergonomique accessible directement via votre navigateur :

  • Agencement dynamique : 3 panneaux redimensionnables (Requête, Résultat, File d’attente).
  • Monitoring Matériel : Affichage en temps réel du CPU, RAM, GPU (utilisation et VRAM) et des températures.
  • Mode Conversation (Mémoire) : Permet de conserver le contexte de la discussion avec le LLM.
  • Support Multimodal & Fichiers :
  • Upload d’images pour LLaVA (Vision) ou Stable Diffusion (Img2Img).
  • Bouton ou « Glisser-Déposer » pour intégrer rapidement un script (.py, .js, etc.) ou un fichier texte dans votre prompt.
  • Historique et Favoris : Gardez une trace de vos anciennes générations, mettez vos meilleurs résultats en favoris (⭐) et purgez le cache facilement.
  • Confort de lecture : Coloration syntaxique automatique du code généré, boutons « Copier le code », bouton « Télécharger en .txt », et choix du Thème (Clair ☀️ / Sombre 🌙).
  • Raccourcis : Soumission rapide via Ctrl+Entrée.

Backend & API

  • API REST robuste propulsée par FastAPI.
  • File d’attente FIFO gérée par un worker en arrière-plan avec persistance SQLite (auto-migration incluse).
  • Ollama Intégré : Exécution de LLM locaux en streaming simulé, sans limite stricte de tokens générés.
  • SDK Client Python pour une intégration facile dans vos propres scripts.

Installation

Prérequis

  • Python 3.10+
  • Ollama installé localement et en cours d’exécution.
  • Les modèles LLM téléchargés via Ollama (ex: ollama run llama3).

Dépendances

pip install -r requirements.txt

(Note : le premier appel au modèle d’image téléchargera les poids volumineux depuis HuggingFace).

Démarrage du serveur

Lancez simplement le fichier principal :

python main.py

L’application web et l’API seront accessibles sur : http://127.0.0.1:8000
(N’oubliez pas d’autoriser le port 8000 ou le binaire Python dans le pare-feu de Windows pour y accéder depuis le réseau).

Utilisation via le SDK Python

from ai_client import LocalAIClient

client = LocalAIClient(endpoint="http://127.0.0.1:8000")

# Génération de texte
result = client.generate_text("llama3", "Explique-moi la théorie de la relativité en une phrase.")
print("Texte :", result)

# Génération d'image
image_path = client.generate_image("stable-diffusion", "A futuristic city in the night")
print("Image enregistrée dans le serveur à :", image_path)

# Consulter la file d'attente
queue_status = client.get_queue_status()
print("File d'attente :", queue_status)

Guide d’Utilisation : Interface Web du Serveur IA

Le Serveur IA embarque un tableau de bord web complet. Il vous permet de lancer des tâches, de surveiller la santé du serveur et de consulter l’historique sans avoir à écrire la moindre ligne de code.

Vous pouvez accéder à l’interface depuis n’importe quel appareil sur votre réseau local (LAN) en tapant l’adresse IP de l’ordinateur hébergeant le serveur, suivie du port 8000 (ex: http://192.168.1.135:8000).


1. Barre de Statut et Surveillance en Temps Réel

En haut de l’écran, un bandeau de statut vous permet de monitorer la « santé » du serveur et de la file d’attente à la seconde près :

  • CPU / RAM : Utilisation globale du processeur et de la mémoire vive de la machine. Si le matériel le permet, la température du processeur est affichée.
  • VRAM / GPU : Utilisation de la puce graphique et de sa mémoire (indispensable pour surveiller la charge lors de la génération d’images).
  • Thème (☀️/🌙) : Un bouton à droite permet de basculer instantanément entre le mode clair et le mode sombre. Votre préférence est mémorisée.
  • Tâches en attente & Worker : État actuel du moteur d’IA (Idle = inactif, Processing = travail en cours).

2. Onglet « Générateur » (Lancer une tâche)

C’est l’interface principale. Elle s’adapte intelligemment selon que vous souhaitez générer du texte ou une image.

Génération de Texte (LLM)

  • Choisissez le modèle désiré (la liste est dynamiquement récupérée depuis Ollama).
  • Tapez votre requête (prompt). Vous pouvez utiliser le raccourci clavier Ctrl + Entrée pour l’envoyer rapidement.
  • Joindre un fichier (Code/Texte) : Grâce à l’icône « trombone » ou par simple Glisser-Déposer (Drag & Drop) depuis votre bureau vers la zone de texte, vous pouvez intégrer le contenu d’un fichier .py, .js, .txt, etc. directement dans votre prompt ! Idéal pour demander une analyse de code.
  • Vision (Image-to-Text) : Vous pouvez optionnellement uploader une image de base via le bouton dédié. Si le modèle choisi supporte la vision (ex: llava), il pourra l’analyser.
  • Mode Conversation : En cochant la case « Mode Conversation », le serveur gardera en mémoire tout votre historique de discussion et l’enverra au modèle à chaque nouvelle question pour préserver le contexte. Attention, un très long contexte consomme plus de tokens !

Génération d’Images (Stable Diffusion)

  • Choisissez le modèle (ex: Dreamshaper).
  • Upload d’image (Image-to-Image) : Uploadez une ébauche ou une photo pour que l’IA la transforme selon votre texte.
  • Options Basiques : Réglez le niveau de qualité (nombre d’étapes de calcul).
  • Options Avancées : Force de modification (Strength), Résolution (Largeur/Hauteur) et Seed.

Affichage du Résultat

Dès l’envoi, l’interface vous indique votre position dans la file d’attente et le temps d’attente estimé (environ 15s par tâche précédente).
Dès que la tâche est terminée, le résultat s’affiche sous forme de texte riche :

  • Coloration Syntaxique : Le code source généré par l’IA est automatiquement mis en évidence avec un thème sombre (atom-one-dark) pour être facile à lire.
  • Actions Rapides : Des boutons permettent de « Copier » le code en un clic, ou de télécharger la réponse complète dans un fichier .txt.

3. Onglet « Historique »

Le serveur IA enregistre absolument toutes les requêtes (qu’elles viennent de l’interface web ou de vos scripts Python automatisés).

Cet onglet permet de revoir les anciennes tâches :

  • Une liste claire et colorée (Vert = Succès, Rouge = Échec).
  • Favoris (⭐) : Vous pouvez cliquer sur l’étoile à côté d’une tâche pour l’ajouter à vos favoris. Cela évite qu’elle ne soit supprimée lors des purges de maintenance.
  • En cliquant sur une tâche, vous rouvrez le détail complet dans le panneau central (Modèle utilisé, Prompt exact, Résultat, Date et Temps de traitement).

4. Onglet « Paramètres » (Maintenance)

[!NOTE]
Les paramètres modifiés ici sont sauvegardés dans la base de données SQLite et persistent après le redémarrage du serveur.

  • Nettoyage automatique (Rétention des Images) : Pour éviter de saturer votre disque dur avec les images générées. Par défaut, les images vieilles de plus de 7 jours sont supprimées au démarrage.
  • Purger le Cache (Bouton Rouge) : Permet de supprimer instantanément toutes les anciennes générations et de nettoyer les images associées, à l’exception de celles que vous avez marquées comme favorites (⭐).

Documentation de l’API du Serveur IA

Le serveur IA met à disposition une API REST robuste et une file d’attente (gérée par base de données) pour traiter des requêtes textuelles (LLM) et des générations/traitements d’images (Stable Diffusion).

Cette documentation explique comment interagir programmatiquement avec ce serveur depuis un script Python, sans modifier le serveur lui-même.

Le Client Python Fourni (ai_client.py)

Le serveur est livré avec un client Python prêt à l’emploi (ai_client.py) qui encapsule toute la logique de requêtage, de file d’attente (polling) et d’upload.


1. generate_text : Génération de texte simple

Permet de générer du texte. Bloque l’exécution jusqu’à ce que la tâche soit terminée et retourne la chaîne de caractères générée.

Vous pouvez également passer une liste chat_history pour donner de la mémoire contextuelle au modèle.

Exemple d’utilisation :

from ai_client import LocalAIClient

client = LocalAIClient(endpoint="http://127.0.0.1:8000")

# Exemple avec historique
historique = [
    {"role": "user", "content": "Je m'appelle Alice."},
    {"role": "assistant", "content": "Bonjour Alice !"}
]

print("Demande envoyée au LLM...")
reponse = client.generate_text(
    model="llama3:latest",
    prompt="Quel est mon nom ?",
    chat_history=historique,
    system="Tu es un assistant utile.",
    max_tokens=-1, # -1 = illimité
    temperature=0.7
)

print("\n--- Réponse du modèle ---")
print(reponse)

2. generate_image : Génération d’image (Text-to-Image)

Permet de générer une image à partir d’un prompt. Bloque l’exécution et retourne le chemin d’accès local vers l’image générée (sur le serveur).

Si votre script ne tourne pas sur la même machine que le serveur, vous pouvez utiliser la méthode download_image pour la rapatrier via HTTP.

Exemple d’utilisation :

from ai_client import LocalAIClient

client = LocalAIClient(endpoint="http://127.0.0.1:8000")

print("Génération de l'image en cours...")
image_path_serveur = client.generate_image(
    model="Lykon/dreamshaper-8-lcm",
    prompt="A futuristic military drone flying over a neon city, highly detailed, 4k",
    width=768,
    height=512
)

print(f"\nImage générée avec succès sur le serveur : {image_path_serveur}")

# Rapatrier l'image sur notre propre machine
image_locale = client.download_image(image_path_serveur, destination_path="C:/mon_projet/drone_resultat.png")
print(f"L'image a été téléchargée sur votre machine ici : {image_locale}")

3. upload_image et Vision (Image-to-Text)

Permet d’envoyer une image locale vers le serveur pour qu’un modèle de vision (comme llava) l’analyse.

Exemple d’utilisation :

from ai_client import LocalAIClient

client = LocalAIClient(endpoint="http://127.0.0.1:8000")

# 1. On upload d'abord le fichier
print("Upload de l'image...")
chemin_serveur = client.upload_image("C:/mon_projet/photo_suspecte.jpg")

# 2. On demande au LLM d'analyser ce fichier
print("Analyse de l'image par l'IA...")
analyse = client.generate_text(
    model="llava",
    prompt="Décris en détail ce qui se trouve sur cette image.",
    init_image_path=chemin_serveur # <-- On passe le chemin renvoyé par l'upload
)

print("\n--- Analyse ---")
print(analyse)

4. upload_image et Modification (Image-to-Image)

Permet de transformer une image existante à l’aide d’un modèle d’image en utilisant le paramètre strength.

Exemple d’utilisation :

from ai_client import LocalAIClient

client = LocalAIClient(endpoint="http://127.0.0.1:8000")

print("Upload du croquis...")
chemin_serveur = client.upload_image("C:/mon_projet/croquis_brouillon.png")

print("Transformation du croquis en rendu réaliste...")
image_finale = client.generate_image(
    model="Lykon/dreamshaper-8-lcm",
    prompt="A photorealistic rendering of a modern tactical vehicle, military green, highly detailed",
    init_image_path=chemin_serveur,
    strength=0.8 # 0.8 = on modifie beaucoup le croquis d'origine
)

print(f"\nRendu final disponible ici : {image_finale}")

5. get_queue_status : Surveiller le serveur

Permet de savoir combien de tâches sont en attente et si le processeur/GPU est actuellement occupé.

Exemple d’utilisation :

from ai_client import LocalAIClient

client = LocalAIClient(endpoint="http://127.0.0.1:8000")

statut = client.get_queue_status()

print(f"Tâches en attente : {statut['pending_tasks']}")
print(f"État du travailleur : {statut['worker_status']}") # 'idle' ou 'processing'

if statut['pending_tasks'] > 5:
    print("Alerte: Le serveur IA est très sollicité en ce moment.")

6. Gestion du Cache et des Favoris (Nouveau !)

Le client vous permet d’interagir avec la base de données interne pour marquer des tâches comme favorites ou nettoyer les données orphelines.

Exemples :

from ai_client import LocalAIClient

client = LocalAIClient(endpoint="http://127.0.0.1:8000")

# Mettre une tâche en favori (toggle)
is_fav = client.toggle_favorite("mon_task_id_123")
if is_fav:
    print("Tâche ajoutée aux favoris !")

# Purger toutes les tâches et images qui ne sont pas en favori
result = client.purge_cache()
print(result["message"]) # Affiche le nombre d'éléments supprimés

7. Requêtes Asynchrones (submit_task et delete_task)

Les méthodes generate_* précédentes bloquent le script Python jusqu’à la fin du calcul. Si vous voulez lancer une tâche en arrière-plan sans bloquer votre script, utilisez submit_task.

Exemple d’utilisation :

import time
from ai_client import LocalAIClient

client = LocalAIClient(endpoint="http://127.0.0.1:8000")

# 1. On soumet la tâche (retourne immédiatement)
parametres = {
    "prompt": "Génère un rapport de 3 pages sur...",
    "max_tokens": 2000
}
task_id = client.submit_task("llm", "llama3:latest", parametres)
print(f"Tâche {task_id} envoyée. Je peux faire autre chose en attendant...")

# 2. Le script peut continuer de faire d'autres opérations
print("Le script principal continue de tourner...")
time.sleep(2)

# 3. Supposons qu'on veuille annuler la tâche
print("Annulation de la tâche...")
succes = client.delete_task(task_id)

if succes:
    print("Tâche supprimée avec succès de la file d'attente.")
else:
    print("Impossible de la supprimer (elle est probablement déjà terminée ou en cours de traitement).")

Guide d’Architecture et Développeur

Ce document s’adresse aux développeurs qui souhaitent comprendre le fonctionnement interne du Serveur IA, le modifier, ou y ajouter de nouvelles fonctionnalités (nouveaux modèles, nouveaux types de tâches).

1. Vue d’ensemble du système

Le serveur est construit autour d’une architecture asynchrone producteur/consommateur pour éviter de bloquer l’API web pendant que la carte graphique (ou le processeur) calcule des résultats lourds.

Les briques principales :

  • Client (Frontend / SDK) : Envoie des requêtes REST (JSON) ou uploade des fichiers (multipart/form-data).
  • FastAPI (main.py) : Le routeur principal. Il valide les données (via Pydantic), gère l’upload, et enregistre la tâche en base de données avec le statut pending. Il ne fait aucun calcul d’IA.
  • Base de données (database.py & SQLite) : Agit comme une file d’attente persistante. Chaque tâche possède un ID, un type, des paramètres JSON, et un statut (pending, processing, completed, failed).
  • Le Worker (worker.py) : Tourne dans un processus séparé (multiprocessing). Il scrute la base de données en permanence à la recherche de la tâche pending la plus ancienne, passe son statut en processing, et la confie au pipeline.
  • La Pipeline d’IA (models_pipeline.py) : Contient la logique d’exécution propre aux modèles. C’est ici que diffusers ou requests (vers Ollama) sont appelés.

2. Structure des fichiers

iaserver/
│
├── main.py                # Point d'entrée FastAPI, définitions des routes API
├── worker.py              # Boucle infinie scrutant la BDD pour exécuter les tâches
├── models_pipeline.py     # Logique métier des modèles d'IA (Ollama, Stable Diffusion)
├── database.py            # Modèles SQLAlchemy (Tasks, Settings) et auto-migrations
├── schemas.py             # Modèles Pydantic pour la validation des données d'API
├── config.py              # Variables de configuration (Ports, IPs, Modèles disponibles)
├── ai_client.py           # SDK Python fourni pour attaquer l'API
│
├── client/                # Interface Web (Frontend)
│   ├── index.html         # Structure de la page
│   ├── app.js             # Logique applicative (Polling, Drag&Drop, DOM)
│   └── style.css          # Styles (Thèmes clair/sombre)
│
└── saves/                 # Dossier généré automatiquement pour les images
    └── uploads/           # Fichiers sources envoyés par l'utilisateur (ex: Image-to-image)

3. Comment ajouter un nouveau type de tâche ?

Imaginons que vous souhaitiez ajouter de la génération audio (Text-to-Speech) :

  1. Mettre à jour schemas.py :
    Dans TaskSubmitRequest, le task_type pourra désormais accepter "tts". Ajoutez les paramètres spécifiques (ex: voice, speed) dans TaskParameters.
  2. Créer la méthode dans models_pipeline.py :
    Ajoutez une méthode dans BaseModelPipeline, par exemple def run_tts(self, parameters):.
    Implémentez-y le code d’inférence (ex: avec pyttsx3 ou le modèle Bark d’HuggingFace). La fonction doit retourner un dictionnaire avec le chemin du fichier audio généré.
  3. Mettre à jour worker.py :
    Dans la méthode process_task, ajoutez une condition :
   elif task.task_type == "tts":
       result = pipeline.run_tts(params)
  1. Mettre à jour le Frontend (client/index.html & client/app.js) :
    Ajoutez une option <option value="tts">Texte vers Audio</option> dans le selecteur HTML. Mettez à jour le Javascript (renderResult()) pour afficher un lecteur <audio> quand task_type === "tts".

4. Cycle de vie d’une requête

  1. L’utilisateur clique sur Envoyer. app.js fait un POST /api/v1/tasks.
  2. main.py génère un UUID, crée l’entrée en base (Statut: pending) et retourne l’UUID.
  3. Le navigateur commence à faire un « polling » (interrogation) régulier via GET /api/v1/tasks/{uuid}.
  4. Le worker.py (qui tourne en tâche de fond) récupère l’entrée, la passe en processing.
  5. La fonction appropriée de models_pipeline.py est appelée. Le calcul bloque le worker (mais pas l’API web).
  6. Le calcul se termine. Le worker.py met à jour la base avec le résultat (JSON) et le statut completed.
  7. Le prochain polling du navigateur récupère le statut completed et affiche le résultat final à l’écran !

Résolution de Problèmes (FAQ & Troubleshooting)

Héberger et exécuter des modèles d’intelligence artificielle en local demande souvent des ressources matérielles importantes. Ce document liste les problèmes les plus courants et leurs solutions.


1. Problèmes liés aux Modèles LLM (Ollama)

Le serveur indique qu’Ollama est injoignable

  • Symptôme : Vos requêtes de texte restent bloquées ou finissent en erreur « Connection Refused ».
  • Cause : L’exécutable ollama n’est pas lancé en arrière-plan.
  • Solution :
  1. Ouvrez un terminal et tapez ollama serve.
  2. Si le port est déjà pris, vérifiez que l’icône Ollama n’est pas déjà présente dans la barre des tâches Windows (en bas à droite) et qu’il n’y a pas d’antivirus/pare-feu qui bloque le port 11434.

« Model not found » lors de l’exécution

  • Symptôme : Erreur immédiate indiquant que le modèle (ex: llama3) n’existe pas.
  • Cause : Le modèle n’a pas été téléchargé sur votre machine.
  • Solution : Ouvrez un terminal et exécutez la commande ollama pull nom_du_modele (ex: ollama pull llama3).

2. Problèmes liés à la Génération d’Images (Stable Diffusion / Diffusers)

Erreur OOM (Out Of Memory) / CUDA Out of Memory

  • Symptôme : La génération d’image crash avec une longue erreur mentionnant CUDA out of memory. Tried to allocate XXX MiB...
  • Cause : Votre carte graphique ne possède pas assez de VRAM pour charger le modèle ou générer une image à la résolution demandée.
  • Solutions :
  1. Réduire la résolution : Ne dépassez pas 512×512 ou 768×768.
  2. Changer de device : Si vous n’avez pas une carte graphique Nvidia puissante, le modèle doit tourner sur le processeur (CPU). Par défaut, models_pipeline.py détecte automatiquement cuda. Si votre GPU est trop faible (ex: moins de 6 Go de VRAM), forcez le calcul sur CPU en modifiant le fichier models_pipeline.py : remplacez self.device = "cuda" if torch.cuda.is_available() else "cpu" par self.device = "cpu". Attention, ce sera plus lent !

L’image met énormément de temps à générer (plusieurs minutes)

  • Cause : Le calcul se fait sur le CPU (processeur) au lieu du GPU (carte graphique).
  • Solution : Vérifiez que vous avez bien installé la version de PyTorch compatible avec CUDA.
    Exécutez dans votre environnement : pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 (adaptez l’URL selon votre version de CUDA installée).

Disque dur saturé (Poids des modèles HuggingFace)

  • Symptôme : Vous manquez subitement de dizaines de Gigaoctets sur votre disque système (Lecteur C:).
  • Cause : La bibliothèque diffusers télécharge les modèles (qui pèsent de 2 à 10 Go chacun) et les met en cache.
  • Solution : Sur Windows, videz le dossier de cache situé par défaut dans C:\Users\VOTRE_NOM\.cache\huggingface\hub.

3. Problèmes liés au Serveur (Base de données / API)

« Database is locked » (Erreur SQLite)

  • Symptôme : Le terminal du serveur affiche une erreur sqlite3.OperationalError: database is locked.
  • Cause : L’API (main.py) et le Worker (worker.py) essaient d’écrire en même temps dans la base tasks.db.
  • Solution : Bien que le mode WAL (Write-Ahead Logging) soit activé pour limiter cela, si cela arrive, redémarrez simplement le serveur (Ctrl+C puis relancez python main.py).

Port 8000 déjà utilisé

  • Symptôme : Uvicorn refuse de démarrer avec l’erreur [Errno 10048] error while attempting to bind on address ('0.0.0.0', 8000).
  • Cause : Un autre serveur ou logiciel utilise déjà le port 8000.
  • Solution : Modifiez le fichier config.py et changez la ligne PORT = 8000 par PORT = 8080 (ou un autre nombre). N’oubliez pas d’indiquer ce nouveau port si vous utilisez le client Python !

SOURCE