Fix: Improve podcast analysis LLM prompt and skip bible generation in podcast mode

- Add pandas to requirements-podcast.txt for usage tracking
- Fix LLM prompt to return plain strings instead of objects for enhanced_ideas
- Add object-to-string normalization for LLM responses that return objects
- Skip bible generation in podcast-only mode (onboarding disabled)
- Skip alerts polling in AlertsBadge when in podcast-only demo mode
This commit is contained in:
ajaysi
2026-04-06 15:19:23 +05:30
parent b5ab46a749
commit 348839be36
3 changed files with 65 additions and 14 deletions

View File

@@ -19,6 +19,7 @@ from services.llm_providers.main_image_generation import generate_image
from services.podcast_bible_service import PodcastBibleService from services.podcast_bible_service import PodcastBibleService
from utils.asset_tracker import save_asset_to_library from utils.asset_tracker import save_asset_to_library
from loguru import logger from loguru import logger
import os
from ..constants import PODCAST_IMAGES_DIR from ..constants import PODCAST_IMAGES_DIR
from ..models import ( from ..models import (
PodcastAnalyzeRequest, PodcastAnalyzeRequest,
@@ -27,6 +28,11 @@ from ..models import (
PodcastEnhanceIdeaResponse PodcastEnhanceIdeaResponse
) )
# Check if running in podcast-only demo mode
def _is_podcast_only_mode() -> bool:
"""Check if podcast-only demo mode is enabled."""
return os.getenv("ALWRITY_ENABLED_FEATURES", "").strip().lower() == "podcast"
router = APIRouter() router = APIRouter()
@@ -42,19 +48,31 @@ async def enhance_podcast_idea(
user_id = require_authenticated_user(current_user) user_id = require_authenticated_user(current_user)
# Serialize Bible context if provided or generate from onboarding # Serialize Bible context if provided or generate from onboarding
# In podcast-only mode, skip bible generation since onboarding is disabled
bible_context = "" bible_context = ""
try: if not _is_podcast_only_mode():
bible_service = PodcastBibleService() try:
bible_service = PodcastBibleService()
if request.bible:
from models.podcast_bible_models import PodcastBible
bible_data = PodcastBible(**request.bible)
bible_context = bible_service.serialize_bible(bible_data)
else:
# Generate from onboarding data directly
bible_obj = bible_service.generate_bible(user_id, "temp_enhance")
bible_context = bible_service.serialize_bible(bible_obj)
except Exception as exc:
logger.warning(f"[Podcast Enhance] Failed to parse or generate bible context: {exc}")
else:
# In podcast mode, use the provided bible directly if available
if request.bible: if request.bible:
from models.podcast_bible_models import PodcastBible try:
bible_data = PodcastBible(**request.bible) from models.podcast_bible_models import PodcastBible
bible_context = bible_service.serialize_bible(bible_data) bible_data = PodcastBible(**request.bible)
else: bible_service = PodcastBibleService()
# Generate from onboarding data directly bible_context = bible_service.serialize_bible(bible_data)
bible_obj = bible_service.generate_bible(user_id, "temp_enhance") except Exception as exc:
bible_context = bible_service.serialize_bible(bible_obj) logger.debug(f"[Podcast Enhance] Bible parsing skipped in podcast mode: {exc}")
except Exception as exc:
logger.warning(f"[Podcast Enhance] Failed to parse or generate bible context: {exc}")
prompt = f""" prompt = f"""
You are a creative podcast producer. Generate 3 distinct, compelling podcast episode concepts from the raw idea. You are a creative podcast producer. Generate 3 distinct, compelling podcast episode concepts from the raw idea.
@@ -72,8 +90,22 @@ Generate 3 different enhanced versions, each with a unique angle:
Each version should be 2-3 sentences, audience-focused, and align with host persona if provided. Each version should be 2-3 sentences, audience-focused, and align with host persona if provided.
Return JSON with: Return JSON with:
- enhanced_ideas: array of 3 enhanced episode pitches (in order: Professional, Storytelling, Trendy) - enhanced_ideas: array of 3 strings, each string being a complete episode pitch (NOT objects, just plain strings)
- rationales: array of 3 rationales explaining the approach for each version - rationales: array of 3 strings explaining the approach for each version
IMPORTANT: enhanced_ideas must be an array of plain strings, NOT objects. Example:
{{
"enhanced_ideas": [
"Your expert guide to AI advancement: A practical look at how AI is transforming industries...",
"The human stories behind AI innovation: From Silicon Valley to your daily life...",
"AI in 2026: What's trending and what's next in artificial intelligence..."
],
"rationales": [
"Professional approach focusing on expertise and authority",
"Storytelling approach emphasizing human connection",
"Contemporary approach highlighting current relevance"
]
}}
""" """
try: try:
@@ -95,6 +127,19 @@ Return JSON with:
enhanced_ideas = data.get("enhanced_ideas", []) enhanced_ideas = data.get("enhanced_ideas", [])
rationales = data.get("rationales", []) rationales = data.get("rationales", [])
# Handle case where LLM returns objects instead of strings
normalized_ideas = []
for idea in enhanced_ideas:
if isinstance(idea, dict):
# Extract title and description from object
title = idea.get("title", "")
description = idea.get("description", "") or idea.get("content", "")
normalized_ideas.append(f"{title}: {description}" if description else title)
elif isinstance(idea, str):
normalized_ideas.append(idea)
enhanced_ideas = normalized_ideas
# Ensure we have exactly 3 ideas, fallback to original if needed # Ensure we have exactly 3 ideas, fallback to original if needed
if not isinstance(enhanced_ideas, list) or len(enhanced_ideas) != 3: if not isinstance(enhanced_ideas, list) or len(enhanced_ideas) != 3:
# Fallback: create 3 variations of the original idea # Fallback: create 3 variations of the original idea

View File

@@ -41,8 +41,9 @@ exa-py==1.9.1
markdown>=3.5.0 markdown>=3.5.0
beautifulsoup4>=4.12.0 beautifulsoup4>=4.12.0
# Data processing (numpy needed for moviepy) # Data processing (numpy needed for moviepy, pandas for usage tracking)
numpy>=1.24.0 numpy>=1.24.0
pandas>=2.0.0
# Image/media for podcast # Image/media for podcast
Pillow>=10.0.0 Pillow>=10.0.0

View File

@@ -222,6 +222,11 @@ const AlertsBadge: React.FC<AlertsBadgeProps> = ({ colorMode = 'light' }) => {
// Poll for alerts // Poll for alerts
useEffect(() => { useEffect(() => {
// Skip alerts polling entirely in podcast-only mode
if (isPodcastOnlyDemoMode()) {
return;
}
if (!userId) return; if (!userId) return;
// Delay initial fetch slightly to ensure auth token getter is installed // Delay initial fetch slightly to ensure auth token getter is installed