Aller au contenu

Mise en œuvre du téléchargement d'images et de la reconnaissance IA dans le chat : solution complète de la conception au déploiement

Modifier cette page
HagiCode for Windows Microsoft Store artwork
HagiCode for Windows is now on Microsoft Store
HagiCode for Windows is officially live on Microsoft Store. Windows users can install it directly from the storefront and stay on the store-managed update path. Open the listing and take a look.
Open Microsoft Store

Mise en œuvre du téléchargement d’images et de la reconnaissance IA dans le chat : solution complète de la conception au déploiement

Dans les systèmes d’interaction IA, comment permettre aux utilisateurs de télécharger des images et de laisser l’IA les reconnaître directement ? En fait, j’ai longtemps hésité sur cette question, mais heureusement, j’ai découvert quelques astuces dans la pratique de HagiCode. Aujourd’hui, je vais vous parler de cette solution de téléchargement et de reconnaissance d’images, de la conception de protocoles personnalisés au stockage sur système de fichiers, en passant par la prévision front-end/back-end séparée. C’est aussi un journal technique complet.

Contexte

À cette époque où la conversation IA est en plein essor, les informations visuelles sont en fait un vecteur important pour que les utilisateurs expriment leurs intentions. Cependant, la plupart des systèmes de chat traditionnels ne prennent en charge que la saisie de texte brut, ce qui empêche les utilisateurs de transmettre directement le contexte visuel à l’IA pour analyse, ce qui est un peu regrettable.

HagiCode a rencontré des difficultés similaires au cours de son développement : les utilisateurs ne pouvaient pas télécharger d’images lors du chat ou de la création de commentaires principaux, l’IA ne pouvait pas accéder aux informations visuelles locales des utilisateurs, et il manquait une boucle fermée complète allant de la saisie, du stockage, du rendu à la transmission du contexte IA des images.

En fait, ces problèmes ne sont pas graves, ils ont juste besoin d’un peu de temps et de patience pour être résolus. Nous avons conçu et mis en œuvre un processus complet de téléchargement et de reconnaissance d’images, permettant à Claude et autres IA de reconnaître et d’analyser directement les captures d’écran téléchargées par les utilisateurs. Je vais expliquer en détail les détails de mise en œuvre de cette solution.

À propos de HagiCode

La solution partagée dans cet article provient de notre expérience pratique dans le projet HagiCode. HagiCode est un projet d’assistant de codage IA open source, utilisant une conception de workflow basée sur OpenSpec, s’efforçant de fournir une expérience de codage plus intelligente.

Analyse

Défis techniques

Avant de commencer la mise en œuvre, nous devons d’abord clarifier les principaux défis auxquels nous sommes confrontés, après tout, “aiguiser sa hache ne nuit pas à son travail de bûcheron”.

Collaboration inter-modules : Le téléchargement d’images implique plusieurs modules tels que l’interface utilisateur frontale, le service de téléchargement, l’API back-end, le stockage de fichiers, la persistance des messages et le mappage d’exécution IA. Chaque module a ses propres responsabilités et interfaces, nécessitant une solution globale coordonnée.

Choix de stratégie de stockage : Les images doivent-elles être stockées dans la base de données ou le système de fichiers ? Si le système de fichiers est choisi, comment concevoir la structure des répertoires ? Comment l’intégrer avec le workflow OpenSpec existant ? Tout cela nécessite une pesée attentive.

Conception de protocole de référence : Un moyen standard de référence d’image est nécessaire, qui peut être affiché par le rendu front-end et correctement analysé par le pipeline d’exécution IA. Chemin de fichier direct ? URL HTTP ? Ou concevoir un protocole dédié ?

Compatibilité des capacités IA : Les différents exécuteurs IA ont des degrés de support multimodal variables. Certains exécuteurs prennent en charge nativement l’entrée d’images, d’autres ne peuvent traiter que du texte. Comment concevoir une couche d’adaptation unifiée pour garantir que tous les exécuteurs puissent correctement traiter les informations d’image ?

Décisions de conception

Après une discussion et une pesée complètes, nous avons pris les décisions de conception clés suivantes.

Décision 1 : Stockage sur système de fichiers

Nous avons choisi de stocker les images sur le système de fichiers plutôt que dans la base de données. La structure des répertoires est conçue comme suit :

<Répertoire racine du système>/images/<sessionId>/
├── <timestamp>-<uuid>.jpg
└── <timestamp>-<uuid>.png

La raison est en fait assez claire : simplifier la mise en œuvre, éviter l’expansion de la base de données, les fichiers peuvent être directement lus par l’IA. De plus, les fichiers image ne sont fondamentalement pas adaptés pour être placés dans la base de données, le système de fichiers est le choix plus naturel. C’est comme mettre des livres sur une étagère plutôt que de les fourrer dans un cahier, c’est la même logique.

Décision 2 : Protocole personnalisé hagiimag://

Afin d’éviter les conflits avec les URL HTTP tout en rendant la sémantique de référence plus claire, nous avons conçu un protocole de référence d’image personnalisé :

hagiimag://session-abc123/20260301-143022-a1b2c3d4

Le format de ce protocole est hagiimag://<sessionId>/<imageId>, avec une sémantique claire, facile à analyser et à router. En voyant ce format, les développeurs comprendront immédiatement qu’il s’agit d’une référence d’image et non d’une URL ordinaire. Ce genre de petite attention de conception est parfois très utile.

Décision 3 : Séparation de la prévisualisation frontale et de l’accès IA

Au cours de la mise en œuvre, nous avons découvert que les besoins d’accès aux images du front-end et de l’IA sont différents : le front-end doit prévisualiser via l’API HTTP, tandis que l’IA doit lire directement le chemin de fichier local. Par conséquent, nous avons conçu des méthodes d’accès séparées :

  • Le front-end utilise /api/Images/{sessionId}/{imageId}/content pour la prévisualisation
  • L’IA utilise le chemin de fichier local analysé côté serveur

Cela garantit à la fois la sécurité (ne pas exposer les chemins du serveur) et la facilité d’utilisation (le navigateur peut y accéder directement). Après tout, la sécurité et la facilité d’utilisation doivent toujours être équilibrées.

Décision 4 : Stratégie de téléchargement immédiat

Une autre décision clé concerne le moment du téléchargement. Nous choisissons de déclencher immédiatement le téléchargement lorsque l’utilisateur sélectionne ou colle une image, et lors de l’envoi du message, nous ne référençons que les images déjà téléchargées avec succès.

L’avantage de cette approche est de traiter les erreurs en amont, d’éviter de compliquer l’API d’envoi de messages, et de maintenir la simplicité du contrat JSON. Les utilisateurs peuvent savoir si l’image a été téléchargée avec succès avant l’envoi, ce qui offre une meilleure expérience. Cette idée de conception “prévoyante” peut s’appliquer dans de nombreux cas.

Solution

Conception de l’architecture

Sur la base des décisions ci-dessus, nous avons conçu l’architecture globale suivante :

Couche frontale
├── ConversationInputArea ◄─────── useImageAttachmentManager
│ │ │
│ ├── Sélection de fichiers ├── Gestion de l'état des pièces jointes
│ ├── Collage du presse-papiers ├── Téléchargement/réessayer/supprimer
│ └── Prévisualisation des pièces jointes └── Génération de références d'images
│
Couche de service
├── ImageUploadService
│ ├── uploadImage() ◄─────── ImagesController
│ ├── deleteImage() │
│ ├── parseHagiImageUrl() ◄─────── Analyser les liens de protocole
│ └── buildPreviewUrl() │
│
Couche back-end
├── ImagesController ◄─────── ImagesDomainService
│ │ │
│ ├── POST /upload ├── Validation des fichiers
│ ├── GET /{sessionId}/{imageId} ├── Enregistrement des images
│ ├── DELETE ├── Compression des images
│ └── GET /content └── Analyse des références
│
Couche d'exécution IA
├── ImageContentBlock ◄─────── StructuredMessageDomainService
│ │ │
│ ├── Exécuteur multimodal ├── Analyse des blocs d'images
│ └── Dégradation de l'exécuteur de texte └── Génération d'indices de chemin

Cette architecture illustre clairement le flux de données complet du front-end à l’IA. Chaque couche a des responsabilités claires et interagit via des interfaces standard. En fait, une bonne architecture est comme ça : chacun fait son travail, ne s’interfère pas, et communique sans problème.

Processus clés

Processus de téléchargement d’images :

  1. L’utilisateur sélectionne une image via la sélection de fichiers ou le collage du presse-papiers
  2. Le front-end valide le type et la taille du fichier (prend en charge JPEG/PNG/WEBP/GIF, 10 Mo par fichier)
  3. Appel de l’API de téléchargement, l’image est sauvegardée dans le répertoire /images/{sessionId}/
  4. L’API renvoie la référence hagiimag:// et l’URL de prévisualisation
  5. Le front-end affiche la vignette de prévisualisation dans la barre des pièces jointes, l’utilisateur peut prévisualiser avant l’envoi

Processus de reconnaissance IA :

  1. L’utilisateur envoie un message contenant une référence d’image
  2. Le back-end analyse le lien du protocole hagiimag://, extrait sessionId et imageId
  3. Mappe la référence d’image vers ImageContentBlock
  4. Sélectionne la méthode de traitement en fonction des capacités de l’exécuteur :
    • Exécuteur multimodal : transmettre l’entrée d’image structurée
    • Exécuteur de texte : dégradation vers un indice de chemin d’image

Ainsi, une boucle fermée complète est accomplie : l’utilisateur télécharge l’image → l’IA reconnaît l’image → l’IA renvoie le résultat de l’analyse. Ce genre de flux fluide apporte souvent une meilleure expérience aux utilisateurs.

Pratique

Mise en œuvre frontale

Sur le front-end, nous fournissons un Hook dédié pour gérer l’état des pièces jointes d’images :

import { useImageAttachmentManager } from '@/hooks/useImageAttachmentManager';
function ChatInput() {
const {
attachments,
uploadedImages,
hasBlockingAttachments,
isUploading,
selectFiles,
removeAttachment,
clearAttachments,
} = useImageAttachmentManager({
ownerId: sessionId,
mapUploadedImage: (response) => response,
uploadOptions: { compress: false },
});
const handleFileSelect = (files: File[]) => {
selectFiles(files);
};
const handlePaste = (e: ClipboardEvent) => {
const files = Array.from(e.clipboardData?.files || [])
.filter(f => f.type.startsWith('image/'));
if (files.length > 0) {
handleFileSelect(files);
}
};
return (
<div>
{/* Barre des pièces jointes */}
{attachments.map(att => (
<AttachmentItem
key={att.localId}
file={att.file}
status={att.status}
onRemove={() => removeAttachment(att.localId)}
/>
))}
{/* Zone de saisie */}
<textarea onPaste={handlePaste} />
{/* Bouton de téléchargement */}
<button onClick={() => fileInputRef.current?.click()}>
Télécharger une image
</button>
</div>
);
}

Ce Hook encapsule toute la logique de gestion des pièces jointes, y compris le suivi de l’état de téléchargement, la nouvelle tentative en cas d’échec, la suppression des pièces jointes, etc. Il est très simple à utiliser, il suffit d’appeler quelques méthodes pour compléter l’ensemble du processus. En fait, une bonne conception d’API est comme ça : simple et facile à utiliser, sans perdre en flexibilité.

Analyse du protocole personnalisé :

// Extraire sessionId et imageId du protocole personnalisé
const parsed = parseHagiImageUrl("hagiimag://session-abc123/20260301-143022-uuid");
// Renvoie : { sessionId: "session-abc123", imageId: "20260301-143022-uuid" }
// Construire l'URL de prévisualisation
const previewUrl = buildPreviewUrl(parsed.sessionId, parsed.imageId);
// Renvoie : "/api/Images/session-abc123/20260301-143022-uuid/content"

Avec ces deux fonctions utilitaires, le front-end peut facilement effectuer des conversions entre le protocole hagiimag:// et l’URL HTTP. Une fois cette logique de conversion encapsulée, elle est beaucoup plus pratique à utiliser.

Mise en œuvre back-end

Le back-end utilise ASP.NET Core pour la mise en œuvre, le cœur étant ImagesController et ImagesDomainService :

[HttpPost("upload")]
[RequestSizeLimit(50 * 1024 * 1024)]
public async Task<ActionResult<ImageUploadResponseDto>> Upload(
[FromForm] UploadImageFormRequest input)
{
// 1. Valider la requête
if (file == null || file.Length == 0)
throw new UserFriendlyException("No file provided");
// 2. Valider le type et la taille du fichier
var (isValid, errorMessage) = _imagesDomainService.ValidateImage(
file.FileName, file.ContentType, file.Length);
if (!isValid)
throw new UserFriendlyException(errorMessage);
// 3. Sauvegarder sur le système de fichiers
await using var stream = file.OpenReadStream();
var result = await _imagesDomainService.UploadImageAsync(
stream,
sessionId,
file.FileName,
file.ContentType,
CurrentUserId,
compress: input.Compress);
// 4. Renvoyer le résultat
return Ok(result);
}

Cette mise en œuvre suit le modèle typique de développement d’API Web : validation, traitement, retour. Il convient de noter que nous avons défini une limite de taille de requête de 50 Mo pour empêcher le téléchargement malveillant de fichiers volumineux. Après tout, dans le monde en ligne, il vaut mieux être prudent.

Points d’attention

Au cours de la mise en œuvre, certains détails nécessitent une attention particulière :

Vérification des autorisations : L’accès aux images doit vérifier l’identité de l’utilisateur, garantissant que seules les images de sa propre session peuvent être consultées. C’est une exigence de sécurité de base qui ne peut être omise. En matière de sécurité, mieux vaut prévenir que guérir.

Sécurité des chemins : Valider strictement sessionId et imageId pour empêcher les attaques de traversée de chemins. Par exemple, refuser les chemins contenant ../ pour empêcher les utilisateurs d’accéder à des fichiers arbitraires dans le système. Une fois ces conditions aux limites bien traitées, le système peut être plus robuste.

Nettoyage des fichiers : Lors de la suppression d’une session, les images associées doivent être nettoyées de manière synchronisée pour éviter l’accumulation de fichiers orphelins. Après une exécution à long terme, ces fichiers peuvent occuper beaucoup d’espace disque. Nettoyer à temps est aussi une bonne habitude.

Stratégie de compression : Pour les noms de fichiers de type capture d’écran (tels que screenshot.png), activer automatiquement la compression pour économiser de l’espace. Cette stratégie peut être ajustée en fonction des besoins réels. Pour l’espace de stockage, chaque petit peu compte.

Traitement de dégradation : Les exécuteurs qui ne prennent pas en charge le multimodal doivent recevoir un indice de chemin d’image et ne peuvent pas silently supprimer les informations d’image. C’est très important, sinon les utilisateurs penseront que l’IA a ignoré leur image. L’expérience utilisateur, ce sont les détails qui font la différence.

Gestion de l’état : Les pièces jointes en cours de téléchargement bloquent l’envoi de messages, les pièces jointes échouées permettent de réessayer ou de supprimer. Cette conception garantit la cohérence de l’expérience utilisateur. Une fois la gestion de l’état claire, les utilisateurs ne seront pas confus.

Résumé

Grâce à cette solution complète de téléchargement et de reconnaissance d’images, HagiCode a réalisé une boucle fermée complète allant de la saisie utilisateur à la reconnaissance IA. Les points forts de cette solution comprennent :

  • Le protocole personnalisé hagiimag:// réalise la standardisation des références d’images
  • Le stockage sur système de fichiers simplifie la mise en œuvre et améliore les performances
  • La séparation de la prévisualisation frontale et de l’accès IA équilibre la sécurité et la facilité d’utilisation
  • La stratégie de téléchargement immédiat optimise l’expérience utilisateur
  • La conception de compatibilité multimodal et de dégradation de texte garantit la flexibilité

Cette solution fonctionne de manière stable dans HagiCode et a reçu des commentaires positifs des utilisateurs. Si vous mettez également en œuvre des fonctionnalités similaires, j’espère que cette expérience vous sera utile.

En fait, pour les solutions techniques, il n’y a pas de bien ou de mal absolu, seulement de ce qui convient ou non. Trouver la voie adaptée à son propre projet est le plus important.

Références

开始使用 HagiCode

一次安装,几分钟上手

HagiCode for Windows 在 Microsoft Store 免费提供。打开商店即可安装并保持更新;也可以先对比各版本与定价,再决定从哪个渠道开始。