use serde_json::Value;
use crate::json::extract_json;
use crate::schema::validate;
use crate::{Error, FinishReason, Response, Signature};
pub fn output_schema<S: Signature>() -> Value {
schemars::schema_for!(S::Output).to_value()
}
pub fn parse_output<S: Signature>(response: &Response, schema: &Value) -> Result<S::Output, Error> {
match response.finish {
FinishReason::Refusal => {
return Err(Error::Refusal {
model: response.model.clone(),
message: response.content.clone(),
});
}
FinishReason::Length => {
return Err(Error::Truncated {
model: response.model.clone(),
});
}
FinishReason::Stop => {}
}
let value = extract_json(&response.content).map_err(|reason| Error::InvalidJson {
reason,
response: response.content.clone(),
})?;
let violations = validate(schema, &value);
if !violations.is_empty() {
return Err(Error::SchemaViolation {
violations,
response: response.content.clone(),
});
}
let output: S::Output = serde_json::from_value(value).map_err(|e| Error::Deserialize {
message: e.to_string(),
response: response.content.clone(),
})?;
S::validate(&output).map_err(|errors| Error::Validation { errors })?;
Ok(output)
}