mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-17 10:15:27 -04:00
Odysseus v1.0
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
"""Preset routes — /api/presets GET, /api/presets/custom POST, user templates CRUD."""
|
||||
|
||||
import logging
|
||||
import uuid
|
||||
from typing import Dict, Any, List
|
||||
|
||||
from fastapi import APIRouter, HTTPException, Request, Depends
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from src.request_models import PresetUpdateRequest
|
||||
from core.middleware import require_admin
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class UserTemplateRequest(BaseModel):
|
||||
id: str = ""
|
||||
name: str = Field(..., min_length=1, max_length=100)
|
||||
system_prompt: str = Field("", max_length=10000)
|
||||
temperature: float = Field(1.0, ge=0.0, le=2.0)
|
||||
max_tokens: int = Field(0, ge=0, le=65536)
|
||||
|
||||
|
||||
def setup_preset_routes(preset_manager) -> APIRouter:
|
||||
router = APIRouter(tags=["presets"])
|
||||
|
||||
@router.get("/api/presets")
|
||||
async def get_presets() -> Dict[str, Any]:
|
||||
return preset_manager.presets
|
||||
|
||||
@router.post("/api/presets/custom")
|
||||
async def update_custom_preset(preset_update: PresetUpdateRequest, _admin: None = Depends(require_admin)) -> Dict[str, Any]:
|
||||
try:
|
||||
success = preset_manager.update_custom(
|
||||
preset_update.temperature,
|
||||
preset_update.max_tokens,
|
||||
preset_update.system_prompt,
|
||||
preset_update.name,
|
||||
preset_update.enabled,
|
||||
preset_update.inject_prefix,
|
||||
preset_update.inject_suffix,
|
||||
)
|
||||
if success:
|
||||
return {"success": True, "message": "Custom preset updated"}
|
||||
return {"success": False, "message": "Failed to save preset"}
|
||||
except Exception as e:
|
||||
logger.error(f"Preset update error: {e}")
|
||||
raise HTTPException(500, "Failed to update custom preset")
|
||||
|
||||
@router.get("/api/presets/templates")
|
||||
async def get_user_templates() -> List[Dict]:
|
||||
return preset_manager.get_user_templates()
|
||||
|
||||
@router.post("/api/presets/templates")
|
||||
async def save_user_template(req: UserTemplateRequest, _admin: None = Depends(require_admin)) -> Dict[str, Any]:
|
||||
template = req.model_dump()
|
||||
if not template["id"]:
|
||||
template["id"] = f"user-{uuid.uuid4().hex[:8]}"
|
||||
success = preset_manager.save_user_template(template)
|
||||
if success:
|
||||
return {"success": True, "template": template}
|
||||
return {"success": False, "message": "Failed to save template"}
|
||||
|
||||
@router.delete("/api/presets/templates/{template_id}")
|
||||
async def delete_user_template(template_id: str, _admin: None = Depends(require_admin)) -> Dict[str, Any]:
|
||||
success = preset_manager.delete_user_template(template_id)
|
||||
if success:
|
||||
return {"success": True}
|
||||
return {"success": False, "message": "Failed to delete template"}
|
||||
|
||||
@router.post("/api/presets/expand")
|
||||
async def expand_character_prompt(request: Request) -> Dict[str, Any]:
|
||||
"""Use AI to expand a rough character description into a full system prompt."""
|
||||
from src.ai_interaction import _resolve_model
|
||||
from src.llm_core import llm_call_async
|
||||
|
||||
data = await request.json()
|
||||
draft = (data.get("prompt") or "").strip()
|
||||
name = (data.get("name") or "").strip()
|
||||
|
||||
if not draft and not name:
|
||||
return {"success": False, "message": "Nothing to expand"}
|
||||
|
||||
user_input = ""
|
||||
if name:
|
||||
user_input += f"Character name: {name}\n"
|
||||
if draft:
|
||||
user_input += f"Notes: {draft}\n"
|
||||
|
||||
messages = [
|
||||
{"role": "system", "content": (
|
||||
"You are an expert at writing character system prompts for AI assistants. "
|
||||
"The user will give you a character name and/or rough notes. "
|
||||
"Write a concise, effective system prompt (3-6 sentences) that captures the character's personality, "
|
||||
"speaking style, knowledge areas, and behavioral guidelines. "
|
||||
"Output ONLY the system prompt text — no quotes, no preamble, no explanation."
|
||||
)},
|
||||
{"role": "user", "content": user_input},
|
||||
]
|
||||
|
||||
try:
|
||||
model_spec = data.get("model") or ""
|
||||
url, model, headers = _resolve_model(model_spec)
|
||||
result = await llm_call_async(url, model, messages, temperature=0.8, max_tokens=500, headers=headers)
|
||||
return {"success": True, "prompt": result.strip()}
|
||||
except Exception as e:
|
||||
logger.error(f"Expand prompt failed: {e}")
|
||||
return {"success": False, "message": str(e)}
|
||||
|
||||
# ── Group presets ──
|
||||
@router.get("/api/presets/groups")
|
||||
async def get_group_presets():
|
||||
"""Get saved group chat presets."""
|
||||
return {"groups": preset_manager.get_group_presets()}
|
||||
|
||||
@router.post("/api/presets/groups")
|
||||
async def save_group_presets(request: Request, _admin: None = Depends(require_admin)):
|
||||
"""Save group chat presets."""
|
||||
data = await request.json()
|
||||
preset_manager.save_group_presets(data.get("groups", []))
|
||||
return {"ok": True}
|
||||
|
||||
return router
|
||||
Reference in New Issue
Block a user