Spaces:
Building
Building
Update admin_routes.py
Browse files- admin_routes.py +103 -4
admin_routes.py
CHANGED
@@ -139,6 +139,22 @@ class APIUpdate(BaseModel):
|
|
139 |
class TestRequest(BaseModel):
|
140 |
test_type: str # "all", "ui", "backend", "integration", "spark"
|
141 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
142 |
# ===================== Helpers =====================
|
143 |
def verify_token(credentials: HTTPAuthorizationCredentials = Depends(security)) -> str:
|
144 |
"""Verify JWT token and return username"""
|
@@ -408,9 +424,14 @@ async def get_environment(username: str = Depends(verify_token)):
|
|
408 |
"work_mode": env_config.get("work_mode", "on-premise"),
|
409 |
"cloud_token": env_config.get("cloud_token", ""),
|
410 |
"spark_endpoint": env_config.get("spark_endpoint", "http://localhost:7861"),
|
411 |
-
"internal_prompt": env_config.get("internal_prompt", "")
|
|
|
|
|
|
|
|
|
412 |
}
|
413 |
|
|
|
414 |
@router.put("/environment")
|
415 |
async def update_environment(
|
416 |
update: EnvironmentUpdate,
|
@@ -423,35 +444,113 @@ async def update_environment(
|
|
423 |
if update.work_mode in ("gpt4o", "gpt4o-mini"):
|
424 |
if not update.cloud_token:
|
425 |
raise HTTPException(status_code=400, detail="OpenAI API key is required for GPT modes")
|
426 |
-
# Basic format check for OpenAI key
|
427 |
if not update.cloud_token.startswith("sk-") and not update.cloud_token.startswith("enc:"):
|
428 |
raise HTTPException(status_code=400, detail="Invalid OpenAI API key format")
|
429 |
elif update.work_mode in ("hfcloud", "cloud"):
|
430 |
if not update.cloud_token:
|
431 |
raise HTTPException(status_code=400, detail="Cloud token is required for cloud modes")
|
432 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
433 |
# Spark endpoint validation
|
434 |
if update.work_mode not in ("gpt4o", "gpt4o-mini") and not update.spark_endpoint:
|
435 |
raise HTTPException(status_code=400, detail="Spark endpoint is required for non-GPT modes")
|
436 |
|
|
|
|
|
|
|
437 |
# Update config
|
438 |
config["config"]["work_mode"] = update.work_mode
|
439 |
config["config"]["cloud_token"] = update.cloud_token or ""
|
440 |
config["config"]["spark_endpoint"] = update.spark_endpoint
|
441 |
config["config"]["internal_prompt"] = update.internal_prompt or ""
|
|
|
|
|
|
|
|
|
442 |
config["config"]["last_update_date"] = get_timestamp()
|
443 |
config["config"]["last_update_user"] = username
|
444 |
|
445 |
# Add activity log
|
446 |
add_activity_log(config, username, "UPDATE_ENVIRONMENT", "config", "environment",
|
447 |
-
"environment", f"Changed to {update.work_mode}")
|
448 |
|
449 |
# Save
|
450 |
save_config(config)
|
451 |
|
452 |
-
log(f"✅ Environment updated to {update.work_mode} by {username}")
|
453 |
return {"success": True}
|
454 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
455 |
# ===================== Project Endpoints =====================
|
456 |
@router.get("/projects/names")
|
457 |
def list_enabled_projects():
|
|
|
139 |
class TestRequest(BaseModel):
|
140 |
test_type: str # "all", "ui", "backend", "integration", "spark"
|
141 |
|
142 |
+
class EnvironmentUpdate(BaseModel):
|
143 |
+
work_mode: str
|
144 |
+
cloud_token: Optional[str] = None
|
145 |
+
spark_endpoint: str
|
146 |
+
internal_prompt: Optional[str] = None
|
147 |
+
tts_engine: str = "no_tts"
|
148 |
+
tts_engine_api_key: Optional[str] = None
|
149 |
+
stt_engine: str = "no_stt"
|
150 |
+
stt_engine_api_key: Optional[str] = None
|
151 |
+
|
152 |
+
class TTSRequest(BaseModel):
|
153 |
+
text: str
|
154 |
+
voice_id: Optional[str] = None
|
155 |
+
model_id: Optional[str] = None
|
156 |
+
output_format: Optional[str] = "mp3_44100_128"
|
157 |
+
|
158 |
# ===================== Helpers =====================
|
159 |
def verify_token(credentials: HTTPAuthorizationCredentials = Depends(security)) -> str:
|
160 |
"""Verify JWT token and return username"""
|
|
|
424 |
"work_mode": env_config.get("work_mode", "on-premise"),
|
425 |
"cloud_token": env_config.get("cloud_token", ""),
|
426 |
"spark_endpoint": env_config.get("spark_endpoint", "http://localhost:7861"),
|
427 |
+
"internal_prompt": env_config.get("internal_prompt", ""),
|
428 |
+
"tts_engine": env_config.get("tts_engine", "no_tts"),
|
429 |
+
"tts_engine_api_key": env_config.get("tts_engine_api_key", ""),
|
430 |
+
"stt_engine": env_config.get("stt_engine", "no_stt"),
|
431 |
+
"stt_engine_api_key": env_config.get("stt_engine_api_key", "")
|
432 |
}
|
433 |
|
434 |
+
|
435 |
@router.put("/environment")
|
436 |
async def update_environment(
|
437 |
update: EnvironmentUpdate,
|
|
|
444 |
if update.work_mode in ("gpt4o", "gpt4o-mini"):
|
445 |
if not update.cloud_token:
|
446 |
raise HTTPException(status_code=400, detail="OpenAI API key is required for GPT modes")
|
|
|
447 |
if not update.cloud_token.startswith("sk-") and not update.cloud_token.startswith("enc:"):
|
448 |
raise HTTPException(status_code=400, detail="Invalid OpenAI API key format")
|
449 |
elif update.work_mode in ("hfcloud", "cloud"):
|
450 |
if not update.cloud_token:
|
451 |
raise HTTPException(status_code=400, detail="Cloud token is required for cloud modes")
|
452 |
|
453 |
+
# TTS/STT validation
|
454 |
+
if update.tts_engine not in ("no_tts", "elevenlabs", "blaze"):
|
455 |
+
raise HTTPException(status_code=400, detail="Invalid TTS engine")
|
456 |
+
|
457 |
+
if update.stt_engine not in ("no_stt", "elevenlabs", "flicker"):
|
458 |
+
raise HTTPException(status_code=400, detail="Invalid STT engine")
|
459 |
+
|
460 |
+
if update.tts_engine != "no_tts" and not update.tts_engine_api_key:
|
461 |
+
raise HTTPException(status_code=400, detail=f"{update.tts_engine} API key is required")
|
462 |
+
|
463 |
+
if update.stt_engine != "no_stt" and not update.stt_engine_api_key:
|
464 |
+
raise HTTPException(status_code=400, detail=f"{update.stt_engine} API key is required")
|
465 |
+
|
466 |
# Spark endpoint validation
|
467 |
if update.work_mode not in ("gpt4o", "gpt4o-mini") and not update.spark_endpoint:
|
468 |
raise HTTPException(status_code=400, detail="Spark endpoint is required for non-GPT modes")
|
469 |
|
470 |
+
# Encrypt API keys if needed
|
471 |
+
from encryption_utils import encrypt
|
472 |
+
|
473 |
# Update config
|
474 |
config["config"]["work_mode"] = update.work_mode
|
475 |
config["config"]["cloud_token"] = update.cloud_token or ""
|
476 |
config["config"]["spark_endpoint"] = update.spark_endpoint
|
477 |
config["config"]["internal_prompt"] = update.internal_prompt or ""
|
478 |
+
config["config"]["tts_engine"] = update.tts_engine
|
479 |
+
config["config"]["tts_engine_api_key"] = encrypt(update.tts_engine_api_key) if update.tts_engine_api_key else ""
|
480 |
+
config["config"]["stt_engine"] = update.stt_engine
|
481 |
+
config["config"]["stt_engine_api_key"] = encrypt(update.stt_engine_api_key) if update.stt_engine_api_key else ""
|
482 |
config["config"]["last_update_date"] = get_timestamp()
|
483 |
config["config"]["last_update_user"] = username
|
484 |
|
485 |
# Add activity log
|
486 |
add_activity_log(config, username, "UPDATE_ENVIRONMENT", "config", "environment",
|
487 |
+
"environment", f"Changed to {update.work_mode}, TTS: {update.tts_engine}, STT: {update.stt_engine}")
|
488 |
|
489 |
# Save
|
490 |
save_config(config)
|
491 |
|
492 |
+
log(f"✅ Environment updated to {update.work_mode} with TTS: {update.tts_engine} by {username}")
|
493 |
return {"success": True}
|
494 |
|
495 |
+
# ===================== TTS Endpoints =====================
|
496 |
+
@router.post("/tts/generate")
|
497 |
+
async def generate_tts(
|
498 |
+
request: TTSRequest,
|
499 |
+
username: str = Depends(verify_token)
|
500 |
+
):
|
501 |
+
"""Generate TTS audio from text"""
|
502 |
+
try:
|
503 |
+
config = load_config()
|
504 |
+
env_config = config.get("config", {})
|
505 |
+
|
506 |
+
tts_engine = env_config.get("tts_engine", "no_tts")
|
507 |
+
if tts_engine == "no_tts":
|
508 |
+
raise HTTPException(status_code=400, detail="TTS is not configured")
|
509 |
+
|
510 |
+
# Get TTS provider
|
511 |
+
from config_provider import ConfigProvider
|
512 |
+
cfg = ConfigProvider.get()
|
513 |
+
api_key = cfg.global_config.get_tts_api_key()
|
514 |
+
|
515 |
+
if not api_key:
|
516 |
+
raise HTTPException(status_code=400, detail="TTS API key not configured")
|
517 |
+
|
518 |
+
# Import here to avoid circular dependency
|
519 |
+
from tts_interface import create_tts_provider
|
520 |
+
|
521 |
+
tts_provider = create_tts_provider(tts_engine, api_key)
|
522 |
+
if not tts_provider:
|
523 |
+
raise HTTPException(status_code=500, detail="Failed to create TTS provider")
|
524 |
+
|
525 |
+
log(f"🎤 Generating TTS for {len(request.text)} characters using {tts_engine}")
|
526 |
+
|
527 |
+
# Generate audio
|
528 |
+
audio_data = await tts_provider.synthesize(
|
529 |
+
text=request.text,
|
530 |
+
voice_id=request.voice_id,
|
531 |
+
model_id=request.model_id,
|
532 |
+
output_format=request.output_format
|
533 |
+
)
|
534 |
+
|
535 |
+
# Return audio data
|
536 |
+
from fastapi.responses import Response
|
537 |
+
|
538 |
+
content_type = "audio/mpeg" if request.output_format.startswith("mp3") else "audio/wav"
|
539 |
+
|
540 |
+
return Response(
|
541 |
+
content=audio_data,
|
542 |
+
media_type=content_type,
|
543 |
+
headers={
|
544 |
+
"Content-Disposition": f"attachment; filename=tts_output.{request.output_format.split('_')[0]}"
|
545 |
+
}
|
546 |
+
)
|
547 |
+
|
548 |
+
except HTTPException:
|
549 |
+
raise
|
550 |
+
except Exception as e:
|
551 |
+
log(f"❌ TTS generation error: {e}")
|
552 |
+
raise HTTPException(status_code=500, detail=str(e))
|
553 |
+
|
554 |
# ===================== Project Endpoints =====================
|
555 |
@router.get("/projects/names")
|
556 |
def list_enabled_projects():
|