Skip to content

Commit 5fa75d4

Browse files
committed
google gemini support
1 parent 2e9e627 commit 5fa75d4

File tree

5 files changed

+106
-18
lines changed

5 files changed

+106
-18
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
[package]
22
name = "rattlebrain"
3-
version = "0.1.6"
3+
version = "0.1.7"
44
edition = "2021"
55
authors = ["Scott Davis <scottleedavis@gmail.com>"]
6-
description = "A Rocket League replay analyzer using Multiple AI agents"
6+
description = "A Rocket League replay analyzer using Multiple AI agents (supports OpenAI, Antrhopic and Gemini)"
77
license = "MIT"
88
repository = "https://github.com/scottleedavis/rattlebrain"
99

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ also see the current [TODOs](TODO.md) for upcoming features.
1717
## Features
1818

1919
- **AI-Enhanced Analysis**: Analyze Rocket League replay files with the help of AI services for in-depth insights.
20-
- **Dynamic AI Selection**: Automatically detects and configures available AI services via environment variables (e.g., `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`).
20+
- **Dynamic AI Selection**: Automatically detects and configures available AI services via environment variables (e.g., `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GEMINI_API_KEY`).
2121
- **Unified Reporting**: Combines outputs from multiple AI agents into a single, comprehensive report.
2222
- **Tactical Insights**: Highlights key plays, strategic opportunities, and areas for improvement.
2323
- **Performance Metrics**: Extracts useful data points to track your progress over time.
@@ -35,10 +35,11 @@ also see the current [TODOs](TODO.md) for upcoming features.
3535
- Get API keys for the AI services you'd like to use (e.g., OpenAI, Claude).
3636

3737
3. Set Environment Variables:
38-
- Add your API keys to your environment variables:
38+
- Add API keys to AI Services in environment variables (at least 1):
3939
```bash
4040
export OPENAI_API_KEY=<your_openai_api_key>
4141
export ANTHROPIC_API_KEY=<your_anthropic_api_key>
42+
export GEMINI_API_KEY=<your_google_gemini_api_key>
4243
```
4344

4445
---

src/ai/google.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
use reqwest::Client;
2+
use serde::{Deserialize, Serialize};
3+
use std::env;
4+
use std::error::Error;
5+
6+
#[derive(Debug, Serialize)]
7+
struct GeminiRequest {
8+
contents: Vec<Content>,
9+
}
10+
11+
#[derive(Debug, Serialize, Deserialize)] // Added Deserialize for request and response
12+
struct Content {
13+
parts: Vec<Part>,
14+
}
15+
16+
#[derive(Debug, Serialize, Deserialize)] // Added Deserialize for request and response
17+
struct Part {
18+
text: String,
19+
}
20+
21+
#[derive(Debug, Deserialize)]
22+
struct GeminiResponse {
23+
candidates: Vec<Candidate>,
24+
}
25+
26+
#[derive(Debug, Deserialize)]
27+
struct Candidate {
28+
content: Content,
29+
}
30+
31+
/// Sends a query to Gemini AI and returns the response.
32+
///
33+
/// # Arguments
34+
/// * `prompt` - The prompt string to send to Gemini.
35+
///
36+
/// # Returns
37+
/// A `Result` containing the response string, or an error if the request fails.
38+
pub async fn query_gemini(prompt: &str) -> Result<String, Box<dyn Error>> {
39+
// Retrieve the API key from the environment
40+
let api_key = env::var("GEMINI_API_KEY").expect("GEMINI_API_KEY must be set");
41+
42+
// API URL
43+
let base_url = format!(
44+
"https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-latest:generateContent?key={}",
45+
api_key
46+
);
47+
48+
// Prepare the request body
49+
let request_body = GeminiRequest {
50+
contents: vec![Content {
51+
parts: vec![Part {
52+
text: prompt.to_string(),
53+
}],
54+
}],
55+
};
56+
57+
// Initialize HTTP client
58+
let client = Client::new();
59+
60+
// Send the request
61+
let response = client
62+
.post(&base_url)
63+
.header("Content-Type", "application/json")
64+
.json(&request_body)
65+
.send()
66+
.await?;
67+
68+
// Extract status and response text for debugging
69+
let status = response.status();
70+
let response_text = response.text().await.unwrap_or_else(|_| "Unknown error".to_string());
71+
72+
if status.is_success() {
73+
// eprintln!("Successful response: {}", response_text); // Debugging raw response
74+
// Parse the response JSON
75+
let response_body: GeminiResponse = serde_json::from_str(&response_text)?;
76+
77+
// Extract and concatenate text from the candidate's content parts
78+
let output = response_body
79+
.candidates
80+
.into_iter()
81+
.flat_map(|candidate| candidate.content.parts)
82+
.map(|part| part.text)
83+
.collect::<Vec<String>>()
84+
.join("\n");
85+
86+
Ok(output)
87+
} else {
88+
eprintln!("Failed response: {}", response_text); // Debugging raw error response
89+
Err(Box::new(std::io::Error::new(
90+
std::io::ErrorKind::Other,
91+
format!("Request failed with status: {} - {}", status, response_text),
92+
)))
93+
}
94+
}

src/ai/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
pub mod openai;
22
pub mod anthropic;
3+
pub mod google;

src/query.rs

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::ai::openai;
22
use crate::ai::anthropic;
3+
use crate::ai::google;
34

45
use std::fs;
56
use std::env;
@@ -117,20 +118,11 @@ pub async fn query_ai(match_guid: &str, focus: &str) -> io::Result<String> {
117118

118119
// Gemini
119120
if let Ok(gemini_key) = env::var("GEMINI_API_KEY") {
120-
println!("Using Gemini with key: {}", &gemini_key[0..4]);
121-
responses.push(format!(
122-
"Gemini response to '{}': [This is a stubbed response from Gemini]",
123-
query
124-
));
125-
}
126-
127-
// GitHub Copilot
128-
if let Ok(copilot_key) = env::var("COPILOT_API_KEY") {
129-
println!("Using GitHub Copilot with key: {}", &copilot_key[0..4]);
130-
responses.push(format!(
131-
"GitHub Copilot response to '{}': [This is a stubbed response from Copilot]",
132-
query
133-
));
121+
println!("Using Google with key: {}****", &gemini_key[0..8]);
122+
match google::query_gemini(&query).await {
123+
Ok(response) => responses.push(format!("## Gemini response\n\n {}", response)),
124+
Err(e) => eprintln!("Error querying Gemini: {}", e),
125+
}
134126
}
135127

136128
// Handle case where no providers are configured

0 commit comments

Comments
 (0)