fixes
This commit is contained in:
@@ -177,7 +177,7 @@ class ContentIdeasAdmin(SiteSectorAdminMixin, Igny8ModelAdmin):
|
|||||||
'fields': ('content_type', 'content_structure', 'estimated_word_count')
|
'fields': ('content_type', 'content_structure', 'estimated_word_count')
|
||||||
}),
|
}),
|
||||||
('Keywords & Clustering', {
|
('Keywords & Clustering', {
|
||||||
'fields': ('keyword_cluster', 'target_keywords', 'taxonomy')
|
'fields': ('keyword_cluster', 'target_keywords')
|
||||||
}),
|
}),
|
||||||
('Timestamps', {
|
('Timestamps', {
|
||||||
'fields': ('created_at', 'updated_at'),
|
'fields': ('created_at', 'updated_at'),
|
||||||
|
|||||||
@@ -1,103 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
"""
|
|
||||||
Test ACTUAL content generation using existing task (same as frontend)
|
|
||||||
"""
|
|
||||||
import os, sys, django
|
|
||||||
sys.path.insert(0, '/app')
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'igny8_core.settings')
|
|
||||||
django.setup()
|
|
||||||
|
|
||||||
from igny8_core.ai.functions.generate_content import execute as generate_content
|
|
||||||
from igny8_core.auth.models import Account
|
|
||||||
from igny8_core.business.content.models import Tasks, Content
|
|
||||||
import re
|
|
||||||
from html import unescape
|
|
||||||
|
|
||||||
print("=" * 80)
|
|
||||||
print("TESTING ACTUAL CONTENT GENERATION (same function as frontend)")
|
|
||||||
print("=" * 80)
|
|
||||||
print()
|
|
||||||
|
|
||||||
# Get account and task
|
|
||||||
account = Account.objects.filter(slug='aws-admin').first()
|
|
||||||
task_id = 229 # "Essential Garden Tools for Every Gardener"
|
|
||||||
|
|
||||||
task = Tasks.objects.get(id=task_id)
|
|
||||||
print(f"✅ Using task: {task.title}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
# Delete any existing content for this task to start fresh
|
|
||||||
existing = Content.objects.filter(task=task)
|
|
||||||
if existing.exists():
|
|
||||||
count = existing.count()
|
|
||||||
existing.delete()
|
|
||||||
print(f"🗑️ Deleted {count} existing content items")
|
|
||||||
print()
|
|
||||||
|
|
||||||
print("=" * 80)
|
|
||||||
print("CALLING generate_content() - THE ACTUAL FUNCTION")
|
|
||||||
print("=" * 80)
|
|
||||||
print()
|
|
||||||
|
|
||||||
# Call the ACTUAL function
|
|
||||||
try:
|
|
||||||
result = generate_content(
|
|
||||||
payload={'ids': [task_id]},
|
|
||||||
account=account,
|
|
||||||
user=None
|
|
||||||
)
|
|
||||||
|
|
||||||
print()
|
|
||||||
print("=" * 80)
|
|
||||||
print("GENERATION RESULT")
|
|
||||||
print("=" * 80)
|
|
||||||
print()
|
|
||||||
|
|
||||||
if result.get('success'):
|
|
||||||
print(f"✅ Success: {result.get('message')}")
|
|
||||||
print(f" Items: {result.get('count', 0)}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
# Get the generated content
|
|
||||||
content = Content.objects.filter(task=task).order_by('-created_at').first()
|
|
||||||
|
|
||||||
if content:
|
|
||||||
# Count actual words
|
|
||||||
html_content = content.content_html or ''
|
|
||||||
text_only = re.sub(r'<[^>]+>', '', html_content)
|
|
||||||
text_only = unescape(text_only)
|
|
||||||
words = len(text_only.split())
|
|
||||||
|
|
||||||
print(f"📝 Content Details:")
|
|
||||||
print(f" Title: {content.title}")
|
|
||||||
print(f" Word Count (actual): {words}")
|
|
||||||
print(f" Word Count (reported): {content.word_count}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
if words < 1200:
|
|
||||||
print(f"🚨 CRITICAL ISSUE: Only {words} words!")
|
|
||||||
print(f" Target: 1200+ words")
|
|
||||||
print(f" Shortfall: {1200 - words} words")
|
|
||||||
else:
|
|
||||||
print(f"✅ EXCELLENT: {words} words (exceeds 1200)")
|
|
||||||
|
|
||||||
print()
|
|
||||||
print("=" * 80)
|
|
||||||
print("FIRST 800 CHARACTERS OF CONTENT:")
|
|
||||||
print("=" * 80)
|
|
||||||
print(text_only[:800])
|
|
||||||
print()
|
|
||||||
print(f"[...{len(text_only) - 800} more characters...]" if len(text_only) > 800 else "")
|
|
||||||
|
|
||||||
else:
|
|
||||||
print(f"❌ Failed: {result.get('error')}")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"❌ Exception: {e}")
|
|
||||||
import traceback
|
|
||||||
traceback.print_exc()
|
|
||||||
|
|
||||||
print()
|
|
||||||
print("=" * 80)
|
|
||||||
print("This is the EXACT same generate_content() function called by frontend")
|
|
||||||
print("=" * 80)
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
"""
|
|
||||||
Test idea generation with 16384 max_tokens to ensure it works correctly
|
|
||||||
"""
|
|
||||||
import os, sys, django
|
|
||||||
sys.path.insert(0, '/app')
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'igny8_core.settings')
|
|
||||||
django.setup()
|
|
||||||
|
|
||||||
import requests, json
|
|
||||||
from igny8_core.modules.system.models import IntegrationSettings
|
|
||||||
from igny8_core.auth.models import Account
|
|
||||||
|
|
||||||
account = Account.objects.filter(slug='aws-admin').first()
|
|
||||||
settings = IntegrationSettings.objects.filter(integration_type='openai', account=account, is_active=True).first()
|
|
||||||
config = settings.config or {}
|
|
||||||
api_key = config.get('apiKey')
|
|
||||||
model = config.get('model', 'gpt-4o')
|
|
||||||
max_tokens = config.get('max_tokens', 16384)
|
|
||||||
|
|
||||||
# Read the actual idea generation prompt
|
|
||||||
with open('/data/idea-generation-prompt.md', 'r') as f:
|
|
||||||
prompt_template = f.read()
|
|
||||||
|
|
||||||
# Simulate idea generation input
|
|
||||||
cluster_data = """
|
|
||||||
Cluster ID: 1 | Name: Organic Cotton Bedding | Description: Keywords related to organic and eco-friendly bedding products
|
|
||||||
"""
|
|
||||||
|
|
||||||
cluster_keywords = """
|
|
||||||
Cluster ID: 1 | Name: Organic Cotton Bedding | Keywords: organic cotton sheets, eco-friendly bedding, sustainable duvet covers, GOTS certified bedding, organic mattress protector, chemical-free bedding, organic pillowcases, hypoallergenic sheets
|
|
||||||
"""
|
|
||||||
|
|
||||||
prompt = prompt_template.replace('[IGNY8_CLUSTERS]', cluster_data)
|
|
||||||
prompt = prompt.replace('[IGNY8_CLUSTER_KEYWORDS]', cluster_keywords)
|
|
||||||
|
|
||||||
print(f"🧪 Testing Idea Generation with max_tokens={max_tokens:,}")
|
|
||||||
print("=" * 70)
|
|
||||||
print(f"Prompt length: {len(prompt):,} characters (~{len(prompt)//4:,} tokens)")
|
|
||||||
print()
|
|
||||||
|
|
||||||
try:
|
|
||||||
response = requests.post(
|
|
||||||
'https://api.openai.com/v1/chat/completions',
|
|
||||||
headers={'Authorization': f'Bearer {api_key}', 'Content-Type': 'application/json'},
|
|
||||||
json={
|
|
||||||
'model': model,
|
|
||||||
'messages': [{'role': 'user', 'content': prompt}],
|
|
||||||
'max_tokens': max_tokens,
|
|
||||||
'temperature': 0.7,
|
|
||||||
'response_format': {"type": "json_object"}
|
|
||||||
},
|
|
||||||
timeout=60
|
|
||||||
)
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
data = response.json()
|
|
||||||
usage = data.get('usage', {})
|
|
||||||
finish_reason = data['choices'][0].get('finish_reason')
|
|
||||||
|
|
||||||
prompt_tokens = usage.get('prompt_tokens', 0)
|
|
||||||
completion_tokens = usage.get('completion_tokens', 0)
|
|
||||||
total_tokens = usage.get('total_tokens', 0)
|
|
||||||
|
|
||||||
print(f"✓ Response received")
|
|
||||||
print(f" Input Tokens: {prompt_tokens:>6,}")
|
|
||||||
print(f" Output Tokens: {completion_tokens:>6,}")
|
|
||||||
print(f" Total Tokens: {total_tokens:>6,}")
|
|
||||||
print(f" Finish Reason: {finish_reason}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
# Try to parse the response
|
|
||||||
try:
|
|
||||||
response_text = data['choices'][0]['message']['content']
|
|
||||||
ideas_data = json.loads(response_text)
|
|
||||||
ideas_count = len(ideas_data.get('ideas', []))
|
|
||||||
|
|
||||||
print(f"✅ Generated {ideas_count} ideas successfully")
|
|
||||||
|
|
||||||
# Show summary of first idea
|
|
||||||
if ideas_count > 0:
|
|
||||||
first_idea = ideas_data['ideas'][0]
|
|
||||||
print()
|
|
||||||
print("Sample Idea:")
|
|
||||||
print(f" Title: {first_idea.get('title', 'N/A')}")
|
|
||||||
|
|
||||||
desc = first_idea.get('description', {})
|
|
||||||
if isinstance(desc, dict) and 'H2' in desc:
|
|
||||||
h2_count = len(desc['H2'])
|
|
||||||
print(f" H2 Sections: {h2_count}")
|
|
||||||
|
|
||||||
print(f" Keywords: {first_idea.get('covered_keywords', 'N/A')[:60]}...")
|
|
||||||
except json.JSONDecodeError:
|
|
||||||
print("⚠️ Could not parse JSON response")
|
|
||||||
|
|
||||||
print()
|
|
||||||
if finish_reason == 'length':
|
|
||||||
print("🚨 WARNING: Response was TRUNCATED!")
|
|
||||||
print(" Consider increasing max_tokens further")
|
|
||||||
else:
|
|
||||||
print("✅ Response completed successfully")
|
|
||||||
print(f" Used {completion_tokens} of {max_tokens:,} available tokens")
|
|
||||||
print(f" Headroom: {((max_tokens - completion_tokens) / max_tokens * 100):.1f}%")
|
|
||||||
|
|
||||||
else:
|
|
||||||
print(f"✗ API Error: {response.status_code}")
|
|
||||||
print(response.json().get('error', {}).get('message', '')[:200])
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"✗ Exception: {str(e)}")
|
|
||||||
|
|
||||||
print()
|
|
||||||
print("=" * 70)
|
|
||||||
print("CONCLUSION:")
|
|
||||||
print("=" * 70)
|
|
||||||
print("Idea generation typically uses 1500-2500 tokens for 3 ideas with outlines.")
|
|
||||||
print(f"Current max_tokens={max_tokens:,} provides plenty of headroom.")
|
|
||||||
print("✅ Configuration is optimal for idea generation.")
|
|
||||||
@@ -1,298 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
"""
|
|
||||||
Test AI with LARGE INPUT (5000+ tokens) and LARGE OUTPUT (5000+ tokens)
|
|
||||||
This simulates real content generation scenarios
|
|
||||||
"""
|
|
||||||
import os, sys, django
|
|
||||||
sys.path.insert(0, '/app')
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'igny8_core.settings')
|
|
||||||
django.setup()
|
|
||||||
|
|
||||||
import requests
|
|
||||||
from igny8_core.modules.system.models import IntegrationSettings
|
|
||||||
from igny8_core.auth.models import Account
|
|
||||||
|
|
||||||
account = Account.objects.filter(slug='aws-admin').first()
|
|
||||||
settings = IntegrationSettings.objects.filter(integration_type='openai', account=account, is_active=True).first()
|
|
||||||
config = settings.config or {}
|
|
||||||
api_key = config.get('apiKey')
|
|
||||||
model = config.get('model', 'gpt-4o')
|
|
||||||
|
|
||||||
print(f"🧪 Testing {model} with LARGE INPUT + LARGE OUTPUT")
|
|
||||||
print("=" * 80)
|
|
||||||
print()
|
|
||||||
|
|
||||||
# Create a VERY LONG prompt to ensure input > 5000 tokens
|
|
||||||
# Including detailed outline, examples, and extensive instructions
|
|
||||||
large_prompt = """You are a professional content writer. Generate a complete, comprehensive article following this detailed specification.
|
|
||||||
|
|
||||||
## Article Topic: "Complete Guide to Organic Cotton Bedding: Benefits, Types, and Buying Guide"
|
|
||||||
|
|
||||||
## Target Word Count: 2500+ words (approximately 3500+ tokens in output)
|
|
||||||
|
|
||||||
## JSON Output Format Required:
|
|
||||||
{
|
|
||||||
"title": "article title",
|
|
||||||
"meta_title": "SEO title under 60 chars",
|
|
||||||
"meta_description": "SEO description under 160 chars",
|
|
||||||
"content": "<full HTML content>",
|
|
||||||
"word_count": actual_word_count,
|
|
||||||
"primary_keyword": "organic cotton bedding",
|
|
||||||
"secondary_keywords": ["eco-friendly bedding", "sustainable sheets", "organic duvet covers"],
|
|
||||||
"tags": ["organic bedding", "sustainable home", "eco-friendly textiles", "cotton sheets", "bedroom essentials"],
|
|
||||||
"categories": ["Home & Living > Bedding", "Sustainable Living > Eco-Friendly Products"]
|
|
||||||
}
|
|
||||||
|
|
||||||
## DETAILED CONTENT STRUCTURE (Each section must be fully written with examples, data, and depth):
|
|
||||||
|
|
||||||
### Section 1: Introduction (300 words)
|
|
||||||
Write a compelling introduction that:
|
|
||||||
- Opens with an engaging hook about the rise of organic bedding
|
|
||||||
- Explains why consumers are switching from conventional to organic cotton
|
|
||||||
- Discusses market trends and growth statistics
|
|
||||||
- Mentions health concerns with conventional bedding
|
|
||||||
- Previews what readers will learn in this comprehensive guide
|
|
||||||
- Naturally incorporates the primary keyword "organic cotton bedding"
|
|
||||||
|
|
||||||
### Section 2: Understanding Organic Cotton (400 words)
|
|
||||||
Write a detailed section covering:
|
|
||||||
- Definition of organic cotton and GOTS (Global Organic Textile Standard) certification
|
|
||||||
- Differences between organic and conventional cotton farming practices
|
|
||||||
- Specific pesticides and chemicals avoided in organic farming
|
|
||||||
- Water usage statistics (organic vs conventional)
|
|
||||||
- Soil health and crop rotation practices
|
|
||||||
- Carbon footprint comparison data
|
|
||||||
- Other certifications to look for (OEKO-TEX, Fair Trade, etc.)
|
|
||||||
- Include specific examples of organic cotton farms and their practices
|
|
||||||
- Mention leading organic cotton producing regions globally
|
|
||||||
|
|
||||||
### Section 3: Health Benefits of Organic Cotton Bedding (400 words)
|
|
||||||
Comprehensive coverage of:
|
|
||||||
- Hypoallergenic properties and why they matter
|
|
||||||
- Impact on sensitive skin and skin conditions (eczema, psoriasis, allergies)
|
|
||||||
- Chemical residues in conventional bedding and health risks
|
|
||||||
- Dermatologist recommendations and clinical studies
|
|
||||||
- Respiratory benefits from chemical-free textiles
|
|
||||||
- Benefits for babies and children
|
|
||||||
- Real customer testimonials and experiences
|
|
||||||
- Comparison of skin irritation rates between organic and conventional bedding
|
|
||||||
- Long-term health advantages
|
|
||||||
|
|
||||||
### Section 4: Environmental Impact and Sustainability (400 words)
|
|
||||||
Detailed analysis including:
|
|
||||||
- Water conservation statistics (gallons saved per pound of cotton)
|
|
||||||
- Pesticide elimination impact on ecosystems
|
|
||||||
- Biodiversity benefits for pollinators and wildlife
|
|
||||||
- Soil degradation prevention through organic farming
|
|
||||||
- Carbon emissions comparison with conventional cotton
|
|
||||||
- Impact on farmer health and community welfare
|
|
||||||
- Waste reduction in textile production
|
|
||||||
- End-of-life biodegradability
|
|
||||||
- Circular economy considerations
|
|
||||||
- Case studies of sustainable bedding brands
|
|
||||||
|
|
||||||
### Section 5: Types of Organic Cotton Bedding (350 words)
|
|
||||||
Comprehensive overview of:
|
|
||||||
- Organic cotton sheets (fitted, flat, pillowcases)
|
|
||||||
- Thread count ranges and what they mean
|
|
||||||
- Weave types: percale, sateen, jersey, flannel
|
|
||||||
- Specific characteristics of each weave
|
|
||||||
- Organic cotton duvet covers and comforters
|
|
||||||
- Fill power and warmth ratings
|
|
||||||
- Seasonal considerations
|
|
||||||
- Organic cotton mattress protectors and pads
|
|
||||||
- Waterproof vs breathable options
|
|
||||||
- Organic cotton blankets and throws
|
|
||||||
- Specialty items (body pillows, Euro shams, bed skirts)
|
|
||||||
- Price ranges for each category
|
|
||||||
- Brand examples for each product type
|
|
||||||
|
|
||||||
### Section 6: Quality Factors and What to Look For (350 words)
|
|
||||||
In-depth buying guidance:
|
|
||||||
- Thread count myths and realities (why 800+ isn't always better)
|
|
||||||
- Ply differences (single-ply vs multi-ply)
|
|
||||||
- Weave construction details
|
|
||||||
- Fabric weight and GSM (grams per square meter)
|
|
||||||
- Fiber length and quality grades
|
|
||||||
- Color fastness and dye methods (low-impact dyes)
|
|
||||||
- Shrinkage rates and pre-washing
|
|
||||||
- Durability testing standards
|
|
||||||
- Pilling resistance
|
|
||||||
- How to verify authentic organic certification
|
|
||||||
- Red flags for fake "organic" claims
|
|
||||||
|
|
||||||
### Section 7: Top Organic Cotton Bedding Brands (400 words)
|
|
||||||
Detailed brand reviews including:
|
|
||||||
- Coyuchi: Product range, price points, unique features, customer ratings
|
|
||||||
- Boll & Branch: Signature products, fair trade practices, pricing
|
|
||||||
- Parachute: Material quality, design aesthetic, value proposition
|
|
||||||
- Pottery Barn Organic: Accessibility, variety, retail presence
|
|
||||||
- West Elm Organic: Style options, price range, sustainability initiatives
|
|
||||||
- SOL Organics: Budget-friendly options, certification details
|
|
||||||
- Avocado: Premium positioning, additional eco-features
|
|
||||||
- Include specific product examples from each brand
|
|
||||||
- Price comparison table format
|
|
||||||
- Warranty and return policy highlights
|
|
||||||
|
|
||||||
### Section 8: Care and Maintenance (300 words)
|
|
||||||
Comprehensive care instructions:
|
|
||||||
- Initial washing recommendations before first use
|
|
||||||
- Water temperature guidelines for different weaves
|
|
||||||
- Detergent recommendations (eco-friendly, fragrance-free)
|
|
||||||
- Drying methods: air-dry vs machine dry
|
|
||||||
- Ironing tips for different weaves
|
|
||||||
- Stain removal techniques for organic cotton
|
|
||||||
- Frequency of washing for longevity
|
|
||||||
- Storage recommendations for seasonal items
|
|
||||||
- How to maintain whiteness without bleach
|
|
||||||
- Expected lifespan with proper care (5-10 years)
|
|
||||||
- When to replace bedding
|
|
||||||
|
|
||||||
### Section 9: Cost Analysis and Value Proposition (300 words)
|
|
||||||
Financial breakdown:
|
|
||||||
- Price range overview: budget ($50-100), mid-range ($100-250), premium ($250-500+)
|
|
||||||
- Cost per use calculation over 5 years
|
|
||||||
- Durability comparison with conventional bedding
|
|
||||||
- Health cost savings (reduced allergies, better sleep)
|
|
||||||
- Environmental value beyond personal use
|
|
||||||
- Sale and discount timing (when to buy)
|
|
||||||
- Starter set recommendations for budget-conscious buyers
|
|
||||||
- Investment prioritization (which pieces to buy first)
|
|
||||||
- Comparison with luxury conventional bedding prices
|
|
||||||
|
|
||||||
### Section 10: Where to Buy (200 words)
|
|
||||||
Shopping guide including:
|
|
||||||
- Direct-to-consumer brands (online)
|
|
||||||
- Major retailers (Pottery Barn, West Elm, Crate & Barrel)
|
|
||||||
- Amazon and online marketplaces (verification tips)
|
|
||||||
- Local organic stores and boutiques
|
|
||||||
- Outlet and discount sources
|
|
||||||
- International shipping considerations
|
|
||||||
- Return policies and trial periods
|
|
||||||
- Customer service quality comparisons
|
|
||||||
|
|
||||||
### Section 11: Conclusion (150 words)
|
|
||||||
Wrap up with:
|
|
||||||
- Summary of key benefits
|
|
||||||
- Final recommendations for different buyer types
|
|
||||||
- Call to action
|
|
||||||
- Future of organic bedding industry
|
|
||||||
|
|
||||||
## Writing Requirements:
|
|
||||||
- Use active voice throughout
|
|
||||||
- Include specific data points, statistics, and examples
|
|
||||||
- Vary sentence structure for natural flow
|
|
||||||
- Use HTML tags properly: <p>, <h2>, <h3>, <ul>, <ol>, <table>
|
|
||||||
- Create comparison tables where appropriate
|
|
||||||
- Use <blockquote> for expert quotes or key insights
|
|
||||||
- Maintain professional, editorial tone
|
|
||||||
- Avoid generic phrases and filler content
|
|
||||||
- Each paragraph should be 3-5 sentences minimum
|
|
||||||
- Lists should have detailed descriptions, not just bullet points
|
|
||||||
|
|
||||||
Return ONLY the JSON object. The content field must contain ALL sections fully written in HTML format."""
|
|
||||||
|
|
||||||
print("📊 Prompt Statistics:")
|
|
||||||
print(f" Prompt Length: {len(large_prompt)} characters")
|
|
||||||
print(f" Estimated Input Tokens: ~{len(large_prompt) // 4} tokens")
|
|
||||||
print()
|
|
||||||
|
|
||||||
# Test with different max_tokens settings
|
|
||||||
tests = [
|
|
||||||
{"name": "Test 1: max_tokens=4096", "max_tokens": 4096},
|
|
||||||
{"name": "Test 2: max_tokens=8192", "max_tokens": 8192},
|
|
||||||
{"name": "Test 3: max_tokens=16384", "max_tokens": 16384},
|
|
||||||
]
|
|
||||||
|
|
||||||
print("🚀 Starting API Tests...")
|
|
||||||
print("=" * 80)
|
|
||||||
|
|
||||||
for test in tests:
|
|
||||||
print(f"\n{test['name']}")
|
|
||||||
print("-" * 80)
|
|
||||||
|
|
||||||
try:
|
|
||||||
response = requests.post(
|
|
||||||
'https://api.openai.com/v1/chat/completions',
|
|
||||||
headers={
|
|
||||||
'Authorization': f'Bearer {api_key}',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
json={
|
|
||||||
'model': model,
|
|
||||||
'messages': [{'role': 'user', 'content': large_prompt}],
|
|
||||||
'max_tokens': test['max_tokens'],
|
|
||||||
'temperature': 0.7,
|
|
||||||
},
|
|
||||||
timeout=180 # 3 minutes for long generation
|
|
||||||
)
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
data = response.json()
|
|
||||||
usage = data.get('usage', {})
|
|
||||||
finish_reason = data['choices'][0].get('finish_reason')
|
|
||||||
|
|
||||||
prompt_tokens = usage.get('prompt_tokens', 0)
|
|
||||||
completion_tokens = usage.get('completion_tokens', 0)
|
|
||||||
total_tokens = usage.get('total_tokens', 0)
|
|
||||||
|
|
||||||
# Estimate word count (1 token ≈ 0.75 words)
|
|
||||||
estimated_words = int(completion_tokens * 0.75)
|
|
||||||
|
|
||||||
print(f"✓ Response received")
|
|
||||||
print(f" Input Tokens: {prompt_tokens:>6,} tokens")
|
|
||||||
print(f" Output Tokens: {completion_tokens:>6,} tokens")
|
|
||||||
print(f" Total Tokens: {total_tokens:>6,} tokens")
|
|
||||||
print(f" Estimated Words: ~{estimated_words:>5,} words")
|
|
||||||
print(f" Finish Reason: {finish_reason}")
|
|
||||||
|
|
||||||
if finish_reason == 'length':
|
|
||||||
print(f" 🚨 TRUNCATED: Hit max_tokens={test['max_tokens']:,} limit!")
|
|
||||||
print(f" ⚠️ Content is INCOMPLETE - needs higher max_tokens")
|
|
||||||
elif finish_reason == 'stop':
|
|
||||||
print(f" ✅ COMPLETE: Response finished naturally")
|
|
||||||
|
|
||||||
# Check if we met our goals
|
|
||||||
if prompt_tokens > 5000:
|
|
||||||
print(f" ✅ Input > 5000 tokens")
|
|
||||||
else:
|
|
||||||
print(f" ⚠️ Input only {prompt_tokens} tokens (target: 5000+)")
|
|
||||||
|
|
||||||
if completion_tokens > 5000:
|
|
||||||
print(f" ✅ Output > 5000 tokens")
|
|
||||||
else:
|
|
||||||
print(f" ⚠️ Output only {completion_tokens} tokens (target: 5000+)")
|
|
||||||
|
|
||||||
else:
|
|
||||||
error_data = response.json()
|
|
||||||
error_msg = error_data.get('error', {}).get('message', 'Unknown error')
|
|
||||||
print(f" ✗ API Error: {response.status_code}")
|
|
||||||
print(f" Error: {error_msg}")
|
|
||||||
|
|
||||||
except requests.exceptions.Timeout:
|
|
||||||
print(f" ✗ Request timed out after 180 seconds")
|
|
||||||
except Exception as e:
|
|
||||||
print(f" ✗ Exception: {str(e)}")
|
|
||||||
|
|
||||||
print("\n" + "=" * 80)
|
|
||||||
print("🎯 FINAL ANALYSIS")
|
|
||||||
print("=" * 80)
|
|
||||||
print()
|
|
||||||
print("Key Questions Answered:")
|
|
||||||
print()
|
|
||||||
print("1. Can the model handle 5000+ token INPUT?")
|
|
||||||
print(" → Check 'Input Tokens' above (should be 5000+)")
|
|
||||||
print()
|
|
||||||
print("2. Can the model generate 5000+ token OUTPUT?")
|
|
||||||
print(" → Check 'Output Tokens' above (should be 5000+)")
|
|
||||||
print()
|
|
||||||
print("3. Does max_tokens limit actually work as expected?")
|
|
||||||
print(" → Compare output tokens across tests with different limits")
|
|
||||||
print()
|
|
||||||
print("4. Is content getting truncated with current 8192 setting?")
|
|
||||||
print(" → Check if 'Finish Reason' is 'length' for 8192 test")
|
|
||||||
print()
|
|
||||||
print("💡 RECOMMENDATION:")
|
|
||||||
print(" If Test 2 (8192) shows 'TRUNCATED', increase max_tokens for content generation")
|
|
||||||
print(" If Test 3 (16384) shows 'COMPLETE', that's the minimum needed for long articles")
|
|
||||||
print()
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
"""
|
|
||||||
Test if AI can generate 2000+ word content (requires ~2700+ tokens)
|
|
||||||
"""
|
|
||||||
import os, sys, django
|
|
||||||
sys.path.insert(0, '/app')
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'igny8_core.settings')
|
|
||||||
django.setup()
|
|
||||||
|
|
||||||
import requests
|
|
||||||
from igny8_core.modules.system.models import IntegrationSettings
|
|
||||||
from igny8_core.auth.models import Account
|
|
||||||
|
|
||||||
account = Account.objects.filter(slug='aws-admin').first()
|
|
||||||
settings = IntegrationSettings.objects.filter(integration_type='openai', account=account, is_active=True).first()
|
|
||||||
config = settings.config or {}
|
|
||||||
api_key = config.get('apiKey')
|
|
||||||
model = config.get('model', 'gpt-4o')
|
|
||||||
|
|
||||||
print(f"🧪 Testing {model} with VERY LONG content requirement")
|
|
||||||
print("=" * 70)
|
|
||||||
|
|
||||||
# This prompt REQUIRES a very long response with many detailed sections
|
|
||||||
prompt = """Generate a complete JSON article about "Complete Guide to Organic Cotton Bedding" following this EXACT structure. Each section MUST be fully detailed with examples, data, and comprehensive explanations.
|
|
||||||
|
|
||||||
JSON Format:
|
|
||||||
{
|
|
||||||
"title": "Complete Guide to Organic Cotton Bedding: Benefits, Buying Tips, and Care",
|
|
||||||
"content": "<full HTML content here>",
|
|
||||||
"word_count": 2000
|
|
||||||
}
|
|
||||||
|
|
||||||
Content Requirements (MINIMUM 2000 words total):
|
|
||||||
|
|
||||||
<h2>Introduction</h2>
|
|
||||||
Write 200 words introducing organic cotton bedding, market trends, and why consumers are switching.
|
|
||||||
|
|
||||||
<h2>What is Organic Cotton?</h2>
|
|
||||||
Write 250 words explaining organic cotton certification, farming methods, GOTS standards, and differences from conventional cotton. Include specific examples of organic farming practices.
|
|
||||||
|
|
||||||
<h2>Health and Skin Benefits</h2>
|
|
||||||
Write 300 words covering hypoallergenic properties, chemical-free benefits, impact on sensitive skin, dermatologist recommendations, and real-world testimonials.
|
|
||||||
|
|
||||||
<h2>Environmental Impact and Sustainability</h2>
|
|
||||||
Write 300 words with detailed statistics on water conservation, pesticide elimination, carbon footprint, soil health, biodiversity benefits, and certification bodies.
|
|
||||||
|
|
||||||
<h2>Quality, Durability, and Thread Count</h2>
|
|
||||||
Write 250 words explaining thread count myths, weave types (percale vs sateen), durability testing, washing cycle performance, and longevity comparisons.
|
|
||||||
|
|
||||||
<h2>Cost Analysis and Value</h2>
|
|
||||||
Write 250 words with price comparisons, cost-per-use calculations, 5-year ownership analysis, warranty information, and investment justification.
|
|
||||||
|
|
||||||
<h2>Top Organic Cotton Bedding Brands</h2>
|
|
||||||
Write 250 words reviewing 5-7 major brands with specific product examples, price ranges, unique features, and customer ratings.
|
|
||||||
|
|
||||||
<h2>Buying Guide and What to Look For</h2>
|
|
||||||
Write 200 words on certification verification, red flags, shopping tips, online vs retail, and return policies.
|
|
||||||
|
|
||||||
Return ONLY valid JSON. The content field must contain complete HTML with ALL sections fully written."""
|
|
||||||
|
|
||||||
tests = [
|
|
||||||
("4096 tokens", 4096),
|
|
||||||
("8192 tokens", 8192),
|
|
||||||
("16384 tokens", 16384),
|
|
||||||
]
|
|
||||||
|
|
||||||
print()
|
|
||||||
for name, max_tokens in tests:
|
|
||||||
print(f"📝 Testing with max_tokens = {max_tokens}")
|
|
||||||
print("-" * 70)
|
|
||||||
|
|
||||||
try:
|
|
||||||
response = requests.post(
|
|
||||||
'https://api.openai.com/v1/chat/completions',
|
|
||||||
headers={'Authorization': f'Bearer {api_key}', 'Content-Type': 'application/json'},
|
|
||||||
json={
|
|
||||||
'model': model,
|
|
||||||
'messages': [{'role': 'user', 'content': prompt}],
|
|
||||||
'max_tokens': max_tokens,
|
|
||||||
'temperature': 0.7,
|
|
||||||
},
|
|
||||||
timeout=120
|
|
||||||
)
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
data = response.json()
|
|
||||||
usage = data.get('usage', {})
|
|
||||||
finish_reason = data['choices'][0].get('finish_reason')
|
|
||||||
completion = usage.get('completion_tokens', 0)
|
|
||||||
|
|
||||||
# Rough word count estimate (1 token ≈ 0.75 words)
|
|
||||||
estimated_words = int(completion * 0.75)
|
|
||||||
|
|
||||||
print(f" Completion Tokens: {completion}")
|
|
||||||
print(f" Estimated Words: ~{estimated_words}")
|
|
||||||
print(f" Finish Reason: {finish_reason}")
|
|
||||||
|
|
||||||
if finish_reason == 'length':
|
|
||||||
print(f" ⚠️ TRUNCATED at {max_tokens} tokens!")
|
|
||||||
print(f" 🚨 Content was CUT OFF - NOT COMPLETE")
|
|
||||||
else:
|
|
||||||
print(f" ✅ Response completed naturally")
|
|
||||||
|
|
||||||
print()
|
|
||||||
else:
|
|
||||||
error = response.json().get('error', {})
|
|
||||||
print(f" ✗ Error: {error.get('message', 'Unknown')}\n")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f" ✗ Exception: {e}\n")
|
|
||||||
|
|
||||||
print("=" * 70)
|
|
||||||
print("🎯 CONCLUSION:")
|
|
||||||
print("=" * 70)
|
|
||||||
print("If any test shows 'TRUNCATED', we need higher max_tokens for content generation.")
|
|
||||||
print("A 2000-word article needs ~2700 completion tokens minimum.")
|
|
||||||
print()
|
|
||||||
@@ -1,149 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
"""
|
|
||||||
Test script to verify if AI model can actually use 8192+ max_tokens
|
|
||||||
"""
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import django
|
|
||||||
|
|
||||||
# Setup Django
|
|
||||||
sys.path.insert(0, '/app')
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'igny8_core.settings')
|
|
||||||
django.setup()
|
|
||||||
|
|
||||||
import requests
|
|
||||||
import json
|
|
||||||
from igny8_core.modules.system.models import IntegrationSettings
|
|
||||||
from igny8_core.auth.models import Account
|
|
||||||
|
|
||||||
# Get API configuration
|
|
||||||
account = Account.objects.filter(slug='aws-admin').first()
|
|
||||||
settings = IntegrationSettings.objects.filter(
|
|
||||||
integration_type='openai',
|
|
||||||
account=account,
|
|
||||||
is_active=True
|
|
||||||
).first()
|
|
||||||
|
|
||||||
config = settings.config or {}
|
|
||||||
api_key = config.get('apiKey')
|
|
||||||
model = config.get('model', 'gpt-4o')
|
|
||||||
|
|
||||||
print(f"🧪 Testing AI Model: {model}")
|
|
||||||
print("=" * 70)
|
|
||||||
print()
|
|
||||||
|
|
||||||
# Test with a prompt requiring long response
|
|
||||||
test_prompt = """Write a comprehensive 1500-word article about "The Benefits of Organic Cotton Bedding" with these 7 sections:
|
|
||||||
|
|
||||||
1. Introduction (200 words)
|
|
||||||
2. Health and Skin Benefits (250 words)
|
|
||||||
3. Environmental Sustainability (250 words)
|
|
||||||
4. Quality and Durability (250 words)
|
|
||||||
5. Cost Analysis (200 words)
|
|
||||||
6. Buying Guide (250 words)
|
|
||||||
7. Conclusion (100 words)
|
|
||||||
|
|
||||||
Include specific examples, data points, and detailed comparisons in each section."""
|
|
||||||
|
|
||||||
tests = [
|
|
||||||
{"name": "Test with max_tokens=4096", "max_tokens": 4096},
|
|
||||||
{"name": "Test with max_tokens=8192", "max_tokens": 8192},
|
|
||||||
{"name": "Test with max_tokens=16384", "max_tokens": 16384},
|
|
||||||
]
|
|
||||||
|
|
||||||
results = []
|
|
||||||
|
|
||||||
for test in tests:
|
|
||||||
print(f"\n{test['name']}")
|
|
||||||
print("-" * 70)
|
|
||||||
|
|
||||||
try:
|
|
||||||
response = requests.post(
|
|
||||||
'https://api.openai.com/v1/chat/completions',
|
|
||||||
headers={
|
|
||||||
'Authorization': f'Bearer {api_key}',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
json={
|
|
||||||
'model': model,
|
|
||||||
'messages': [{'role': 'user', 'content': test_prompt}],
|
|
||||||
'max_tokens': test['max_tokens'],
|
|
||||||
'temperature': 0.7,
|
|
||||||
},
|
|
||||||
timeout=120
|
|
||||||
)
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
data = response.json()
|
|
||||||
usage = data.get('usage', {})
|
|
||||||
finish_reason = data['choices'][0].get('finish_reason', 'unknown')
|
|
||||||
|
|
||||||
result = {
|
|
||||||
'max_tokens': test['max_tokens'],
|
|
||||||
'prompt_tokens': usage.get('prompt_tokens', 0),
|
|
||||||
'completion_tokens': usage.get('completion_tokens', 0),
|
|
||||||
'total_tokens': usage.get('total_tokens', 0),
|
|
||||||
'finish_reason': finish_reason,
|
|
||||||
'status': 'success'
|
|
||||||
}
|
|
||||||
results.append(result)
|
|
||||||
|
|
||||||
print(f"✓ Response received")
|
|
||||||
print(f" Prompt Tokens: {result['prompt_tokens']}")
|
|
||||||
print(f" Completion Tokens: {result['completion_tokens']}")
|
|
||||||
print(f" Total Tokens: {result['total_tokens']}")
|
|
||||||
print(f" Finish Reason: {finish_reason}")
|
|
||||||
|
|
||||||
if finish_reason == 'length':
|
|
||||||
print(f" ⚠️ TRUNCATED: Hit the max_tokens={test['max_tokens']} limit!")
|
|
||||||
elif finish_reason == 'stop':
|
|
||||||
print(f" ✅ COMPLETE: Response finished naturally")
|
|
||||||
else:
|
|
||||||
print(f"✗ API Error: {response.status_code}")
|
|
||||||
error_data = response.json()
|
|
||||||
print(f" Error: {error_data.get('error', {}).get('message', 'Unknown error')}")
|
|
||||||
results.append({
|
|
||||||
'max_tokens': test['max_tokens'],
|
|
||||||
'status': 'error',
|
|
||||||
'error': error_data.get('error', {}).get('message', 'Unknown error')
|
|
||||||
})
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"✗ Exception: {str(e)}")
|
|
||||||
results.append({
|
|
||||||
'max_tokens': test['max_tokens'],
|
|
||||||
'status': 'exception',
|
|
||||||
'error': str(e)
|
|
||||||
})
|
|
||||||
|
|
||||||
# Print summary
|
|
||||||
print("\n" + "=" * 70)
|
|
||||||
print("📊 SUMMARY")
|
|
||||||
print("=" * 70)
|
|
||||||
|
|
||||||
success_results = [r for r in results if r.get('status') == 'success']
|
|
||||||
|
|
||||||
if len(success_results) >= 2:
|
|
||||||
for i, result in enumerate(success_results):
|
|
||||||
status_icon = "⚠️ " if result['finish_reason'] == 'length' else "✅"
|
|
||||||
print(f"{status_icon} max_tokens={result['max_tokens']:5d}: {result['completion_tokens']:5d} tokens generated ({result['finish_reason']})")
|
|
||||||
|
|
||||||
print()
|
|
||||||
# Compare results
|
|
||||||
if success_results[0]['finish_reason'] == 'length' and success_results[-1]['finish_reason'] == 'stop':
|
|
||||||
print("✅ VERIFIED: Higher max_tokens allows longer, complete responses!")
|
|
||||||
print(f" Model can generate {success_results[-1]['completion_tokens']} tokens without truncation")
|
|
||||||
elif success_results[-1]['completion_tokens'] > success_results[0]['max_tokens']:
|
|
||||||
print(f"✅ VERIFIED: Model generated {success_results[-1]['completion_tokens']} tokens")
|
|
||||||
print(f" This exceeds the {success_results[0]['max_tokens']} limit from first test")
|
|
||||||
else:
|
|
||||||
print("ℹ️ All tests completed but responses were similar in length")
|
|
||||||
print(" The prompt may not require more than ~4000 tokens")
|
|
||||||
|
|
||||||
print()
|
|
||||||
print("💡 RECOMMENDATION:")
|
|
||||||
if any(r.get('finish_reason') == 'length' and r.get('max_tokens', 0) <= 8192 for r in success_results):
|
|
||||||
print(" Content generation needs max_tokens > 8192 for long articles (1200+ words)")
|
|
||||||
print(" Suggest: Set max_tokens to 16384 for content_generation function")
|
|
||||||
else:
|
|
||||||
print(" Current max_tokens=8192 appears sufficient for most content")
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
"""
|
|
||||||
Test the ACTUAL AI function execution path (same as frontend)
|
|
||||||
"""
|
|
||||||
import os, sys, django
|
|
||||||
sys.path.insert(0, '/app')
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'igny8_core.settings')
|
|
||||||
django.setup()
|
|
||||||
|
|
||||||
from igny8_core.ai.tasks import run_ai_task
|
|
||||||
from igny8_core.auth.models import Account, Site
|
|
||||||
from igny8_core.business.content.models import Tasks
|
|
||||||
import json
|
|
||||||
|
|
||||||
# Get account
|
|
||||||
account = Account.objects.filter(slug='aws-admin').first()
|
|
||||||
site = Site.objects.filter(account=account).first()
|
|
||||||
|
|
||||||
# Create a test task with the massager content idea
|
|
||||||
task_data = {
|
|
||||||
"title": "Top Shiatsu Back and Neck Massagers for Effective Pain Relief",
|
|
||||||
"description": json.dumps({
|
|
||||||
"introduction": {
|
|
||||||
"hook": "Explore the best shiatsu back and neck massagers to alleviate pain and improve relaxation.",
|
|
||||||
"paragraphs": [
|
|
||||||
{"content_type": "paragraph", "details": "Introduction to the concept of shiatsu massage and its effectiveness for pain relief."},
|
|
||||||
{"content_type": "paragraph", "details": "The shift towards home-based massage solutions in managing chronic pain."}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"H2": [
|
|
||||||
{
|
|
||||||
"heading": "Understanding Shiatsu Back and Neck Massagers",
|
|
||||||
"subsections": [
|
|
||||||
{"subheading": "The Science of Shiatsu Massage", "content_type": "paragraph", "details": "Explanation of shiatsu techniques and their therapeutic benefits."},
|
|
||||||
{"subheading": "Choosing the Right Shiatsu Massager", "content_type": "list", "details": "Evaluating features like heat, intensity settings, and portability."}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"heading": "Benefits of Shiatsu Massagers for Neck and Back",
|
|
||||||
"subsections": [
|
|
||||||
{"subheading": "Pain Relief and Muscle Relaxation", "content_type": "paragraph", "details": "How shiatsu massage helps release muscle tension."},
|
|
||||||
{"subheading": "Improved Sleep and Stress Reduction", "content_type": "list", "details": "Additional health benefits of regular shiatsu massages."}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"heading": "Top Shiatsu Back and Neck Massagers to Consider",
|
|
||||||
"subsections": [
|
|
||||||
{"subheading": "High-End Models", "content_type": "paragraph", "details": "Features of top-tier shiatsu massagers."},
|
|
||||||
{"subheading": "Best Budget Picks", "content_type": "list", "details": "Affordable options without compromising on quality."}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"heading": "User Guide: How to Use a Shiatsu Massager",
|
|
||||||
"subsections": [
|
|
||||||
{"subheading": "Step-by-Step Instructions", "content_type": "paragraph", "details": "Detailed guide on using your massager effectively."},
|
|
||||||
{"subheading": "Safety Tips", "content_type": "list", "details": "Precautions to ensure safe and beneficial use."}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"heading": "Comparing Shiatsu and Electric Massagers for Back Pain",
|
|
||||||
"subsections": [
|
|
||||||
{"subheading": "Pros and Cons", "content_type": "paragraph", "details": "Comparison of features and benefits."},
|
|
||||||
{"subheading": "Choosing Based on Personal Needs", "content_type": "list", "details": "Factors to consider when selecting a massager."}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"heading": "Caring for Your Shiatsu Massager",
|
|
||||||
"subsections": [
|
|
||||||
{"subheading": "Cleaning and Maintenance Tips", "content_type": "paragraph", "details": "Ensuring your massager lasts longer with proper care."},
|
|
||||||
{"subheading": "Troubleshooting and Repairs", "content_type": "list", "details": "Common issues and how to fix them."}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}),
|
|
||||||
"content_type": "post",
|
|
||||||
"content_structure": "comparison",
|
|
||||||
"keywords": "shiatsu back and neck massager, shiatsu neck and back massager, shiatsu back massager",
|
|
||||||
"status": "new",
|
|
||||||
"account": account,
|
|
||||||
"site": site,
|
|
||||||
}
|
|
||||||
|
|
||||||
# Create or get existing test task
|
|
||||||
task = Tasks.objects.filter(
|
|
||||||
title=task_data['title'],
|
|
||||||
account=account
|
|
||||||
).first()
|
|
||||||
|
|
||||||
if not task:
|
|
||||||
task = Tasks.objects.create(**task_data)
|
|
||||||
print(f"✅ Created test task: {task.id}")
|
|
||||||
else:
|
|
||||||
print(f"✅ Using existing task: {task.id}")
|
|
||||||
|
|
||||||
print()
|
|
||||||
print("=" * 70)
|
|
||||||
print("RUNNING ACTUAL AI FUNCTION (same path as frontend)")
|
|
||||||
print("=" * 70)
|
|
||||||
print()
|
|
||||||
|
|
||||||
# Run the ACTUAL function (synchronous, not Celery)
|
|
||||||
result = run_ai_task(
|
|
||||||
function_name='generate_content',
|
|
||||||
payload={'ids': [task.id]},
|
|
||||||
account_id=account.id,
|
|
||||||
self=type('obj', (object,), {'request': type('obj', (object,), {'id': 'test-task-id'})(), 'update_state': lambda *args, **kwargs: None})()
|
|
||||||
)
|
|
||||||
|
|
||||||
print()
|
|
||||||
print("=" * 70)
|
|
||||||
print("RESULT")
|
|
||||||
print("=" * 70)
|
|
||||||
print()
|
|
||||||
|
|
||||||
if result.get('success'):
|
|
||||||
print("✅ Content generated successfully")
|
|
||||||
print(f" Items created: {result.get('count', 0)}")
|
|
||||||
|
|
||||||
# Get the generated content
|
|
||||||
from igny8_core.business.content.models import Content
|
|
||||||
content = Content.objects.filter(task=task).order_by('-created_at').first()
|
|
||||||
|
|
||||||
if content:
|
|
||||||
# Count actual words
|
|
||||||
import re
|
|
||||||
from html import unescape
|
|
||||||
|
|
||||||
html_content = content.content_html or ''
|
|
||||||
# Strip HTML tags
|
|
||||||
text_only = re.sub(r'<[^>]+>', '', html_content)
|
|
||||||
# Unescape HTML entities
|
|
||||||
text_only = unescape(text_only)
|
|
||||||
# Count words
|
|
||||||
words = len(text_only.split())
|
|
||||||
|
|
||||||
print(f" Title: {content.title[:60]}...")
|
|
||||||
print(f" Word Count (actual): {words}")
|
|
||||||
print(f" Word Count (reported): {content.word_count}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
if words < 1200:
|
|
||||||
print(f"🚨 PROBLEM: Only {words} words generated (target: 1200+)")
|
|
||||||
print(f" Shortfall: {1200 - words} words missing")
|
|
||||||
else:
|
|
||||||
print(f"✅ SUCCESS: {words} words generated (exceeds 1200 minimum)")
|
|
||||||
|
|
||||||
# Show first 500 chars
|
|
||||||
print()
|
|
||||||
print("First 500 characters of content:")
|
|
||||||
print("-" * 70)
|
|
||||||
print(text_only[:500])
|
|
||||||
|
|
||||||
else:
|
|
||||||
print(f"❌ Generation failed: {result.get('error')}")
|
|
||||||
|
|
||||||
print()
|
|
||||||
print("=" * 70)
|
|
||||||
print("This is the EXACT same code path used by the frontend")
|
|
||||||
print("=" * 70)
|
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
"""
|
|
||||||
Test with ACTUAL content generation prompt structure to see real token usage
|
|
||||||
"""
|
|
||||||
import os, sys, django
|
|
||||||
sys.path.insert(0, '/app')
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'igny8_core.settings')
|
|
||||||
django.setup()
|
|
||||||
|
|
||||||
import requests, json
|
|
||||||
from igny8_core.modules.system.models import IntegrationSettings
|
|
||||||
from igny8_core.auth.models import Account
|
|
||||||
|
|
||||||
account = Account.objects.filter(slug='aws-admin').first()
|
|
||||||
settings = IntegrationSettings.objects.filter(integration_type='openai', account=account, is_active=True).first()
|
|
||||||
config = settings.config or {}
|
|
||||||
api_key = config.get('apiKey')
|
|
||||||
model = config.get('model', 'gpt-4o')
|
|
||||||
|
|
||||||
# Read the ACTUAL content generation prompt
|
|
||||||
with open('/data/content-generation-prompt.md', 'r') as f:
|
|
||||||
prompt_template = f.read()
|
|
||||||
|
|
||||||
# Create realistic content idea with 7 detailed H2 sections
|
|
||||||
idea_data = {
|
|
||||||
"title": "Complete Guide to Organic Cotton Bedding: Benefits, Care, and Buying Tips",
|
|
||||||
"description": {
|
|
||||||
"introduction": {
|
|
||||||
"hook": "Transform your bedroom into a healthier sanctuary with organic cotton bedding that promises better sleep and peace of mind.",
|
|
||||||
"paragraphs": [
|
|
||||||
{"content_type": "paragraph", "details": "Growing consumer awareness of chemical exposure in everyday products | Rise of organic bedding market | Health and environmental benefits driving adoption"},
|
|
||||||
{"content_type": "paragraph", "details": "Investment in quality sleep surfaces | Long-term value proposition | This comprehensive guide covers everything you need to know"}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"H2": [
|
|
||||||
{"heading": "Understanding Organic Cotton Certification", "subsections": [
|
|
||||||
{"subheading": "GOTS Standards Explained", "content_type": "paragraph", "details": "Global Organic Textile Standard requirements | Certification process | Third-party verification"},
|
|
||||||
{"subheading": "Other Important Certifications", "content_type": "list", "details": "OEKO-TEX Standard 100 | Fair Trade | Organic Content Standard"},
|
|
||||||
{"subheading": "Verification Methods", "content_type": "paragraph", "details": "How to verify authentic certifications | Common red flags | Label reading guide"}
|
|
||||||
]},
|
|
||||||
{"heading": "Health Benefits of Organic Cotton Bedding", "subsections": [
|
|
||||||
{"subheading": "Hypoallergenic Properties", "content_type": "paragraph", "details": "Absence of chemical irritants | Benefits for sensitive skin | Clinical studies on allergen reduction"},
|
|
||||||
{"subheading": "Chemical-Free Advantages", "content_type": "paragraph", "details": "Pesticide residues in conventional cotton | Health impacts of formaldehyde and other chemicals | Dermatologist recommendations"},
|
|
||||||
{"subheading": "Impact on Sleep Quality", "content_type": "paragraph", "details": "Breathability and temperature regulation | Moisture wicking properties | Sleep study findings"}
|
|
||||||
]},
|
|
||||||
{"heading": "Environmental Impact and Sustainability", "subsections": [
|
|
||||||
{"subheading": "Water Conservation", "content_type": "paragraph", "details": "Water usage comparison organic vs conventional | Statistics on water savings | Impact on global water resources"},
|
|
||||||
{"subheading": "Pesticide Elimination", "content_type": "list", "details": "Toxic chemicals avoided | Impact on ecosystems | Soil health benefits"},
|
|
||||||
{"subheading": "Carbon Footprint", "content_type": "table", "details": "Emissions comparison | Manufacturing process differences | Transportation considerations"}
|
|
||||||
]},
|
|
||||||
{"heading": "Quality Factors and Thread Count", "subsections": [
|
|
||||||
{"subheading": "Thread Count Myths", "content_type": "paragraph", "details": "Why higher isn't always better | Optimal thread count ranges | Marketing misconceptions"},
|
|
||||||
{"subheading": "Weave Types Compared", "content_type": "table", "details": "Percale characteristics | Sateen properties | Jersey and flannel options | Best use cases for each"},
|
|
||||||
{"subheading": "Durability Factors", "content_type": "paragraph", "details": "Fiber length and strength | Ply construction | Expected lifespan with proper care"}
|
|
||||||
]},
|
|
||||||
{"heading": "Top Organic Cotton Bedding Brands", "subsections": [
|
|
||||||
{"subheading": "Premium Brands", "content_type": "paragraph", "details": "Coyuchi overview and price range | Boll & Branch unique features | Parachute product line"},
|
|
||||||
{"subheading": "Mid-Range Options", "content_type": "list", "details": "West Elm Organic collection | Pottery Barn Organic line | Target's organic offerings"},
|
|
||||||
{"subheading": "Budget-Friendly Choices", "content_type": "paragraph", "details": "SOL Organics value proposition | Amazon organic options | Direct-to-consumer brands"}
|
|
||||||
]},
|
|
||||||
{"heading": "Buying Guide and Shopping Tips", "subsections": [
|
|
||||||
{"subheading": "What to Look For", "content_type": "list", "details": "Certification verification | Return policies | Warranty coverage | Customer reviews"},
|
|
||||||
{"subheading": "When to Buy", "content_type": "paragraph", "details": "Best sale seasons | Holiday promotions | End-of-season clearances"},
|
|
||||||
{"subheading": "Starter Set Recommendations", "content_type": "paragraph", "details": "Essential pieces for beginners | Budget allocation | Prioritization strategy"}
|
|
||||||
]},
|
|
||||||
{"heading": "Care and Maintenance Best Practices", "subsections": [
|
|
||||||
{"subheading": "Washing Instructions", "content_type": "paragraph", "details": "Pre-washing requirements | Water temperature guidelines | Eco-friendly detergent recommendations"},
|
|
||||||
{"subheading": "Drying and Storage", "content_type": "list", "details": "Air-dry vs machine dry | Shrinkage prevention | Long-term storage tips"},
|
|
||||||
{"subheading": "Longevity Tips", "content_type": "paragraph", "details": "Rotation schedules | Stain removal methods | When to replace"}
|
|
||||||
]}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"content_type": "post",
|
|
||||||
"content_structure": "guide",
|
|
||||||
"estimated_word_count": 2000
|
|
||||||
}
|
|
||||||
|
|
||||||
# Format the prompt with real data
|
|
||||||
prompt = prompt_template.replace('[IGNY8_IDEA]', json.dumps(idea_data, indent=2))
|
|
||||||
prompt = prompt.replace('[IGNY8_CLUSTER]', 'Organic Bedding')
|
|
||||||
prompt = prompt.replace('[IGNY8_KEYWORDS]', 'organic cotton bedding, eco-friendly sheets, sustainable duvet covers, GOTS certified bedding, hypoallergenic sheets, organic mattress protector, chemical-free bedding, organic cotton pillowcases')
|
|
||||||
|
|
||||||
print(f"🧪 Testing with REAL content generation prompt")
|
|
||||||
print("=" * 80)
|
|
||||||
print(f"Prompt characters: {len(prompt):,}")
|
|
||||||
print(f"Estimated input tokens: ~{len(prompt) // 4:,}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
tests = [
|
|
||||||
("max_tokens=4096", 4096),
|
|
||||||
("max_tokens=8192", 8192),
|
|
||||||
("max_tokens=16384", 16384),
|
|
||||||
]
|
|
||||||
|
|
||||||
for name, max_tokens in tests:
|
|
||||||
print(f"\n📝 {name}")
|
|
||||||
print("-" * 80)
|
|
||||||
|
|
||||||
try:
|
|
||||||
response = requests.post(
|
|
||||||
'https://api.openai.com/v1/chat/completions',
|
|
||||||
headers={'Authorization': f'Bearer {api_key}', 'Content-Type': 'application/json'},
|
|
||||||
json={
|
|
||||||
'model': model,
|
|
||||||
'messages': [{'role': 'user', 'content': prompt}],
|
|
||||||
'max_tokens': max_tokens,
|
|
||||||
'temperature': 0.7,
|
|
||||||
'response_format': {"type": "json_object"} # JSON mode like real requests
|
|
||||||
},
|
|
||||||
timeout=180
|
|
||||||
)
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
data = response.json()
|
|
||||||
usage = data.get('usage', {})
|
|
||||||
finish_reason = data['choices'][0].get('finish_reason')
|
|
||||||
|
|
||||||
prompt_tokens = usage.get('prompt_tokens', 0)
|
|
||||||
completion_tokens = usage.get('completion_tokens', 0)
|
|
||||||
total_tokens = usage.get('total_tokens', 0)
|
|
||||||
estimated_words = int(completion_tokens * 0.75)
|
|
||||||
|
|
||||||
print(f" Input: {prompt_tokens:>6,} tokens")
|
|
||||||
print(f" Output: {completion_tokens:>6,} tokens (~{estimated_words:,} words)")
|
|
||||||
print(f" Total: {total_tokens:>6,} tokens")
|
|
||||||
print(f" Status: {finish_reason}")
|
|
||||||
|
|
||||||
if finish_reason == 'length':
|
|
||||||
print(f" 🚨 TRUNCATED - Content incomplete!")
|
|
||||||
else:
|
|
||||||
print(f" ✅ Complete response")
|
|
||||||
|
|
||||||
else:
|
|
||||||
print(f" ✗ Error: {response.status_code}")
|
|
||||||
print(f" {response.json().get('error', {}).get('message', '')[:100]}")
|
|
||||||
except Exception as e:
|
|
||||||
print(f" ✗ Exception: {str(e)[:100]}")
|
|
||||||
|
|
||||||
print("\n" + "=" * 80)
|
|
||||||
print("🎯 CONCLUSION")
|
|
||||||
print("=" * 80)
|
|
||||||
print("Check which max_tokens setting allows complete 1200+ word articles")
|
|
||||||
print("If 8192 shows 'TRUNCATED', we need to increase it in settings.py")
|
|
||||||
Reference in New Issue
Block a user