Repository: confident-ai/deepeval (python)

Issue:
VertexAI default application credentials support broken in 3.7.x

**❗BEFORE YOU BEGIN❗**
Are you on discord? 🤗 We'd love to have you asking questions on discord instead: https://discord.com/invite/a3K9c8GRGt

**Describe the bug**
Google application default credentials support appears to be broken since 3.7.x. (as described in this doc https://deepeval.com/integrations/models/vertex-ai)
It results in the following error `Google Gemini API key is not configured. Set GOOGLE_SERVICE_ACCOUNT_KEY in your environment or pass `service_account_key` to GeminiModel(...)`

It works on 3.6.x



**To Reproduce**
Steps to reproduce the behavior:
Follow the steps here: https://deepeval.com/integrations/models/vertex-ai

**Expected behavior**
Should work



Patch:
diff --git a/deepeval/models/llms/gemini_model.py b/deepeval/models/llms/gemini_model.py
index 53a71deb4..c9f8572d5 100644
--- a/deepeval/models/llms/gemini_model.py
+++ b/deepeval/models/llms/gemini_model.py
@@ -371,25 +371,6 @@ def _build_client(self) -> "Client":
         client_kwargs = self._client_kwargs(**self.kwargs)
 
         if self.should_use_vertexai():
-            service_account_key_json = require_secret_api_key(
-                self.service_account_key,
-                provider_label="Google Gemini",
-                env_var_name="GOOGLE_SERVICE_ACCOUNT_KEY",
-                param_hint="`service_account_key` to GeminiModel(...)",
-            )
-
-            try:
-                service_account_key = json.loads(service_account_key_json)
-            except Exception as e:
-                raise DeepEvalError(
-                    "GOOGLE_SERVICE_ACCOUNT_KEY must be valid JSON for a Google service account."
-                ) from e
-
-            if not isinstance(service_account_key, dict):
-                raise DeepEvalError(
-                    "GOOGLE_SERVICE_ACCOUNT_KEY must decode to a JSON object."
-                )
-
             if not self.project or not self.location:
                 raise DeepEvalError(
                     "When using Vertex AI API, both project and location are required. "
@@ -397,17 +378,34 @@ def _build_client(self) -> "Client":
                     "GOOGLE_CLOUD_LOCATION in your DeepEval configuration."
                 )
 
-            oauth2 = self._require_oauth2()
-            credentials = (
-                oauth2.service_account.Credentials.from_service_account_info(
+            # if no service account key is provided, allow the SDK
+            # to resolve Application Default Credentials automatically.
+            credentials = None
+            if self.service_account_key is not None:
+                service_account_key_json = require_secret_api_key(
+                    self.service_account_key,
+                    provider_label="Google Gemini",
+                    env_var_name="GOOGLE_SERVICE_ACCOUNT_KEY",
+                    param_hint="`service_account_key` to GeminiModel(...)",
+                )
+
+                try:
+                    service_account_key = json.loads(service_account_key_json)
+                except Exception as e:
+                    raise DeepEvalError(
+                        "GOOGLE_SERVICE_ACCOUNT_KEY must be valid JSON for a Google service account."
+                    ) from e
+
+                if not isinstance(service_account_key, dict):
+                    raise DeepEvalError(
+                        "GOOGLE_SERVICE_ACCOUNT_KEY must decode to a JSON object."
+                    )
+
+                oauth2 = self._require_oauth2()
+                credentials = oauth2.service_account.Credentials.from_service_account_info(
                     service_account_key,
-                    scopes=[
-                        "https://www.googleapis.com/auth/cloud-platform",
-                    ],
+                    scopes=["https://www.googleapis.com/auth/cloud-platform"],
                 )
-                if service_account_key
-                else None
-            )
 
             client = self._module.Client(
                 vertexai=True,


Test patch:
diff --git a/tests/test_core/test_models/test_gemini_model.py b/tests/test_core/test_models/test_gemini_model.py
index d5ae627e0..3eeef0bc6 100644
--- a/tests/test_core/test_models/test_gemini_model.py
+++ b/tests/test_core/test_models/test_gemini_model.py
@@ -76,3 +76,50 @@ def test_gemini_model_defaults_key_from_settings_and_unwraps_secret(
     # Client must see the Settings key, as a plain string
     assert isinstance(api_key, str)
     assert api_key == "env-secret-key"
+
+
+@patch("deepeval.models.llms.gemini_model.require_dependency")
+def test_gemini_vertexai_allows_adc_when_no_service_account_key(
+    mock_require_dep,
+    settings,
+):
+    """
+    Vertex AI mode should allow Application Default Credentials (ADC)
+
+    With GOOGLE_GENAI_USE_VERTEXAI enabled and project/location set,
+    GeminiModel should create a Vertex client even when no service account
+    key is provided. In that case, credentials should be None and resolved via ADC.
+    """
+    fake_genai = _make_fake_genai_module()
+
+    def _fake_require_dependency(name, *args, **kwargs):
+        # ADC path should only need the genai module and not require oauth2
+        # just to allow default creds.
+        if name == "google.genai":
+            return fake_genai
+        raise AssertionError(f"Unexpected dependency requested: {name}")
+
+    mock_require_dep.side_effect = _fake_require_dependency
+
+    with settings.edit(persist=False):
+        settings.GOOGLE_GENAI_USE_VERTEXAI = True
+        settings.GOOGLE_CLOUD_PROJECT = "test-project"
+        settings.GOOGLE_CLOUD_LOCATION = "us-central1"
+        settings.GOOGLE_SERVICE_ACCOUNT_KEY = None
+
+    model = GeminiModel(
+        model="gemini-1.5-pro",
+        project="test-project",
+        location="us-central1",
+        service_account_key=None,
+    )
+
+    client = model.model
+
+    # assert that we are building a Vertex client rather than API-key mode
+    assert client.kwargs.get("vertexai") is True
+    assert client.kwargs.get("project") == "test-project"
+    assert client.kwargs.get("location") == "us-central1"
+
+    # credentials should be absent/None so the SDK resolves via ADC.
+    assert client.kwargs.get("credentials") is None