feat: image generation overhaul (model-aware text, dim clamping, \.30 pricing), event-driven dashboard cache invalidation, SEO insights (AI visibility, GSC, keyword gap), YouTube OAuth/publish, blog writer & content planning improvements, scheduler monitoring updates

This commit is contained in:
ajaysi
2026-05-30 07:58:22 +05:30
parent aaf94049da
commit 64f1f88cdd
129 changed files with 8796 additions and 8755 deletions

View File

@@ -166,6 +166,8 @@ def _track_image_operation_usage(
video_limit = limits['limits'].get("video_calls", 0) if limits else 0
db_track.commit()
from services.subscription.cache import clear_dashboard_cache
clear_dashboard_cache(user_id)
logger.info(f"{log_prefix} ✅ Tracked usage: user {user_id} -> {operation_type} -> {new_calls} calls, ${cost:.4f}")
operation_name = operation_type.replace("-", " ").title()

View File

@@ -24,21 +24,21 @@ class WaveSpeedImageProvider(ImageGenerationProvider):
"ideogram-v3-turbo": {
"name": "Ideogram V3 Turbo",
"description": "Photorealistic generation with superior text rendering",
"cost_per_image": 0.10, # Estimated, adjust based on actual pricing
"cost_per_image": 0.30,
"max_resolution": (1024, 1024),
"default_steps": 20,
},
"qwen-image": {
"name": "Qwen Image",
"description": "Fast, high-quality text-to-image generation",
"cost_per_image": 0.05, # Estimated, adjust based on actual pricing
"cost_per_image": 0.30,
"max_resolution": (1024, 1024),
"default_steps": 15,
},
"flux-kontext-pro": {
"name": "FLUX Kontext Pro",
"description": "Professional typography and text rendering with improved prompt adherence",
"cost_per_image": 0.04, # $0.04 per image
"cost_per_image": 0.30,
"max_resolution": (1024, 1024),
"default_steps": 20,
}

View File

@@ -307,6 +307,8 @@ def generate_audio(
video_limit = limits['limits'].get("video_calls", 0) if limits else 0
db_track.commit()
from services.subscription.cache import clear_dashboard_cache
clear_dashboard_cache(user_id)
logger.info(f"[audio_gen] ✅ Successfully tracked usage: user {user_id} -> audio -> {new_calls} calls, ${estimated_cost:.4f}")
# UNIFIED SUBSCRIPTION LOG - Shows before/after state in one message
@@ -519,6 +521,8 @@ def clone_voice(
)
db_track.add(usage_log)
db_track.commit()
from services.subscription.cache import clear_dashboard_cache
clear_dashboard_cache(user_id)
print(f"""
[SUBSCRIPTION] Voice Clone
@@ -708,6 +712,8 @@ def qwen3_voice_clone(
)
db_track.add(usage_log)
db_track.commit()
from services.subscription.cache import clear_dashboard_cache
clear_dashboard_cache(user_id)
print(f"""
[SUBSCRIPTION] Qwen3 Voice Clone
@@ -891,6 +897,8 @@ def qwen3_voice_design(
)
db_track.add(usage_log)
db_track.commit()
from services.subscription.cache import clear_dashboard_cache
clear_dashboard_cache(user_id)
print(f"""
[SUBSCRIPTION] Qwen3 Voice Design
@@ -1079,6 +1087,8 @@ def cosyvoice_voice_clone(
)
db_track.add(usage_log)
db_track.commit()
from services.subscription.cache import clear_dashboard_cache
clear_dashboard_cache(user_id)
print(f"""
[SUBSCRIPTION] CosyVoice Voice Clone

View File

@@ -27,6 +27,9 @@ from .tenant_provider_config import tenant_provider_config_resolver
logger = get_service_logger("image_generation.facade")
# Models that can render readable text directly in generated images
_TEXT_CAPABLE = {"flux-kontext-pro", "flux-2-flex", "glm-image"}
def _select_provider(explicit: Optional[str], user_id: Optional[str] = None) -> str:
cfg = tenant_provider_config_resolver.resolve(
@@ -109,8 +112,13 @@ def generate_image(prompt: str, options: Optional[Dict[str, Any]] = None, user_i
image_options.model = "black-forest-labs/FLUX.1-Krea-dev"
if provider_name == "wavespeed" and not image_options.model:
# Default to cost-effective model: Qwen Image ($0.05/image, optimized for blog images)
image_options.model = "qwen-image"
# Default to FLUX Kontext Pro (professional typography, lower cost)
image_options.model = "flux-kontext-pro"
# Append overlay text for text-capable models
overlay_text = opts.get("overlay_text")
if overlay_text and image_options.model and image_options.model.lower() in _TEXT_CAPABLE:
image_options.prompt += f" Include the text '{overlay_text}' as a typographic element in the image."
logger.info("Generating image via provider=%s model=%s", provider_name, image_options.model)
provider = _get_provider(provider_name, user_id=user_id)
@@ -130,18 +138,13 @@ def generate_image(prompt: str, options: Optional[Dict[str, Any]] = None, user_i
if result.metadata and "estimated_cost" in result.metadata:
estimated_cost = float(result.metadata["estimated_cost"])
else:
# Fallback: estimate based on provider/model (OSS-focused pricing)
# Fallback: estimate based on provider/model
if provider_name == "wavespeed":
if result.model and "qwen" in result.model.lower():
estimated_cost = 0.05 # Qwen Image: $0.05/image
elif result.model and "ideogram" in result.model.lower():
estimated_cost = 0.10 # Ideogram V3 Turbo: $0.10/image
else:
estimated_cost = 0.05 # Default to Qwen Image pricing
estimated_cost = 0.30
elif provider_name == "stability":
estimated_cost = 0.04
estimated_cost = 0.30
else:
estimated_cost = 0.05 # Default estimate
estimated_cost = 0.30
# Reuse tracking helper
_track_image_operation_usage(
@@ -215,8 +218,8 @@ def generate_character_image(
if user_id and image_bytes:
logger.info(f"[Character Image Generation] ✅ API call successful, tracking usage for user {user_id}")
# Character image cost (same as ideogram-v3-turbo)
estimated_cost = 0.10
# Character image cost
estimated_cost = 0.30
# Reuse tracking helper
_track_image_operation_usage(
@@ -272,12 +275,7 @@ def generate_character_image(
if result.metadata and "estimated_cost" in result.metadata:
estimated_cost = float(result.metadata["estimated_cost"])
else:
# Fallback: estimate based on provider/model
if provider_name == "wavespeed":
# Default WaveSpeed edit cost
estimated_cost = 0.02 # Default for most editing models
else:
estimated_cost = 0.05 # Default estimate
estimated_cost = 0.30
# Reuse tracking helper
_track_image_operation_usage(

View File

@@ -162,6 +162,8 @@ def _track_video_operation_usage(
image_edit_limit_display = image_edit_limit if (image_edit_limit > 0 or tier != 'enterprise') else ''
db_track.commit()
from services.subscription.cache import clear_dashboard_cache
clear_dashboard_cache(user_id)
logger.info(f"{log_prefix} ✅ Successfully tracked usage: user {user_id} -> {operation_type} -> {new_calls} calls, ${cost:.4f}")
# UNIFIED SUBSCRIPTION LOG
@@ -861,6 +863,8 @@ def track_video_usage(
db_track.flush()
logger.debug(f"[video_gen] Committing usage tracking changes...")
db_track.commit()
from services.subscription.cache import clear_dashboard_cache
clear_dashboard_cache(user_id)
db_track.refresh(usage_summary)
logger.debug(f"[video_gen] Commit successful. Final video_calls: {usage_summary.video_calls}, video_cost: {usage_summary.video_cost}")

View File

@@ -51,7 +51,7 @@ class TenantProviderConfigResolver:
_DEFAULT_MODELS: Dict[Tuple[str, str], str] = {
("text", "google"): "gemini-2.0-flash-001",
("text", "huggingface"): "mistralai/Mistral-7B-Instruct-v0.3:groq",
("image", "wavespeed"): "qwen-image",
("image", "wavespeed"): "flux-kontext-pro",
("image", "huggingface"): "black-forest-labs/FLUX.1-Krea-dev",
("video", "huggingface"): "tencent/HunyuanVideo",
("video", "wavespeed"): "hunyuan-video-1.5",