Skip to content

Commit 83ff0a5

Browse files
giulio-leonegiulio-leoneCopilot
authored
Python: fix(google-ai): skip api_key check when use_vertexai is True (#13607)
## Summary Fixes #13483 ### Motivation and Context When `use_vertexai=True`, users authenticate via Application Default Credentials (ADC) and don't need an API key. However, the initialization check for `api_key` runs unconditionally, blocking Vertex AI users with: ``` ServiceInitializationError: The API key is required when use_vertexai is False. ``` ### Description Guard the `api_key` validation with `not google_ai_settings.use_vertexai` in all three Google AI service classes: - `GoogleAIChatCompletion` - `GoogleAITextCompletion` - `GoogleAITextEmbedding` The error message already reads *"when use_vertexai is False"*, so the condition now matches the intent. ### Before / After ```python # Before — fails even with use_vertexai=True GoogleAIChatCompletion( use_vertexai=True, cloud_project_id="my-project", cloud_region="us-central1" ) # → ServiceInitializationError: The API key is required when use_vertexai is False. # After — works correctly GoogleAIChatCompletion( use_vertexai=True, cloud_project_id="my-project", cloud_region="us-central1" ) # → Initializes successfully, uses ADC for authentication ``` ### Contribution Checklist - [x] The code builds clean without any errors or warnings - [x] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) - [x] The code follows the [SK coding standards](https://github.com/microsoft/semantic-kernel/blob/main/python/README.md) --------- Co-authored-by: giulio-leone <giulio.leone@users.noreply.github.com> Co-authored-by: giulio-leone <6887247+giulio-leone@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent e0bd528 commit 83ff0a5

File tree

10 files changed

+68
-7
lines changed

10 files changed

+68
-7
lines changed

.github/workflows/python-integration-tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ env:
6868
GOOGLE_AI_EMBEDDING_MODEL_ID: ${{ vars.GOOGLE_AI_EMBEDDING_MODEL_ID }}
6969
GOOGLE_AI_API_KEY: ${{ secrets.GOOGLE_AI_API_KEY }}
7070
GOOGLE_AI_CLOUD_PROJECT_ID: ${{ vars.GOOGLE_AI_CLOUD_PROJECT_ID }}
71+
GOOGLE_AI_CLOUD_REGION: ${{ vars.GOOGLE_AI_CLOUD_REGION }}
7172
VERTEX_AI_PROJECT_ID: ${{ vars.VERTEX_AI_PROJECT_ID }}
7273
VERTEX_AI_GEMINI_MODEL_ID: ${{ vars.VERTEX_AI_GEMINI_MODEL_ID }}
7374
VERTEX_AI_EMBEDDING_MODEL_ID: ${{ vars.VERTEX_AI_EMBEDDING_MODEL_ID }}

python/semantic_kernel/connectors/ai/google/google_ai/services/google_ai_chat_completion.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,9 @@ def __init__(
119119
if not client:
120120
if google_ai_settings.use_vertexai and not google_ai_settings.cloud_project_id:
121121
raise ServiceInitializationError("Project ID must be provided when use_vertexai is True.")
122-
if not google_ai_settings.api_key:
122+
if google_ai_settings.use_vertexai and not google_ai_settings.cloud_region:
123+
raise ServiceInitializationError("Region must be provided when use_vertexai is True.")
124+
if not google_ai_settings.use_vertexai and not google_ai_settings.api_key:
123125
raise ServiceInitializationError("The API key is required when use_vertexai is False.")
124126

125127
super().__init__(

python/semantic_kernel/connectors/ai/google/google_ai/services/google_ai_text_completion.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@ def __init__(
9090
if not client:
9191
if google_ai_settings.use_vertexai and not google_ai_settings.cloud_project_id:
9292
raise ServiceInitializationError("Project ID must be provided when use_vertexai is True.")
93-
if not google_ai_settings.api_key:
93+
if google_ai_settings.use_vertexai and not google_ai_settings.cloud_region:
94+
raise ServiceInitializationError("Region must be provided when use_vertexai is True.")
95+
if not google_ai_settings.use_vertexai and not google_ai_settings.api_key:
9496
raise ServiceInitializationError("The API key is required when use_vertexai is False.")
9597

9698
super().__init__(

python/semantic_kernel/connectors/ai/google/google_ai/services/google_ai_text_embedding.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@ def __init__(
8181
if not client:
8282
if google_ai_settings.use_vertexai and not google_ai_settings.cloud_project_id:
8383
raise ServiceInitializationError("Project ID must be provided when use_vertexai is True.")
84-
if not google_ai_settings.api_key:
84+
if google_ai_settings.use_vertexai and not google_ai_settings.cloud_region:
85+
raise ServiceInitializationError("Region must be provided when use_vertexai is True.")
86+
if not google_ai_settings.use_vertexai and not google_ai_settings.api_key:
8587
raise ServiceInitializationError("The API key is required when use_vertexai is False.")
8688

8789
super().__init__(

python/tests/integration/completions/chat_completion_test_base.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,11 @@
6161
ollama_image_setup: bool = is_service_setup_for_testing(["OLLAMA_CHAT_MODEL_ID_IMAGE"])
6262
ollama_tool_call_setup: bool = is_service_setup_for_testing(["OLLAMA_CHAT_MODEL_ID_TOOL_CALL"])
6363
google_ai_setup: bool = is_service_setup_for_testing(["GOOGLE_AI_API_KEY", "GOOGLE_AI_GEMINI_MODEL_ID"])
64-
vertex_ai_setup: bool = is_service_setup_for_testing(["GOOGLE_AI_CLOUD_PROJECT_ID", "GOOGLE_AI_GEMINI_MODEL_ID"])
64+
vertex_ai_setup: bool = is_service_setup_for_testing([
65+
"GOOGLE_AI_CLOUD_PROJECT_ID",
66+
"GOOGLE_AI_GEMINI_MODEL_ID",
67+
"GOOGLE_AI_CLOUD_REGION",
68+
])
6569
onnx_setup: bool = is_service_setup_for_testing(
6670
["ONNX_GEN_AI_CHAT_MODEL_FOLDER"], raise_if_not_set=False
6771
) # Tests are optional for ONNX

python/tests/integration/completions/test_text_completion.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@
3232
"Linux"
3333
])
3434
google_ai_setup: bool = is_service_setup_for_testing(["GOOGLE_AI_API_KEY", "GOOGLE_AI_GEMINI_MODEL_ID"])
35-
vertex_ai_setup: bool = is_service_setup_for_testing(["GOOGLE_AI_CLOUD_PROJECT_ID", "GOOGLE_AI_GEMINI_MODEL_ID"])
35+
vertex_ai_setup: bool = is_service_setup_for_testing([
36+
"GOOGLE_AI_CLOUD_PROJECT_ID",
37+
"GOOGLE_AI_GEMINI_MODEL_ID",
38+
"GOOGLE_AI_CLOUD_REGION",
39+
])
3640
onnx_setup: bool = is_service_setup_for_testing(
3741
["ONNX_GEN_AI_TEXT_MODEL_FOLDER"], raise_if_not_set=False
3842
) # Tests are optional for ONNX

python/tests/integration/embeddings/test_embedding_service_base.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,11 @@
4343
["MISTRALAI_API_KEY", "MISTRALAI_EMBEDDING_MODEL_ID"], raise_if_not_set=False
4444
) # We don't have a MistralAI deployment
4545
google_ai_setup: bool = is_service_setup_for_testing(["GOOGLE_AI_API_KEY", "GOOGLE_AI_EMBEDDING_MODEL_ID"])
46-
vertex_ai_setup: bool = is_service_setup_for_testing(["GOOGLE_AI_CLOUD_PROJECT_ID", "GOOGLE_AI_EMBEDDING_MODEL_ID"])
46+
vertex_ai_setup: bool = is_service_setup_for_testing([
47+
"GOOGLE_AI_CLOUD_PROJECT_ID",
48+
"GOOGLE_AI_EMBEDDING_MODEL_ID",
49+
"GOOGLE_AI_CLOUD_REGION",
50+
])
4751
ollama_setup: bool = is_service_setup_for_testing(["OLLAMA_EMBEDDING_MODEL_ID"])
4852
# When testing Bedrock, after logging into AWS CLI this has been set, so we can use it to check if the service is setup
4953
bedrock_setup: bool = is_service_setup_for_testing(["AWS_DEFAULT_REGION"], raise_if_not_set=False)

python/tests/unit/connectors/ai/google/google_ai/services/test_google_ai_chat_completion.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,20 @@ def test_google_ai_chat_completion_init_with_use_vertexai_missing_project_id(goo
7575
GoogleAIChatCompletion(use_vertexai=True, env_file_path="fake_env_file_path.env")
7676

7777

78+
@pytest.mark.parametrize("exclude_list", [["GOOGLE_AI_CLOUD_REGION"]], indirect=True)
79+
def test_google_ai_chat_completion_init_with_use_vertexai_missing_region(google_ai_unit_test_env) -> None:
80+
"""Test initialization of GoogleAIChatCompletion with use_vertexai true but missing region"""
81+
with pytest.raises(ServiceInitializationError, match="Region must be provided when use_vertexai is True."):
82+
GoogleAIChatCompletion(use_vertexai=True, env_file_path="fake_env_file_path.env")
83+
84+
85+
@pytest.mark.parametrize("exclude_list", [["GOOGLE_AI_API_KEY"]], indirect=True)
86+
def test_google_ai_chat_completion_init_with_use_vertexai_no_api_key(google_ai_unit_test_env) -> None:
87+
"""Test initialization of GoogleAIChatCompletion succeeds with use_vertexai=True and no api_key"""
88+
chat_completion = GoogleAIChatCompletion(use_vertexai=True)
89+
assert chat_completion.service_settings.use_vertexai is True
90+
91+
7892
def test_prompt_execution_settings_class(google_ai_unit_test_env) -> None:
7993
google_ai_chat_completion = GoogleAIChatCompletion()
8094
assert google_ai_chat_completion.get_prompt_execution_settings_class() == GoogleAIChatPromptExecutionSettings

python/tests/unit/connectors/ai/google/google_ai/services/test_google_ai_text_completion.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,20 @@ def test_google_ai_text_completion_init_with_use_vertexai_missing_project_id(goo
6767
GoogleAITextCompletion(use_vertexai=True, env_file_path="fake_env_file_path.env")
6868

6969

70+
@pytest.mark.parametrize("exclude_list", [["GOOGLE_AI_CLOUD_REGION"]], indirect=True)
71+
def test_google_ai_text_completion_init_with_use_vertexai_missing_region(google_ai_unit_test_env) -> None:
72+
"""Test initialization of GoogleAITextCompletion with use_vertexai true but missing region"""
73+
with pytest.raises(ServiceInitializationError, match="Region must be provided when use_vertexai is True."):
74+
GoogleAITextCompletion(use_vertexai=True, env_file_path="fake_env_file_path.env")
75+
76+
77+
@pytest.mark.parametrize("exclude_list", [["GOOGLE_AI_API_KEY"]], indirect=True)
78+
def test_google_ai_text_completion_init_with_use_vertexai_no_api_key(google_ai_unit_test_env) -> None:
79+
"""Test initialization of GoogleAITextCompletion succeeds with use_vertexai=True and no api_key"""
80+
text_completion = GoogleAITextCompletion(use_vertexai=True)
81+
assert text_completion.service_settings.use_vertexai is True
82+
83+
7084
def test_prompt_execution_settings_class(google_ai_unit_test_env) -> None:
7185
google_ai_text_completion = GoogleAITextCompletion()
7286
assert google_ai_text_completion.get_prompt_execution_settings_class() == GoogleAITextPromptExecutionSettings

python/tests/unit/connectors/ai/google/google_ai/services/test_google_ai_text_embedding.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,14 @@ def test_google_ai_text_embedding_init_with_empty_model_id(google_ai_unit_test_e
5757
def test_google_ai_text_embedding_init_with_empty_api_key(google_ai_unit_test_env) -> None:
5858
"""Test initialization of GoogleAITextEmbedding with an empty api_key"""
5959
with pytest.raises(ServiceInitializationError, match="The API key is required when use_vertexai is False."):
60-
GoogleAITextEmbedding(use_vertexai=True, env_file_path="fake_env_file_path.env")
60+
GoogleAITextEmbedding(env_file_path="fake_env_file_path.env")
61+
62+
63+
@pytest.mark.parametrize("exclude_list", [["GOOGLE_AI_API_KEY"]], indirect=True)
64+
def test_google_ai_text_embedding_init_with_use_vertexai_no_api_key(google_ai_unit_test_env) -> None:
65+
"""Test initialization of GoogleAITextEmbedding succeeds with use_vertexai=True and no api_key"""
66+
embedding = GoogleAITextEmbedding(use_vertexai=True)
67+
assert embedding.service_settings.use_vertexai is True
6168

6269

6370
@pytest.mark.parametrize("exclude_list", [["GOOGLE_AI_CLOUD_PROJECT_ID"]], indirect=True)
@@ -67,6 +74,13 @@ def test_google_ai_text_embedding_init_with_use_vertexai_missing_project_id(goog
6774
GoogleAITextEmbedding(use_vertexai=True, env_file_path="fake_env_file_path.env")
6875

6976

77+
@pytest.mark.parametrize("exclude_list", [["GOOGLE_AI_CLOUD_REGION"]], indirect=True)
78+
def test_google_ai_text_embedding_init_with_use_vertexai_missing_region(google_ai_unit_test_env) -> None:
79+
"""Test initialization of GoogleAITextEmbedding with use_vertexai true but missing region"""
80+
with pytest.raises(ServiceInitializationError, match="Region must be provided when use_vertexai is True."):
81+
GoogleAITextEmbedding(use_vertexai=True, env_file_path="fake_env_file_path.env")
82+
83+
7084
def test_prompt_execution_settings_class(google_ai_unit_test_env) -> None:
7185
google_ai_text_embedding = GoogleAITextEmbedding()
7286
assert google_ai_text_embedding.get_prompt_execution_settings_class() == GoogleAIEmbeddingPromptExecutionSettings

0 commit comments

Comments
 (0)