Nous.Providers.VertexAI (nous v0.13.3)

View Source

Google Vertex AI provider implementation.

Supports Gemini models via the Vertex AI API, which provides enterprise features like VPC-SC, CMEK, IAM, and regional/global endpoints.

Supported Models

ModelModel IDEndpointAPI Version
Gemini 3.1 Pro (preview)gemini-3.1-pro-previewglobal onlyv1beta1
Gemini 3 Flash (preview)gemini-3-flash-previewglobal onlyv1beta1
Gemini 3.1 Flash-Litegemini-3.1-flash-lite-previewglobal onlyv1beta1
Gemini 2.5 Progemini-2.5-proregional/globalv1
Gemini 2.5 Flashgemini-2.5-flashregional/globalv1
Gemini 2.0 Flashgemini-2.0-flashregional/globalv1

Preview and experimental models automatically use the v1beta1 API version. Stable models use v1. This is determined by api_version_for_model/1.

Authentication

Vertex AI uses OAuth2 Bearer tokens (not API keys like Google AI). Token resolution order:

  1. :api_key option passed directly (treated as a Bearer access token)
  2. Goth integration — if a Goth process name is configured, fetches tokens automatically
  3. VERTEX_AI_ACCESS_TOKEN environment variable
  4. Application config: config :nous, :vertex_ai, api_key: "..."

Goth handles OAuth2 token fetching, caching, and auto-refresh from a GCP service account. Load the service account JSON from an environment variable (no file path dependency):

# Set env vars:
# export GOOGLE_CREDENTIALS='{"type":"service_account","project_id":"...",...}'
# export GOOGLE_CLOUD_PROJECT="your-project-id"
# export GOOGLE_CLOUD_LOCATION="global"  # required for Gemini 3.x preview

# mix.exs
{:goth, "~> 1.4"}

# application.ex — start Goth in your supervision tree
credentials = System.get_env("GOOGLE_CREDENTIALS") |> JSON.decode!()

children = [
  {Goth, name: MyApp.Goth, source: {:service_account, credentials}}
]

Then configure Nous to use it:

# config.exs (recommended for production)
config :nous, :vertex_ai, goth: MyApp.Goth

# Then just use it:
agent = Nous.new("vertex_ai:gemini-3.1-pro-preview")
{:ok, result} = Nous.run(agent, "Hello!")

Or pass Goth per-model (useful for multiple projects):

agent = Nous.new("vertex_ai:gemini-3-flash-preview",
  default_settings: %{goth: MyApp.Goth}
)

Using an Access Token

For quick testing without Goth (tokens expire after ~1 hour):

# export VERTEX_AI_ACCESS_TOKEN="$(gcloud auth print-access-token)"
agent = Nous.new("vertex_ai:gemini-3.1-pro-preview")

Or pass it explicitly:

agent = Nous.new("vertex_ai:gemini-3.1-pro-preview",
  api_key: System.get_env("VERTEX_AI_ACCESS_TOKEN")
)

URL Construction

The base URL is built at request time from environment variables and the model name. The provider selects the correct hostname and API version automatically.

Regional Endpoints (for stable models)

https://{region}-aiplatform.googleapis.com/v1/projects/{project}/locations/{region}

Global Endpoint (required for Gemini 3.x preview models)

https://aiplatform.googleapis.com/v1beta1/projects/{project}/locations/global

Environment Variables

  • GOOGLE_CLOUD_PROJECT (or GCLOUD_PROJECT) — GCP project ID (required)
  • GOOGLE_CLOUD_REGION (or GOOGLE_CLOUD_LOCATION) — GCP region or global (defaults to us-central1)

Both GOOGLE_CLOUD_REGION and GOOGLE_CLOUD_LOCATION are supported, consistent with other Google Cloud libraries and tooling. GOOGLE_CLOUD_REGION takes precedence if both are set.

Explicit Base URL

You can override the auto-constructed URL entirely:

alias Nous.Providers.VertexAI

# Use the endpoint helper to build the URL with correct API version:
url = VertexAI.endpoint("my-project", "global", "gemini-3.1-pro-preview")
# => "https://aiplatform.googleapis.com/v1beta1/projects/my-project/locations/global"

agent = Nous.new("vertex_ai:gemini-3.1-pro-preview", base_url: url)

Input Validation

The provider validates GOOGLE_CLOUD_PROJECT and the region at request time and returns helpful error messages for invalid values (e.g., typos, wrong format) instead of opaque DNS or HTTP errors.

Configuration

# config.exs
config :nous, :vertex_ai,
  goth: MyApp.Goth

# Or with an explicit base_url (overrides env var URL construction):
config :nous, :vertex_ai,
  goth: MyApp.Goth,
  base_url: "https://aiplatform.googleapis.com/v1beta1/projects/my-project/locations/global"

Examples

# Gemini 3.1 Pro on global endpoint (preview, v1beta1)
agent = Nous.new("vertex_ai:gemini-3.1-pro-preview")

# Gemini 3 Flash on global endpoint (preview, v1beta1)
agent = Nous.new("vertex_ai:gemini-3-flash-preview")

# Gemini 2.0 Flash on regional endpoint (stable, v1)
agent = Nous.new("vertex_ai:gemini-2.0-flash")

# With explicit region override
agent = Nous.new("vertex_ai:gemini-3.1-pro-preview",
  base_url: VertexAI.endpoint("my-project", "global", "gemini-3.1-pro-preview")
)

Summary

Functions

Get the API key from options, environment, or application config.

Returns the appropriate API version for a model name.

Get the base URL from options, application config, or default.

Count tokens in messages (rough estimate).

Build a Vertex AI endpoint URL from project ID, region, and optional model name.

High-level request with message conversion, telemetry, and error wrapping.

High-level streaming request with message conversion and telemetry.

Functions

api_key(opts \\ [])

@spec api_key(keyword()) :: String.t() | nil

Get the API key from options, environment, or application config.

Lookup order:

  1. :api_key option passed directly
  2. Environment variable (VERTEX_AI_ACCESS_TOKEN)
  3. Application config: config :nous, vertex_ai, api_key: "..."

api_version_for_model(model)

@spec api_version_for_model(String.t() | nil) :: String.t()

Returns the appropriate API version for a model name.

Preview and experimental models use v1beta1, stable models use v1.

base_url(opts \\ [])

@spec base_url(keyword()) :: String.t()

Get the base URL from options, application config, or default.

Lookup order:

  1. :base_url option passed directly
  2. Application config: config :nous, vertex_ai, base_url: "..."
  3. Default:

count_tokens(messages)

@spec count_tokens(list()) :: integer()

Count tokens in messages (rough estimate).

Override this in your provider for more accurate counting.

endpoint(project_id, region \\ "us-central1", model \\ nil)

@spec endpoint(String.t(), String.t(), String.t() | nil) :: String.t()

Build a Vertex AI endpoint URL from project ID, region, and optional model name.

Uses v1beta1 API version for preview/experimental models and v1 for stable models. If no model name is provided, defaults to v1.

When region is "global", uses aiplatform.googleapis.com (no region prefix). Regional endpoints use {region}-aiplatform.googleapis.com.

Gemini 3.x preview models (gemini-3.1-pro-preview, gemini-3-flash-preview, etc.) are only available on the global endpoint.

Examples

# Regional endpoint, stable model (v1)
iex> Nous.Providers.VertexAI.endpoint("my-project", "us-central1")
"https://us-central1-aiplatform.googleapis.com/v1/projects/my-project/locations/us-central1"

iex> Nous.Providers.VertexAI.endpoint("my-project", "us-central1", "gemini-2.0-flash")
"https://us-central1-aiplatform.googleapis.com/v1/projects/my-project/locations/us-central1"

# Global endpoint, preview model (v1beta1) — required for Gemini 3.x
iex> Nous.Providers.VertexAI.endpoint("my-project", "global", "gemini-3.1-pro-preview")
"https://aiplatform.googleapis.com/v1beta1/projects/my-project/locations/global"

iex> Nous.Providers.VertexAI.endpoint("my-project", "global", "gemini-3-flash-preview")
"https://aiplatform.googleapis.com/v1beta1/projects/my-project/locations/global"

request(model, messages, settings)

High-level request with message conversion, telemetry, and error wrapping.

Default implementation that:

  1. Converts messages to provider format
  2. Builds request params
  3. Calls chat/2
  4. Parses response
  5. Emits telemetry events
  6. Wraps errors

request_stream(model, messages, settings)

High-level streaming request with message conversion and telemetry.