use magi_tool::Tool as MagiTool;
use crate::completions::request::{FunctionTool, Tool, ToolType};
impl From<MagiTool> for Tool {
fn from(magi_tool: MagiTool) -> Self {
Tool {
r#type: ToolType::Function,
function: FunctionTool {
name: magi_tool.name.clone(),
description: magi_tool.description,
parameters: Some(magi_tool.input_schema),
},
}
}
}
impl From<Tool> for MagiTool {
fn from(tool: Tool) -> Self {
MagiTool {
name: tool.function.name.clone(),
description: tool.function.description.clone(),
input_schema: tool.function.parameters.unwrap_or_default(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
use std::borrow::Cow;
#[test]
fn test_convert_magi_tool_to_openai_tool() {
let magi_tool = MagiTool {
name: "get_weather".into(),
description: Some("Get the current weather in a location".into()),
input_schema: json!({
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["location"]
}),
};
let openai_tool: Tool = magi_tool.into();
assert_eq!(openai_tool.r#type, ToolType::Function);
assert_eq!(openai_tool.function.name, "get_weather");
assert_eq!(
openai_tool.function.description,
Some(Cow::from("Get the current weather in a location"))
);
let params = openai_tool.function.parameters.unwrap();
assert_eq!(params["type"], "object");
assert!(params["properties"].is_object());
assert!(params["properties"]["location"].is_object());
assert_eq!(params["properties"]["location"]["type"], "string");
assert!(params["required"].is_array());
assert_eq!(params["required"][0], "location");
}
#[test]
fn test_convert_openai_tool_to_magi_tool() {
let openai_tool = Tool {
r#type: ToolType::Function,
function: FunctionTool {
name: "get_weather".into(),
description: Some("Get the current weather in a location".into()),
parameters: Some(json!({
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["location"]
})),
},
};
let magi_tool: MagiTool = openai_tool.into();
assert_eq!(magi_tool.name, "get_weather");
assert_eq!(
magi_tool.description,
Some("Get the current weather in a location".into())
);
let schema = &magi_tool.input_schema;
assert_eq!(schema["type"], "object");
assert!(schema["properties"].is_object());
assert!(schema["properties"]["location"].is_object());
assert_eq!(schema["properties"]["location"]["type"], "string");
assert!(schema["required"].is_array());
assert_eq!(schema["required"][0], "location");
}
#[test]
fn test_handle_none_parameters() {
let openai_tool = Tool {
r#type: ToolType::Function,
function: FunctionTool {
name: "simple_tool".into(),
description: Some("A tool with no parameters".into()),
parameters: None,
},
};
let magi_tool: MagiTool = openai_tool.into();
assert_eq!(magi_tool.name, "simple_tool");
assert_eq!(
magi_tool.description,
Some("A tool with no parameters".into())
);
assert!(magi_tool.input_schema.is_null());
}
#[test]
fn test_roundtrip_conversion() {
let original_magi_tool = MagiTool {
name: "test_function".into(),
description: Some("A test function".into()),
input_schema: json!({
"type": "object",
"properties": {
"arg1": {
"type": "string"
}
},
"required": ["arg1"]
}),
};
let openai_tool: Tool = original_magi_tool.clone().into();
let roundtrip_magi_tool: MagiTool = openai_tool.into();
assert_eq!(roundtrip_magi_tool.name, original_magi_tool.name);
assert_eq!(
roundtrip_magi_tool.description,
original_magi_tool.description
);
assert_eq!(
roundtrip_magi_tool.input_schema,
original_magi_tool.input_schema
);
}
}