SPB Git

spb/ai-atlas

Public
7.1 KB · 100 lines python
1import pytest23from aiatlas.connectors.labs.google import DEEPMIND_RSS, DOCS, GOOGLE_AI_RSS, GoogleConnector4from aiatlas.sdk.facts import Target5from tests.conftest import claims_of, entity_names, extract_from_fixture, fixture_path678@pytest.fixture9def connector() -> GoogleConnector:10    return GoogleConnector()111213async def test_models_overview(connector):14    target = Target(url=f"{DOCS}/models", doc_type="model_docs", key="models")15    facts = await extract_from_fixture(connector, target, fixture_path("google", "models.html"))16    models = entity_names(facts, "model")17    assert len(models) >= 4018    assert {"Gemini 3.8 Flash", "Gemini 2.5 Pro", "Nano Banana 2", "Veo 3.1", "Gemini Embedding 2"} <= models19    flash = claims_of(facts, "Gemini 3.8 Flash")20    assert flash["api_model_id"] == "gemini-3.8-flash" and flash["status"] == "active" and flash["family"] == "Gemini"21    assert claims_of(facts, "Gemini 3.1 Pro")["status"] == "preview"22    assert claims_of(facts, "Gemini 2.0 Flash")["status"] == "retired"23    ref = next(e for e in facts.entities if e.name == "Nano Banana 2")24    assert ref.identifiers == {"gemini_model_id": "gemini-3.1-flash-image"}25    pages = [t for t in facts.targets if t.doc_type == "model_page"]26    assert len(pages) >= 40 and pages[0].url == f"{DOCS}/models/gemini-3.8-flash"27    # several endpoints under one display name: identity = first endpoint, the others are a claim (never aliases)28    transcribe = next(e for e in facts.entities if e.name == "Gemini 3.5 Transcribe")29    assert transcribe.identifiers == {"gemini_model_id": "gemini-3.5-transcribe"} and "gemini-3.5-transcribe-live" not in transcribe.aliases30    assert claims_of(facts, "Gemini 3.5 Transcribe")["api_aliases"] == ["gemini-3.5-transcribe-live"]31    assert len([e for e in facts.entities if e.name == "Gemini Embedding 2"]) == 132    omni = {e.name: e.identifiers["gemini_model_id"] for e in facts.entities if e.entity_type == "model" and e.name.startswith("Gemini Omni Flash")}33    assert omni == {"Gemini Omni Flash": "gemini-omni-flash"}                  # the GA endpoint row folds into the card's api_aliases34    assert claims_of(facts, "Gemini Omni Flash")["api_aliases"] == ["gemini-omni-1.1-flash"]35    assert sum(1 for c in facts.claims if c.property == "api_aliases" and c.entity.name == "Gemini Omni Flash") == 136    names = [e.name.lower() for e in facts.entities if e.entity_type == "model"]37    assert len(names) == len(set(names))                                       # every model ref has a distinct name inside the document38    props = [(c.entity.name, c.property) for c in facts.claims if c.property in ("api_model_id", "context_length")]39    assert len(props) == len(set(props))404142async def test_model_pages(connector):43    target = Target(url=f"{DOCS}/models/gemini-3.8-flash", doc_type="model_page", key="model:gemini-3.8-flash", meta={"api_id": "gemini-3.8-flash"})44    facts = await extract_from_fixture(connector, target, fixture_path("google", "model-gemini-3.8-flash.html"))45    m = claims_of(facts, "Gemini 3.8 Flash")46    assert m["context_length"] == 1_048_576 and m["max_output_tokens"] == 65_53647    assert m["modalities_input"] == ["text", "image", "video", "audio", "pdf"] and m["modalities_output"] == ["text"]48    assert m["tool_calling"] is True and m["structured_output"] is True and m["reasoning"] is True and m["vision"] is True49    assert "Function calling" in m["capabilities"] and "Image generation" not in m["capabilities"]50    assert m["latest_update"] == "2026-09" and m["versions"] == {"stable": ["gemini-3.8-flash"]}51    target = Target(url=f"{DOCS}/models/gemini-2.5-pro", doc_type="model_page", key="model:gemini-2.5-pro", meta={"api_id": "gemini-2.5-pro"})52    facts = await extract_from_fixture(connector, target, fixture_path("google", "model-gemini-2.5-pro.html"))53    pro = claims_of(facts, "Gemini 2.5 Pro")54    assert pro["knowledge_cutoff"] == "2025-01" and pro["latest_update"] == "2025-06" and pro["context_length"] == 1_048_576555657async def test_pricing(connector):58    target = Target(url=f"{DOCS}/pricing", doc_type="pricing", key="pricing")59    facts = await extract_from_fixture(connector, target, fixture_path("google", "pricing.html"))60    by_id = {p.provider_model_id: p for p in facts.prices}61    assert len(by_id) >= 2562    flash = by_id["gemini-3.8-flash"]63    assert (flash.input_per_mtok, flash.cached_input_per_mtok, flash.output_per_mtok) == (0.75, 0.075, 3.75)64    assert (flash.batch_input_per_mtok, flash.batch_output_per_mtok) == (0.375, 1.875)65    assert flash.features["scheduled_input_per_mtok"] == 1.5 and flash.features["promotional_until"] == "December 31, 2026"66    assert flash.features["priority_input_per_mtok"] == 1.35 and flash.features["free_tier"] is True67    assert flash.provider.identifiers["registry_provider"] == "google-gemini-api" and flash.model.name == "Gemini 3.8 Flash"68    pro = by_id["gemini-2.5-pro"]69    assert (pro.input_per_mtok, pro.cached_input_per_mtok, pro.output_per_mtok) == (1.25, 0.125, 10.0)70    assert pro.features["long_context_input_per_mtok"] == 2.5 and pro.features["long_context_output_per_mtok"] == 15.071    assert pro.features["cache_storage_per_mtok_hour"] == 4.572    lite = by_id["gemini-2.5-flash-lite"]73    assert lite.input_per_mtok == 0.10 and lite.features["audio_input_per_mtok"] == 0.30       # "(text / image / video)" is a modality list, not a unit74    assert by_id["gemini-2.5-flash-image"].per_image == 0.03975    assert by_id["lyria-3.5"].per_request == 0.0876    assert "720p" in str(by_id["veo-3.1-generate-preview"].features["per_second"])77    assert by_id["gemini-embedding-2"].input_per_mtok == 0.20 and by_id["gemini-embedding-2"].features["image_input_per_mtok"] == 0.45787980async def test_changelog(connector):81    target = Target(url=f"{DOCS}/changelog", doc_type="listing", key="changelog")82    facts = await extract_from_fixture(connector, target, fixture_path("google", "changelog.html"))83    events = facts.events84    assert len(events) >= 80 and all(e.effective_at is not None and e.dedupe_key for e in events)85    assert events[0].summary == "Gemini API: Lyria 3.5 in public preview" and events[0].effective_at.date().isoformat() == "2026-09-03"86    ga = next(e for e in events if "Gemini 3.8 Flash generally available" in e.summary)87    assert ga.category == "release" and "gemini-3.8-flash" in ga.meta["models"]88    assert len({e.dedupe_key for e in events}) == len(events)899091async def test_feeds(connector):92    facts = await extract_from_fixture(connector, Target(url=DEEPMIND_RSS, doc_type="feed", key="deepmind_feed"), fixture_path("google", "deepmind.rss.xml"),93                                       content_type="application/rss+xml")94    assert len(facts.events) == 100 and facts.events[0].entity.name == "Google DeepMind"95    assert any(e.category == "release" and "WeatherNext 3" in e.summary for e in facts.events)96    facts = await extract_from_fixture(connector, Target(url=GOOGLE_AI_RSS, doc_type="feed", key="google_ai_feed"), fixture_path("google", "google-ai-blog.rss.xml"),97                                       content_type="application/rss+xml")98    assert len(facts.events) == 20 and facts.events[0].entity.name == "Google"99    assert facts.events[0].effective_at.date().isoformat() == "2026-09-10"100
Files · c64e7b8df811b05589bef5f6549ffc03d7075427
Menu

Theme