conceptvector / analysis /scorer.py
Tawhid Bin Omar
cleaned up code comments and docs
892d4dd
"""
Understanding Scorer Module
Calculates final understanding scores from analysis results
"""
from typing import Dict, Optional
class UnderstandingScorer:
def __init__(self):
# Scoring weights - adjusted these a few times based on testing
# coverage is weighted highest because it's most reliable
self.weights = {
'consistency': 0.25,
'coverage': 0.35,
'stability': 0.25,
'assumptions': 0.15
}
def calculate_scores(
self,
consistency_result: Dict,
coverage_result: Dict,
stability_result: Optional[Dict]
) -> Dict:
"""
Calculate multi-dimensional understanding scores
Returns:
{
'overall': float (0-100),
'consistency': float (0-100),
'coverage': float (0-100),
'stability': float (0-100),
'assumptions': float (0-100)
}
"""
# Extract individual scores
consistency_score = consistency_result.get('consistency_score', 0)
coverage_score = coverage_result.get('coverage_score', 0)
stability_score = stability_result.get('stability_score', 100) if stability_result else 100
# Calculate assumption completeness score
# Based on whether key assumptions are made explicit
assumptions_score = self._calculate_assumption_score(
coverage_result=coverage_result,
consistency_result=consistency_result
)
# Calculate weighted overall score
overall_score = (
consistency_score * self.weights['consistency'] +
coverage_score * self.weights['coverage'] +
stability_score * self.weights['stability'] +
assumptions_score * self.weights['assumptions']
)
return {
'overall': round(overall_score, 1),
'consistency': round(consistency_score, 1),
'coverage': round(coverage_score, 1),
'stability': round(stability_score, 1),
'assumptions': round(assumptions_score, 1)
}
def _calculate_assumption_score(
self,
coverage_result: Dict,
consistency_result: Dict
) -> float:
"""
Calculate assumption completeness score
High score = explicit about assumptions, boundary conditions, limitations
Low score = makes implicit assumptions without stating them
"""
# Simple heuristic for now - basically if consistency and coverage are good,
# assumptions are probably okay. Not perfect but works decently.
consistency_score = consistency_result.get('consistency_score', 0)
coverage_score = coverage_result.get('coverage_score', 0)
# Missing concepts indicate unstated assumptions
missing_count = len(coverage_result.get('missing_concepts', []))
# Contradictions indicate conflicting implicit assumptions
contradiction_count = len(consistency_result.get('contradictions', []))
# Base score on coverage and consistency
base_score = (consistency_score + coverage_score) / 2
# Penalize for missing concepts (unstated prerequisites)
missing_penalty = min(30, missing_count * 10)
# Penalize for contradictions (conflicting assumptions)
contradiction_penalty = min(20, contradiction_count * 15)
final_score = base_score - missing_penalty - contradiction_penalty
return max(0, min(100, final_score))