From f14c56ddd3e2381bcdd7574b245fee963fb72de6 Mon Sep 17 00:00:00 2001 From: Matteo Rosati Date: Thu, 29 Jan 2026 15:02:18 +0100 Subject: [PATCH] explicit project_id --- lib.py | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/lib.py b/lib.py index aff40b4..29cd6a8 100644 --- a/lib.py +++ b/lib.py @@ -23,14 +23,15 @@ load_dotenv() def get_credentials(): - """Get Google Cloud credentials from environment. + """Get Google Cloud credentials and project ID from environment. Supports two methods: 1. GOOGLE_CREDENTIALS_JSON: Direct JSON content as string (production) 2. GOOGLE_APPLICATION_CREDENTIALS: Path to JSON file (local development) Returns: - service_account.Credentials: The loaded credentials + tuple: (credentials, project_id) where credentials is a + service_account.Credentials object and project_id is the Google Cloud project """ # OAuth scopes required for Vertex AI API SCOPES = ["https://www.googleapis.com/auth/cloud-platform"] @@ -44,10 +45,12 @@ def get_credentials(): try: credentials_info = json.loads(credentials_json) logger.info(f"creds JSON parsed: {credentials_info}") + project_id = credentials_info.get("project_id") - return service_account.Credentials.from_service_account_info( + credentials = service_account.Credentials.from_service_account_info( credentials_info, scopes=SCOPES ) + return credentials, project_id except json.JSONDecodeError as e: raise ValueError(f"Invalid JSON in GOOGLE_CREDENTIALS_JSON: {e}") @@ -57,13 +60,18 @@ def get_credentials(): logger.info(f"creds path: {credentials_path}") if credentials_path and os.path.exists(credentials_path): - return service_account.Credentials.from_service_account_file( + with open(credentials_path) as f: + credentials_info = json.load(f) + project_id = credentials_info.get("project_id") + + credentials = service_account.Credentials.from_service_account_file( credentials_path, scopes=SCOPES ) + return credentials, project_id # If neither is provided, return None to let the client use default credentials # (useful when running on Google Cloud with service account attached) - return None + return None, None # Gemini model name @@ -92,11 +100,16 @@ async def generate(prompt: str): def run_streaming(): """Run the synchronous streaming in a separate thread.""" try: - credentials = get_credentials() + credentials, project_id = get_credentials() logger.info(f"credentials: {credentials}") + logger.info(f"project_id: {project_id}") - client = genai.Client(vertexai=True, credentials=credentials) + client = genai.Client( + vertexai=True, + credentials=credentials, + project=project_id + ) contents = [ types.Content(role="user", parts=[