feat: add NSFW script generation feature and Grok API configuration
This commit is contained in:
@@ -26,6 +26,8 @@ from schemas.audiobook import (
|
||||
ScriptGenerationRequest,
|
||||
SynopsisGenerationRequest,
|
||||
ContinueScriptRequest,
|
||||
NsfwSynopsisGenerationRequest,
|
||||
NsfwScriptGenerationRequest,
|
||||
)
|
||||
from core.config import settings
|
||||
|
||||
@@ -33,6 +35,13 @@ logger = logging.getLogger(__name__)
|
||||
router = APIRouter(prefix="/audiobook", tags=["audiobook"])
|
||||
|
||||
|
||||
async def require_nsfw(current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
|
||||
from db.crud import can_user_use_nsfw
|
||||
if not can_user_use_nsfw(current_user):
|
||||
raise HTTPException(status_code=403, detail="NSFW access not granted")
|
||||
return current_user
|
||||
|
||||
|
||||
def _project_to_response(project) -> AudiobookProjectResponse:
|
||||
return AudiobookProjectResponse(
|
||||
id=project.id,
|
||||
@@ -268,6 +277,86 @@ async def continue_script(
|
||||
return {"message": f"Continuing script generation ({additional_chapters} chapters)", "project_id": project_id}
|
||||
|
||||
|
||||
@router.post("/projects/generate-synopsis-nsfw")
|
||||
async def generate_synopsis_nsfw(
|
||||
data: NsfwSynopsisGenerationRequest,
|
||||
current_user: User = Depends(require_nsfw),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
from db.crud import get_system_setting
|
||||
if not get_system_setting(db, "grok_api_key") or not get_system_setting(db, "grok_base_url"):
|
||||
raise HTTPException(status_code=400, detail="Grok config not set. Please configure Grok API key first.")
|
||||
|
||||
from core.audiobook_service import _get_grok_service
|
||||
llm = _get_grok_service(db)
|
||||
|
||||
system_prompt = (
|
||||
"你是一位专业的成人小说策划师,擅长根据创作参数生成引人入胜的故事简介。"
|
||||
"请根据用户提供的类型、风格、主角、冲突等参数,生成一段200-400字的中文故事简介。"
|
||||
"简介需涵盖:世界观背景、主角基本情况、核心矛盾冲突、故事基调。"
|
||||
"直接输出简介正文,不要加任何前缀标题或说明文字。"
|
||||
)
|
||||
parts = [f"类型:{data.genre}"]
|
||||
if data.subgenre:
|
||||
parts.append(f"子类型:{data.subgenre}")
|
||||
if data.protagonist_type:
|
||||
parts.append(f"主角类型:{data.protagonist_type}")
|
||||
if data.tone:
|
||||
parts.append(f"故事基调:{data.tone}")
|
||||
if data.conflict_scale:
|
||||
parts.append(f"冲突规模:{data.conflict_scale}")
|
||||
parts.append(f"角色数量:约{data.num_characters}个主要角色")
|
||||
parts.append(f"故事体量:约{data.num_chapters}章")
|
||||
user_message = "\n".join(parts) + "\n\n请生成故事简介:"
|
||||
|
||||
try:
|
||||
synopsis = await llm.chat(system_prompt, user_message)
|
||||
except Exception as e:
|
||||
logger.error(f"NSFW synopsis generation failed: {e}")
|
||||
raise HTTPException(status_code=500, detail=f"Grok generation failed: {str(e)}")
|
||||
|
||||
return {"synopsis": synopsis}
|
||||
|
||||
|
||||
@router.post("/projects/generate-script-nsfw", response_model=AudiobookProjectResponse, status_code=status.HTTP_201_CREATED)
|
||||
async def create_nsfw_script_project(
|
||||
data: NsfwScriptGenerationRequest,
|
||||
current_user: User = Depends(require_nsfw),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
from db.crud import get_system_setting
|
||||
if not get_system_setting(db, "grok_api_key") or not get_system_setting(db, "grok_base_url"):
|
||||
raise HTTPException(status_code=400, detail="Grok config not set. Please configure Grok API key first.")
|
||||
|
||||
script_config = data.model_dump()
|
||||
script_config["nsfw_mode"] = True
|
||||
|
||||
project = crud.create_audiobook_project(
|
||||
db=db,
|
||||
user_id=current_user.id,
|
||||
title=data.title,
|
||||
source_type="ai_generated",
|
||||
script_config=script_config,
|
||||
)
|
||||
|
||||
from core.audiobook_service import generate_ai_script_nsfw
|
||||
from core.database import SessionLocal
|
||||
|
||||
project_id = project.id
|
||||
user_id = current_user.id
|
||||
|
||||
async def run():
|
||||
async_db = SessionLocal()
|
||||
try:
|
||||
db_user = crud.get_user_by_id(async_db, user_id)
|
||||
await generate_ai_script_nsfw(project_id, db_user, async_db)
|
||||
finally:
|
||||
async_db.close()
|
||||
|
||||
asyncio.create_task(run())
|
||||
return _project_to_response(project)
|
||||
|
||||
|
||||
@router.get("/projects/{project_id}", response_model=AudiobookProjectDetail)
|
||||
async def get_project(
|
||||
project_id: int,
|
||||
|
||||
Reference in New Issue
Block a user