ferritin_plms/esm3/tokenization/
sequence.rs1use crate::esm3::utils::constants::{SEQUENCE_BOS_TOKEN, SEQUENCE_EOS_TOKEN, SEQUENCE_VOCAB};
4use std::collections::HashMap;
5
6fn vocab_map() -> HashMap<&'static str, u32> {
7 SEQUENCE_VOCAB
8 .iter()
9 .enumerate()
10 .map(|(i, s)| (*s, i as u32))
11 .collect()
12}
13
14pub fn tokenize_sequence(sequence: &str, add_special_tokens: bool) -> Vec<u32> {
19 let vocab = vocab_map();
20 let unk = *vocab.get("<unk>").unwrap_or(&3);
21
22 let mut tokens = Vec::with_capacity(sequence.len() + 2);
23 if add_special_tokens {
24 tokens.push(SEQUENCE_BOS_TOKEN);
25 }
26 for ch in sequence.chars() {
27 let s = ch.to_string();
28 tokens.push(vocab.get(s.as_str()).copied().unwrap_or(unk));
29 }
30 if add_special_tokens {
31 tokens.push(SEQUENCE_EOS_TOKEN);
32 }
33 tokens
34}
35
36pub fn decode_sequence(token_ids: &[u32]) -> String {
40 const SPECIAL: [u32; 4] = [0, 1, 2, 32];
41 let mut out = String::new();
42 for &id in token_ids {
43 if SPECIAL.contains(&id) {
44 continue;
45 }
46 if let Some(tok) = SEQUENCE_VOCAB.get(id as usize) {
47 out.push_str(tok);
48 }
49 }
50 out
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[test]
58 fn test_tokenize_sequence_no_special() {
59 let ids = tokenize_sequence("MA", false);
60 assert_eq!(ids, vec![20, 5]);
62 }
63
64 #[test]
65 fn test_tokenize_sequence_with_special() {
66 let ids = tokenize_sequence("G", true);
67 assert_eq!(ids[0], SEQUENCE_BOS_TOKEN);
68 assert_eq!(*ids.last().unwrap(), SEQUENCE_EOS_TOKEN);
69 assert_eq!(ids.len(), 3);
70 }
71
72 #[test]
73 fn test_decode_roundtrip() {
74 let seq = "ACDEFGHIKLMNPQRSTVWY";
75 let ids = tokenize_sequence(seq, true);
76 let decoded = decode_sequence(&ids);
77 assert_eq!(decoded, seq);
78 }
79
80 #[test]
81 fn test_unknown_char_maps_to_unk() {
82 let ids = tokenize_sequence("?", false);
83 assert_eq!(ids, vec![3]); }
85}