tease 0.5.0

Rapidly prototype interfaces for your machine learning models
Documentation
use tease::{Choice, Input, Output, Teaser, Value};

fn main() -> Result<(), tease::Error> {
    demo().run()
}

fn demo() -> Teaser {
    Teaser::default()
        .with_title("Threshold classifier")
        .with_description(
            "A small rule-based example of labeled choices and multiple typed results.",
        )
        .with_inputs(vec![
            Input::Number {
                label: Some("Score".into()),
                initial_value: 0.7,
                min: Some(0.0),
                max: Some(1.0),
            },
            Input::Dropdown {
                label: Some("Threshold".into()),
                initial_value: 0,
                options: vec![
                    Choice::text("Standard (0.5)", "standard"),
                    Choice::text("Strict (0.8)", "strict"),
                ],
            },
        ])
        .with_outputs(vec![
            Output::text("Class"),
            Output::number("Margin above threshold", 2),
        ])
        .with_predictor(|values| {
            let score = values[0].as_number()?;
            let threshold = match values[1].as_text()? {
                "standard" => 0.5,
                "strict" => 0.8,
                _ => return Err("Unknown threshold.".into()),
            };
            let class = if score >= threshold {
                "Positive"
            } else {
                "Negative"
            };
            Ok(vec![
                Value::Text(class.into()),
                Value::Number(score - threshold),
            ])
        })
}

#[test]
fn choices_change_class_and_margin() {
    let demo = demo().prepare().unwrap();
    let results = demo
        .predict(&[Value::Number(0.7), Value::Text("standard".into())])
        .unwrap();
    assert_eq!(results[0], Value::Text("Positive".into()));
    assert!((results[1].as_number().unwrap() - 0.2).abs() < 1e-12);
    let results = demo
        .predict(&[Value::Number(0.7), Value::Text("strict".into())])
        .unwrap();
    assert_eq!(results[0], Value::Text("Negative".into()));
    assert!(demo
        .predict(&[Value::Number(1.1), Value::Text("strict".into())])
        .is_err());
}