AI Enhancement (Gemini)
Automatische Erkennung von Sprache, Land, Kategorie, Keywords und Beschreibung fuer Social Profiles per Google Gemini API.
Ueberblick
Der ChannelLanguageDetector sendet Profildaten (Handle, Titel, Beschreibung, Plattform) an Gemini 2.5 Flash-Lite und empfaengt eine strukturierte JSON-Analyse. Alle AI-generierten Inhalte (Kategorie, Keywords, Beschreibung) sind auf Englisch.
Location: app/Services/AI/ChannelLanguageDetector.php
Erkannte Felder
AI-Felder auf social_profiles
| Spalte | Typ | Beschreibung |
|---|---|---|
language | string | Sprache aus YouTube API (defaultLanguage) |
detected_country | string | AI-erkanntes Land (ISO 3166-1 alpha-2, z.B. DE) |
detected_language | string | AI-erkannte Sprache (ISO 639-1, z.B. de) |
detected_at | timestamp | Zeitpunkt der AI-Analyse |
ai_category | string | AI-erkannte Kategorie (z.B. Gaming) |
ai_category_confidence | string | Confidence: high, medium, low |
ai_keywords | json | Array mit bis zu 10 englischen Keywords |
ai_keywords_confidence | string | Confidence: high, medium, low |
ai_description | string | AI-generierte englische Beschreibung (200-1200 Zeichen) |
ai_description_confidence | string | Nur gespeichert bei high Confidence |
ai_social_links | json | Erkannte Cross-Platform-Handles (high confidence) |
YouTube-Daten (language, country) haben Vorrang -- AI-Erkennung ergaenzt nur fehlende Werte.
Manual Override Felder
Admins koennen AI-Ergebnisse manuell ueberschreiben. Die ai_manual_* Felder haben immer Vorrang vor den AI-Feldern.
| Spalte | Typ | Beschreibung |
|---|---|---|
ai_manual_category | string | Manuell gesetzte Kategorie (ueberschreibt ai_category) |
ai_manual_description | text | Manuell gesetzte Beschreibung (ueberschreibt ai_description) |
ai_manual_keywords | json | Manuell gesetzte Keywords (ueberschreibt ai_keywords) |
ai_manual_edited_at | timestamp | Zeitpunkt der letzten manuellen Aenderung |
ai_manual_edited_by | bigint (FK) | Admin-User-ID |
effective_* Accessors (Dual-Field-System)
Alle Consumer verwenden effective_* Accessors statt direkt ai_* oder ai_manual_* zu lesen:
$profile->effective_category // ai_manual_category ?? ai_category
$profile->effective_description // ai_manual_description ?? ai_description
$profile->effective_keywords // ai_manual_keywords ?? ai_keywords
In Raw-SQL (z.B. Explore, Leaderboards) wird COALESCE(ai_manual_category, ai_category) verwendet.
Consumer (15+ Dateien): Explore Browse/TagCloud/ProfileGrid, Discover, TagManagement, ProfileCategories, PublicExplorerService, CrossPlatformRelatedCalculator, ExploreCategoryDetector, YouTubeResearchKeywordSuggester.
Audit Log
Jede manuelle Aenderung wird in ai_manual_override_logs protokolliert:
| Feld | Typ | Beschreibung |
|---|---|---|
social_profile_id | bigint (FK) | Bearbeitetes Profil |
user_id | bigint (FK) | Admin der die Aenderung vornahm |
field | string | category, description oder keywords |
old_value | text | Vorheriger Wert |
new_value | text | Neuer Wert |
created_at | timestamp | Zeitpunkt |
Location: app/Models/AiManualOverrideLog.php
Kategorien
Genau eine Kategorie wird zugewiesen (26 verfuegbar):
Automotive, Beauty & Fashion, Comedy, Education,
Finance & Business, Fitness & Health, Food & Cooking, Gaming,
Lifestyle, Music, News, Politics,
Pets & Animals, Science, Technology, Sports,
Travel & Adventure, Kids & Family, Movies, TV & Anime,
DIY, Crafts & Maker, Art & Design, Home & Garden,
True Crime, ASMR & Relaxation, Podcasts & Interviews, Other
Nicht zuordenbare Profile erhalten Other als Fallback.
Gemini API Integration
Request
POST https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-lite:generateContent?key={API_KEY}
{
"contents": [{
"parts": [{
"text": "Analyze this youtube profile and provide a comprehensive analysis.\n\nHandle: example\nName: Example Channel\nPlatform: youtube\nURL: https://www.youtube.com/@example\nDescription: ...\nRecent Videos: Video Title 1 | Video Title 2 | ...\nVerified Cross-Platform: @instagram_handle (instagram, 50000 followers)\n\nRespond ONLY in this exact JSON format..."
}]
}],
"generationConfig": {
"temperature": 0.1
}
}
Enriched Prompt (E10)
Der Prompt enthaelt neben den Standard-Profildaten zusaetzlichen Kontext:
| Datenquelle | Beschreibung | Limit |
|---|---|---|
| Handle, Name, URL | Basis-Profildaten | immer |
| Description | Profil-Beschreibung | max 1000 Zeichen |
| Recent Videos | YouTube-Video-Titel (neueste zuerst) | max 10 Titel |
| Verified Cross-Platform | Verifizierte Partner-Profile mit Handle, Plattform und Follower-Zahl | nur cross_profile_verified_at IS NOT NULL |
Video-Titel und Cross-Platform-Kontext verbessern die Kategorie-/Keyword-Erkennung signifikant, besonders bei Profilen mit wenig aussagekraeftiger Beschreibung.
Location: app/Services/AI/ChannelLanguageDetector.php (Methode buildPrompt())
Response-Parsing
Die AI-Antwort wird als JSON geparst mit folgender Validierung:
language: ISO 639-1 (2 Kleinbuchstaben, z.B.de)country: ISO 3166-1 alpha-2 (2 Grossbuchstaben, z.B.DE)category: Muss in der erlaubten Liste sein (Case-insensitive Match, FallbackOther)keywords: Array von Strings, max 10, Lowercase, max 50 Zeichen pro Keyworddescription: Min 100 Zeichen, max 1200 Zeichen (wird abgeschnitten)social_links: Cross-Platform-Handles mit Confidence (optional)
Mindestvoraussetzung: language oder country muss erkannt worden sein, sonst gilt die Analyse als fehlgeschlagen.
Detection Logging
Jede AI-Analyse wird in ai_detection_logs protokolliert:
| Feld | Beschreibung |
|---|---|
social_profile_id | Analysiertes Profil |
type | language_detection |
model | z.B. gemini-2.5-flash-lite |
input_data | Handle, Titel, Description, Platform, URL |
output_data | Geparste AI-Antwort |
raw_response | Vollstaendige Gemini-Response |
status | success oder error |
tokens_used | Token-Verbrauch (aus usageMetadata) |
duration_ms | Antwortzeit in Millisekunden |
Log Pruning
php artisan ai:prune-detection-logs # Default: 7 Tage
php artisan ai:prune-detection-logs --days=14 # Custom Retention
Laeuft taeglich um 02:00 UTC via Scheduler.
Location: app/Console/Commands/PruneAiDetectionLogs.php
Queue-Verarbeitung
Rate Limiting
- Queue:
ai-detection - Max 15 Jobs pro Minute (Rate-Limited)
ShouldBeUniqueInterface verhindert doppelte Verarbeitung
Prioritaet
Profile werden nach Follower-Anzahl sortiert (groesste zuerst), damit populaere Profile priorisiert werden.
Schedule
php artisan social:detect-languages --queue --queue-limit=100
Laeuft alle 6 Stunden. Queued Profile die:
tracking_enabled = truedetected_country IS NULLoderdetected_language IS NULL- Nicht in den letzten 7 Tagen analysiert wurden
- Nicht bereits in der Queue sind
Queue Worker
php artisan queue:work database --queue=ai-detection --sleep=5
Location: app/Jobs/DetectProfileLanguage.php, app/Console/Commands/DetectChannelLanguages.php
Admin UI
AI Enhancements Uebersicht
Route: /admin/ai-enhancements (Admin-Gate geschuetzt)
- Statistiken: Gesamtanalysen, Erfolgs-/Fehlerrate, Profile mit Kategorie/Keywords/Beschreibung
- Tabelle: Badges fuer Language, Country, Category, Keywords, Description
- Detail-Modal: Alle AI-generierten Daten mit Confidence-Levels
- Social Links: Erkannte Cross-Platform-Profile mit URLs
- Quick-Fix Button: "AI bearbeiten" oeffnet den AiFieldEditor direkt aus dem Detail-Modal
Location: app/Livewire/Admin/AiEnhancements/Index.php
AiFieldEditor (Manual Override Modal)
Admin-only Modal-Component zum manuellen Ueberschreiben von AI-Feldern. Kann auf verschiedenen Seiten eingebettet werden:
/admin/ai-enhancements(Detail-Modal)- Watcher Show Seite
- Public Explorer Show Seite
Features
| Feature | Beschreibung |
|---|---|
| Vergleichsansicht | AI-Wert vs. Manual Override nebeneinander |
| Override-Toggles | Checkbox pro Feld (Kategorie, Beschreibung, Keywords) |
| Kategorie-Dropdown | Alle 26 Kategorien aus ChannelLanguageDetector::CATEGORIES |
| Keywords-Input | Komma-getrennte Tags, max 10, max 50 Zeichen, auto-lowercase |
| Audit-History | Letzte 10 Aenderungen mit Admin-Name und Zeitstempel |
| Cross-Platform-Relations | Verify/Unverify + Propagate zu Partner-Profil |
| Explore-Sync | Speichern aktualisiert sofort die Explore-Kategorie via ExploreCategoryDetector::syncSingleProfile() |
Datenfluss
graph TD
A["Admin klickt 'AI bearbeiten'"] --> B["openAiFieldEditor Event"]
B --> C["AiFieldEditor Modal oeffnet"]
C --> D["Admin aendert Felder"]
D --> E["save()"]
E --> F["ai_manual_* Felder aktualisieren"]
E --> G["AiManualOverrideLog Eintraege"]
E --> H["ExploreCategoryDetector::syncSingleProfile"]
F --> I["effective_* Accessors liefern Manual-Werte"]
I --> J["Explore, Discover, PublicExplorer, Tags"]
Cross-Platform Propagation
Admins koennen Kategorie und Keywords von einem Profil auf ein verifiziertes Partner-Profil uebertragen:
- Verify: Admin bestaetigt Cross-Platform-Zuordnung (
cross_profile_verified_at) - Propagieren:
effective_categoryundeffective_keywordswerden alsai_manual_*auf dem Partner gespeichert - Audit-Log: Auch Propagierungen werden vollstaendig geloggt
Location: app/Livewire/Admin/AiFieldEditor.php, resources/views/livewire/admin/ai-field-editor.blade.php
Cross-Platform Social Links
Die AI erkennt Social-Media-Handles anderer Plattformen aus der Profilbeschreibung:
Unterstuetzte Plattformen: instagram, tiktok, twitter, twitch, facebook, spotify, website
Die Quell-Plattform (z.B. YouTube bei YouTube-Profilen) wird automatisch ausgeschlossen. Links werden mit Confidence gespeichert und koennen fuer Cross-Platform-Matching verwendet werden.
Automatische Alerts
Cross-Platform Category Mismatch (E3)
Der DetectProfileLanguage-Job erkennt nach der AI-Erkennung automatisch Kategorie-Abweichungen zwischen verifizierten Cross-Platform-Profilen. Wenn z.B. ein YouTube-Profil als "Gaming" erkannt wird, aber das verifizierte Instagram-Profil "Music" hat, wird eine ai_category_mismatch Admin-Notification erstellt.
Trigger: Nur bei Profilen mit verifizierter Cross-Platform-Verknuepfung (cross_profile_verified_at IS NOT NULL).
Low-Confidence Alert (E6)
Profile mit hoher Reichweite (>= 10.000 Follower) und niedriger AI-Confidence (low) erhalten eine ai_review_needed Admin-Notification. Damit koennen Admins gezielt die wichtigsten Profile manuell pruefen.
Schwellwert: Konfigurierbar via config('postbox.ai_review_min_followers') (Default: 10.000).
Location: app/Jobs/DetectProfileLanguage.php
API Limits (Gemini Tier 2)
Postbox nutzt Gemini 2.5 Flash-Lite im Tier-2-Plan. RPD (Requests Per Day) ist bei 2.5 Flash-Lite unbegrenzt — das Limit liegt nur auf TPM (Tokens Per Minute) und TPD (Tokens Per Day).
| Limit-Typ | Gemini 2.0 Flash (alt) | Gemini 2.5 Flash-Lite (aktuell) |
|---|---|---|
| RPM (Requests Per Minute) | 2.000 | 2.000 |
| RPD (Requests Per Day) | 10.000 | Unbegrenzt (innerhalb TPM) |
| TPM (Tokens Per Minute) | 10.000.000 | 10.000.000 |
| TPD (Tokens Per Day) | 1.000.000.000 | 500.000.000 |
Auswirkung auf den Quota Guard: Da RPD bei 2.5 Flash-Lite unbegrenzt ist, greift GEMINI_DAILY_LIMIT primaer als Sicherheitsnetz fuer Token-Kosten (nicht mehr fuer Request-Limits). Der Guard zaehlt weiterhin Requests pro Tag, um unerwartete Kostenexplosionen zu verhindern.
End-of-Life (EOL) Daten
| Modell | EOL-Datum | Status | Nachfolger |
|---|---|---|---|
Gemini 2.0 Flash (001) | 01. Juni 2026 | Abgeloest | Gemini 2.5 Flash-Lite |
| Gemini 2.5 Flash-Lite (Preview) | 22. Juli 2026 | Aktuell in Nutzung | Gemini 3 Flash-Lite (erwartet) |
Migrationsstrategie: Vor dem EOL-Datum von 2.5 Flash-Lite (22. Juli 2026) muss auf den Nachfolger (voraussichtlich Gemini 3 Flash-Lite) gewechselt werden. Der Wechsel erfordert nur eine Anpassung der GEMINI_MODEL env-Variable — alle drei AI-Services (ChannelLanguageDetector, TagConsolidator, MetaDescriptionGenerator) lesen das Modell aus config('services.gemini.model').
Mehrsprachige Beschreibungen
Uebersicht
AI-generierte englische Beschreibungen werden automatisch in 5 Sprachen uebersetzt:
SocialProfile::TRANSLATION_LANGUAGES = ['de', 'es', 'it', 'fr', 'pt']
Jede Uebersetzung wird mit einer Confidence gespeichert. Der ProfileTranslator nutzt Gemini fuer die Uebersetzung.
Felder auf social_profiles
| Spalte | Beschreibung |
|---|---|
ai_description_de | Deutsche Uebersetzung |
ai_description_de_confidence | Confidence (high/medium/low) |
ai_description_es | Spanische Uebersetzung |
ai_description_es_confidence | Confidence |
ai_description_it | Italienische Uebersetzung |
ai_description_it_confidence | Confidence |
ai_description_fr | Franzoesische Uebersetzung |
ai_description_fr_confidence | Confidence |
ai_description_pt | Portugiesische Uebersetzung |
ai_description_pt_confidence | Confidence |
ai_translated_at | Zeitpunkt der letzten Uebersetzung |
Qualitaetsbewertung
Der DescriptionQualityAssessor bewertet englische Beschreibungen auf einer Skala von 1-10:
| Spalte | Beschreibung |
|---|---|
ai_description_quality_score | Qualitaetsscore (1-10) |
Commands
php artisan ai:translate-descriptions # Uebersetzt englische Beschreibungen
php artisan ai:assess-quality # Bewertet Beschreibungsqualitaet
Zugriff auf Uebersetzungen
$profile->getAiDescriptionForLocale('de') // Deutsche Beschreibung, Fallback auf EN
$profile->getAiDescriptionConfidenceForLocale('de') // Confidence fuer deutsch
$profile->availableTranslations() // ['de', 'es', ...] verfuegbare Sprachen
Location: app/Services/AI/ProfileTranslator.php, app/Services/AI/DescriptionQualityAssessor.php
.env Variablen
| Variable | Default | Beschreibung |
|---|---|---|
GEMINI_API_KEY | -- | Google Gemini API Key |
GEMINI_MODEL | gemini-2.5-flash-lite | Gemini-Modell (konfigurierbar in config/services.php) |
AI_ENHANCER_RATE_PER_MINUTE | 14 | Max. Gemini API Calls pro Minute (Selbst-Throttling, weit unter RPM-Limit) |
AI_ENHANCER_COOLDOWN_DAYS | 365 | Tage bis ein Profil erneut analysiert wird |
GEMINI_DAILY_LIMIT | 9000 | Taegliches API-Call-Limit (Sicherheitsnetz fuer Token-Kosten) |