some changes
This commit is contained in:
107
EXPECTED_RESPONSE_STRUCTURE.md
Normal file
107
EXPECTED_RESPONSE_STRUCTURE.md
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
# Expected Response Structure for generate_images_from_prompts
|
||||||
|
|
||||||
|
## Function Flow
|
||||||
|
|
||||||
|
1. **Frontend calls**: `POST /v1/writer/images/generate_images/` with `{ ids: [1, 2, 3] }`
|
||||||
|
2. **Backend ViewSet** (`ImagesViewSet.generate_images`):
|
||||||
|
- Calls `run_ai_task` with `function_name='generate_images_from_prompts'`
|
||||||
|
- Returns response with `queued_prompts` if in TEST MODE
|
||||||
|
|
||||||
|
3. **AIEngine.execute**:
|
||||||
|
- Validates, prepares, builds prompt (placeholder), parses (placeholder)
|
||||||
|
- Calls `save_output` which queues prompts (TEST MODE)
|
||||||
|
|
||||||
|
4. **GenerateImagesFromPromptsFunction.save_output**:
|
||||||
|
- Returns dict with queued prompts
|
||||||
|
|
||||||
|
## Response Structure (TEST MODE)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"count": 3,
|
||||||
|
"images_generated": 0,
|
||||||
|
"images_failed": 0,
|
||||||
|
"total_images": 3,
|
||||||
|
"queued_prompts": [
|
||||||
|
{
|
||||||
|
"image_id": 1,
|
||||||
|
"index": 1,
|
||||||
|
"image_type": "featured_image",
|
||||||
|
"content_title": "Your Content Title",
|
||||||
|
"provider": "openai",
|
||||||
|
"model": "dall-e-2",
|
||||||
|
"formatted_prompt": "Create a high-quality realistic image to use as a featured photo for a blog post titled \"Your Content Title\". The image should visually represent the theme, mood, and subject implied by the image prompt: [original prompt]. Focus on a realistic, well-composed scene that naturally communicates the topic without text or logos...",
|
||||||
|
"negative_prompt": null,
|
||||||
|
"prompt_length": 250
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"image_id": 2,
|
||||||
|
"index": 2,
|
||||||
|
"image_type": "in_article_1",
|
||||||
|
"content_title": "Your Content Title",
|
||||||
|
"provider": "openai",
|
||||||
|
"model": "dall-e-2",
|
||||||
|
"formatted_prompt": "...",
|
||||||
|
"negative_prompt": null,
|
||||||
|
"prompt_length": 245
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"test_mode": true,
|
||||||
|
"provider": "openai",
|
||||||
|
"model": "dall-e-2",
|
||||||
|
"errors": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Response Structure (Production Mode - when AI calls are enabled)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"count": 3,
|
||||||
|
"images_generated": 3,
|
||||||
|
"images_failed": 0,
|
||||||
|
"total_images": 3,
|
||||||
|
"errors": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key Points
|
||||||
|
|
||||||
|
1. **TEST MODE** (current):
|
||||||
|
- `images_generated: 0` (no actual images generated)
|
||||||
|
- `queued_prompts` array contains all formatted prompts
|
||||||
|
- `test_mode: true`
|
||||||
|
- Each prompt includes the complete formatted prompt that would be sent to AI
|
||||||
|
|
||||||
|
2. **Production MODE** (when AI calls are uncommented):
|
||||||
|
- `images_generated` will be > 0
|
||||||
|
- `queued_prompts` will not be in response
|
||||||
|
- `test_mode: false` or not present
|
||||||
|
- Images will have `image_url` and `status='generated'`
|
||||||
|
|
||||||
|
## Console Logging
|
||||||
|
|
||||||
|
The function logs to console (if DEBUG_MODE=True):
|
||||||
|
- `[generate_images_from_prompts] [TEST MODE] Queued prompt X/Y`
|
||||||
|
- `[generate_images_from_prompts] [TEST MODE] Provider: openai, Model: dall-e-2`
|
||||||
|
- `[generate_images_from_prompts] [TEST MODE] Prompt length: 250 chars`
|
||||||
|
- `[generate_images_from_prompts] [TEST MODE] Prompt preview: ...`
|
||||||
|
|
||||||
|
## Frontend Console Output
|
||||||
|
|
||||||
|
When clicking "Generate Images", browser console will show:
|
||||||
|
```
|
||||||
|
[Generate Images] Request: { imageIds: [1, 2, 3], count: 3 }
|
||||||
|
[Generate Images] Endpoint: /v1/writer/images/generate_images/
|
||||||
|
[Generate Images] Full Response: { success: true, queued_prompts: [...], ... }
|
||||||
|
[Generate Images] Queued Prompts (TEST MODE - NOT sent to AI): [...]
|
||||||
|
[Generate Images] Provider: openai, Model: dall-e-2
|
||||||
|
[Generate Images] Prompt 1/3:
|
||||||
|
- Image Type: featured_image
|
||||||
|
- Content: "Your Content Title"
|
||||||
|
- Prompt Length: 250 chars
|
||||||
|
- Full Prompt: "Create a high-quality realistic image..."
|
||||||
|
```
|
||||||
|
|
||||||
@@ -551,12 +551,24 @@ class ImagesViewSet(SiteSectorModelViewSet):
|
|||||||
account_id=account_id
|
account_id=account_id
|
||||||
)
|
)
|
||||||
if result.get('success'):
|
if result.get('success'):
|
||||||
return Response({
|
# Include queued prompts in response for TEST MODE
|
||||||
|
response_data = {
|
||||||
'success': True,
|
'success': True,
|
||||||
'images_generated': result.get('count', 0),
|
'images_generated': result.get('images_generated', 0),
|
||||||
'images_failed': result.get('images_failed', 0),
|
'images_failed': result.get('images_failed', 0),
|
||||||
|
'count': result.get('count', 0),
|
||||||
|
'total_images': result.get('total_images', 0),
|
||||||
'message': 'Images generated successfully'
|
'message': 'Images generated successfully'
|
||||||
}, status=status.HTTP_200_OK)
|
}
|
||||||
|
# Add test mode data if available
|
||||||
|
if result.get('queued_prompts'):
|
||||||
|
response_data['queued_prompts'] = result.get('queued_prompts')
|
||||||
|
response_data['test_mode'] = result.get('test_mode', False)
|
||||||
|
response_data['provider'] = result.get('provider')
|
||||||
|
response_data['model'] = result.get('model')
|
||||||
|
|
||||||
|
logger.info(f"[generate_images] Response: {response_data}")
|
||||||
|
return Response(response_data, status=status.HTTP_200_OK)
|
||||||
else:
|
else:
|
||||||
return Response({
|
return Response({
|
||||||
'error': result.get('error', 'Image generation failed'),
|
'error': result.get('error', 'Image generation failed'),
|
||||||
|
|||||||
@@ -165,8 +165,31 @@ export default function Images() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('[Generate Images] Request:', { imageIds, count: imageIds.length });
|
||||||
|
console.log('[Generate Images] Endpoint: /v1/writer/images/generate_images/');
|
||||||
|
|
||||||
const result = await generateImages(imageIds);
|
const result = await generateImages(imageIds);
|
||||||
|
|
||||||
|
console.log('[Generate Images] Full Response:', result);
|
||||||
|
console.log('[Generate Images] Response Keys:', Object.keys(result));
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
|
// Log queued prompts if available (TEST MODE)
|
||||||
|
if (result.queued_prompts && result.queued_prompts.length > 0) {
|
||||||
|
console.log('[Generate Images] Queued Prompts (TEST MODE - NOT sent to AI):', result.queued_prompts);
|
||||||
|
console.log(`[Generate Images] Provider: ${result.provider}, Model: ${result.model}`);
|
||||||
|
result.queued_prompts.forEach((qp: any, idx: number) => {
|
||||||
|
console.log(`[Generate Images] Prompt ${idx + 1}/${result.queued_prompts.length}:`);
|
||||||
|
console.log(` - Image Type: ${qp.image_type}`);
|
||||||
|
console.log(` - Content: ${qp.content_title}`);
|
||||||
|
console.log(` - Prompt Length: ${qp.prompt_length} chars`);
|
||||||
|
console.log(` - Full Prompt:`, qp.formatted_prompt);
|
||||||
|
if (qp.negative_prompt) {
|
||||||
|
console.log(` - Negative Prompt:`, qp.negative_prompt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Show toast message (no progress modal)
|
// Show toast message (no progress modal)
|
||||||
const generated = result.images_generated || 0;
|
const generated = result.images_generated || 0;
|
||||||
const failed = result.images_failed || 0;
|
const failed = result.images_failed || 0;
|
||||||
@@ -179,9 +202,19 @@ export default function Images() {
|
|||||||
}
|
}
|
||||||
loadImages(); // Reload to show new images
|
loadImages(); // Reload to show new images
|
||||||
} else {
|
} else {
|
||||||
|
console.error('[Generate Images] Error:', result.error);
|
||||||
|
console.error('[Generate Images] Full Error Response:', result);
|
||||||
toast.error(result.error || 'Failed to generate images');
|
toast.error(result.error || 'Failed to generate images');
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
console.error('[Generate Images] Exception:', error);
|
||||||
|
console.error('[Generate Images] Error Details:', {
|
||||||
|
message: error.message,
|
||||||
|
stack: error.stack,
|
||||||
|
response: error.response,
|
||||||
|
status: error.status,
|
||||||
|
statusText: error.statusText
|
||||||
|
});
|
||||||
toast.error(`Failed to generate images: ${error.message}`);
|
toast.error(`Failed to generate images: ${error.message}`);
|
||||||
}
|
}
|
||||||
}, [toast, loadImages, images]);
|
}, [toast, loadImages, images]);
|
||||||
|
|||||||
184
test_image_generation.py
Normal file
184
test_image_generation.py
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Test script for generate_images_from_prompts function
|
||||||
|
Run this to test the function and see the response
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import django
|
||||||
|
|
||||||
|
# Setup Django
|
||||||
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'backend'))
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'igny8_core.settings')
|
||||||
|
django.setup()
|
||||||
|
|
||||||
|
from igny8_core.ai.functions.generate_images_from_prompts import GenerateImagesFromPromptsFunction
|
||||||
|
from igny8_core.ai.engine import AIEngine
|
||||||
|
from igny8_core.modules.writer.models import Images
|
||||||
|
from igny8_core.auth.models import Account
|
||||||
|
|
||||||
|
def test_generate_images_from_prompts():
|
||||||
|
"""Test the generate_images_from_prompts function"""
|
||||||
|
print("=" * 80)
|
||||||
|
print("Testing generate_images_from_prompts function")
|
||||||
|
print("=" * 80)
|
||||||
|
|
||||||
|
# Get first account
|
||||||
|
try:
|
||||||
|
account = Account.objects.first()
|
||||||
|
if not account:
|
||||||
|
print("ERROR: No accounts found in database")
|
||||||
|
return
|
||||||
|
print(f"Using account: {account.name} (ID: {account.id})")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"ERROR: Failed to get account: {e}")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Get pending images with prompts
|
||||||
|
try:
|
||||||
|
images = Images.objects.filter(
|
||||||
|
account=account,
|
||||||
|
status='pending'
|
||||||
|
).exclude(prompt__isnull=True).exclude(prompt='')[:3] # Get first 3
|
||||||
|
|
||||||
|
if not images.exists():
|
||||||
|
print("ERROR: No pending images with prompts found")
|
||||||
|
print("Please create some images with prompts first")
|
||||||
|
return
|
||||||
|
|
||||||
|
image_ids = list(images.values_list('id', flat=True))
|
||||||
|
print(f"\nFound {len(image_ids)} pending images: {image_ids}")
|
||||||
|
|
||||||
|
# Show image details
|
||||||
|
for img in images:
|
||||||
|
content_title = "Unknown"
|
||||||
|
if img.content:
|
||||||
|
content_title = img.content.title or img.content.meta_title or "No title"
|
||||||
|
elif img.task:
|
||||||
|
content_title = img.task.title or "No title"
|
||||||
|
print(f" - Image ID {img.id}: {img.image_type} for '{content_title}'")
|
||||||
|
print(f" Prompt: {img.prompt[:100] if img.prompt else 'None'}...")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"ERROR: Failed to get images: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
return
|
||||||
|
|
||||||
|
# Create function instance
|
||||||
|
try:
|
||||||
|
fn = GenerateImagesFromPromptsFunction()
|
||||||
|
print(f"\nFunction created: {fn.get_name()}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"ERROR: Failed to create function: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
return
|
||||||
|
|
||||||
|
# Validate
|
||||||
|
try:
|
||||||
|
print("\n" + "=" * 80)
|
||||||
|
print("Step 1: VALIDATE")
|
||||||
|
print("=" * 80)
|
||||||
|
validation = fn.validate({'ids': image_ids}, account=account)
|
||||||
|
print(f"Validation result: {validation}")
|
||||||
|
if not validation.get('valid'):
|
||||||
|
print(f"ERROR: Validation failed: {validation.get('error')}")
|
||||||
|
return
|
||||||
|
except Exception as e:
|
||||||
|
print(f"ERROR: Validation failed: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
return
|
||||||
|
|
||||||
|
# Prepare
|
||||||
|
try:
|
||||||
|
print("\n" + "=" * 80)
|
||||||
|
print("Step 2: PREPARE")
|
||||||
|
print("=" * 80)
|
||||||
|
prepared = fn.prepare({'ids': image_ids}, account=account)
|
||||||
|
print(f"Prepared data keys: {list(prepared.keys())}")
|
||||||
|
print(f"Provider: {prepared.get('provider')}")
|
||||||
|
print(f"Model: {prepared.get('model')}")
|
||||||
|
print(f"API Key: {'***' + prepared.get('api_key', '')[-4:] if prepared.get('api_key') and len(prepared.get('api_key', '')) > 4 else 'NOT SET'}")
|
||||||
|
print(f"Images count: {len(prepared.get('images', []))}")
|
||||||
|
print(f"Has prompt template: {bool(prepared.get('image_prompt_template'))}")
|
||||||
|
print(f"Has negative prompt: {bool(prepared.get('negative_prompt'))}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"ERROR: Prepare failed: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
return
|
||||||
|
|
||||||
|
# Build prompt (placeholder for this function)
|
||||||
|
try:
|
||||||
|
print("\n" + "=" * 80)
|
||||||
|
print("Step 3: BUILD PROMPT")
|
||||||
|
print("=" * 80)
|
||||||
|
prompt = fn.build_prompt(prepared, account=account)
|
||||||
|
print(f"Prompt (placeholder): {prompt}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"ERROR: Build prompt failed: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
return
|
||||||
|
|
||||||
|
# Execute via AIEngine (simulated, no actual Celery)
|
||||||
|
try:
|
||||||
|
print("\n" + "=" * 80)
|
||||||
|
print("Step 4: EXECUTE (via AIEngine - TEST MODE)")
|
||||||
|
print("=" * 80)
|
||||||
|
print("Note: This will queue prompts but NOT send to AI (TEST MODE)")
|
||||||
|
|
||||||
|
engine = AIEngine(account=account)
|
||||||
|
result = engine.execute(fn, {'ids': image_ids})
|
||||||
|
|
||||||
|
print("\n" + "=" * 80)
|
||||||
|
print("EXECUTION RESULT")
|
||||||
|
print("=" * 80)
|
||||||
|
print(f"Success: {result.get('success')}")
|
||||||
|
print(f"Keys in result: {list(result.keys())}")
|
||||||
|
|
||||||
|
if result.get('success'):
|
||||||
|
print(f"\nCount: {result.get('count', 0)}")
|
||||||
|
print(f"Images generated: {result.get('images_generated', 0)}")
|
||||||
|
print(f"Images failed: {result.get('images_failed', 0)}")
|
||||||
|
print(f"Total images: {result.get('total_images', 0)}")
|
||||||
|
print(f"Test mode: {result.get('test_mode', False)}")
|
||||||
|
print(f"Provider: {result.get('provider')}")
|
||||||
|
print(f"Model: {result.get('model')}")
|
||||||
|
|
||||||
|
queued_prompts = result.get('queued_prompts', [])
|
||||||
|
if queued_prompts:
|
||||||
|
print(f"\nQueued Prompts ({len(queued_prompts)}):")
|
||||||
|
for idx, qp in enumerate(queued_prompts, 1):
|
||||||
|
print(f"\n Prompt {idx}/{len(queued_prompts)}:")
|
||||||
|
print(f" Image ID: {qp.get('image_id')}")
|
||||||
|
print(f" Image Type: {qp.get('image_type')}")
|
||||||
|
print(f" Content Title: {qp.get('content_title')}")
|
||||||
|
print(f" Provider: {qp.get('provider')}")
|
||||||
|
print(f" Model: {qp.get('model')}")
|
||||||
|
print(f" Prompt Length: {qp.get('prompt_length')} chars")
|
||||||
|
print(f" Full Prompt:")
|
||||||
|
print(f" {qp.get('formatted_prompt', '')[:200]}...")
|
||||||
|
if qp.get('negative_prompt'):
|
||||||
|
print(f" Negative Prompt: {qp.get('negative_prompt')}")
|
||||||
|
else:
|
||||||
|
print(f"\nError: {result.get('error')}")
|
||||||
|
print(f"Error type: {result.get('error_type')}")
|
||||||
|
|
||||||
|
print("\n" + "=" * 80)
|
||||||
|
print("FULL RESULT JSON (for frontend)")
|
||||||
|
print("=" * 80)
|
||||||
|
import json
|
||||||
|
print(json.dumps(result, indent=2, default=str))
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"ERROR: Execution failed: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
return
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test_generate_images_from_prompts()
|
||||||
|
|
||||||
Reference in New Issue
Block a user