Theoretical Enrichment & Tenability Evaluation¶
Theoretical Enrichment is a modular post-processing subsystem implementing dynamic Theory-Element induction (\(\Phi_{\text{spec}}\)) and structuralist tenability evaluation (\(TS_{\text{local}}, TS_{\text{edge}}\)) for the Episteme pipeline.
It bridges the domain-agnostic structural graph (\(\Phi_{\text{gen}}\)) produced by Phases 1–6 with formal structuralist metatheory (Stegmüller, 1976; Balzer et al., 1987; Schurz, 2024), without hardcoding any domain-specific scientific frameworks.
Architectural Role & Two-Stage Pipeline¶
flowchart TD
subgraph CorePipeline ["Core Pipeline (Phases 1-6)"]
UP["Extracted Graph:<br>TheoreticalHypothesis (Partition A)<br>ObservationUnit (Partition B)<br>Relations (EXPLAINS, SUPPORTS, CONSTRAINS)"]
end
subgraph Stage1 ["Stage 1: Macro Theory Induction (Graph Scope)"]
TI["LLMTheoryInducer<br>(Discovers active T = ⟨K⟩ without hardcoded schemas)"]
REG["TheoryRegistry<br>(M_pp dimensions, M_p parameters, Laws M)"]
UP --> TI --> REG
end
subgraph Stage2 ["Stage 2: Micro Cluster Projection & Evaluation (Cluster Scope)"]
CLUST["Empirical Clusters (Intended Applications I_k ⊆ M_pp)"]
TP["LLMTheoryProjector<br>(Projects cluster into candidate M_p space)"]
SOLV["TenabilitySolver<br>(Safe AST Law Evaluator + Blur Minimization)"]
REG --> TP
CLUST --> TP
TP -->|"Phi_spec(I_k)"| SOLV
end
SOLV -->|"Enriched Parameters & TS Scores"| NEO4J[("Neo4j Projection Graph")]
SOLV -->|"TheoreticalEnrichmentArtifact"| ARTS[(".pipeline_artifacts")]
The Four Processing Steps¶
Stage 0 / Step 1: Dynamic Theory-Element Induction (Macro Scope)¶
- If the
TheoryRegistryis unseeded,LLMTheoryInducerscans the entire graph'sTheoreticalHypothesisnodes (Partition \(A\)) and empirical observation types (Partition \(B\)). - Induces up to
max_theoriesactive Theory-Elements (\(T = \langle K, I \rangle\)), extracting: - Non-theoretical empirical dimensions (\(M_{pp}\)).
- Latent theoretical parameters (\(M_p\)).
- Core mathematical constraint laws (\(M\)) with symbolic formulas (e.g.
abs(P1 - P2) * 0.5). - Automatically registers the induced theories into
TheoryRegistry.
Step 2: Cluster Mapping & Domain-Specific Projection (\(\Phi_{\text{spec}}\))¶
- Groups
ObservationUnitandEmpiricalStatementnodes into empirical clusters representing Intended Applications (\(I \subseteq M_{pp}\)). - Evaluates each cluster through the claiming theory's lens via
LLMTheoryProjectoror structured measurement lookups. - Estimates candidate latent theoretical parameter values \(\Phi_{\text{spec}}(I_k) \in [0.0, 1.0]\).
Step 3: Local Tenability Calculation (\(TS_{\text{local}}\))¶
- Evaluates core laws using the AST-based
SafeFormulaEvaluator(zeroeval()security risk): $\(TS_{\text{local}}(y, M) = \sup \{ 1 - \delta \mid \exists x^* \in M : (\Phi(y), x^*) \in u_\delta \}\)$ - Determines the tightest admissible blur \(\delta^*\) reconciling postulated parameters with core laws \(M\).
Step 4: Global and Intertheoretical Consistency (\(GL\))¶
- Evaluates
CONSTRAINSandREDUCES_TOedges across clusters and models: $\(TS_{\text{edge}}(e) = \sup \{ 1 - \delta_C \mid (\Phi(y_a), \Phi(y_b)) \in v_{\delta_C} \}\)$ - Flags edges or hypotheses with \(TS < 0.5\) as untenable anomalies.
Python API Reference¶
episteme_pipeline.post_processing.theoretical_enrichment.runner.TheoreticalEnrichmentRunner
¶
Bases: PhaseRunner[Phase4ArtifactsView]
Executes Theoretical Enrichment & Tenability Evaluation post-processing.
Parameters¶
config : TheoreticalEnrichmentConfig | None, optional Configuration block for Theoretical Enrichment, by default None. schema : SchemaConfig | None, optional Decoupled schema configuration, by default None. graph_store : ProjectionGraph | None, optional Graph backend to project enriched parameters and scores into, by default None. registry : TheoryRegistry | None, optional Registry of formal Theory-Element definitions, by default None. projector : TheoryProjector | None, optional Domain projection engine (Phi_spec), by default None. solver : TenabilitySolver | None, optional Tenability optimization solver, by default None. inducer : TheoryInducer | None, optional Dynamic Theory-Element induction engine, by default None. llm : Any | None, optional Underlying LLM facade for induction and projection, by default None.
Source code in packages/episteme-pipeline/episteme_pipeline/post_processing/theoretical_enrichment/runner.py
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 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 | |
event_emitter
property
¶
Centralized event emitter.
run(input, context)
async
¶
Run the Theoretical Enrichment and Tenability Evaluation post-processor.
Parameters¶
input : Phase4ArtifactsView Typed slice of upstream Phase 4/5 theory atoms and relations. context : ArtifactExecutionContext Execution run context and manifest tracking.
Returns¶
ArtifactCollection Collection of emitted TheoreticalEnrichmentArtifact envelopes.
Source code in packages/episteme-pipeline/episteme_pipeline/post_processing/theoretical_enrichment/runner.py
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 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 | |
episteme_pipeline.post_processing.theoretical_enrichment.inducer.LLMTheoryInducer
¶
LLM-backed inducer for discovering Theory-Elements from epistemic graphs.
Parameters¶
llm : Any Underlying LLM facade or StructuredLLM instance. prompts : StructuredPromptBundle | str | None, optional Custom prompt bundle or template string, by default None. strategy : Any, optional Decoding strategy for structured prediction, by default "direct_constrained".
Source code in packages/episteme-pipeline/episteme_pipeline/post_processing/theoretical_enrichment/inducer.py
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 | |
induce_theories(atoms, relations, schema=None, max_theories=5)
async
¶
Induce Theory-Elements using structured LLM prediction.
Parameters¶
atoms : list[TheoryAtom] Input graph nodes across partitions A and B. relations : list[TheoryRelation] Structural relations connecting atoms. schema : SchemaConfig | None, optional Graph schema defining component partitions, by default None. max_theories : int, optional Upper bound on induced theories, by default 5.
Returns¶
list[TheoryElementDefinition] List of induced formal Theory-Element specifications.
Source code in packages/episteme-pipeline/episteme_pipeline/post_processing/theoretical_enrichment/inducer.py
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 | |
episteme_pipeline.post_processing.theoretical_enrichment.projectors.LLMTheoryProjector
¶
Bases: TheoryProjector
LLM-backed projector estimating empirical dimensions and theoretical parameters.
Prompts the LLM to project an empirical cluster through the specific formal lens of a Theory-Element, extracting observed dimension values and postulating candidate latent parameter values (M_p).
Parameters¶
llm : Any Underlying LLM facade or StructuredLLM instance. prompts : StructuredPromptBundle | str | None, optional Custom prompt bundle or template string, by default None. strategy : Any, optional Decoding strategy for structured prediction, by default "direct_constrained".
Source code in packages/episteme-pipeline/episteme_pipeline/post_processing/theoretical_enrichment/projectors.py
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 | |
aproject(cluster, theory)
async
¶
Asynchronously project empirical cluster into theoretical parameters via LLM.
Parameters¶
cluster : EmpiricalCluster Target empirical cluster. theory : TheoryElementDefinition Theory-element definition specifying M_pp and M_p.
Returns¶
dict[str, Any] Dictionary of parameter name to postulated value.
Source code in packages/episteme-pipeline/episteme_pipeline/post_processing/theoretical_enrichment/projectors.py
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 | |
project(cluster, theory)
¶
Synchronous projection wrapper using fast-path or fallback.
Source code in packages/episteme-pipeline/episteme_pipeline/post_processing/theoretical_enrichment/projectors.py
182 183 184 185 186 187 188 189 | |
episteme_pipeline.post_processing.theoretical_enrichment.solvers.SafeFormulaEvaluator
¶
Safe AST-based evaluator for induced mathematical constraint laws.
Evaluates symbolic arithmetic and functional constraints without using Python's eval() function, preventing code injection and syntax crashes.
Source code in packages/episteme-pipeline/episteme_pipeline/post_processing/theoretical_enrichment/solvers.py
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 | |
evaluate(expression, parameters)
classmethod
¶
Evaluate a constraint expression and return deviation >= 0.0.
Parameters¶
expression : str Symbolic formula (e.g. 'abs(dopamine - amygdala) * 0.5'). parameters : dict[str, Any] Dictionary of parameter names to numeric values.
Returns¶
float Computed deviation (0.0 represents exact satisfaction).
Source code in packages/episteme-pipeline/episteme_pipeline/post_processing/theoretical_enrichment/solvers.py
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 | |
episteme_pipeline.post_processing.theoretical_enrichment.enrichment_models.TheoryRegistry
¶
Registry holding active Theory-Element definitions.
Parameters¶
seed_theories : list[TheoryElementDefinition] | None, optional Initial list of theory elements to populate the registry with.
Source code in packages/episteme-pipeline/episteme_pipeline/post_processing/theoretical_enrichment/enrichment_models.py
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 | |
all_theories()
¶
Return all registered theory definitions.
Returns¶
list[TheoryElementDefinition] List of registered theory definitions.
Source code in packages/episteme-pipeline/episteme_pipeline/post_processing/theoretical_enrichment/enrichment_models.py
314 315 316 317 318 319 320 321 322 | |
get(theory_id)
¶
Retrieve a registered Theory-Element by id.
Parameters¶
theory_id : str Identifier of the theory.
Returns¶
TheoryElementDefinition | None The registered theory definition, or None if not found.
Source code in packages/episteme-pipeline/episteme_pipeline/post_processing/theoretical_enrichment/enrichment_models.py
299 300 301 302 303 304 305 306 307 308 309 310 311 312 | |
match_claimants(cluster)
¶
Identify which registered theories claim an empirical cluster.
A theory claims a cluster if: 1. Any of the theory's required dimensions are present in the cluster measurements, OR 2. Any observation unit text mentions the theory keywords or concepts, OR 3. Any cluster node is registered as a claimant hypothesis ID for the theory.
Parameters¶
cluster : EmpiricalCluster Target empirical cluster.
Returns¶
list[str] List of matching theory_id strings.
Source code in packages/episteme-pipeline/episteme_pipeline/post_processing/theoretical_enrichment/enrichment_models.py
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 | |
register(theory)
¶
Register a new Theory-Element definition.
Parameters¶
theory : TheoryElementDefinition Theory-element specification to register.
Source code in packages/episteme-pipeline/episteme_pipeline/post_processing/theoretical_enrichment/enrichment_models.py
250 251 252 253 254 255 256 257 258 | |
register_induced_theories(induced)
¶
Convert and register dynamically induced Theory-Elements.
Parameters¶
induced : list[InducedTheoryElement] List of induced theory elements from LLM induction.
Returns¶
list[TheoryElementDefinition] The instantiated and registered TheoryElementDefinition objects.
Source code in packages/episteme-pipeline/episteme_pipeline/post_processing/theoretical_enrichment/enrichment_models.py
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 | |
episteme_pipeline.post_processing.theoretical_enrichment.solvers.TenabilitySolver
¶
Solver for local and intertheoretical tenability optimization.
Parameters¶
anomaly_threshold : float, optional Threshold below which scores are flagged as anomalies, by default 0.5. weight_local : float, optional Relative weight for local law satisfaction, by default 0.5. weight_edge : float, optional Relative weight for intertheoretical / constraint consistency, by default 0.5.
Source code in packages/episteme-pipeline/episteme_pipeline/post_processing/theoretical_enrichment/solvers.py
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 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 | |
evaluate_theory_tenability(local_score, edge_scores, delta_star, local_anomalies, edge_anomalies)
¶
Combine local and edge scores into a final TenabilityResult.
Parameters¶
local_score : float Local law adherence score (TS_local). edge_scores : dict[str, float] Map of relation_id -> TS_edge. delta_star : float Tightest admissible blur found. local_anomalies : list[str] Local law violation notices. edge_anomalies : list[str] Constraint violation notices.
Returns¶
TenabilityResult Complete aggregated result.
Source code in packages/episteme-pipeline/episteme_pipeline/post_processing/theoretical_enrichment/solvers.py
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 | |
solve_edge_tenability(source_params, target_params, relation)
¶
Evaluate constraint or intertheoretical consistency across an edge.
Under constraint blurs v_{delta_C}, calculates: TS_edge(e) = sup { 1 - delta_C | (Phi(y_a), Phi(y_b)) in v_{delta_C} }
Parameters¶
source_params : dict[str, Any] Parameters postulated at the source theory/cluster. target_params : dict[str, Any] Parameters postulated at the target theory/cluster. relation : TheoryRelation The intertheoretical or constraint relation.
Returns¶
tuple[float, float, list[str]] Tuple of (TS_edge, delta_c, anomalies).
Source code in packages/episteme-pipeline/episteme_pipeline/post_processing/theoretical_enrichment/solvers.py
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 | |
solve_local_tenability(parameters, theory)
¶
Calculate the tightest admissible blur delta* and TS_local score.
Parameters¶
parameters : dict[str, Any] The postulated theoretical parameters. theory : TheoryElementDefinition Target theory definition with its core laws M.
Returns¶
tuple[float, float, list[str]] Tuple of (TS_local, delta_star, anomalies).
Source code in packages/episteme-pipeline/episteme_pipeline/post_processing/theoretical_enrichment/solvers.py
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 | |
Programmatic Seeding of Custom Theories¶
While the runner dynamically induces theories via LLM by default, custom theories can be registered explicitly:
from pipeline.post_processing.theoretical_enrichment import (
TheoryElementDefinition,
TheoryLaw,
TheoryRegistry,
TheoreticalEnrichmentRunner,
)
# 1. Define a core law with symbolic formula or callable evaluator
law = TheoryLaw(
law_id="newton_second_law",
description="Force equals mass times acceleration.",
formula_expression="abs(Force - Mass * Acceleration)",
involved_parameters=["Force", "Mass", "Acceleration"],
)
# 2. Define the Theory-Element
classical_mechanics = TheoryElementDefinition(
theory_id="classical_mechanics",
name="Classical Mechanics",
required_dimensions=["position", "time"],
parameter_names=["Mass", "Force", "Acceleration"],
laws=[law],
max_admissible_blur=1.0,
)
# 3. Seed the registry
registry = TheoryRegistry(seed_theories=[classical_mechanics])
runner = TheoreticalEnrichmentRunner(registry=registry)