"""Read-only, conservative mapping to Deck's maintained execution adapters.""" from catalog import file_role from stt import supported as stt_supported from profiles import image_recipe, video_recipe from tts_runtime import REPO, REVISION def _assess(model, installed, profile=None): kind=model.get('kind'); filename=model.get('file',''); repo=model.get('repo','') meta=model.get('runtime_metadata') if isinstance(model.get('runtime_metadata'),dict) else {} architecture=meta.get('architecture') if isinstance(meta.get('architecture'),str) else None result=dict(state='unsupported',label='Noch nicht unterstützt',runtime=None,installed=False,route=None,components=[],family=architecture or 'Unbekannt',evidence='Hub-Metadaten' if architecture else 'Keine ausreichenden Metadaten',message='Für dieses Modell ist in Deck noch kein geprüfter Ausführungsweg hinterlegt. Herunterladen und Aufbewahren ist möglich; eine Installation allein genügt nicht.') if not file_role(filename)['profile_eligible']: result.update(state='component',label='Zusatzdatei',message='Diese Datei wird einem kompatiblen Modellprofil zugeordnet und benötigt keine eigene Laufzeit.') return result if kind=='stt' and stt_supported(model): result['family']='Qwen3-ASR 0.6B' result.update(runtime='llama.cpp · Qwen3-ASR auf CPU',route='#stt-runtime',components=['Passender Audio-Projektor (unter Einrichten herunterladen)']) elif kind=='image' and image_recipe(model): result['family']='FLUX.2 Klein 9B' if 'FLUX' in filename.upper() else 'Qwen Image 2.1' result.update(runtime='ComfyUI + ComfyUI-GGUF',route='#image-runtime',components=[x['label'] for x in image_recipe(model).values()]) elif kind=='audio' and repo==REPO and filename=='model.safetensors' and model.get('revision')==REVISION: result['family']='Qwen3-TTS CustomVoice' result.update(runtime='Qwen3-TTS CustomVoice',route='#tts-runtime',components=['Vollständiges Modellpaket und Sprach-Tokenizer (im Einrichtungsassistenten enthalten)']) elif kind=='chat' and filename.lower().endswith('.gguf'): result.update(runtime='llama.cpp',route='#runtime',state='check',label='Kompatibilität beim Laden prüfen',message='llama.cpp ist der mögliche Ausführungsweg für dieses Chat-GGUF. Architektur und gewählte Optionen müssen vom installierten Build unterstützt werden. Der Testchat prüft die tatsächliche Ausführung.') elif kind=='image' and filename.lower().endswith(('.safetensors','.gguf')) and (meta.get('pipeline_tag') in ('text-to-image','image-to-image') or meta.get('library_name') in ('diffusers','comfyui')): result.update(state='workflow_missing',label='Bildfamilie erkannt · Workflow fehlt',runtime='ComfyUI (vorhandene Bildlaufzeit prüfen)',installed=bool(installed.get('image')),route='#image-runtime',message='Hub-Metadaten ordnen die Datei einer Bildpipeline zu. Deck hat bereits eine gemeinsame Bildlaufzeit; ein neuer Build ist nicht automatisch nötig. Für diese Modellvariante fehlen noch ein geprüfter ComfyUI-Workflow und die genaue Komponentenliste. Bis dahin kann sie nicht gestartet werden.') if not architecture:result['family']='Bildpipeline laut Hugging Face' elif kind=='stt': result.update(message='Für diese STT-Datei fehlt die Anbindung. Die geprüfte llama.cpp-Variante von Qwen3-ASR kann unter Einrichten zusätzlich geladen und ausdrücklich einem Profil zugeordnet werden.',alternative=dict(route='#stt-runtime',label='Unterstützte STT-Alternative einrichten (Modellwechsel)')) elif kind=='audio': result.update(message='Dieses TTS-Modell wird noch nicht ausgeführt. Deck unterstützt derzeit die festgelegte Qwen3-TTS-CustomVoice-Variante mit eingebauten Stimmen. MLX, Base mit Referenzstimme und andere TTS-Architekturen benötigen andere Anbindungen.',alternative=dict(route='#tts-runtime',label='Unterstützte TTS-Alternative ansehen (Modellwechsel)')) if video_recipe(model): result['family']='LTX 2.5' result.update(runtime='LTX Original oder ComfyUI · LTX 2.5',state='runtime_missing',label='Komponenten und Video-Laufzeit einrichten',route='#video',components=[x['label'] for x in video_recipe(model).values()],message='Im Bereich Video LTX Original für LTX DeskWEB oder die vorhandene ComfyUI-Laufzeit wählen. Gewichte und passende Komponenten derselben Quellversion werden wiederverwendet.') if not result['runtime']:return result result['installed']=bool(installed.get(kind)) if kind!='chat' and result['state']!='workflow_missing': result.update(state='setup',label='Unterstützt – Einrichtung prüfen',message='Die Laufzeit wird für kompatible Modelle gemeinsam genutzt. Modellabhängige Komponenten werden dem jeweiligen Profil zugeordnet.') if not result['installed'] and result['state']!='workflow_missing': result.update(state='runtime_missing',label='Passende Laufzeit fehlt') if profile: result['blockers']=profile.get('blockers',[]) if profile.get('runnable'): result.update(state='ready',label='Ausführbar – Laufzeit eingerichtet') elif result['installed']: result.update(state='profile_incomplete',label='Profil prüfen – Voraussetzungen fehlen') return result def assess(model, installed, profile=None): result=_assess(model,installed,profile) result['candidates']=[] if result['state']=='component':return result kind=model.get('kind');repo=model.get('repo','').lower();name=model.get('file','').lower() meta=model.get('runtime_metadata') or {};family=str(meta.get('architecture') or '').lower() def add(id,label,key,route,reason,maintained=True): result['candidates'].append(dict(id=id,label=label,installed=bool(installed.get(key)),route=route,installation_available=maintained,evidence=reason)) if result.get('runtime'): add('current',result['runtime'],kind,result['route'],'Vorhandene Deck-Zuordnung') if kind=='music' and repo=='audio-cpp/yue2-3b-gguf' and name.startswith('yue2-3b-') and name.endswith('.gguf'): result.update(family='YuE2',evidence='audio-cpp/Yue2-3B-GGUF · Hauptmodell',state='adapter_missing',label='YuE2 erkannt · Deck-Worker fehlt',message='Passende Laufzeit: audio.cpp. Sie kann einmalig heruntergeladen und gebaut werden. Zur Generierung fehlen noch der Deck-Musikworker und die Ladypoly-Anbindung. Installation allein schaltet dieses Modell nicht frei.',components=['YuE2-VAE GGUF','Modell-/Generierungskonfiguration, VAE-Konfiguration und Qwen-Tokenizer (sidecars)']) add('audio_cpp','audio.cpp','audio_cpp','#audio-cpp-runtime','Geprüfte GGUF-Quelle für die YuE2-Modellfamilie') elif kind=='music' and ('yue2' in repo or 'yue2' in family): result.update(family='YuE2',evidence='Repository-/Architekturhinweis; Ausführung ungeprüft') add('yue2','YuE2 Python / PyTorch','yue2',None,'Originale YuE2-Pipeline; Originalgewichte erforderlich',False) if kind in ('audio','stt','music','voice') and not result['candidates']: if 'audio-cpp/' in repo and name.endswith('.gguf'): add('audio_cpp','audio.cpp','audio_cpp','#audio-cpp-runtime','audio-cpp-Repository; konkrete Familie und Zusatzdateien noch prüfen') elif meta.get('library_name')=='transformers': add('transformers','Hugging Face Transformers / PyTorch','transformers',None,'Hub nennt Transformers; modellabhängiger Worker erforderlich',False) if kind=='video' and not result['candidates'] and meta.get('library_name')=='diffusers': add('diffusers','Diffusers / PyTorch','diffusers',None,'Hub nennt Diffusers; passende Video-Pipeline noch prüfen',False) if not result['candidates']: # Category-level options are explicit research hints, never compatibility claims. options={'chat':('llama.cpp','chat','#runtime'), 'image':('ComfyUI','image','#image-runtime'), 'video':('ComfyUI','image','#image-runtime'), 'audio':('audio.cpp','audio_cpp','#audio-cpp-runtime'), 'stt':('audio.cpp','audio_cpp','#audio-cpp-runtime'), 'music':('audio.cpp','audio_cpp','#audio-cpp-runtime'), 'voice':('audio.cpp','audio_cpp','#audio-cpp-runtime')} if kind in options: label,key,route=options[kind] add('category',label,key,route,'Option für diese Kategorie; Kompatibilität mit dieser unbekannten Modellfamilie NICHT bestätigt') result['candidate_message']='Keine passende Laufzeit zuverlässig ermittelt. Modellkarte und Architektur müssen geprüft werden; keine automatische Installation auf Verdacht.' return result