use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GenerateContentRequest {
pub model: String,
pub contents: Vec<Content>,
#[serde(skip_serializing_if = "Option::is_none", rename = "systemInstruction")]
pub system_instruction: Option<Content>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tools: Option<Vec<GeminiTool>>,
#[serde(skip_serializing_if = "Option::is_none", rename = "toolConfig")]
pub tool_config: Option<ToolConfig>,
#[serde(skip_serializing_if = "Option::is_none", rename = "safetySettings")]
pub safety_settings: Option<Vec<SafetySetting>>,
#[serde(skip_serializing_if = "Option::is_none", rename = "generationConfig")]
pub generation_config: Option<GenerationConfig>,
#[serde(skip_serializing_if = "Option::is_none", rename = "cachedContent")]
pub cached_content: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GenerateContentResponse {
#[serde(default)]
pub candidates: Vec<Candidate>,
#[serde(skip_serializing_if = "Option::is_none")]
pub prompt_feedback: Option<PromptFeedback>,
#[serde(skip_serializing_if = "Option::is_none")]
pub usage_metadata: Option<UsageMetadata>,
#[serde(skip_serializing_if = "Option::is_none")]
pub model_version: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub response_id: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Content {
#[serde(skip_serializing_if = "Option::is_none")]
pub role: Option<String>,
pub parts: Vec<Part>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Part {
Text {
text: String,
#[serde(skip_serializing_if = "Option::is_none")]
thought: Option<bool>,
},
InlineData {
#[serde(rename = "inlineData")]
inline_data: Blob,
},
FileData {
#[serde(rename = "fileData")]
file_data: FileData,
},
FunctionCall {
#[serde(rename = "functionCall")]
function_call: FunctionCall,
},
FunctionResponse {
#[serde(rename = "functionResponse")]
function_response: FunctionResponse,
},
ExecutableCode {
#[serde(rename = "executableCode")]
executable_code: ExecutableCode,
},
CodeExecutionResult {
#[serde(rename = "codeExecutionResult")]
code_execution_result: CodeExecutionResult,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Blob {
pub mime_type: String,
pub data: String, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileData {
pub file_uri: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub mime_type: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FunctionCall {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub args: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FunctionResponse {
pub name: String,
pub response: serde_json::Value,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExecutableCode {
pub language: CodeLanguage,
pub code: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum CodeLanguage {
#[serde(rename = "LANGUAGE_UNSPECIFIED")]
Unspecified,
#[serde(rename = "PYTHON")]
Python,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CodeExecutionResult {
pub outcome: CodeExecutionOutcome,
#[serde(skip_serializing_if = "Option::is_none")]
pub output: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum CodeExecutionOutcome {
#[serde(rename = "OUTCOME_UNSPECIFIED")]
Unspecified,
#[serde(rename = "OUTCOME_OK")]
Ok,
#[serde(rename = "OUTCOME_FAILED")]
Failed,
#[serde(rename = "OUTCOME_DEADLINE_EXCEEDED")]
DeadlineExceeded,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Candidate {
#[serde(skip_serializing_if = "Option::is_none")]
pub content: Option<Content>,
#[serde(skip_serializing_if = "Option::is_none")]
pub finish_reason: Option<FinishReason>,
#[serde(default)]
pub safety_ratings: Vec<SafetyRating>,
#[serde(skip_serializing_if = "Option::is_none")]
pub citation_metadata: Option<CitationMetadata>,
#[serde(skip_serializing_if = "Option::is_none")]
pub token_count: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub index: Option<i32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum FinishReason {
#[serde(rename = "FINISH_REASON_UNSPECIFIED")]
Unspecified,
#[serde(rename = "STOP")]
Stop,
#[serde(rename = "MAX_TOKENS")]
MaxTokens,
#[serde(rename = "SAFETY")]
Safety,
#[serde(rename = "RECITATION")]
Recitation,
#[serde(rename = "LANGUAGE")]
Language,
#[serde(rename = "OTHER")]
Other,
#[serde(rename = "BLOCKLIST")]
Blocklist,
#[serde(rename = "PROHIBITED_CONTENT")]
ProhibitedContent,
#[serde(rename = "SPII")]
Spii,
#[serde(rename = "MALFORMED_FUNCTION_CALL")]
MalformedFunctionCall,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CitationMetadata {
#[serde(default)]
pub citation_sources: Vec<CitationSource>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CitationSource {
#[serde(skip_serializing_if = "Option::is_none")]
pub start_index: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub end_index: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub uri: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub license: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SafetyRating {
pub category: HarmCategory,
pub probability: HarmProbability,
#[serde(skip_serializing_if = "Option::is_none")]
pub blocked: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum HarmCategory {
#[serde(rename = "HARM_CATEGORY_UNSPECIFIED")]
Unspecified,
#[serde(rename = "HARM_CATEGORY_DEROGATORY")]
Derogatory,
#[serde(rename = "HARM_CATEGORY_TOXICITY")]
Toxicity,
#[serde(rename = "HARM_CATEGORY_VIOLENCE")]
Violence,
#[serde(rename = "HARM_CATEGORY_SEXUAL")]
Sexual,
#[serde(rename = "HARM_CATEGORY_MEDICAL")]
Medical,
#[serde(rename = "HARM_CATEGORY_DANGEROUS")]
Dangerous,
#[serde(rename = "HARM_CATEGORY_HARASSMENT")]
Harassment,
#[serde(rename = "HARM_CATEGORY_HATE_SPEECH")]
HateSpeech,
#[serde(rename = "HARM_CATEGORY_SEXUALLY_EXPLICIT")]
SexuallyExplicit,
#[serde(rename = "HARM_CATEGORY_DANGEROUS_CONTENT")]
DangerousContent,
#[serde(rename = "HARM_CATEGORY_CIVIC_INTEGRITY")]
CivicIntegrity,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum HarmProbability {
#[serde(rename = "HARM_PROBABILITY_UNSPECIFIED")]
Unspecified,
#[serde(rename = "NEGLIGIBLE")]
Negligible,
#[serde(rename = "LOW")]
Low,
#[serde(rename = "MEDIUM")]
Medium,
#[serde(rename = "HIGH")]
High,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SafetySetting {
pub category: HarmCategory,
pub threshold: HarmBlockThreshold,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum HarmBlockThreshold {
#[serde(rename = "HARM_BLOCK_THRESHOLD_UNSPECIFIED")]
Unspecified,
#[serde(rename = "BLOCK_LOW_AND_ABOVE")]
BlockLowAndAbove,
#[serde(rename = "BLOCK_MEDIUM_AND_ABOVE")]
BlockMediumAndAbove,
#[serde(rename = "BLOCK_ONLY_HIGH")]
BlockOnlyHigh,
#[serde(rename = "BLOCK_NONE")]
BlockNone,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GenerationConfig {
#[serde(skip_serializing_if = "Option::is_none", rename = "candidateCount")]
pub candidate_count: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none", rename = "stopSequences")]
pub stop_sequences: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none", rename = "maxOutputTokens")]
pub max_output_tokens: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub temperature: Option<f32>,
#[serde(skip_serializing_if = "Option::is_none", rename = "topP")]
pub top_p: Option<f32>,
#[serde(skip_serializing_if = "Option::is_none", rename = "topK")]
pub top_k: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none", rename = "responseMimeType")]
pub response_mime_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", rename = "responseSchema")]
pub response_schema: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none", rename = "thinkingConfig")]
pub thinking_config: Option<ThinkingConfig>,
#[serde(skip_serializing_if = "Option::is_none", rename = "responseModalities")]
pub response_modalities: Option<Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThinkingConfig {
#[serde(skip_serializing_if = "Option::is_none", rename = "thinkingBudget")]
pub thinking_budget: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none", rename = "includeThoughts")]
pub include_thoughts: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PromptFeedback {
#[serde(skip_serializing_if = "Option::is_none")]
pub block_reason: Option<BlockReason>,
#[serde(default)]
pub safety_ratings: Vec<SafetyRating>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum BlockReason {
#[serde(rename = "BLOCK_REASON_UNSPECIFIED")]
Unspecified,
#[serde(rename = "SAFETY")]
Safety,
#[serde(rename = "OTHER")]
Other,
#[serde(rename = "BLOCKLIST")]
Blocklist,
#[serde(rename = "PROHIBITED_CONTENT")]
ProhibitedContent,
#[serde(rename = "IMAGE_SAFETY")]
ImageSafety,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UsageMetadata {
#[serde(skip_serializing_if = "Option::is_none")]
pub prompt_token_count: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub total_token_count: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cached_content_token_count: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub candidates_token_count: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub thoughts_token_count: Option<i32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GeminiTool {
FunctionDeclarations {
function_declarations: Vec<FunctionDeclaration>,
},
CodeExecution { code_execution: CodeExecution },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FunctionDeclaration {
pub name: String,
pub description: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub parameters: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub response: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CodeExecution {
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub function_calling_config: Option<FunctionCallingConfig>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FunctionCallingConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub mode: Option<FunctionCallingMode>,
#[serde(skip_serializing_if = "Option::is_none")]
pub allowed_function_names: Option<Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum FunctionCallingMode {
#[serde(rename = "MODE_UNSPECIFIED")]
Unspecified,
#[serde(rename = "AUTO")]
Auto,
#[serde(rename = "ANY")]
Any,
#[serde(rename = "NONE")]
None,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GeminiConfig {
pub api_key: String,
pub base_url: String,
pub model: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub generation_config: Option<GenerationConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub safety_settings: Option<Vec<SafetySetting>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub timeout: Option<u64>,
}
impl Default for GeminiConfig {
fn default() -> Self {
Self {
api_key: String::new(),
base_url: "https://generativelanguage.googleapis.com/v1beta".to_string(),
model: "gemini-1.5-flash".to_string(),
generation_config: None,
safety_settings: None,
timeout: Some(30),
}
}
}
impl GeminiConfig {
pub fn new(api_key: String) -> Self {
Self {
api_key,
..Default::default()
}
}
pub fn with_model(mut self, model: String) -> Self {
self.model = model;
self
}
pub fn with_base_url(mut self, base_url: String) -> Self {
self.base_url = base_url;
self
}
pub fn with_generation_config(mut self, config: GenerationConfig) -> Self {
self.generation_config = Some(config);
self
}
pub fn with_safety_settings(mut self, settings: Vec<SafetySetting>) -> Self {
self.safety_settings = Some(settings);
self
}
pub const fn with_timeout(mut self, timeout: u64) -> Self {
self.timeout = Some(timeout);
self
}
}
impl GenerationConfig {
pub const fn new() -> Self {
Self {
candidate_count: None,
stop_sequences: None,
max_output_tokens: None,
temperature: None,
top_p: None,
top_k: None,
response_mime_type: None,
response_schema: None,
thinking_config: None,
response_modalities: None,
}
}
pub const fn with_candidate_count(mut self, count: i32) -> Self {
self.candidate_count = Some(count);
self
}
pub fn with_stop_sequences(mut self, sequences: Vec<String>) -> Self {
self.stop_sequences = Some(sequences);
self
}
pub const fn with_max_output_tokens(mut self, tokens: i32) -> Self {
self.max_output_tokens = Some(tokens);
self
}
pub const fn with_temperature(mut self, temperature: f32) -> Self {
self.temperature = Some(temperature);
self
}
pub const fn with_top_p(mut self, top_p: f32) -> Self {
self.top_p = Some(top_p);
self
}
pub const fn with_top_k(mut self, top_k: i32) -> Self {
self.top_k = Some(top_k);
self
}
pub fn with_response_mime_type(mut self, mime_type: String) -> Self {
self.response_mime_type = Some(mime_type);
self
}
pub fn with_response_schema(mut self, schema: serde_json::Value) -> Self {
self.response_schema = Some(schema);
self
}
pub const fn with_thinking_config(mut self, config: ThinkingConfig) -> Self {
self.thinking_config = Some(config);
self
}
pub fn with_response_modalities(mut self, modalities: Vec<String>) -> Self {
self.response_modalities = Some(modalities);
self
}
}
impl Default for GenerationConfig {
fn default() -> Self {
Self::new()
}
}
impl ThinkingConfig {
pub const fn new() -> Self {
Self {
thinking_budget: None,
include_thoughts: None,
}
}
pub const fn with_budget(budget: i32) -> Self {
Self {
thinking_budget: Some(budget),
include_thoughts: None,
}
}
pub const fn with_thoughts() -> Self {
Self {
thinking_budget: None,
include_thoughts: Some(true),
}
}
pub const fn dynamic() -> Self {
Self {
thinking_budget: Some(-1),
include_thoughts: Some(true),
}
}
pub const fn disabled() -> Self {
Self {
thinking_budget: Some(0),
include_thoughts: Some(false),
}
}
pub fn validate(&self) -> Result<(), String> {
if let Some(budget) = self.thinking_budget
&& budget < -1
{
return Err("Thinking budget cannot be less than -1".to_string());
}
Ok(())
}
}
impl Default for ThinkingConfig {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_thinking_config_json_serialization() {
let thinking_config = ThinkingConfig {
thinking_budget: Some(-1),
include_thoughts: Some(true),
};
let json = serde_json::to_string(&thinking_config).unwrap();
println!("ThinkingConfig JSON: {}", json);
assert!(json.contains("thinkingBudget"));
assert!(json.contains("includeThoughts"));
assert!(!json.contains("thinking_budget"));
assert!(!json.contains("include_thoughts"));
}
#[test]
fn test_generation_config_json_serialization() {
let thinking_config = ThinkingConfig {
thinking_budget: Some(-1),
include_thoughts: Some(true),
};
let generation_config = GenerationConfig {
candidate_count: Some(1),
stop_sequences: None,
max_output_tokens: Some(1000),
temperature: Some(0.7),
top_p: Some(0.9),
top_k: Some(40),
response_mime_type: None,
response_schema: None,
thinking_config: Some(thinking_config),
response_modalities: None,
};
let json = serde_json::to_string(&generation_config).unwrap();
println!("GenerationConfig JSON: {}", json);
assert!(json.contains("candidateCount"));
assert!(json.contains("maxOutputTokens"));
assert!(json.contains("topP"));
assert!(json.contains("topK"));
assert!(json.contains("thinkingConfig"));
assert!(json.contains("thinkingBudget"));
assert!(json.contains("includeThoughts"));
}
}
impl SafetySetting {
pub const fn new(category: HarmCategory, threshold: HarmBlockThreshold) -> Self {
Self {
category,
threshold,
}
}
pub const fn block_low_and_above(category: HarmCategory) -> Self {
Self::new(category, HarmBlockThreshold::BlockLowAndAbove)
}
pub const fn block_medium_and_above(category: HarmCategory) -> Self {
Self::new(category, HarmBlockThreshold::BlockMediumAndAbove)
}
pub const fn block_only_high(category: HarmCategory) -> Self {
Self::new(category, HarmBlockThreshold::BlockOnlyHigh)
}
pub const fn block_none(category: HarmCategory) -> Self {
Self::new(category, HarmBlockThreshold::BlockNone)
}
}
impl Content {
pub const fn new(role: Option<String>, parts: Vec<Part>) -> Self {
Self { role, parts }
}
pub fn user_text(text: String) -> Self {
Self {
role: Some("user".to_string()),
parts: vec![Part::Text {
text,
thought: None,
}],
}
}
pub fn model_text(text: String) -> Self {
Self {
role: Some("model".to_string()),
parts: vec![Part::Text {
text,
thought: None,
}],
}
}
pub fn system_text(text: String) -> Self {
Self {
role: None, parts: vec![Part::Text {
text,
thought: None,
}],
}
}
}
impl Part {
pub const fn text(text: String) -> Self {
Self::Text {
text,
thought: None,
}
}
pub const fn thought_summary(text: String) -> Self {
Self::Text {
text,
thought: Some(true),
}
}
pub const fn inline_data(mime_type: String, data: String) -> Self {
Self::InlineData {
inline_data: Blob { mime_type, data },
}
}
pub const fn file_data(file_uri: String, mime_type: Option<String>) -> Self {
Self::FileData {
file_data: FileData {
file_uri,
mime_type,
},
}
}
pub const fn function_call(name: String, args: Option<serde_json::Value>) -> Self {
Self::FunctionCall {
function_call: FunctionCall { name, args },
}
}
pub const fn function_response(name: String, response: serde_json::Value) -> Self {
Self::FunctionResponse {
function_response: FunctionResponse { name, response },
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GeminiFile {
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub display_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub mime_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub size_bytes: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub create_time: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub update_time: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expiration_time: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sha256_hash: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub uri: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub state: Option<GeminiFileState>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<GeminiStatus>,
#[serde(skip_serializing_if = "Option::is_none")]
pub video_metadata: Option<VideoFileMetadata>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum GeminiFileState {
#[serde(rename = "STATE_UNSPECIFIED")]
Unspecified,
#[serde(rename = "PROCESSING")]
Processing,
#[serde(rename = "ACTIVE")]
Active,
#[serde(rename = "FAILED")]
Failed,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GeminiStatus {
#[serde(skip_serializing_if = "Option::is_none")]
pub code: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub message: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub details: Option<Vec<serde_json::Value>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VideoFileMetadata {
#[serde(skip_serializing_if = "Option::is_none")]
pub video_duration: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateFileRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub file: Option<GeminiFile>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateFileResponse {
#[serde(skip_serializing_if = "Option::is_none")]
pub file: Option<GeminiFile>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ListFilesResponse {
#[serde(default)]
pub files: Vec<GeminiFile>,
#[serde(skip_serializing_if = "Option::is_none")]
pub next_page_token: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DownloadFileResponse {
}
#[derive(Debug, Clone, Default)]
pub struct GeminiEmbeddingOptions {
pub task_type: Option<crate::types::EmbeddingTaskType>,
pub title: Option<String>,
pub output_dimensionality: Option<u32>,
}
impl GeminiEmbeddingOptions {
pub fn new() -> Self {
Self::default()
}
pub fn with_task_type(mut self, task_type: crate::types::EmbeddingTaskType) -> Self {
self.task_type = Some(task_type);
self
}
pub fn with_title(mut self, title: impl Into<String>) -> Self {
self.title = Some(title.into());
self
}
pub fn with_output_dimensionality(mut self, dimensions: u32) -> Self {
self.output_dimensionality = Some(dimensions);
self
}
pub fn apply_to_request(
self,
mut request: crate::types::EmbeddingRequest,
) -> crate::types::EmbeddingRequest {
if let Some(task_type) = self.task_type {
request = request.with_task_type(task_type);
}
if let Some(title) = self.title {
request = request.with_provider_param("title", serde_json::Value::String(title));
}
if let Some(dims) = self.output_dimensionality {
request.dimensions = Some(dims);
}
request
}
}
pub trait GeminiEmbeddingRequestExt {
fn with_gemini_config(self, config: GeminiEmbeddingOptions) -> Self;
fn with_gemini_task_type(self, task_type: crate::types::EmbeddingTaskType) -> Self;
fn with_gemini_title(self, title: impl Into<String>) -> Self;
fn with_gemini_dimensions(self, dimensions: u32) -> Self;
}
impl GeminiEmbeddingRequestExt for crate::types::EmbeddingRequest {
fn with_gemini_config(self, config: GeminiEmbeddingOptions) -> Self {
config.apply_to_request(self)
}
fn with_gemini_task_type(self, task_type: crate::types::EmbeddingTaskType) -> Self {
self.with_task_type(task_type)
}
fn with_gemini_title(self, title: impl Into<String>) -> Self {
self.with_provider_param("title", serde_json::Value::String(title.into()))
}
fn with_gemini_dimensions(self, dimensions: u32) -> Self {
let mut request = self;
request.dimensions = Some(dimensions);
request
}
}