Add profile-aware image reference editing

This commit is contained in:
Mikei386 committed 2026-09-29 20:17:20 +02:00
1 parent 67cf57a5b7
commit f1ccb02e10
11 files changed
+156 -21

No files matched your search

+16 -4
View File
@@ -183,6 +183,15 @@ class APIHandler(BaseHTTPRequestHandler):
if self.command!='POST':raise APIError('Route nicht gefunden.',404)
if ep.video and ep.scheduler.gpu_mode!='llm' and self.path!='/v1/audio/transcriptions':raise APIError('Video-Modus aktiv; Chat-, Bild- und TTS-Aufträge sind gesperrt. Auf LLM zurückschalten.',503,'video_mode_active')
if self.path=='/v1/audio/transcriptions':return self.transcription(ep)
if self.path=='/v1/images/edits':
from image_upload import read_image_upload
try:
fields,images=read_image_upload(self)
if not images:raise ValueError('Mindestens ein Referenzbild erforderlich.')
if set(fields)-{'model','prompt','size','n','response_format'}:raise ValueError('Nicht unterstützte Bildparameter.')
fields['n']=int(fields.get('n','1'))
return self.image(ep,fields,images)
except ValueError as exc:raise APIError(str(exc)) from None
if self.path not in ('/v1/chat/completions','/v1/images/generations','/v1/audio/speech'):raise APIError('Route nicht implementiert.',404)
if self.headers.get('Transfer-Encoding'):raise APIError('Chunked Upload wird nicht unterstützt.')
try:length=int(self.headers.get('Content-Length','0'))
@@ -286,18 +295,21 @@ class APIHandler(BaseHTTPRequestHandler):
self.wfile.write(chunk);self.wfile.flush()
raise InferenceError('Zeitlimit der Streaming-Antwort überschritten.')
finally:conn.close()
def image(self,ep,data):
def image(self,ep,data,reference_images=None):
if set(data)-{'model','prompt','n','size','response_format','user'}:raise APIError('Nicht unterstützte Bildparameter. Schritte/Guidance/Seed stehen im Profil.')
if data.get('n',1)!=1 or data.get('response_format','b64_json')!='b64_json':raise APIError('Unterstützt werden n=1 und response_format=b64_json.')
profile=ep.find_profile(data.get('model'),'image');params=profile['parameters']
from profiles import image_capabilities
if len(reference_images or [])>image_capabilities(profile.get('model'))['reference_images']:raise APIError('Das aktive Bildprofil unterstützt diese Anzahl Referenzbilder nicht.')
size=data.get('size')
if size is not None and (not isinstance(size,str) or (size!='auto' and not re.fullmatch(r'[1-9][0-9]{1,4}x[1-9][0-9]{1,4}',size))):raise APIError('size muss auto oder eine Auflösung wie 1024x1024 sein.')
# The selected profile owns resource limits; client size is only a preference.
def allowed():return ep.allowed() and any(p['id']==profile['id'] and p['revision']==profile['revision'] and p['enabled'] for p in ep.rows())
with ep.scheduler.lease(('image',),allowed=allowed):
return self.generate_image(ep,profile,data)
def generate_image(self,ep,profile,data):
job=ep.images.start(profile['id'],data.get('prompt'),reserved=True)
return self.generate_image(ep,profile,data,reference_images or [])
def generate_image(self,ep,profile,data,reference_images=None):
options={'reference_images':reference_images} if reference_images else {}
job=ep.images.start(profile['id'],data.get('prompt'),reserved=True,**options)
deadline=time.monotonic()+2100
while time.monotonic()<deadline:
current=ep.images.status()['job']