use rig_core::completion::Cost;
use rig_core::json_utils::Lenient;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_json::Value;
use std::collections::BTreeMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Request {
pub state: Value,
pub questions: Box<serde_json::value::RawValue>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "lowercase")]
pub enum Question {
Choice {
instructions: Value,
criteria: BTreeMap<String, Option<Value>>,
},
Score {
instructions: Value,
criteria: Vec<Value>,
},
Noul {
instructions: Value,
#[serde(skip_serializing_if = "Option::is_none")]
criteria: Option<BTreeMap<String, Value>>,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "lowercase")]
pub enum Answer {
Choice {
choice: String,
probabilities: BTreeMap<String, f64>,
confidence: f64,
},
Score {
score: f64,
probabilities: BTreeMap<String, f64>,
legend: BTreeMap<String, Value>,
confidence: f64,
},
Noul {
noul: f64,
},
}
pub use rig_core::completion::Usage;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Response {
pub model: String,
pub answers: Box<serde_json::value::RawValue>,
#[serde(
default,
deserialize_with = "reported_usage",
serialize_with = "jev_usage"
)]
pub usage: Option<Usage>,
#[serde(skip)]
pub provider_request_id: Option<String>,
#[serde(skip)]
pub raw: Value,
}
fn reported_usage<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Option<Usage>, D::Error> {
let usage = Option::<Value>::deserialize(deserializer)?;
Ok(usage.filter(Value::is_object).map(|usage| {
Usage::new()
.input_tokens(usage.u64("input_tokens"))
.output_tokens(usage.u64("output_tokens"))
.cost(
usage
.f64("cost")
.filter(|cost| cost.is_finite())
.map(Cost::from_total),
)
}))
}
fn jev_usage<S: Serializer>(usage: &Option<Usage>, serializer: S) -> Result<S::Ok, S::Error> {
#[derive(Serialize)]
struct JevUsage {
#[serde(skip_serializing_if = "Option::is_none")]
input_tokens: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
output_tokens: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
cost: Option<f64>,
}
usage
.map(|usage| JevUsage {
input_tokens: usage.input_tokens,
output_tokens: usage.output_tokens,
cost: usage.cost.map(|cost| cost.total),
})
.serialize(serializer)
}