rlx_florence2/
generate.rs1use crate::config::Florence2TextConfig;
21use crate::runner::Florence2Model;
22use anyhow::Result;
23
24#[derive(Debug, Clone)]
26pub struct GenerateConfig {
27 pub max_new_tokens: usize,
28 pub num_beams: usize,
29 pub length_penalty: f64,
30 pub early_stopping: bool,
31}
32
33impl GenerateConfig {
34 pub fn from_text(t: &Florence2TextConfig, max_new_tokens: usize) -> Self {
35 Self {
36 max_new_tokens,
37 num_beams: t.num_beams,
38 length_penalty: 1.0,
39 early_stopping: true,
40 }
41 }
42}
43
44fn log_softmax(logits: &[f32]) -> Vec<f32> {
45 let max = logits.iter().cloned().fold(f32::NEG_INFINITY, f32::max);
46 let mut sum = 0f64;
47 for &l in logits {
48 sum += ((l - max) as f64).exp();
49 }
50 let lse = max as f64 + sum.ln();
51 logits.iter().map(|&l| (l as f64 - lse) as f32).collect()
52}
53
54fn apply_processors(
58 logits: &mut [f32],
59 seq: &[u32],
60 cur_len: usize,
61 max_len: usize,
62 t: &Florence2TextConfig,
63 no_repeat_ngram: usize,
64) {
65 if no_repeat_ngram > 0 && seq.len() >= no_repeat_ngram {
67 let n = no_repeat_ngram;
68 let prefix = &seq[seq.len() + 1 - n..]; for i in 0..=seq.len() - n {
70 if seq[i..i + n - 1] == *prefix {
71 let banned = seq[i + n - 1] as usize;
72 if banned < logits.len() {
73 logits[banned] = f32::NEG_INFINITY;
74 }
75 }
76 }
77 }
78 if cur_len == 1 {
80 force_token(logits, t.forced_bos_token_id);
81 }
82 if cur_len == max_len - 1 {
84 force_token(logits, t.forced_eos_token_id);
85 }
86}
87
88fn force_token(logits: &mut [f32], token: u32) {
89 for (i, l) in logits.iter_mut().enumerate() {
90 *l = if i as u32 == token {
91 0.0
92 } else {
93 f32::NEG_INFINITY
94 };
95 }
96}
97
98fn argmax(a: &[f32]) -> u32 {
99 let mut bi = 0u32;
100 let mut bv = f32::NEG_INFINITY;
101 for (i, &v) in a.iter().enumerate() {
102 if v > bv {
103 bv = v;
104 bi = i as u32;
105 }
106 }
107 bi
108}
109
110impl Florence2Model {
111 pub fn generate_greedy(
114 &mut self,
115 encoder_hidden: &[f32],
116 enc_seq: usize,
117 opts: &GenerateConfig,
118 ) -> Result<Vec<u32>> {
119 let t = self.config().text.clone();
120 let max_len = opts.max_new_tokens + 1;
121 let no_ngram = t.no_repeat_ngram_size;
122 let mut seq = vec![t.decoder_start_token_id];
123 while seq.len() < max_len {
124 let mut last = self.decode_logits(&seq, encoder_hidden, enc_seq, max_len)?;
125 apply_processors(&mut last, &seq, seq.len(), max_len, &t, no_ngram);
126 let next = argmax(&last);
127 seq.push(next);
128 if next == t.eos_token_id {
129 break;
130 }
131 }
132 Ok(seq)
133 }
134
135 pub fn generate_beam(
138 &mut self,
139 encoder_hidden: &[f32],
140 enc_seq: usize,
141 opts: &GenerateConfig,
142 ) -> Result<Vec<u32>> {
143 let t = self.config().text.clone();
144 let nb = opts.num_beams.max(1);
145 if nb == 1 {
146 return self.generate_greedy(encoder_hidden, enc_seq, opts);
147 }
148 let max_len = opts.max_new_tokens + 1;
149 let no_ngram = t.no_repeat_ngram_size;
150 let eos = t.eos_token_id;
151
152 let mut beams: Vec<(Vec<u32>, f64)> = vec![(vec![t.decoder_start_token_id], 0.0)];
155 let mut finished: Vec<(Vec<u32>, f64)> = Vec::new();
156
157 for _ in 0..max_len - 1 {
158 let mut cands: Vec<(Vec<u32>, f64)> = Vec::new();
159 for (seq, score) in &beams {
160 let mut last = self.decode_logits(seq, encoder_hidden, enc_seq, max_len)?;
161 apply_processors(&mut last, seq, seq.len(), max_len, &t, no_ngram);
162 let logp = log_softmax(&last);
163 let mut idx: Vec<usize> = (0..logp.len()).collect();
165 idx.select_nth_unstable_by(2 * nb, |&a, &b| logp[b].partial_cmp(&logp[a]).unwrap());
166 for &tok in idx.iter().take(2 * nb) {
167 if logp[tok] == f32::NEG_INFINITY {
168 continue;
169 }
170 let mut ns = seq.clone();
171 ns.push(tok as u32);
172 cands.push((ns, score + logp[tok] as f64));
173 }
174 }
175 cands.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap());
177 let mut next_beams: Vec<(Vec<u32>, f64)> = Vec::new();
178 for (seq, score) in cands {
179 if *seq.last().unwrap() == eos {
180 let norm = score / (seq.len() as f64).powf(opts.length_penalty);
181 finished.push((seq, norm));
182 } else {
183 next_beams.push((seq, score));
184 }
185 if next_beams.len() >= nb {
186 break;
187 }
188 }
189 beams = next_beams;
190 if beams.is_empty() {
191 break;
192 }
193 if opts.early_stopping && finished.len() >= nb {
196 break;
197 }
198 }
199
200 for (seq, score) in beams {
202 let norm = score / (seq.len() as f64).powf(opts.length_penalty);
203 finished.push((seq, norm));
204 }
205 finished.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap());
206 Ok(finished
207 .into_iter()
208 .next()
209 .map(|(s, _)| s)
210 .unwrap_or_default())
211 }
212}