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}