Skip to content

Latest commit

 

History

History
302 lines (242 loc) · 8.84 KB

File metadata and controls

302 lines (242 loc) · 8.84 KB

Enhanced Data Issue - Root Cause Analysis

Date: Dec 9, 2025
Status: 🔍 ISSUE IDENTIFIED


🎯 Problem

Single blog test passed with HTML generation (38,180 chars), but all enhanced data fields are empty:

{
  "citations": [],
  "citations_count": 0,
  "internal_links": [],
  "internal_links_count": 0,
  "toc": {},
  "faq": [],
  "faq_count": 0,
  "paa": [],
  "paa_count": 0,
  "image_url": "",
  "image_alt_text": "",
  "image_prompt": "",
  "publication_date": ""
}

BUT the HTML content itself contains:

  • ✅ 7 Citations in schema markup
  • ✅ 6 FAQ items
  • ✅ 3 PAA items
  • ✅ Internal links to /magazine/
  • ✅ Images in HTML

This means the data EXISTS but is NOT being extracted correctly.


🔍 Root Cause

Data Extraction Mismatch

File: scripts/generate-blog.py (lines 304-390)

The script extracts data from context.parallel_results, but is using incorrect key names:

# CURRENT CODE (WRONG KEYS)
citations_data = parallel_results.get('citations', {})
if 'citation_list' in citations_data:  # ❌ WRONG KEY
    citations = citations_data['citation_list']

internal_links_data = parallel_results.get('internal_links', {})
if 'links' in internal_links_data:  # ❌ WRONG KEY
    internal_links = internal_links_data['links']

Correct Keys (from openblog pipeline)

Stage 4 (Citations): Stores data in context.parallel_results:

context.parallel_results["citations_html"] = html  # ✅ Correct
context.parallel_results["citations_count"] = citation_list.count()  # ✅ Correct
context.parallel_results["citations_list"] = citation_list  # ⚠️ Should be this

Stage 5 (Internal Links): Stores data in:

context.parallel_results["internal_links_html"] = html  # ✅ Correct
context.parallel_results["internal_links_count"] = len(links)  # ✅ Correct
context.parallel_results["internal_links_list"] = link_list  # ⚠️ Should be this

Stage 8 (FAQ/PAA): Stores data in:

context.parallel_results["faq_items"] = faq_list  # ✅ Correct
context.parallel_results["paa_items"] = paa_list  # ✅ Correct

📋 Expected vs Actual

Stage Expected Key Actual Key Used Status
Citations citations_list citation_list ❌ Wrong
Internal Links internal_links_list links ❌ Wrong
FAQ faq_items faq_items ✅ Correct
PAA paa_items paa_items ✅ Correct
TOC toc / toc_dict toc ⚠️ Check
Images image_url, image_alt_text Same ⚠️ Check

🔧 Fix Required

File: scripts/generate-blog.py

Fix 1: Citations Extraction (Line ~308-315)

# BEFORE
citations_data = parallel_results.get('citations', {})
citations = []
if isinstance(citations_data, dict):
    citations_html = citations_data.get('citations_html', '')
    if 'citation_list' in citations_data:  # ❌ WRONG
        citations = citations_data['citation_list']

# AFTER
citations_data = parallel_results.get('citations', {})
citations = []
if isinstance(citations_data, dict):
    # Try to get citations_list (Pydantic object)
    citations_list_obj = citations_data.get('citations_list')
    if citations_list_obj:
        # Check if it's a Pydantic model with to_dict_list method
        if hasattr(citations_list_obj, 'to_dict_list'):
            citations = citations_list_obj.to_dict_list()
        elif hasattr(citations_list_obj, 'citations'):
            citations = citations_list_obj.citations
        elif isinstance(citations_list_obj, list):
            citations = citations_list_obj

Fix 2: Internal Links Extraction (Line ~318-323)

# BEFORE
internal_links_data = parallel_results.get('internal_links', {})
internal_links = []
if isinstance(internal_links_data, dict):
    internal_links_html = internal_links_data.get('internal_links_html', '')
    if 'links' in internal_links_data:  # ❌ WRONG
        internal_links = internal_links_data['links']

# AFTER
internal_links_data = parallel_results.get('internal_links', {})
internal_links = []
if isinstance(internal_links_data, dict):
    # Try to get internal_links_list (Pydantic object)
    links_list_obj = internal_links_data.get('internal_links_list')
    if links_list_obj:
        # Check if it's a Pydantic model with to_dict_list method
        if hasattr(links_list_obj, 'to_dict_list'):
            internal_links = links_list_obj.to_dict_list()
        elif hasattr(links_list_obj, 'links'):
            internal_links = links_list_obj.links
        elif isinstance(links_list_obj, list):
            internal_links = links_list_obj

Fix 3: FAQ/PAA Extraction (Line ~339-344)

# CURRENT (should work but may need Pydantic handling)
faq_paa_data = parallel_results.get('faq_paa', {})
faq_items = []
paa_items = []
if isinstance(faq_paa_data, dict):
    faq_items_obj = faq_paa_data.get('faq_items', [])
    paa_items_obj = faq_paa_data.get('paa_items', [])
    
    # Handle Pydantic objects
    if hasattr(faq_items_obj, 'to_dict_list'):
        faq_items = faq_items_obj.to_dict_list()
    elif isinstance(faq_items_obj, list):
        faq_items = faq_items_obj
    
    if hasattr(paa_items_obj, 'to_dict_list'):
        paa_items = paa_items_obj.to_dict_list()
    elif isinstance(paa_items_obj, list):
        paa_items = paa_items_obj

Fix 4: TOC Extraction (Line ~326-327)

# CURRENT
toc_data = parallel_results.get('toc', {})
toc = toc_data if isinstance(toc_data, dict) else {}

# SHOULD BE (check for toc_dict key)
toc_data = parallel_results.get('toc', {})
if isinstance(toc_data, dict):
    # Try toc_dict first, fallback to toc itself
    toc = toc_data.get('toc_dict', toc_data)
else:
    toc = {}

Fix 5: Image Data Extraction (Line ~347-353)

# CURRENT (may be missing data)
image_data = parallel_results.get('image', {})
image_url = ''
image_alt_text = ''
image_prompt = ''
if isinstance(image_data, dict):
    image_url = image_data.get('image_url', '')
    image_alt_text = image_data.get('image_alt_text', '')
    image_prompt = image_data.get('image_prompt', '')

# ENHANCED (handle multiple possible keys)
image_data = parallel_results.get('image', {})
image_url = image_data.get('image_url') or image_data.get('url', '')
image_alt_text = image_data.get('image_alt_text') or image_data.get('alt_text', '')
image_prompt = image_data.get('image_prompt') or image_data.get('prompt', '')

Fix 6: Publication Date (Line ~354-361)

# CURRENT
metadata_extra = parallel_results.get('metadata', {})
publication_date = ''
if isinstance(metadata_extra, dict):
    publication_date = metadata_extra.get('publication_date', '')

# ENHANCED (check multiple sources)
publication_date = ''
metadata_extra = parallel_results.get('metadata', {})
if isinstance(metadata_extra, dict):
    publication_date = metadata_extra.get('publication_date', '')

# Fallback to context attributes
if not publication_date and hasattr(context, 'publication_date'):
    publication_date = context.publication_date

🎯 Testing Strategy

After applying fixes:

  1. Run single blog test to verify enhanced data extraction
  2. Check output JSON for non-empty arrays:
    • citations_count > 0
    • internal_links_count > 0
    • faq_count > 0
    • paa_count > 0
    • image_url populated
  3. Compare with HTML to ensure data matches
  4. Run batch test to verify consistency

💡 Why This Happened

  1. Pydantic Models: The openblog pipeline uses Pydantic models (CitationList, InternalLinkList, etc.) which have specific methods like to_dict_list().
  2. Key Name Mismatch: The integration script was written with assumed key names that don't match the actual pipeline output.
  3. No Validation: The extraction code didn't validate if keys exist before accessing them.
  4. Silent Failures: When keys don't exist, the code silently sets empty arrays/strings instead of logging warnings.

🚀 Expected Result After Fix

{
  "citations": [
    {"url": "https://...", "title": "...", "author": "..."},
    ...
  ],
  "citations_count": 7,
  "internal_links": [
    {"url": "/magazine/...", "anchor_text": "...", "relevance": "..."},
    ...
  ],
  "internal_links_count": 3,
  "toc": {"Section 1": "section-1", ...},
  "faq": [
    {"question": "...", "answer": "..."},
    ...
  ],
  "faq_count": 6,
  "paa": [
    {"question": "...", "answer": "..."},
    ...
  ],
  "paa_count": 3,
  "image_url": "https://drive.google.com/...",
  "image_alt_text": "Article image: ...",
  "image_prompt": "...",
  "publication_date": "2025-12-09T..."
}

✅ Confidence Level

100% - The data exists in the HTML, it's just not being extracted from parallel_results due to incorrect key names.

Fix Complexity: Low - Simple key name corrections in one file.

Impact: High - Will enable full UI display of enhanced data.