Spaces:
Sleeping
Sleeping
File size: 7,035 Bytes
634567d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
"""
Base Summarizer Class
Defines the interface for all summarization models
Implements Strategy Design Pattern for interchangeable algorithms
"""
from abc import ABC, abstractmethod
from typing import Dict, Any, Optional, List
import time
import logging
# Setup logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class BaseSummarizer(ABC):
"""
Abstract base class for all summarization models.
Implements common functionality and defines interface.
Design Pattern: Strategy Pattern
- Allows switching between different summarization algorithms
- Ensures consistent interface across models
"""
def __init__(self, model_name: str, model_type: str):
"""
Initialize base summarizer
Args:
model_name: Name of the model (e.g., "TextRank", "BART")
model_type: Type of summarization ("Extractive" or "Abstractive")
"""
self.model_name = model_name
self.model_type = model_type
self.is_initialized = False
self.stats = {
'total_summarizations': 0,
'total_processing_time': 0.0,
'average_processing_time': 0.0
}
logger.info(f"Initializing {model_name} ({model_type}) summarizer")
@abstractmethod
def summarize(self, text: str, **kwargs) -> str:
"""
Generate summary from input text.
Must be implemented by all subclasses.
Args:
text: Input text to summarize
**kwargs: Additional parameters specific to each model
Returns:
Generated summary string
"""
pass
def summarize_with_metrics(self, text: str, **kwargs) -> Dict[str, Any]:
"""
Summarize text and return detailed metrics
Args:
text: Input text to summarize
**kwargs: Model-specific parameters
Returns:
Dictionary containing summary and metadata
"""
start_time = time.time()
# Generate summary
summary = self.summarize(text, **kwargs)
# Calculate metrics
processing_time = time.time() - start_time
self._update_stats(processing_time)
return {
'summary': summary,
'metadata': {
'model_name': self.model_name,
'model_type': self.model_type,
'processing_time': processing_time,
'input_length': len(text.split()),
'summary_length': len(summary.split()),
'compression_ratio': len(summary.split()) / len(text.split()) if len(text.split()) > 0 else 0,
'timestamp': time.strftime('%Y-%m-%d %H:%M:%S')
}
}
def batch_summarize(self, texts: List[str], **kwargs) -> List[Dict[str, Any]]:
"""
Summarize multiple texts
Args:
texts: List of texts to summarize
**kwargs: Model-specific parameters
Returns:
List of dictionaries with summaries and metadata
"""
logger.info(f"Batch summarizing {len(texts)} texts with {self.model_name}")
results = []
for idx, text in enumerate(texts):
logger.info(f"Processing text {idx + 1}/{len(texts)}")
result = self.summarize_with_metrics(text, **kwargs)
result['metadata']['batch_index'] = idx
results.append(result)
return results
def _update_stats(self, processing_time: float):
"""Update internal statistics"""
self.stats['total_summarizations'] += 1
self.stats['total_processing_time'] += processing_time
self.stats['average_processing_time'] = (
self.stats['total_processing_time'] / self.stats['total_summarizations']
)
def get_model_info(self) -> Dict[str, Any]:
"""
Get detailed model information
Returns:
Dictionary with model specifications
"""
return {
'name': self.model_name,
'type': self.model_type,
'statistics': self.stats.copy(),
'is_initialized': self.is_initialized
}
def reset_stats(self):
"""Reset usage statistics"""
self.stats = {
'total_summarizations': 0,
'total_processing_time': 0.0,
'average_processing_time': 0.0
}
logger.info(f"Statistics reset for {self.model_name}")
def validate_input(self, text: str, min_length: int = 10) -> bool:
"""
Validate input text
Args:
text: Input text
min_length: Minimum number of words required
Returns:
Boolean indicating if input is valid
Raises:
ValueError: If input is invalid
"""
if not text or not isinstance(text, str):
raise ValueError("Input text must be a non-empty string")
word_count = len(text.split())
if word_count < min_length:
raise ValueError(
f"Input text too short. Minimum {min_length} words required, got {word_count}"
)
return True
def __repr__(self) -> str:
"""String representation of the summarizer"""
return (f"{self.__class__.__name__}(model_name='{self.model_name}', "
f"model_type='{self.model_type}', "
f"total_summarizations={self.stats['total_summarizations']})")
class SummarizerFactory:
"""
Factory Pattern for creating summarizer instances
Centralizes model instantiation logic
"""
_models = {}
@classmethod
def register_model(cls, model_class, name: str):
"""Register a new summarizer model"""
cls._models[name.lower()] = model_class
logger.info(f"Registered model: {name}")
@classmethod
def create_summarizer(cls, model_name: str, **kwargs):
"""
Create a summarizer instance
Args:
model_name: Name of the model to create
**kwargs: Model-specific initialization parameters
Returns:
Instance of requested summarizer
Raises:
ValueError: If model not found
"""
model_name_lower = model_name.lower()
if model_name_lower not in cls._models:
available = ', '.join(cls._models.keys())
raise ValueError(
f"Model '{model_name}' not found. Available models: {available}"
)
model_class = cls._models[model_name_lower]
return model_class(**kwargs)
@classmethod
def list_available_models(cls) -> List[str]:
"""Get list of available models"""
return list(cls._models.keys()) |