Documentation Index
Fetch the complete documentation index at: https://mintlify.com/mofa-org/mofa/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The GeminiProvider implements the LLMProvider trait for Google’s Gemini API, supporting Gemini 1.5 Pro and other Gemini models. It provides text generation and multi-modal capabilities through the Generative Language API v1beta.
The Gemini provider is currently experimental and supports text-only and vision capabilities. Tool/function calling support is planned for future releases.
Configuration
GeminiConfig
pub struct GeminiConfig {
pub api_key: String,
pub base_url: String,
pub default_model: String,
pub default_temperature: f32,
pub default_max_tokens: u32,
pub timeout_secs: u64,
}
base_url
String
default:"https://generativelanguage.googleapis.com"
API base URL for the Generative Language API
default_model
String
default:"gemini-1.5-pro-latest"
Default model to use when not specified in requestsAvailable models:
gemini-1.5-pro-latest
gemini-1.5-flash-latest
gemini-pro
Default sampling temperature (0.0 to 1.0)
Default maximum tokens to generate
Request timeout in seconds
Creating a Provider
Basic Usage
use mofa_foundation::llm::GeminiProvider;
let provider = GeminiProvider::new("your-api-key");
From Environment
// Reads GEMINI_API_KEY, GEMINI_MODEL, GEMINI_BASE_URL
let provider = GeminiProvider::from_env();
With Configuration
use mofa_foundation::llm::{GeminiProvider, GeminiConfig};
let config = GeminiConfig::new("your-api-key")
.with_model("gemini-1.5-flash-latest")
.with_temperature(0.8)
.with_max_tokens(4096)
.with_timeout(120);
let provider = GeminiProvider::with_config(config);
Supported Models
Gemini 1.5 Pro
- gemini-1.5-pro-latest: Most capable model with 1M+ token context window
- gemini-1.5-flash-latest: Faster, more efficient version
Gemini Pro
- gemini-pro: Standard Gemini model
- gemini-pro-vision: Vision-enabled variant (legacy)
Features
Capabilities
let provider = GeminiProvider::new("api-key");
println!("Streaming: {}", provider.supports_streaming()); // false (planned)
println!("Tools: {}", provider.supports_tools()); // false (planned)
println!("Vision: {}", provider.supports_vision()); // false (planned)
Basic Chat Completion
use mofa_foundation::llm::{LLMClient, GeminiProvider};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let provider = Arc::new(GeminiProvider::new("your-api-key"));
let client = LLMClient::new(provider);
let response = client.chat()
.system("You are a helpful assistant")
.user("What is Rust?")
.send()
.await?;
println!("Response: {}", response.content().unwrap());
Ok(())
}
Multi-Turn Conversation
use mofa_foundation::llm::*;
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let provider = Arc::new(GeminiProvider::from_env());
let client = LLMClient::new(provider);
let response = client.chat()
.system("You are a knowledgeable programming expert")
.user("What is Rust?")
.assistant("Rust is a systems programming language...")
.user("What are its main benefits?")
.send()
.await?;
println!("Answer: {}", response.content().unwrap());
Ok(())
}
Vision (Multi-Modal)
use mofa_foundation::llm::*;
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let provider = Arc::new(GeminiProvider::new("api-key"));
let client = LLMClient::new(provider);
let content = MessageContent::Parts(vec![
ContentPart::Text {
text: "What do you see in this image?".to_string(),
},
ContentPart::Image {
image_url: ImageUrl {
url: "data:image/png;base64,iVBORw0KGgoAAAA...".to_string(),
detail: Some(ImageDetail::High),
},
},
]);
let response = client.chat()
.user_with_content(content)
.send()
.await?;
println!("Analysis: {}", response.content().unwrap());
Ok(())
}
use mofa_foundation::llm::*;
let content = MessageContent::Parts(vec![
ContentPart::Text {
text: "Transcribe this audio".to_string(),
},
ContentPart::Audio {
audio: AudioInput {
data: "data:audio/mp3;base64,SUQzBAA...".to_string(),
format: "mp3".to_string(),
},
},
]);
let response = client.chat()
.user_with_content(content)
.send()
.await?;
use mofa_foundation::llm::*;
let content = MessageContent::Parts(vec![
ContentPart::Text {
text: "Describe what happens in this video".to_string(),
},
ContentPart::Video {
video: VideoInput {
data: "data:video/mp4;base64,AAAAIGZ0eXBpc29t...".to_string(),
format: "mp4".to_string(),
},
},
]);
let response = client.chat()
.user_with_content(content)
.send()
.await?;
Generation Parameters
use mofa_foundation::llm::*;
let response = client.chat()
.user("Write a short poem")
.temperature(0.9) // Higher creativity
.max_tokens(500) // Limit output length
.top_p(0.95) // Nucleus sampling
.stop(vec!["\n\n"]) // Stop sequences
.send()
.await?;
Error Handling
The provider maps Gemini API errors to LLMError variants:
use mofa_foundation::llm::LLMError;
match client.chat().user("Test").send().await {
Ok(response) => println!("Success: {}", response.content().unwrap()),
Err(LLMError::ApiError { code, message }) => {
println!("API Error {}: {}", code.unwrap_or_default(), message)
}
Err(LLMError::Timeout(msg)) => println!("Timeout: {}", msg),
Err(LLMError::NetworkError(msg)) => println!("Network error: {}", msg),
Err(LLMError::RateLimited(msg)) => println!("Rate limited: {}", msg),
Err(e) => println!("Other error: {}", e),
}
let provider = GeminiProvider::new("api-key");
let info = provider.get_model_info("gemini-1.5-pro-latest").await?;
println!("Model: {}", info.name);
println!("Max output tokens: {}", info.max_output_tokens.unwrap());
println!("Capabilities:");
println!(" - Streaming: {}", info.capabilities.streaming);
println!(" - Tools: {}", info.capabilities.tools);
println!(" - Vision: {}", info.capabilities.vision);
println!(" - JSON mode: {}", info.capabilities.json_mode);
Health Check
let provider = GeminiProvider::new("api-key");
if provider.health_check().await? {
println!("Gemini API is accessible");
} else {
println!("Gemini API is not responding");
}
Complete Example
use mofa_foundation::llm::*;
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create provider from environment
let config = GeminiConfig::from_env()
.with_model("gemini-1.5-pro-latest")
.with_temperature(0.7)
.with_max_tokens(2048);
let provider = Arc::new(GeminiProvider::with_config(config));
let client = LLMClient::new(provider.clone());
// Check health
if !provider.health_check().await? {
eprintln!("Gemini API is not accessible");
return Ok(());
}
// Simple query
println!("Simple Query:");
let answer = client.ask("What is the capital of France?").await?;
println!("Answer: {}\n", answer);
// Multi-turn conversation
println!("Multi-turn Conversation:");
let response = client.chat()
.system("You are a travel guide")
.user("I'm visiting Paris. What should I see?")
.send()
.await?;
println!("Recommendations: {}\n", response.content().unwrap());
// Vision example (with base64 encoded image)
println!("Vision Analysis:");
let vision_content = MessageContent::Parts(vec![
ContentPart::Text {
text: "What landmarks are in this image?".to_string(),
},
ContentPart::Image {
image_url: ImageUrl {
url: "data:image/jpeg;base64,/9j/4AAQSkZJRg...".to_string(),
detail: None,
},
},
]);
let vision_response = client.chat()
.user_with_content(vision_content)
.send()
.await?;
println!("Analysis: {}\n", vision_response.content().unwrap());
// Usage statistics
if let Some(usage) = response.usage {
println!("Token Usage:");
println!(" Prompt: {} tokens", usage.prompt_tokens);
println!(" Completion: {} tokens", usage.completion_tokens);
println!(" Total: {} tokens", usage.total_tokens);
}
// Provider info
println!("\nProvider: {}", provider.name());
println!("Default model: {}", provider.default_model());
Ok(())
}
Limitations
Current limitations of the Gemini provider:
- Streaming: Not yet implemented (returns error)
- Tool calling: Not yet implemented (returns unsupported)
- Function calling: Planned for future release
- Embeddings: Not supported by Generative Language API v1beta
Environment Variables
GEMINI_API_KEY: Google AI API key (required)
GEMINI_MODEL: Default model name
GEMINI_BASE_URL: Custom API base URL
API Key Setup
- Visit Google AI Studio
- Sign in with your Google account
- Click “Get API Key”
- Copy the key and set it as
GEMINI_API_KEY environment variable
export GEMINI_API_KEY="your-api-key-here"
Context Window
Gemini 1.5 Pro supports extremely large context windows:
- gemini-1.5-pro-latest: Up to 1 million tokens (experimental: 2 million)
- gemini-1.5-flash-latest: Up to 1 million tokens
- gemini-pro: 32,768 tokens
Rate Limits
Be aware of Gemini API rate limits:
- Free tier: 60 requests per minute
- Paid tier: Higher limits based on quota
The provider will return LLMError::RateLimited when limits are exceeded.
Best Practices
- API Key Security: Store API keys in environment variables, not in code
- Error Handling: Always handle API errors gracefully
- Timeouts: Set appropriate timeouts for long-running requests
- Rate Limiting: Implement retry logic with exponential backoff
- Context Management: Be mindful of context window limits
- Multi-modal Content: Use appropriate formats for images (JPEG, PNG, WebP)
- System Instructions: Use system messages to set behavior and context