Skip to content

Commit 68e78c8

Browse files
authored
feat(llmo): support Vertex AI (#302)
* feat(llmo): support Vertex AI * chore(llmo): run formatter * fix(llmo): fix types error * chore(llmo): run formatter * chore(llmo): bump version
1 parent 07cf32b commit 68e78c8

File tree

4 files changed

+142
-12
lines changed

4 files changed

+142
-12
lines changed

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
# 6.4.0 - 2025-08-05
2+
3+
- feat: support Vertex AI for Gemini
4+
15
# 6.3.4 - 2025-08-04
26

3-
- fix: Set `$ai_tools` for all providers and `$ai_output_choices` for all non-streaming provider flows properly
7+
- fix: set `$ai_tools` for all providers and `$ai_output_choices` for all non-streaming provider flows properly
48

59
# 6.3.3 - 2025-08-01
610

posthog/ai/gemini/gemini.py

Lines changed: 64 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ class Client:
4242
def __init__(
4343
self,
4444
api_key: Optional[str] = None,
45+
vertexai: Optional[bool] = None,
46+
credentials: Optional[Any] = None,
47+
project: Optional[str] = None,
48+
location: Optional[str] = None,
49+
debug_config: Optional[Any] = None,
50+
http_options: Optional[Any] = None,
4551
posthog_client: Optional[PostHogClient] = None,
4652
posthog_distinct_id: Optional[str] = None,
4753
posthog_properties: Optional[Dict[str, Any]] = None,
@@ -51,7 +57,13 @@ def __init__(
5157
):
5258
"""
5359
Args:
54-
api_key: Google AI API key. If not provided, will use GOOGLE_API_KEY or API_KEY environment variable
60+
api_key: Google AI API key. If not provided, will use GOOGLE_API_KEY or API_KEY environment variable (not required for Vertex AI)
61+
vertexai: Whether to use Vertex AI authentication
62+
credentials: Vertex AI credentials object
63+
project: GCP project ID for Vertex AI
64+
location: GCP location for Vertex AI
65+
debug_config: Debug configuration for the client
66+
http_options: HTTP options for the client
5567
posthog_client: PostHog client for tracking usage
5668
posthog_distinct_id: Default distinct ID for all calls (can be overridden per call)
5769
posthog_properties: Default properties for all calls (can be overridden per call)
@@ -66,6 +78,12 @@ def __init__(
6678

6779
self.models = Models(
6880
api_key=api_key,
81+
vertexai=vertexai,
82+
credentials=credentials,
83+
project=project,
84+
location=location,
85+
debug_config=debug_config,
86+
http_options=http_options,
6987
posthog_client=self._ph_client,
7088
posthog_distinct_id=posthog_distinct_id,
7189
posthog_properties=posthog_properties,
@@ -85,6 +103,12 @@ class Models:
85103
def __init__(
86104
self,
87105
api_key: Optional[str] = None,
106+
vertexai: Optional[bool] = None,
107+
credentials: Optional[Any] = None,
108+
project: Optional[str] = None,
109+
location: Optional[str] = None,
110+
debug_config: Optional[Any] = None,
111+
http_options: Optional[Any] = None,
88112
posthog_client: Optional[PostHogClient] = None,
89113
posthog_distinct_id: Optional[str] = None,
90114
posthog_properties: Optional[Dict[str, Any]] = None,
@@ -94,7 +118,13 @@ def __init__(
94118
):
95119
"""
96120
Args:
97-
api_key: Google AI API key. If not provided, will use GOOGLE_API_KEY or API_KEY environment variable
121+
api_key: Google AI API key. If not provided, will use GOOGLE_API_KEY or API_KEY environment variable (not required for Vertex AI)
122+
vertexai: Whether to use Vertex AI authentication
123+
credentials: Vertex AI credentials object
124+
project: GCP project ID for Vertex AI
125+
location: GCP location for Vertex AI
126+
debug_config: Debug configuration for the client
127+
http_options: HTTP options for the client
98128
posthog_client: PostHog client for tracking usage
99129
posthog_distinct_id: Default distinct ID for all calls
100130
posthog_properties: Default properties for all calls
@@ -113,16 +143,40 @@ def __init__(
113143
self._default_privacy_mode = posthog_privacy_mode
114144
self._default_groups = posthog_groups
115145

116-
# Handle API key - try parameter first, then environment variables
117-
if api_key is None:
118-
api_key = os.environ.get("GOOGLE_API_KEY") or os.environ.get("API_KEY")
146+
# Build genai.Client arguments
147+
client_args: Dict[str, Any] = {}
148+
149+
# Add Vertex AI parameters if provided
150+
if vertexai is not None:
151+
client_args["vertexai"] = vertexai
152+
if credentials is not None:
153+
client_args["credentials"] = credentials
154+
if project is not None:
155+
client_args["project"] = project
156+
if location is not None:
157+
client_args["location"] = location
158+
if debug_config is not None:
159+
client_args["debug_config"] = debug_config
160+
if http_options is not None:
161+
client_args["http_options"] = http_options
162+
163+
# Handle API key authentication
164+
if vertexai:
165+
# For Vertex AI, api_key is optional
166+
if api_key is not None:
167+
client_args["api_key"] = api_key
168+
else:
169+
# For non-Vertex AI mode, api_key is required (backwards compatibility)
170+
if api_key is None:
171+
api_key = os.environ.get("GOOGLE_API_KEY") or os.environ.get("API_KEY")
119172

120-
if api_key is None:
121-
raise ValueError(
122-
"API key must be provided either as parameter or via GOOGLE_API_KEY/API_KEY environment variable"
123-
)
173+
if api_key is None:
174+
raise ValueError(
175+
"API key must be provided either as parameter or via GOOGLE_API_KEY/API_KEY environment variable"
176+
)
177+
client_args["api_key"] = api_key
124178

125-
self._client = genai.Client(api_key=api_key)
179+
self._client = genai.Client(**client_args)
126180
self._base_url = "https://generativelanguage.googleapis.com"
127181

128182
def _merge_posthog_params(

posthog/test/ai/gemini/test_gemini.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,78 @@ def test_new_client_override_defaults(
401401
assert props["urgent"] is True # from call
402402

403403

404+
def test_vertex_ai_parameters_passed_through(
405+
mock_client, mock_google_genai_client, mock_gemini_response
406+
):
407+
"""Test that Vertex AI parameters are properly passed to genai.Client"""
408+
mock_google_genai_client.models.generate_content.return_value = mock_gemini_response
409+
410+
# Mock credentials object
411+
mock_credentials = MagicMock()
412+
mock_debug_config = MagicMock()
413+
mock_http_options = MagicMock()
414+
415+
# Create client with Vertex AI parameters
416+
Client(
417+
vertexai=True,
418+
credentials=mock_credentials,
419+
project="test-project",
420+
location="us-central1",
421+
debug_config=mock_debug_config,
422+
http_options=mock_http_options,
423+
posthog_client=mock_client,
424+
)
425+
426+
# Verify genai.Client was called with correct parameters
427+
google_genai.Client.assert_called_once_with(
428+
vertexai=True,
429+
credentials=mock_credentials,
430+
project="test-project",
431+
location="us-central1",
432+
debug_config=mock_debug_config,
433+
http_options=mock_http_options,
434+
)
435+
436+
437+
def test_api_key_mode(mock_client, mock_google_genai_client):
438+
"""Test API key authentication mode"""
439+
440+
# Create client with just API key (traditional mode)
441+
Client(
442+
api_key="test-api-key",
443+
posthog_client=mock_client,
444+
)
445+
446+
# Verify genai.Client was called with only api_key
447+
google_genai.Client.assert_called_once_with(api_key="test-api-key")
448+
449+
450+
def test_vertex_ai_mode_with_optional_api_key(
451+
mock_client, mock_google_genai_client, mock_gemini_response
452+
):
453+
"""Test Vertex AI mode with optional API key"""
454+
mock_google_genai_client.models.generate_content.return_value = mock_gemini_response
455+
456+
mock_credentials = MagicMock()
457+
458+
# Create client with Vertex AI + API key
459+
Client(
460+
vertexai=True,
461+
api_key="test-api-key",
462+
credentials=mock_credentials,
463+
project="test-project",
464+
posthog_client=mock_client,
465+
)
466+
467+
# Verify genai.Client was called with both Vertex AI params and API key
468+
google_genai.Client.assert_called_once_with(
469+
vertexai=True,
470+
api_key="test-api-key",
471+
credentials=mock_credentials,
472+
project="test-project",
473+
)
474+
475+
404476
def test_tool_use_response(mock_client, mock_google_genai_client, mock_gemini_response):
405477
"""Test that tools defined in config are captured in $ai_tools property"""
406478
mock_google_genai_client.models.generate_content.return_value = mock_gemini_response

posthog/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
VERSION = "6.3.4"
1+
VERSION = "6.4.0"
22

33
if __name__ == "__main__":
44
print(VERSION, end="") # noqa: T201

0 commit comments

Comments
 (0)