close the RECAP critic-policy loop

This commit is contained in:
seeker
2026-07-12 19:33:15 +08:00
parent 53ef020b46
commit bd88a46b23
13 changed files with 780 additions and 314 deletions
+31 -6
View File
@@ -191,15 +191,18 @@ class MiniTokenizer:
parts.append(query)
return torch.cat(parts)
def build_value_input(self, history_xy: Tensor, metadata: str | None = None) -> Tensor:
"""Return image marker plus discretized state, without policy query tokens."""
def build_value_input(self, history_xy: Tensor) -> Tensor:
"""Return observation tokens for the critic without outcome metadata.
RECAP's value function estimates ``V(o, task)``. Experience provenance
and success/failure labels are training targets, not observable inputs;
including them would let the critic solve the toy buffer by leakage.
The single-task minimal experiment keeps the task command implicit.
"""
coordinate_tokens = self.coordinates.encode(history_xy).reshape(-1).cpu()
specials = torch.tensor([self.BOS, self.IMAGE, self.STATE], dtype=torch.long)
parts = [specials, coordinate_tokens]
metadata_token = self.encode_metadata(metadata)
if metadata_token is not None: parts.append(metadata_token.reshape(1))
return torch.cat(parts)
return torch.cat((specials, coordinate_tokens))
# Backward-compatible name used by the pi0.5 data utilities.
build_prefix = build_observation
@@ -216,6 +219,28 @@ class MiniTokenizer:
return None
raise ValueError("advantage must be positive, negative, omitted, bool, or None")
def build_subtask_query(self, history_xy: Tensor) -> Tensor:
"""Observation prefix whose final token predicts the next subtask."""
return self.build_observation(history_xy, metadata=None)
def build_action_condition(
self,
history_xy: Tensor,
subtask_token: int | Tensor,
advantage: Advantage | bool | None,
) -> Tensor:
"""Build the inference prefix ``observation -> subtask -> advantage``."""
pieces = [
self.build_observation(history_xy, metadata=None),
torch.as_tensor(subtask_token, dtype=torch.long).reshape(1).cpu(),
]
advantage_token = self.encode_advantage(advantage)
if advantage_token is not None:
pieces.append(advantage_token.reshape(1))
return torch.cat(pieces)
@staticmethod
def _orthonormal_dct_matrix(
horizon: int, *, device: torch.device, dtype: torch.dtype