Upload fractus/continuous_engine.py with huggingface_hub
Browse files- fractus/continuous_engine.py +36 -8
fractus/continuous_engine.py
CHANGED
|
@@ -198,12 +198,14 @@ class CTEBlock(nn.Module):
|
|
| 198 |
attn_out = attn_out @ attn.w_out + attn.b_out
|
| 199 |
h = h + attn_out
|
| 200 |
|
| 201 |
-
# Kuramoto
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
self.kuramoto_phases = theta
|
|
|
|
|
|
|
| 207 |
|
| 208 |
# MoE.
|
| 209 |
h_moe = self.norm_moe(h)
|
|
@@ -374,6 +376,32 @@ class ContinuousThoughtEngine(nn.Module):
|
|
| 374 |
f"(now {self.blocks[0].moe.n_experts} experts, dominance was {dominance:.2f})", flush=True)
|
| 375 |
return True
|
| 376 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 377 |
def tick(self, observation: torch.Tensor = None) -> tuple:
|
| 378 |
"""Advance the thought by ONE tick through all blocks.
|
| 379 |
|
|
@@ -457,12 +485,12 @@ class ContinuousThoughtEngine(nn.Module):
|
|
| 457 |
total_lb = torch.tensor(0.0, device=h.device)
|
| 458 |
for blk in self.blocks:
|
| 459 |
h, lb = blk.tick_chunk_core(h)
|
| 460 |
-
total_lb = total_lb + lb
|
| 461 |
self.last_lb_loss = total_lb
|
| 462 |
|
| 463 |
self.thought_state = h[:, -1:, :].detach()
|
| 464 |
last_logits = self.output_head(h[:, -1, :])
|
| 465 |
-
return last_logits
|
| 466 |
|
| 467 |
def think(self, observations: torch.Tensor, max_ticks: int = 10,
|
| 468 |
confidence_threshold: float = 0.7) -> torch.Tensor:
|
|
|
|
| 198 |
attn_out = attn_out @ attn.w_out + attn.b_out
|
| 199 |
h = h + attn_out
|
| 200 |
|
| 201 |
+
# Kuramoto: LEARNED clock (omega/coupling receive gradients).
|
| 202 |
+
# Phase state is still carried; parameters are no longer frozen.
|
| 203 |
+
h_kur = self.norm_kur(h)
|
| 204 |
+
theta = self.kuramoto._encode_from_hidden(h_kur)
|
| 205 |
+
theta = self.kuramoto._rk4_integrate(theta)
|
| 206 |
+
self.kuramoto_phases = theta.detach() # carry state without backprop-through-time explosion
|
| 207 |
+
# Re-attach a differentiable theta for MoE routing so omega/coupling get CE+LB signal
|
| 208 |
+
theta = theta
|
| 209 |
|
| 210 |
# MoE.
|
| 211 |
h_moe = self.norm_moe(h)
|
|
|
|
| 376 |
f"(now {self.blocks[0].moe.n_experts} experts, dominance was {dominance:.2f})", flush=True)
|
| 377 |
return True
|
| 378 |
|
| 379 |
+
|
| 380 |
+
def tick_vec(self, obs_vec: torch.Tensor) -> tuple:
|
| 381 |
+
"""Advance one tick with a precomputed observation vector (B, d_model).
|
| 382 |
+
|
| 383 |
+
Used for vision / multimodal inputs that bypass the token embedding.
|
| 384 |
+
"""
|
| 385 |
+
if obs_vec.dim() == 1:
|
| 386 |
+
obs_vec = obs_vec.unsqueeze(0)
|
| 387 |
+
assert obs_vec.shape[-1] == self.d_model, (obs_vec.shape, self.d_model)
|
| 388 |
+
B = self.thought_state.shape[0]
|
| 389 |
+
if obs_vec.shape[0] != B:
|
| 390 |
+
# broadcast or trim
|
| 391 |
+
obs_vec = obs_vec[:B]
|
| 392 |
+
h = self.thought_state + obs_vec.unsqueeze(1)
|
| 393 |
+
|
| 394 |
+
total_lb = torch.tensor(0.0, device=h.device)
|
| 395 |
+
for blk in self.blocks:
|
| 396 |
+
h, lb = blk.tick_single(h)
|
| 397 |
+
total_lb = total_lb + lb.detach()
|
| 398 |
+
self.last_lb_loss = total_lb
|
| 399 |
+
self._tick_count = getattr(self, '_tick_count', 0) + 1
|
| 400 |
+
self.thought_state = h.detach().clone()
|
| 401 |
+
confidence = torch.sigmoid(self.confidence_head(h[:, 0, :]).squeeze(-1))
|
| 402 |
+
output_logits = self.output_head(h[:, 0, :])
|
| 403 |
+
return output_logits, confidence
|
| 404 |
+
|
| 405 |
def tick(self, observation: torch.Tensor = None) -> tuple:
|
| 406 |
"""Advance the thought by ONE tick through all blocks.
|
| 407 |
|
|
|
|
| 485 |
total_lb = torch.tensor(0.0, device=h.device)
|
| 486 |
for blk in self.blocks:
|
| 487 |
h, lb = blk.tick_chunk_core(h)
|
| 488 |
+
total_lb = total_lb + lb # keep graph — load-balance must train
|
| 489 |
self.last_lb_loss = total_lb
|
| 490 |
|
| 491 |
self.thought_state = h[:, -1:, :].detach()
|
| 492 |
last_logits = self.output_head(h[:, -1, :])
|
| 493 |
+
return last_logits, total_lb
|
| 494 |
|
| 495 |
def think(self, observations: torch.Tensor, max_ticks: int = 10,
|
| 496 |
confidence_threshold: float = 0.7) -> torch.Tensor:
|