Skip to main content

litellm_rs/core/function_calling/
conversion.rs

1//! Provider-specific format conversion for function calling
2
3use super::executor::FunctionCallingHandler;
4use super::types::{FunctionCall, ToolCall, ToolDefinition};
5use crate::utils::error::gateway_error::{GatewayError, Result};
6use serde_json::{Value, json};
7
8impl FunctionCallingHandler {
9    /// Convert function definitions to provider-specific format
10    pub fn convert_tools_for_provider(
11        &self,
12        provider_type: &crate::core::providers::ProviderType,
13        tools: &[ToolDefinition],
14    ) -> Result<Value> {
15        match provider_type {
16            crate::core::providers::ProviderType::OpenAI
17            | crate::core::providers::ProviderType::Azure => {
18                // OpenAI format
19                Ok(json!(tools))
20            }
21            crate::core::providers::ProviderType::Anthropic => {
22                // Anthropic format
23                let anthropic_tools: Vec<Value> = tools
24                    .iter()
25                    .map(|tool| {
26                        json!({
27                            "name": tool.function.name,
28                            "description": tool.function.description,
29                            "input_schema": tool.function.parameters
30                        })
31                    })
32                    .collect();
33                Ok(json!(anthropic_tools))
34            }
35            crate::core::providers::ProviderType::VertexAI => {
36                // Google VertexAI format
37                let google_tools: Vec<Value> = tools
38                    .iter()
39                    .map(|tool| {
40                        json!({
41                            "function_declarations": [{
42                                "name": tool.function.name,
43                                "description": tool.function.description,
44                                "parameters": tool.function.parameters
45                            }]
46                        })
47                    })
48                    .collect();
49                Ok(json!(google_tools))
50            }
51            _ => Err(GatewayError::bad_request(format!(
52                "Function calling not supported for provider: {:?}",
53                provider_type
54            ))),
55        }
56    }
57
58    /// Extract tool calls from provider response
59    pub fn extract_tool_calls_from_response(
60        &self,
61        provider_type: &crate::core::providers::ProviderType,
62        response: &Value,
63    ) -> Result<Vec<ToolCall>> {
64        match provider_type {
65            crate::core::providers::ProviderType::OpenAI
66            | crate::core::providers::ProviderType::Azure => {
67                // OpenAI format
68                if let Some(choices) = response.get("choices").and_then(|c| c.as_array())
69                    && let Some(choice) = choices.first()
70                    && let Some(message) = choice.get("message")
71                    && let Some(tool_calls) = message.get("tool_calls")
72                {
73                    let tool_calls: Vec<ToolCall> = serde_json::from_value(tool_calls.clone())?;
74                    return Ok(tool_calls);
75                }
76                Ok(vec![])
77            }
78            crate::core::providers::ProviderType::Anthropic => {
79                // Anthropic format
80                if let Some(content) = response.get("content").and_then(|c| c.as_array()) {
81                    let mut tool_calls = Vec::new();
82                    for item in content {
83                        if let Some(tool_type) = item.get("type").and_then(|t| t.as_str())
84                            && tool_type == "tool_use"
85                            && let (Some(id), Some(name), Some(input)) = (
86                                item.get("id").and_then(|i| i.as_str()),
87                                item.get("name").and_then(|n| n.as_str()),
88                                item.get("input"),
89                            )
90                        {
91                            tool_calls.push(ToolCall {
92                                id: id.to_string(),
93                                tool_type: "function".to_string(),
94                                function: FunctionCall {
95                                    name: name.to_string(),
96                                    arguments: input.to_string(),
97                                },
98                            });
99                        }
100                    }
101                    return Ok(tool_calls);
102                }
103                Ok(vec![])
104            }
105            _ => Ok(vec![]),
106        }
107    }
108}