use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Tool {
#[serde(rename = "type")]
pub tool_type: String,
pub function: ToolFunction,
}
impl Tool {
pub fn function(name: impl Into<String>, description: impl Into<String>) -> ToolBuilder {
ToolBuilder {
name: name.into(),
description: description.into(),
parameters: None,
}
}
}
pub struct ToolBuilder {
name: String,
description: String,
parameters: Option<Value>,
}
impl ToolBuilder {
pub fn parameters(mut self, parameters: Value) -> Self {
self.parameters = Some(parameters);
self
}
pub fn build(self) -> Tool {
Tool {
tool_type: "function".to_string(),
function: ToolFunction {
name: self.name,
description: Some(self.description),
parameters: self.parameters,
},
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ToolFunction {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parameters: Option<Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ToolCall {
pub id: String,
#[serde(rename = "type")]
pub tool_type: String,
pub function: Function,
}
impl ToolCall {
pub fn new(
id: impl Into<String>,
name: impl Into<String>,
arguments: impl Into<String>,
) -> Self {
Self {
id: id.into(),
tool_type: "function".to_string(),
function: Function {
name: name.into(),
arguments: arguments.into(),
},
}
}
pub fn parse_arguments<T: serde::de::DeserializeOwned>(&self) -> Result<T, serde_json::Error> {
serde_json::from_str(&self.function.arguments)
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Function {
pub name: String,
pub arguments: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
pub struct ToolCallDelta {
#[serde(skip_serializing_if = "Option::is_none")]
pub index: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
#[serde(rename = "type", skip_serializing_if = "Option::is_none")]
pub tool_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub function: Option<FunctionDelta>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
pub struct FunctionDelta {
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub arguments: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(untagged)]
pub enum ToolChoice {
Mode(String),
Function {
#[serde(rename = "type")]
choice_type: String,
function: ToolChoiceFunction,
},
}
impl ToolChoice {
pub fn none() -> Self {
ToolChoice::Mode("none".to_string())
}
pub fn auto() -> Self {
ToolChoice::Mode("auto".to_string())
}
pub fn required() -> Self {
ToolChoice::Mode("required".to_string())
}
pub fn function(name: impl Into<String>) -> Self {
ToolChoice::Function {
choice_type: "function".to_string(),
function: ToolChoiceFunction { name: name.into() },
}
}
pub fn as_mode(&self) -> Option<&str> {
match self {
ToolChoice::Mode(mode) => Some(mode),
_ => None,
}
}
pub fn as_function(&self) -> Option<&str> {
match self {
ToolChoice::Function { function, .. } => Some(&function.name),
_ => None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ToolChoiceFunction {
pub name: String,
}