rusty_gemini/
api.rs

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    /// Generated content returned from the model.
13    pub content: Content,
14
15    /// List of ratings for the safety of a response candidate.
16    ///
17    /// There is at most one rating per category.
18    pub safety_ratings: Option<Vec<SafetyRating>>,
19
20    /// Citation information for model-generated candidate.
21    ///
22    /// This field may be populated with recitation information for any text
23    /// included in the [content]. These are passages that are "recited" from
24    /// copyrighted material in the foundational LLM's training data.
25    pub citation_metadata: Option<CitationMetadata>,
26
27    /// The reason why the model stopped generating tokens.
28    ///
29    /// If None, the model has not stopped generating the tokens.
30    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    /// The category for this rating.
38    category: HarmCategory,
39
40    /// The probability of harm for this content.
41    probability: HarmProbability,
42}
43
44#[derive(Serialize, Deserialize, Debug, Clone)]
45pub enum HarmCategory {
46    #[serde(rename = "HARM_CATEGORY_UNSPECIFIED")]
47    Unspecified,
48    /// Malicious, intimidating, bullying, or abusive comments targeting another
49    /// individual.
50    #[serde(rename = "HARM_CATEGORY_HARASSMENT")]
51    Harassment,
52
53    /// Negative or harmful comments targeting identity and/or protected
54    /// attributes.
55    #[serde(rename = "HARM_CATEGORY_HATE_SPEECH")]
56    HateSpeech,
57
58    /// Contains references to sexual acts or other lewd content.
59    #[serde(rename = "HARM_CATEGORY_SEXUALLY_EXPLICIT")]
60    SexuallyExplicit,
61
62    /// Promotes or enables access to harmful goods, services, and activities.
63    #[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    /// Probability is unspecified.
71    Unspecified,
72
73    /// Content has a negligible probability of being unsafe.
74    Negligible,
75
76    /// Content has a low probability of being unsafe.
77    Low,
78
79    /// Content has a medium probability of being unsafe.
80    Medium,
81
82    /// Content has a high probability of being unsafe.
83    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    /// The category for this setting.
129    pub category: HarmCategory,
130    pub threshold: HarmBlockThreshold,
131}
132
133/// Probability of harm which causes content to be blocked.
134///
135/// When provided in [SafetySetting.threshold], a predicted harm probability at
136/// or above this level will block content from being returned.
137#[derive(Serialize, Deserialize, Debug, Clone)]
138pub enum HarmBlockThreshold {
139    /// Threshold is unspecified, block using default threshold.
140    #[serde(rename = "HARM_BLOCK_THRESHOLD_UNSPECIFIED")]
141    Unspecified,
142
143    /// Block when medium or high probability of unsafe content.
144    #[serde(rename = "BLOCK_LOW_AND_ABOVE")]
145    Low,
146
147    /// Block when medium or high probability of unsafe content.
148    #[serde(rename = "BLOCK_MEDIUM_AND_ABOVE")]
149    Medium,
150
151    /// Block when high probability of unsafe content.
152    #[serde(rename = "BLOCK_ONLY_HIGH")]
153    High,
154
155    /// Always show regardless of probability of unsafe content.
156    #[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    /// The maximum number of tokens to include in a response candidate
271    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}