ai_sdk_provider/language_model/
call_options.rs

1use super::prompt::Prompt;
2use super::tools::{Tool, ToolChoice};
3use crate::SharedProviderOptions;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7/// Configuration options for language model generation requests.
8///
9/// This struct encapsulates all available parameters for controlling language model behavior.
10/// It provides fine-grained control over sampling, generation limits, response formatting,
11/// and tool integration. Use this structure when making requests to language models through
12/// the SDK.
13///
14/// # Fields
15///
16/// * `prompt` - The input prompt or conversation history to send to the model. This is the
17///   primary content that guides the model's response generation.
18///
19/// * `max_output_tokens` - The maximum number of tokens the model should generate in its
20///   response. Helps control response length and API costs. Typical values range from 100 to 4096.
21///
22/// * `temperature` - Controls randomness in token selection. Values from 0.0 to 2.0:
23///   - 0.0: Deterministic, always selects the most likely token
24///   - 0.7: Balanced randomness (recommended for most use cases)
25///   - 2.0: Maximum randomness
26///
27/// * `stop_sequences` - List of strings that, when generated, will cause the model to stop
28///   generating further tokens. Useful for controlling output boundaries.
29///
30/// * `top_p` - Nucleus sampling parameter (0.0 to 1.0). The model selects from the smallest
31///   set of tokens whose probabilities sum to this value. Works well with temperature.
32///
33/// * `top_k` - Top-k sampling parameter. Limits selection to the k most likely next tokens,
34///   reducing tail probability mass. A value of 40-50 is typical.
35///
36/// * `presence_penalty` - Penalty for tokens that have already appeared in the prompt
37///   (-2.0 to 2.0). Positive values encourage diversity and reduce repetition.
38///
39/// * `frequency_penalty` - Penalty based on token frequency in the generated text (-2.0 to 2.0).
40///   Positive values reduce likelihood of repeating common phrases.
41///
42/// * `response_format` - Specifies the desired format for the model's response, either
43///   plain text or structured JSON with optional schema validation.
44///
45/// * `seed` - Random seed for deterministic output. When set, the same seed with the same
46///   inputs will produce identical outputs (if supported by the provider).
47///
48/// * `tools` - Array of tool definitions available for the model to call. Enables function
49///   calling and tool use capabilities.
50///
51/// * `tool_choice` - Strategy for tool invocation: Auto (model decides), None (disable tools),
52///   Required (must call at least one), or a specific tool by name.
53///
54/// * `include_raw_chunks` - When streaming, includes raw provider chunks in the response
55///   for debugging or advanced use cases.
56///
57/// * `headers` - Additional HTTP headers to include in the request. Useful for custom
58///   authentication, routing, or provider-specific headers.
59///
60/// * `provider_options` - Provider-specific configuration options that may not be part of
61///   the standard SDK parameters.
62#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
63#[serde(rename_all = "camelCase")]
64pub struct CallOptions {
65    /// The input prompt or conversation history for the model.
66    pub prompt: Prompt,
67
68    /// Maximum number of tokens to generate in the response.
69    #[serde(skip_serializing_if = "Option::is_none")]
70    pub max_output_tokens: Option<u32>,
71
72    /// Sampling temperature controlling randomness (0.0 to 2.0).
73    #[serde(skip_serializing_if = "Option::is_none")]
74    pub temperature: Option<f32>,
75
76    /// Sequences that trigger generation to stop when encountered.
77    #[serde(skip_serializing_if = "Option::is_none")]
78    pub stop_sequences: Option<Vec<String>>,
79
80    /// Nucleus sampling probability mass (0.0 to 1.0).
81    #[serde(skip_serializing_if = "Option::is_none")]
82    pub top_p: Option<f32>,
83
84    /// Top-k sampling parameter limiting token selection.
85    #[serde(skip_serializing_if = "Option::is_none")]
86    pub top_k: Option<u32>,
87
88    /// Penalty for tokens that have appeared in the prompt (-2.0 to 2.0).
89    #[serde(skip_serializing_if = "Option::is_none")]
90    pub presence_penalty: Option<f32>,
91
92    /// Penalty based on token frequency in generated text (-2.0 to 2.0).
93    #[serde(skip_serializing_if = "Option::is_none")]
94    pub frequency_penalty: Option<f32>,
95
96    /// Expected format for the model's response (Text or JSON).
97    #[serde(skip_serializing_if = "Option::is_none")]
98    pub response_format: Option<ResponseFormat>,
99
100    /// Random seed for deterministic generation.
101    #[serde(skip_serializing_if = "Option::is_none")]
102    pub seed: Option<i64>,
103
104    /// Tool definitions available for the model to call.
105    #[serde(skip_serializing_if = "Option::is_none")]
106    pub tools: Option<Vec<Tool>>,
107
108    /// Strategy for tool selection and invocation.
109    #[serde(skip_serializing_if = "Option::is_none")]
110    pub tool_choice: Option<ToolChoice>,
111
112    /// Whether to include raw provider chunks in streaming responses.
113    #[serde(skip_serializing_if = "Option::is_none")]
114    pub include_raw_chunks: Option<bool>,
115
116    /// Additional HTTP headers for the provider request.
117    #[serde(skip_serializing_if = "Option::is_none")]
118    pub headers: Option<HashMap<String, String>>,
119
120    /// Provider-specific configuration options.
121    #[serde(skip_serializing_if = "Option::is_none")]
122    pub provider_options: Option<SharedProviderOptions>,
123}
124
125/// Specifies the expected format for the language model's response.
126///
127/// The response format controls how the model should structure its output. This can be used
128/// to enforce specific output formats like JSON for structured data extraction or validation.
129///
130/// # Variants
131///
132/// * `Text` - Plain text format. The model generates natural language text without structural
133///   constraints. This is the default and most flexible format.
134///
135/// * `Json` - Structured JSON format. The model generates output in valid JSON format. You can
136///   optionally provide a JSON schema to guide the structure.
137///   - `schema`: JSON Schema (as serde_json::Value) defining the expected structure
138///   - `name`: Optional name/identifier for the schema
139///   - `description`: Optional description of what the JSON should contain
140#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
141#[serde(tag = "type", rename_all = "lowercase")]
142pub enum ResponseFormat {
143    /// Plain text format without structural constraints.
144    ///
145    /// The model generates natural language text freely. This is the default and most
146    /// flexible format, suitable for general-purpose text generation.
147    Text,
148    /// Structured JSON format with optional schema validation.
149    ///
150    /// The model generates output in valid JSON format. You can optionally provide a
151    /// JSON schema to guide the structure, a name to identify the schema, and a
152    /// description of what the JSON should contain.
153    Json {
154        /// JSON Schema defining the expected structure of the output
155        #[serde(skip_serializing_if = "Option::is_none")]
156        schema: Option<serde_json::Value>,
157        /// Optional name or identifier for the schema
158        #[serde(skip_serializing_if = "Option::is_none")]
159        name: Option<String>,
160        /// Optional description of what the JSON should contain
161        #[serde(skip_serializing_if = "Option::is_none")]
162        description: Option<String>,
163    },
164}
165
166#[cfg(test)]
167mod tests {
168    use super::*;
169    use crate::language_model::prompt::Message;
170
171    #[test]
172    fn test_call_options() {
173        let opts = CallOptions {
174            prompt: vec![Message::System {
175                content: "test".into(),
176            }]
177            .into(),
178            temperature: Some(0.7),
179            max_output_tokens: Some(1000),
180            ..Default::default()
181        };
182        let json = serde_json::to_string(&opts).unwrap();
183        assert!(json.contains("temperature"));
184        assert!(json.contains("maxOutputTokens"));
185    }
186
187    #[test]
188    fn test_response_format_text() {
189        let format = ResponseFormat::Text;
190        let json = serde_json::to_value(&format).unwrap();
191        assert_eq!(json["type"], "text");
192    }
193
194    #[test]
195    fn test_response_format_json() {
196        let format = ResponseFormat::Json {
197            schema: None,
198            name: Some("MySchema".into()),
199            description: None,
200        };
201        let json = serde_json::to_value(&format).unwrap();
202        assert_eq!(json["type"], "json");
203        assert_eq!(json["name"], "MySchema");
204    }
205}