Skip to content

Commit 094b1e6

Browse files
authored
Update pipeline.py
1 parent 5a46607 commit 094b1e6

1 file changed

Lines changed: 30 additions & 33 deletions

File tree

synapdrive_ai/pipeline.py

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
# synapdrive_ai/pipeline.py
2-
31
from __future__ import annotations
42

5-
from typing import Any, Dict, Optional
63
import random
4+
from typing import Any, Dict, Optional
75

86
from synapdrive_ai.bci.signal_simulator import BrainSignalSimulator
97
from synapdrive_ai.agi.core_reasoning import AGICoreReasoner
@@ -20,53 +18,60 @@ class SynapDrivePipeline:
2018
"""
2119
Canonical end-to-end simulation pipeline.
2220
23-
This is the repo’s single “source of truth” wiring:
24-
input → intent/decoding → optimizer (memory + vision) → safety → actuation → evaluation
21+
Wiring: input → intent → optimizer (memory + vision) → safety → actuation → evaluation
2522
26-
NOTE:
27-
- Simulation-first. No clinical claims.
28-
- Text input path is for “decoded intent” (what a BCI decoder *could* output).
29-
- Signal input path uses the built-in BrainSignalSimulator + AGICoreReasoner.
23+
Args:
24+
simulate_delay: If True, actuation sleeps to emulate real timing.
25+
Set False for tests, replay, and the Flask dashboard.
3026
"""
3127

32-
def __init__(self) -> None:
33-
# Shared components
28+
def __init__(self, simulate_delay: bool = True) -> None:
3429
self.simulator = BrainSignalSimulator()
3530
self.reasoner = AGICoreReasoner()
3631

3732
self.memory = EpisodicMemory()
3833
self.visual = VisualInferenceEngine()
3934

4035
self.optimizer = CognitiveOptimizer()
41-
# Ensure the optimizer uses the SAME memory/vision objects (more credible than duplicates)
36+
# Share the same memory/vision instances so the optimizer sees live state
4237
self.optimizer.memory = self.memory
4338
self.optimizer.visual = self.visual
4439

4540
self.guard = SafetyGuard()
46-
self.router = DecisionRouter()
41+
self.router = DecisionRouter(simulate_delay=simulate_delay)
4742
self.evaluator = MetaEvaluator()
4843

44+
# ------------------------------------------------------------------
45+
# Public entrypoints
46+
# ------------------------------------------------------------------
47+
4948
def run_text_command(self, command_text: str, image_label: Optional[str] = None) -> Dict[str, Any]:
50-
"""
51-
Text pathway = “decoded” intent (BCI output or operator input).
52-
"""
49+
"""Text path: decoded intent or operator input (e.g. 'move left', 'stop')."""
5350
intent_packet = generate_intent(command_text)
54-
return self._run_common(intent_packet, image_label=image_label)
51+
return self.run_intent_packet(intent_packet, image_label=image_label)
5552

5653
def run_signal_event(self, label: Optional[str] = None, image_label: Optional[str] = None) -> Dict[str, Any]:
57-
"""
58-
Signal pathway = simulated EEG-like waveform event.
59-
"""
54+
"""Signal path: simulated EEG-like waveform event."""
6055
label = label or random.choice(["left_arm", "right_arm", "walk", "stop", "calculate", "recall", "explore"])
6156
signal = self._generate_signal_for_label(label)
6257
intent_packet = self.reasoner.receive_signal(label, signal)
63-
return self._run_common(intent_packet, image_label=image_label)
58+
return self.run_intent_packet(intent_packet, image_label=image_label)
6459

65-
def _generate_signal_for_label(self, label: str):
60+
def run_intent_packet(self, intent_packet: Dict[str, Any], image_label: Optional[str] = None) -> Dict[str, Any]:
6661
"""
67-
Uses the same label→frequency mapping as BrainSignalSimulator.emit_event().
68-
We generate directly to keep this method single-step (no subscriber side-effects).
62+
Primary entrypoint for integrations and replay.
63+
Accepts a pre-built intent packet and runs it through the full pipeline.
6964
"""
65+
return self._run_common(intent_packet, image_label=image_label)
66+
67+
def get_action_log(self):
68+
return self.router.get_action_log()
69+
70+
# ------------------------------------------------------------------
71+
# Internals
72+
# ------------------------------------------------------------------
73+
74+
def _generate_signal_for_label(self, label: str):
7075
patterns = {
7176
"left_arm": 10,
7277
"right_arm": 12,
@@ -77,14 +82,10 @@ def _generate_signal_for_label(self, label: str):
7782
"explore": 30,
7883
}
7984
if label not in patterns:
80-
raise ValueError(f"Unknown signal label: {label}")
85+
raise ValueError(f"Unknown signal label: {label!r}. Valid labels: {sorted(patterns)}")
8186
return self.simulator.generate_waveform(patterns[label])
8287

8388
def _run_common(self, intent_packet: Dict[str, Any], image_label: Optional[str]) -> Dict[str, Any]:
84-
"""
85-
Shared pipeline:
86-
optimizer → safety → route/actuate → memory → evaluate
87-
"""
8889
optimized = self.optimizer.optimize(intent_packet, image_label=image_label)
8990

9091
is_safe, reason = self.guard.evaluate_safety(optimized)
@@ -108,7 +109,6 @@ def _run_common(self, intent_packet: Dict[str, Any], image_label: Optional[str])
108109

109110
result = self.router.route(optimized)
110111

111-
# Record episode (keep errors non-fatal — never crash the pipeline because of logging)
112112
try:
113113
self.memory.record_episode(optimized, result)
114114
except Exception:
@@ -122,6 +122,3 @@ def _run_common(self, intent_packet: Dict[str, Any], image_label: Optional[str])
122122
"result": result,
123123
"evaluation": evaluation,
124124
}
125-
126-
def get_action_log(self):
127-
return self.router.get_action_log()

0 commit comments

Comments
 (0)