Skip to content

Commit 922551f

Browse files
Merge pull request #56 from goldlabelapps/staging
Add Gemini POST endpoint and tests
2 parents 9bdc9c8 + 5429c6f commit 922551f

3 files changed

Lines changed: 102 additions & 4 deletions

File tree

app/api/gemini/gemini.py

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,57 @@
1-
from fastapi import APIRouter
1+
import os
2+
from fastapi import APIRouter, HTTPException
3+
from app.utils.make_meta import make_meta
24

35
router = APIRouter()
46

57
@router.get("/gemini")
68
def root() -> dict:
79
"""GET /gemini endpoint."""
8-
return {"message": "Welcome to the Gemini API!"}
10+
meta = make_meta("success", "Gemini endpoint says hello")
11+
return {"meta": meta}
12+
13+
@router.post("/gemini")
14+
def gemini_post(payload: dict) -> dict:
15+
"""POST /gemini: send prompt to Gemini, returns completion google-genai SDK."""
16+
prompt = payload.get("prompt")
17+
if not prompt:
18+
raise HTTPException(status_code=400, detail="Missing 'prompt' in request body.")
19+
api_key = os.getenv("GEMINI_API_KEY")
20+
if not api_key:
21+
raise HTTPException(status_code=500, detail="Gemini API key not configured.")
22+
import logging
23+
try:
24+
from google import genai
25+
client = genai.Client(api_key=api_key)
26+
# Try a list of known Gemini model names
27+
model_names = [
28+
"models/gemini-flash-latest",
29+
"models/gemini-1.5-pro",
30+
"models/gemini-1.5-flash",
31+
"models/gemini-1.0-pro",
32+
"models/gemini-pro",
33+
"models/gemini-pro-vision"
34+
]
35+
response = None
36+
completion = None
37+
used_model = None
38+
errors = {}
39+
for model_name in model_names:
40+
try:
41+
response = client.models.generate_content(model=model_name, contents=prompt)
42+
completion = getattr(response, "text", None)
43+
if completion:
44+
used_model = model_name
45+
break
46+
except Exception as e:
47+
errors[model_name] = str(e)
48+
continue
49+
if not completion:
50+
error_details = " | ".join([f"{k}: {v}" for k, v in errors.items()])
51+
raise Exception(f"No available Gemini model succeeded for generate_content with your API key. Details: {error_details}")
52+
except Exception as e:
53+
meta = make_meta("error", f"Gemini API error: {str(e)}")
54+
return {"meta": meta, "data": {}}
55+
meta = make_meta("success", f"Gemini completion received from {used_model}")
56+
return {"meta": meta, "data": {"prompt": prompt, "completion": completion}}
957

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ python-dotenv>=1.0.0
88
psycopg2-binary>=2.9.0
99
python-multipart>=0.0.20
1010
Faker>=25.2.0
11+
google-genai>=0.3.0

tests/test_gemini.py

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
import os
2+
import pytest
3+
def test_gemini_real_api():
4+
api_key = os.getenv("GEMINI_API_KEY")
5+
if not api_key:
6+
pytest.skip("GEMINI_API_KEY not set; skipping real Gemini API test.")
7+
from google import genai
8+
client = genai.Client(api_key=api_key)
9+
try:
10+
response = client.models.generate_content(
11+
model="models/gemini-flash-latest",
12+
contents="Say hello from Gemini!"
13+
)
14+
completion = getattr(response, "text", None)
15+
assert completion is not None and "hello" in completion.lower()
16+
except Exception as e:
17+
pytest.fail(f"Gemini real API call failed: {e}")
118
import sys
219
import os
320
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../")))
@@ -8,7 +25,39 @@
825
client = TestClient(app)
926

1027

11-
def test_gemini_endpoint():
28+
29+
def test_gemini_get_endpoint():
1230
response = client.get("/gemini")
1331
assert response.status_code == 200
14-
assert response.json() == {"message": "Welcome to the Gemini API!"}
32+
data = response.json()
33+
assert "meta" in data
34+
assert data["meta"]["severity"] == "success"
35+
assert "Gemini endpoint says hello" in data["meta"]["title"]
36+
37+
38+
def test_gemini_post_endpoint(monkeypatch):
39+
# Mock google-genai SDK to avoid real API call
40+
class MockGenAIResponse:
41+
text = "Test completion"
42+
43+
class MockGenAIModel:
44+
def generate_content(self, model, contents):
45+
return MockGenAIResponse()
46+
47+
class MockGenAIClient:
48+
models = MockGenAIModel()
49+
50+
monkeypatch.setattr("google.genai.Client", lambda *args, **kwargs: MockGenAIClient())
51+
52+
payload = {"prompt": "Test prompt"}
53+
response = client.post("/gemini", json=payload)
54+
assert response.status_code == 200
55+
data = response.json()
56+
assert "meta" in data
57+
assert data["meta"]["severity"] == "success"
58+
assert "Gemini completion received" in data["meta"]["title"]
59+
assert data["data"]["prompt"] == "Test prompt"
60+
assert data["data"]["completion"] == "Test completion"
61+
assert "data" in data
62+
assert data["data"]["prompt"] == "Test prompt"
63+
assert data["data"]["completion"] == "Test completion"

0 commit comments

Comments
 (0)