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 pub fn inline_data(mime_type: &str, data: &str) -> Self {
221 Self {
222 inline_data: Some(InlineData {
223 mime_type: mime_type.into(),
224 data: data.into(),
225 }),
226 ..Default::default()
227 }
228 }
229}
230
231#[derive(Debug, Deserialize, Serialize, Clone)]
235#[serde(rename_all = "camelCase")]
236pub struct VideoMetadata {
237 pub start_offset: StartOffset,
238 pub end_offset: EndOffset,
239}
240
241#[derive(Debug, Deserialize, Serialize, Clone)]
242pub struct EndOffset {
243 pub seconds: i32,
244 pub nanos: i32,
245}
246
247#[derive(Debug, Deserialize, Serialize, Clone)]
248pub struct StartOffset {
249 pub seconds: i32,
250 pub nanos: i32,
251}
252
253#[derive(Debug, Deserialize, Serialize, Clone)]
257pub struct FileData {
258 pub mime_type: String,
259 pub file_uri: String,
260}
261
262#[derive(Debug, Deserialize, Serialize, Clone)]
266#[serde(rename_all = "camelCase")]
267pub struct InlineData {
268 pub mime_type: String,
269 pub data: String,
270}
271
272#[derive(Debug, Serialize, Deserialize)]
276#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
277pub enum FinishReason {
278 FinishReasonUnspecified,
280 Stop,
282 MaxTokens,
284 Safety,
286 Recitation,
288 Language,
290 Other,
292 Blocklist,
294 ProhibitedContent,
296 Spii,
298 MalformedFunctionCall,
300 ImageSafety,
302}
303
304#[derive(Debug, Serialize, Deserialize, Clone)]
310#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
311pub enum HarmCategory {
312 HarmCategoryUnspecified,
314 HarmCategoryDerogatory,
316 HarmCategoryToxicity,
318 HarmCategoryViolence,
320 HarmCategorySexual,
322 HarmCategoryMedical,
324 HarmCategoryDangerous,
326 HarmCategoryHarassment,
328 HarmCategoryHateSpeech,
330 HarmCategorySexuallyExplicit,
332 HarmCategoryDangerousContent,
334 HarmCategoryCivicIntegrity,
336}
337
338#[derive(Debug, Deserialize, Serialize, Clone)]
342#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
343pub enum HarmBlockThreshold {
344 HarmBlockThresholdUnspecified,
346 BlockLowAndAbove,
348 BlockMedAndAbove,
350 BlockOnlyHigh,
353 BlockNone,
355 OFF,
357}
358
359#[derive(Debug, Deserialize, Serialize)]
366#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
367pub enum HarmProbability {
368 HarmProbabilityUnspecified,
370 Negligible,
372 Low,
374 Medium,
376 High,
378}
379
380#[derive(Debug, Clone, Deserialize, Serialize)]
386pub struct GoogleSearchTool {}
387
388#[derive(Debug, Clone, Deserialize, Serialize)]
394pub struct CodeExecutionTool {}
395
396#[derive(Debug, Clone, Serialize)]
403pub struct Tools {
404 #[serde(skip_serializing_if = "Option::is_none")]
405 #[serde(rename = "functionDeclarations")]
406 pub function_declarations: Option<Vec<FunctionDeclaration>>,
407 #[serde(skip_serializing_if = "Option::is_none")]
408 pub google_search: Option<GoogleSearchTool>,
409 #[serde(skip_serializing_if = "Option::is_none")]
410 pub code_execution: Option<CodeExecutionTool>,
411}
412
413#[derive(Debug, Clone, Deserialize, Serialize)]
420pub struct FunctionDeclaration {
421 pub name: String,
422 pub description: String,
423 pub parameters: Value,
428}
429
430#[derive(Debug, Default, Clone, Serialize)]
434pub struct GenerateContent {
435 pub contents: Vec<Content>,
436 #[serde(skip_serializing_if = "Vec::is_empty")]
437 pub tools: Vec<Tools>,
438 #[serde(
439 default,
440 rename = "toolConfig",
441 skip_serializing_if = "Option::is_none"
442 )]
443 pub tool_config: Option<ToolConfig>,
444 #[serde(skip_serializing_if = "Vec::is_empty")]
445 #[serde(default, rename = "safetySettings")]
446 pub safety_settings: Vec<SafetySettings>,
447 #[serde(skip_serializing_if = "Option::is_none")]
448 #[serde(default, rename = "system_instruction")]
449 pub system_instruction: Option<SystemInstructionContent>,
450 #[serde(skip_serializing_if = "Option::is_none")]
451 #[serde(default, rename = "generationConfig")]
452 pub generation_config: Option<GenerationConfig>,
453}
454
455#[derive(Debug, Clone, Deserialize, Serialize)]
459pub struct SystemInstructionContent {
460 #[serde(default)]
461 pub parts: Vec<SystemInstructionPart>,
462}
463
464#[derive(Debug, Clone, Deserialize, Serialize)]
466#[serde(rename_all = "camelCase")]
467pub struct SystemInstructionPart {
468 #[serde(skip_serializing_if = "Option::is_none")]
469 pub text: Option<String>,
470}
471
472#[derive(Debug, Deserialize, Serialize, Default, Clone)]
478#[serde(rename_all = "camelCase")]
479pub struct GenerationConfig {
480 pub temperature: Option<f32>,
481 pub top_p: Option<f32>,
482 pub top_k: Option<i32>,
483 pub candidate_count: Option<i32>,
484 pub max_output_tokens: Option<i32>,
485 pub stop_sequences: Option<Vec<String>>,
486 pub response_mime_type: Option<String>,
487 pub response_schema: Option<Schema>,
488 #[serde(rename = "thinkingConfig", skip_serializing_if = "Option::is_none")]
489 pub thinking_config: Option<ThinkingConfig>,
490}
491
492#[derive(Debug, Default, Serialize, Deserialize, Clone)]
496#[serde(rename_all = "camelCase")]
497pub struct ThinkingConfig {
498 #[serde(rename = "thinkingBudget", skip_serializing_if = "Option::is_none")]
499 pub thinking_budget: Option<u16>, #[serde(rename = "includeThoughts", skip_serializing_if = "Option::is_none")]
501 pub include_thoughts: Option<bool>,
502}
503
504#[derive(Debug, Deserialize, Serialize, Clone)]
510pub struct SafetySettings {
511 pub category: HarmCategory,
512 pub threshold: HarmBlockThreshold,
513}
514
515#[derive(Debug, Serialize, Deserialize, Clone, Default)]
523#[serde(rename_all = "camelCase")]
524pub struct Schema {
525 #[serde(rename = "type")]
526 pub schema_type: Option<Type>,
527 pub format: Option<String>,
528 pub title: Option<String>,
529 pub description: Option<String>,
530 pub nullable: Option<bool>,
531 #[serde(rename = "enum")]
532 pub enum_values: Option<Vec<String>>,
533 #[serde(rename = "maxItems")]
534 pub max_items: Option<String>,
535 #[serde(rename = "minItems")]
536 pub min_items: Option<String>,
537 pub properties: Option<BTreeMap<String, Schema>>,
538 pub required: Option<Vec<String>>,
539 #[serde(rename = "propertyOrdering")]
540 pub property_ordering: Option<Vec<String>>,
541 pub items: Option<Box<Schema>>,
542}
543
544#[derive(Debug, Clone, Deserialize, Serialize)]
548#[serde(rename_all = "camelCase")]
549pub struct ToolConfig {
550 #[serde(skip_serializing_if = "Option::is_none")]
551 pub function_calling_config: Option<FunctionCallingConfig>,
552}
553
554#[derive(Debug, Clone, Deserialize, Serialize)]
558#[serde(rename_all = "camelCase")]
559pub struct FunctionCallingConfig {
560 #[serde(skip_serializing_if = "Option::is_none")]
561 pub mode: Option<FunctionCallingMode>,
562 #[serde(skip_serializing_if = "Option::is_none")]
563 pub allowed_function_names: Option<Vec<String>>,
564}
565
566#[derive(Debug, Clone, Deserialize, Serialize)]
570#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
571pub enum FunctionCallingMode {
572 ModeUnspecified,
574 Auto,
576 Any,
578 None,
580 Validated,
582}
583
584#[derive(Debug, Deserialize, Serialize, Clone)]
588pub struct ExecutableCode {
589 #[serde(rename = "language")]
590 pub language: ProgrammingLanguage,
591 #[serde(rename = "code")]
592 pub code: String,
593}
594
595#[derive(Debug, Deserialize, Serialize, Clone)]
599#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
600pub enum ProgrammingLanguage {
601 LanguageUnspecified,
603 Python,
605}
606
607#[derive(Debug, Deserialize, Serialize, Clone)]
611#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
612pub enum Outcome {
613 OutcomeUnspecified,
615 OutcomeOk,
617 OutcomeError,
619 OutcomeDeadlineExceeded,
621}
622
623#[derive(Debug, Deserialize, Serialize, Clone)]
627pub struct FunctionResponse {
628 #[serde(skip_serializing_if = "Option::is_none")]
629 pub id: Option<String>,
630 pub name: String,
631 #[serde(skip_serializing_if = "Option::is_none")]
632 pub args: Option<Value>,
634}
635
636#[derive(Debug, Deserialize, Serialize, Clone)]
640pub struct CodeExecutionResult {
641 pub outcome: Outcome,
642 #[serde(skip_serializing_if = "Option::is_none")]
643 pub output: Option<String>,
644}
645
646#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
650#[serde(rename_all = "lowercase")]
651pub enum Type {
652 Object,
653 Array,
654 String,
655 Integer,
656 Number,
657 Boolean,
658}