From b1d86cd4b8bfd6a0012461e862e8742c861dd684 Mon Sep 17 00:00:00 2001 From: "IGNY8 VPS (Salman)" Date: Mon, 10 Nov 2025 12:29:15 +0000 Subject: [PATCH] Refactor generate_ideas function integration and add auto_generate_ideas action for cluster idea generation --- backend/igny8_core/ai/functions/__init__.py | 8 +- backend/igny8_core/ai/prompts.py | 3 +- backend/igny8_core/ai/registry.py | 12 ++- backend/igny8_core/modules/planner/views.py | 97 ++++++++++++++++++++- 4 files changed, 105 insertions(+), 15 deletions(-) diff --git a/backend/igny8_core/ai/functions/__init__.py b/backend/igny8_core/ai/functions/__init__.py index d1aa5060..bad2ef31 100644 --- a/backend/igny8_core/ai/functions/__init__.py +++ b/backend/igny8_core/ai/functions/__init__.py @@ -2,16 +2,14 @@ AI Function implementations """ from igny8_core.ai.functions.auto_cluster import AutoClusterFunction -# REMOVED: generate_ideas function removed -# from igny8_core.ai.functions.generate_ideas import GenerateIdeasFunction, generate_ideas_core +from igny8_core.ai.functions.generate_ideas import GenerateIdeasFunction, generate_ideas_core from igny8_core.ai.functions.generate_content import GenerateContentFunction, generate_content_core from igny8_core.ai.functions.generate_images import GenerateImagesFunction, generate_images_core __all__ = [ 'AutoClusterFunction', - # REMOVED: generate_ideas function removed - # 'GenerateIdeasFunction', - # 'generate_ideas_core', + 'GenerateIdeasFunction', + 'generate_ideas_core', 'GenerateContentFunction', 'generate_content_core', 'GenerateImagesFunction', diff --git a/backend/igny8_core/ai/prompts.py b/backend/igny8_core/ai/prompts.py index 2df411eb..00c38172 100644 --- a/backend/igny8_core/ai/prompts.py +++ b/backend/igny8_core/ai/prompts.py @@ -270,8 +270,7 @@ Make sure each prompt is detailed enough for image generation, describing the vi # Mapping from function names to prompt types FUNCTION_TO_PROMPT_TYPE = { 'auto_cluster': 'clustering', - # REMOVED: generate_ideas function removed - # 'generate_ideas': 'ideas', + 'generate_ideas': 'ideas', 'generate_content': 'content_generation', 'generate_images': 'image_prompt_extraction', 'extract_image_prompts': 'image_prompt_extraction', diff --git a/backend/igny8_core/ai/registry.py b/backend/igny8_core/ai/registry.py index fdedd7ab..ae784d37 100644 --- a/backend/igny8_core/ai/registry.py +++ b/backend/igny8_core/ai/registry.py @@ -66,11 +66,10 @@ def _load_auto_cluster(): from igny8_core.ai.functions.auto_cluster import AutoClusterFunction return AutoClusterFunction -# REMOVED: generate_ideas function removed -# def _load_generate_ideas(): -# """Lazy loader for generate_ideas function""" -# from igny8_core.ai.functions.generate_ideas import GenerateIdeasFunction -# return GenerateIdeasFunction +def _load_generate_ideas(): + """Lazy loader for generate_ideas function""" + from igny8_core.ai.functions.generate_ideas import GenerateIdeasFunction + return GenerateIdeasFunction def _load_generate_content(): """Lazy loader for generate_content function""" @@ -83,8 +82,7 @@ def _load_generate_images(): return GenerateImagesFunction register_lazy_function('auto_cluster', _load_auto_cluster) -# REMOVED: generate_ideas function removed -# register_lazy_function('generate_ideas', _load_generate_ideas) +register_lazy_function('generate_ideas', _load_generate_ideas) register_lazy_function('generate_content', _load_generate_content) register_lazy_function('generate_images', _load_generate_images) diff --git a/backend/igny8_core/modules/planner/views.py b/backend/igny8_core/modules/planner/views.py index 1f37ca71..5fb39c94 100644 --- a/backend/igny8_core/modules/planner/views.py +++ b/backend/igny8_core/modules/planner/views.py @@ -714,7 +714,102 @@ class ClusterViewSet(SiteSectorModelViewSet): # Save with all required fields explicitly serializer.save(account=account, site=site, sector=sector) - # REMOVED: auto_generate_ideas action - idea generation function removed + @action(detail=False, methods=['post'], url_path='auto_generate_ideas', url_name='auto_generate_ideas') + def auto_generate_ideas(self, request): + """Auto-generate ideas for clusters using AI - New unified framework""" + import logging + from igny8_core.ai.tasks import run_ai_task + from kombu.exceptions import OperationalError as KombuOperationalError + + logger = logging.getLogger(__name__) + + try: + # Get account + account = getattr(request, 'account', None) + account_id = account.id if account else None + + # Prepare payload + payload = { + 'ids': request.data.get('ids', []) + } + + logger.info(f"auto_generate_ideas called with ids={payload['ids']}") + + # Validate basic input + if not payload['ids']: + return Response({ + 'success': False, + 'error': 'No IDs provided' + }, status=status.HTTP_400_BAD_REQUEST) + + if len(payload['ids']) > 10: + return Response({ + 'success': False, + 'error': 'Maximum 10 clusters allowed for idea generation' + }, status=status.HTTP_400_BAD_REQUEST) + + # Try to queue Celery task + try: + if hasattr(run_ai_task, 'delay'): + task = run_ai_task.delay( + function_name='auto_generate_ideas', + payload=payload, + account_id=account_id + ) + logger.info(f"Task queued: {task.id}") + return Response({ + 'success': True, + 'task_id': str(task.id), + 'message': 'Idea generation started' + }, status=status.HTTP_200_OK) + else: + # Celery not available - execute synchronously + logger.warning("Celery not available, executing synchronously") + result = run_ai_task( + function_name='auto_generate_ideas', + payload=payload, + account_id=account_id + ) + if result.get('success'): + return Response({ + 'success': True, + **result + }, status=status.HTTP_200_OK) + else: + return Response({ + 'success': False, + 'error': result.get('error', 'Idea generation failed') + }, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + except (KombuOperationalError, ConnectionError) as e: + # Broker connection failed - fall back to synchronous execution + logger.warning(f"Celery broker unavailable, falling back to synchronous execution: {str(e)}") + result = run_ai_task( + function_name='auto_generate_ideas', + payload=payload, + account_id=account_id + ) + if result.get('success'): + return Response({ + 'success': True, + **result + }, status=status.HTTP_200_OK) + else: + return Response({ + 'success': False, + 'error': result.get('error', 'Idea generation failed') + }, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + except Exception as e: + logger.error(f"Error in auto_generate_ideas: {str(e)}", exc_info=True) + return Response({ + 'success': False, + 'error': str(e) + }, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + except Exception as e: + logger.error(f"Unexpected error in auto_generate_ideas: {str(e)}", exc_info=True) + return Response({ + 'success': False, + 'error': f'Unexpected error: {str(e)}' + }, status=status.HTTP_500_INTERNAL_SERVER_ERROR) def list(self, request, *args, **kwargs): """