Skip to content

Commit c44bb3b

Browse files
authored
Merge pull request #21 from nshkrdotcom/fix-vertex-models
Fix: update Vertex AI model path handling
2 parents 80a240d + 9085db6 commit c44bb3b

47 files changed

Lines changed: 2785 additions & 659 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,85 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.10.0] - 2026-02-22
11+
12+
### Added
13+
14+
#### Model Registry (`Gemini.ModelRegistry`)
15+
- **Canonical model registry** with capability metadata sourced from Gemini model catalog pages
16+
- Model lookup by code, resource-style names (`models/`, `publishers/google/models/`), and aliases
17+
- Capability checks for `:live_api`, `:thinking`, `:function_calling`, `:structured_outputs`, `:audio_generation`, `:image_generation`, `:batch_api`, and `:caching`
18+
- Support state tracking: `:supported`, `:not_supported`, `:experimental`, `:unknown`
19+
- Modality tracking (input/output): `:text`, `:image`, `:video`, `:audio`, `:pdf`, `:embeddings`, `:music`
20+
- Live-model candidate selection by modality (`:text` / `:audio`)
21+
22+
#### Config API Additions
23+
- **`Gemini.Config.model_info/1`**: Return model metadata from the registry by key atom or model string
24+
- **`Gemini.Config.model_supports?/2,3`**: Check whether a model supports a given capability
25+
- **`Gemini.Config.models_with_capability/1,2`**: List model codes matching a capability and support state
26+
- **`Gemini.Config.live_registry_candidates/1`**: Registry-backed Live API candidate model codes for a modality
27+
28+
#### New Model Entries
29+
- `gemini-3.1-pro-preview` and `gemini-3.1-pro-preview-customtools` (Gemini 3.1 preview)
30+
- `gemini-2.5-flash-native-audio-latest` (latest native audio)
31+
- Legacy Live aliases: `gemini-live-2.5-flash`, `gemini-live-2.5-flash-preview`, `gemini-live-2.5-flash-native-audio`, etc.
32+
- Specialized model families: `gemini-2.5-computer-use-preview-10-2025`, `gemini-robotics-er-1.5-preview`, `lyria-realtime-exp`, `veo-3.1-generate-preview`, `veo-3.1-fast-generate-preview`, `imagen-4.0-generate-001`, `imagen-4.0-ultra-generate-001`, `imagen-4.0-fast-generate-001`
33+
34+
#### ADC: `GOOGLE_APPLICATION_CREDENTIALS_JSON` Support
35+
- New ADC credential source for containerized environments (Heroku, Fly.io, Railway, Docker) where mounting credential files is impractical
36+
- Set `GOOGLE_APPLICATION_CREDENTIALS_JSON='{"type":"service_account",...}'` with full JSON content
37+
- Parsed before the standard file-path `GOOGLE_APPLICATION_CREDENTIALS` in the credential discovery chain
38+
- Service account JSON parsing now uses an explicit key allowlist instead of `String.to_atom/1`
39+
40+
#### Vertex AI Model Endpoints
41+
- **`list_models/1`** uses the correct Vertex publisher models endpoint (`/v1beta1/publishers/google/models`) with `pageSize`/`pageToken` query params
42+
- **`list_models/1` pagination**: accepts `:page_size` and `:page_token` options passed as query parameters
43+
- **`get_model/2`** uses `publishers/google/models/{model}` path for Vertex AI
44+
- **`publisherModels` response normalization**: Vertex AI `list_models` responses are transparently normalized to the same `%ListModelsResponse{}` shape as Gemini API responses
45+
46+
#### HTTP Client Per-Request Auth Override
47+
- `Gemini.Client.HTTP` verb functions (`get`, `post`, `patch`, `delete`) now respect `:auth`, `:api_key`, `:project_id`, `:location`, `:access_token`, and `:service_account` options passed per-request
48+
- Absolute paths (`/v1beta1/...`) and full URLs are passed through without re-prefixing
49+
50+
#### Vertex Live Session Model Prefix
51+
- Live sessions with `auth: :vertex_ai` now build correct `projects/{p}/locations/{l}/publishers/google/models/{m}` resource names in the setup message
52+
53+
#### `stream_generate/2` Configurable Timeout
54+
- New `:stream_timeout` option (default: 60,000ms, up from hardcoded 30,000ms) for `Gemini.stream_generate/2`
55+
- Stream cleanup on timeout: `Coordinator.stop_stream/1` is called before returning the error, preventing orphaned streams
56+
57+
#### Live API ADC Integration Test
58+
- New `test/live_api/adc_live_test.exs` for end-to-end ADC-authenticated Live API sessions
59+
60+
### Changed
61+
- **Vertex Live API upgraded to v1**: WebSocket endpoint changed from `v1beta1.LlmBidiService/BidiGenerateContent` to `v1.LlmBidiService/BidiGenerateContent`; Vertex WebSocket path no longer appends `?project=...&location=...` query parameters
62+
- **Live model resolution uses registry**: `Gemini.Live.Models.resolve/1` now consults `ModelRegistry` plus runtime `list_models` results instead of hardcoded candidate lists
63+
- **Live model auth-aware candidate selection**: separate candidate and default lists for `:gemini` vs `:vertex_ai` auth strategies; Vertex AI candidates exclude Gemini-only `gemini-live-*` aliases; smart modality-based fallback scans available models when no candidate matches
64+
- **Default text live model**: changed from `gemini-2.0-flash-exp` to `gemini-2.5-flash-native-audio-preview-12-2025`
65+
- **`latest` model alias**: updated from `gemini-3-pro-preview` to `gemini-3.1-pro-preview`
66+
- **ADC credential discovery order**: now `GOOGLE_APPLICATION_CREDENTIALS_JSON``GOOGLE_APPLICATION_CREDENTIALS` → gcloud user creds → metadata server
67+
- **`Live.Models.candidates/1`** and **`Live.Models.default/1`** now accept an optional `opts` keyword list for auth-aware candidate selection
68+
- **`Live.Setup.normalize_model_name/1`**: now recognizes `projects/`, `publishers/`, and `models/` prefixes
69+
- **Video generation request format**: flattened request params — `numberOfVideos`, `durationSeconds`, `aspectRatio`, `personGeneration` are now top-level keys instead of nested under `videoConfig`; compatible with Veo 3.1 API requirements
70+
- **Video `person_generation` default**: changed from `:allow_none` to `:dont_allow`; format changed from camelCase (`allowAdult`) to snake_case (`allow_adult`); `:allow_none` now maps to `"dont_allow"`
71+
- **Video binary encoding**: `image_to_api/1` and `video_to_api/1` now use `%{"inlineData" => %{"data" => ..., "mimeType" => ...}}` format instead of `%{"bytesBase64Encoded" => ...}`; response parsing handles both legacy and new formats
72+
- **Video generation legacy fields**: `fps`, `compression_format`, `safety_filter_level`, and `guidance_scale` are no longer sent in API requests (struct fields retained for backwards compatibility)
73+
- **Images API implicit Vertex AI auth**: `generate/3`, `edit/5`, and `upscale/3` now auto-set `auth: :vertex_ai` on opts; validation uses per-request auth credentials via `HTTP.auth_config_for_request/1` with actual credential completeness checking; location resolved from per-request auth config
74+
- **Streaming options pass-through**: `UnifiedManager` now extracts `:timeout`, `:max_retries`, `:max_backoff_ms`, `:connect_timeout`, `:method`, and `:add_sse_params` from stream config and passes them to `HTTPStreaming.stream_to_process/6`
75+
- **Model reclassifications**: `deep_research_pro_preview_12_2025` moved from universal to Gemini-only models; `live_2_5_flash_preview` moved to Gemini-only legacy aliases; `flash_2_5_native_audio_latest` added as a universal model
76+
- **`RUN_BILLED_VERTEX_LIVE_TESTS` gate**: Vertex Live tests now require explicit opt-in via environment variable to prevent accidental GCP billing
77+
78+
### Fixed
79+
- **Vertex AI model path handling**: `list_models` and `get_model` use correct Vertex AI resource paths instead of Gemini API paths
80+
- **WebSocket model name normalization**: handles `models/`, `publishers/google/models/`, and full `projects/.../models/` prefixes, plus endpoint suffixes (`:generateContent`)
81+
- **Live Setup model prefix**: Vertex AI sessions correctly prefix model names with `projects/{p}/locations/{l}/publishers/google/`
82+
- **HTTP client URL building**: absolute paths and full URLs are no longer double-prefixed with the base URL
83+
84+
### Removed
85+
- Bulk cleanup of ~50,000 lines of internal planning documents, gap analyses, implementation specs, and development notes not intended for distribution
86+
- Removed `test.sh`, `repro_concurrency_gate.exs`, and `CLAUDE.md` development artifacts
87+
- Removed `.kiro/` spec directory
88+
1089
## [0.9.1] - 2026-01-27
1190

1291
### Added
@@ -1919,7 +1998,8 @@ config :gemini_ex,
19191998
- Minimal latency overhead
19201999
- Concurrent request processing
19212000

1922-
[Unreleased]: https://github.com/nshkrdotcom/gemini_ex/compare/v0.9.1...HEAD
2001+
[Unreleased]: https://github.com/nshkrdotcom/gemini_ex/compare/v0.10.0...HEAD
2002+
[0.10.0]: https://github.com/nshkrdotcom/gemini_ex/compare/v0.9.1...v0.10.0
19232003
[0.9.1]: https://github.com/nshkrdotcom/gemini_ex/compare/v0.9.0...v0.9.1
19242004
[0.9.0]: https://github.com/nshkrdotcom/gemini_ex/compare/v0.8.8...v0.9.0
19252005
[0.8.8]: https://github.com/nshkrdotcom/gemini_ex/compare/v0.8.7...v0.8.8

README.md

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,19 @@ A comprehensive Elixir client for Google's Gemini AI API with dual authenticatio
1818
- **Automatic Tool Calling**: A seamless, Python-SDK-like experience that automates the entire multi-turn tool-calling loop
1919
- **Built-in Tools (Gemini 3)**: Google Search, URL Context, and Code Execution via `tools:`
2020
- **Dual Authentication**: Seamless support for both Gemini API keys and Vertex AI OAuth/Service Accounts
21-
- **Application Default Credentials (ADC)**: Zero-config GCP auth with automatic discovery and token refresh (NEW in v0.8.x!)
21+
- **Application Default Credentials (ADC)**: Zero-config GCP auth with automatic discovery, token refresh, and `GOOGLE_APPLICATION_CREDENTIALS_JSON` for containers
2222
- **Advanced Streaming**: Production-grade Server-Sent Events streaming with real-time processing
2323
- **Interactions API**: Stateful interactions (CRUD), background execution, SSE streaming, and resumption
24-
- **Live API (WebSocket)**: Bidirectional, low-latency sessions with real-time input/output, native audio with affective dialog and proactivity (Enhanced in v0.9.0!)
24+
- **Live API (WebSocket)**: Bidirectional, low-latency sessions with real-time input/output, native audio with affective dialog and proactivity (Enhanced in v0.10.0!)
2525
- **Automatic Rate Limiting**: Built-in rate limit handling with retries, concurrency gating, and adaptive backoff
2626
- **Files API**: Upload, manage, and use files with Gemini models for multimodal content (NEW in v0.7.0!)
2727
- **File Search Stores**: RAG store creation, ingestion, and semantic search (NEW in v0.8.x!)
2828
- **Documents API**: Manage indexed documents inside stores for RAG workflows (NEW in v0.7.0!)
2929
- **Batches API**: Submit large numbers of requests with 50% cost savings (NEW in v0.7.0!)
3030
- **Operations API**: Track long-running operations like video generation (NEW in v0.7.0!)
3131
- **Tunings (Fine-Tuning)**: Create, monitor, and manage tuned models (NEW in v0.8.x!)
32-
- **Image & Video Generation**: Imagen/Veo APIs for text-to-image, editing, upscaling, and video generation (NEW in v0.8.x!)
32+
- **Model Registry**: Centralized model capabilities, modality tracking, and registry-backed Live API model resolution (NEW in v0.10.0!)
33+
- **Image & Video Generation**: Imagen/Veo APIs for text-to-image, editing, upscaling, and video generation with Veo 3.1 support
3334
- **Embeddings with MRL**: Text embeddings with Matryoshka Representation Learning, normalization, and distance metrics
3435
- **Async Batch Embeddings**: Production-scale embedding generation with 50% cost savings
3536
- **Type Safety**: Complete type definitions with runtime validation
@@ -58,7 +59,7 @@ Add `gemini` to your list of dependencies in `mix.exs`:
5859
```elixir
5960
def deps do
6061
[
61-
{:gemini_ex, "~> 0.9.1"}
62+
{:gemini_ex, "~> 0.10.0"}
6263
]
6364
end
6465
```
@@ -175,7 +176,7 @@ Gemini.Streaming.resume_stream(stream_id)
175176
Gemini.Streaming.stop_stream(stream_id)
176177
```
177178

178-
Streaming knobs: pass `timeout:` (per attempt, default `config :gemini_ex, :timeout` = 120_000), `max_retries:` (default 3), `max_backoff_ms:` (default 10_000), and `connect_timeout:` (default 5_000). Manager cleanup delay can be tuned via `config :gemini_ex, :streaming, cleanup_delay_ms: ...`.
179+
Streaming knobs: pass `timeout:` (per attempt, default `config :gemini_ex, :timeout` = 120_000), `stream_timeout:` (collect timeout, default 60_000; orphaned streams are cleaned up on timeout), `max_retries:` (default 3), `max_backoff_ms:` (default 10_000), and `connect_timeout:` (default 5_000). Manager cleanup delay can be tuned via `config :gemini_ex, :streaming, cleanup_delay_ms: ...`.
179180

180181
### Interactions Quick Start
181182

@@ -201,15 +202,15 @@ for event <- stream do
201202
end
202203
```
203204

204-
See `docs/guides/interactions.md` for CRUD, resumption (`last_event_id`), and background/cancel/delete examples.
205+
See `guides/interactions.md` for CRUD, resumption (`last_event_id`), and background/cancel/delete examples.
205206

206207
### Live API (WebSocket)
207208

208-
Real-time bidirectional streaming for voice, video, and text interactions. The v0.9.0 release upgrades to v1beta as the default API version while supporting v1alpha for advanced native audio features.
209+
Real-time bidirectional streaming for voice, video, and text interactions. For Gemini Live connections, `v1beta` is the default API version, while `v1alpha` is available for advanced native-audio features. Vertex Live connections use the Vertex `v1` WebSocket endpoint.
209210

210211
#### Model Resolution
211212

212-
Live API model availability varies by API key and regional rollout. Use `Gemini.Live.Models.resolve/1` to automatically select an available model:
213+
Live API model availability varies by API key and regional rollout. `Gemini.Live.Models.resolve/1` uses the model registry plus runtime `list_models` results to select a compatible model:
213214

214215
```elixir
215216
alias Gemini.Live.Models
@@ -284,7 +285,7 @@ tools = [
284285
)
285286
```
286287

287-
See the [Live API Guide](docs/guides/live_api.md) for complete documentation including voice activity detection, session resumption, thinking budgets, and context window compression.
288+
See the [Live API Guide](guides/live_api.md) for complete documentation including voice activity detection, session resumption, thinking budgets, and context window compression.
288289

289290
### Rate Limiting & Concurrency (built-in)
290291

@@ -393,7 +394,7 @@ config =
393394
|> GenerationConfig.property_ordering(["answer", "confidence"])
394395
```
395396

396-
See [Structured Outputs Guide](docs/guides/structured_outputs.md) for details.
397+
See [Structured Outputs Guide](guides/structured_outputs.md) for details.
397398

398399
## Context Caching (New in v0.6.0!)
399400

@@ -468,7 +469,7 @@ alias Gemini.Types.File
468469
- Automatic MIME type detection
469470
- 48-hour file expiration
470471

471-
See [Files API Guide](docs/guides/files.md) for complete documentation.
472+
See [Files API Guide](guides/files.md) for complete documentation.
472473

473474
## File Search Stores (New in v0.8.x!)
474475

@@ -559,7 +560,7 @@ end
559560
- GCS and BigQuery integration (Vertex AI)
560561
- Comprehensive job management
561562

562-
See [Batches API Guide](docs/guides/batches.md) for complete documentation.
563+
See [Batches API Guide](guides/batches.md) for complete documentation.
563564

564565
## Operations API (New in v0.7.0!)
565566

@@ -596,7 +597,7 @@ end
596597
- Cancel and delete operations
597598
- Comprehensive state helpers
598599

599-
See [Operations API Guide](docs/guides/operations.md) for complete documentation.
600+
See [Operations API Guide](guides/operations.md) for complete documentation.
600601

601602
## Tunings API (New in v0.8.x!)
602603

@@ -1360,6 +1361,8 @@ export GEMINI_API_KEY="your_gemini_api_key"
13601361

13611362
# For Vertex AI (optional, for multi-auth demos)
13621363
export VERTEX_JSON_FILE="/path/to/service-account.json"
1364+
# Alternative (standard ADC path)
1365+
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"
13631366
export VERTEX_PROJECT_ID="your-gcp-project-id"
13641367
```
13651368

@@ -1408,16 +1411,21 @@ config :gemini_ex, :auth,
14081411

14091412
Zero-config GCP authentication with automatic credential discovery and token refresh.
14101413

1414+
```bash
1415+
# Configure ADC explicitly (optional)
1416+
export GOOGLE_APPLICATION_CREDENTIALS_JSON='{"type":"service_account",...}' # gemini_ex extension
1417+
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service_account.json"
1418+
```
1419+
14111420
```elixir
14121421
# Works on GCE/Cloud Run/GKE with no extra setup
14131422
{:ok, response} = Gemini.generate("Hello from Vertex AI", auth: :vertex_ai)
14141423

1415-
# Or point to a service account key
1416-
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service_account.json"
1424+
# Also works with either env var above
14171425
{:ok, response} = Gemini.generate("Hello", auth: :vertex_ai)
14181426
```
14191427

1420-
The client checks `GOOGLE_APPLICATION_CREDENTIALS`, gcloud user credentials, and metadata server endpoints, caching access tokens for you via ETS.
1428+
The client checks `GOOGLE_APPLICATION_CREDENTIALS_JSON` (gemini_ex extension), `GOOGLE_APPLICATION_CREDENTIALS` (standard ADC), gcloud user credentials, and metadata server endpoints, caching access tokens for you via ETS. Official Google ADC order starts with `GOOGLE_APPLICATION_CREDENTIALS`; JSON-content env support is a gemini_ex convenience.
14211429

14221430
## Model Configuration System
14231431

@@ -1459,6 +1467,11 @@ Gemini.Config.models_for(:both) # Only universal models
14591467
# Get model by key with validation
14601468
Gemini.Config.get_model(:flash_2_5) #=> "gemini-2.5-flash"
14611469
Gemini.Config.get_model(:flash_2_5, api: :vertex_ai) # Validates compatibility
1470+
1471+
# Registry metadata helpers
1472+
Gemini.Config.model_info(:pro_3_1_preview)
1473+
Gemini.Config.model_supports?(:pro_3_1_preview, :thinking) #=> true
1474+
Gemini.Config.models_with_capability(:live_api, :supported)
14621475
```
14631476

14641477
### Embedding Model Differences
@@ -1507,7 +1520,7 @@ Gemini.embed_content("Text", model: "gemini-embedding-001")
15071520
- **[Architecture Guide](https://hexdocs.pm/gemini_ex/architecture.html)** - System design and components
15081521
- **[Authentication System](https://hexdocs.pm/gemini_ex/authentication_system.html)** - Detailed auth configuration
15091522
- **[Examples](https://github.com/nshkrdotcom/gemini_ex/tree/main/examples)** - Working code examples
1510-
- **Guides (docs/guides/...)**:
1523+
- **Guides (guides/...)**:
15111524
- `adc.md` - Application Default Credentials
15121525
- `batches.md` - Batches API
15131526
- `file_search_stores.md` - RAG stores and document ingestion
@@ -1652,9 +1665,9 @@ content = [
16521665

16531666
**Supported image formats:** PNG, JPEG, GIF, WebP (auto-detected from magic bytes)
16541667

1655-
### Image Generation API (Imagen, New in v0.8.x!)
1668+
### Image Generation API (Imagen)
16561669

1657-
Use the dedicated Imagen endpoints for text-to-image, editing, and upscaling (Vertex AI).
1670+
Use the dedicated Imagen endpoints for text-to-image, editing, and upscaling. As of v0.10.0, `auth: :vertex_ai` is set automatically on all Images API calls.
16581671

16591672
```elixir
16601673
alias Gemini.APIs.Images
@@ -1704,7 +1717,7 @@ alias Gemini.Types.Generation.Video.VideoGenerationConfig
17041717
{:ok, op} =
17051718
Videos.generate(
17061719
"A cinematic drone shot over misty mountains at sunrise",
1707-
%VideoGenerationConfig{duration_seconds: 6, aspect_ratio: "16:9"},
1720+
%VideoGenerationConfig{duration_seconds: 8, aspect_ratio: "16:9"},
17081721
auth: :vertex_ai
17091722
)
17101723

0 commit comments

Comments
 (0)