cp
This commit is contained in:
parent
c00f0e641f
commit
38d5cb8d98
@ -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}")
|
||||
|
||||
@ -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
|
||||
|
||||
107
deployment/cloud-function/test_vertex_ai_embeddings.py
Normal file
107
deployment/cloud-function/test_vertex_ai_embeddings.py
Normal file
@ -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)
|
||||
135
deployment/fix-cloud-run-deployment.sh
Normal file
135
deployment/fix-cloud-run-deployment.sh
Normal file
@ -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
|
||||
@ -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}"
|
||||
}
|
||||
|
||||
|
||||
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -81,3 +81,9 @@ variable "use_static_ip" {
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "image_tag" {
|
||||
description = "The Docker image tag for the Cloud Run service"
|
||||
type = string
|
||||
default = "latest"
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user