dynamo_llm/preprocessor/
tools.rs1mod request;
17mod response;
18
19pub use request::*;
20pub use response::*;
21use serde_json::Value;
22use std::collections::HashMap;
23use uuid::Uuid;
24
25pub struct ToolCallingMatcher {
31 tool_choice: ToolChoice,
32}
33
34#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
36pub struct CalledFunctionParameters {
37 pub name: String,
38 pub parameters: HashMap<String, Value>,
39}
40
41#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
43pub struct CalledFunctionArguments {
44 pub name: String,
45 pub arguments: HashMap<String, Value>,
46}
47
48impl ToolCallingMatcher {
49 pub fn new(tool_choice: ToolChoice) -> anyhow::Result<Self> {
50 Ok(Self { tool_choice })
51 }
52
53 pub fn get_call(&self, message: &str) -> anyhow::Result<Vec<ToolCallResponse>> {
54 if matches!(self.tool_choice, ToolChoice::None) {
55 return Ok(Vec::new());
56 }
57
58 if let Ok(deser) = serde_json::from_str::<CalledFunctionParameters>(message) {
59 let id = format!("call-{}", Uuid::new_v4());
60 Ok(vec![ToolCallResponse {
61 id,
62 tp: ToolCallType::Function,
63 function: CalledFunction {
64 name: deser.name,
65 arguments: serde_json::to_string(&deser.parameters)?,
66 },
67 }])
68 } else if let Ok(deser) = serde_json::from_str::<Vec<CalledFunctionParameters>>(message) {
69 Ok(deser
70 .into_iter()
71 .map(|deser| {
72 let id = format!("call-{}", Uuid::new_v4());
73 Ok(ToolCallResponse {
74 id,
75 tp: ToolCallType::Function,
76 function: CalledFunction {
77 name: deser.name,
78 arguments: serde_json::to_string(&deser.parameters)?,
79 },
80 })
81 })
82 .collect::<anyhow::Result<Vec<_>>>()?)
83 } else if let Ok(deser) = serde_json::from_str::<CalledFunctionArguments>(message) {
84 let id = format!("call-{}", Uuid::new_v4());
85 Ok(vec![ToolCallResponse {
86 id,
87 tp: ToolCallType::Function,
88 function: CalledFunction {
89 name: deser.name,
90 arguments: serde_json::to_string(&deser.arguments)?,
91 },
92 }])
93 } else if let Ok(deser) = serde_json::from_str::<Vec<CalledFunctionArguments>>(message) {
94 Ok(deser
95 .into_iter()
96 .map(|deser| {
97 let id = format!("call-{}", Uuid::new_v4());
98 Ok(ToolCallResponse {
99 id,
100 tp: ToolCallType::Function,
101 function: CalledFunction {
102 name: deser.name,
103 arguments: serde_json::to_string(&deser.arguments)?,
104 },
105 })
106 })
107 .collect::<anyhow::Result<Vec<_>>>()?)
108 } else {
109 if matches!(self.tool_choice, ToolChoice::Tool(_)) {
110 anyhow::bail!("Tool choice was required but no tools were called.")
111 }
112 Ok(Vec::new())
113 }
114 }
115}