issues fixes related to autaitmioan and ai idea genration
This commit is contained in:
@@ -205,7 +205,10 @@ class GenerateIdeasFunction(BaseAIFunction):
|
||||
elif not isinstance(description, str):
|
||||
description = str(description)
|
||||
|
||||
# Handle target_keywords
|
||||
# Handle primary_focus_keywords (new field)
|
||||
primary_focus_keywords = idea_data.get('primary_focus_keywords', '')
|
||||
|
||||
# Handle target_keywords (covered_keywords from AI)
|
||||
target_keywords = idea_data.get('covered_keywords', '') or idea_data.get('target_keywords', '')
|
||||
|
||||
# Direct mapping - no conversion needed
|
||||
@@ -216,6 +219,7 @@ class GenerateIdeasFunction(BaseAIFunction):
|
||||
ContentIdeas.objects.create(
|
||||
idea_title=idea_data.get('title', 'Untitled Idea'),
|
||||
description=description, # Stored as JSON string
|
||||
primary_focus_keywords=primary_focus_keywords,
|
||||
content_type=content_type,
|
||||
content_structure=content_structure,
|
||||
target_keywords=target_keywords,
|
||||
|
||||
@@ -82,14 +82,41 @@ def run_automation_task(self, run_id: str):
|
||||
try:
|
||||
service = AutomationService.from_run_id(run_id)
|
||||
|
||||
# Run all stages sequentially
|
||||
# Run all stages sequentially, checking for pause/cancel between stages
|
||||
service.run_stage_1()
|
||||
if service.run.status in ['paused', 'cancelled']:
|
||||
logger.info(f"[AutomationTask] Automation {service.run.status} after stage 1")
|
||||
return
|
||||
|
||||
service.run_stage_2()
|
||||
if service.run.status in ['paused', 'cancelled']:
|
||||
logger.info(f"[AutomationTask] Automation {service.run.status} after stage 2")
|
||||
return
|
||||
|
||||
service.run_stage_3()
|
||||
if service.run.status in ['paused', 'cancelled']:
|
||||
logger.info(f"[AutomationTask] Automation {service.run.status} after stage 3")
|
||||
return
|
||||
|
||||
service.run_stage_4()
|
||||
if service.run.status in ['paused', 'cancelled']:
|
||||
logger.info(f"[AutomationTask] Automation {service.run.status} after stage 4")
|
||||
return
|
||||
|
||||
service.run_stage_5()
|
||||
if service.run.status in ['paused', 'cancelled']:
|
||||
logger.info(f"[AutomationTask] Automation {service.run.status} after stage 5")
|
||||
return
|
||||
|
||||
service.run_stage_6()
|
||||
if service.run.status in ['paused', 'cancelled']:
|
||||
logger.info(f"[AutomationTask] Automation {service.run.status} after stage 6")
|
||||
return
|
||||
|
||||
service.run_stage_7()
|
||||
if service.run.status in ['paused', 'cancelled']:
|
||||
logger.info(f"[AutomationTask] Automation {service.run.status} after stage 7")
|
||||
return
|
||||
|
||||
logger.info(f"[AutomationTask] Completed automation run: {run_id}")
|
||||
|
||||
|
||||
@@ -244,7 +244,8 @@ class ContentIdeas(SoftDeletableModel, SiteSectorBaseModel):
|
||||
|
||||
idea_title = models.CharField(max_length=255, db_index=True)
|
||||
description = models.TextField(blank=True, null=True)
|
||||
target_keywords = models.CharField(max_length=500, blank=True) # Comma-separated keywords (legacy)
|
||||
primary_focus_keywords = models.CharField(max_length=500, blank=True, help_text="1-2 main keywords this content targets")
|
||||
target_keywords = models.CharField(max_length=500, blank=True) # Comma-separated keywords (covered_keywords from AI)
|
||||
keyword_objects = models.ManyToManyField(
|
||||
'Keywords',
|
||||
blank=True,
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated migration for adding primary_focus_keywords field
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('planner', '0010_add_taxonomy_soft_delete_and_keyword_fk_cascade'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
# Add primary_focus_keywords field to ContentIdeas
|
||||
migrations.AddField(
|
||||
model_name='contentideas',
|
||||
name='primary_focus_keywords',
|
||||
field=models.CharField(blank=True, help_text='1-2 main keywords this content targets', max_length=500),
|
||||
),
|
||||
]
|
||||
@@ -245,6 +245,7 @@ class ContentIdeasSerializer(serializers.ModelSerializer):
|
||||
'id',
|
||||
'idea_title',
|
||||
'description',
|
||||
'primary_focus_keywords',
|
||||
'content_type',
|
||||
'content_structure',
|
||||
'target_keywords',
|
||||
|
||||
280
backend/scripts/update_ideas_prompt.sql
Normal file
280
backend/scripts/update_ideas_prompt.sql
Normal file
@@ -0,0 +1,280 @@
|
||||
-- Update the Ideas Generation prompt in GlobalAIPrompt
|
||||
-- Run this SQL to update the prompt
|
||||
|
||||
UPDATE igny8_global_ai_prompts
|
||||
SET prompt_value = '# SEO Content Idea Generator
|
||||
|
||||
You are a content strategist. Generate content ideas and simple outlines for keyword clusters. The actual content will be written by a separate system.
|
||||
|
||||
---
|
||||
|
||||
## INPUT FORMAT
|
||||
|
||||
**Clusters to analyze:**
|
||||
[IGNY8_CLUSTERS]
|
||||
|
||||
**Keywords in each cluster:**
|
||||
[IGNY8_CLUSTER_KEYWORDS]
|
||||
|
||||
---
|
||||
|
||||
## OUTPUT REQUIREMENTS
|
||||
|
||||
Generate **3-7 content ideas per cluster** based on the number of unique major topics within the cluster:
|
||||
- Analyze the cluster keywords to identify distinct major topics
|
||||
- Generate one idea per major topic (not for minor keyword variations)
|
||||
- Each idea must target completely different major topics/angles
|
||||
|
||||
**Important**:
|
||||
- Focus on **major topic differences**, not minor keyword variations
|
||||
- Each idea must cover **completely different keywords** from the cluster
|
||||
- Generate fewer ideas for focused clusters, more for broad clusters
|
||||
|
||||
---
|
||||
|
||||
## OUTPUT JSON OBJECT STRUCTURE
|
||||
|
||||
{
|
||||
"ideas": [
|
||||
{
|
||||
"title": "[Compelling title with primary focus keyword]",
|
||||
"description": {
|
||||
"overview": "[2-3 sentence description of what this content covers and its unique angle]",
|
||||
"outline": {
|
||||
"intro_focus": "[What the introduction should establish]",
|
||||
"main_sections": [
|
||||
{
|
||||
"h2_topic": "[Section topic/angle - must include covered keywords]",
|
||||
"coverage": "[What this section should cover - 1 sentence]"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"primary_focus_keywords": "[1-2 main keywords this content targets, comma-separated]",
|
||||
"covered_keywords": "[2-3 additional supporting keywords, comma-separated]",
|
||||
"content_type": "post|page",
|
||||
"content_structure": "guide_tutorial|how_to|comparison|review|top_listicle|question",
|
||||
"cluster_id": "[Cluster ID number]",
|
||||
"estimated_word_count": "[AI determined based on sections and keyword coverage]"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
## KEYWORD REQUIREMENTS
|
||||
|
||||
### Primary Focus Keywords (1-2 per idea)
|
||||
The main keywords this content primarily targets:
|
||||
- **MUST appear in the title**
|
||||
- **MUST appear in at least 2 different H2 section headings**
|
||||
- These drive the content''s core topic
|
||||
- These have the highest search priority
|
||||
|
||||
### Covered Keywords (2-3 per idea)
|
||||
Additional supporting keywords from the cluster:
|
||||
- Include related search terms from cluster
|
||||
- Include natural variations and long-tail keywords
|
||||
- Should also appear in H2 section headings where natural
|
||||
|
||||
**Total Keywords Per Idea**: 3-5 maximum (1-2 primary + 2-3 covered)
|
||||
|
||||
### Keyword Distribution Strategy
|
||||
- **Each of the ideas must cover completely different keywords**
|
||||
- **Focus on major topic differences, not minor variations**
|
||||
- Minimize overlap between ideas in the same cluster
|
||||
- Each idea should target a distinct subtopic within the cluster
|
||||
|
||||
**Example for "Email Marketing" cluster:**
|
||||
|
||||
**Idea 1**: "How to Build an Email List from Scratch"
|
||||
- primary_focus_keywords: "email list building"
|
||||
- covered_keywords: "subscriber acquisition, lead magnets"
|
||||
- Total: 3 keywords covering list growth subtopic
|
||||
|
||||
**Idea 2**: "Best Email Marketing Platforms Compared"
|
||||
- primary_focus_keywords: "email marketing platforms"
|
||||
- covered_keywords: "email software, automation tools"
|
||||
- Total: 3 keywords covering platform selection subtopic
|
||||
|
||||
**Idea 3**: "Email Campaign Strategy Guide"
|
||||
- primary_focus_keywords: "email campaigns"
|
||||
- covered_keywords: "campaign optimization, conversion tactics"
|
||||
- Total: 3 keywords covering campaign execution subtopic
|
||||
|
||||
---
|
||||
|
||||
## CONTENT STRUCTURE TYPES
|
||||
|
||||
### Guide/Tutorial
|
||||
- **Purpose**: Step-by-step educational content
|
||||
- **Coverage**: Process-oriented, actionable steps
|
||||
- **Sections**: AI determines based on content depth and keywords
|
||||
|
||||
### How-To
|
||||
- **Purpose**: Solve a specific problem
|
||||
- **Coverage**: Problem → solution framework
|
||||
- **Sections**: AI determines based on complexity
|
||||
|
||||
### Comparison
|
||||
- **Purpose**: Compare options/alternatives
|
||||
- **Coverage**: Feature analysis, pros/cons, recommendations
|
||||
- **Sections**: AI determines based on items compared
|
||||
|
||||
### Review
|
||||
- **Purpose**: Evaluate specific products/services
|
||||
- **Coverage**: Features, testing, verdict
|
||||
- **Sections**: AI determines based on review depth
|
||||
|
||||
### Top Listicle
|
||||
- **Purpose**: Curated ranked list
|
||||
- **Coverage**: Criteria, ranked items, selection guide
|
||||
- **Sections**: AI determines based on list size
|
||||
|
||||
### Question
|
||||
- **Purpose**: Answer specific query
|
||||
- **Coverage**: Question → context → answer → implications
|
||||
- **Sections**: AI determines based on answer complexity
|
||||
|
||||
---
|
||||
|
||||
## WORD COUNT DETERMINATION
|
||||
|
||||
**AI must determine estimated_word_count based on:**
|
||||
- Number of H2 sections outlined
|
||||
- Number of keywords to be covered (3-5 total)
|
||||
- Content structure complexity
|
||||
- Topic depth requirements
|
||||
|
||||
**Guideline**: More sections + more keywords = higher word count
|
||||
**Range**: Typically 1200-1800 words, but AI decides the optimal length
|
||||
|
||||
---
|
||||
|
||||
## OUTLINE REQUIREMENTS
|
||||
|
||||
For each idea, provide:
|
||||
|
||||
1. **Intro Focus**: What angle/hook the introduction should take (1 sentence)
|
||||
|
||||
2. **Main Sections**: Variable number of H2 topics based on content needs
|
||||
- **CRITICAL**: Primary focus keywords must appear in at least 2 different H2 section headings
|
||||
- Each covered keyword should appear in H2 headings where natural
|
||||
- Integrate keywords naturally into section titles
|
||||
- 1 sentence on what each section should cover
|
||||
- AI determines optimal section count for topic coverage
|
||||
- No need for H3 breakdown (content generator will handle)
|
||||
- No formatting details (content generator will handle)
|
||||
|
||||
3. **Section approach**:
|
||||
- Foundation/basics sections (if needed)
|
||||
- Core concept sections (main body)
|
||||
- Application/implementation sections
|
||||
- Advanced/future sections (if appropriate)
|
||||
- AI determines which sections are necessary
|
||||
|
||||
---
|
||||
|
||||
## SECTION COUNT DETERMINATION
|
||||
|
||||
**AI must determine the number of H2 sections based on:**
|
||||
- Content structure type requirements
|
||||
- Number of keywords to cover (3-5 total)
|
||||
- Topic complexity and depth
|
||||
- Natural content flow
|
||||
|
||||
**Do not use hardcoded section counts** - evaluate each idea independently.
|
||||
|
||||
---
|
||||
|
||||
## TITLE GUIDELINES
|
||||
|
||||
- **MUST include primary focus keywords (1-2 keywords)**
|
||||
- 50-65 characters ideal
|
||||
- Compelling and specific
|
||||
- Match content structure type:
|
||||
- How-to: "How to [Action] [Object/Goal]"
|
||||
- Comparison: "[X] vs [Y]: Which Is Better?"
|
||||
- Review: "[Product/Service] Review: [Key Benefit]"
|
||||
- Listicle: "[Number] Best [Items] for [Purpose]"
|
||||
- Question: "[Question Using Primary Keyword]?"
|
||||
- Guide: "[Complete/Ultimate] Guide to [Topic]"
|
||||
|
||||
---
|
||||
|
||||
## CONTENT ANGLE REQUIREMENTS
|
||||
|
||||
Each idea must have a **unique angle**:
|
||||
|
||||
✓ Different content structure types across ideas
|
||||
✓ Different major topics (not just minor keyword variations)
|
||||
✓ Different target intents (informational, commercial, navigational)
|
||||
✓ Different depth levels (overview vs deep-dive)
|
||||
✓ No duplicate section topics across ideas in same cluster
|
||||
✓ **Completely different keyword sets targeting distinct subtopics**
|
||||
|
||||
---
|
||||
|
||||
## GENERATING 3-7 IDEAS
|
||||
|
||||
**Decision criteria for idea count:**
|
||||
- **3 ideas**: Narrow, focused cluster with 1-3 major subtopics
|
||||
- **4-5 ideas**: Moderate cluster with 4-5 major subtopics
|
||||
- **6-7 ideas**: Broad cluster with 6+ distinct major subtopics
|
||||
|
||||
**What counts as a major topic difference:**
|
||||
✓ List building vs Platform selection vs Campaign strategy (MAJOR - generate separate ideas)
|
||||
✓ "Best tools" vs "Top platforms" (MINOR variation - combine into one idea)
|
||||
✓ Email automation vs Email design vs Email analytics (MAJOR - generate separate ideas)
|
||||
✓ "How to write emails" vs "Email writing tips" (MINOR variation - combine into one idea)
|
||||
|
||||
---
|
||||
|
||||
## QUALITY CHECKS
|
||||
|
||||
Before finalizing, verify:
|
||||
- ✓ 3-7 ideas per cluster (based on major topic count)
|
||||
- ✓ Each idea targets a distinct major topic
|
||||
- ✓ Each idea has unique content_structure type
|
||||
- ✓ Title includes 1-2 primary focus keywords
|
||||
- ✓ 1-2 primary_focus_keywords listed per idea
|
||||
- ✓ 2-3 covered_keywords listed per idea (3-5 total keywords maximum)
|
||||
- ✓ **Primary focus keywords appear in title AND at least 2 H2 headings**
|
||||
- ✓ **Each idea covers completely different keywords from cluster**
|
||||
- ✓ Content angles represent major topic differences
|
||||
- ✓ AI determined optimal section count for each idea
|
||||
- ✓ AI determined word count based on sections and keywords
|
||||
- ✓ Valid JSON format
|
||||
|
||||
---
|
||||
|
||||
## OUTPUT FORMAT
|
||||
|
||||
Return ONLY valid JSON with no comments or explanations.
|
||||
|
||||
The "outline" object should be simple and high-level - just enough to guide the content generator. The actual detailed structure, formatting, H3 subsections, lists, tables, etc. will be handled by the content generation system.
|
||||
|
||||
---
|
||||
|
||||
## WHAT NOT TO INCLUDE
|
||||
|
||||
❌ Detailed H3 subsections (content generator handles this)
|
||||
❌ Specific formatting instructions (paragraph/list/table details)
|
||||
❌ Word count per section (content generator calculates)
|
||||
❌ Detailed content descriptions (keep coverage notes brief)
|
||||
❌ HTML structure (content generator outputs HTML)
|
||||
❌ Introduction hook text (content generator writes this)
|
||||
❌ Hardcoded section counts (AI determines optimal count)
|
||||
❌ Hardcoded word count ranges (AI determines based on content needs)
|
||||
|
||||
Keep outlines strategic and high-level. Let the content generation system handle tactical execution.',
|
||||
description = 'Generates 3-7 content ideas per cluster with titles, outlines, primary_focus_keywords, and covered_keywords. Outputs JSON with cluster IDs for proper linking.',
|
||||
variables = '["[IGNY8_CLUSTERS]", "[IGNY8_CLUSTER_KEYWORDS]"]',
|
||||
version = version + 1,
|
||||
last_updated = NOW()
|
||||
WHERE prompt_type = 'ideas';
|
||||
|
||||
-- Verify the update
|
||||
SELECT prompt_type, version, description, variables, LEFT(prompt_value, 100) as prompt_preview, last_updated
|
||||
FROM igny8_global_ai_prompts
|
||||
WHERE prompt_type = 'ideas';
|
||||
@@ -200,6 +200,21 @@ export default function ClusterDetail() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Keywords Section */}
|
||||
{cluster.keywords_count > 0 && (
|
||||
<div className="mt-4 pt-4 border-t border-gray-200 dark:border-gray-700">
|
||||
<div className="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Keywords in this Cluster</div>
|
||||
<div className="text-sm text-gray-500 dark:text-gray-400">
|
||||
<Link
|
||||
to={`/planner/keywords?cluster=${cluster.id}`}
|
||||
className="text-brand-600 hover:text-brand-700 dark:text-brand-400 dark:hover:text-brand-300 underline"
|
||||
>
|
||||
View {cluster.keywords_count} keyword{cluster.keywords_count !== 1 ? 's' : ''} →
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="mt-4 pt-4 border-t border-gray-200 dark:border-gray-700 flex items-center gap-4">
|
||||
{cluster.sector_name && (
|
||||
<Badge variant="light" color="info">
|
||||
|
||||
Reference in New Issue
Block a user