Gargi_AI / test_gemini.py
Sameer Singh
Added
5aaf5ba
Raw
History Blame Contribute Delete
6.13 kB
"""Live diagnostic for the configured Gemini API key and Gemini Live API.
This is intentionally a runnable diagnostic, not a pytest unit test, because it
makes real billable/network API calls.
"""
import argparse
import asyncio
import sys
from pathlib import Path
import async_timeout
from google import genai
from google.genai import types
from gargi_ai.config import get_settings
DEFAULT_PROMPT = (
"You are Professor AI. Explain why the sky looks blue to a curious "
"12-year-old in three short paragraphs, then ask one check-for-understanding "
"question."
)
DEFAULT_LIVE_MODEL = "gemini-3.1-flash-live-preview"
def print_heading(title: str) -> None:
print(f"\n{'=' * 72}\n{title}\n{'=' * 72}")
def check_standard_response(
client: genai.Client, model: str, prompt: str
) -> bool:
print_heading("1. STANDARD GEMINI API TEST")
print(f"Model : {model}")
print(f"Prompt: {prompt}\n")
try:
response = client.models.generate_content(model=model, contents=prompt)
answer = (response.text or "").strip()
if not answer:
print("FAILED: Gemini returned an empty response.")
return False
print("Gemini response:\n")
print(answer)
print("\nStatus: PASSED - normal Gemini generation is responding.")
return True
except Exception as exc:
print(f"Status: FAILED - {type(exc).__name__}: {exc}")
return False
async def check_live_response(
client: genai.Client,
model: str,
output_path: Path | None,
) -> bool:
print_heading("2. GEMINI LIVE API TEST")
print(f"Live model: {model}")
print("Opening a WebSocket session and requesting a short audio greeting...\n")
audio = bytearray()
transcript_parts: list[str] = []
turn_completed = False
config = types.LiveConnectConfig(
response_modalities=[types.Modality.AUDIO],
output_audio_transcription=types.AudioTranscriptionConfig(),
system_instruction=(
"You are Professor AI. Keep this diagnostic response to one short sentence."
),
)
try:
async with async_timeout.timeout(45):
async with client.aio.live.connect(model=model, config=config) as session:
await session.send_realtime_input(
text="Say: Hello! Professor AI Live API is working."
)
async for response in session.receive():
content = response.server_content
if not content:
continue
if content.output_transcription and content.output_transcription.text:
transcript_parts.append(content.output_transcription.text)
if content.model_turn:
for part in content.model_turn.parts or []:
if part.inline_data and part.inline_data.data:
audio.extend(part.inline_data.data)
if content.turn_complete:
turn_completed = True
break
transcript = "".join(transcript_parts).strip()
print(f"WebSocket connected : yes")
print(f"Turn completed : {turn_completed}")
print(f"Audio received : {len(audio):,} bytes (PCM 24 kHz, 16-bit)")
print(f"Transcription : {transcript or '<not returned>'}")
if output_path and audio:
output_path.parent.mkdir(parents=True, exist_ok=True)
output_path.write_bytes(audio)
print(f"Raw audio saved : {output_path.resolve()}")
passed = turn_completed and bool(audio)
if passed:
print("\nStatus: PASSED - this key supports Gemini Live API.")
else:
print("\nStatus: FAILED - the session opened but no complete audio turn arrived.")
return passed
except Exception as exc:
print(f"Status: FAILED - {type(exc).__name__}: {exc}")
print(
"The normal API may still work even if this preview Live model is "
"unavailable for the key, account, or region."
)
return False
async def main() -> int:
parser = argparse.ArgumentParser(
description="Test the Gemini API key with normal generation and Live API."
)
parser.add_argument("--prompt", default=DEFAULT_PROMPT)
parser.add_argument("--skip-live", action="store_true")
parser.add_argument(
"--live-model",
default=None,
help=f"Defaults to GEMINI_LIVE_MODEL or {DEFAULT_LIVE_MODEL}.",
)
parser.add_argument(
"--save-live-audio",
type=Path,
metavar="PATH",
help="Optionally save returned raw 24 kHz PCM audio.",
)
args = parser.parse_args()
settings = get_settings()
api_key = settings.gemini_api_key.strip()
if not api_key:
print("FAILED: GEMINI_API_KEY is missing from .env.")
return 1
live_model = (
args.live_model
or getattr(settings, "gemini_live_model", None)
or DEFAULT_LIVE_MODEL
)
print("Gemini credentials loaded from .env (key value hidden).")
print(f"Key length: {len(api_key)} characters")
client = genai.Client(api_key=api_key)
try:
standard_ok = check_standard_response(
client, settings.gemini_model, args.prompt
)
live_ok = True
if not args.skip_live:
live_ok = await check_live_response(
client, live_model, args.save_live_audio
)
print_heading("FINAL RESULT")
print(f"Standard API: {'PASSED' if standard_ok else 'FAILED'}")
print(
f"Live API : "
f"{'SKIPPED' if args.skip_live else ('PASSED' if live_ok else 'FAILED')}"
)
return 0 if standard_ok and live_ok else 1
finally:
await client.aio.aclose()
client.close()
if __name__ == "__main__":
try:
raise SystemExit(asyncio.run(main()))
except KeyboardInterrupt:
print("\nCancelled.")
sys.exit(130)