Zum Inhalt springen

Bild-Upload und KI-Erkennung im Chat: Die komplette Lösung von Design bis Implementierung

Seite bearbeiten
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

Bild-Upload und KI-Erkennung im Chat: Die komplette Lösung von Design bis Implementierung

In KI-Interaktionssystemen: Wie können Benutzer Bilder hochladen und die KI diese direkt erkennen? Diese Frage hat mich auch lange beschäftigt, aber zum Glück haben wir im HagiCode-Projekt einige Lösungen gefunden. Heute sprechen wir über dieses Bild-Upload- und Erkennungssystem – von der benutzerdefinierten Protokollentwürfung bis zur Dateisystemspeicherung und der Frontend-Backend-separaten Vorschau. Dies ist auch eine vollständige technische Dokumentation.

Hintergrund

In dieser Ära des KI-Chat-Hype sind visuelle Informationen tatsächlich ein wichtiger Träger für die Benutzerabsicht. Nur unterstützen die meisten traditionellen Chat-Systeme reine Texteingabe, was dazu führt, dass Benutzer visuelle Kontexte nicht direkt zur KI-Analyse übergeben können – ein wenig bedauerlich.

HagiCode stieß während der Entwicklung auf ein ähnliches Dilemma: Benutzer konnten beim Chatten oder Erstellen von Hauptmeinungen keine Bilder hochladen, die KI konnte nicht auf lokale visuelle Informationen der Benutzer zugreifen, und es fehlte der geschlossene Kreislauf von Bildeingabe, Speicherung, Rendering und KI-Kontextübergabe.

Diese Probleme sind eigentlich nicht besonders groß, sie erfordern nur etwas Zeit und Geduld zur Lösung. Wir haben einen vollständigen Bild-Upload- und Erkennungsablauf entworfen und implementiert, damit Claude und andere KIs direkt Screenshots erkennen und analysieren können, die Benutzer hochladen. Im Folgenden werde ich die Implementierungsdetails dieser Lösung langsam erläutern.

Über HagiCode

Die in diesem Artikel vorgestellte Lösung stammt aus unserer praktischen Erfahrung im HagiCode-Projekt. HagiCode ist ein Open-Source-KI-Coding-Assistent-Projekt, das auf einem OpenSpec-basierten Workflow-Design basiert und sich der Bereitstellung einer intelligenteren Coderfahrung verschrieben hat.

Analyse

Technische Herausforderungen

Bevor wir mit der Implementierung beginnen, müssen wir zunächst die Haupt-Herausforderungen klären – schließlich schadet es nicht, die Werkzeuge vorher zu schärfen.

Cross-Module-Kooperation: Der Bild-Upload betrifft mehrere Module wie Frontend-UI, Upload-Service, Backend-API, Dateispeicherung, Nachrichtenpersistenz und KI-Executions-Mapping. Jedes Modul hat seine eigenen Zuständigkeiten und Schnittstellen, und eine abgestimmte Gesamtlösung muss entworfen werden.

Speicherstrategie-Auswahl: Sollen Bilder in der Datenbank oder im Dateisystem gespeichert werden? Bei Dateisystemwahl – wie soll die Verzeichnisstruktur entworfen werden? Wie kann sie in den bestehenden OpenSpec-Workflow integriert werden? All dies muss sorgfältig abgewogen werden.

Referenzprotokoll-Design: Es wird eine Standard-Bildreferenzmethode benötigt, die sowohl vom Frontend gerendert werden kann als auch vom KI-Executions-Pfad korrekt geparst werden kann. Direkter Dateipfad verwenden? HTTP-URL? Oder ein spezielles Protokoll entwerfen?

KI-Fähigkeitskompatibilität: Verschiedene KI-Executoren unterstützen Multimodalität in unterschiedlichem Maße. Einige Executoren unterstützen nativ Bildeingaben, andere können nur Text verarbeiten. Wie kann eine einheitliche Adapterschicht entworfen werden, um sicherzustellen, dass alle Executoren Bildinformationen korrekt verarbeiten?

Designentscheidungen

Nach ausführlicher Diskussion und Abwägung trafen wir die folgenden Schlüssel-Designentscheidungen.

Entscheidung 1: Dateisystemspeicherung

Wir entschieden uns dafür, Bilder im Dateisystem statt in der Datenbank zu speichern. Die Verzeichnisstruktur ist wie folgt aufgebaut:

<System-Root>/images/<sessionId>/
├── <timestamp>-<uuid>.jpg
└── <timestamp>-<uuid>.png

Die Gründe sind eigentlich ziemlich klar: Implementierung vereinfachen, Datenbank-Aufblähung vermeiden, Dateien können direkt von der KI gelesen werden. Außerdem eign sich Bilddaten von Natur aus nicht für die Datenbank – das Dateisystem ist die natürlichere Wahl. Das ist wie Bücher ins Regal stellen, nicht in ein Notizbuch stopfen – derselbe Grundsatz.

Entscheidung 2: Benutzerdefiniertes Protokoll hagiimag://

Um Konflikte mit HTTP-URLs zu vermeiden und die Referenzsemantik klarer zu machen, entwarfen wir ein benutzerdefiniertes Bildreferenzprotokoll:

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

Das Format dieses Protokolls ist hagiimag://<sessionId>/<imageId>, mit klarer Semantik, einfach zu parsen und zu routen. Bei diesem Format erkennen Entwickler sofort, dass es sich um eine Bildreferenz handelt, nicht um eine normale URL. Solche kleinen Design-Details sind manchmal ziemlich nützlich.

Entscheidung 3: Frontend-Vorschau und KI-Zugriff getrennt

Bei der Implementierung stellten wir fest, dass Frontend und KI unterschiedliche Zugriffanforderungen an Bilder haben: Das Frontend benötigt eine Vorschau über HTTP-API, während die KI lokale Dateipfade direkt lesen muss. Daher entwarfen wir getrennte Zugriffsmethoden:

  • Frontend verwendet /api/Images/{sessionId}/{imageId}/content für Vorschau
  • KI verwendet vom Server geparste lokale Dateipfade

So wird sowohl die Sicherheit gewährleistet (Serverpfade werden nicht offengelegt) als auch die Benutzerfreundlichkeit berücksichtigt (Browser können direkt zugreifen). Schließlich müssen Sicherheit und Benutzerfreundlichkeit immer ausbalanciert werden.

Entscheidung 4: Sofortiger Upload-Strategie

Eine weitere wichtige Entscheidung war der Upload-Zeitpunkt. Wir entschieden uns, den Upload sofort beim Auswählen oder Einfügen eines Bildes auszulösen, und beim Senden der Nachricht nur bereits erfolgreich hochgeladene Bilder zu referenzieren.

Der Vorteil ist die Fehlerbehandlung im Voraus – die Nachrichten-Send-API bleibt einfach, der JSON-Vertrag wird kompakt gehalten. Benutzer wissen vor dem Senden, ob der Bild-Upload erfolgreich war – bessere Benutzererfahrung. Dieser Design-Ansatz “vorsorgen im Voraus” ist vielleicht oft anwendbar.

Lösung

Architektur-Design

Basierend auf den oben genannten Entscheidungen entwarfen wir die folgende Gesamtarchitektur:

Frontend-Schicht
├── ConversationInputArea ◄─────── useImageAttachmentManager
│ │ │
│ ├── Dateiauswahl ├── Anhänge-Status-Management
│ ├── Clipboard-Einfügen ├── Upload/Wiederholen/Löschen
│ └── Anhang-Vorschau └── Bildreferenz-Generierung
│
Service-Schicht
├── ImageUploadService
│ ├── uploadImage() ◄─────── ImagesController
│ ├── deleteImage() │
│ ├── parseHagiImageUrl() ◄─────── Protokoll-Link parsen
│ └── buildPreviewUrl() │
│
Backend-Schicht
├── ImagesController ◄─────── ImagesDomainService
│ │ │
│ ├── POST /upload ├── Dateivalidierung
│ ├── GET /{sessionId}/{imageId} ├── Bildspeicherung
│ ├── DELETE ├── Bildkomprimierung
│ └── GET /content └── Referenzparsing
│
KI-Executions-Schicht
├── ImageContentBlock ◄─────── StructuredMessageDomainService
│ │ │
│ ├── Multimodale Executoren ├── Bildblock-Parsing
│ └── Text-Executor-Fallback └── Pfadhinweis-Generierung

Diese Architektur zeigt klar den vollständigen Datenfluss vom Frontend zur KI. Jede Schicht hat klare Zuständigkeiten und interagiert über Standardschnittstellen. Gute Architektur ist eigentlich so: jeder erledigt seine Aufgabe, stört sich nicht gegenseitig, Kommunikation läuft reibungslos.

Schlüsselprozesse

Bild-Upload-Prozess:

  1. Benutzer wählt Bild über Dateiauswahl oder Clipboard-Einfügen
  2. Frontend validiert Dateityp und -größe (unterstützt JPEG/PNG/WEBP/GIF, 10MB pro Datei)
  3. Upload-API wird aufgerufen, Bild wird im Verzeichnis /images/{sessionId}/ gespeichert
  4. API gibt hagiimag://-Referenz und Vorschau-URL zurück
  5. Frontend zeigt Vorschau-Thumbnail im Anhänge-Balken, Benutzer kann vor dem Senden vorschauen

KI-Erkennungsprozess:

  1. Benutzer sendet Nachricht mit Bildreferenz
  2. Backend parsed hagiimag://-Protokoll-Link, extrahiert sessionId und imageId
  3. Bildreferenz wird auf ImageContentBlock abgebildet
  4. Verarbeitungsart wird basierend auf Executor-Fähigkeiten gewählt:
    • Multimodale Executoren: strukturierte Bildeingabe übergeben
    • Text-Executoren: Fallback auf Bildpfad-Hinweis

So ist ein vollständiger geschlossener Kreislauf entstanden: Benutzer lädt Bild hoch → KI erkennt Bild → KI gibt Analyseergebnis zurück. Ein solcher reibungsloser Ablauf bietet oft eine bessere Benutzererfahrung.

Praxis

Frontend-Implementierung

Im Frontend stellen wir einen speziellen Hook zur Verfügung, um den Bildanhänge-Status zu verwalten:

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>
{/* Anhänge-Leiste */}
{attachments.map(att => (
<AttachmentItem
key={att.localId}
file={att.file}
status={att.status}
onRemove={() => removeAttachment(att.localId)}
/>
))}
{/* Eingabefeld */}
<textarea onPaste={handlePaste} />
{/* Upload-Button */}
<button onClick={() => fileInputRef.current?.click()}>
Bild hochladen
</button>
</div>
);
}

Dieser Hook kapselt die gesamte Logik des Anhangs-Managements, einschließlich Upload-Status-Tracking, Fehler-Wiederholung, Anhang-Löschen usw. Die Verwendung ist sehr einfach –只需几个 Methoden aufrufen, um den gesamten Prozess abzuschließen. Gutes API-Design ist eigentlich so: einfach zu bedienen, ohne Flexibilität zu verlieren.

Benutzerdefiniertes Protokoll parsen:

// sessionId und imageId aus benutzerdefiniertem Protokoll extrahieren
const parsed = parseHagiImageUrl("hagiimag://session-abc123/20260301-143022-uuid");
// Rückgabe: { sessionId: "session-abc123", imageId: "20260301-143022-uuid" }
// Vorschau-URL aufbauen
const previewUrl = buildPreviewUrl(parsed.sessionId, parsed.imageId);
// Rückgabe: "/api/Images/session-abc123/20260301-143022-uuid/content"

Mit diesen beiden Hilfsfunktionen kann das Frontend einfach zwischen hagiimag://-Protokoll und HTTP-URL konvertieren. Wenn diese Konvertierungslogik gut gekapselt ist, ist die Verwendung viel bequemer.

Backend-Implementierung

Das Backend verwendet ASP.NET Core, der Kern sind ImagesController und ImagesDomainService:

[HttpPost("upload")]
[RequestSizeLimit(50 * 1024 * 1024)]
public async Task<ActionResult<ImageUploadResponseDto>> Upload(
[FromForm] UploadImageFormRequest input)
{
// 1. Anfrage validieren
if (file == null || file.Length == 0)
throw new UserFriendlyException("No file provided");
// 2. Dateityp und -größe validieren
var (isValid, errorMessage) = _imagesDomainService.ValidateImage(
file.FileName, file.ContentType, file.Length);
if (!isValid)
throw new UserFriendlyException(errorMessage);
// 3. Im Dateisystem speichern
await using var stream = file.OpenReadStream();
var result = await _imagesDomainService.UploadImageAsync(
stream,
sessionId,
file.FileName,
file.ContentType,
CurrentUserId,
compress: input.Compress);
// 4. Ergebnis zurückgeben
return Ok(result);
}

Diese Implementierung folgt dem typischen Web-API-Entwicklungsmuster: validieren, verarbeiten, zurückgeben. Zu beachten ist, dass wir ein 50MB-Request-Größen-Limit festgelegt haben, um böswillige Large-File-Uploads zu verhindern. In der Netzwerkwelt ist Vorsicht immer richtig.

Zu beachtende Punkte

Bei der Implementierung müssen einige Details besonders beachtet werden:

Berechtigungsprüfung: Der Bildzugriff muss die Benutzeridentität validieren, um sicherzustellen, dass nur auf Bilder der eigenen Sitzung zugegriffen werden kann. Dies ist eine grundlegende Sicherheitsanforderung, nicht weglassen. Bei Sicherheit – lieber einmal zu viel als zu wenig.

**Pfadsicherheit: sessionId und imageIdstreng validieren, um Path-Traversal-Angriffe zu verhindern. Zum Beispiel Pfade mit../` ablehnen, um zu verhindern, dass Benutzer auf beliebige Dateien im System zugreifen. Wenn solche Randbedingungen gut behandelt werden, wird das System robuster.

Dateibereinigung: Beim Löschen von Sitzungen müssen zugehörige Bilder synchron bereinigt werden, um die Ansammlung von Waisendateien zu vermeiden. Nach langem Lauf können diese Dateien viel Speicherplatz belegen. Rechtzeitige Bereinigung ist auch eine gute Gewohnheit.

Komprimierungsstrategie: Für Screenshot-ähnliche Dateinamen (wie screenshot.png) wird automatisch Komprimierung aktiviert, um Speicherplatz zu sparen. Diese Strategie kann je nach Bedarf angepasst werden. Speicherplatz – sparen, wo man kann.

Fallback-Behandlung: Executoren ohne Multimodal-Unterstützung müssen Bildpfad-Hinweise erhalten, dürfen Bildinformationen nicht stillschweigend verwerfen. Dies ist wichtig, sonst denken Benutzer, die KI habe ihr Bild ignoriert. Bei Benutzererfahrung entscheiden Details über Erfolg oder Misserfolg.

Status-Management: Hochladende Anhänge blockieren das Senden von Nachrichten, fehlgeschlagene Anhänge ermöglichen Wiederholung oder Löschung. Dieses Design gewährleistet die Kohärenz der Benutzererfahrung. Wenn das Status-Management klar ist, fühlen sich Benutzer nicht verwirrt.

Zusammenfassung

Mit dieser vollständigen Bild-Upload- und Erkennungslösung hat HagiCode einen vollständigen geschlossenen Kreislauf von Benutzereingabe bis KI-Erkennung realisiert. Die Kern-Highlights der gesamten Lösung sind:

  • Benutzerdefiniertes hagiimag://-Protokoll realisierte die Standardisierung von Bildreferenzen
  • Dateisystemspeicher vereinfachte die Implementierung und verbesserte die Performance
  • Frontend-Vorschau und KI-Zugriff getrennt balancieren Sicherheit und Benutzerfreundlichkeit
  • Sofortiger Upload optimierte die Benutzererfahrung
  • Kompatibles Design von Multimodal und Text-Fallback gewährleistet Flexibilität

Diese Lösung läuft in HagiCode stabil, das Benutzer-Feedback ist positiv. Wenn Sie ähnliche Funktionen implementieren, hoffe ich, dass diese Erfahrungen für Sie nützlich sind.

Technische Lösungen haben kein absolut richtig oder falsch, nur passend oder nicht passend. Den für das eigene Projekt passenden Weg zu finden, ist am wichtigsten.

Referenzen

开始使用 HagiCode

一次安装,几分钟上手

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