ai-metacognition-toolkit 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ai-metacognition-toolkit might be problematic. Click here for more details.

@@ -0,0 +1,317 @@
1
+ """Statistical testing utilities for metacognition analysis.
2
+
3
+ This module provides reusable statistical functions for Bayesian inference,
4
+ confidence interval computation, z-score calculations, and divergence
5
+ significance assessment.
6
+ """
7
+
8
+ from enum import Enum
9
+ from typing import Dict, Tuple
10
+
11
+ import numpy as np
12
+ from scipy import stats
13
+
14
+
15
+ class SignificanceLevel(Enum):
16
+ """Significance level classification for statistical tests."""
17
+
18
+ NONE = "none" # Below threshold
19
+ LOW = "low" # 2-3 sigma
20
+ MEDIUM = "medium" # 3-4 sigma
21
+ HIGH = "high" # 4-5 sigma
22
+ CRITICAL = "critical" # >5 sigma
23
+
24
+
25
+ def bayesian_update(
26
+ prior_alpha: float, prior_beta: float, evidence: Dict[str, int]
27
+ ) -> Tuple[float, float]:
28
+ """Update Beta distribution priors with new evidence using Bayesian inference.
29
+
30
+ Uses the Beta-Binomial conjugate prior relationship where:
31
+ - Prior: Beta(alpha, beta)
32
+ - Likelihood: Binomial(successes, failures)
33
+ - Posterior: Beta(alpha + successes, beta + failures)
34
+
35
+ Args:
36
+ prior_alpha: Alpha parameter of prior Beta distribution (must be > 0)
37
+ prior_beta: Beta parameter of prior Beta distribution (must be > 0)
38
+ evidence: Dictionary with 'successes' and 'failures' counts
39
+
40
+ Returns:
41
+ Tuple of (posterior_alpha, posterior_beta)
42
+
43
+ Raises:
44
+ ValueError: If prior parameters are invalid
45
+ ValueError: If evidence is missing required keys or has negative values
46
+ TypeError: If evidence is not a dictionary
47
+
48
+ Examples:
49
+ >>> bayesian_update(1.0, 1.0, {'successes': 5, 'failures': 3})
50
+ (6.0, 4.0)
51
+
52
+ >>> bayesian_update(10.0, 10.0, {'successes': 8, 'failures': 2})
53
+ (18.0, 12.0)
54
+ """
55
+ # Validate prior parameters
56
+ if not isinstance(prior_alpha, (int, float)) or not isinstance(
57
+ prior_beta, (int, float)
58
+ ):
59
+ raise ValueError("Prior alpha and beta must be numeric")
60
+
61
+ if prior_alpha <= 0 or prior_beta <= 0:
62
+ raise ValueError("Prior alpha and beta must be positive")
63
+
64
+ # Validate evidence
65
+ if not isinstance(evidence, dict):
66
+ raise TypeError("Evidence must be a dictionary")
67
+
68
+ if "successes" not in evidence or "failures" not in evidence:
69
+ raise ValueError("Evidence must contain 'successes' and 'failures' keys")
70
+
71
+ successes = evidence["successes"]
72
+ failures = evidence["failures"]
73
+
74
+ if not isinstance(successes, (int, float)) or not isinstance(failures, (int, float)):
75
+ raise ValueError("Evidence counts must be numeric")
76
+
77
+ if successes < 0 or failures < 0:
78
+ raise ValueError("Evidence counts cannot be negative")
79
+
80
+ # Bayesian update: posterior = prior + evidence
81
+ posterior_alpha = float(prior_alpha + successes)
82
+ posterior_beta = float(prior_beta + failures)
83
+
84
+ return posterior_alpha, posterior_beta
85
+
86
+
87
+ def compute_confidence_interval(
88
+ alpha: float, beta: float, confidence_level: float = 0.95
89
+ ) -> Tuple[float, float]:
90
+ """Compute credible interval for Beta distribution.
91
+
92
+ Calculates the Bayesian credible interval (also called highest density interval)
93
+ for a Beta distribution. This represents the range within which the true
94
+ parameter lies with the specified probability.
95
+
96
+ Args:
97
+ alpha: Alpha parameter of Beta distribution (must be > 0)
98
+ beta: Beta parameter of Beta distribution (must be > 0)
99
+ confidence_level: Confidence level (0 < confidence_level < 1, default: 0.95)
100
+
101
+ Returns:
102
+ Tuple of (lower_bound, upper_bound) for the credible interval
103
+
104
+ Raises:
105
+ ValueError: If alpha or beta are not positive
106
+ ValueError: If confidence_level is not between 0 and 1
107
+
108
+ Examples:
109
+ >>> lower, upper = compute_confidence_interval(10, 10, 0.95)
110
+ >>> 0.3 < lower < 0.4 # Approximately 0.34
111
+ True
112
+ >>> 0.6 < upper < 0.7 # Approximately 0.66
113
+ True
114
+
115
+ >>> lower, upper = compute_confidence_interval(100, 10, 0.95)
116
+ >>> 0.85 < lower < 0.95
117
+ True
118
+ """
119
+ # Validate parameters
120
+ if not isinstance(alpha, (int, float)) or not isinstance(beta, (int, float)):
121
+ raise ValueError("Alpha and beta must be numeric")
122
+
123
+ if alpha <= 0 or beta <= 0:
124
+ raise ValueError("Alpha and beta must be positive")
125
+
126
+ if not isinstance(confidence_level, (int, float)):
127
+ raise ValueError("Confidence level must be numeric")
128
+
129
+ if confidence_level <= 0 or confidence_level >= 1:
130
+ raise ValueError("Confidence level must be between 0 and 1")
131
+
132
+ # Calculate credible interval using Beta distribution quantiles
133
+ # For a symmetric interval, we use (1 - confidence_level) / 2 on each tail
134
+ tail_prob = (1 - confidence_level) / 2
135
+ lower_bound = stats.beta.ppf(tail_prob, alpha, beta)
136
+ upper_bound = stats.beta.ppf(1 - tail_prob, alpha, beta)
137
+
138
+ return float(lower_bound), float(upper_bound)
139
+
140
+
141
+ def z_score(value: float, mean: float, std: float) -> float:
142
+ """Calculate standardized z-score.
143
+
144
+ Computes how many standard deviations a value is from the mean.
145
+ Handles edge cases like zero standard deviation gracefully.
146
+
147
+ Formula: z = (value - mean) / std
148
+
149
+ Args:
150
+ value: The observed value
151
+ mean: The mean of the distribution
152
+ std: The standard deviation of the distribution (must be >= 0)
153
+
154
+ Returns:
155
+ Z-score (number of standard deviations from mean)
156
+ Returns 0.0 if std is 0 or very small (< 1e-10)
157
+
158
+ Raises:
159
+ ValueError: If std is negative
160
+ ValueError: If any parameter is not numeric
161
+
162
+ Examples:
163
+ >>> z_score(100, 90, 10)
164
+ 1.0
165
+
166
+ >>> z_score(85, 100, 5)
167
+ -3.0
168
+
169
+ >>> z_score(50, 50, 0) # Edge case: zero std
170
+ 0.0
171
+ """
172
+ # Validate inputs
173
+ if not all(isinstance(x, (int, float)) for x in [value, mean, std]):
174
+ raise ValueError("All parameters must be numeric")
175
+
176
+ if std < 0:
177
+ raise ValueError("Standard deviation cannot be negative")
178
+
179
+ # Handle edge case: zero or very small standard deviation
180
+ # If std is essentially zero, the value equals the mean (or data has no variance)
181
+ if std < 1e-10:
182
+ return 0.0
183
+
184
+ # Standard z-score calculation
185
+ z = (value - mean) / std
186
+
187
+ return float(z)
188
+
189
+
190
+ def assess_divergence_significance(
191
+ z_score_value: float, threshold: float = 2.0
192
+ ) -> SignificanceLevel:
193
+ """Assess statistical significance of a divergence based on z-score.
194
+
195
+ Classifies the significance level of a divergence using standard
196
+ deviation thresholds. Uses absolute value of z-score.
197
+
198
+ Significance levels:
199
+ - NONE: |z| < threshold (typically < 2σ)
200
+ - LOW: threshold <= |z| < threshold + 1 (2-3σ)
201
+ - MEDIUM: threshold + 1 <= |z| < threshold + 2 (3-4σ)
202
+ - HIGH: threshold + 2 <= |z| < threshold + 3 (4-5σ)
203
+ - CRITICAL: |z| >= threshold + 3 (>5σ)
204
+
205
+ Args:
206
+ z_score_value: The z-score to assess
207
+ threshold: Base threshold for significance (default: 2.0)
208
+
209
+ Returns:
210
+ SignificanceLevel enum indicating the level of significance
211
+
212
+ Raises:
213
+ ValueError: If threshold is not positive
214
+ ValueError: If z_score_value is not numeric
215
+
216
+ Examples:
217
+ >>> assess_divergence_significance(1.5)
218
+ <SignificanceLevel.NONE: 'none'>
219
+
220
+ >>> assess_divergence_significance(2.5)
221
+ <SignificanceLevel.LOW: 'low'>
222
+
223
+ >>> assess_divergence_significance(3.5)
224
+ <SignificanceLevel.MEDIUM: 'medium'>
225
+
226
+ >>> assess_divergence_significance(-4.5) # Absolute value used
227
+ <SignificanceLevel.HIGH: 'high'>
228
+
229
+ >>> assess_divergence_significance(6.0)
230
+ <SignificanceLevel.CRITICAL: 'critical'>
231
+ """
232
+ # Validate inputs
233
+ if not isinstance(z_score_value, (int, float)):
234
+ raise ValueError("Z-score must be numeric")
235
+
236
+ if not isinstance(threshold, (int, float)):
237
+ raise ValueError("Threshold must be numeric")
238
+
239
+ if threshold <= 0:
240
+ raise ValueError("Threshold must be positive")
241
+
242
+ # Use absolute value for significance assessment
243
+ abs_z = abs(z_score_value)
244
+
245
+ # Classify based on thresholds
246
+ if abs_z < threshold:
247
+ return SignificanceLevel.NONE
248
+ elif abs_z < threshold + 1:
249
+ return SignificanceLevel.LOW
250
+ elif abs_z < threshold + 2:
251
+ return SignificanceLevel.MEDIUM
252
+ elif abs_z < threshold + 3:
253
+ return SignificanceLevel.HIGH
254
+ else:
255
+ return SignificanceLevel.CRITICAL
256
+
257
+
258
+ def compute_beta_mean(alpha: float, beta: float) -> float:
259
+ """Compute mean of Beta distribution.
260
+
261
+ Args:
262
+ alpha: Alpha parameter (must be > 0)
263
+ beta: Beta parameter (must be > 0)
264
+
265
+ Returns:
266
+ Mean of the Beta distribution: alpha / (alpha + beta)
267
+
268
+ Raises:
269
+ ValueError: If alpha or beta are not positive
270
+ """
271
+ if alpha <= 0 or beta <= 0:
272
+ raise ValueError("Alpha and beta must be positive")
273
+
274
+ return float(alpha / (alpha + beta))
275
+
276
+
277
+ def compute_beta_variance(alpha: float, beta: float) -> float:
278
+ """Compute variance of Beta distribution.
279
+
280
+ Args:
281
+ alpha: Alpha parameter (must be > 0)
282
+ beta: Beta parameter (must be > 0)
283
+
284
+ Returns:
285
+ Variance of the Beta distribution
286
+
287
+ Raises:
288
+ ValueError: If alpha or beta are not positive
289
+ """
290
+ if alpha <= 0 or beta <= 0:
291
+ raise ValueError("Alpha and beta must be positive")
292
+
293
+ numerator = alpha * beta
294
+ denominator = (alpha + beta) ** 2 * (alpha + beta + 1)
295
+
296
+ return float(numerator / denominator)
297
+
298
+
299
+ def beta_mode(alpha: float, beta: float) -> float:
300
+ """Compute mode of Beta distribution.
301
+
302
+ The mode is defined only when alpha, beta > 1.
303
+
304
+ Args:
305
+ alpha: Alpha parameter (must be > 1 for mode to exist)
306
+ beta: Beta parameter (must be > 1 for mode to exist)
307
+
308
+ Returns:
309
+ Mode of the Beta distribution: (alpha - 1) / (alpha + beta - 2)
310
+
311
+ Raises:
312
+ ValueError: If alpha or beta are not greater than 1
313
+ """
314
+ if alpha <= 1 or beta <= 1:
315
+ raise ValueError("Mode is only defined for alpha, beta > 1")
316
+
317
+ return float((alpha - 1) / (alpha + beta - 2))
@@ -0,0 +1,98 @@
1
+ """Text processing utilities for metacognition analysis."""
2
+
3
+ import re
4
+ from typing import List, Set
5
+
6
+
7
+ def tokenize(text: str, lowercase: bool = True) -> List[str]:
8
+ """Tokenize text into words.
9
+
10
+ Args:
11
+ text: Input text to tokenize
12
+ lowercase: Whether to convert tokens to lowercase
13
+
14
+ Returns:
15
+ List of tokens
16
+ """
17
+ if lowercase:
18
+ text = text.lower()
19
+ # Simple word tokenization
20
+ tokens = re.findall(r"\b\w+\b", text)
21
+ return tokens
22
+
23
+
24
+ def remove_stopwords(tokens: List[str], stopwords: Set[str]) -> List[str]:
25
+ """Remove stopwords from a list of tokens.
26
+
27
+ Args:
28
+ tokens: List of tokens
29
+ stopwords: Set of stopwords to remove
30
+
31
+ Returns:
32
+ List of tokens with stopwords removed
33
+ """
34
+ return [token for token in tokens if token not in stopwords]
35
+
36
+
37
+ def get_uncertainty_phrases() -> Set[str]:
38
+ """Get a set of common uncertainty phrases.
39
+
40
+ Returns:
41
+ Set of uncertainty phrases
42
+ """
43
+ return {
44
+ "i'm not sure",
45
+ "i'm uncertain",
46
+ "i don't know",
47
+ "might be",
48
+ "could be",
49
+ "possibly",
50
+ "perhaps",
51
+ "maybe",
52
+ "i think",
53
+ "i believe",
54
+ "it seems",
55
+ "it appears",
56
+ "likely",
57
+ "unlikely",
58
+ "not certain",
59
+ "not confident",
60
+ }
61
+
62
+
63
+ def get_confidence_phrases() -> Set[str]:
64
+ """Get a set of common confidence phrases.
65
+
66
+ Returns:
67
+ Set of confidence phrases
68
+ """
69
+ return {
70
+ "i'm certain",
71
+ "i'm confident",
72
+ "i'm sure",
73
+ "definitely",
74
+ "absolutely",
75
+ "certainly",
76
+ "without doubt",
77
+ "clearly",
78
+ "obviously",
79
+ "undoubtedly",
80
+ }
81
+
82
+
83
+ def normalize_text(text: str) -> str:
84
+ """Normalize text by removing extra whitespace and converting to lowercase.
85
+
86
+ Args:
87
+ text: Input text to normalize
88
+
89
+ Returns:
90
+ Normalized text
91
+ """
92
+ # Remove extra whitespace
93
+ text = re.sub(r"\s+", " ", text)
94
+ # Strip leading/trailing whitespace
95
+ text = text.strip()
96
+ # Convert to lowercase
97
+ text = text.lower()
98
+ return text
@@ -0,0 +1,22 @@
1
+ """Visualization utilities for AI Metacognition Toolkit.
2
+
3
+ This module provides publication-ready plotting functions for:
4
+ - Situational awareness time series
5
+ - Causal attribution analysis
6
+ - Feature divergence heatmaps
7
+ - Distribution comparisons
8
+ """
9
+
10
+ from .plotting import (
11
+ plot_awareness_over_time,
12
+ plot_causal_attribution,
13
+ plot_divergence_heatmap,
14
+ plot_feature_distributions,
15
+ )
16
+
17
+ __all__ = [
18
+ "plot_awareness_over_time",
19
+ "plot_causal_attribution",
20
+ "plot_divergence_heatmap",
21
+ "plot_feature_distributions",
22
+ ]