use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum TopicModelingApproach {
KeywordClustering,
TfIdf,
LatentSemantic,
CoOccurrence,
Hierarchical,
Dynamic,
}
impl Default for TopicModelingApproach {
fn default() -> Self {
Self::KeywordClustering
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TopicExtractionConfig {
pub approach: TopicModelingApproach,
pub min_topic_size: usize,
pub max_topics: usize,
pub topic_threshold: f64,
pub keyword_sensitivity: f64,
pub min_topic_prominence: f64,
}
impl Default for TopicExtractionConfig {
fn default() -> Self {
Self {
approach: TopicModelingApproach::default(),
min_topic_size: 2,
max_topics: 10,
topic_threshold: 0.6,
keyword_sensitivity: 0.7,
min_topic_prominence: 0.1,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimilarityConfig {
pub enable_character_similarity: bool,
pub enable_semantic_similarity: bool,
pub enable_cooccurrence_similarity: bool,
pub character_similarity_weight: f64,
pub semantic_similarity_weight: f64,
pub cooccurrence_similarity_weight: f64,
}
impl Default for SimilarityConfig {
fn default() -> Self {
Self {
enable_character_similarity: true,
enable_semantic_similarity: true,
enable_cooccurrence_similarity: true,
character_similarity_weight: 0.3,
semantic_similarity_weight: 0.5,
cooccurrence_similarity_weight: 0.2,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnalysisConfig {
pub track_topic_evolution: bool,
pub enable_semantic_profiling: bool,
pub calculate_quality_metrics: bool,
pub analyze_relationships: bool,
pub topic_overlap_threshold: f64,
}
impl Default for AnalysisConfig {
fn default() -> Self {
Self {
track_topic_evolution: true,
enable_semantic_profiling: true,
calculate_quality_metrics: true,
analyze_relationships: true,
topic_overlap_threshold: 0.3,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MetricsConfig {
pub coherence_threshold: f64,
pub enable_detailed_metrics: bool,
pub enable_statistical_testing: bool,
pub confidence_level: f64,
}
impl Default for MetricsConfig {
fn default() -> Self {
Self {
coherence_threshold: 0.5,
enable_detailed_metrics: true,
enable_statistical_testing: true,
confidence_level: 0.95,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AdvancedAnalysisConfig {
pub enable_hierarchical_analysis: bool,
pub enable_dynamic_modeling: bool,
pub enable_network_analysis: bool,
pub max_topic_depth: usize,
pub enable_temporal_analysis: bool,
}
impl Default for AdvancedAnalysisConfig {
fn default() -> Self {
Self {
enable_hierarchical_analysis: true,
enable_dynamic_modeling: true,
enable_network_analysis: true,
max_topic_depth: 4,
enable_temporal_analysis: true,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TopicCoherenceConfig {
pub extraction: TopicExtractionConfig,
pub similarity: SimilarityConfig,
pub analysis: AnalysisConfig,
pub metrics: MetricsConfig,
pub advanced: AdvancedAnalysisConfig,
pub use_comprehensive_analysis: bool,
}
impl Default for TopicCoherenceConfig {
fn default() -> Self {
Self {
extraction: TopicExtractionConfig::default(),
similarity: SimilarityConfig::default(),
analysis: AnalysisConfig::default(),
metrics: MetricsConfig::default(),
advanced: AdvancedAnalysisConfig::default(),
use_comprehensive_analysis: true,
}
}
}
pub struct TopicCoherenceConfigBuilder {
config: TopicCoherenceConfig,
}
impl TopicCoherenceConfigBuilder {
pub fn new() -> Self {
Self {
config: TopicCoherenceConfig::default(),
}
}
pub fn extraction_approach(mut self, approach: TopicModelingApproach) -> Self {
self.config.extraction.approach = approach;
self
}
pub fn max_topics(mut self, max_topics: usize) -> Self {
self.config.extraction.max_topics = max_topics;
self
}
pub fn topic_threshold(mut self, threshold: f64) -> Self {
self.config.extraction.topic_threshold = threshold;
self
}
pub fn enable_advanced_analysis(mut self, enable: bool) -> Self {
self.config.use_comprehensive_analysis = enable;
self
}
pub fn semantic_similarity_weight(mut self, weight: f64) -> Self {
self.config.similarity.semantic_similarity_weight = weight;
self
}
pub fn build(self) -> TopicCoherenceConfig {
self.config
}
}
impl Default for TopicCoherenceConfigBuilder {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = TopicCoherenceConfig::default();
assert_eq!(config.extraction.max_topics, 10);
assert_eq!(
config.extraction.approach,
TopicModelingApproach::KeywordClustering
);
assert!(config.use_comprehensive_analysis);
}
#[test]
fn test_config_builder() {
let config = TopicCoherenceConfigBuilder::new()
.extraction_approach(TopicModelingApproach::TfIdf)
.max_topics(15)
.topic_threshold(0.8)
.enable_advanced_analysis(false)
.build();
assert_eq!(config.extraction.approach, TopicModelingApproach::TfIdf);
assert_eq!(config.extraction.max_topics, 15);
assert_eq!(config.extraction.topic_threshold, 0.8);
assert!(!config.use_comprehensive_analysis);
}
#[test]
fn test_config_serialization() {
let config = TopicCoherenceConfig::default();
let serialized = serde_json::to_string(&config).expect("Should serialize");
let deserialized: TopicCoherenceConfig =
serde_json::from_str(&serialized).expect("Should deserialize");
assert_eq!(
config.extraction.max_topics,
deserialized.extraction.max_topics
);
assert_eq!(config.extraction.approach, deserialized.extraction.approach);
}
}