MCPcopy Create free account
hub / github.com/SHAILAB-IPEC/OpenFly-Platform / ActionTokenizer

Class ActionTokenizer

train/model/action_tokenizer.py:13–72  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

11
12
13class ActionTokenizer:
14 def __init__(
15 self, tokenizer: PreTrainedTokenizerBase, bins: int = 256, min_action: int = -1, max_action: int = 1
16 ) -> None:
17 """
18 Discretizes continuous robot actions into N bins per dimension and maps to the least used tokens.
19
20 NOTE =>> by default, assumes a BPE-style tokenizer akin to the LlamaTokenizer, where *the least used tokens*
21 appear at the end of the vocabulary!
22
23 :param tokenizer: Base LLM/VLM tokenizer to extend.
24 :param bins: Number of bins for each continuous value; we'll adopt a uniform binning strategy.
25 :param min_action: Minimum action value (for clipping, setting lower bound on bin interval).
26 :param max_action: Maximum action value (for clipping, setting upper bound on bin interval).
27 """
28 self.tokenizer, self.n_bins, self.min_action, self.max_action = tokenizer, bins, min_action, max_action
29
30 # Create Uniform Bins + Compute Bin Centers
31 self.bins = np.linspace(min_action, max_action, self.n_bins)
32 self.bin_centers = (self.bins[:-1] + self.bins[1:]) / 2.0
33
34 # [Contract] Set "action_token_begin_idx" based on `self.tokenizer.vocab_size - (self.n_bins + 1)`
35 # =>> Assumes we're always overwriting the final `n_bins` tokens of the vocabulary!
36 self.action_token_begin_idx: int = int(self.tokenizer.vocab_size - (self.n_bins + 1))
37
38 def __call__(self, action: np.ndarray) -> Union[str, List[str]]:
39 """Clip & bin actions to *the last `n_bins` tokens* of the vocabulary (e.g., tokenizer.vocab[-256:])."""
40 action = np.clip(action, a_min=float(self.min_action), a_max=float(self.max_action))
41 discretized_action = np.digitize(action, self.bins)
42
43 # Handle single element vs. batch
44 if len(discretized_action.shape) == 1:
45 return self.tokenizer.decode(list(self.tokenizer.vocab_size - discretized_action))
46 else:
47 return self.tokenizer.batch_decode((self.tokenizer.vocab_size - discretized_action).tolist())
48
49 def decode_token_ids_to_actions(self, action_token_ids: np.ndarray) -> np.ndarray:
50 """
51 Returns continuous actions for discrete action token IDs.
52
53 NOTE =>> Because of the way the actions are discretized w.r.t. the bins (and not the bin centers), the
54 digitization returns bin indices between [1, # bins], inclusive, when there are actually only
55 (# bins - 1) bin intervals.
56
57 Therefore, if the digitization returns the last possible index, we map this to the last bin interval.
58
59 EXAMPLE =>> Let's say self._bins has 256 values. Then self._bin_centers has 255 values. Digitization returns
60 indices between [1, 256]. We subtract 1 from all indices so that they are between [0, 255]. There
61 is still one index (i==255) that would cause an out-of-bounds error if used to index into
62 self._bin_centers. Therefore, if i==255, we subtract 1 from it so that it just becomes the index of
63 the last bin center. We implement this simply via clipping between [0, 255 - 1].
64 """
65 discretized_actions = self.tokenizer.vocab_size - action_token_ids
66 discretized_actions = np.clip(discretized_actions - 1, a_min=0, a_max=self.bin_centers.shape[0] - 1)
67
68 return self.bin_centers[discretized_actions]
69
70 @property

Callers 2

load_vlaFunction · 0.90

Calls

no outgoing calls

Tested by

no test coverage detected