Implement Stage 3: Enhance content metadata and validation features
- Added entity metadata fields to the Tasks model, including entity_type, taxonomy, and cluster_role. - Updated CandidateEngine to prioritize content relevance based on cluster mappings. - Introduced metadata completeness scoring in ContentAnalyzer. - Enhanced validation services to check for entity type and mapping completeness. - Updated frontend components to display and validate new metadata fields. - Implemented API endpoints for content validation and metadata persistence. - Migrated existing data to populate new metadata fields for Tasks and Content.
This commit is contained in:
@@ -35,25 +35,77 @@ class ContentAnalyzer:
|
||||
readability_score = self._calculate_readability_score(content)
|
||||
engagement_score = self._calculate_engagement_score(content)
|
||||
|
||||
# Overall score is weighted average
|
||||
# Stage 3: Calculate metadata completeness score
|
||||
metadata_score = self._calculate_metadata_score(content)
|
||||
|
||||
# Overall score is weighted average (includes metadata)
|
||||
overall_score = (
|
||||
seo_score * 0.4 +
|
||||
readability_score * 0.3 +
|
||||
engagement_score * 0.3
|
||||
seo_score * 0.35 +
|
||||
readability_score * 0.25 +
|
||||
engagement_score * 0.25 +
|
||||
metadata_score * 0.15
|
||||
)
|
||||
|
||||
return {
|
||||
'seo_score': round(seo_score, 2),
|
||||
'readability_score': round(readability_score, 2),
|
||||
'engagement_score': round(engagement_score, 2),
|
||||
'metadata_score': round(metadata_score, 2), # Stage 3: Add metadata score
|
||||
'overall_score': round(overall_score, 2),
|
||||
'word_count': content.word_count or 0,
|
||||
'has_meta_title': bool(content.meta_title),
|
||||
'has_meta_description': bool(content.meta_description),
|
||||
'has_primary_keyword': bool(content.primary_keyword),
|
||||
'internal_links_count': len(content.internal_links) if content.internal_links else 0
|
||||
'internal_links_count': len(content.internal_links) if content.internal_links else 0,
|
||||
# Stage 3: Metadata completeness indicators
|
||||
'has_entity_type': bool(content.entity_type),
|
||||
'has_cluster_mapping': self._has_cluster_mapping(content),
|
||||
'has_taxonomy_mapping': self._has_taxonomy_mapping(content),
|
||||
}
|
||||
|
||||
def _calculate_metadata_score(self, content: Content) -> float:
|
||||
"""Stage 3: Calculate metadata completeness score (0-100)"""
|
||||
score = 0
|
||||
|
||||
# Entity type (20 points)
|
||||
if content.entity_type:
|
||||
score += 20
|
||||
|
||||
# Cluster mapping (30 points)
|
||||
if self._has_cluster_mapping(content):
|
||||
score += 30
|
||||
|
||||
# Taxonomy mapping (30 points) - required for products/services
|
||||
if self._has_taxonomy_mapping(content):
|
||||
score += 30
|
||||
elif content.entity_type in ['product', 'service']:
|
||||
# Products/services must have taxonomy
|
||||
score += 0
|
||||
else:
|
||||
# Other types get partial credit
|
||||
score += 15
|
||||
|
||||
# Attributes (20 points) - for products
|
||||
if content.entity_type == 'product':
|
||||
from igny8_core.business.content.models import ContentAttributeMap
|
||||
attr_count = ContentAttributeMap.objects.filter(content=content).count()
|
||||
if attr_count >= 3:
|
||||
score += 20
|
||||
elif attr_count >= 1:
|
||||
score += 10
|
||||
|
||||
return min(score, 100)
|
||||
|
||||
def _has_cluster_mapping(self, content: Content) -> bool:
|
||||
"""Stage 3: Check if content has cluster mapping"""
|
||||
from igny8_core.business.content.models import ContentClusterMap
|
||||
return ContentClusterMap.objects.filter(content=content).exists()
|
||||
|
||||
def _has_taxonomy_mapping(self, content: Content) -> bool:
|
||||
"""Stage 3: Check if content has taxonomy mapping"""
|
||||
from igny8_core.business.content.models import ContentTaxonomyMap
|
||||
return ContentTaxonomyMap.objects.filter(content=content).exists()
|
||||
|
||||
def _calculate_seo_score(self, content: Content) -> float:
|
||||
"""Calculate SEO score (0-100)"""
|
||||
score = 0
|
||||
|
||||
Reference in New Issue
Block a user