crca 1.4.0__py3-none-any.whl → 1.5.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.
- CRCA.py +172 -7
- MODEL_CARD.md +53 -0
- PKG-INFO +8 -2
- RELEASE_NOTES.md +17 -0
- STABILITY.md +19 -0
- architecture/hybrid/consistency_engine.py +362 -0
- architecture/hybrid/conversation_manager.py +421 -0
- architecture/hybrid/explanation_generator.py +452 -0
- architecture/hybrid/few_shot_learner.py +533 -0
- architecture/hybrid/graph_compressor.py +286 -0
- architecture/hybrid/hybrid_agent.py +4398 -0
- architecture/hybrid/language_compiler.py +623 -0
- architecture/hybrid/main,py +0 -0
- architecture/hybrid/reasoning_tracker.py +322 -0
- architecture/hybrid/self_verifier.py +524 -0
- architecture/hybrid/task_decomposer.py +567 -0
- architecture/hybrid/text_corrector.py +341 -0
- benchmark_results/crca_core_benchmarks.json +178 -0
- branches/crca_sd/crca_sd_realtime.py +6 -2
- branches/general_agent/__init__.py +102 -0
- branches/general_agent/general_agent.py +1400 -0
- branches/general_agent/personality.py +169 -0
- branches/general_agent/utils/__init__.py +19 -0
- branches/general_agent/utils/prompt_builder.py +170 -0
- {crca-1.4.0.dist-info → crca-1.5.0.dist-info}/METADATA +8 -2
- {crca-1.4.0.dist-info → crca-1.5.0.dist-info}/RECORD +303 -20
- crca_core/__init__.py +35 -0
- crca_core/benchmarks/__init__.py +14 -0
- crca_core/benchmarks/synthetic_scm.py +103 -0
- crca_core/core/__init__.py +23 -0
- crca_core/core/api.py +120 -0
- crca_core/core/estimate.py +208 -0
- crca_core/core/godclass.py +72 -0
- crca_core/core/intervention_design.py +174 -0
- crca_core/core/lifecycle.py +48 -0
- crca_core/discovery/__init__.py +9 -0
- crca_core/discovery/tabular.py +193 -0
- crca_core/identify/__init__.py +171 -0
- crca_core/identify/backdoor.py +39 -0
- crca_core/identify/frontdoor.py +48 -0
- crca_core/identify/graph.py +106 -0
- crca_core/identify/id_algorithm.py +43 -0
- crca_core/identify/iv.py +48 -0
- crca_core/models/__init__.py +67 -0
- crca_core/models/provenance.py +56 -0
- crca_core/models/refusal.py +39 -0
- crca_core/models/result.py +83 -0
- crca_core/models/spec.py +151 -0
- crca_core/models/validation.py +68 -0
- crca_core/scm/__init__.py +9 -0
- crca_core/scm/linear_gaussian.py +198 -0
- crca_core/timeseries/__init__.py +6 -0
- crca_core/timeseries/pcmci.py +181 -0
- crca_llm/__init__.py +12 -0
- crca_llm/client.py +85 -0
- crca_llm/coauthor.py +118 -0
- crca_llm/orchestrator.py +289 -0
- crca_llm/types.py +21 -0
- crca_reasoning/__init__.py +16 -0
- crca_reasoning/critique.py +54 -0
- crca_reasoning/godclass.py +206 -0
- crca_reasoning/memory.py +24 -0
- crca_reasoning/rationale.py +10 -0
- crca_reasoning/react_controller.py +81 -0
- crca_reasoning/tool_router.py +97 -0
- crca_reasoning/types.py +40 -0
- crca_sd/__init__.py +15 -0
- crca_sd/crca_sd_core.py +2 -0
- crca_sd/crca_sd_governance.py +2 -0
- crca_sd/crca_sd_mpc.py +2 -0
- crca_sd/crca_sd_realtime.py +2 -0
- crca_sd/crca_sd_tui.py +2 -0
- cuda-keyring_1.1-1_all.deb +0 -0
- cuda-keyring_1.1-1_all.deb.1 +0 -0
- docs/IMAGE_ANNOTATION_USAGE.md +539 -0
- docs/INSTALL_DEEPSPEED.md +125 -0
- docs/api/branches/crca-cg.md +19 -0
- docs/api/branches/crca-q.md +27 -0
- docs/api/branches/crca-sd.md +37 -0
- docs/api/branches/general-agent.md +24 -0
- docs/api/branches/overview.md +19 -0
- docs/api/crca/agent-methods.md +62 -0
- docs/api/crca/operations.md +79 -0
- docs/api/crca/overview.md +32 -0
- docs/api/image-annotation/engine.md +52 -0
- docs/api/image-annotation/overview.md +17 -0
- docs/api/schemas/annotation.md +34 -0
- docs/api/schemas/core-schemas.md +82 -0
- docs/api/schemas/overview.md +32 -0
- docs/api/schemas/policy.md +30 -0
- docs/api/utils/conversation.md +22 -0
- docs/api/utils/graph-reasoner.md +32 -0
- docs/api/utils/overview.md +21 -0
- docs/api/utils/router.md +19 -0
- docs/api/utils/utilities.md +97 -0
- docs/architecture/causal-graphs.md +41 -0
- docs/architecture/data-flow.md +29 -0
- docs/architecture/design-principles.md +33 -0
- docs/architecture/hybrid-agent/components.md +38 -0
- docs/architecture/hybrid-agent/consistency.md +26 -0
- docs/architecture/hybrid-agent/overview.md +44 -0
- docs/architecture/hybrid-agent/reasoning.md +22 -0
- docs/architecture/llm-integration.md +26 -0
- docs/architecture/modular-structure.md +37 -0
- docs/architecture/overview.md +69 -0
- docs/architecture/policy-engine-arch.md +29 -0
- docs/branches/crca-cg/corposwarm.md +39 -0
- docs/branches/crca-cg/esg-scoring.md +30 -0
- docs/branches/crca-cg/multi-agent.md +35 -0
- docs/branches/crca-cg/overview.md +40 -0
- docs/branches/crca-q/alternative-data.md +55 -0
- docs/branches/crca-q/architecture.md +71 -0
- docs/branches/crca-q/backtesting.md +45 -0
- docs/branches/crca-q/causal-engine.md +33 -0
- docs/branches/crca-q/execution.md +39 -0
- docs/branches/crca-q/market-data.md +60 -0
- docs/branches/crca-q/overview.md +58 -0
- docs/branches/crca-q/philosophy.md +60 -0
- docs/branches/crca-q/portfolio-optimization.md +66 -0
- docs/branches/crca-q/risk-management.md +102 -0
- docs/branches/crca-q/setup.md +65 -0
- docs/branches/crca-q/signal-generation.md +61 -0
- docs/branches/crca-q/signal-validation.md +43 -0
- docs/branches/crca-sd/core.md +84 -0
- docs/branches/crca-sd/governance.md +53 -0
- docs/branches/crca-sd/mpc-solver.md +65 -0
- docs/branches/crca-sd/overview.md +59 -0
- docs/branches/crca-sd/realtime.md +28 -0
- docs/branches/crca-sd/tui.md +20 -0
- docs/branches/general-agent/overview.md +37 -0
- docs/branches/general-agent/personality.md +36 -0
- docs/branches/general-agent/prompt-builder.md +30 -0
- docs/changelog/index.md +79 -0
- docs/contributing/code-style.md +69 -0
- docs/contributing/documentation.md +43 -0
- docs/contributing/overview.md +29 -0
- docs/contributing/testing.md +29 -0
- docs/core/crcagent/async-operations.md +65 -0
- docs/core/crcagent/automatic-extraction.md +107 -0
- docs/core/crcagent/batch-prediction.md +80 -0
- docs/core/crcagent/bayesian-inference.md +60 -0
- docs/core/crcagent/causal-graph.md +92 -0
- docs/core/crcagent/counterfactuals.md +96 -0
- docs/core/crcagent/deterministic-simulation.md +78 -0
- docs/core/crcagent/dual-mode-operation.md +82 -0
- docs/core/crcagent/initialization.md +88 -0
- docs/core/crcagent/optimization.md +65 -0
- docs/core/crcagent/overview.md +63 -0
- docs/core/crcagent/time-series.md +57 -0
- docs/core/schemas/annotation.md +30 -0
- docs/core/schemas/core-schemas.md +82 -0
- docs/core/schemas/overview.md +30 -0
- docs/core/schemas/policy.md +41 -0
- docs/core/templates/base-agent.md +31 -0
- docs/core/templates/feature-mixins.md +31 -0
- docs/core/templates/overview.md +29 -0
- docs/core/templates/templates-guide.md +75 -0
- docs/core/tools/mcp-client.md +34 -0
- docs/core/tools/overview.md +24 -0
- docs/core/utils/conversation.md +27 -0
- docs/core/utils/graph-reasoner.md +29 -0
- docs/core/utils/overview.md +27 -0
- docs/core/utils/router.md +27 -0
- docs/core/utils/utilities.md +97 -0
- docs/css/custom.css +84 -0
- docs/examples/basic-usage.md +57 -0
- docs/examples/general-agent/general-agent-examples.md +50 -0
- docs/examples/hybrid-agent/hybrid-agent-examples.md +56 -0
- docs/examples/image-annotation/image-annotation-examples.md +54 -0
- docs/examples/integration/integration-examples.md +58 -0
- docs/examples/overview.md +37 -0
- docs/examples/trading/trading-examples.md +46 -0
- docs/features/causal-reasoning/advanced-topics.md +101 -0
- docs/features/causal-reasoning/counterfactuals.md +43 -0
- docs/features/causal-reasoning/do-calculus.md +50 -0
- docs/features/causal-reasoning/overview.md +47 -0
- docs/features/causal-reasoning/structural-models.md +52 -0
- docs/features/hybrid-agent/advanced-components.md +55 -0
- docs/features/hybrid-agent/core-components.md +64 -0
- docs/features/hybrid-agent/overview.md +34 -0
- docs/features/image-annotation/engine.md +82 -0
- docs/features/image-annotation/features.md +113 -0
- docs/features/image-annotation/integration.md +75 -0
- docs/features/image-annotation/overview.md +53 -0
- docs/features/image-annotation/quickstart.md +73 -0
- docs/features/policy-engine/doctrine-ledger.md +105 -0
- docs/features/policy-engine/monitoring.md +44 -0
- docs/features/policy-engine/mpc-control.md +89 -0
- docs/features/policy-engine/overview.md +46 -0
- docs/getting-started/configuration.md +225 -0
- docs/getting-started/first-agent.md +164 -0
- docs/getting-started/installation.md +144 -0
- docs/getting-started/quickstart.md +137 -0
- docs/index.md +118 -0
- docs/js/mathjax.js +13 -0
- docs/lrm/discovery_proof_notes.md +25 -0
- docs/lrm/finetune_full.md +83 -0
- docs/lrm/math_appendix.md +120 -0
- docs/lrm/overview.md +32 -0
- docs/mkdocs.yml +238 -0
- docs/stylesheets/extra.css +21 -0
- docs_generated/crca_core/CounterfactualResult.md +12 -0
- docs_generated/crca_core/DiscoveryHypothesisResult.md +13 -0
- docs_generated/crca_core/DraftSpec.md +13 -0
- docs_generated/crca_core/EstimateResult.md +13 -0
- docs_generated/crca_core/IdentificationResult.md +17 -0
- docs_generated/crca_core/InterventionDesignResult.md +12 -0
- docs_generated/crca_core/LockedSpec.md +15 -0
- docs_generated/crca_core/RefusalResult.md +12 -0
- docs_generated/crca_core/ValidationReport.md +9 -0
- docs_generated/crca_core/index.md +13 -0
- examples/general_agent_example.py +277 -0
- examples/general_agent_quickstart.py +202 -0
- examples/general_agent_simple.py +92 -0
- examples/hybrid_agent_auto_extraction.py +84 -0
- examples/hybrid_agent_dictionary_demo.py +104 -0
- examples/hybrid_agent_enhanced.py +179 -0
- examples/hybrid_agent_general_knowledge.py +107 -0
- examples/image_annotation_quickstart.py +328 -0
- examples/test_hybrid_fixes.py +77 -0
- image_annotation/__init__.py +27 -0
- image_annotation/annotation_engine.py +2593 -0
- install_cuda_wsl2.sh +59 -0
- install_deepspeed.sh +56 -0
- install_deepspeed_simple.sh +87 -0
- mkdocs.yml +252 -0
- ollama/Modelfile +8 -0
- prompts/__init__.py +2 -1
- prompts/default_crca.py +9 -1
- prompts/general_agent.py +227 -0
- prompts/image_annotation.py +56 -0
- pyproject.toml +17 -2
- requirements-docs.txt +10 -0
- requirements.txt +21 -2
- schemas/__init__.py +26 -1
- schemas/annotation.py +222 -0
- schemas/conversation.py +193 -0
- schemas/hybrid.py +211 -0
- schemas/reasoning.py +276 -0
- schemas_export/crca_core/CounterfactualResult.schema.json +108 -0
- schemas_export/crca_core/DiscoveryHypothesisResult.schema.json +113 -0
- schemas_export/crca_core/DraftSpec.schema.json +635 -0
- schemas_export/crca_core/EstimateResult.schema.json +113 -0
- schemas_export/crca_core/IdentificationResult.schema.json +145 -0
- schemas_export/crca_core/InterventionDesignResult.schema.json +111 -0
- schemas_export/crca_core/LockedSpec.schema.json +646 -0
- schemas_export/crca_core/RefusalResult.schema.json +90 -0
- schemas_export/crca_core/ValidationReport.schema.json +62 -0
- scripts/build_lrm_dataset.py +80 -0
- scripts/export_crca_core_schemas.py +54 -0
- scripts/export_hf_lrm.py +37 -0
- scripts/export_ollama_gguf.py +45 -0
- scripts/generate_changelog.py +157 -0
- scripts/generate_crca_core_docs_from_schemas.py +86 -0
- scripts/run_crca_core_benchmarks.py +163 -0
- scripts/run_full_finetune.py +198 -0
- scripts/run_lrm_eval.py +31 -0
- templates/graph_management.py +29 -0
- tests/conftest.py +9 -0
- tests/test_core.py +2 -3
- tests/test_crca_core_discovery_tabular.py +15 -0
- tests/test_crca_core_estimate_dowhy.py +36 -0
- tests/test_crca_core_identify.py +18 -0
- tests/test_crca_core_intervention_design.py +36 -0
- tests/test_crca_core_linear_gaussian_scm.py +69 -0
- tests/test_crca_core_spec.py +25 -0
- tests/test_crca_core_timeseries_pcmci.py +15 -0
- tests/test_crca_llm_coauthor.py +12 -0
- tests/test_crca_llm_orchestrator.py +80 -0
- tests/test_hybrid_agent_llm_enhanced.py +556 -0
- tests/test_image_annotation_demo.py +376 -0
- tests/test_image_annotation_operational.py +408 -0
- tests/test_image_annotation_unit.py +551 -0
- tests/test_training_moe.py +13 -0
- training/__init__.py +42 -0
- training/datasets.py +140 -0
- training/deepspeed_zero2_0_5b.json +22 -0
- training/deepspeed_zero2_1_5b.json +22 -0
- training/deepspeed_zero3_0_5b.json +28 -0
- training/deepspeed_zero3_14b.json +28 -0
- training/deepspeed_zero3_h100_3gpu.json +20 -0
- training/deepspeed_zero3_offload.json +28 -0
- training/eval.py +92 -0
- training/finetune.py +516 -0
- training/public_datasets.py +89 -0
- training_data/react_train.jsonl +7473 -0
- utils/agent_discovery.py +311 -0
- utils/batch_processor.py +317 -0
- utils/conversation.py +78 -0
- utils/edit_distance.py +118 -0
- utils/formatter.py +33 -0
- utils/graph_reasoner.py +530 -0
- utils/rate_limiter.py +283 -0
- utils/router.py +2 -2
- utils/tool_discovery.py +307 -0
- webui/__init__.py +10 -0
- webui/app.py +229 -0
- webui/config.py +104 -0
- webui/static/css/style.css +332 -0
- webui/static/js/main.js +284 -0
- webui/templates/index.html +42 -0
- tests/test_crca_excel.py +0 -166
- tests/test_data_broker.py +0 -424
- tests/test_palantir.py +0 -349
- {crca-1.4.0.dist-info → crca-1.5.0.dist-info}/WHEEL +0 -0
- {crca-1.4.0.dist-info → crca-1.5.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Enhanced Explanation System with Interpretable AI and Explainable Reasoning.
|
|
3
|
+
|
|
4
|
+
Implements XAI with counterfactual explanations, uncertainty decomposition,
|
|
5
|
+
provenance tracking, and graph-theoretic structure explanation.
|
|
6
|
+
|
|
7
|
+
Theoretical Basis:
|
|
8
|
+
- Explainable AI (XAI) (Adadi & Berrada 2018)
|
|
9
|
+
- Interpretability (Lipton 2016)
|
|
10
|
+
- Counterfactual Explanations (Wachter et al. 2017)
|
|
11
|
+
- Causal Explanations (Pearl & Mackenzie 2018)
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from typing import Dict, List, Optional, Tuple, Any, Set
|
|
15
|
+
from collections import defaultdict
|
|
16
|
+
import logging
|
|
17
|
+
import math
|
|
18
|
+
|
|
19
|
+
from schemas.reasoning import ReasoningStep, ReasoningChain
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
# Try to import numpy
|
|
24
|
+
try:
|
|
25
|
+
import numpy as np
|
|
26
|
+
NUMPY_AVAILABLE = True
|
|
27
|
+
except ImportError:
|
|
28
|
+
NUMPY_AVAILABLE = False
|
|
29
|
+
np = None
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ExplanationBuilder:
|
|
33
|
+
"""
|
|
34
|
+
Implements multi-level explanations with step-by-step reasoning.
|
|
35
|
+
|
|
36
|
+
Features:
|
|
37
|
+
- Step-by-step explanations with graph state visualization
|
|
38
|
+
- Decision justification with evidence
|
|
39
|
+
- Counterfactual explanations
|
|
40
|
+
- Evidence provision with provenance tracking
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(self):
|
|
44
|
+
"""Initialize explanation builder."""
|
|
45
|
+
self.explanation_templates = {
|
|
46
|
+
'step': "Step {step_num}: {operation}\n Input: {input_state}\n Output: {output_state}\n Reasoning: {justification}\n Confidence: {confidence:.2f}",
|
|
47
|
+
'decision': "Decision: {decision}\n Evidence: {evidence}\n Rule: {rule}\n Confidence: {confidence:.2f}",
|
|
48
|
+
'counterfactual': "If {condition} were different, then {outcome} would be {value}.\n Current: {current_value}\n Counterfactual: {counterfactual_value}"
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
def generate_explanation(
|
|
52
|
+
self,
|
|
53
|
+
reasoning_chain: ReasoningChain,
|
|
54
|
+
graph: Optional[Dict[str, Any]] = None
|
|
55
|
+
) -> Dict[str, Any]:
|
|
56
|
+
"""
|
|
57
|
+
Generate step-by-step explanation from reasoning chain.
|
|
58
|
+
|
|
59
|
+
Algorithm:
|
|
60
|
+
function generate_explanation(reasoning_chain, graph):
|
|
61
|
+
explanation = []
|
|
62
|
+
for step in reasoning_chain:
|
|
63
|
+
explanation.append({
|
|
64
|
+
'operation': step.operation,
|
|
65
|
+
'input_state': graph_snapshot(step.input_state),
|
|
66
|
+
'output_state': graph_snapshot(step.output_state),
|
|
67
|
+
'justification': justify(step.operation, step.evidence),
|
|
68
|
+
'confidence': step.confidence,
|
|
69
|
+
'uncertainty': decompose_uncertainty(step)
|
|
70
|
+
})
|
|
71
|
+
return format_explanation(explanation)
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
reasoning_chain: Reasoning chain to explain
|
|
75
|
+
graph: Optional graph state
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
Explanation dictionary
|
|
79
|
+
"""
|
|
80
|
+
explanation = {
|
|
81
|
+
'steps': [],
|
|
82
|
+
'summary': '',
|
|
83
|
+
'confidence': 1.0,
|
|
84
|
+
'uncertainty': {}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
for i, step in enumerate(reasoning_chain.steps, 1):
|
|
88
|
+
step_explanation = {
|
|
89
|
+
'step_num': i,
|
|
90
|
+
'step_id': step.step_id,
|
|
91
|
+
'operation': step.operation,
|
|
92
|
+
'step_type': step.step_type.value,
|
|
93
|
+
'input_state': self._format_graph_state(step.input_state),
|
|
94
|
+
'output_state': self._format_graph_state(step.output_state),
|
|
95
|
+
'justification': self._justify_step(step),
|
|
96
|
+
'confidence': step.confidence,
|
|
97
|
+
'uncertainty': self._decompose_uncertainty(step),
|
|
98
|
+
'evidence': [e.content for e in step.evidence]
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
explanation['steps'].append(step_explanation)
|
|
102
|
+
|
|
103
|
+
# Compute overall confidence and uncertainty
|
|
104
|
+
if reasoning_chain.steps:
|
|
105
|
+
confidences = [s.confidence for s in reasoning_chain.steps]
|
|
106
|
+
explanation['confidence'] = sum(confidences) / len(confidences) if confidences else 1.0
|
|
107
|
+
|
|
108
|
+
# Generate summary
|
|
109
|
+
explanation['summary'] = self._generate_summary(reasoning_chain)
|
|
110
|
+
|
|
111
|
+
return explanation
|
|
112
|
+
|
|
113
|
+
def _format_graph_state(self, state: Dict[str, Any]) -> str:
|
|
114
|
+
"""
|
|
115
|
+
Format graph state for display.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
state: Graph state dictionary
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
Formatted string
|
|
122
|
+
"""
|
|
123
|
+
if not state:
|
|
124
|
+
return "Empty state"
|
|
125
|
+
|
|
126
|
+
nodes = state.get('nodes', [])
|
|
127
|
+
edges = state.get('edges', [])
|
|
128
|
+
|
|
129
|
+
if nodes:
|
|
130
|
+
nodes_str = f"Nodes: {', '.join(sorted(nodes))}"
|
|
131
|
+
else:
|
|
132
|
+
nodes_str = "No nodes"
|
|
133
|
+
|
|
134
|
+
if edges:
|
|
135
|
+
edges_str = f"Edges: {len(edges)} relationships"
|
|
136
|
+
else:
|
|
137
|
+
edges_str = "No edges"
|
|
138
|
+
|
|
139
|
+
return f"{nodes_str}\n{edges_str}"
|
|
140
|
+
|
|
141
|
+
def _justify_step(self, step: ReasoningStep) -> str:
|
|
142
|
+
"""
|
|
143
|
+
Generate justification for a reasoning step.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
step: Reasoning step
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
Justification string
|
|
150
|
+
"""
|
|
151
|
+
justification_parts = []
|
|
152
|
+
|
|
153
|
+
if step.inference_rule:
|
|
154
|
+
justification_parts.append(f"Applied {step.inference_rule.value} rule")
|
|
155
|
+
|
|
156
|
+
if step.premises:
|
|
157
|
+
justification_parts.append(f"Based on {len(step.premises)} premises")
|
|
158
|
+
|
|
159
|
+
if step.evidence:
|
|
160
|
+
evidence_summary = ", ".join([str(e.content)[:50] for e in step.evidence[:3]])
|
|
161
|
+
justification_parts.append(f"Evidence: {evidence_summary}")
|
|
162
|
+
|
|
163
|
+
if step.conclusion:
|
|
164
|
+
justification_parts.append(f"Concluded: {step.conclusion}")
|
|
165
|
+
|
|
166
|
+
return ". ".join(justification_parts) if justification_parts else "No justification provided"
|
|
167
|
+
|
|
168
|
+
def _decompose_uncertainty(self, step: ReasoningStep) -> Dict[str, float]:
|
|
169
|
+
"""
|
|
170
|
+
Decompose uncertainty into epistemic and aleatoric components.
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
step: Reasoning step
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
Dictionary with uncertainty components
|
|
177
|
+
"""
|
|
178
|
+
uncertainty = step.uncertainty or 0.0
|
|
179
|
+
confidence = step.confidence
|
|
180
|
+
|
|
181
|
+
# Simple decomposition:
|
|
182
|
+
# Epistemic uncertainty: model uncertainty (lack of knowledge)
|
|
183
|
+
# Aleatoric uncertainty: data uncertainty (inherent randomness)
|
|
184
|
+
|
|
185
|
+
# If confidence is low, more epistemic uncertainty
|
|
186
|
+
epistemic = (1.0 - confidence) * 0.7 # 70% of low confidence is epistemic
|
|
187
|
+
aleatoric = uncertainty * 0.3 # 30% is aleatoric
|
|
188
|
+
|
|
189
|
+
return {
|
|
190
|
+
'total': uncertainty,
|
|
191
|
+
'epistemic': epistemic,
|
|
192
|
+
'aleatoric': aleatoric,
|
|
193
|
+
'confidence': confidence
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
def _generate_summary(self, reasoning_chain: ReasoningChain) -> str:
|
|
197
|
+
"""
|
|
198
|
+
Generate summary of reasoning chain.
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
reasoning_chain: Reasoning chain
|
|
202
|
+
|
|
203
|
+
Returns:
|
|
204
|
+
Summary string
|
|
205
|
+
"""
|
|
206
|
+
if not reasoning_chain.steps:
|
|
207
|
+
return "No reasoning steps"
|
|
208
|
+
|
|
209
|
+
num_steps = len(reasoning_chain.steps)
|
|
210
|
+
success = "succeeded" if reasoning_chain.success else "failed"
|
|
211
|
+
conclusion = reasoning_chain.final_conclusion or "No conclusion"
|
|
212
|
+
|
|
213
|
+
return f"Reasoning chain with {num_steps} steps {success}. Final conclusion: {conclusion}"
|
|
214
|
+
|
|
215
|
+
def generate_counterfactual_explanation(
|
|
216
|
+
self,
|
|
217
|
+
variable: str,
|
|
218
|
+
current_value: Any,
|
|
219
|
+
counterfactual_value: Any,
|
|
220
|
+
outcome: str,
|
|
221
|
+
outcome_value: Any
|
|
222
|
+
) -> str:
|
|
223
|
+
"""
|
|
224
|
+
Generate counterfactual explanation.
|
|
225
|
+
|
|
226
|
+
"If X were different, then Y would be Z"
|
|
227
|
+
|
|
228
|
+
Args:
|
|
229
|
+
variable: Variable name
|
|
230
|
+
current_value: Current value
|
|
231
|
+
counterfactual_value: Counterfactual value
|
|
232
|
+
outcome: Outcome variable
|
|
233
|
+
outcome_value: Outcome value
|
|
234
|
+
|
|
235
|
+
Returns:
|
|
236
|
+
Counterfactual explanation string
|
|
237
|
+
"""
|
|
238
|
+
return self.explanation_templates['counterfactual'].format(
|
|
239
|
+
condition=variable,
|
|
240
|
+
outcome=outcome,
|
|
241
|
+
value=outcome_value,
|
|
242
|
+
current_value=current_value,
|
|
243
|
+
counterfactual_value=counterfactual_value
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
class TransparencyLayer:
|
|
248
|
+
"""
|
|
249
|
+
Implements complete transparency with reasoning trace and uncertainty visualization.
|
|
250
|
+
|
|
251
|
+
Features:
|
|
252
|
+
- Complete reasoning trace
|
|
253
|
+
- Confidence visualization with uncertainty quantification
|
|
254
|
+
- Uncertainty decomposition (epistemic/aleatoric)
|
|
255
|
+
- Graph structure explanation
|
|
256
|
+
"""
|
|
257
|
+
|
|
258
|
+
def __init__(self):
|
|
259
|
+
"""Initialize transparency layer."""
|
|
260
|
+
self.trace_history: List[Dict[str, Any]] = []
|
|
261
|
+
|
|
262
|
+
def show_reasoning_trace(
|
|
263
|
+
self,
|
|
264
|
+
reasoning_chain: ReasoningChain
|
|
265
|
+
) -> Dict[str, Any]:
|
|
266
|
+
"""
|
|
267
|
+
Show complete reasoning trace.
|
|
268
|
+
|
|
269
|
+
Args:
|
|
270
|
+
reasoning_chain: Reasoning chain
|
|
271
|
+
|
|
272
|
+
Returns:
|
|
273
|
+
Trace dictionary
|
|
274
|
+
"""
|
|
275
|
+
trace = {
|
|
276
|
+
'chain_id': reasoning_chain.chain_id,
|
|
277
|
+
'steps': [],
|
|
278
|
+
'decision_points': reasoning_chain.decision_points,
|
|
279
|
+
'alternative_branches': reasoning_chain.alternative_branches
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
for step in reasoning_chain.steps:
|
|
283
|
+
step_trace = {
|
|
284
|
+
'step_id': step.step_id,
|
|
285
|
+
'step_type': step.step_type.value,
|
|
286
|
+
'operation': step.operation,
|
|
287
|
+
'input_state': step.input_state,
|
|
288
|
+
'output_state': step.output_state,
|
|
289
|
+
'confidence': step.confidence,
|
|
290
|
+
'uncertainty': step.uncertainty,
|
|
291
|
+
'premises': step.premises,
|
|
292
|
+
'conclusion': step.conclusion,
|
|
293
|
+
'timestamp': step.timestamp
|
|
294
|
+
}
|
|
295
|
+
trace['steps'].append(step_trace)
|
|
296
|
+
|
|
297
|
+
self.trace_history.append(trace)
|
|
298
|
+
return trace
|
|
299
|
+
|
|
300
|
+
def visualize_confidence(
|
|
301
|
+
self,
|
|
302
|
+
reasoning_chain: ReasoningChain
|
|
303
|
+
) -> Dict[str, Any]:
|
|
304
|
+
"""
|
|
305
|
+
Visualize confidence scores with uncertainty quantification.
|
|
306
|
+
|
|
307
|
+
P(conclusion | evidence) ± σ
|
|
308
|
+
|
|
309
|
+
Args:
|
|
310
|
+
reasoning_chain: Reasoning chain
|
|
311
|
+
|
|
312
|
+
Returns:
|
|
313
|
+
Confidence visualization dictionary
|
|
314
|
+
"""
|
|
315
|
+
if not reasoning_chain.steps:
|
|
316
|
+
return {}
|
|
317
|
+
|
|
318
|
+
confidences = [s.confidence for s in reasoning_chain.steps]
|
|
319
|
+
uncertainties = [s.uncertainty or 0.0 for s in reasoning_chain.steps]
|
|
320
|
+
|
|
321
|
+
if NUMPY_AVAILABLE and confidences:
|
|
322
|
+
mean_confidence = float(np.mean(confidences))
|
|
323
|
+
std_confidence = float(np.std(confidences))
|
|
324
|
+
mean_uncertainty = float(np.mean(uncertainties))
|
|
325
|
+
else:
|
|
326
|
+
mean_confidence = sum(confidences) / len(confidences) if confidences else 0.0
|
|
327
|
+
std_confidence = math.sqrt(sum((c - mean_confidence) ** 2 for c in confidences) / len(confidences)) if confidences else 0.0
|
|
328
|
+
mean_uncertainty = sum(uncertainties) / len(uncertainties) if uncertainties else 0.0
|
|
329
|
+
|
|
330
|
+
return {
|
|
331
|
+
'mean_confidence': mean_confidence,
|
|
332
|
+
'std_confidence': std_confidence,
|
|
333
|
+
'confidence_interval_95': (
|
|
334
|
+
max(0.0, mean_confidence - 1.96 * std_confidence),
|
|
335
|
+
min(1.0, mean_confidence + 1.96 * std_confidence)
|
|
336
|
+
),
|
|
337
|
+
'mean_uncertainty': mean_uncertainty,
|
|
338
|
+
'step_confidences': confidences,
|
|
339
|
+
'step_uncertainties': uncertainties
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
def explain_graph_structure(
|
|
343
|
+
self,
|
|
344
|
+
graph: Dict[str, Any]
|
|
345
|
+
) -> Dict[str, Any]:
|
|
346
|
+
"""
|
|
347
|
+
Explain graph structure using graph-theoretic concepts.
|
|
348
|
+
|
|
349
|
+
Args:
|
|
350
|
+
graph: Graph dictionary
|
|
351
|
+
|
|
352
|
+
Returns:
|
|
353
|
+
Graph structure explanation
|
|
354
|
+
"""
|
|
355
|
+
nodes = graph.get('nodes', [])
|
|
356
|
+
edges = graph.get('edges', [])
|
|
357
|
+
|
|
358
|
+
# Build adjacency representation
|
|
359
|
+
adjacency: Dict[str, Set[str]] = defaultdict(set)
|
|
360
|
+
in_degree: Dict[str, int] = defaultdict(int)
|
|
361
|
+
out_degree: Dict[str, int] = defaultdict(int)
|
|
362
|
+
|
|
363
|
+
for source, target in edges:
|
|
364
|
+
adjacency[source].add(target)
|
|
365
|
+
out_degree[source] += 1
|
|
366
|
+
in_degree[target] += 1
|
|
367
|
+
|
|
368
|
+
# Find key nodes
|
|
369
|
+
root_nodes = [n for n in nodes if in_degree[n] == 0]
|
|
370
|
+
leaf_nodes = [n for n in nodes if out_degree[n] == 0]
|
|
371
|
+
hub_nodes = [n for n in nodes if out_degree[n] > 2]
|
|
372
|
+
|
|
373
|
+
# Detect cycles (simplified)
|
|
374
|
+
has_cycles = self._detect_cycles(nodes, edges)
|
|
375
|
+
|
|
376
|
+
# Find strongly connected components (simplified)
|
|
377
|
+
sccs = self._find_sccs(nodes, edges)
|
|
378
|
+
|
|
379
|
+
return {
|
|
380
|
+
'num_nodes': len(nodes),
|
|
381
|
+
'num_edges': len(edges),
|
|
382
|
+
'root_nodes': root_nodes,
|
|
383
|
+
'leaf_nodes': leaf_nodes,
|
|
384
|
+
'hub_nodes': hub_nodes,
|
|
385
|
+
'has_cycles': has_cycles,
|
|
386
|
+
'strongly_connected_components': len(sccs),
|
|
387
|
+
'structure_type': self._classify_structure(nodes, edges, root_nodes, leaf_nodes)
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
def _detect_cycles(
|
|
391
|
+
self,
|
|
392
|
+
nodes: List[str],
|
|
393
|
+
edges: List[Tuple[str, str]]
|
|
394
|
+
) -> bool:
|
|
395
|
+
"""Detect cycles in graph (simplified DFS)."""
|
|
396
|
+
visited = set()
|
|
397
|
+
rec_stack = set()
|
|
398
|
+
adjacency = defaultdict(list)
|
|
399
|
+
|
|
400
|
+
for source, target in edges:
|
|
401
|
+
adjacency[source].append(target)
|
|
402
|
+
|
|
403
|
+
def has_cycle(node: str) -> bool:
|
|
404
|
+
visited.add(node)
|
|
405
|
+
rec_stack.add(node)
|
|
406
|
+
|
|
407
|
+
for neighbor in adjacency.get(node, []):
|
|
408
|
+
if neighbor not in visited:
|
|
409
|
+
if has_cycle(neighbor):
|
|
410
|
+
return True
|
|
411
|
+
elif neighbor in rec_stack:
|
|
412
|
+
return True
|
|
413
|
+
|
|
414
|
+
rec_stack.remove(node)
|
|
415
|
+
return False
|
|
416
|
+
|
|
417
|
+
for node in nodes:
|
|
418
|
+
if node not in visited:
|
|
419
|
+
if has_cycle(node):
|
|
420
|
+
return True
|
|
421
|
+
|
|
422
|
+
return False
|
|
423
|
+
|
|
424
|
+
def _find_sccs(
|
|
425
|
+
self,
|
|
426
|
+
nodes: List[str],
|
|
427
|
+
edges: List[Tuple[str, str]]
|
|
428
|
+
) -> List[Set[str]]:
|
|
429
|
+
"""Find strongly connected components (simplified)."""
|
|
430
|
+
# Simplified: return each node as its own SCC
|
|
431
|
+
# Full implementation would use Tarjan's algorithm
|
|
432
|
+
return [{node} for node in nodes]
|
|
433
|
+
|
|
434
|
+
def _classify_structure(
|
|
435
|
+
self,
|
|
436
|
+
nodes: List[str],
|
|
437
|
+
edges: List[Tuple[str, str]],
|
|
438
|
+
root_nodes: List[str],
|
|
439
|
+
leaf_nodes: List[str]
|
|
440
|
+
) -> str:
|
|
441
|
+
"""Classify graph structure type."""
|
|
442
|
+
if not nodes:
|
|
443
|
+
return "empty"
|
|
444
|
+
|
|
445
|
+
if len(root_nodes) == 1 and len(leaf_nodes) == 1:
|
|
446
|
+
return "linear_chain"
|
|
447
|
+
elif len(root_nodes) == 1:
|
|
448
|
+
return "tree"
|
|
449
|
+
elif len(leaf_nodes) == 1:
|
|
450
|
+
return "convergent"
|
|
451
|
+
else:
|
|
452
|
+
return "general_dag"
|