feat: add generation trace and partial-ready workflow status
This commit is contained in:
@@ -17,6 +17,9 @@ from app.schemas.story_schemas import (
|
||||
AchievementItem,
|
||||
FullStoryResponse,
|
||||
GenerateRequest,
|
||||
GenerationJobDetailResponse,
|
||||
GenerationJobSummaryResponse,
|
||||
GenerationProviderStatsResponse,
|
||||
GenerationRequest,
|
||||
GenerationResponse,
|
||||
StoryAssetRetryRequest,
|
||||
@@ -28,6 +31,11 @@ from app.schemas.story_schemas import (
|
||||
StoryResponse,
|
||||
)
|
||||
from app.services import story_service
|
||||
from app.services.generation_jobs import (
|
||||
get_generation_job_detail,
|
||||
get_story_provider_stats,
|
||||
list_story_generation_jobs,
|
||||
)
|
||||
from app.services.memory_service import build_enhanced_memory_context
|
||||
from app.services.provider_router import (
|
||||
generate_image,
|
||||
@@ -65,6 +73,42 @@ async def create_generation(
|
||||
return await story_service.generate_generation_service(request, user.id, db)
|
||||
|
||||
|
||||
@router.get("/generations/jobs/{job_id}", response_model=GenerationJobDetailResponse)
|
||||
async def get_generation_job(
|
||||
job_id: str,
|
||||
user: User = Depends(require_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
"""Get one generation job with ordered workflow events."""
|
||||
return await get_generation_job_detail(db, job_id=job_id, user_id=user.id)
|
||||
|
||||
|
||||
@router.get(
|
||||
"/generations/{story_id}/jobs",
|
||||
response_model=list[GenerationJobSummaryResponse],
|
||||
)
|
||||
async def list_generation_jobs(
|
||||
story_id: int,
|
||||
user: User = Depends(require_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
"""List recent generation jobs for a generated story/storybook."""
|
||||
return await list_story_generation_jobs(db, story_id=story_id, user_id=user.id)
|
||||
|
||||
|
||||
@router.get(
|
||||
"/generations/{story_id}/provider-stats",
|
||||
response_model=GenerationProviderStatsResponse,
|
||||
)
|
||||
async def get_generation_provider_stats(
|
||||
story_id: int,
|
||||
user: User = Depends(require_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
"""Get provider call stats aggregated from generation job events."""
|
||||
return await get_story_provider_stats(db, story_id=story_id, user_id=user.id)
|
||||
|
||||
|
||||
@router.get("/generations/{story_id}", response_model=StoryDetailResponse)
|
||||
async def get_generation(
|
||||
story_id: int,
|
||||
@@ -135,13 +179,14 @@ async def generate_story_stream(
|
||||
|
||||
# Step 1: Generate Content
|
||||
try:
|
||||
result = await generate_story_content(
|
||||
input_type=request.type,
|
||||
data=request.data,
|
||||
education_theme=request.education_theme,
|
||||
memory_context=memory_context,
|
||||
db=db,
|
||||
)
|
||||
result = await generate_story_content(
|
||||
input_type=request.type,
|
||||
data=request.data,
|
||||
education_theme=request.education_theme,
|
||||
memory_context=memory_context,
|
||||
user_id=user.id,
|
||||
db=db,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error("sse_story_generation_failed", error=str(e))
|
||||
yield {"event": "story_failed", "data": json.dumps({"error": str(e)})}
|
||||
@@ -163,6 +208,7 @@ async def generate_story_stream(
|
||||
"child_profile_id": story.child_profile_id,
|
||||
"universe_id": story.universe_id,
|
||||
"generation_status": story.generation_status,
|
||||
"text_status": story.text_status,
|
||||
"image_status": story.image_status,
|
||||
"audio_status": story.audio_status,
|
||||
"last_error": story.last_error,
|
||||
@@ -175,7 +221,12 @@ async def generate_story_stream(
|
||||
await db.commit()
|
||||
try:
|
||||
# Direct call to provider router's generate_image, sharing db session
|
||||
image_url = await generate_image(story.cover_prompt, db=db)
|
||||
image_url = await generate_image(
|
||||
story.cover_prompt,
|
||||
db=db,
|
||||
user_id=user.id,
|
||||
story_id=story.id,
|
||||
)
|
||||
story.image_url = image_url
|
||||
sync_story_status(
|
||||
story,
|
||||
@@ -188,6 +239,7 @@ async def generate_story_stream(
|
||||
{
|
||||
"image_url": image_url,
|
||||
"generation_status": story.generation_status,
|
||||
"text_status": story.text_status,
|
||||
"image_status": story.image_status,
|
||||
"audio_status": story.audio_status,
|
||||
"last_error": story.last_error,
|
||||
@@ -208,6 +260,7 @@ async def generate_story_stream(
|
||||
{
|
||||
"error": str(e),
|
||||
"generation_status": story.generation_status,
|
||||
"text_status": story.text_status,
|
||||
"image_status": story.image_status,
|
||||
"audio_status": story.audio_status,
|
||||
"last_error": story.last_error,
|
||||
@@ -221,6 +274,7 @@ async def generate_story_stream(
|
||||
{
|
||||
"story_id": story.id,
|
||||
"generation_status": story.generation_status,
|
||||
"text_status": story.text_status,
|
||||
"image_status": story.image_status,
|
||||
"audio_status": story.audio_status,
|
||||
"last_error": story.last_error,
|
||||
@@ -296,6 +350,7 @@ async def generate_story_image(
|
||||
return {
|
||||
"image_url": url,
|
||||
"generation_status": story.generation_status,
|
||||
"text_status": story.text_status,
|
||||
"image_status": story.image_status,
|
||||
"audio_status": story.audio_status,
|
||||
"last_error": story.last_error,
|
||||
|
||||
Reference in New Issue
Block a user