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:
@@ -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()
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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}")
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user