ollama_rs/generation/tools/
mod.rs1#[cfg_attr(docsrs, doc(cfg(feature = "tool-implementations")))]
2#[cfg(feature = "tool-implementations")]
3pub mod implementations;
4
5use std::{future::Future, pin::Pin};
6
7use schemars::{generate::SchemaSettings, JsonSchema, Schema};
8use serde::{de::DeserializeOwned, Deserialize, Serialize};
9use serde_json::Value;
10
11pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
12
13pub trait Tool: Send + Sync {
17 type Params: Parameters;
18
19 fn name() -> &'static str;
20 fn description() -> &'static str;
21
22 fn call(&mut self, parameters: Self::Params) -> impl Future<Output = Result<String>> + Send;
26}
27
28pub trait Parameters: DeserializeOwned + JsonSchema {}
29
30impl<P: DeserializeOwned + JsonSchema> Parameters for P {}
31
32pub(crate) trait ToolHolder: Send + Sync {
33 fn call(
34 &mut self,
35 parameters: Value,
36 ) -> Pin<Box<dyn Future<Output = Result<String>> + '_ + Send>>;
37}
38
39impl<T: Tool> ToolHolder for T {
40 fn call(
41 &mut self,
42 parameters: Value,
43 ) -> Pin<Box<dyn Future<Output = Result<String>> + '_ + Send>> {
44 Box::pin(async move {
45 let param_value = match serde_json::from_value(parameters.clone()) {
48 Ok(ToolCallFunction { name: _, arguments }) => arguments,
50 Err(_err) => match serde_json::from_value::<ToolInfo>(parameters.clone()) {
51 Ok(ti) => ti.function.parameters.to_value(),
52 Err(_err) => parameters,
53 },
54 };
55
56 let param = serde_json::from_value(param_value)?;
57
58 T::call(self, param).await
59 })
60 }
61}
62
63#[derive(Clone, Debug, Serialize, Deserialize)]
64pub struct ToolInfo {
65 #[serde(rename = "type")]
66 pub tool_type: ToolType,
67 pub function: ToolFunctionInfo,
68}
69
70impl ToolInfo {
71 pub fn new<P: Parameters, T: Tool<Params = P>>() -> Self {
74 let mut settings = SchemaSettings::draft07();
75 settings.inline_subschemas = true;
76 let generator = settings.into_generator();
77
78 let parameters = generator.into_root_schema_for::<T::Params>();
79
80 Self {
81 tool_type: ToolType::Function,
82 function: ToolFunctionInfo {
83 name: T::name().to_string(),
84 description: T::description().to_string(),
85 parameters,
86 },
87 }
88 }
89}
90
91#[derive(Clone, Debug, Serialize, Deserialize)]
92pub enum ToolType {
93 #[serde(rename_all(deserialize = "PascalCase"))]
94 Function,
95}
96
97#[derive(Clone, Debug, Serialize, Deserialize)]
98pub struct ToolFunctionInfo {
99 pub name: String,
100 pub description: String,
101 pub parameters: Schema,
102}
103
104#[derive(Clone, Debug, Serialize, Deserialize)]
105pub struct ToolCall {
106 pub function: ToolCallFunction,
107}
108
109#[derive(Clone, Debug, Serialize, Deserialize)]
110pub struct ToolCallFunction {
111 pub name: String,
112 #[serde(alias = "parameters")]
116 pub arguments: Value,
117}