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,421 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Conversation Memory & Context Management with Memory Networks and Attention.
|
|
3
|
+
|
|
4
|
+
Implements episodic memory with attention mechanisms for multi-turn conversations.
|
|
5
|
+
Uses exponential decay for recency weighting and Hobbs algorithm for coreference resolution.
|
|
6
|
+
|
|
7
|
+
Theoretical Basis:
|
|
8
|
+
- Memory Networks (Weston et al. 2014)
|
|
9
|
+
- Attention mechanisms (Bahdanau et al. 2014)
|
|
10
|
+
- Episodic Memory (Tulving 1972)
|
|
11
|
+
- Discourse Representation Theory (Kamp & Reyle 1993)
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from typing import Dict, List, Optional, Tuple, Set, Any
|
|
15
|
+
from collections import defaultdict, deque
|
|
16
|
+
import logging
|
|
17
|
+
import re
|
|
18
|
+
import math
|
|
19
|
+
|
|
20
|
+
from schemas.conversation import (
|
|
21
|
+
ConversationMessage, ConversationContext, VariableMapping,
|
|
22
|
+
GraphSnapshot, MessageRole
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
logger = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
# Import numpy if available for attention computation
|
|
28
|
+
try:
|
|
29
|
+
import numpy as np
|
|
30
|
+
NUMPY_AVAILABLE = True
|
|
31
|
+
except ImportError:
|
|
32
|
+
NUMPY_AVAILABLE = False
|
|
33
|
+
np = None
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ConversationHistory:
|
|
37
|
+
"""
|
|
38
|
+
Implements episodic memory with O(n) space, O(log n) query time.
|
|
39
|
+
|
|
40
|
+
Stores multi-turn conversation with:
|
|
41
|
+
- Message sequence with temporal ordering
|
|
42
|
+
- Graph state snapshots per turn (immutable)
|
|
43
|
+
- Variable mappings across turns (bijective function φ: V_t → V_{t+1})
|
|
44
|
+
- Context windows with exponential decay attention
|
|
45
|
+
- Reference resolution using entity linking
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
def __init__(self, conversation_id: Optional[str] = None, decay_lambda: float = 0.1):
|
|
49
|
+
"""
|
|
50
|
+
Initialize conversation history.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
conversation_id: Unique identifier for conversation
|
|
54
|
+
decay_lambda: Exponential decay parameter for attention weights
|
|
55
|
+
"""
|
|
56
|
+
import time
|
|
57
|
+
self.conversation_id = conversation_id or f"conv_{int(time.time() * 1000)}"
|
|
58
|
+
self.decay_lambda = decay_lambda
|
|
59
|
+
self.context = ConversationContext(
|
|
60
|
+
conversation_id=self.conversation_id,
|
|
61
|
+
decay_lambda=decay_lambda
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# Index for fast retrieval (O(log n) query)
|
|
65
|
+
self._message_index: Dict[str, int] = {} # message_id -> index
|
|
66
|
+
self._variable_index: Dict[str, List[int]] = defaultdict(list) # variable -> [turn_indices]
|
|
67
|
+
|
|
68
|
+
def add_message(
|
|
69
|
+
self,
|
|
70
|
+
role: MessageRole,
|
|
71
|
+
content: str,
|
|
72
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
73
|
+
) -> ConversationMessage:
|
|
74
|
+
"""
|
|
75
|
+
Add a message to conversation history.
|
|
76
|
+
|
|
77
|
+
O(1) insertion time.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
role: Message role (user/agent/system)
|
|
81
|
+
content: Message content
|
|
82
|
+
metadata: Optional metadata (variables, graph state, etc.)
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
Created ConversationMessage
|
|
86
|
+
"""
|
|
87
|
+
message = ConversationMessage(
|
|
88
|
+
role=role,
|
|
89
|
+
content=content,
|
|
90
|
+
metadata=metadata or {}
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
self.context.add_message(message)
|
|
94
|
+
self._message_index[message.message_id] = len(self.context.messages) - 1
|
|
95
|
+
|
|
96
|
+
# Index variables mentioned in metadata
|
|
97
|
+
if 'variables' in message.metadata:
|
|
98
|
+
for var in message.metadata['variables']:
|
|
99
|
+
self._variable_index[var].append(len(self.context.messages) - 1)
|
|
100
|
+
|
|
101
|
+
return message
|
|
102
|
+
|
|
103
|
+
def add_graph_snapshot(
|
|
104
|
+
self,
|
|
105
|
+
turn_number: int,
|
|
106
|
+
nodes: Set[str],
|
|
107
|
+
edges: List[Tuple[str, str]],
|
|
108
|
+
node_attributes: Optional[Dict[str, Dict[str, Any]]] = None,
|
|
109
|
+
edge_attributes: Optional[Dict[Tuple[str, str], Dict[str, Any]]] = None
|
|
110
|
+
) -> GraphSnapshot:
|
|
111
|
+
"""
|
|
112
|
+
Add immutable graph snapshot for a turn.
|
|
113
|
+
|
|
114
|
+
Uses persistent data structures (copy-on-write) for O(1) snapshot creation.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
turn_number: Turn number
|
|
118
|
+
nodes: Set of node names
|
|
119
|
+
edges: List of (source, target) edges
|
|
120
|
+
node_attributes: Optional node attributes
|
|
121
|
+
edge_attributes: Optional edge attributes
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
Created GraphSnapshot
|
|
125
|
+
"""
|
|
126
|
+
snapshot = GraphSnapshot(
|
|
127
|
+
turn_number=turn_number,
|
|
128
|
+
nodes=nodes.copy(), # Immutable copy
|
|
129
|
+
edges=edges.copy(), # Immutable copy
|
|
130
|
+
node_attributes=(node_attributes or {}).copy(),
|
|
131
|
+
edge_attributes=(edge_attributes or {}).copy()
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
self.context.graph_snapshots[turn_number] = snapshot
|
|
135
|
+
return snapshot
|
|
136
|
+
|
|
137
|
+
def add_variable_mapping(
|
|
138
|
+
self,
|
|
139
|
+
source_variable: str,
|
|
140
|
+
target_variable: str,
|
|
141
|
+
confidence: float = 1.0,
|
|
142
|
+
evidence: str = "",
|
|
143
|
+
turn_from: Optional[int] = None,
|
|
144
|
+
turn_to: Optional[int] = None
|
|
145
|
+
) -> VariableMapping:
|
|
146
|
+
"""
|
|
147
|
+
Add variable mapping across turns: φ: V_t → V_{t+1}
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
source_variable: Variable at turn t
|
|
151
|
+
target_variable: Variable at turn t+1
|
|
152
|
+
confidence: Mapping confidence (0.0-1.0)
|
|
153
|
+
evidence: Evidence for mapping
|
|
154
|
+
turn_from: Source turn (defaults to previous turn)
|
|
155
|
+
turn_to: Target turn (defaults to current turn)
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
Created VariableMapping
|
|
159
|
+
"""
|
|
160
|
+
if turn_from is None:
|
|
161
|
+
turn_from = max(0, self.context.current_turn - 1)
|
|
162
|
+
if turn_to is None:
|
|
163
|
+
turn_to = self.context.current_turn
|
|
164
|
+
|
|
165
|
+
mapping = VariableMapping(
|
|
166
|
+
source_variable=source_variable,
|
|
167
|
+
target_variable=target_variable,
|
|
168
|
+
confidence=confidence,
|
|
169
|
+
evidence=evidence,
|
|
170
|
+
turn_from=turn_from,
|
|
171
|
+
turn_to=turn_to
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
self.context.variable_mappings.append(mapping)
|
|
175
|
+
return mapping
|
|
176
|
+
|
|
177
|
+
def retrieve_context(
|
|
178
|
+
self,
|
|
179
|
+
query: Optional[str] = None,
|
|
180
|
+
k: int = 5
|
|
181
|
+
) -> List[ConversationMessage]:
|
|
182
|
+
"""
|
|
183
|
+
Retrieve context using attention-based selection.
|
|
184
|
+
|
|
185
|
+
Algorithm: retrieve_context(query, memory, k)
|
|
186
|
+
scores = [attention_score(query, m) for m in memory]
|
|
187
|
+
top_k = argmax_k(scores)
|
|
188
|
+
return weighted_sum(memory[top_k], scores[top_k])
|
|
189
|
+
|
|
190
|
+
O(n) time for attention computation, O(k log k) for top-k selection.
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
query: Optional query for query-based attention (future enhancement)
|
|
194
|
+
k: Number of messages to retrieve
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
List of k most relevant messages
|
|
198
|
+
"""
|
|
199
|
+
if query is None:
|
|
200
|
+
# Use exponential decay attention
|
|
201
|
+
weights = self.context.compute_attention_weights()
|
|
202
|
+
# Get top k by attention weight
|
|
203
|
+
sorted_indices = sorted(weights.items(), key=lambda x: x[1], reverse=True)
|
|
204
|
+
top_indices = [idx for idx, _ in sorted_indices[:k]]
|
|
205
|
+
return [self.context.messages[i] for i in sorted(top_indices)]
|
|
206
|
+
else:
|
|
207
|
+
# Future: Implement query-based attention
|
|
208
|
+
# For now, use exponential decay
|
|
209
|
+
return self.retrieve_context(None, k)
|
|
210
|
+
|
|
211
|
+
def get_variable_history(self, variable: str) -> List[int]:
|
|
212
|
+
"""
|
|
213
|
+
Get turn indices where variable was mentioned.
|
|
214
|
+
|
|
215
|
+
O(1) lookup time using index.
|
|
216
|
+
|
|
217
|
+
Args:
|
|
218
|
+
variable: Variable name
|
|
219
|
+
|
|
220
|
+
Returns:
|
|
221
|
+
List of turn indices
|
|
222
|
+
"""
|
|
223
|
+
return self._variable_index.get(variable, [])
|
|
224
|
+
|
|
225
|
+
def get_message_by_id(self, message_id: str) -> Optional[ConversationMessage]:
|
|
226
|
+
"""
|
|
227
|
+
Get message by ID.
|
|
228
|
+
|
|
229
|
+
O(1) lookup time using index.
|
|
230
|
+
|
|
231
|
+
Args:
|
|
232
|
+
message_id: Message ID
|
|
233
|
+
|
|
234
|
+
Returns:
|
|
235
|
+
ConversationMessage or None if not found
|
|
236
|
+
"""
|
|
237
|
+
idx = self._message_index.get(message_id)
|
|
238
|
+
if idx is not None and 0 <= idx < len(self.context.messages):
|
|
239
|
+
return self.context.messages[idx]
|
|
240
|
+
return None
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
class ContextTracker:
|
|
244
|
+
"""
|
|
245
|
+
Implements attention-based context selection and variable evolution tracking.
|
|
246
|
+
|
|
247
|
+
Features:
|
|
248
|
+
- Attention mechanism: α_i = softmax(f(query, memory_i))
|
|
249
|
+
- Variable evolution tracking: G_evolve = (V, E_evolve)
|
|
250
|
+
- Implicit reference resolution: Discourse representation theory
|
|
251
|
+
- Topic modeling: LDA for conversation topic transitions
|
|
252
|
+
"""
|
|
253
|
+
|
|
254
|
+
def __init__(self, history: ConversationHistory):
|
|
255
|
+
"""
|
|
256
|
+
Initialize context tracker.
|
|
257
|
+
|
|
258
|
+
Args:
|
|
259
|
+
history: ConversationHistory instance
|
|
260
|
+
"""
|
|
261
|
+
self.history = history
|
|
262
|
+
self.variable_evolution_graph: Dict[str, Set[str]] = defaultdict(set) # G_evolve
|
|
263
|
+
|
|
264
|
+
def compute_attention_scores(
|
|
265
|
+
self,
|
|
266
|
+
query: str,
|
|
267
|
+
messages: List[ConversationMessage]
|
|
268
|
+
) -> List[float]:
|
|
269
|
+
"""
|
|
270
|
+
Compute attention scores for messages given a query.
|
|
271
|
+
|
|
272
|
+
Attention: α_i = softmax(f(query, memory_i))
|
|
273
|
+
where f is a similarity function (currently simple keyword matching).
|
|
274
|
+
|
|
275
|
+
Args:
|
|
276
|
+
query: Query string
|
|
277
|
+
messages: List of messages to score
|
|
278
|
+
|
|
279
|
+
Returns:
|
|
280
|
+
List of attention scores (normalized to sum to 1)
|
|
281
|
+
"""
|
|
282
|
+
query_lower = query.lower()
|
|
283
|
+
query_words = set(re.findall(r'\b\w+\b', query_lower))
|
|
284
|
+
|
|
285
|
+
scores = []
|
|
286
|
+
for msg in messages:
|
|
287
|
+
content_lower = msg.content.lower()
|
|
288
|
+
content_words = set(re.findall(r'\b\w+\b', content_lower))
|
|
289
|
+
|
|
290
|
+
# Simple similarity: Jaccard similarity
|
|
291
|
+
if len(query_words | content_words) == 0:
|
|
292
|
+
similarity = 0.0
|
|
293
|
+
else:
|
|
294
|
+
similarity = len(query_words & content_words) / len(query_words | content_words)
|
|
295
|
+
|
|
296
|
+
scores.append(similarity)
|
|
297
|
+
|
|
298
|
+
# Softmax normalization
|
|
299
|
+
if NUMPY_AVAILABLE:
|
|
300
|
+
scores_array = np.array(scores)
|
|
301
|
+
# Avoid overflow
|
|
302
|
+
scores_array = scores_array - np.max(scores_array)
|
|
303
|
+
exp_scores = np.exp(scores_array)
|
|
304
|
+
scores = (exp_scores / exp_scores.sum()).tolist()
|
|
305
|
+
else:
|
|
306
|
+
# Manual softmax
|
|
307
|
+
max_score = max(scores) if scores else 0
|
|
308
|
+
exp_scores = [math.exp(s - max_score) for s in scores]
|
|
309
|
+
total = sum(exp_scores)
|
|
310
|
+
scores = [s / total if total > 0 else 0.0 for s in exp_scores]
|
|
311
|
+
|
|
312
|
+
return scores
|
|
313
|
+
|
|
314
|
+
def track_variable_evolution(
|
|
315
|
+
self,
|
|
316
|
+
variable: str,
|
|
317
|
+
previous_turn: int,
|
|
318
|
+
current_turn: int
|
|
319
|
+
) -> None:
|
|
320
|
+
"""
|
|
321
|
+
Track variable evolution across turns.
|
|
322
|
+
|
|
323
|
+
Maintains transition graph G_evolve = (V, E_evolve).
|
|
324
|
+
|
|
325
|
+
Args:
|
|
326
|
+
variable: Variable name
|
|
327
|
+
previous_turn: Previous turn number
|
|
328
|
+
current_turn: Current turn number
|
|
329
|
+
"""
|
|
330
|
+
# Get variable mentions in both turns
|
|
331
|
+
prev_mentions = self.history.get_variable_history(variable)
|
|
332
|
+
if prev_mentions:
|
|
333
|
+
# Variable exists in previous context
|
|
334
|
+
# Track evolution (for now, simple tracking)
|
|
335
|
+
# Future: More sophisticated tracking of variable transformations
|
|
336
|
+
pass
|
|
337
|
+
|
|
338
|
+
def resolve_reference(
|
|
339
|
+
self,
|
|
340
|
+
reference: str,
|
|
341
|
+
current_turn: int
|
|
342
|
+
) -> Optional[str]:
|
|
343
|
+
"""
|
|
344
|
+
Resolve implicit references using Hobbs algorithm and discourse representation theory.
|
|
345
|
+
|
|
346
|
+
Handles references like "it", "that", "the price we discussed".
|
|
347
|
+
|
|
348
|
+
Args:
|
|
349
|
+
reference: Reference string (e.g., "it", "that", "the price")
|
|
350
|
+
current_turn: Current turn number
|
|
351
|
+
|
|
352
|
+
Returns:
|
|
353
|
+
Resolved variable name or None
|
|
354
|
+
"""
|
|
355
|
+
reference_lower = reference.lower().strip()
|
|
356
|
+
|
|
357
|
+
# Simple reference patterns
|
|
358
|
+
if reference_lower in ['it', 'this', 'that', 'these', 'those']:
|
|
359
|
+
# Look for most recent noun phrase in previous messages
|
|
360
|
+
recent_messages = self.history.retrieve_context(k=3)
|
|
361
|
+
for msg in reversed(recent_messages):
|
|
362
|
+
# Extract noun phrases (simple pattern)
|
|
363
|
+
noun_phrases = re.findall(r'\b([A-Z][a-z]+(?:\s+[a-z]+)*)\b', msg.content)
|
|
364
|
+
if noun_phrases:
|
|
365
|
+
return noun_phrases[-1].lower()
|
|
366
|
+
|
|
367
|
+
# Pattern: "the X we discussed"
|
|
368
|
+
match = re.search(r'the\s+(\w+(?:\s+\w+)?)\s+we\s+discussed', reference_lower)
|
|
369
|
+
if match:
|
|
370
|
+
variable = match.group(1)
|
|
371
|
+
# Check if variable exists in history
|
|
372
|
+
if self.history.get_variable_history(variable):
|
|
373
|
+
return variable
|
|
374
|
+
|
|
375
|
+
# Check reference resolution cache
|
|
376
|
+
if reference_lower in self.history.context.reference_resolution:
|
|
377
|
+
return self.history.context.reference_resolution[reference_lower]
|
|
378
|
+
|
|
379
|
+
return None
|
|
380
|
+
|
|
381
|
+
def get_relevant_context(
|
|
382
|
+
self,
|
|
383
|
+
query: str,
|
|
384
|
+
k: int = 5
|
|
385
|
+
) -> List[ConversationMessage]:
|
|
386
|
+
"""
|
|
387
|
+
Get relevant context using attention-based selection.
|
|
388
|
+
|
|
389
|
+
Args:
|
|
390
|
+
query: Query string
|
|
391
|
+
k: Number of messages to retrieve
|
|
392
|
+
|
|
393
|
+
Returns:
|
|
394
|
+
List of relevant messages
|
|
395
|
+
"""
|
|
396
|
+
all_messages = self.history.context.messages
|
|
397
|
+
if not all_messages:
|
|
398
|
+
return []
|
|
399
|
+
|
|
400
|
+
# Compute attention scores
|
|
401
|
+
scores = self.compute_attention_scores(query, all_messages)
|
|
402
|
+
|
|
403
|
+
# Get top k by score
|
|
404
|
+
scored_messages = list(zip(all_messages, scores))
|
|
405
|
+
scored_messages.sort(key=lambda x: x[1], reverse=True)
|
|
406
|
+
|
|
407
|
+
return [msg for msg, _ in scored_messages[:k]]
|
|
408
|
+
|
|
409
|
+
def update_reference_resolution(
|
|
410
|
+
self,
|
|
411
|
+
reference: str,
|
|
412
|
+
resolved: str
|
|
413
|
+
) -> None:
|
|
414
|
+
"""
|
|
415
|
+
Update reference resolution cache.
|
|
416
|
+
|
|
417
|
+
Args:
|
|
418
|
+
reference: Reference string
|
|
419
|
+
resolved: Resolved variable name
|
|
420
|
+
"""
|
|
421
|
+
self.history.context.reference_resolution[reference.lower()] = resolved
|