1use std::collections::BTreeMap;
4
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7
8#[derive(Debug, Deserialize, Serialize, Clone, Copy)]
10#[serde(rename_all = "lowercase")]
11pub enum Role {
12 User,
13 Model,
14}
15
16#[derive(Debug, Deserialize)]
17#[serde(untagged)]
18pub enum ApiResponse<T> {
19 Ok(T),
20 Err(ApiError),
21}
22
23#[derive(Debug, Deserialize)]
24pub struct ApiError {
25 pub error: ErrorDetail,
26}
27
28#[derive(Debug, Deserialize)]
29pub struct ErrorDetail {
30 pub code: u16,
31 pub message: String,
32 pub status: Status,
33 #[serde(default)]
34 pub details: Vec<ErrorInfo>,
35}
36
37#[derive(Debug, Deserialize)]
38pub struct ErrorInfo {
39 #[serde(rename = "@type")]
40 pub r#type: String,
41 #[serde(default)]
42 pub reason: Option<String>,
43 #[serde(default)]
44 pub domain: Option<String>,
45 #[serde(default)]
46 pub metadata: Option<BTreeMap<String, String>>,
47}
48
49#[derive(Debug, Deserialize)]
54#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
55pub enum Status {
56 InvalidArgument,
58 FailedPrecondition,
60 PermissionDenied,
62 NotFound,
64 ResourceExhausted,
66 Internal,
68 Unavailable,
70 DeadlineExceeded,
72}
73
74#[derive(Deserialize, Debug)]
78#[serde(rename_all = "camelCase")]
79pub struct Models {
80 pub models: Vec<Model>,
81 pub next_page_token: Option<String>,
82}
83
84#[derive(Debug, Default, Deserialize)]
88#[serde(rename_all = "camelCase")]
89pub struct Model {
90 pub name: String,
91 pub version: String,
92 pub display_name: String,
93 pub description: String,
94 pub input_token_limit: i32,
95 pub output_token_limit: i32,
96 pub supported_generation_methods: Vec<String>,
97 #[serde(skip_serializing_if = "Option::is_none")]
98 pub temperature: Option<f32>,
99 #[serde(skip_serializing_if = "Option::is_none")]
100 pub top_p: Option<f32>,
101 #[serde(skip_serializing_if = "Option::is_none")]
102 pub top_k: Option<i32>,
103}
104
105#[derive(Debug, Deserialize)]
109#[serde(rename_all = "camelCase")]
110pub struct Response {
111 pub candidates: Vec<Candidate>,
112 pub prompt_feedback: Option<PromptFeedback>,
113 pub usage_metadata: Option<UsageMetadata>,
114}
115
116impl std::fmt::Display for Response {
117 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118 f.write_str(
119 self.candidates[0].content.parts[0]
120 .text
121 .as_deref()
122 .unwrap_or_default(),
123 )
124 }
125}
126
127#[derive(Debug, Deserialize)]
131#[serde(rename_all = "camelCase")]
132pub struct UsageMetadata {
133 pub prompt_token_count: u64,
134 pub candidates_token_count: u64,
135}
136
137#[derive(Debug, Deserialize)]
141#[serde(rename_all = "camelCase")]
142pub struct Candidate {
143 pub content: Content,
144 pub finish_reason: Option<FinishReason>,
145 pub index: Option<i32>,
146 #[serde(default)]
147 pub safety_ratings: Vec<SafetyRating>,
148}
149
150#[derive(Debug, Deserialize)]
154pub struct PromptFeedback {
155 #[serde(rename = "safetyRatings")]
156 pub safety_ratings: Vec<SafetyRating>,
157}
158
159#[derive(Debug, Deserialize)]
166pub struct SafetyRating {
167 pub category: HarmCategory,
168 pub probability: HarmProbability,
169 #[serde(default)]
170 pub blocked: bool,
171}
172
173#[derive(Debug, Serialize, Deserialize, Clone)]
174pub struct FunctionCall {
175 #[serde(rename = "id", skip_serializing_if = "Option::is_none")]
176 pub id: Option<String>,
177 pub name: String,
178 pub args: Value,
179}
180
181#[derive(Debug, Deserialize, Serialize, Clone)]
185pub struct Content {
186 pub role: Role,
187 #[serde(default)]
188 pub parts: Vec<Part>,
189}
190
191#[derive(Debug, Default, Deserialize, Serialize, Clone)]
195#[serde(rename_all = "camelCase")]
196pub struct Part {
197 #[serde(skip_serializing_if = "Option::is_none")]
198 pub text: Option<String>,
199 #[serde(skip_serializing_if = "Option::is_none")]
200 pub inline_data: Option<InlineData>,
201 #[serde(skip_serializing_if = "Option::is_none")]
202 pub file_data: Option<FileData>,
203 #[serde(skip_serializing_if = "Option::is_none")]
204 pub video_metadata: Option<VideoMetadata>,
205 #[serde(skip_serializing_if = "Option::is_none")]
206 pub executable_code: Option<ExecutableCode>,
207 #[serde(skip_serializing_if = "Option::is_none")]
208 pub code_execution_result: Option<CodeExecutionResult>,
209 #[serde(rename = "functionCall", skip_serializing_if = "Option::is_none")]
210 pub function_call: Option<FunctionCall>,
211}
212
213impl Part {
214 pub fn text(text: &str) -> Self {
215 Self {
216 text: Some(text.into()),
217 ..Default::default()
218 }
219 }
220}
221
222#[derive(Debug, Deserialize, Serialize, Clone)]
226#[serde(rename_all = "camelCase")]
227pub struct VideoMetadata {
228 pub start_offset: StartOffset,
229 pub end_offset: EndOffset,
230}
231
232#[derive(Debug, Deserialize, Serialize, Clone)]
233pub struct EndOffset {
234 pub seconds: i32,
235 pub nanos: i32,
236}
237
238#[derive(Debug, Deserialize, Serialize, Clone)]
239pub struct StartOffset {
240 pub seconds: i32,
241 pub nanos: i32,
242}
243
244#[derive(Debug, Deserialize, Serialize, Clone)]
248pub struct FileData {
249 pub mime_type: String,
250 pub file_uri: String,
251}
252
253#[derive(Debug, Deserialize, Serialize, Clone)]
257pub struct InlineData {
258 pub mime_type: String,
259 pub data: String,
260}
261
262#[derive(Debug, Serialize, Deserialize)]
266#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
267pub enum FinishReason {
268 FinishReasonUnspecified,
270 Stop,
272 MaxTokens,
274 Safety,
276 Recitation,
278 Language,
280 Other,
282 Blocklist,
284 ProhibitedContent,
286 Spii,
288 MalformedFunctionCall,
290 ImageSafety,
292}
293
294#[derive(Debug, Serialize, Deserialize, Clone)]
300#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
301pub enum HarmCategory {
302 HarmCategoryUnspecified,
304 HarmCategoryDerogatory,
306 HarmCategoryToxicity,
308 HarmCategoryViolence,
310 HarmCategorySexual,
312 HarmCategoryMedical,
314 HarmCategoryDangerous,
316 HarmCategoryHarassment,
318 HarmCategoryHateSpeech,
320 HarmCategorySexuallyExplicit,
322 HarmCategoryDangerousContent,
324 HarmCategoryCivicIntegrity,
326}
327
328#[derive(Debug, Deserialize, Serialize, Clone)]
332#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
333pub enum HarmBlockThreshold {
334 HarmBlockThresholdUnspecified,
336 BlockLowAndAbove,
338 BlockMedAndAbove,
340 BlockOnlyHigh,
343 BlockNone,
345 OFF,
347}
348
349#[derive(Debug, Deserialize, Serialize)]
356#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
357pub enum HarmProbability {
358 HarmProbabilityUnspecified,
360 Negligible,
362 Low,
364 Medium,
366 High,
368}
369
370#[derive(Debug, Clone, Deserialize, Serialize)]
376pub struct GoogleSearchTool {}
377
378#[derive(Debug, Clone, Deserialize, Serialize)]
384pub struct CodeExecutionTool {}
385
386#[derive(Debug, Clone, Serialize)]
393pub struct Tools {
394 #[serde(skip_serializing_if = "Option::is_none")]
395 #[serde(rename = "functionDeclarations")]
396 pub function_declarations: Option<Vec<FunctionDeclaration>>,
397 #[serde(skip_serializing_if = "Option::is_none")]
398 pub google_search: Option<GoogleSearchTool>,
399 #[serde(skip_serializing_if = "Option::is_none")]
400 pub code_execution: Option<CodeExecutionTool>,
401}
402
403#[derive(Debug, Clone, Deserialize, Serialize)]
410pub struct FunctionDeclaration {
411 pub name: String,
412 pub description: String,
413 pub parameters: Value,
418}
419
420#[derive(Debug, Default, Clone, Serialize)]
424pub struct GenerateContent {
425 pub contents: Vec<Content>,
426 #[serde(skip_serializing_if = "Vec::is_empty")]
427 pub tools: Vec<Tools>,
428 #[serde(
429 default,
430 rename = "toolConfig",
431 skip_serializing_if = "Option::is_none"
432 )]
433 pub tool_config: Option<ToolConfig>,
434 #[serde(skip_serializing_if = "Vec::is_empty")]
435 #[serde(default, rename = "safetySettings")]
436 pub safety_settings: Vec<SafetySettings>,
437 #[serde(skip_serializing_if = "Option::is_none")]
438 #[serde(default, rename = "system_instruction")]
439 pub system_instruction: Option<SystemInstructionContent>,
440 #[serde(skip_serializing_if = "Option::is_none")]
441 #[serde(default, rename = "generationConfig")]
442 pub generation_config: Option<GenerationConfig>,
443}
444
445#[derive(Debug, Clone, Deserialize, Serialize)]
449pub struct SystemInstructionContent {
450 #[serde(default)]
451 pub parts: Vec<SystemInstructionPart>,
452}
453
454#[derive(Debug, Clone, Deserialize, Serialize)]
456#[serde(rename_all = "camelCase")]
457pub struct SystemInstructionPart {
458 #[serde(skip_serializing_if = "Option::is_none")]
459 pub text: Option<String>,
460}
461
462#[derive(Debug, Deserialize, Serialize, Default, Clone)]
468#[serde(rename_all = "camelCase")]
469pub struct GenerationConfig {
470 pub temperature: Option<f32>,
471 pub top_p: Option<f32>,
472 pub top_k: Option<i32>,
473 pub candidate_count: Option<i32>,
474 pub max_output_tokens: Option<i32>,
475 pub stop_sequences: Option<Vec<String>>,
476 pub response_mime_type: Option<String>,
477 pub response_schema: Option<Schema>,
478 #[serde(rename = "thinkingConfig", skip_serializing_if = "Option::is_none")]
479 pub thinking_config: Option<ThinkingConfig>,
480}
481
482#[derive(Debug, Default, Serialize, Deserialize, Clone)]
486#[serde(rename_all = "camelCase")]
487pub struct ThinkingConfig {
488 #[serde(rename = "thinkingBudget", skip_serializing_if = "Option::is_none")]
489 pub thinking_budget: Option<u16>, #[serde(rename = "includeThoughts", skip_serializing_if = "Option::is_none")]
491 pub include_thoughts: Option<bool>,
492}
493
494#[derive(Debug, Deserialize, Serialize, Clone)]
500pub struct SafetySettings {
501 pub category: HarmCategory,
502 pub threshold: HarmBlockThreshold,
503}
504
505#[derive(Debug, Serialize, Deserialize, Clone, Default)]
513#[serde(rename_all = "camelCase")]
514pub struct Schema {
515 #[serde(rename = "type")]
516 pub schema_type: Option<Type>,
517 pub format: Option<String>,
518 pub title: Option<String>,
519 pub description: Option<String>,
520 pub nullable: Option<bool>,
521 #[serde(rename = "enum")]
522 pub enum_values: Option<Vec<String>>,
523 #[serde(rename = "maxItems")]
524 pub max_items: Option<String>,
525 #[serde(rename = "minItems")]
526 pub min_items: Option<String>,
527 pub properties: Option<BTreeMap<String, Schema>>,
528 pub required: Option<Vec<String>>,
529 #[serde(rename = "propertyOrdering")]
530 pub property_ordering: Option<Vec<String>>,
531 pub items: Option<Box<Schema>>,
532}
533
534#[derive(Debug, Clone, Deserialize, Serialize)]
538#[serde(rename_all = "camelCase")]
539pub struct ToolConfig {
540 #[serde(skip_serializing_if = "Option::is_none")]
541 pub function_calling_config: Option<FunctionCallingConfig>,
542}
543
544#[derive(Debug, Clone, Deserialize, Serialize)]
548#[serde(rename_all = "camelCase")]
549pub struct FunctionCallingConfig {
550 #[serde(skip_serializing_if = "Option::is_none")]
551 pub mode: Option<FunctionCallingMode>,
552 #[serde(skip_serializing_if = "Option::is_none")]
553 pub allowed_function_names: Option<Vec<String>>,
554}
555
556#[derive(Debug, Clone, Deserialize, Serialize)]
560#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
561pub enum FunctionCallingMode {
562 ModeUnspecified,
564 Auto,
566 Any,
568 None,
570 Validated,
572}
573
574#[derive(Debug, Deserialize, Serialize, Clone)]
578pub struct ExecutableCode {
579 #[serde(rename = "language")]
580 pub language: ProgrammingLanguage,
581 #[serde(rename = "code")]
582 pub code: String,
583}
584
585#[derive(Debug, Deserialize, Serialize, Clone)]
589#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
590pub enum ProgrammingLanguage {
591 LanguageUnspecified,
593 Python,
595}
596
597#[derive(Debug, Deserialize, Serialize, Clone)]
601#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
602pub enum Outcome {
603 OutcomeUnspecified,
605 OutcomeOk,
607 OutcomeError,
609 OutcomeDeadlineExceeded,
611}
612
613#[derive(Debug, Deserialize, Serialize, Clone)]
617pub struct FunctionResponse {
618 #[serde(skip_serializing_if = "Option::is_none")]
619 pub id: Option<String>,
620 pub name: String,
621 #[serde(skip_serializing_if = "Option::is_none")]
622 pub args: Option<Value>,
624}
625
626#[derive(Debug, Deserialize, Serialize, Clone)]
630pub struct CodeExecutionResult {
631 pub outcome: Outcome,
632 #[serde(skip_serializing_if = "Option::is_none")]
633 pub output: Option<String>,
634}
635
636#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
640#[serde(rename_all = "lowercase")]
641pub enum Type {
642 Object,
643 Array,
644 String,
645 Integer,
646 Number,
647 Boolean,
648}