From 38d5cb8d987afd0077090716ef33f64355cc230c Mon Sep 17 00:00:00 2001 From: johnpccd Date: Sun, 25 May 2025 00:32:06 +0200 Subject: [PATCH] cp --- deployment/cloud-function/main.py | 112 ++++----------- deployment/cloud-function/requirements.txt | 2 +- .../test_vertex_ai_embeddings.py | 107 ++++++++++++++ deployment/fix-cloud-run-deployment.sh | 135 ++++++++++++++++++ deployment/terraform/cloud-function.tf | 9 +- deployment/terraform/main.tf | 47 ++---- deployment/terraform/terraform.tfstate | 86 ++++++----- deployment/terraform/terraform.tfstate.backup | 29 ++-- deployment/terraform/variables.tf | 6 + 9 files changed, 358 insertions(+), 175 deletions(-) create mode 100644 deployment/cloud-function/test_vertex_ai_embeddings.py create mode 100644 deployment/fix-cloud-run-deployment.sh diff --git a/deployment/cloud-function/main.py b/deployment/cloud-function/main.py index 603042c..c13ba15 100644 --- a/deployment/cloud-function/main.py +++ b/deployment/cloud-function/main.py @@ -4,7 +4,8 @@ import base64 from datetime import datetime from typing import Dict, Any, Optional import functions_framework -from google.cloud import vision +import vertexai +from vertexai.vision_models import MultiModalEmbeddingModel, Image as VertexImage from google.cloud import firestore from google.cloud import storage from qdrant_client import QdrantClient @@ -20,8 +21,15 @@ import uuid logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) -# Initialize clients -vision_client = vision.ImageAnnotatorClient() +# Initialize Vertex AI +PROJECT_ID = os.environ.get('GOOGLE_CLOUD_PROJECT') or os.environ.get('GCP_PROJECT') +LOCATION = os.environ.get('VERTEX_AI_LOCATION', 'us-central1') + +if PROJECT_ID: + vertexai.init(project=PROJECT_ID, location=LOCATION) + logger.info(f"Initialized Vertex AI with project {PROJECT_ID} in location {LOCATION}") +else: + logger.error("PROJECT_ID not found in environment variables") # Get Firestore configuration from environment variables FIRESTORE_PROJECT_ID = os.environ.get('FIRESTORE_PROJECT_ID') @@ -63,7 +71,7 @@ try: qdrant_client.create_collection( collection_name=QDRANT_COLLECTION, vectors_config=VectorParams( - size=512, # Fixed size for image embeddings + size=1408, # Vertex AI multimodal embedding size distance=Distance.COSINE ) ) @@ -161,7 +169,7 @@ def process_image(image_id: str, storage_path: str, team_id: str, retry_count: i # Download image data image_data = blob.download_as_bytes() - # Generate embeddings using Google Cloud Vision + # Generate embeddings using Vertex AI embeddings = generate_image_embeddings(image_data) if embeddings is None: @@ -178,7 +186,7 @@ def process_image(image_id: str, storage_path: str, team_id: str, retry_count: i 'team_id': team_id, 'storage_path': storage_path, 'created_at': datetime.utcnow().isoformat(), - 'model': 'google-vision-v1' + 'model': 'vertex-ai-multimodal' } # Create point for Qdrant @@ -197,7 +205,7 @@ def process_image(image_id: str, storage_path: str, team_id: str, retry_count: i logger.info(f"Stored embeddings for image {image_id} in Qdrant with point ID {point_id}") # Update Firestore with embedding info - update_image_embedding_info(image_id, point_id, 'google-vision-v1') + update_image_embedding_info(image_id, point_id, 'vertex-ai-multimodal') return True @@ -207,7 +215,7 @@ def process_image(image_id: str, storage_path: str, team_id: str, retry_count: i def generate_image_embeddings(image_data: bytes) -> Optional[np.ndarray]: """ - Generate image embeddings using Google Cloud Vision API + Generate image embeddings using Vertex AI multimodal embedding model Args: image_data: Binary image data @@ -216,88 +224,30 @@ def generate_image_embeddings(image_data: bytes) -> Optional[np.ndarray]: Numpy array of embeddings or None if failed """ try: - # Create Vision API image object - image = vision.Image(content=image_data) + # Create Vertex AI image object + vertex_image = VertexImage(image_data) - # Use object localization to get feature vectors - # This provides rich semantic information about the image - response = vision_client.object_localization(image=image) + # Use multimodal embedding model to get embeddings + model = MultiModalEmbeddingModel.from_pretrained("multimodalembedding@001") + embeddings = model.get_embeddings(image=vertex_image) - if response.error.message: - logger.error(f"Vision API error: {response.error.message}") + if embeddings is None or embeddings.image_embedding is None: + logger.error("Failed to generate embeddings - no image embedding returned") return None - # Extract features from detected objects - features = [] + # Get the image embedding vector + embedding_vector = embeddings.image_embedding - # Get object detection features - for obj in response.localized_object_annotations: - # Use object name and confidence as features - features.extend([ - hash(obj.name) % 1000 / 1000.0, # Normalized hash of object name - obj.score, # Confidence score - obj.bounding_poly.normalized_vertices[0].x, # Bounding box features - obj.bounding_poly.normalized_vertices[0].y, - obj.bounding_poly.normalized_vertices[2].x - obj.bounding_poly.normalized_vertices[0].x, # Width - obj.bounding_poly.normalized_vertices[2].y - obj.bounding_poly.normalized_vertices[0].y, # Height - ]) - - # Also get label detection for additional semantic information - label_response = vision_client.label_detection(image=image) - - for label in label_response.label_annotations[:10]: # Top 10 labels - features.extend([ - hash(label.description) % 1000 / 1000.0, # Normalized hash of label - label.score # Confidence score - ]) - - # Get text detection for additional context - text_response = vision_client.text_detection(image=image) - - if text_response.text_annotations: - # Add text features - text_content = text_response.text_annotations[0].description if text_response.text_annotations else "" - text_hash = hash(text_content.lower()) % 1000 / 1000.0 - features.extend([text_hash, len(text_content) / 1000.0]) # Normalized text length - - # Get face detection for additional features - face_response = vision_client.face_detection(image=image) - - face_count = len(face_response.face_annotations) - features.append(min(face_count / 10.0, 1.0)) # Normalized face count - - # Add image properties - try: - # Get image properties - properties_response = vision_client.image_properties(image=image) - - if properties_response.image_properties_annotation: - # Add dominant colors as features - colors = properties_response.image_properties_annotation.dominant_colors.colors - for i, color in enumerate(colors[:5]): # Top 5 colors - features.extend([ - color.color.red / 255.0, - color.color.green / 255.0, - color.color.blue / 255.0, - color.score - ]) - except Exception as e: - logger.warning(f"Could not extract image properties: {e}") - - # Pad or truncate to fixed size (512 dimensions) - target_size = 512 - if len(features) < target_size: - features.extend([0.0] * (target_size - len(features))) - else: - features = features[:target_size] + # Convert to numpy array + embeddings_array = np.array(embedding_vector, dtype=np.float32) # Normalize the feature vector - features_array = np.array(features, dtype=np.float32) - norm = np.linalg.norm(features_array) + norm = np.linalg.norm(embeddings_array) if norm > 0: - features_array = features_array / norm + embeddings_array = embeddings_array / norm - return features_array + logger.info(f"Generated embeddings with shape: {embeddings_array.shape}") + return embeddings_array except Exception as e: logger.error(f"Error generating embeddings: {e}") diff --git a/deployment/cloud-function/requirements.txt b/deployment/cloud-function/requirements.txt index 118bedb..45bb073 100644 --- a/deployment/cloud-function/requirements.txt +++ b/deployment/cloud-function/requirements.txt @@ -1,5 +1,5 @@ functions-framework==3.4.0 -google-cloud-vision==3.4.5 +google-cloud-aiplatform==1.38.0 google-cloud-firestore==2.11.1 google-cloud-storage==2.12.0 qdrant-client==1.7.0 diff --git a/deployment/cloud-function/test_vertex_ai_embeddings.py b/deployment/cloud-function/test_vertex_ai_embeddings.py new file mode 100644 index 0000000..eef647e --- /dev/null +++ b/deployment/cloud-function/test_vertex_ai_embeddings.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 +""" +Simple test script to verify Vertex AI multimodal embeddings work correctly. +Run this script to test the embedding generation before deploying. +""" + +import os +import sys +import logging +from PIL import Image +import io +import numpy as np + +# Add the current directory to the path so we can import main +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +# Set up logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +def create_test_image(): + """Create a simple test image""" + # Create a simple 100x100 RGB image with a red square + img = Image.new('RGB', (100, 100), color='white') + pixels = img.load() + + # Draw a red square in the center + for i in range(25, 75): + for j in range(25, 75): + pixels[i, j] = (255, 0, 0) # Red + + # Convert to bytes + img_bytes = io.BytesIO() + img.save(img_bytes, format='PNG') + return img_bytes.getvalue() + +def test_vertex_ai_embeddings(): + """Test Vertex AI embedding generation""" + try: + # Set required environment variables for testing + os.environ['GOOGLE_CLOUD_PROJECT'] = os.environ.get('GOOGLE_CLOUD_PROJECT', 'your-project-id') + os.environ['VERTEX_AI_LOCATION'] = os.environ.get('VERTEX_AI_LOCATION', 'us-central1') + + # Import the function we want to test + from main import generate_image_embeddings + + # Create test image + logger.info("Creating test image...") + test_image_data = create_test_image() + logger.info(f"Created test image with {len(test_image_data)} bytes") + + # Generate embeddings + logger.info("Generating embeddings using Vertex AI...") + embeddings = generate_image_embeddings(test_image_data) + + if embeddings is None: + logger.error("Failed to generate embeddings!") + return False + + # Verify embeddings + logger.info(f"Generated embeddings with shape: {embeddings.shape}") + logger.info(f"Embeddings dtype: {embeddings.dtype}") + logger.info(f"Embeddings range: [{embeddings.min():.4f}, {embeddings.max():.4f}]") + logger.info(f"Embeddings norm: {np.linalg.norm(embeddings):.4f}") + + # Basic validation + assert isinstance(embeddings, np.ndarray), "Embeddings should be numpy array" + assert embeddings.dtype == np.float32, "Embeddings should be float32" + assert len(embeddings.shape) == 1, "Embeddings should be 1D array" + assert embeddings.shape[0] == 1408, f"Expected 1408 dimensions, got {embeddings.shape[0]}" + + # Check if normalized (should be close to 1.0) + norm = np.linalg.norm(embeddings) + assert 0.9 <= norm <= 1.1, f"Embeddings should be normalized, norm is {norm}" + + logger.info("✅ All tests passed! Vertex AI embeddings are working correctly.") + return True + + except ImportError as e: + logger.error(f"Import error: {e}") + logger.error("Make sure you have installed the required dependencies:") + logger.error("pip install google-cloud-aiplatform") + return False + except Exception as e: + logger.error(f"Test failed with error: {e}") + return False + +if __name__ == "__main__": + logger.info("Testing Vertex AI multimodal embeddings...") + + # Check if required environment variables are set + project_id = os.environ.get('GOOGLE_CLOUD_PROJECT') + if not project_id: + logger.error("Please set GOOGLE_CLOUD_PROJECT environment variable") + logger.error("Example: export GOOGLE_CLOUD_PROJECT=your-project-id") + sys.exit(1) + + logger.info(f"Using project: {project_id}") + + success = test_vertex_ai_embeddings() + + if success: + logger.info("🎉 Test completed successfully!") + sys.exit(0) + else: + logger.error("❌ Test failed!") + sys.exit(1) \ No newline at end of file diff --git a/deployment/fix-cloud-run-deployment.sh b/deployment/fix-cloud-run-deployment.sh new file mode 100644 index 0000000..2d159c6 --- /dev/null +++ b/deployment/fix-cloud-run-deployment.sh @@ -0,0 +1,135 @@ +#!/bin/bash +set -e + +# Configuration +PROJECT_ID="gen-lang-client-0424120530" +REGION="us-central1" +SERVICE_NAME="sereact" + +echo "=== Cloud Run Deployment Fix Script ===" +echo "Project: $PROJECT_ID" +echo "Region: $REGION" +echo "Service: $SERVICE_NAME" +echo "" + +# Function to check if gcloud is authenticated +check_auth() { + if ! gcloud auth list --filter=status:ACTIVE --format="value(account)" | grep -q .; then + echo "ERROR: No active gcloud authentication found." + echo "Please run: gcloud auth login" + exit 1 + fi +} + +# Function to clean up problematic revisions +cleanup_revisions() { + echo "Step 1: Cleaning up problematic revisions..." + + # Get all revisions for the service + REVISIONS=$(gcloud run revisions list --service=$SERVICE_NAME --region=$REGION --project=$PROJECT_ID --format="value(metadata.name)" 2>/dev/null || echo "") + + if [ -z "$REVISIONS" ]; then + echo "No revisions found or service doesn't exist." + return 0 + fi + + echo "Found revisions:" + echo "$REVISIONS" + echo "" + + # Delete old revisions (keep the latest one for now) + REVISION_COUNT=$(echo "$REVISIONS" | wc -l) + if [ $REVISION_COUNT -gt 1 ]; then + echo "Deleting old revisions to prevent conflicts..." + echo "$REVISIONS" | head -n -1 | while read revision; do + if [ ! -z "$revision" ]; then + echo "Deleting revision: $revision" + gcloud run revisions delete "$revision" --region=$REGION --project=$PROJECT_ID --quiet || echo "Failed to delete $revision (may be in use)" + fi + done + fi +} + +# Function to force a new deployment +force_redeploy() { + echo "Step 2: Forcing a new deployment with Terraform..." + + cd "$(dirname "$0")/terraform" + + # Taint the Cloud Run service to force recreation + echo "Tainting Cloud Run service to force recreation..." + terraform taint google_cloud_run_service.sereact || echo "Service not in state or already tainted" + + # Apply the configuration + echo "Applying Terraform configuration..." + terraform apply -auto-approve + + cd - > /dev/null +} + +# Function to verify deployment +verify_deployment() { + echo "Step 3: Verifying deployment..." + + # Wait a moment for the service to be ready + sleep 10 + + # Check service status + SERVICE_URL=$(gcloud run services describe $SERVICE_NAME --region=$REGION --project=$PROJECT_ID --format="value(status.url)" 2>/dev/null || echo "") + + if [ ! -z "$SERVICE_URL" ]; then + echo "✅ Service deployed successfully!" + echo "Service URL: $SERVICE_URL" + + # Test the service + echo "Testing service health..." + if curl -s -o /dev/null -w "%{http_code}" "$SERVICE_URL/health" | grep -q "200"; then + echo "✅ Service is responding correctly!" + else + echo "⚠️ Service deployed but health check failed. Check logs:" + echo "gcloud logging read \"resource.type=cloud_run_revision AND resource.labels.service_name=$SERVICE_NAME\" --limit=10 --project=$PROJECT_ID" + fi + else + echo "❌ Service deployment failed." + exit 1 + fi +} + +# Main execution +main() { + echo "Starting Cloud Run deployment fix..." + echo "" + + check_auth + cleanup_revisions + force_redeploy + verify_deployment + + echo "" + echo "=== Deployment Fix Complete ===" + echo "If you continue to have issues, try:" + echo "1. Building a new image: ./deployment/deploy.sh --deploy --build" + echo "2. Checking logs: gcloud logging read \"resource.type=cloud_run_revision AND resource.labels.service_name=$SERVICE_NAME\" --limit=10 --project=$PROJECT_ID" +} + +# Help function +show_help() { + echo "Usage: $0 [--help]" + echo "" + echo "This script fixes Cloud Run deployment issues by:" + echo "1. Cleaning up problematic revisions" + echo "2. Forcing a new deployment with Terraform" + echo "3. Verifying the deployment" + echo "" + echo "Options:" + echo " --help Show this help message" +} + +# Parse arguments +if [ "$1" = "--help" ]; then + show_help + exit 0 +fi + +# Run main function +main \ No newline at end of file diff --git a/deployment/terraform/cloud-function.tf b/deployment/terraform/cloud-function.tf index 40090a8..ad7d1f4 100644 --- a/deployment/terraform/cloud-function.tf +++ b/deployment/terraform/cloud-function.tf @@ -60,8 +60,9 @@ resource "google_cloudfunctions2_function" "image_processor" { # Google Cloud Storage configuration GCS_BUCKET_NAME = var.storage_bucket_name - # Google Cloud Vision API - VISION_API_ENABLED = "true" + # Vertex AI configuration + GOOGLE_CLOUD_PROJECT = var.project_id + VERTEX_AI_LOCATION = var.region # Logging LOG_LEVEL = "INFO" @@ -97,9 +98,9 @@ resource "google_project_iam_member" "function_storage" { member = "serviceAccount:${local.cloud_function_service_account}" } -resource "google_project_iam_member" "function_vision" { +resource "google_project_iam_member" "function_vertex_ai" { project = var.project_id - role = "roles/ml.developer" + role = "roles/aiplatform.user" member = "serviceAccount:${local.cloud_function_service_account}" } diff --git a/deployment/terraform/main.tf b/deployment/terraform/main.tf index 40fefbc..04f5340 100644 --- a/deployment/terraform/main.tf +++ b/deployment/terraform/main.tf @@ -21,7 +21,8 @@ resource "google_project_service" "services" { "cloudfunctions.googleapis.com", "cloudbuild.googleapis.com", "eventarc.googleapis.com", - "pubsub.googleapis.com" + "pubsub.googleapis.com", + "aiplatform.googleapis.com" ]) project = var.project_id @@ -63,10 +64,20 @@ resource "google_cloud_run_service" "sereact" { } template { + metadata { + annotations = { + "autoscaling.knative.dev/maxScale" = "10" + # Force Cloud Run to always pull the latest image + "run.googleapis.com/execution-environment" = "gen2" + # Disable CPU throttling for better performance + "run.googleapis.com/cpu-throttling" = "false" + } + } + spec { containers { # Use our optimized image - image = "gcr.io/${var.project_id}/sereact-api:latest" + image = "gcr.io/${var.project_id}/sereact-api:${var.image_tag}" ports { container_port = 8000 @@ -133,38 +144,6 @@ resource "google_cloud_run_service" "sereact" { name = "LOG_LEVEL" value = "INFO" } - - # # CORS Configuration - These were missing! - # env { - # name = "CORS_ORIGINS" - # value = "[\"*\"]" - # } - - # env { - # name = "CORS_METHODS" - # value = "GET,POST,PUT,DELETE,OPTIONS" - # } - - # env { - # name = "CORS_HEADERS" - # value = "Content-Type,Authorization,X-Requested-With" - # } - - # env { - # name = "CORS_EXPOSE_HEADERS" - # value = "Content-Length,Content-Range" - # } - - # env { - # name = "CORS_MAX_AGE" - # value = "3600" - # } - } - } - - metadata { - annotations = { - "autoscaling.knative.dev/maxScale" = "10" } } } diff --git a/deployment/terraform/terraform.tfstate b/deployment/terraform/terraform.tfstate index 0eda6e6..3a277b6 100644 --- a/deployment/terraform/terraform.tfstate +++ b/deployment/terraform/terraform.tfstate @@ -1,7 +1,7 @@ { "version": 4, "terraform_version": "1.10.1", - "serial": 399, + "serial": 410, "lineage": "a183cd95-f987-8698-c6dd-84e933c394a5", "outputs": { "cloud_function_name": { @@ -98,16 +98,16 @@ "attributes": { "exclude_symlink_directories": null, "excludes": null, - "id": "045029ac803155784c12f8d587fee56b85b1fbe9", - "output_base64sha256": "b/FgNMMT30JSXfrLRXNkWeNc6i22YAmT3YwQRTw1+A4=", - "output_base64sha512": "7GDDTkHwwQVAlwSxe7yzgtGccMNIRCQ7t72ZRk7bcfDI1tzpruhJ5G/0AbrUMXWQO6LffnWtwumQ7XdFHAIzBA==", + "id": "7a7a706b5bba3a12744f2dd109eb18de7112f351", + "output_base64sha256": "0wAfDV7tH41jEspQ3LBLvIEnrQ6XU2aEtK2GWsMdyCA=", + "output_base64sha512": "glsNAiHzSTOy9mGDckkSyDJhBVFDtLh8Xr6+hSxtCT8nok9qNGO+61iTRLU42OPxaPS/BrbDAXJeT86F3riefA==", "output_file_mode": null, - "output_md5": "34d81725abbd4f423de71ecd4215d116", + "output_md5": "a5d3a7fe131c972bf8d0edf309545042", "output_path": "./function-source.zip", - "output_sha": "045029ac803155784c12f8d587fee56b85b1fbe9", - "output_sha256": "6ff16034c313df42525dfacb45736459e35cea2db6600993dd8c10453c35f80e", - "output_sha512": "ec60c34e41f0c105409704b17bbcb382d19c70c34844243bb7bd99464edb71f0c8d6dce9aee849e46ff401bad43175903ba2df7e75adc2e990ed77451c023304", - "output_size": 5014, + "output_sha": "7a7a706b5bba3a12744f2dd109eb18de7112f351", + "output_sha256": "d3001f0d5eed1f8d6312ca50dcb04bbc8127ad0e97536684b4ad865ac31dc820", + "output_sha512": "825b0d0221f34933b2f66183724912c83261055143b4b87c5ebebe852c6d093f27a24f6a3463beeb589344b538d8e3f168f4bf06b6c301725e4fce85deb89e7c", + "output_size": 4487, "source": [], "source_content": null, "source_content_filename": null, @@ -170,11 +170,9 @@ "run.googleapis.com/ingress": "all" }, "effective_annotations": { - "run.googleapis.com/client-name": "gcloud", - "run.googleapis.com/client-version": "431.0.0", "run.googleapis.com/ingress": "all", "run.googleapis.com/ingress-status": "all", - "run.googleapis.com/operation-id": "e4d7484f-39e4-4dde-8105-28d285eb927b", + "run.googleapis.com/operation-id": "7869f742-fe94-42d0-8d82-a1462681980d", "run.googleapis.com/urls": "[\"https://sereact-761163285547.us-central1.run.app\",\"https://sereact-p64zpdtkta-uc.a.run.app\"]", "serving.knative.dev/creator": "johnpccd3@gmail.com", "serving.knative.dev/lastModifier": "johnpccd3@gmail.com" @@ -183,15 +181,15 @@ "cloud.googleapis.com/location": "us-central1", "goog-terraform-provisioned": "true" }, - "generation": 2, - "labels": {}, + "generation": 1, + "labels": null, "namespace": "gen-lang-client-0424120530", - "resource_version": "AAY16Gy+yWQ", + "resource_version": "AAY16UbSm4k", "self_link": "/apis/serving.knative.dev/v1/namespaces/761163285547/services/sereact", "terraform_labels": { "goog-terraform-provisioned": "true" }, - "uid": "c67276c9-0c25-4a6c-8f39-4ea942599769" + "uid": "d5532269-ab10-4b77-b90f-698306bf0919" } ], "name": "sereact", @@ -218,14 +216,14 @@ "type": "RoutesReady" } ], - "latest_created_revision_name": "sereact-00002-cew", - "latest_ready_revision_name": "sereact-00002-cew", - "observed_generation": 2, + "latest_created_revision_name": "sereact-00001-9rv", + "latest_ready_revision_name": "sereact-00001-9rv", + "observed_generation": 1, "traffic": [ { "latest_revision": true, "percent": 100, - "revision_name": "sereact-00002-cew", + "revision_name": "sereact-00001-9rv", "tag": "", "url": "" } @@ -239,14 +237,14 @@ { "annotations": { "autoscaling.knative.dev/maxScale": "10", - "run.googleapis.com/client-name": "gcloud", - "run.googleapis.com/client-version": "431.0.0" + "run.googleapis.com/cpu-throttling": "false", + "run.googleapis.com/execution-environment": "gen2" }, "generation": 0, "labels": { "run.googleapis.com/startupProbeType": "Default" }, - "name": "sereact-00002-cew", + "name": "", "namespace": "", "resource_version": "", "self_link": "", @@ -258,8 +256,8 @@ "container_concurrency": 80, "containers": [ { - "args": [], - "command": [], + "args": null, + "command": null, "env": [ { "name": "FIRESTORE_DATABASE_NAME", @@ -334,7 +332,7 @@ "cpu": "1", "memory": "1Gi" }, - "requests": {} + "requests": null } ], "startup_probe": [ @@ -356,7 +354,7 @@ "working_dir": "" } ], - "node_selector": {}, + "node_selector": null, "service_account_name": "761163285547-compute@developer.gserviceaccount.com", "serving_state": "", "timeout_seconds": 300, @@ -437,7 +435,7 @@ "schema_version": 0, "attributes": { "condition": [], - "etag": "BwY16Etxb+g=", + "etag": "BwY16UdHJ00=", "id": "v1/projects/gen-lang-client-0424120530/locations/us-central1/services/sereact/roles/run.invoker/allUsers", "location": "us-central1", "member": "allUsers", @@ -471,7 +469,7 @@ "automatic_update_policy": [ {} ], - "build": "projects/761163285547/locations/us-central1/builds/1b8e28d1-ee4d-4d2f-acf2-47e2b03aa421", + "build": "projects/761163285547/locations/us-central1/builds/b2b7e513-e00e-462a-8ac8-94abdfb4a0b9", "docker_repository": "projects/gen-lang-client-0424120530/locations/us-central1/repositories/gcf-artifacts", "entry_point": "process_image_embedding", "environment_variables": {}, @@ -485,7 +483,7 @@ { "bucket": "gen-lang-client-0424120530-cloud-function-source", "generation": 1748123369545880, - "object": "function-source-34d81725abbd4f423de71ecd4215d116.zip" + "object": "function-source-a5d3a7fe131c972bf8d0edf309545042.zip" } ] } @@ -554,7 +552,7 @@ "goog-terraform-provisioned": "true" }, "timeouts": null, - "update_time": "2025-05-24T22:08:16.899711009Z", + "update_time": "2025-05-24T22:31:52.525335119Z", "url": "https://us-central1-gen-lang-client-0424120530.cloudfunctions.net/process-image-embedding" }, "sensitive_attributes": [ @@ -870,8 +868,8 @@ "database_edition": "STANDARD", "delete_protection_state": "DELETE_PROTECTION_DISABLED", "deletion_policy": "ABANDON", - "earliest_version_time": "2025-05-24T21:16:19.051906Z", - "etag": "INn0mIORvY0DMKrW4vCEvY0D", + "earliest_version_time": "2025-05-24T21:29:52.924798Z", + "etag": "IPHgo4eUvY0DMKrW4vCEvY0D", "id": "projects/gen-lang-client-0424120530/databases/sereact-imagedb", "key_prefix": "", "location_id": "us-central1", @@ -1495,21 +1493,21 @@ "content_encoding": "", "content_language": "", "content_type": "application/zip", - "crc32c": "YXAlNA==", + "crc32c": "Y4Q5hw==", "customer_encryption": [], - "detect_md5hash": "NNgXJau9T0I95x7NQhXRFg==", + "detect_md5hash": "pdOn/hMclyv40O3zCVRQQg==", "event_based_hold": false, - "generation": 1748124439573408, - "id": "gen-lang-client-0424120530-cloud-function-source-function-source-34d81725abbd4f423de71ecd4215d116.zip", + "generation": 1748125796837241, + "id": "gen-lang-client-0424120530-cloud-function-source-function-source-a5d3a7fe131c972bf8d0edf309545042.zip", "kms_key_name": "", - "md5hash": "NNgXJau9T0I95x7NQhXRFg==", - "md5hexhash": "34d81725abbd4f423de71ecd4215d116", - "media_link": "https://storage.googleapis.com/download/storage/v1/b/gen-lang-client-0424120530-cloud-function-source/o/function-source-34d81725abbd4f423de71ecd4215d116.zip?generation=1748124439573408\u0026alt=media", - "metadata": {}, - "name": "function-source-34d81725abbd4f423de71ecd4215d116.zip", - "output_name": "function-source-34d81725abbd4f423de71ecd4215d116.zip", + "md5hash": "pdOn/hMclyv40O3zCVRQQg==", + "md5hexhash": "a5d3a7fe131c972bf8d0edf309545042", + "media_link": "https://storage.googleapis.com/download/storage/v1/b/gen-lang-client-0424120530-cloud-function-source/o/function-source-a5d3a7fe131c972bf8d0edf309545042.zip?generation=1748125796837241\u0026alt=media", + "metadata": null, + "name": "function-source-a5d3a7fe131c972bf8d0edf309545042.zip", + "output_name": "function-source-a5d3a7fe131c972bf8d0edf309545042.zip", "retention": [], - "self_link": "https://www.googleapis.com/storage/v1/b/gen-lang-client-0424120530-cloud-function-source/o/function-source-34d81725abbd4f423de71ecd4215d116.zip", + "self_link": "https://www.googleapis.com/storage/v1/b/gen-lang-client-0424120530-cloud-function-source/o/function-source-a5d3a7fe131c972bf8d0edf309545042.zip", "source": "./function-source.zip", "storage_class": "STANDARD", "temporary_hold": false, diff --git a/deployment/terraform/terraform.tfstate.backup b/deployment/terraform/terraform.tfstate.backup index 6e488a6..e202c57 100644 --- a/deployment/terraform/terraform.tfstate.backup +++ b/deployment/terraform/terraform.tfstate.backup @@ -1,7 +1,7 @@ { "version": 4, "terraform_version": "1.10.1", - "serial": 397, + "serial": 404, "lineage": "a183cd95-f987-8698-c6dd-84e933c394a5", "outputs": { "cloud_function_name": { @@ -239,8 +239,8 @@ { "annotations": { "autoscaling.knative.dev/maxScale": "10", - "run.googleapis.com/client-name": "gcloud", - "run.googleapis.com/client-version": "431.0.0" + "run.googleapis.com/cpu-throttling": "false", + "run.googleapis.com/execution-environment": "gen2" }, "generation": 0, "labels": { @@ -598,6 +598,13 @@ } ] }, + { + "mode": "managed", + "type": "google_compute_address", + "name": "vector_db_static_ip", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [] + }, { "mode": "managed", "type": "google_compute_firewall", @@ -804,6 +811,12 @@ "zone": "us-central1-a" }, "sensitive_attributes": [ + [ + { + "type": "get_attr", + "value": "metadata_startup_script" + } + ], [ { "type": "get_attr", @@ -837,12 +850,6 @@ "type": "get_attr", "value": "disk_encryption_key_raw" } - ], - [ - { - "type": "get_attr", - "value": "metadata_startup_script" - } ] ], "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInVwZGF0ZSI6MTIwMDAwMDAwMDAwMH0sInNjaGVtYV92ZXJzaW9uIjoiNiJ9", @@ -870,8 +877,8 @@ "database_edition": "STANDARD", "delete_protection_state": "DELETE_PROTECTION_DISABLED", "deletion_policy": "ABANDON", - "earliest_version_time": "2025-05-24T21:15:22.382696Z", - "etag": "IPeLluiQvY0DMKrW4vCEvY0D", + "earliest_version_time": "2025-05-24T21:26:23.088753Z", + "etag": "IOqynKOTvY0DMKrW4vCEvY0D", "id": "projects/gen-lang-client-0424120530/databases/sereact-imagedb", "key_prefix": "", "location_id": "us-central1", diff --git a/deployment/terraform/variables.tf b/deployment/terraform/variables.tf index 069891d..67eda76 100644 --- a/deployment/terraform/variables.tf +++ b/deployment/terraform/variables.tf @@ -80,4 +80,10 @@ variable "use_static_ip" { description = "Whether to use a static IP for the vector database VM" type = bool default = false +} + +variable "image_tag" { + description = "The Docker image tag for the Cloud Run service" + type = string + default = "latest" } \ No newline at end of file