fine tuning
This commit is contained in:
@@ -161,6 +161,7 @@ class GenerateContentFunction(BaseAIFunction):
|
||||
"""
|
||||
STAGE 3: Save content using final Stage 1 Content model schema.
|
||||
Creates independent Content record (no OneToOne to Task).
|
||||
Handles tags and categories from AI response.
|
||||
"""
|
||||
if isinstance(original_data, list):
|
||||
task = original_data[0] if original_data else None
|
||||
@@ -179,6 +180,9 @@ class GenerateContentFunction(BaseAIFunction):
|
||||
meta_description = parsed.get('meta_description') or parsed.get('seo_description')
|
||||
primary_keyword = parsed.get('primary_keyword') or parsed.get('focus_keyword')
|
||||
secondary_keywords = parsed.get('secondary_keywords') or parsed.get('keywords', [])
|
||||
# Extract tags and categories from AI response
|
||||
tags_from_response = parsed.get('tags', [])
|
||||
categories_from_response = parsed.get('categories', [])
|
||||
else:
|
||||
# Plain text response
|
||||
content_html = str(parsed)
|
||||
@@ -187,6 +191,8 @@ class GenerateContentFunction(BaseAIFunction):
|
||||
meta_description = None
|
||||
primary_keyword = None
|
||||
secondary_keywords = []
|
||||
tags_from_response = []
|
||||
categories_from_response = []
|
||||
|
||||
# Calculate word count
|
||||
word_count = 0
|
||||
@@ -222,8 +228,51 @@ class GenerateContentFunction(BaseAIFunction):
|
||||
if task.taxonomy_term:
|
||||
content_record.taxonomy_terms.add(task.taxonomy_term)
|
||||
|
||||
# Link all keywords from task as taxonomy terms (if they have taxonomy mappings)
|
||||
# This is optional - keywords are M2M on Task, not directly on Content
|
||||
# Process tags from AI response
|
||||
if tags_from_response and isinstance(tags_from_response, list):
|
||||
from django.utils.text import slugify
|
||||
for tag_name in tags_from_response:
|
||||
if tag_name and isinstance(tag_name, str):
|
||||
tag_name = tag_name.strip()
|
||||
if tag_name:
|
||||
try:
|
||||
# Get or create tag taxonomy term
|
||||
tag_obj, _ = ContentTaxonomy.objects.get_or_create(
|
||||
site=task.site,
|
||||
name=tag_name,
|
||||
taxonomy_type='tag',
|
||||
defaults={
|
||||
'slug': slugify(tag_name),
|
||||
'sector': task.sector,
|
||||
'account': task.account,
|
||||
}
|
||||
)
|
||||
content_record.taxonomy_terms.add(tag_obj)
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to add tag '{tag_name}': {e}")
|
||||
|
||||
# Process categories from AI response
|
||||
if categories_from_response and isinstance(categories_from_response, list):
|
||||
from django.utils.text import slugify
|
||||
for category_name in categories_from_response:
|
||||
if category_name and isinstance(category_name, str):
|
||||
category_name = category_name.strip()
|
||||
if category_name:
|
||||
try:
|
||||
# Get or create category taxonomy term
|
||||
category_obj, _ = ContentTaxonomy.objects.get_or_create(
|
||||
site=task.site,
|
||||
name=category_name,
|
||||
taxonomy_type='category',
|
||||
defaults={
|
||||
'slug': slugify(category_name),
|
||||
'sector': task.sector,
|
||||
'account': task.account,
|
||||
}
|
||||
)
|
||||
content_record.taxonomy_terms.add(category_obj)
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to add category '{category_name}': {e}")
|
||||
|
||||
# STAGE 3: Update task status to completed
|
||||
task.status = 'completed'
|
||||
|
||||
@@ -707,6 +707,25 @@ def process_image_generation_queue(self, image_ids: list, account_id: int = None
|
||||
})
|
||||
failed += 1
|
||||
|
||||
# Check if all images for the content are generated and update status to 'review'
|
||||
if content_id and completed > 0:
|
||||
try:
|
||||
from igny8_core.business.content.models import Content, Images
|
||||
|
||||
content = Content.objects.get(id=content_id)
|
||||
|
||||
# Check if all images for this content are now generated
|
||||
all_images = Images.objects.filter(content=content)
|
||||
pending_images = all_images.filter(status='pending').count()
|
||||
|
||||
# If no pending images and content is still in draft, move to review
|
||||
if pending_images == 0 and content.status == 'draft':
|
||||
content.status = 'review'
|
||||
content.save(update_fields=['status'])
|
||||
logger.info(f"[process_image_generation_queue] Content #{content_id} status updated to 'review' (all images generated)")
|
||||
except Exception as e:
|
||||
logger.error(f"[process_image_generation_queue] Error updating content status: {str(e)}", exc_info=True)
|
||||
|
||||
# Final state
|
||||
logger.info("=" * 80)
|
||||
logger.info(f"process_image_generation_queue COMPLETED")
|
||||
|
||||
@@ -235,6 +235,7 @@ class Content(SiteSectorBaseModel):
|
||||
# Status tracking
|
||||
STATUS_CHOICES = [
|
||||
('draft', 'Draft'),
|
||||
('review', 'Review'),
|
||||
('published', 'Published'),
|
||||
]
|
||||
status = models.CharField(
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# Generated manually on 2025-11-28
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('writer', '0009_add_word_count_to_tasks'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='content',
|
||||
name='status',
|
||||
field=models.CharField(
|
||||
choices=[
|
||||
('draft', 'Draft'),
|
||||
('review', 'Review'),
|
||||
('published', 'Published')
|
||||
],
|
||||
db_index=True,
|
||||
default='draft',
|
||||
help_text='Content status',
|
||||
max_length=50
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -154,6 +154,9 @@ class ContentSerializer(serializers.ModelSerializer):
|
||||
cluster_name = serializers.SerializerMethodField()
|
||||
sector_name = serializers.SerializerMethodField()
|
||||
taxonomy_terms_data = serializers.SerializerMethodField()
|
||||
has_image_prompts = serializers.SerializerMethodField()
|
||||
image_status = serializers.SerializerMethodField()
|
||||
has_generated_images = serializers.SerializerMethodField()
|
||||
site_id = serializers.IntegerField(write_only=True, required=False)
|
||||
sector_id = serializers.IntegerField(write_only=True, required=False)
|
||||
|
||||
@@ -181,6 +184,9 @@ class ContentSerializer(serializers.ModelSerializer):
|
||||
'site_id',
|
||||
'sector_id',
|
||||
'account_id',
|
||||
'has_image_prompts',
|
||||
'image_status',
|
||||
'has_generated_images',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
]
|
||||
@@ -239,6 +245,35 @@ class ContentSerializer(serializers.ModelSerializer):
|
||||
}
|
||||
for term in obj.taxonomy_terms.all()
|
||||
]
|
||||
|
||||
def get_has_image_prompts(self, obj):
|
||||
"""Check if content has any image prompts (images with prompts)"""
|
||||
return obj.images.filter(prompt__isnull=False).exclude(prompt='').exists()
|
||||
|
||||
def get_image_status(self, obj):
|
||||
"""Get image generation status: 'generated', 'pending', 'failed', or None"""
|
||||
images = obj.images.all()
|
||||
if not images.exists():
|
||||
return None
|
||||
|
||||
# Check statuses
|
||||
has_failed = images.filter(status='failed').exists()
|
||||
has_generated = images.filter(status='generated').exists()
|
||||
has_pending = images.filter(status='pending').exists()
|
||||
|
||||
# Priority: failed > pending > generated
|
||||
if has_failed:
|
||||
return 'failed'
|
||||
elif has_pending:
|
||||
return 'pending'
|
||||
elif has_generated:
|
||||
return 'generated'
|
||||
|
||||
return None
|
||||
|
||||
def get_has_generated_images(self, obj):
|
||||
"""Check if content has any successfully generated images"""
|
||||
return obj.images.filter(status='generated', image_url__isnull=False).exclude(image_url='').exists()
|
||||
|
||||
|
||||
class ContentTaxonomySerializer(serializers.ModelSerializer):
|
||||
|
||||
Reference in New Issue
Block a user