1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum Provider {
6 OpenAI,
8
9 Anthropic,
11
12 Local,
14}
15
16impl Provider {
17 pub fn tool_format(&self) -> ToolFormat {
19 match self {
20 Provider::OpenAI | Provider::Local => ToolFormat::OpenAI,
21 Provider::Anthropic => ToolFormat::Anthropic,
22 }
23 }
24}
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum ToolFormat {
29 OpenAI,
31
32 Anthropic,
34}
35
36pub fn build_request_with_tools(
38 messages: &[crate::Message],
39 tools: &[crate::ToolDefinition],
40 provider: Provider,
41) -> serde_json::Value {
42 match provider {
43 Provider::OpenAI | Provider::Local => build_openai_request(messages, tools),
44 Provider::Anthropic => build_anthropic_request(messages, tools),
45 }
46}
47
48pub fn build_enforced_tool_request(
67 messages: &[crate::Message],
68 tool: &crate::ToolDefinition,
69 provider: Provider,
70) -> serde_json::Value {
71 match provider {
72 Provider::OpenAI | Provider::Local => {
73 let mut request = build_openai_request(messages, &[tool.clone()]);
74 request["tool_choice"] = serde_json::json!({
76 "type": "function",
77 "function": {
78 "name": tool.name
79 }
80 });
81 request
82 }
83 Provider::Anthropic => {
84 let mut request = build_anthropic_request(messages, &[tool.clone()]);
85 request["tool_choice"] = serde_json::json!({
87 "type": "tool",
88 "name": tool.name
89 });
90 request
91 }
92 }
93}
94
95fn build_openai_request(
96 messages: &[crate::Message],
97 tools: &[crate::ToolDefinition],
98) -> serde_json::Value {
99 let mut request = serde_json::json!({
100 "messages": messages,
101 });
102
103 if !tools.is_empty() {
104 let formatted_tools: Vec<_> = tools
105 .iter()
106 .map(|tool| {
107 serde_json::json!({
108 "type": "function",
109 "function": {
110 "name": tool.name,
111 "description": tool.description,
112 "parameters": tool.parameters,
113 }
114 })
115 })
116 .collect();
117
118 request["tools"] = serde_json::json!(formatted_tools);
119 }
120
121 request
122}
123
124fn build_anthropic_request(
125 messages: &[crate::Message],
126 tools: &[crate::ToolDefinition],
127) -> serde_json::Value {
128 let mut request = serde_json::json!({
129 "messages": messages,
130 });
131
132 if !tools.is_empty() {
133 let formatted_tools: Vec<_> = tools
134 .iter()
135 .map(|tool| {
136 serde_json::json!({
137 "name": tool.name,
138 "description": tool.description,
139 "input_schema": tool.parameters,
140 })
141 })
142 .collect();
143
144 request["tools"] = serde_json::json!(formatted_tools);
145 }
146
147 request
148}
149
150#[cfg(test)]
151mod tests {
152 use super::*;
153
154 #[test]
155 fn test_provider_tool_format() {
156 assert_eq!(Provider::OpenAI.tool_format(), ToolFormat::OpenAI);
157 assert_eq!(Provider::Anthropic.tool_format(), ToolFormat::Anthropic);
158 assert_eq!(Provider::Local.tool_format(), ToolFormat::OpenAI);
159 }
160}