feat: save account model and thinking settings for Hermes
Rebuild & Deploy / rebuild (push) Successful in 1m9s
Rebuild & Deploy / rebuild (push) Successful in 1m9s
This commit is contained in:
1 parent
a45569f8c1
commit
6cb4427210
13 files changed
+798
-16
No files matched your search
+43
-2
@@ -206,7 +206,7 @@ class Lifecycle:
|
||||
await asyncio.gather(*tasks, return_exceptions=True)
|
||||
|
||||
|
||||
def create_app(settings=None, provisioner=None):
|
||||
def create_app(settings=None, provisioner=None, model_catalog=None):
|
||||
settings = settings or Settings()
|
||||
|
||||
@asynccontextmanager
|
||||
@@ -222,6 +222,9 @@ def create_app(settings=None, provisioner=None):
|
||||
if adapter is None:
|
||||
from .provisioner import Provisioner as HermesProvisioner
|
||||
adapter = HermesProvisioner()
|
||||
from .model_catalog import ModelCatalog
|
||||
catalog = model_catalog if model_catalog is not None else ModelCatalog()
|
||||
app.state.model_catalog = catalog
|
||||
app.state.lifecycle = Lifecycle(store, adapter)
|
||||
# Revalidate even previously-ready containers after control restart.
|
||||
for user in store.users():
|
||||
@@ -234,6 +237,8 @@ def create_app(settings=None, provisioner=None):
|
||||
loop.cancel()
|
||||
await asyncio.gather(loop, return_exceptions=True)
|
||||
await app.state.lifecycle.stop()
|
||||
if hasattr(catalog, 'aclose'):
|
||||
await catalog.aclose()
|
||||
if hasattr(adapter, 'aclose'):
|
||||
await adapter.aclose()
|
||||
finally:
|
||||
@@ -315,6 +320,41 @@ def create_app(settings=None, provisioner=None):
|
||||
async def me(user=Depends(current_user)):
|
||||
return {'user': user}
|
||||
|
||||
@app.get('/api/settings/model')
|
||||
async def model_settings(user=Depends(current_user)):
|
||||
try:
|
||||
saved = await asyncio.to_thread(app.state.accounts.get_model_settings, user['id'])
|
||||
except KeyError:
|
||||
raise HTTPException(401, 'Account unavailable') from None
|
||||
try:
|
||||
models = await app.state.model_catalog.models()
|
||||
available, message = True, ''
|
||||
except Exception:
|
||||
models, available = [], False
|
||||
message = 'Model list unavailable. Your saved settings are unchanged; try again.'
|
||||
return {'settings': saved, 'models': models, 'catalog_available': available,
|
||||
'message': message, 'thinking_note': 'Thinking levels are requests. Some models may limit or ignore them.'}
|
||||
|
||||
@app.put('/api/settings/model')
|
||||
async def save_model_settings(request: Request, user=Depends(current_user)):
|
||||
body = await bounded_json(request)
|
||||
if set(body) != {'model', 'thinking_level'}:
|
||||
raise HTTPException(400, 'Only model and thinking_level are accepted')
|
||||
try:
|
||||
models = await app.state.model_catalog.models()
|
||||
except Exception:
|
||||
raise HTTPException(503, 'Model list unavailable. Settings were not changed; try again.') from None
|
||||
selected = next((m for m in models if m['id'] == body.get('model')), None)
|
||||
if selected is None or body.get('thinking_level') not in selected['thinking_levels']:
|
||||
raise HTTPException(400, 'Choose an available model and thinking level')
|
||||
try:
|
||||
saved = await asyncio.to_thread(app.state.accounts.set_model_settings, user['id'], body['model'], body['thinking_level'])
|
||||
except ValueError:
|
||||
raise HTTPException(400, 'Invalid model settings') from None
|
||||
except KeyError:
|
||||
raise HTTPException(401, 'Account unavailable') from None
|
||||
return {'settings': saved, 'message': 'Saved for your account. Applies to your next request.'}
|
||||
|
||||
@app.get('/api/admin/users')
|
||||
async def list_users(user=Depends(administrator)):
|
||||
return {'users': [public_user(u) for u in await asyncio.to_thread(app.state.accounts.users)]}
|
||||
@@ -366,7 +406,8 @@ def create_app(settings=None, provisioner=None):
|
||||
raise HTTPException(404, 'User not found')
|
||||
if user['status'] != 'ready' or not user['hermes_url'] or not user['hermes_api_key']:
|
||||
raise HTTPException(503, 'User Hermes is not ready')
|
||||
return {'user': public_user(user), 'hermes_url': user['hermes_url'], 'hermes_api_key': user['hermes_api_key']}
|
||||
return {'user': public_user(user), 'hermes_url': user['hermes_url'], 'hermes_api_key': user['hermes_api_key'],
|
||||
'model_settings': app.state.accounts.get_model_settings(user['id'])}
|
||||
|
||||
@app.get('/internal/users/{user_id}', dependencies=[Depends(internal_authorized)])
|
||||
async def internal_user(user_id: str):
|
||||
|
||||
Reference in new issue
Block a user