use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConfidenceConfig {
pub base: f32,
pub multi_source_bonus: f32,
pub no_contradiction_bonus: f32,
pub accept_threshold: f32,
pub pending_threshold: f32,
}
impl Default for ConfidenceConfig {
fn default() -> Self {
Self {
base: 0.5,
multi_source_bonus: 0.2,
no_contradiction_bonus: 0.1,
accept_threshold: 0.7,
pending_threshold: 0.4,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct NliConfig {
pub contradiction_threshold: f32,
pub entailment_threshold: f32,
}
impl Default for NliConfig {
fn default() -> Self {
Self {
contradiction_threshold: 0.5,
entailment_threshold: 0.6,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MergeConfig {
pub cosine_threshold: f32,
}
impl Default for MergeConfig {
fn default() -> Self {
Self {
cosine_threshold: 0.85,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HeatConfig {
pub decay_rate: f32,
pub min_threshold: f32,
}
impl Default for HeatConfig {
fn default() -> Self {
Self {
decay_rate: 0.03,
min_threshold: 0.2,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RetrievalConfig {
pub top_k_initial: usize,
pub top_k_final: usize,
pub min_confidence: f32,
pub min_topic_chars: usize,
}
impl Default for RetrievalConfig {
fn default() -> Self {
Self {
top_k_initial: 50,
top_k_final: 5,
min_confidence: 0.7,
min_topic_chars: 3,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExtractionConfig {
pub dedup_cosine_threshold: f32,
}
impl Default for ExtractionConfig {
fn default() -> Self {
Self {
dedup_cosine_threshold: 0.95,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn confidence_defaults_match_spec() {
let c = ConfidenceConfig::default();
assert_eq!(c.base, 0.5);
assert_eq!(c.multi_source_bonus, 0.2);
assert_eq!(c.no_contradiction_bonus, 0.1);
assert_eq!(c.accept_threshold, 0.7);
assert_eq!(c.pending_threshold, 0.4);
}
#[test]
fn nli_defaults_match_spec() {
let n = NliConfig::default();
assert_eq!(n.contradiction_threshold, 0.5);
assert_eq!(n.entailment_threshold, 0.6);
}
#[test]
fn merge_defaults_match_spec() {
assert_eq!(MergeConfig::default().cosine_threshold, 0.85);
}
#[test]
fn heat_defaults_match_spec() {
let h = HeatConfig::default();
assert_eq!(h.decay_rate, 0.03);
assert_eq!(h.min_threshold, 0.2);
}
#[test]
fn retrieval_defaults_match_spec() {
let r = RetrievalConfig::default();
assert_eq!(r.top_k_initial, 50);
assert_eq!(r.top_k_final, 5);
assert_eq!(r.min_confidence, 0.7);
assert_eq!(r.min_topic_chars, 3);
}
#[test]
fn extraction_defaults_match_spec() {
let e = ExtractionConfig::default();
assert_eq!(e.dedup_cosine_threshold, 0.95);
}
#[test]
fn configs_roundtrip_serde() {
let configs: Vec<String> = vec![
serde_json::to_string(&ConfidenceConfig::default()).unwrap(),
serde_json::to_string(&NliConfig::default()).unwrap(),
serde_json::to_string(&MergeConfig::default()).unwrap(),
serde_json::to_string(&HeatConfig::default()).unwrap(),
serde_json::to_string(&RetrievalConfig::default()).unwrap(),
serde_json::to_string(&ExtractionConfig::default()).unwrap(),
];
for c in configs {
assert!(c.len() > 2);
}
}
}