1use serde::{Deserialize, Serialize};
2
3use crate::{
4 content::{Content, InnerPart, Part},
5 grounding::{GoogleSearchRetrieval, GroundingAtrribution},
6 schema::Schema,
7};
8
9#[derive(Debug, Deserialize)]
10#[serde(rename_all = "camelCase")]
11pub struct Candidate {
12 pub content: Content,
14
15 pub safety_ratings: Option<Vec<SafetyRating>>,
19
20 pub citation_metadata: Option<CitationMetadata>,
26
27 pub finish_reason: Option<FinishReason>,
31
32 pub grounding_attributions: Option<Vec<GroundingAtrribution>>,
33}
34
35#[derive(Serialize, Deserialize, Debug, Clone)]
36pub struct SafetyRating {
37 category: HarmCategory,
39
40 probability: HarmProbability,
42}
43
44#[derive(Serialize, Deserialize, Debug, Clone)]
45pub enum HarmCategory {
46 #[serde(rename = "HARM_CATEGORY_UNSPECIFIED")]
47 Unspecified,
48 #[serde(rename = "HARM_CATEGORY_HARASSMENT")]
51 Harassment,
52
53 #[serde(rename = "HARM_CATEGORY_HATE_SPEECH")]
56 HateSpeech,
57
58 #[serde(rename = "HARM_CATEGORY_SEXUALLY_EXPLICIT")]
60 SexuallyExplicit,
61
62 #[serde(rename = "HARM_CATEGORY_DANGEROUS_CONTENT")]
64 DangerousContent,
65}
66
67#[derive(Deserialize, Serialize, Debug, Clone)]
68#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
69pub enum HarmProbability {
70 Unspecified,
72
73 Negligible,
75
76 Low,
78
79 Medium,
81
82 High,
84}
85
86#[derive(Debug, Deserialize)]
87#[serde(rename_all = "camelCase")]
88pub struct CitationMetadata {
89 pub citation_sources: Vec<CitationSource>,
90}
91
92#[derive(Debug, Deserialize)]
93#[serde(rename_all = "camelCase")]
94pub struct CitationSource {
95 pub start_index: i32,
96 pub end_index: i32,
97 pub uri: String,
98 pub license: Option<String>,
99}
100
101#[derive(Debug, Deserialize)]
102pub enum FinishReason {
103 #[serde(rename = "FINISH_REASON_UNSPECIFIED")]
104 Unspecified,
105 #[serde(rename = "STOP")]
106 Stop,
107 #[serde(rename = "MAX_TOKENS")]
108 MaxTokens,
109 #[serde(rename = "SAFTEY")]
110 Safety,
111 #[serde(rename = "RECITATION")]
112 Recitation,
113 #[serde(rename = "LANGUAGE")]
114 Language,
115 #[serde(rename = "OTHER")]
116 Other,
117 #[serde(rename = "BLOCKLIST")]
118 BlockList,
119 #[serde(rename = "PROHIBITED_CONTENT")]
120 ProhibitedContent,
121 SPII,
122 #[serde(rename = "MALFORMED_FUNCTION_CALL")]
123 MalformedFunctionCall,
124}
125
126#[derive(Debug, Serialize, Deserialize, Clone)]
127pub struct SafetySetting {
128 pub category: HarmCategory,
130 pub threshold: HarmBlockThreshold,
131}
132
133#[derive(Serialize, Deserialize, Debug, Clone)]
138pub enum HarmBlockThreshold {
139 #[serde(rename = "HARM_BLOCK_THRESHOLD_UNSPECIFIED")]
141 Unspecified,
142
143 #[serde(rename = "BLOCK_LOW_AND_ABOVE")]
145 Low,
146
147 #[serde(rename = "BLOCK_MEDIUM_AND_ABOVE")]
149 Medium,
150
151 #[serde(rename = "BLOCK_ONLY_HIGH")]
153 High,
154
155 #[serde(rename = "BLOCK_NONE")]
157 None,
158}
159
160#[derive(Debug, Deserialize)]
161pub enum BlockReason {
162 #[serde(rename = "BLOCK_REASON_UNSPECIFIED")]
163 Unspecified,
164 #[serde(rename = "SAFETY")]
165 Saftey,
166 #[serde(rename = "OTHER")]
167 Other,
168}
169
170#[derive(Debug, Deserialize)]
171#[serde(rename_all = "camelCase")]
172pub struct PromptFeedback {
173 pub block_reason: Option<BlockReason>,
174 pub block_reason_message: Option<String>,
175 pub safety_ratings: Vec<SafetyRating>,
176}
177#[derive(Debug, Deserialize)]
178#[serde(rename_all = "camelCase")]
179pub struct UsageMetadata {
180 pub prompt_token_count: Option<i32>,
181 pub candidates_token_count: Option<i32>,
182 pub cached_content_token_count: Option<i32>,
183 pub thoughts_token_count: Option<i32>,
184 pub total_token_count: Option<i32>,
185}
186
187#[derive(Debug, Deserialize)]
188pub struct ContentEmbedding {
189 pub values: Vec<f64>,
190}
191
192pub struct CountTokenResponse {
193 pub total_tokens: i32,
194}
195
196impl Candidate {
197 pub fn text(&self) -> Option<String> {
198 let mut text = String::new();
199 for part in &self.content.parts {
200 if let InnerPart::Text(t) = &part.inner {
201 text.push_str(t);
202 }
203 }
204
205 if text.is_empty() {
206 None
207 } else {
208 Some(text)
209 }
210 }
211}
212
213#[derive(Debug, Serialize, Clone, Default)]
214#[serde(rename_all = "camelCase")]
215pub struct Tool {
216 #[serde(skip_serializing_if = "Option::is_none")]
217 pub function_declarations: Option<Vec<FunctionDeclaration>>,
218 #[serde(skip_serializing_if = "Option::is_none")]
219 pub google_search_retrieval: Option<GoogleSearchRetrieval>,
220 #[serde(skip_serializing_if = "Option::is_none")]
221 pub code_execution: Option<CodeExecution>,
222}
223
224#[derive(Debug, Serialize, Clone)]
225pub struct ToolConfig {
226 function_calling_config: Option<FunctionCallingConfig>,
227}
228
229#[derive(Debug, Serialize, Clone)]
230pub struct ThinkingConfig {
231 pub include_thoughts: bool,
232 pub thinking_budget: Option<i32>,
233}
234
235#[derive(Debug, Serialize, Clone)]
236#[serde(rename_all = "camelCase")]
237pub struct FunctionCallingConfig {
238 pub mode: Option<Mode>,
239 pub allowed_function_names: Vec<String>,
240}
241
242#[derive(Debug, Serialize, Clone)]
243#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
244pub enum Mode {
245 #[serde(rename = "MODE_UNSPECIFIED")]
246 Unspecified,
247 Auto,
248 Any,
249 None,
250}
251
252#[derive(Debug, Serialize, Clone)]
253pub struct CodeExecution;
254
255#[derive(Debug, Serialize, Clone, Default)]
256#[serde(rename_all = "camelCase")]
257pub struct GenerationConfig {
258
259 #[serde(skip_serializing_if = "Option::is_none")]
260 pub thinking_config: Option<ThinkingConfig>,
261 #[serde(skip_serializing_if = "Option::is_none")]
262 pub stop_sequences: Option<Vec<String>>,
263 #[serde(skip_serializing_if = "Option::is_none")]
264 pub response_mime_type: Option<ResponseMimeType>,
265 #[serde(skip_serializing_if = "Option::is_none")]
266 pub response_schema: Option<Schema>,
267 #[serde(skip_serializing_if = "Option::is_none")]
268 pub candidate_count: Option<i32>,
269 #[serde(skip_serializing_if = "Option::is_none")]
270 pub max_output_tokens: Option<i32>,
272 #[serde(skip_serializing_if = "Option::is_none")]
273 pub temperature: Option<f32>,
274 #[serde(skip_serializing_if = "Option::is_none")]
275 pub top_p: Option<f64>,
276 #[serde(skip_serializing_if = "Option::is_none")]
277 pub top_k: Option<i32>,
278 #[serde(skip_serializing_if = "Option::is_none")]
279 pub presence_penalty: Option<f32>,
280 #[serde(skip_serializing_if = "Option::is_none")]
281 pub frequence_penalty: Option<f32>,
282 #[serde(skip_serializing_if = "Option::is_none")]
283 pub response_logprobs: Option<bool>,
284}
285
286#[derive(Debug, Serialize, Clone)]
287#[serde(rename = "camelCase")]
288pub enum ResponseMimeType {
289 #[serde(rename = "text/plain")]
290 TextPlain,
291 #[serde(rename = "application/json")]
292 ApplicationJson,
293}
294
295#[derive(Debug, Serialize, Clone)]
296pub struct FunctionDeclaration {
297 pub name: String,
298 pub description: String,
299 pub parameters: Option<Schema>,
300}
301
302#[derive(Debug, Serialize, Deserialize, Clone)]
303pub enum TaskType {
304 #[serde(rename = "TASK_TYPE_UNSPECIFIED")]
305 Unspecified,
306 #[serde(rename = "RETRIEVAL_QUERY")]
307 RetrievalQuery,
308 #[serde(rename = "RETRIEVAL_DOCUMENT")]
309 RetrievalDocument,
310 #[serde(rename = "SEMANTIC_SIMILARITY")]
311 SemanticSimilarity,
312 #[serde(rename = "CLASSIFICATION")]
313 Classification,
314 #[serde(rename = "CLUSTERING")]
315 Clustering,
316 #[serde(rename = "QUESTION_ANSWERING")]
317 QuestionAnswering,
318 #[serde(rename = "FACT_VERIFICATION")]
319 FactVerification,
320}
321
322#[derive(Debug, Serialize, Deserialize)]
323pub struct GeminiGenericErrorResponse {
324 pub(crate) error: GeminiGenericError,
325}
326#[derive(Debug, Serialize, Deserialize)]
327pub struct GeminiGenericError {
328 pub code: i32,
329 pub message: String,
330 pub status: String,
331}