pub fn predict(
        &self,
        qa_inputs: &[QaInput],
        top_k: i64,
        batch_size: usize,
    ) -> Vec<Vec<Answer>> {
        let examples: Vec<QaExample> = qa_inputs
            .iter()
            .map(|qa_input| QaExample::new(&qa_input.question, &qa_input.context))
            .collect();
        let features: Vec<QaFeature> = examples
            .iter()
            .enumerate()
            .map(|(example_index, qa_example)| {
                self.generate_features(
                    &qa_example,
                    self.max_seq_len,
                    self.doc_stride,
                    self.max_query_length,
                    example_index as i64,
                )
            })
            .flatten()
            .collect();

        let mut example_top_k_answers_map: HashMap<usize, Vec<Answer>> = HashMap::new();
        let mut start = 0usize;
        let len_features = features.len();

        while start < len_features {
            let end = start + min(len_features - start, batch_size);
            let batch_features = &features[start..end];
            let mut input_ids = Vec::with_capacity(batch_features.len());
            let mut attention_masks = Vec::with_capacity(batch_features.len());
            no_grad(|| {
                for feature in batch_features {
                    input_ids.push(Tensor::of_slice(&feature.input_ids));
                    attention_masks.push(Tensor::of_slice(&feature.attention_mask));
                }

                let input_ids = Tensor::stack(&input_ids, 0).to(self.var_store.device());
                let attention_masks =
                    Tensor::stack(&attention_masks, 0).to(self.var_store.device());

                let (start_logits, end_logits) =
                    self.qa_model
                        .forward_t(Some(input_ids), Some(attention_masks), None, false);

                let start_logits = start_logits.detach();
                let end_logits = end_logits.detach();
                let example_index_to_feature_end_position: Vec<(usize, i64)> = batch_features
                    .iter()
                    .enumerate()
                    .map(|(feature_index, feature)| {
                        (feature.example_index as usize, feature_index as i64 + 1)
                    })
                    .collect();

                let mut feature_id_start = 0;

                for (example_id, max_feature_id) in example_index_to_feature_end_position {
                    let mut answers: Vec<Answer> = vec![];
                    let example = &examples[example_id];
                    for feature_idx in feature_id_start..max_feature_id {
                        let feature = &batch_features[feature_idx as usize];
                        let start = start_logits.get(feature_idx);
                        let end = end_logits.get(feature_idx);
                        let p_mask = (Tensor::of_slice(&feature.p_mask) - 1)
                            .abs()
                            .to_device(start.device());

                        let start: Tensor = start.exp() / start.exp().sum(Float) * &p_mask;
                        let end: Tensor = end.exp() / end.exp().sum(Float) * &p_mask;

                        let (starts, ends, scores) = self.decode(&start, &end, top_k);

                        for idx in 0..starts.len() {
                            let start_pos = feature.token_to_orig_map[&starts[idx]] as usize;
                            let end_pos = feature.token_to_orig_map[&ends[idx]] as usize;
                            let answer = example.doc_tokens[start_pos..end_pos + 1].join(" ");

                            let start = example
                                .char_to_word_offset
                                .iter()
                                .position(|&v| v as usize == start_pos)
                                .unwrap();

                            let end = example
                                .char_to_word_offset
                                .iter()
                                .rposition(|&v| v as usize == end_pos)
                                .unwrap();

                            answers.push(Answer {
                                score: scores[idx],
                                start,
                                end,
                                answer,
                            });
                        }
                    }
                    feature_id_start = max_feature_id;
                    let example_answers = example_top_k_answers_map
                        .entry(example_id)
                        .or_insert(vec![]);
                    example_answers.extend(answers);
                }
            });
            start = end;
        }
        let mut all_answers = vec![];
        for example_id in 0..examples.len() {
            if let Some(answers) = example_top_k_answers_map.get_mut(&example_id) {
                remove_duplicates(answers).sort_by(|a, b| b.score.partial_cmp(&a.score).unwrap());
                all_answers.push(answers[..min(answers.len(), top_k as usize)].to_vec());
            } else {
                all_answers.push(vec![]);
            }
        }
        all_answers
    }
/// Perform extractive question answering given a list of `QaInputs`
///
/// # Arguments
///
/// * `qa_inputs` - `&[QaInput]` Array of Question Answering inputs (context and question pairs)
/// * `top_k` - return the top-k answers for each QaInput. Set to 1 to return only the best answer.
/// * `batch_size` - maximum batch size for the model forward pass.
///
/// # Returns
/// * `Vec<Vec<Answer>>` Vector (same length as `qa_inputs`) of vectors (each of length `top_k`) containing the extracted answers.
///
/// # Example
///
/// ```no_run
/// # fn main() -> anyhow::Result<()> {
/// use rust_bert::pipelines::question_answering::{QaInput, QuestionAnsweringModel};
///
/// let qa_model = QuestionAnsweringModel::new(Default::default())?;
///
/// let question_1 = String::from("Where does Amy live ?");
/// let context_1 = String::from("Amy lives in Amsterdam");
/// let question_2 = String::from("Where does Eric live");
/// let context_2 = String::from("While Amy lives in Amsterdam, Eric is in The Hague.");
///
/// let qa_input_1 = QaInput {
///     question: question_1,
///     context: context_1,
/// };
/// let qa_input_2 = QaInput {
///     question: question_2,
///     context: context_2,
/// };
/// let answers = qa_model.predict(&[qa_input_1, qa_input_2], 1, 32);
///
/// # Ok(())
/// # }
/// ```
Perform extractive question answering given a list of `QaInputs`
Perform extractive question answering given a list of ` QaInputs `
pub fn predict(
        &self,
        qa_inputs: &[QaInput],
        top_k: i64,
        batch_size: usize,
    ) -> Vec<Vec<Answer>> {
        let examples: Vec<QaExample> = qa_inputs
            .iter()
            .map(|qa_input| QaExample::new(&qa_input.question, &qa_input.context))
            .collect();
        let features: Vec<QaFeature> = examples
            .iter()
            .enumerate()
            .map(|(example_index, qa_example)| {
                self.generate_features(
                    &qa_example,
                    self.max_seq_len,
                    self.doc_stride,
                    self.max_query_length,
                    example_index as i64,
                )
            })
            .flatten()
            .collect();
        let mut example_top_k_answers_map: HashMap<usize, Vec<Answer>> = HashMap::new();
        let mut start = 0usize;
        let len_features = features.len();
        while start < len_features {
            let end = start + min(len_features - start, batch_size);
            let batch_features = &features[start..end];
            let mut input_ids = Vec::with_capacity(batch_features.len());
            let mut attention_masks = Vec::with_capacity(batch_features.len());
            no_grad(|| {
                for feature in batch_features {
                    input_ids.push(Tensor::of_slice(&feature.input_ids));
                    attention_masks.push(Tensor::of_slice(&feature.attention_mask));
                }
                let input_ids = Tensor::stack(&input_ids, 0).to(self.var_store.device());
                let attention_masks =
                    Tensor::stack(&attention_masks, 0).to(self.var_store.device());
                let (start_logits, end_logits) =
                    self.qa_model
                        .forward_t(Some(input_ids), Some(attention_masks), None, false);
                let start_logits = start_logits.detach();
                let end_logits = end_logits.detach();
                let example_index_to_feature_end_position: Vec<(usize, i64)> = batch_features
                    .iter()
                    .enumerate()
                    .map(|(feature_index, feature)| {
                        (feature.example_index as usize, feature_index as i64 + 1)
                    })
                    .collect();
                let mut feature_id_start = 0;
                for (example_id, max_feature_id) in example_index_to_feature_end_position {
                    let mut answers: Vec<Answer> = vec![];
                    let example = &examples[example_id];
                    for feature_idx in feature_id_start..max_feature_id {
                        let feature = &batch_features[feature_idx as usize];
                        let start = start_logits.get(feature_idx);
                        let end = end_logits.get(feature_idx);
                        let p_mask = (Tensor::of_slice(&feature.p_mask) - 1)
                            .abs()
                            .to_device(start.device());
                        let start: Tensor = start.exp() / start.exp().sum(Float) * &p_mask;
                        let end: Tensor = end.exp() / end.exp().sum(Float) * &p_mask;
                        let (starts, ends, scores) = self.decode(&start, &end, top_k);
                        for idx in 0..starts.len() {
                            let start_pos = feature.token_to_orig_map[&starts[idx]] as usize;
                            let end_pos = feature.token_to_orig_map[&ends[idx]] as usize;
                            let answer = example.doc_tokens[start_pos..end_pos + 1].join(" ");
                            let start = example
                                .char_to_word_offset
                                .iter()
                                .position(|&v| v as usize == start_pos)
                                .unwrap();
                            let end = example
                                .char_to_word_offset
                                .iter()
                                .rposition(|&v| v as usize == end_pos)
                                .unwrap();
                            answers.push(Answer {
                                score: scores[idx],
                                start,
                                end,
                                answer,
                            });
                        }
                    }
                    feature_id_start = max_feature_id;
                    let example_answers = example_top_k_answers_map
                        .entry(example_id)
                        .or_insert(vec![]);
                    example_answers.extend(answers);
                }
            });
            start = end;
        }
        let mut all_answers = vec![];
        for example_id in 0..examples.len() {
            if let Some(answers) = example_top_k_answers_map.get_mut(&example_id) {
                remove_duplicates(answers).sort_by(|a, b| b.score.partial_cmp(&a.score).unwrap());
                all_answers.push(answers[..min(answers.len(), top_k as usize)].to_vec());
            } else {
                all_answers.push(vec![]);
            }
        }
        all_answers
    }
pub fn predict ( & self , qa_inputs : & [ QaInput ] , top_k : i64 , batch_size : usize , ) -> Vec < Vec < Answer > > { let examples : Vec < QaExample > = qa_inputs . iter ( ) . map ( | qa_input | QaExample :: new ( & qa_input . question , & qa_input . context ) ) . collect ( ) ; let features : Vec < QaFeature > = examples . iter ( ) . enumerate ( ) . map ( | ( example_index , qa_example ) | { self . generate_features ( & qa_example , self . max_seq_len , self . doc_stride , self . max_query_length , example_index as i64 , ) } ) . flatten ( ) . collect ( ) ; let mut example_top_k_answers_map : HashMap < usize , Vec < Answer > > = HashMap :: new ( ) ; let mut start = 0usize ; let len_features = features . len ( ) ; while start < len_features { let end = start + min ( len_features - start , batch_size ) ; let batch_features = & features [ start .. end ] ; let mut input_ids = Vec :: with_capacity ( batch_features . len ( ) ) ; let mut attention_masks = Vec :: with_capacity ( batch_features . len ( ) ) ; no_grad ( | | { for feature in batch_features { input_ids . push ( Tensor :: of_slice ( & feature . input_ids ) ) ; attention_masks . push ( Tensor :: of_slice ( & feature . attention_mask ) ) ; } let input_ids = Tensor :: stack ( & input_ids , 0 ) . to ( self . var_store . device ( ) ) ; let attention_masks = Tensor :: stack ( & attention_masks , 0 ) . to ( self . var_store . device ( ) ) ; let ( start_logits , end_logits ) = self . qa_model . forward_t ( Some ( input_ids ) , Some ( attention_masks ) , None , false ) ; let start_logits = start_logits . detach ( ) ; let end_logits = end_logits . detach ( ) ; let example_index_to_feature_end_position : Vec < ( usize , i64 ) > = batch_features . iter ( ) . enumerate ( ) . map ( | ( feature_index , feature ) | { ( feature . example_index as usize , feature_index as i64 + 1 ) } ) . collect ( ) ; let mut feature_id_start = 0 ; for ( example_id , max_feature_id ) in example_index_to_feature_end_position { let mut answers : Vec < Answer > = vec ! [ ] ; let example = & examples [ example_id ] ; for feature_idx in feature_id_start .. max_feature_id { let feature = & batch_features [ feature_idx as usize ] ; let start = start_logits . get ( feature_idx ) ; let end = end_logits . get ( feature_idx ) ; let p_mask = ( Tensor :: of_slice ( & feature . p_mask ) - 1 ) . abs ( ) . to_device ( start . device ( ) ) ; let start : Tensor = start . exp ( ) / start . exp ( ) . sum ( Float ) * & p_mask ; let end : Tensor = end . exp ( ) / end . exp ( ) . sum ( Float ) * & p_mask ; let ( starts , ends , scores ) = self . decode ( & start , & end , top_k ) ; for idx in 0 .. starts . len ( ) { let start_pos = feature . token_to_orig_map [ & starts [ idx ] ] as usize ; let end_pos = feature . token_to_orig_map [ & ends [ idx ] ] as usize ; let answer = example . doc_tokens [ start_pos .. end_pos + 1 ] . join ( " " ) ; let start = example . char_to_word_offset . iter ( ) . position ( | & v | v as usize == start_pos ) . unwrap ( ) ; let end = example . char_to_word_offset . iter ( ) . rposition ( | & v | v as usize == end_pos ) . unwrap ( ) ; answers . push ( Answer { score : scores [ idx ] , start , end , answer , } ) ; } } feature_id_start = max_feature_id ; let example_answers = example_top_k_answers_map . entry ( example_id ) . or_insert ( vec ! [ ] ) ; example_answers . extend ( answers ) ; } } ) ; start = end ; } let mut all_answers = vec ! [ ] ; for example_id in 0 .. examples . len ( ) { if let Some ( answers ) = example_top_k_answers_map . get_mut ( & example_id ) { remove_duplicates ( answers ) . sort_by ( | a , b | b . score . partial_cmp ( & a . score ) . unwrap ( ) ) ; all_answers . push ( answers [ .. min ( answers . len ( ) , top_k as usize ) ] . to_vec ( ) ) ; } else { all_answers . push ( vec ! [ ] ) ; } } all_answers }
Perform extractive question answering given a list of `QaInputs`
Perform extractive question answering given a list of ` QaInputs `
&self
qa_inputs
&[QaInput]
top_k
i64
batch_size
usize
`Vec>` Vector (same length as `qa_inputs`) of vectors (each of length `top_k`) containing the extracted answers.
` Vec > ` Vector ( same length as ` qa_inputs ` ) of vectors ( each of length ` top_k ` ) containing the extracted answers .
&self
qa_inputs
&[QaInput]
top_k
i64
batch_size
usize
example
None
fn main() -> anyhow::result<()> {
use rust_bert::pipelines::question_answering::{QaInput, QuestionAnsweringModel}.

let qa_model = QuestionAnsweringModel::new(Default::default())?.

let question_1 = String::from("Where does Amy live ?");
let context_1 = String::from("Amy lives in Amsterdam");
let question_2 = String::from("Where does Eric live");
let context_2 = String::from("While Amy lives in Amsterdam, Eric is in The Hague.").

let qa_input_1 = QaInput {
question: question_1,
context: context_1,
};
let qa_input_2 = QaInput {
question: question_2,
context: context_2,
};
let answers = qa_model.predict(&[qa_input_1, qa_input_2], 1, 32).
use rust_bert :: pipelines :: question_answering :: { QaInput QuestionAnsweringModel } . let qa_model = QuestionAnsweringModel :: new ( Default :: default () ) ? . let question_1 = String :: from ( " Where does Amy live ? " ) ; let context_1 = String :: from ( " Amy lives in Amsterdam " ) ; let question_2 = String :: from ( " Where does Eric live " ) ; let context_2 = String :: from ( " While Amy lives in Amsterdam Eric is in The Hague . " ) . let qa_input_1 = QaInput { question : question_1 context : context_1 } ; let qa_input_2 = QaInput { question : question_2 context : context_2 } ; let answers = qa_model . predict ( & [ qa_input_1 qa_input_2 ] 1 32 ) .
ok(())
None
}
None