use super::BoxClient;
use super::Result;
use reqwest;
use reqwest::StatusCode;
use serde_json;
use Error;
use Kind;
pub use self::types::{Choice, Feature, FeatureType, Model, ModelBuilder, ModelOptions, ModelStats};
pub use self::types::{Prediction, PredictionRequest, PredictionResponse, Reward};
use std::io::Write;
use std::collections::HashMap;
use utils::{post_json, delete_with_response, get_json};
use utils::RawBoxResponse;
use suggestionbox::types::{ModelList, PredictionResponseFull};
pub struct Suggestionbox {
url: String,
}
impl Suggestionbox {
pub fn new(url: &str) -> Suggestionbox {
Suggestionbox { url: url.to_owned() }
}
pub fn create_model(&self, model: &Model) -> Result<Model> {
let url = format!("{}/suggestionbox/models", self.url());
let raw = post_json(&url,model)?;
let model:Model = serde_json::from_str(&raw)?;
Ok(model)
}
pub fn delete_model(&self, id: &str) -> Result<()> {
let url = format!("{}/suggestionbox/models/{}", self.url(), id);
let raw = delete_with_response(&url)?;
let raw_response: RawBoxResponse = serde_json::from_str(&raw)?;
raw_response.into()
}
pub fn get_model(&self, id: &str) -> Result<Model> {
let url = format!("{}/suggestionbox/models/{}", self.url(), id);
let raw = get_json(&url)?;
let model: Model = serde_json::from_str(&raw)?;
Ok(model)
}
pub fn list_models(&self) -> Result<Vec<Model>> {
let url = format!("{}/suggestionbox/models", self.url());
let raw = get_json(&url)?;
let models:ModelList = serde_json::from_str(&raw)?;
models.into()
}
pub fn get_model_stats(&self, id: &str) -> Result<ModelStats> {
let url = format!("{}/suggestionbox/models/{}/stats", self.url(), id);
let raw = get_json(&url)?;
let stats: ModelStats = serde_json::from_str(&raw)?;
Ok(stats)
}
pub fn predict(
&self,
model_id: &str,
request: &PredictionRequest,
) -> Result<PredictionResponse> {
let url = format!("{}/suggestionbox/models/{}/predict", self.url(), model_id);
let raw = post_json(&url, request)?;
let predict_response: PredictionResponseFull = serde_json::from_str(&raw)?;
predict_response.into()
}
pub fn reward(&self, model_id: &str, reward_id: &str, weight: f64) -> Result<()> {
let reward = Reward {
reward_id: reward_id.to_owned(),
value: weight,
};
let url = format!("{}/suggestionbox/models/{}/rewards", self.url(), model_id);
let raw = post_json(&url, &reward)?;
let raw_response: RawBoxResponse = serde_json::from_str(&raw)?;
raw_response.into()
}
pub fn download_state<W>(&self, model_id: &str, buf: &mut W) -> Result<u64>
where
W: Write,
{
let url = format!("{}/suggestionbox/state/{}", self.url(), model_id);
let mut resp = reqwest::get(&url)?;
if resp.status() != StatusCode::Ok {
let raw = resp.text()?;
Err(Error {
kind: Kind::Machinebox(format!("HTTP {}: {}", resp.status(), raw)),
})
} else {
let bytecount = resp.copy_to(buf)?;
Ok(bytecount)
}
}
pub fn post_state(&self, source_path: &str) -> Result<Model> {
let url = format!("{}/suggestionbox/state", self.url());
let form = reqwest::multipart::Form::new().file("state", source_path)?;
let client = reqwest::Client::new();
match client.post(&url).multipart(form).send() {
Ok(mut response) => {
let raw = response.text()?;
if response.status() != StatusCode::Ok {
Err(Error {
kind: Kind::Machinebox(format!("HTTP {}: {}", response.status(), raw)),
})
} else {
let model: Model = serde_json::from_str(&raw)?;
Ok(model)
}
}
Err(e) => Err(Error {
kind: Kind::Reqwest(e),
}),
}
}
pub fn post_state_url(&self, state_url: &str) -> Result<Model> {
let url = format!("{}/suggestionbox/state", self.url());
let mut params = HashMap::new();
params.insert("url", state_url);
let client = reqwest::Client::new();
match client.post(&url).form(¶ms).send() {
Ok(mut response) => {
let raw = response.text()?;
if response.status() != StatusCode::Ok {
Err(Error {
kind: Kind::Machinebox(format!("HTTP {}: {}", response.status(), raw)),
})
} else {
let model: Model = serde_json::from_str(&raw)?;
Ok(model)
}
}
Err(e) => Err(Error {
kind: Kind::Reqwest(e),
}),
}
}
}
impl BoxClient for Suggestionbox {
fn url(&self) -> &str {
&self.url
}
}
mod types;
#[cfg(test)]
mod tests;