From 880b332822d5fc9868f7d769902a93ede2b25cd0 Mon Sep 17 00:00:00 2001 From: mohit0928 Date: Thu, 16 Jun 2022 08:26:25 +0530 Subject: [PATCH 1/4] updating most_confident_indices --- most_confident_indices/src/lib.rs | 353 ++++++++++-------------------- 1 file changed, 117 insertions(+), 236 deletions(-) diff --git a/most_confident_indices/src/lib.rs b/most_confident_indices/src/lib.rs index 3e033abfb32..17f8b84d731 100644 --- a/most_confident_indices/src/lib.rs +++ b/most_confident_indices/src/lib.rs @@ -1,194 +1,119 @@ -use std::{cmp::Ordering, convert::TryInto, fmt::Display}; +use hotg_rune_proc_blocks::guest::{ + Argument, ArgumentMetadata, ArgumentType, CreateError, Dimensions, + ElementType, InvalidInput, Metadata, ProcBlock, RunError, Tensor, + TensorConstraint, TensorConstraints, TensorMetadata, +}; -use crate::proc_block_v1::*; +use std::{cmp::Ordering, convert::TryInto}; -use hotg_rune_proc_blocks::{ - common, - ndarray::ArrayView1, - runtime_v1::{self, *}, - BufferExt, SliceExt, ValueType, -}; +use hotg_rune_proc_blocks::ndarray::ArrayView1; -wit_bindgen_rust::export!("../wit-files/rune/proc-block-v1.wit"); - -struct ProcBlockV1; - -impl proc_block_v1::ProcBlockV1 for ProcBlockV1 { - fn register_metadata() { - let metadata = - Metadata::new("Most Confident Indices", env!("CARGO_PKG_VERSION")); - metadata.set_description( - "Given some confidence values, create a tensor containing the indices of the top N highest confidences.", - ); - metadata.set_repository(env!("CARGO_PKG_REPOSITORY")); - metadata.set_homepage(env!("CARGO_PKG_HOMEPAGE")); - metadata.add_tag("classify"); - - let count = ArgumentMetadata::new("count"); - count.set_description("The number of indices to return."); - count.set_default_value("1"); - let hint = - runtime_v1::supported_argument_type(ArgumentType::UnsignedInteger); - count.add_hint(&hint); - metadata.add_argument(&count); - - let element_type = ArgumentMetadata::new(common::element_type::NAME); - element_type.set_description(common::element_type::DESCRIPTION); - let hint = runtime_v1::interpret_as_string_in_enum( - common::element_type::NUMERIC, - ); - element_type.add_hint(&hint); - metadata.add_argument(&element_type); - - let input = TensorMetadata::new("confidences"); - input.set_description("A 1D tensor of numeric confidence values."); - let hint = supported_shapes( - &[ - ElementType::U8, - ElementType::I8, - ElementType::U16, - ElementType::I16, - ElementType::U32, - ElementType::I32, - ElementType::F32, - ElementType::U64, - ElementType::I64, - ElementType::F64, - ], - DimensionsParam::Dynamic, - ); - input.add_hint(&hint); - metadata.add_input(&input); - - let output = TensorMetadata::new("indices"); - output - .set_description("The indices, in order of descending confidence."); - let hint = - supported_shapes(&[ElementType::U32], DimensionsParam::Fixed(&[0])); - output.add_hint(&hint); - metadata.add_output(&output); - - register_node(&metadata); - } +hotg_rune_proc_blocks::export_proc_block! { + metadata: metadata, + proc_block: MostConfidentIndices, +} - fn graph(node_id: String) -> Result<(), GraphError> { - let ctx = GraphContext::for_node(&node_id) - .ok_or(GraphError::MissingContext)?; - - let element_type = get_element_type(|n| ctx.get_argument(n)) - .map_err(GraphError::InvalidArgument)?; - let count = get_count(|n| ctx.get_argument(n)) - .map_err(GraphError::InvalidArgument)?; - - ctx.add_input_tensor( - "confidences", - element_type, - DimensionsParam::Dynamic, - ); - ctx.add_output_tensor( - "indices", - element_type, - DimensionsParam::Fixed(&[count]), - ); - - Ok(()) - } +fn metadata() -> Metadata { + Metadata::new("Most Confident Indices", env!("CARGO_PKG_VERSION")) + .with_description( + "Given some confidence values, create a tensor containing the indices of the top N highest confidences.", + ) + .with_repository(env!("CARGO_PKG_REPOSITORY")) + .with_homepage(env!("CARGO_PKG_HOMEPAGE")) + .with_tag("classify") + .with_tag("confidence") + .with_argument(ArgumentMetadata::new("count") + .with_default_value("1") + .with_description("The number of indices to return") + .with_hint(ArgumentType::Float)) + .with_input(TensorMetadata::new("confidences").with_description("A 1D tensor of numeric confidence values.")) + .with_output( + TensorMetadata::new("indices") + .with_description("The indices, in order of descending confidence."), + ) +} - fn kernel(node_id: String) -> Result<(), KernelError> { - let ctx = KernelContext::for_node(&node_id) - .ok_or(KernelError::MissingContext)?; +struct MostConfidentIndices { + count: u32, +} - let count = get_count(|n| ctx.get_argument(n)) - .map_err(KernelError::InvalidArgument)?; +impl ProcBlock for MostConfidentIndices { + fn tensor_constraints(&self) -> TensorConstraints { + let count = 1 as u32; // todo: replace with actual arguements passed by user - let TensorResult { - element_type, - dimensions, - buffer, - } = ctx.get_input_tensor("input").ok_or_else(|| { - KernelError::InvalidInput(InvalidInput { - name: "indices".to_string(), - reason: BadInputReason::NotFound, - }) - })?; + TensorConstraints { + inputs: vec![TensorConstraint::numeric( + "confidences", + Dimensions::Dynamic, + )], + outputs: vec![TensorConstraint::numeric("indices", vec![count])], + } + } + + fn run(&self, inputs: Vec) -> Result, RunError> { + let tensor = Tensor::get_named(&inputs, "confidences")?; - let count = count as usize; + let count = 1 as usize; // todo: replace with actual arguements passed by user - let indices = match element_type { - ElementType::U8 => preprocess_buffer::(&buffer, &dimensions) + let indices = match tensor.element_type { + ElementType::U8 => preprocess_buffer::(tensor) .and_then(|t| most_confident_indices(t, count))?, - ElementType::I8 => preprocess_buffer::(&buffer, &dimensions) + ElementType::I8 => preprocess_buffer::(tensor) .and_then(|t| most_confident_indices(t, count))?, - ElementType::U16 => preprocess_buffer::(&buffer, &dimensions) + ElementType::U16 => preprocess_buffer::(tensor) .and_then(|t| most_confident_indices(t, count))?, - ElementType::I16 => preprocess_buffer::(&buffer, &dimensions) + ElementType::I16 => preprocess_buffer::(&tensor) .and_then(|t| most_confident_indices(t, count))?, - ElementType::U32 => preprocess_buffer::(&buffer, &dimensions) + ElementType::U32 => preprocess_buffer::(tensor) .and_then(|t| most_confident_indices(t, count))?, - ElementType::I32 => preprocess_buffer::(&buffer, &dimensions) + ElementType::I32 => preprocess_buffer::(tensor) .and_then(|t| most_confident_indices(t, count))?, - ElementType::F32 => preprocess_buffer::(&buffer, &dimensions) + ElementType::F32 => preprocess_buffer::(tensor) .and_then(|t| most_confident_indices(t, count))?, - ElementType::U64 => preprocess_buffer::(&buffer, &dimensions) + ElementType::U64 => preprocess_buffer::(tensor) .and_then(|t| most_confident_indices(t, count))?, - ElementType::I64 => preprocess_buffer::(&buffer, &dimensions) + ElementType::I64 => preprocess_buffer::(tensor) .and_then(|t| most_confident_indices(t, count))?, - ElementType::F64 => preprocess_buffer::(&buffer, &dimensions) + ElementType::F64 => preprocess_buffer::(tensor) .and_then(|t| most_confident_indices(t, count))?, - ElementType::Utf8 => { - unreachable!("Already checked by get_element_type()") + _ => { + return Err(InvalidInput::incompatible_element_type( + &tensor.name, + ) + .into()); }, }; - ctx.set_output_tensor( - "indices", - TensorParam { - dimensions: &dimensions, - element_type: ElementType::U32, - buffer: indices.as_bytes(), - }, - ); - - Ok(()) + Ok(vec![Tensor::new_1d("indices", &indices.to_vec())]) } } -fn preprocess_buffer<'buf, T>( - buffer: &'buf [u8], - dimensions: &[u32], -) -> Result, KernelError> -where - T: ValueType, -{ +fn preprocess_buffer< + 'buf, + T: hotg_rune_proc_blocks::guest::PrimitiveTensorElement, +>( + buffer: &Tensor, +) -> Result, RunError> { + buffer - .view::(dimensions) - .and_then(|t| t.into_dimensionality()) - .map_err(|e| { - KernelError::InvalidInput(InvalidInput::invalid_value( - "confidences", - e, - )) - }) + .view::().unwrap().and_then(|t| Ok(t.into_dimensionality())) + .map_err(|e| RunError::other(format!("Invalid input: {}", e))).unwrap() } + fn most_confident_indices( tensor: ArrayView1, count: usize, -) -> Result, KernelError> +) -> Result, RunError> where T: PartialOrd + Copy, { if count > tensor.len() { - return Err(KernelError::InvalidArgument( - InvalidArgument::invalid_value( - "count", - format!( - "Requesting {} indices from a tensor with only {} elements", - count, - tensor.len() - ), - ), - )); + return Err(RunError::other(format!( + "Requesting {} indices from a tensor with only {} elements", + count, + tensor.len() + ))); } let mut indices_and_confidence: Vec<_> = @@ -204,100 +129,56 @@ where .collect()) } -fn get_count( - get_argument: impl FnOnce(&str) -> Option, -) -> Result { - get_argument("count") - .ok_or_else(|| InvalidArgument::not_found("count"))? - .parse::() - .map_err(|e| InvalidArgument::invalid_value("count", e)) -} +impl TryFrom> for MostConfidentIndices { + type Error = CreateError; -fn get_element_type( - get_argument: impl FnOnce(&str) -> Option, -) -> Result { - match get_argument("element_type").as_deref() { - Some("u8") => Ok(ElementType::U8), - Some("i8") => Ok(ElementType::I8), - Some("u16") => Ok(ElementType::U16), - Some("i16") => Ok(ElementType::I16), - Some("u32") => Ok(ElementType::U32), - Some("i32") => Ok(ElementType::I32), - Some("f32") => Ok(ElementType::F32), - Some("u64") => Ok(ElementType::U64), - Some("i64") => Ok(ElementType::I64), - Some("f64") => Ok(ElementType::F64), - Some(other) => Err(InvalidArgument::invalid_value( - "element_type", - format!("Unsupported element type: {}", other), - )), - None => Err(InvalidArgument::not_found("element_type")), - } -} + fn try_from(args: Vec) -> Result { + let count = + hotg_rune_proc_blocks::guest::parse::optional_arg(&args, "count")? + .unwrap_or(1); -impl InvalidArgument { - fn not_found(name: impl Into) -> Self { - InvalidArgument { - name: name.into(), - reason: BadArgumentReason::NotFound, - } - } - - fn invalid_value(name: impl Into, reason: impl Display) -> Self { - InvalidArgument { - name: name.into(), - reason: BadArgumentReason::InvalidValue(reason.to_string()), - } + Ok(MostConfidentIndices { count }) } } -impl InvalidInput { - fn invalid_value(name: impl Into, reason: impl Display) -> Self { - InvalidInput { - name: name.into(), - reason: BadInputReason::InvalidValue(reason.to_string()), - } - } -} +// #[cfg(test)] +// mod tests { +// use super::*; +// use hotg_rune_proc_blocks::ndarray; -#[cfg(test)] -mod tests { - use super::*; - use hotg_rune_proc_blocks::ndarray; +// #[test] +// fn only_works_with_1d() { +// let buffer = [1, 2, 3, 4, 5, 6]; - #[test] - fn only_works_with_1d() { - let buffer = [1, 2, 3, 4, 5, 6]; +// let error = preprocess_buffer::(&buffer).unwrap_err(); - let error = preprocess_buffer::(&buffer, &[2, 3]).unwrap_err(); - - assert!(matches!(error, KernelError::InvalidInput(_))); - } +// assert!(matches!(error, RunError::InvalidInput(_))); +// } - #[test] - fn tensors_equivalent_to_1d_are_okay_too() { - let buffer = [1, 2, 3, 4, 5, 6]; +// #[test] +// fn tensors_equivalent_to_1d_are_okay_too() { +// let buffer = [1, 2, 3, 4, 5, 6]; - let error = preprocess_buffer::(&buffer, &[1, 6, 1]).unwrap_err(); +// let error = preprocess_buffer::(&buffer).unwrap_err(); - assert!(matches!(error, KernelError::InvalidInput(_))); - } +// assert!(matches!(error, RunError::InvalidInput(_))); +// } - #[test] - fn count_must_be_less_than_input_size() { - let input = ndarray::arr1(&[1_u32, 2, 3]); +// #[test] +// fn count_must_be_less_than_input_size() { +// let input = ndarray::arr1(&[1_u32, 2, 3]); - let error = most_confident_indices(input.view(), 42).unwrap_err(); +// let error = most_confident_indices(input.view(), 42).unwrap_err(); - assert!(matches!(error, KernelError::InvalidArgument(_))); - } +// assert!(matches!(error, RunError::InvalidArgument(_))); +// } - #[test] - fn get_top_3_values() { - let elements = ndarray::arr1(&[0.0, 0.5, 10.0, 3.5, -200.0]); +// #[test] +// fn get_top_3_values() { +// let elements = ndarray::arr1(&[0.0, 0.5, 10.0, 3.5, -200.0]); - let got = most_confident_indices(elements.view(), 3).unwrap(); +// let got = most_confident_indices(elements.view(), 3).unwrap(); - assert_eq!(got, &[2, 3, 1]); - } -} +// assert_eq!(got, &[2, 3, 1]); +// } +// } From f5f4ac3d14f93bb8c617482b969c913dd403f250 Mon Sep 17 00:00:00 2001 From: mohit0928 Date: Thu, 16 Jun 2022 08:42:38 +0530 Subject: [PATCH 2/4] removed into_dimensionality --- most_confident_indices/src/lib.rs | 52 +++++++++++++------------------ 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/most_confident_indices/src/lib.rs b/most_confident_indices/src/lib.rs index 17f8b84d731..24db6437203 100644 --- a/most_confident_indices/src/lib.rs +++ b/most_confident_indices/src/lib.rs @@ -56,29 +56,19 @@ impl ProcBlock for MostConfidentIndices { let count = 1 as usize; // todo: replace with actual arguements passed by user let indices = match tensor.element_type { - ElementType::U8 => preprocess_buffer::(tensor) - .and_then(|t| most_confident_indices(t, count))?, - ElementType::I8 => preprocess_buffer::(tensor) - .and_then(|t| most_confident_indices(t, count))?, - ElementType::U16 => preprocess_buffer::(tensor) - .and_then(|t| most_confident_indices(t, count))?, - ElementType::I16 => preprocess_buffer::(&tensor) - .and_then(|t| most_confident_indices(t, count))?, - ElementType::U32 => preprocess_buffer::(tensor) - .and_then(|t| most_confident_indices(t, count))?, - ElementType::I32 => preprocess_buffer::(tensor) - .and_then(|t| most_confident_indices(t, count))?, - ElementType::F32 => preprocess_buffer::(tensor) - .and_then(|t| most_confident_indices(t, count))?, - ElementType::U64 => preprocess_buffer::(tensor) - .and_then(|t| most_confident_indices(t, count))?, - ElementType::I64 => preprocess_buffer::(tensor) - .and_then(|t| most_confident_indices(t, count))?, - ElementType::F64 => preprocess_buffer::(tensor) - .and_then(|t| most_confident_indices(t, count))?, + ElementType::U8 => most_confident_indices(tensor.view_1d::()?, count)?, + ElementType::I8 => most_confident_indices(tensor.view_1d::()?, count)?, + ElementType::U16 => most_confident_indices(tensor.view_1d::()?, count)?, + ElementType::I16 =>most_confident_indices(tensor.view_1d::()?, count)?, + ElementType::U32 => most_confident_indices(tensor.view_1d::()?, count)?, + ElementType::I32 => most_confident_indices(tensor.view_1d::()?, count)?, + ElementType::F32 => most_confident_indices(tensor.view_1d::()?, count)?, + ElementType::U64 => most_confident_indices(tensor.view_1d::()?, count)?, + ElementType::I64 => most_confident_indices(tensor.view_1d::()?, count)?, + ElementType::F64 => most_confident_indices(tensor.view_1d::()?, count)?, _ => { return Err(InvalidInput::incompatible_element_type( - &tensor.name, + "confidences", ) .into()); }, @@ -88,17 +78,17 @@ impl ProcBlock for MostConfidentIndices { } } -fn preprocess_buffer< - 'buf, - T: hotg_rune_proc_blocks::guest::PrimitiveTensorElement, ->( - buffer: &Tensor, -) -> Result, RunError> { +// fn preprocess_buffer< +// 'buf, +// T: hotg_rune_proc_blocks::guest::PrimitiveTensorElement, +// >( +// buffer: &Tensor, +// ) -> Result, RunError> { - buffer - .view::().unwrap().and_then(|t| Ok(t.into_dimensionality())) - .map_err(|e| RunError::other(format!("Invalid input: {}", e))).unwrap() -} +// buffer +// .view::().unwrap().and_then(|t| Ok(t.into_dimensionality())) +// .map_err(|e| RunError::other(format!("Invalid input: {}", e))).unwrap() +// } fn most_confident_indices( From c4e41406fdcc211f287e7fba8ff40d5ec0740758 Mon Sep 17 00:00:00 2001 From: mohit0928 Date: Thu, 16 Jun 2022 11:10:04 +0530 Subject: [PATCH 3/4] working on getting argument --- most_confident_indices/src/lib.rs | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/most_confident_indices/src/lib.rs b/most_confident_indices/src/lib.rs index 24db6437203..9479e7d2bb7 100644 --- a/most_confident_indices/src/lib.rs +++ b/most_confident_indices/src/lib.rs @@ -1,7 +1,7 @@ use hotg_rune_proc_blocks::guest::{ Argument, ArgumentMetadata, ArgumentType, CreateError, Dimensions, ElementType, InvalidInput, Metadata, ProcBlock, RunError, Tensor, - TensorConstraint, TensorConstraints, TensorMetadata, + TensorConstraint, TensorConstraints, TensorMetadata, parse }; use std::{cmp::Ordering, convert::TryInto}; @@ -39,6 +39,7 @@ struct MostConfidentIndices { impl ProcBlock for MostConfidentIndices { fn tensor_constraints(&self) -> TensorConstraints { + let count = 1 as u32; // todo: replace with actual arguements passed by user TensorConstraints { @@ -53,7 +54,7 @@ impl ProcBlock for MostConfidentIndices { fn run(&self, inputs: Vec) -> Result, RunError> { let tensor = Tensor::get_named(&inputs, "confidences")?; - let count = 1 as usize; // todo: replace with actual arguements passed by user + let count = parse::required_arg(args, "count").unwrap(); // todo: replace with actual arguements passed by user let indices = match tensor.element_type { ElementType::U8 => most_confident_indices(tensor.view_1d::()?, count)?, @@ -78,18 +79,6 @@ impl ProcBlock for MostConfidentIndices { } } -// fn preprocess_buffer< -// 'buf, -// T: hotg_rune_proc_blocks::guest::PrimitiveTensorElement, -// >( -// buffer: &Tensor, -// ) -> Result, RunError> { - -// buffer -// .view::().unwrap().and_then(|t| Ok(t.into_dimensionality())) -// .map_err(|e| RunError::other(format!("Invalid input: {}", e))).unwrap() -// } - fn most_confident_indices( tensor: ArrayView1, From 530381047c152b132732416cda21ac21d71417c4 Mon Sep 17 00:00:00 2001 From: mohit0928 Date: Thu, 16 Jun 2022 11:36:39 +0530 Subject: [PATCH 4/4] failing tests for 1-d array with shape [1,n] --- most_confident_indices/src/lib.rs | 62 ++++++++++++++----------------- 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/most_confident_indices/src/lib.rs b/most_confident_indices/src/lib.rs index 9479e7d2bb7..20afca83dc4 100644 --- a/most_confident_indices/src/lib.rs +++ b/most_confident_indices/src/lib.rs @@ -39,8 +39,8 @@ struct MostConfidentIndices { impl ProcBlock for MostConfidentIndices { fn tensor_constraints(&self) -> TensorConstraints { - - let count = 1 as u32; // todo: replace with actual arguements passed by user + + let count = parse::required_arg(&vec![Argument{ name: "count".to_string(), value: self.count.to_string() }], "count").unwrap(); TensorConstraints { inputs: vec![TensorConstraint::numeric( @@ -54,7 +54,7 @@ impl ProcBlock for MostConfidentIndices { fn run(&self, inputs: Vec) -> Result, RunError> { let tensor = Tensor::get_named(&inputs, "confidences")?; - let count = parse::required_arg(args, "count").unwrap(); // todo: replace with actual arguements passed by user + let count = parse::required_arg(&vec![Argument{ name: "count".to_string(), value: self.count.to_string() }], "count").unwrap(); let indices = match tensor.element_type { ElementType::U8 => most_confident_indices(tensor.view_1d::()?, count)?, @@ -120,44 +120,38 @@ impl TryFrom> for MostConfidentIndices { } } -// #[cfg(test)] -// mod tests { -// use super::*; -// use hotg_rune_proc_blocks::ndarray; - -// #[test] -// fn only_works_with_1d() { -// let buffer = [1, 2, 3, 4, 5, 6]; +#[cfg(test)] +mod tests { + use super::*; + use hotg_rune_proc_blocks::ndarray; -// let error = preprocess_buffer::(&buffer).unwrap_err(); + #[test] + fn get_top_3_values_from_2_d() { + let elements = ndarray::arr2(&[[0.0, 0.5, 10.0, 3.5, -200.0]]); -// assert!(matches!(error, RunError::InvalidInput(_))); -// } + let tensor = Tensor::new("confidences", &elements); + -// #[test] -// fn tensors_equivalent_to_1d_are_okay_too() { -// let buffer = [1, 2, 3, 4, 5, 6]; + let got = most_confident_indices(tensor.view_1d::().unwrap(), 3).unwrap(); -// let error = preprocess_buffer::(&buffer).unwrap_err(); - -// assert!(matches!(error, RunError::InvalidInput(_))); -// } + assert_eq!(got, &[2, 3, 1]); + } -// #[test] -// fn count_must_be_less_than_input_size() { -// let input = ndarray::arr1(&[1_u32, 2, 3]); + #[test] + fn count_must_be_less_than_input_size() { + let input = ndarray::arr1(&[1_u32, 2, 3]); -// let error = most_confident_indices(input.view(), 42).unwrap_err(); + most_confident_indices(input.view(), 42).unwrap_err(); -// assert!(matches!(error, RunError::InvalidArgument(_))); -// } + // assert!(matches!(error, RunError)); + } -// #[test] -// fn get_top_3_values() { -// let elements = ndarray::arr1(&[0.0, 0.5, 10.0, 3.5, -200.0]); + #[test] + fn get_top_3_values() { + let elements = ndarray::arr1(&[0.0, 0.5, 10.0, 3.5, -200.0]); -// let got = most_confident_indices(elements.view(), 3).unwrap(); + let got = most_confident_indices(elements.view(), 3).unwrap(); -// assert_eq!(got, &[2, 3, 1]); -// } -// } + assert_eq!(got, &[2, 3, 1]); + } +}