Route stable athena-image alias to selected image profile
This commit is contained in:
+7
-4
@@ -5,6 +5,7 @@ import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import secrets
|
||||
import re
|
||||
import socket
|
||||
import threading
|
||||
import time
|
||||
@@ -111,12 +112,12 @@ class Endpoint:
|
||||
return bool(record and record.get('api_token_hash') and secrets.compare_digest(hashlib.sha256(header[7:].encode()).hexdigest(),record['api_token_hash']))
|
||||
def find_profile(self,name,kind):
|
||||
if not isinstance(name,str):raise APIError('model muss den API-Namen eines aktivierten Profils enthalten.')
|
||||
row=next((p for p in self.rows() if p['name']==name and p['kind']==kind and p['enabled']),None)
|
||||
row=next((p for p in self.rows() if (p['name']==name or (kind=='image' and name=='athena-image')) and p['kind']==kind and p['enabled']),None)
|
||||
if not row:raise APIError('Modellprofil nicht aktiviert oder unbekannt.',404,'model_not_found')
|
||||
if not row['runnable']:raise APIError('Profil derzeit nicht ausführbar: '+' '.join(row['blockers']),503,'model_unavailable')
|
||||
return row
|
||||
def model_list(self,kind="chat"):
|
||||
return dict(object='list',data=[dict(id=p['name'],object='model',created=int(p['updated_at']),owned_by='athena-deck') for p in self.rows() if p['enabled'] and p['runnable'] and p['kind']==kind])
|
||||
return dict(object='list',data=[dict(id='athena-image' if kind=='image' else p['name'],object='model',created=int(p['updated_at']),owned_by='athena-deck') for p in self.rows() if p['enabled'] and p['runnable'] and p['kind']==kind])
|
||||
|
||||
class APIHTTPServer(ThreadingHTTPServer):
|
||||
daemon_threads=True
|
||||
@@ -265,7 +266,9 @@ class APIHandler(BaseHTTPRequestHandler):
|
||||
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']
|
||||
if data.get('size',f"{params['width']}x{params['height']}")!=f"{params['width']}x{params['height']}":raise APIError('size muss der im Profil gespeicherten Auflösung entsprechen.')
|
||||
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)
|
||||
@@ -275,7 +278,7 @@ class APIHandler(BaseHTTPRequestHandler):
|
||||
while time.monotonic()<deadline:
|
||||
current=ep.images.status()['job']
|
||||
if not current or current['id']!=job['id']:raise InferenceError('Bildauftrag nicht mehr verfügbar.')
|
||||
if current['state']=='complete':return self.send({'created':int(time.time()),'data':[{'b64_json':base64.b64encode(ep.images.image(job['id'])).decode()}]})
|
||||
if current['state']=='complete':return self.send({'created':int(time.time()),'data':[{'b64_json':base64.b64encode(ep.images.image(job['id'])).decode()}],'athena_deck':{'model':'athena-image','size':f"{profile['parameters']['width']}x{profile['parameters']['height']}",'requested_size':data.get('size'),'size_policy':'profile'}})
|
||||
if current['state']!='running':raise InferenceError(current['phase'])
|
||||
time.sleep(.25)
|
||||
ep.images.stop();raise InferenceError('Zeitlimit der Bildgenerierung überschritten.')
|
||||
|
||||
Reference in New Issue
Block a user