use crate::config::Florence2Config;
use crate::generate::GenerateConfig;
use crate::postprocess::{Florence2Result, post_process};
use crate::preprocess::preprocess_rgb;
use crate::runner::Florence2Model;
use crate::tokenizer::Florence2Tokenizer;
use anyhow::{Context, Result};
use rlx_runtime::Device;
use std::path::Path;
pub const IMAGE_SIZE: usize = 768;
pub struct Florence2Session {
model: Florence2Model,
tokenizer: Florence2Tokenizer,
image_size: usize,
}
impl Florence2Session {
pub fn from_dir(dir: &Path, device: Device) -> Result<Self> {
let cfg = Florence2Config::from_hf_config_json(&dir.join("config.json"))
.with_context(|| format!("load config from {}", dir.display()))?;
let model = Florence2Model::load(dir, cfg, device)?;
let tokenizer = Florence2Tokenizer::from_file(&dir.join("tokenizer.json"))?;
Ok(Self {
model,
tokenizer,
image_size: IMAGE_SIZE,
})
}
pub fn config(&self) -> &Florence2Config {
self.model.config()
}
pub fn tokenizer(&self) -> &Florence2Tokenizer {
&self.tokenizer
}
pub fn run_tokens(
&mut self,
rgb: &[u8],
in_h: usize,
in_w: usize,
task: &str,
max_new_tokens: usize,
) -> Result<Vec<u32>> {
let pixel = preprocess_rgb(rgb, in_h, in_w, self.image_size);
self.run_pixel_values(&pixel, task, max_new_tokens)
}
pub fn run_pixel_values(
&mut self,
pixel: &[f32],
task: &str,
max_new_tokens: usize,
) -> Result<Vec<u32>> {
let feats = self.model.encode_image(pixel, self.image_size)?;
let input_ids = self.tokenizer.encode_prompt(task)?;
let text = self.model.embed_text(&input_ids);
let merged = self.model.merge_embeds(&feats, &text);
let seq = feats.len() / self.model.config().text.d_model + input_ids.len();
let enc = self.model.encode(&merged, seq)?;
let gcfg = GenerateConfig::from_text(&self.model.config().text, max_new_tokens);
if gcfg.num_beams > 1 {
self.model.generate_beam(&enc, seq, &gcfg)
} else {
self.model.generate_greedy(&enc, seq, &gcfg)
}
}
pub fn run(
&mut self,
rgb: &[u8],
in_h: usize,
in_w: usize,
task: &str,
max_new_tokens: usize,
) -> Result<Florence2Result> {
let ids = self.run_tokens(rgb, in_h, in_w, task, max_new_tokens)?;
post_process(task, &ids, &self.tokenizer, (in_w as f64, in_h as f64))
}
}