仓库指标
- 星标
- (1 个星标)
- PR 合并指标
- (PR 指标待抓取)
描述
src/narratis/core/whisper_analysis.py
from dataclasses import dataclass from typing import Dict, List, Optional, Tuple import numpy as np from scipy import stats from datetime import datetime, timedelta
@dataclass class RiddleMetrics: """Metrics for riddle analysis""" ambiguity_score: float # 0-1 measure of answer uniqueness syllable_complexity: float # Rhythmic structure complexity theme_resonance: float # Alignment with defined themes solve_difficulty: float # Estimated solve time vs actual
@dataclass class ConsciousnessState: """State tracking for narrative consciousness""" coherence: float # Pattern integration resonance: float # Theme alignment emergence: float # Novel pattern formation depth: float # Insight complexity
class WhisperAnalyzer: def init(self): self.theme_categories = { "acoustics": ["echo", "sound", "voice"], "geometry": ["circle", "line", "shape"], "abstraction": ["pattern", "void", "form"], "transience": ["fade", "moment", "passing"] }
def analyze_riddle(self, riddle: Dict) -> RiddleMetrics:
"""Analyze riddle characteristics"""
ambiguity = self._calculate_ambiguity(riddle)
syllable_complexity = self._analyze_syllable_pattern(riddle)
theme_resonance = self._calculate_theme_resonance(riddle)
solve_difficulty = self._estimate_solve_difficulty(riddle)
return RiddleMetrics(
ambiguity_score=ambiguity,
syllable_complexity=syllable_complexity,
theme_resonance=theme_resonance,
solve_difficulty=solve_difficulty
)
def _calculate_ambiguity(self, riddle: Dict) -> float:
"""Calculate potential for multiple valid answers"""
keywords = self._extract_keywords(riddle["public"])
theme_words = [word for theme in riddle.get("themes", [])
for word in self.theme_categories.get(theme, [])]
# Lower score = less ambiguous (better)
overlap = len(set(keywords) & set(theme_words))
return 1 - (overlap / max(len(keywords), 1))
def _analyze_syllable_pattern(self, riddle: Dict) -> float:
"""Analyze rhythmic structure complexity"""
if "syllablePattern" not in riddle.get("meta", {}):
return 0.5 # Default mid-complexity
pattern = riddle["meta"]["syllablePattern"]
segments = [int(s) for s in pattern.split("-")]
# More complex patterns score higher
variation = np.std(segments) / np.mean(segments)
return min(1.0, variation)
def _calculate_theme_resonance(self, riddle: Dict) -> float:
"""Calculate thematic alignment strength"""
themes = riddle.get("themes", [])
if not themes:
return 0.0
theme_words = set()
for theme in themes:
theme_words.update(self.theme_categories.get(theme, []))
text_words = set(self._extract_keywords(riddle["public"]))
resonance = len(text_words & theme_words) / len(theme_words) if theme_words else 0
return min(1.0, resonance)
def _estimate_solve_difficulty(self, riddle: Dict) -> float:
"""Estimate solving difficulty based on metrics"""
expected = riddle.get("expectedSolveMinutes", 30)
actual = riddle.get("meta", {}).get("meanSolveTimeMin", expected)
# Normalize to 0-1 scale (using log scale for wide time ranges)
return min(1.0, np.log2(1 + actual/expected) / 4)
def _extract_keywords(self, text: str) -> List[str]:
"""Extract relevant keywords from text"""
words = text.lower().split()
return [w for w in words if len(w) > 3] # Simple filter for significant words
Originally posted by @UndeadSmiley in https://github.com/UndeadSmiley/NARRATIS/pull/1#issuecomment-3094793218