use crate::error::{MiniLLMError, Result};
use crate::json_repair::{repair_json, RepairOptions};
pub fn extract_json(completion: &str) -> Result<String> {
let repaired = repair_json(completion, &RepairOptions::default())?;
Ok(repaired)
}
pub fn extract_json_value(completion: &str) -> Result<serde_json::Value> {
let repaired = extract_json(completion)?;
let value: serde_json::Value = serde_json::from_str(&repaired)?;
Ok(value)
}
pub fn to_dict<T: serde::Serialize>(value: &T) -> Result<serde_json::Value> {
let json = serde_json::to_value(value)?;
Ok(json)
}
pub fn pretty_json<T: serde::Serialize>(value: &T) -> Result<String> {
let json = serde_json::to_string_pretty(value)?;
Ok(json)
}
pub fn validate_json_response(response: &serde_json::Value) -> Result<String> {
let choices = response.get("choices").ok_or_else(|| {
MiniLLMError::Other(format!("Missing 'choices' key in response: {}", response))
})?;
let choices_arr = choices
.as_array()
.ok_or_else(|| MiniLLMError::Other(format!("'choices' must be an array: {}", response)))?;
if choices_arr.is_empty() {
return Err(MiniLLMError::Other(format!(
"'choices' array is empty: {}",
response
)));
}
let first_choice = &choices_arr[0];
let message = first_choice.get("message").ok_or_else(|| {
MiniLLMError::Other(format!("Missing 'message' in first choice: {}", response))
})?;
let content = message.get("content").ok_or_else(|| {
MiniLLMError::Other(format!("Missing 'content' in message: {}", response))
})?;
content
.as_str()
.map(|s| s.to_string())
.ok_or_else(|| MiniLLMError::Other(format!("'content' is not a string: {}", content)))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_extract_json_simple() {
let input = r#"{"key": "value"}"#;
let result = extract_json(input).unwrap();
assert_eq!(result, r#"{"key": "value"}"#);
}
#[test]
fn test_extract_json_with_markdown() {
let input = r#"```json
{"key": "value"}
```"#;
let result = extract_json(input).unwrap();
assert_eq!(result, r#"{"key": "value"}"#);
}
#[test]
fn test_extract_json_with_single_quotes() {
let input = "{'key': 'value'}";
let result = extract_json(input).unwrap();
assert_eq!(result, r#"{"key": "value"}"#);
}
#[test]
fn test_extract_json_with_trailing_comma() {
let input = r#"{"key": "value",}"#;
let result = extract_json(input).unwrap();
assert_eq!(result, r#"{"key": "value"}"#);
}
}