cognitive-engine 0.2.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.
- cognitive_engine/__init__.py +7 -0
- cognitive_engine/adapters/__init__.py +2 -0
- cognitive_engine/adapters/plastic_numeric_adapter.py +141 -0
- cognitive_engine/api/__init__.py +2 -0
- cognitive_engine/api/service.py +41 -0
- cognitive_engine/compression/__init__.py +2 -0
- cognitive_engine/compression/knowledge_compressor.py +53 -0
- cognitive_engine/compression/semantic_compressor_v2.py +115 -0
- cognitive_engine/config/__init__.py +2 -0
- cognitive_engine/config/loader.py +44 -0
- cognitive_engine/config/schema.py +45 -0
- cognitive_engine/consolidation/__init__.py +2 -0
- cognitive_engine/consolidation/engine.py +25 -0
- cognitive_engine/consolidation/engine_v2.py +39 -0
- cognitive_engine/context/__init__.py +2 -0
- cognitive_engine/context/long_context.py +64 -0
- cognitive_engine/core/__init__.py +2 -0
- cognitive_engine/core/builder.py +154 -0
- cognitive_engine/core/engine.py +174 -0
- cognitive_engine/core/engine_v2.py +280 -0
- cognitive_engine/core/registry.py +29 -0
- cognitive_engine/core/types.py +346 -0
- cognitive_engine/interfaces/__init__.py +2 -0
- cognitive_engine/interfaces/base.py +181 -0
- cognitive_engine/memory/__init__.py +2 -0
- cognitive_engine/memory/graph_memory.py +165 -0
- cognitive_engine/memory/hybrid_memory.py +110 -0
- cognitive_engine/memory/project_memory.py +80 -0
- cognitive_engine/memory/stores.py +177 -0
- cognitive_engine/memory/vector_store.py +28 -0
- cognitive_engine/models/__init__.py +2 -0
- cognitive_engine/models/stable_core.py +79 -0
- cognitive_engine/modules/__init__.py +2 -0
- cognitive_engine/modules/importance_evaluator.py +96 -0
- cognitive_engine/modules/input_processing.py +78 -0
- cognitive_engine/modules/semantic_understanding.py +130 -0
- cognitive_engine/nlp/__init__.py +16 -0
- cognitive_engine/nlp/models.py +116 -0
- cognitive_engine/nlp/trainer.py +95 -0
- cognitive_engine/replay/__init__.py +2 -0
- cognitive_engine/replay/buffer.py +40 -0
- cognitive_engine/routing/__init__.py +2 -0
- cognitive_engine/routing/dynamic_router.py +45 -0
- cognitive_engine/routing/learned_router.py +165 -0
- cognitive_engine/specialists/__init__.py +2 -0
- cognitive_engine/specialists/runtime.py +97 -0
- cognitive_engine/stability/__init__.py +2 -0
- cognitive_engine/stability/governor.py +38 -0
- cognitive_engine/training/__init__.py +2 -0
- cognitive_engine/training/online_trainer.py +87 -0
- cognitive_engine/utils/__init__.py +2 -0
- cognitive_engine/utils/numeric.py +67 -0
- cognitive_engine/utils/seeding.py +13 -0
- cognitive_engine/utils/telemetry.py +39 -0
- cognitive_engine/utils/text.py +104 -0
- cognitive_engine/utils/visualization.py +87 -0
- cognitive_engine-0.2.0.dist-info/METADATA +91 -0
- cognitive_engine-0.2.0.dist-info/RECORD +60 -0
- cognitive_engine-0.2.0.dist-info/WHEEL +5 -0
- cognitive_engine-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from datetime import datetime, timezone
|
|
5
|
+
from typing import Any, Dict, List, Optional, Sequence, Tuple
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
import torch
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class ProcessedInput:
|
|
13
|
+
raw_input: Any
|
|
14
|
+
modality: str
|
|
15
|
+
normalized_text: str = ""
|
|
16
|
+
tokens: List[str] = field(default_factory=list)
|
|
17
|
+
token_tensor: Optional[torch.Tensor] = None
|
|
18
|
+
attention_mask: Optional[torch.Tensor] = None
|
|
19
|
+
numeric_tensor: Optional[torch.Tensor] = None
|
|
20
|
+
operation: Optional[str] = None
|
|
21
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass
|
|
25
|
+
class SemanticConcept:
|
|
26
|
+
label: str
|
|
27
|
+
weight: float
|
|
28
|
+
source: str
|
|
29
|
+
attributes: Dict[str, Any] = field(default_factory=dict)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass
|
|
33
|
+
class SemanticState:
|
|
34
|
+
raw_input: Any
|
|
35
|
+
modality: str
|
|
36
|
+
sequence_embedding: Optional[torch.Tensor]
|
|
37
|
+
pooled_embedding: torch.Tensor
|
|
38
|
+
intent: str
|
|
39
|
+
entities: List[str]
|
|
40
|
+
concepts: List[SemanticConcept]
|
|
41
|
+
concept_graph_edges: List[Tuple[str, str, float]]
|
|
42
|
+
compressed_context: str
|
|
43
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass
|
|
47
|
+
class ImportanceAssessment:
|
|
48
|
+
novelty: float
|
|
49
|
+
utility: float
|
|
50
|
+
frequency: float
|
|
51
|
+
coherence: float
|
|
52
|
+
correction_signal: float
|
|
53
|
+
redundancy: float
|
|
54
|
+
future_relevance: float
|
|
55
|
+
contradiction_risk: float
|
|
56
|
+
importance_score: float
|
|
57
|
+
confidence_score: float
|
|
58
|
+
learning_priority: float
|
|
59
|
+
action: str
|
|
60
|
+
rationale: str
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@dataclass
|
|
64
|
+
class CompressedKnowledge:
|
|
65
|
+
record_id: str
|
|
66
|
+
source_type: str
|
|
67
|
+
summary: str
|
|
68
|
+
concepts: List[str]
|
|
69
|
+
relations: List[Tuple[str, str, str]]
|
|
70
|
+
embedding: np.ndarray
|
|
71
|
+
importance: float
|
|
72
|
+
confidence: float
|
|
73
|
+
provenance: Dict[str, Any]
|
|
74
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
75
|
+
created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
|
76
|
+
reinforced_count: int = 1
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@dataclass
|
|
80
|
+
class MemoryQuery:
|
|
81
|
+
embedding: np.ndarray
|
|
82
|
+
top_k: int = 5
|
|
83
|
+
modality: Optional[str] = None
|
|
84
|
+
intent: Optional[str] = None
|
|
85
|
+
concepts: List[str] = field(default_factory=list)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@dataclass
|
|
89
|
+
class MemoryBundle:
|
|
90
|
+
short_term: List[CompressedKnowledge] = field(default_factory=list)
|
|
91
|
+
working_memory: Dict[str, Any] = field(default_factory=dict)
|
|
92
|
+
semantic_long_term: List[CompressedKnowledge] = field(default_factory=list)
|
|
93
|
+
episodic: List[CompressedKnowledge] = field(default_factory=list)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@dataclass
|
|
97
|
+
class RoutingDecision:
|
|
98
|
+
active_modules: List[str]
|
|
99
|
+
consult_memories: List[str]
|
|
100
|
+
update_memory: bool
|
|
101
|
+
engage_plasticity: bool
|
|
102
|
+
compute_budget: float
|
|
103
|
+
rationale: str
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@dataclass
|
|
107
|
+
class CoreInference:
|
|
108
|
+
prediction: Any
|
|
109
|
+
confidence: float
|
|
110
|
+
explanation: str
|
|
111
|
+
hidden_state: Optional[torch.Tensor] = None
|
|
112
|
+
artifacts: Dict[str, Any] = field(default_factory=dict)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
@dataclass
|
|
116
|
+
class ReplaySample:
|
|
117
|
+
sample_id: str
|
|
118
|
+
payload: Dict[str, Any]
|
|
119
|
+
target: Any
|
|
120
|
+
priority: float
|
|
121
|
+
timestamp: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
@dataclass
|
|
125
|
+
class TraceEvent:
|
|
126
|
+
stage: str
|
|
127
|
+
message: str
|
|
128
|
+
payload: Dict[str, Any] = field(default_factory=dict)
|
|
129
|
+
timestamp: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@dataclass
|
|
133
|
+
class EngineResponse:
|
|
134
|
+
text: str
|
|
135
|
+
semantic_state: SemanticState
|
|
136
|
+
importance: ImportanceAssessment
|
|
137
|
+
routing: RoutingDecision
|
|
138
|
+
memory_bundle: MemoryBundle
|
|
139
|
+
inference: CoreInference
|
|
140
|
+
traces: List[TraceEvent]
|
|
141
|
+
learning_applied: bool
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
@dataclass
|
|
145
|
+
class NumericBatch:
|
|
146
|
+
features: torch.Tensor
|
|
147
|
+
operation_ids: torch.Tensor
|
|
148
|
+
targets: Optional[torch.Tensor] = None
|
|
149
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
@dataclass
|
|
153
|
+
class TrainingMetrics:
|
|
154
|
+
epoch: int
|
|
155
|
+
loss: float
|
|
156
|
+
mae: float
|
|
157
|
+
accuracy: float
|
|
158
|
+
replay_ratio: float
|
|
159
|
+
plastic_norm: float
|
|
160
|
+
stable_drift: float
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
@dataclass
|
|
164
|
+
class ConsolidationReport:
|
|
165
|
+
merged_records: int
|
|
166
|
+
pruned_records: int
|
|
167
|
+
replay_reweighted: int
|
|
168
|
+
notes: str
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
@dataclass
|
|
172
|
+
class KnowledgeTriple:
|
|
173
|
+
subject: str
|
|
174
|
+
relation: str
|
|
175
|
+
object: str
|
|
176
|
+
confidence: float = 0.7
|
|
177
|
+
evidence: List[str] = field(default_factory=list)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
@dataclass
|
|
181
|
+
class GraphNode:
|
|
182
|
+
node_id: str
|
|
183
|
+
node_type: str
|
|
184
|
+
label: str
|
|
185
|
+
namespace: str = ""
|
|
186
|
+
project_id: str = "global"
|
|
187
|
+
confidence: float = 0.7
|
|
188
|
+
version: int = 1
|
|
189
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
190
|
+
created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
|
191
|
+
valid_from: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
|
192
|
+
valid_to: Optional[datetime] = None
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
@dataclass
|
|
196
|
+
class GraphEdge:
|
|
197
|
+
edge_id: str
|
|
198
|
+
source_id: str
|
|
199
|
+
target_id: str
|
|
200
|
+
relation: str
|
|
201
|
+
weight: float = 1.0
|
|
202
|
+
confidence: float = 0.7
|
|
203
|
+
evidence_ids: List[str] = field(default_factory=list)
|
|
204
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
@dataclass
|
|
208
|
+
class GraphPatch:
|
|
209
|
+
nodes: List[GraphNode] = field(default_factory=list)
|
|
210
|
+
edges: List[GraphEdge] = field(default_factory=list)
|
|
211
|
+
source: str = "unknown"
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
@dataclass
|
|
215
|
+
class GraphQuery:
|
|
216
|
+
seeds: List[str] = field(default_factory=list)
|
|
217
|
+
relation_filter: List[str] = field(default_factory=list)
|
|
218
|
+
project_id: Optional[str] = None
|
|
219
|
+
max_depth: int = 2
|
|
220
|
+
top_k: int = 12
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
@dataclass
|
|
224
|
+
class GraphSubgraph:
|
|
225
|
+
nodes: List[GraphNode] = field(default_factory=list)
|
|
226
|
+
edges: List[GraphEdge] = field(default_factory=list)
|
|
227
|
+
rationale: str = ""
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
@dataclass
|
|
231
|
+
class ProcedureMemory:
|
|
232
|
+
procedure_id: str
|
|
233
|
+
title: str
|
|
234
|
+
steps: List[str]
|
|
235
|
+
domains: List[str]
|
|
236
|
+
confidence: float
|
|
237
|
+
evidence_ids: List[str] = field(default_factory=list)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
@dataclass
|
|
241
|
+
class ProjectMemoryRecord:
|
|
242
|
+
project_id: str
|
|
243
|
+
root_path: str
|
|
244
|
+
files_indexed: int
|
|
245
|
+
modules: List[str]
|
|
246
|
+
dependencies: List[str]
|
|
247
|
+
tests: List[str]
|
|
248
|
+
commands: List[str] = field(default_factory=list)
|
|
249
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
@dataclass
|
|
253
|
+
class PreferenceRecord:
|
|
254
|
+
key: str
|
|
255
|
+
value: str
|
|
256
|
+
confidence: float
|
|
257
|
+
source: str
|
|
258
|
+
updated_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
@dataclass
|
|
262
|
+
class EvidenceRecord:
|
|
263
|
+
evidence_id: str
|
|
264
|
+
source: str
|
|
265
|
+
quote: str
|
|
266
|
+
confidence: float
|
|
267
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
@dataclass
|
|
271
|
+
class SemanticStateV2(SemanticState):
|
|
272
|
+
code_symbols: List[str] = field(default_factory=list)
|
|
273
|
+
graph_candidates: List[GraphPatch] = field(default_factory=list)
|
|
274
|
+
uncertainty: float = 0.0
|
|
275
|
+
modality_features: Dict[str, Any] = field(default_factory=dict)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
@dataclass
|
|
279
|
+
class MemoryQueryV2(MemoryQuery):
|
|
280
|
+
project_id: Optional[str] = None
|
|
281
|
+
include_graph: bool = True
|
|
282
|
+
include_procedures: bool = True
|
|
283
|
+
include_project: bool = True
|
|
284
|
+
include_preferences: bool = True
|
|
285
|
+
graph_query: Optional[GraphQuery] = None
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
@dataclass
|
|
289
|
+
class MemoryBundleV2(MemoryBundle):
|
|
290
|
+
procedural: List[ProcedureMemory] = field(default_factory=list)
|
|
291
|
+
project: List[ProjectMemoryRecord] = field(default_factory=list)
|
|
292
|
+
graph_subgraph: Optional[GraphSubgraph] = None
|
|
293
|
+
preferences: List[PreferenceRecord] = field(default_factory=list)
|
|
294
|
+
evidence: List[EvidenceRecord] = field(default_factory=list)
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
@dataclass
|
|
298
|
+
class RoutingDecisionV2(RoutingDecision):
|
|
299
|
+
selected_specialists: List[str] = field(default_factory=list)
|
|
300
|
+
memory_plan: Dict[str, float] = field(default_factory=dict)
|
|
301
|
+
tool_plan: List[str] = field(default_factory=list)
|
|
302
|
+
context_budget: int = 8192
|
|
303
|
+
learning_action: str = "observe"
|
|
304
|
+
consolidation_action: str = "none"
|
|
305
|
+
confidence: float = 0.5
|
|
306
|
+
gate_scores: Dict[str, float] = field(default_factory=dict)
|
|
307
|
+
fallback_plan: str = "heuristic_router"
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
@dataclass
|
|
311
|
+
class CompressionBundle:
|
|
312
|
+
compressed_knowledge: List[CompressedKnowledge] = field(default_factory=list)
|
|
313
|
+
triples: List[KnowledgeTriple] = field(default_factory=list)
|
|
314
|
+
graph_patch: GraphPatch = field(default_factory=GraphPatch)
|
|
315
|
+
replay_samples: List[ReplaySample] = field(default_factory=list)
|
|
316
|
+
validation_requests: List[str] = field(default_factory=list)
|
|
317
|
+
preferences: List[PreferenceRecord] = field(default_factory=list)
|
|
318
|
+
procedures: List[ProcedureMemory] = field(default_factory=list)
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
@dataclass
|
|
322
|
+
class ContextPackage:
|
|
323
|
+
prompt: str
|
|
324
|
+
evidence_ids: List[str]
|
|
325
|
+
token_estimate: int
|
|
326
|
+
sections: Dict[str, str] = field(default_factory=dict)
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
@dataclass
|
|
330
|
+
class StabilityDecision:
|
|
331
|
+
approved: bool
|
|
332
|
+
confidence: float
|
|
333
|
+
risk_score: float
|
|
334
|
+
reasons: List[str] = field(default_factory=list)
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
@dataclass
|
|
338
|
+
class EngineResponseV2(EngineResponse):
|
|
339
|
+
routing_v2: Optional[RoutingDecisionV2] = None
|
|
340
|
+
memory_bundle_v2: Optional[MemoryBundleV2] = None
|
|
341
|
+
context_package: Optional[ContextPackage] = None
|
|
342
|
+
stability_decision: Optional[StabilityDecision] = None
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
def tensor_to_numpy(tensor: torch.Tensor) -> np.ndarray:
|
|
346
|
+
return tensor.detach().cpu().numpy()
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from typing import Any, Dict, Iterable, List, Optional
|
|
5
|
+
|
|
6
|
+
from cognitive_engine.core.types import (
|
|
7
|
+
CompressedKnowledge,
|
|
8
|
+
ConsolidationReport,
|
|
9
|
+
CoreInference,
|
|
10
|
+
ImportanceAssessment,
|
|
11
|
+
MemoryBundle,
|
|
12
|
+
MemoryQuery,
|
|
13
|
+
NumericBatch,
|
|
14
|
+
ProcessedInput,
|
|
15
|
+
ReplaySample,
|
|
16
|
+
RoutingDecision,
|
|
17
|
+
RoutingDecisionV2,
|
|
18
|
+
SemanticState,
|
|
19
|
+
SemanticStateV2,
|
|
20
|
+
TraceEvent,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ConfigurableComponent(ABC):
|
|
25
|
+
name: str
|
|
26
|
+
|
|
27
|
+
@abstractmethod
|
|
28
|
+
def describe(self) -> Dict[str, Any]:
|
|
29
|
+
raise NotImplementedError
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class InputProcessor(ConfigurableComponent, ABC):
|
|
33
|
+
@abstractmethod
|
|
34
|
+
def supports(self, payload: Any) -> bool:
|
|
35
|
+
raise NotImplementedError
|
|
36
|
+
|
|
37
|
+
@abstractmethod
|
|
38
|
+
def process(self, payload: Any) -> ProcessedInput:
|
|
39
|
+
raise NotImplementedError
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class SemanticEncoder(ConfigurableComponent, ABC):
|
|
43
|
+
@abstractmethod
|
|
44
|
+
def encode(self, processed: ProcessedInput) -> SemanticState:
|
|
45
|
+
raise NotImplementedError
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class ImportanceEvaluator(ConfigurableComponent, ABC):
|
|
49
|
+
@abstractmethod
|
|
50
|
+
def evaluate(self, semantic_state: SemanticState, memory_bundle: MemoryBundle) -> ImportanceAssessment:
|
|
51
|
+
raise NotImplementedError
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class KnowledgeCompressor(ConfigurableComponent, ABC):
|
|
55
|
+
@abstractmethod
|
|
56
|
+
def compress(self, semantic_state: SemanticState, importance: ImportanceAssessment) -> CompressedKnowledge:
|
|
57
|
+
raise NotImplementedError
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class MemoryStore(ConfigurableComponent, ABC):
|
|
61
|
+
@abstractmethod
|
|
62
|
+
def write(self, knowledge: CompressedKnowledge) -> None:
|
|
63
|
+
raise NotImplementedError
|
|
64
|
+
|
|
65
|
+
@abstractmethod
|
|
66
|
+
def search(self, query: MemoryQuery) -> List[CompressedKnowledge]:
|
|
67
|
+
raise NotImplementedError
|
|
68
|
+
|
|
69
|
+
@abstractmethod
|
|
70
|
+
def snapshot(self) -> List[CompressedKnowledge]:
|
|
71
|
+
raise NotImplementedError
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class WorkingMemory(ConfigurableComponent, ABC):
|
|
75
|
+
@abstractmethod
|
|
76
|
+
def update(self, semantic_state: SemanticState) -> Dict[str, Any]:
|
|
77
|
+
raise NotImplementedError
|
|
78
|
+
|
|
79
|
+
@abstractmethod
|
|
80
|
+
def snapshot(self) -> Dict[str, Any]:
|
|
81
|
+
raise NotImplementedError
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class Router(ConfigurableComponent, ABC):
|
|
85
|
+
@abstractmethod
|
|
86
|
+
def route(self, processed: ProcessedInput, semantic_state: Optional[SemanticState] = None) -> RoutingDecision:
|
|
87
|
+
raise NotImplementedError
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class StableCore(ConfigurableComponent, ABC):
|
|
91
|
+
@abstractmethod
|
|
92
|
+
def infer(
|
|
93
|
+
self,
|
|
94
|
+
semantic_state: SemanticState,
|
|
95
|
+
memory_bundle: MemoryBundle,
|
|
96
|
+
routing: RoutingDecision,
|
|
97
|
+
plastic_output: Optional[CoreInference] = None,
|
|
98
|
+
) -> CoreInference:
|
|
99
|
+
raise NotImplementedError
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class PlasticLearner(ConfigurableComponent, ABC):
|
|
103
|
+
@abstractmethod
|
|
104
|
+
def predict(self, semantic_state: SemanticState) -> CoreInference:
|
|
105
|
+
raise NotImplementedError
|
|
106
|
+
|
|
107
|
+
@abstractmethod
|
|
108
|
+
def train_step(self, batch: NumericBatch, replay_batch: Optional[NumericBatch] = None) -> Dict[str, float]:
|
|
109
|
+
raise NotImplementedError
|
|
110
|
+
|
|
111
|
+
@abstractmethod
|
|
112
|
+
def parameter_drift(self) -> float:
|
|
113
|
+
raise NotImplementedError
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class ReplayBuffer(ConfigurableComponent, ABC):
|
|
117
|
+
@abstractmethod
|
|
118
|
+
def add(self, sample: ReplaySample) -> None:
|
|
119
|
+
raise NotImplementedError
|
|
120
|
+
|
|
121
|
+
@abstractmethod
|
|
122
|
+
def sample(self, batch_size: int) -> List[ReplaySample]:
|
|
123
|
+
raise NotImplementedError
|
|
124
|
+
|
|
125
|
+
@abstractmethod
|
|
126
|
+
def __len__(self) -> int:
|
|
127
|
+
raise NotImplementedError
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class Consolidator(ConfigurableComponent, ABC):
|
|
131
|
+
@abstractmethod
|
|
132
|
+
def run(self) -> ConsolidationReport:
|
|
133
|
+
raise NotImplementedError
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class TelemetrySink(ConfigurableComponent, ABC):
|
|
137
|
+
@abstractmethod
|
|
138
|
+
def emit(self, event: TraceEvent) -> None:
|
|
139
|
+
raise NotImplementedError
|
|
140
|
+
|
|
141
|
+
@abstractmethod
|
|
142
|
+
def flush(self) -> None:
|
|
143
|
+
raise NotImplementedError
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class LearnedRouter(Router, ABC):
|
|
147
|
+
@abstractmethod
|
|
148
|
+
def route_v2(self, semantic_state: SemanticStateV2, runtime_context: Dict[str, Any]) -> RoutingDecisionV2:
|
|
149
|
+
raise NotImplementedError
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class GraphMemoryStore(ConfigurableComponent, ABC):
|
|
153
|
+
@abstractmethod
|
|
154
|
+
def apply_patch(self, patch: Any) -> None:
|
|
155
|
+
raise NotImplementedError
|
|
156
|
+
|
|
157
|
+
@abstractmethod
|
|
158
|
+
def query_subgraph(self, query: Any) -> Any:
|
|
159
|
+
raise NotImplementedError
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
class Specialist(ConfigurableComponent, ABC):
|
|
163
|
+
@abstractmethod
|
|
164
|
+
def can_handle(self, semantic_state: SemanticStateV2) -> float:
|
|
165
|
+
raise NotImplementedError
|
|
166
|
+
|
|
167
|
+
@abstractmethod
|
|
168
|
+
def prepare_context(self, semantic_state: SemanticStateV2, memory_bundle: Any) -> Dict[str, Any]:
|
|
169
|
+
raise NotImplementedError
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class LongContextManager(ConfigurableComponent, ABC):
|
|
173
|
+
@abstractmethod
|
|
174
|
+
def compose(self, request: Dict[str, Any]) -> Any:
|
|
175
|
+
raise NotImplementedError
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class StabilityGovernor(ConfigurableComponent, ABC):
|
|
179
|
+
@abstractmethod
|
|
180
|
+
def validate_update(self, update: Dict[str, Any]) -> Any:
|
|
181
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import asdict
|
|
4
|
+
from typing import Any, Dict, List
|
|
5
|
+
from uuid import uuid4
|
|
6
|
+
|
|
7
|
+
import networkx as nx
|
|
8
|
+
|
|
9
|
+
from cognitive_engine.core.types import GraphEdge, GraphNode, GraphPatch, GraphQuery, GraphSubgraph
|
|
10
|
+
from cognitive_engine.interfaces.base import GraphMemoryStore
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class CognitiveGraphMemory(GraphMemoryStore):
|
|
14
|
+
name = "cognitive_graph_memory"
|
|
15
|
+
|
|
16
|
+
def __init__(self) -> None:
|
|
17
|
+
self.graph = nx.MultiDiGraph()
|
|
18
|
+
self.nodes: Dict[str, GraphNode] = {}
|
|
19
|
+
self.edges: Dict[str, GraphEdge] = {}
|
|
20
|
+
self.label_index: Dict[str, str] = {}
|
|
21
|
+
|
|
22
|
+
def describe(self) -> Dict[str, Any]:
|
|
23
|
+
return {"name": self.name, "nodes": len(self.nodes), "edges": len(self.edges)}
|
|
24
|
+
|
|
25
|
+
def upsert_node(
|
|
26
|
+
self,
|
|
27
|
+
label: str,
|
|
28
|
+
node_type: str,
|
|
29
|
+
namespace: str = "",
|
|
30
|
+
project_id: str = "global",
|
|
31
|
+
confidence: float = 0.75,
|
|
32
|
+
metadata: Dict[str, Any] | None = None,
|
|
33
|
+
) -> GraphNode:
|
|
34
|
+
key = self._key(label, node_type, namespace, project_id)
|
|
35
|
+
existing_id = self.label_index.get(key)
|
|
36
|
+
if existing_id:
|
|
37
|
+
node = self.nodes[existing_id]
|
|
38
|
+
node.confidence = max(node.confidence, confidence)
|
|
39
|
+
node.version += 1
|
|
40
|
+
node.metadata.update(metadata or {})
|
|
41
|
+
self.graph.nodes[existing_id].update(asdict(node))
|
|
42
|
+
return node
|
|
43
|
+
|
|
44
|
+
node = GraphNode(
|
|
45
|
+
node_id=str(uuid4()),
|
|
46
|
+
node_type=node_type,
|
|
47
|
+
label=label,
|
|
48
|
+
namespace=namespace,
|
|
49
|
+
project_id=project_id,
|
|
50
|
+
confidence=confidence,
|
|
51
|
+
metadata=metadata or {},
|
|
52
|
+
)
|
|
53
|
+
self.nodes[node.node_id] = node
|
|
54
|
+
self.label_index[key] = node.node_id
|
|
55
|
+
self.graph.add_node(node.node_id, **asdict(node))
|
|
56
|
+
return node
|
|
57
|
+
|
|
58
|
+
def upsert_edge(
|
|
59
|
+
self,
|
|
60
|
+
source: GraphNode,
|
|
61
|
+
target: GraphNode,
|
|
62
|
+
relation: str,
|
|
63
|
+
weight: float = 1.0,
|
|
64
|
+
confidence: float = 0.75,
|
|
65
|
+
evidence_ids: List[str] | None = None,
|
|
66
|
+
metadata: Dict[str, Any] | None = None,
|
|
67
|
+
) -> GraphEdge:
|
|
68
|
+
for edge_id, edge in self.edges.items():
|
|
69
|
+
if edge.source_id == source.node_id and edge.target_id == target.node_id and edge.relation == relation:
|
|
70
|
+
edge.weight = max(edge.weight, weight)
|
|
71
|
+
edge.confidence = max(edge.confidence, confidence)
|
|
72
|
+
edge.evidence_ids = list(dict.fromkeys(edge.evidence_ids + (evidence_ids or [])))
|
|
73
|
+
edge.metadata.update(metadata or {})
|
|
74
|
+
self.graph[source.node_id][target.node_id][edge_id].update(asdict(edge))
|
|
75
|
+
return edge
|
|
76
|
+
|
|
77
|
+
edge = GraphEdge(
|
|
78
|
+
edge_id=str(uuid4()),
|
|
79
|
+
source_id=source.node_id,
|
|
80
|
+
target_id=target.node_id,
|
|
81
|
+
relation=relation,
|
|
82
|
+
weight=weight,
|
|
83
|
+
confidence=confidence,
|
|
84
|
+
evidence_ids=evidence_ids or [],
|
|
85
|
+
metadata=metadata or {},
|
|
86
|
+
)
|
|
87
|
+
self.edges[edge.edge_id] = edge
|
|
88
|
+
self.graph.add_edge(source.node_id, target.node_id, key=edge.edge_id, **asdict(edge))
|
|
89
|
+
return edge
|
|
90
|
+
|
|
91
|
+
def apply_patch(self, patch: GraphPatch) -> None:
|
|
92
|
+
id_map: Dict[str, GraphNode] = {}
|
|
93
|
+
for node in patch.nodes:
|
|
94
|
+
upserted = self.upsert_node(
|
|
95
|
+
label=node.label,
|
|
96
|
+
node_type=node.node_type,
|
|
97
|
+
namespace=node.namespace,
|
|
98
|
+
project_id=node.project_id,
|
|
99
|
+
confidence=node.confidence,
|
|
100
|
+
metadata=node.metadata,
|
|
101
|
+
)
|
|
102
|
+
id_map[node.node_id] = upserted
|
|
103
|
+
for edge in patch.edges:
|
|
104
|
+
source = id_map.get(edge.source_id) or self.nodes.get(edge.source_id)
|
|
105
|
+
target = id_map.get(edge.target_id) or self.nodes.get(edge.target_id)
|
|
106
|
+
if source and target:
|
|
107
|
+
self.upsert_edge(source, target, edge.relation, edge.weight, edge.confidence, edge.evidence_ids, edge.metadata)
|
|
108
|
+
|
|
109
|
+
def query_subgraph(self, query: GraphQuery) -> GraphSubgraph:
|
|
110
|
+
if not self.nodes:
|
|
111
|
+
return GraphSubgraph(rationale="Graph is empty.")
|
|
112
|
+
|
|
113
|
+
seeds = self._resolve_seeds(query)
|
|
114
|
+
visited = set(seeds)
|
|
115
|
+
frontier = set(seeds)
|
|
116
|
+
for _ in range(max(query.max_depth, 0)):
|
|
117
|
+
next_frontier = set()
|
|
118
|
+
for node_id in frontier:
|
|
119
|
+
neighbors = set(self.graph.successors(node_id)) | set(self.graph.predecessors(node_id))
|
|
120
|
+
next_frontier.update(neighbors)
|
|
121
|
+
next_frontier -= visited
|
|
122
|
+
visited.update(next_frontier)
|
|
123
|
+
frontier = next_frontier
|
|
124
|
+
|
|
125
|
+
nodes = [self.nodes[node_id] for node_id in visited if self._matches_project(self.nodes[node_id], query)]
|
|
126
|
+
node_ids = {node.node_id for node in nodes}
|
|
127
|
+
edges = [
|
|
128
|
+
edge
|
|
129
|
+
for edge in self.edges.values()
|
|
130
|
+
if edge.source_id in node_ids
|
|
131
|
+
and edge.target_id in node_ids
|
|
132
|
+
and (not query.relation_filter or edge.relation in query.relation_filter)
|
|
133
|
+
]
|
|
134
|
+
nodes = nodes[: query.top_k]
|
|
135
|
+
node_ids = {node.node_id for node in nodes}
|
|
136
|
+
edges = [edge for edge in edges if edge.source_id in node_ids and edge.target_id in node_ids]
|
|
137
|
+
return GraphSubgraph(nodes=nodes, edges=edges, rationale=f"Expanded {len(seeds)} seed nodes to {len(nodes)} nodes.")
|
|
138
|
+
|
|
139
|
+
def snapshot(self) -> Dict[str, Any]:
|
|
140
|
+
type_counts: Dict[str, int] = {}
|
|
141
|
+
relation_counts: Dict[str, int] = {}
|
|
142
|
+
for node in self.nodes.values():
|
|
143
|
+
type_counts[node.node_type] = type_counts.get(node.node_type, 0) + 1
|
|
144
|
+
for edge in self.edges.values():
|
|
145
|
+
relation_counts[edge.relation] = relation_counts.get(edge.relation, 0) + 1
|
|
146
|
+
return {"nodes": len(self.nodes), "edges": len(self.edges), "node_types": type_counts, "relations": relation_counts}
|
|
147
|
+
|
|
148
|
+
def _resolve_seeds(self, query: GraphQuery) -> List[str]:
|
|
149
|
+
if not query.seeds:
|
|
150
|
+
return list(self.nodes)[: query.top_k]
|
|
151
|
+
resolved = []
|
|
152
|
+
normalized_seeds = [seed.lower() for seed in query.seeds]
|
|
153
|
+
for node_id, node in self.nodes.items():
|
|
154
|
+
label = node.label.lower()
|
|
155
|
+
if any(seed in label or label in seed for seed in normalized_seeds):
|
|
156
|
+
if self._matches_project(node, query):
|
|
157
|
+
resolved.append(node_id)
|
|
158
|
+
return resolved[: query.top_k] or list(self.nodes)[: min(query.top_k, len(self.nodes))]
|
|
159
|
+
|
|
160
|
+
def _matches_project(self, node: GraphNode, query: GraphQuery) -> bool:
|
|
161
|
+
return query.project_id is None or node.project_id in {query.project_id, "global"}
|
|
162
|
+
|
|
163
|
+
def _key(self, label: str, node_type: str, namespace: str, project_id: str) -> str:
|
|
164
|
+
return f"{project_id}:{namespace}:{node_type}:{label}".lower()
|
|
165
|
+
|