Coverage for src\cmvk\profiles.py: 51%

1"""

2 CMVK Threshold Profiles Module

3

4 Pre-configured threshold profiles for different verification domains.

5 Each profile defines appropriate thresholds and metric defaults for specific use cases.

6

7 Domains:

8 - carbon: Carbon credit and environmental verification

9 - financial: Financial transaction and fraud detection

10 - medical: Medical claims and health data verification

11 - general: Default profile for general use

12"""

13

14 from __future__ import annotations

15

16 from dataclasses import dataclass, field

17 from enum import Enum

18 from typing import Any

19

20

21 class ProfileName(Enum):

22 """Available threshold profile names."""

23

24 GENERAL = "general"

25 CARBON = "carbon"

26 FINANCIAL = "financial"

27 MEDICAL = "medical"

28 STRICT = "strict"

29 LENIENT = "lenient"

30

31

32@dataclass(frozen=True)

33 class ThresholdProfile:

34 """

35 Configuration profile for verification thresholds.

36

37 Attributes:

38 name: Profile identifier

39 description: Human-readable description

40 drift_threshold: Maximum acceptable drift score (0.0-1.0)

41 confidence_threshold: Minimum required confidence (0.0-1.0)

42 default_metric: Recommended distance metric for this domain

43 dimension_weights: Optional default weights for dimensions

44 anomaly_sigma: Standard deviations for anomaly detection

45 flags: Additional domain-specific flags

46 """

47

48 name: str

49 description: str

50 drift_threshold: float

51 confidence_threshold: float

52 default_metric: str = "euclidean"

53 dimension_weights: dict[str, float] | None = None

54 anomaly_sigma: float = 3.0

55 flags: dict[str, Any] = field(default_factory=dict)

56

57 def is_within_threshold(self, drift_score: float, confidence: float) -> bool:

58 """Check if verification result passes this profile's thresholds."""

59 return drift_score <= self.drift_threshold and confidence >= self.confidence_threshold

60

61 def get_severity(self, drift_score: float) -> str:

62 """

63 Classify drift severity based on profile thresholds.

64

65 Returns:

66 "pass": Within threshold

67 "warning": 1-1.5x threshold

68 "critical": 1.5-2x threshold

69 "severe": >2x threshold

70 """

71 ratio = drift_score / self.drift_threshold if self.drift_threshold > 0 else float("inf")

72

73 if ratio <= 1.0:

74 return "pass"

75 elif ratio <= 1.5:

76 return "warning"

77 elif ratio <= 2.0:

78 return "critical"

79 else:

80 return "severe"

81

82

83# ============================================================================

84# Pre-defined Profiles

85# ============================================================================

86

87 GENERAL_PROFILE = ThresholdProfile(

88 name="general",

89 description="Default profile for general-purpose verification",

90 drift_threshold=0.3,

91 confidence_threshold=0.7,

92 default_metric="cosine",

93 anomaly_sigma=3.0,

94 flags={

95 "require_explanation": False,

96 "strict_shape_match": True,

97 },

98)

99

100 CARBON_PROFILE = ThresholdProfile(

101 name="carbon",

102 description="Profile for carbon credit and environmental data verification. "

103 "Uses Euclidean distance to preserve magnitude information critical "

104 "for detecting discrepancies in NDVI, carbon stock, and sequestration values.",

105 drift_threshold=0.15,

106 confidence_threshold=0.85,

107 default_metric="euclidean",

108 dimension_weights={

109 "ndvi": 0.35,

110 "carbon_stock": 0.30,

111 "sequestration_rate": 0.20,

112 "area": 0.15,

113 },

114 anomaly_sigma=2.5,

115 flags={

116 "require_explanation": True,

117 "fraud_detection_mode": True,

118 "magnitude_sensitive": True,

119 "min_sample_size": 10,

120 },

121)

122

123 FINANCIAL_PROFILE = ThresholdProfile(

124 name="financial",

125 description="Profile for financial transaction and fraud detection. "

126 "Very strict thresholds with Chebyshev metric to catch "

127 "single-dimension anomalies (e.g., one suspicious transaction).",

128 drift_threshold=0.10,

129 confidence_threshold=0.90,

130 default_metric="chebyshev",

131 dimension_weights={

132 "amount": 0.40,

133 "frequency": 0.25,

134 "location": 0.20,

135 "timing": 0.15,

136 },

137 anomaly_sigma=2.0,

138 flags={

139 "require_explanation": True,

140 "fraud_detection_mode": True,

141 "audit_required": True,

142 "real_time_alerting": True,

143 },

144)

145

146 MEDICAL_PROFILE = ThresholdProfile(

147 name="medical",

148 description="Profile for medical claims and health data verification. "

149 "Balanced thresholds with Manhattan distance for robustness to outliers.",

150 drift_threshold=0.20,

151 confidence_threshold=0.85,

152 default_metric="manhattan",

153 dimension_weights={

154 "diagnosis": 0.35,

155 "treatment": 0.30,

156 "outcome": 0.25,

157 "cost": 0.10,

158 },

159 anomaly_sigma=2.5,

160 flags={

161 "require_explanation": True,

162 "hipaa_compliant": True,

163 "audit_required": True,

164 "sensitive_data": True,

165 },

166)

167

168 STRICT_PROFILE = ThresholdProfile(

169 name="strict",

170 description="Strict verification profile with minimal tolerance for drift. "

171 "Use for high-stakes verification where any discrepancy is significant.",

172 drift_threshold=0.05,

173 confidence_threshold=0.95,

174 default_metric="euclidean",

175 anomaly_sigma=2.0,

176 flags={

177 "require_explanation": True,

178 "zero_tolerance_mode": True,

179 },

180)

181

182 LENIENT_PROFILE = ThresholdProfile(

183 name="lenient",

184 description="Lenient profile for exploratory analysis or when some drift "

185 "is acceptable. Higher thresholds allow more variation.",

186 drift_threshold=0.5,

187 confidence_threshold=0.5,

188 default_metric="cosine",

189 anomaly_sigma=4.0,

190 flags={

191 "require_explanation": False,

192 "exploratory_mode": True,

193 },

194)

195

196# Registry of all profiles

197 PROFILES: dict[str, ThresholdProfile] = {

198 "general": GENERAL_PROFILE,

199 "carbon": CARBON_PROFILE,

200 "financial": FINANCIAL_PROFILE,

201 "medical": MEDICAL_PROFILE,

202 "strict": STRICT_PROFILE,

203 "lenient": LENIENT_PROFILE,

204}

205

206

207 def get_profile(name: str | ProfileName) -> ThresholdProfile:

208 """

209 Get a threshold profile by name.

210

211 Args:

212 name: Profile name (string or ProfileName enum)

213

214 Returns:

215 ThresholdProfile configuration

216

217 Raises:

218 ValueError: If profile name is not found

219 """

220 if isinstance(name, ProfileName):

221 name = name.value

222

223 name = name.lower()

224 if name not in PROFILES:

225 available = list(PROFILES.keys())

226 raise ValueError(f"Unknown profile '{name}'. Available profiles: {available}")

227

228 return PROFILES[name]

229

230

231 def list_profiles() -> list[str]:

232 """Return list of available profile names."""

233 return list(PROFILES.keys())

234

235

236 def register_profile(profile: ThresholdProfile) -> None:

237 """

238 Register a custom threshold profile.

239

240 Args:

241 profile: ThresholdProfile to register

242

243 Raises:

244 ValueError: If profile name already exists (use update_profile instead)

245 """

246 if profile.name in PROFILES:

247 raise ValueError(

248 f"Profile '{profile.name}' already exists. Use update_profile() to modify."

249 )

250 PROFILES[profile.name] = profile

251

252

253 def update_profile(profile: ThresholdProfile) -> None:

254 """

255 Update an existing profile or add a new one.

256

257 Args:

258 profile: ThresholdProfile to register/update

259 """

260 PROFILES[profile.name] = profile

261

262

263 def create_profile(

264 name: str,

265 drift_threshold: float,

266 confidence_threshold: float,

267 description: str = "",

268 default_metric: str = "euclidean",

269 dimension_weights: dict[str, float] | None = None,

270 anomaly_sigma: float = 3.0,

271 flags: dict[str, Any] | None = None,

272) -> ThresholdProfile:

273 """

274 Create a new threshold profile.

275

276 Args:

277 name: Unique profile identifier

278 drift_threshold: Maximum acceptable drift score

279 confidence_threshold: Minimum required confidence

280 description: Human-readable description

281 default_metric: Recommended distance metric

282 dimension_weights: Optional default weights

283 anomaly_sigma: Standard deviations for anomaly detection

284 flags: Additional domain-specific flags

285

286 Returns:

287 New ThresholdProfile instance

288 """

289 return ThresholdProfile(

290 name=name,

291 description=description,

292 drift_threshold=drift_threshold,

293 confidence_threshold=confidence_threshold,

294 default_metric=default_metric,

295 dimension_weights=dimension_weights,

296 anomaly_sigma=anomaly_sigma,

297 flags=flags or {},

298 )