This commit is contained in:
johnpccd 2025-05-24 17:42:36 +02:00
parent 6257362ac2
commit 0852b1ea0c
6 changed files with 390 additions and 321 deletions

View File

@ -536,4 +536,36 @@ This modular architecture provides several benefits:
- **Testability**: Modules can be tested in isolation with mocked dependencies
- **Scalability**: New features can be added by extending existing modules
- **Reusability**: Common functionality is centralized for consistent implementation
- **Security**: Authentication and authorization are handled consistently
- **Security**: Authentication and authorization are handled consistently
## TODO
### High Priority
- [ ] Remove Pinecone integration and complete Qdrant migration
- [ ] Test and validate vector search functionality with Qdrant
- [ ] Implement proper pagination for search results
- [ ] Test Cloud Function image processing pipeline
- [ ] Validate VM setup for self-hosted Qdrant instance
### Medium Priority
- [ ] Add comprehensive logging for vector search operations
- [ ] Implement caching layer for frequently accessed embeddings
- [ ] Add monitoring and alerting for vector database performance
- [ ] Create backup strategy for vector database
- [ ] Document vector search API endpoints
### Low Priority
- [ ] Add support for batch embedding generation
- [ ] Implement embedding versioning
- [ ] Add support for custom embedding models
- [ ] Create visualization tools for embedding space
- [ ] Add support for embedding fine-tuning
## Recent Changes
- Migrated from Pinecone to self-hosted Qdrant
- Added Cloud Function for async image processing
- Implemented vector similarity search
- Added E2E testing infrastructure
- Set up VM for vector database hosting

View File

@ -77,6 +77,7 @@ echo "==================================="
# Destroy resources with Terraform
if [ "$DESTROY" = true ]; then
echo "WARNING: This will destroy all cloud resources managed by Terraform!"
echo "This includes Cloud Run services, Firestore database, storage buckets, and all data!"
echo "This action cannot be undone."
read -p "Are you sure you want to continue? (yes/no): " confirm
@ -96,10 +97,21 @@ if [ "$DESTROY" = true ]; then
fi
terraform init
# Import existing resources if they exist and aren't in state
echo "Importing any existing resources not managed by Terraform..."
# Try to import Cloud Run service
terraform import google_cloud_run_service.sereact "locations/$REGION/namespaces/$PROJECT_ID/services/sereact" 2>/dev/null || echo "Cloud Run service import skipped (already in state or doesn't exist)"
# Try to import Firestore database
terraform import google_firestore_database.database "projects/$PROJECT_ID/databases/(default)" 2>/dev/null || echo "Firestore database import skipped (already in state or doesn't exist)"
# Destroy everything through Terraform
terraform destroy -auto-approve
cd - > /dev/null
echo "Resources destroyed successfully."
echo "All resources destroyed successfully via Terraform."
exit 0
fi
@ -149,36 +161,34 @@ fi
# Deploy to Cloud Run
if [ "$DEPLOY" = true ]; then
echo "Deploying to Cloud Run..."
echo "Deploying to Cloud Run via Terraform..."
# Deploy using the latest image
# Ensure the latest image exists
LATEST_IMAGE_NAME="gcr.io/$PROJECT_ID/$IMAGE_NAME:latest"
# Check if we have an existing service.yaml to use
if [ -f "$(dirname "$0")/cloud-run/service.yaml" ]; then
echo "Deploying using service.yaml configuration..."
# Update image in service.yaml before deploying
YAML_FILE="$(dirname "$0")/cloud-run/service.yaml"
# Create a temporary file for sed operation
TMP_FILE=$(mktemp)
# Replace the image line in the YAML file
sed "s|image: gcr.io/[^/]*/[^:]*:.*|image: $LATEST_IMAGE_NAME|" "$YAML_FILE" > "$TMP_FILE"
# Replace the original file
cat "$TMP_FILE" > "$YAML_FILE"
rm "$TMP_FILE"
# Deploy with the updated YAML
gcloud run services replace "$YAML_FILE" --region="$REGION"
else
echo "Deploying directly..."
gcloud run deploy "$SERVICE_NAME" \
--image="$LATEST_IMAGE_NAME" \
--platform="managed" \
--region="$REGION" \
--allow-unauthenticated
# Check if image exists
if ! docker manifest inspect "$LATEST_IMAGE_NAME" > /dev/null 2>&1; then
echo "ERROR: Image $LATEST_IMAGE_NAME not found. Please run --build first."
exit 1
fi
# Deploy using Terraform
cd "$(dirname "$0")/terraform"
# Check if terraform.tfvars exists
if [ ! -f terraform.tfvars ]; then
echo "ERROR: terraform.tfvars not found. Please run --provision first."
exit 1
fi
echo "Applying Terraform configuration to deploy Cloud Run service..."
terraform init
terraform apply -auto-approve
cd - > /dev/null
# Get service URL
SERVICE_URL=$(gcloud run services describe "$SERVICE_NAME" --region="$REGION" --format='value(status.url)')
SERVICE_URL=$(gcloud run services describe "sereact" --region="$REGION" --format='value(status.url)')
echo "Deployment completed successfully."
echo "Service URL: $SERVICE_URL"

View File

@ -69,17 +69,49 @@ resource "google_cloud_run_service" "sereact" {
value = var.project_id
}
env {
name = "FIRESTORE_CREDENTIALS_FILE"
value = "/var/secrets/google/key.json"
}
env {
name = "GOOGLE_APPLICATION_CREDENTIALS"
value = "/var/secrets/google/key.json"
}
env {
name = "GCS_BUCKET_NAME"
value = var.storage_bucket_name
}
env {
name = "VECTOR_DB_ENVIRONMENT"
value = var.vector_db_environment
}
env {
name = "VECTOR_DB_INDEX_NAME"
value = var.vector_db_index_name
}
env {
name = "LOG_LEVEL"
value = "INFO"
}
}
}
metadata {
annotations = {
"autoscaling.knative.dev/maxScale" = "10"
"run.googleapis.com/ingress" = "all"
}
}
}
traffic {
percent = 100
latest_revision = true
}
depends_on = [google_project_service.services]

View File

@ -1,7 +1,7 @@
{
"version": 4,
"terraform_version": "1.10.1",
"serial": 53,
"serial": 57,
"lineage": "a183cd95-f987-8698-c6dd-84e933c394a5",
"outputs": {},
"resources": [],

View File

@ -1,27 +1,55 @@
{
"version": 4,
"terraform_version": "1.10.1",
"serial": 41,
"serial": 54,
"lineage": "a183cd95-f987-8698-c6dd-84e933c394a5",
"outputs": {
"cloud_run_url": {
"value": "https://sereact-p64zpdtkta-uc.a.run.app",
"type": "string"
},
"container_registry_url": {
"value": "gcr.io/gen-lang-client-0424120530/sereact",
"type": "string"
},
"firestore_database_id": {
"value": null,
"type": "string"
},
"pubsub_dlq_topic_name": {
"value": "image-processing-topic-dlq",
"value": null,
"type": "string"
},
"pubsub_subscription_name": {
"value": "image-processing-topic-subscription",
"value": null,
"type": "string"
},
"pubsub_topic_name": {
"value": "image-processing-topic",
"value": null,
"type": "string"
},
"qdrant_grpc_endpoint": {
"value": null,
"type": "string"
},
"qdrant_http_endpoint": {
"value": null,
"type": "string"
},
"storage_bucket_name": {
"value": "sereact-storage-bucket",
"value": null,
"type": "string"
},
"vector_db_vm_external_ip": {
"value": null,
"type": "string"
},
"vector_db_vm_internal_ip": {
"value": null,
"type": "string"
},
"vector_db_vm_name": {
"value": null,
"type": "string"
}
},
@ -61,310 +89,265 @@
},
{
"mode": "managed",
"type": "google_project_service",
"name": "services",
"type": "google_cloud_run_service",
"name": "sereact",
"provider": "provider[\"registry.terraform.io/hashicorp/google\"]",
"instances": [
{
"index_key": "cloudresourcemanager.googleapis.com",
"schema_version": 0,
"schema_version": 2,
"attributes": {
"disable_dependent_services": null,
"disable_on_destroy": false,
"id": "gen-lang-client-0424120530/cloudresourcemanager.googleapis.com",
"project": "gen-lang-client-0424120530",
"service": "cloudresourcemanager.googleapis.com",
"timeouts": null
},
"sensitive_attributes": [],
"private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjYwMDAwMDAwMDAwMCwidXBkYXRlIjoxMjAwMDAwMDAwMDAwfX0="
},
{
"index_key": "containerregistry.googleapis.com",
"schema_version": 0,
"attributes": {
"disable_dependent_services": null,
"disable_on_destroy": false,
"id": "gen-lang-client-0424120530/containerregistry.googleapis.com",
"project": "gen-lang-client-0424120530",
"service": "containerregistry.googleapis.com",
"timeouts": null
},
"sensitive_attributes": [],
"private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjYwMDAwMDAwMDAwMCwidXBkYXRlIjoxMjAwMDAwMDAwMDAwfX0="
},
{
"index_key": "firestore.googleapis.com",
"schema_version": 0,
"attributes": {
"disable_dependent_services": null,
"disable_on_destroy": false,
"id": "gen-lang-client-0424120530/firestore.googleapis.com",
"project": "gen-lang-client-0424120530",
"service": "firestore.googleapis.com",
"timeouts": null
},
"sensitive_attributes": [],
"private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjYwMDAwMDAwMDAwMCwidXBkYXRlIjoxMjAwMDAwMDAwMDAwfX0="
},
{
"index_key": "run.googleapis.com",
"schema_version": 0,
"attributes": {
"disable_dependent_services": null,
"disable_on_destroy": false,
"id": "gen-lang-client-0424120530/run.googleapis.com",
"project": "gen-lang-client-0424120530",
"service": "run.googleapis.com",
"timeouts": null
},
"sensitive_attributes": [],
"private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjYwMDAwMDAwMDAwMCwidXBkYXRlIjoxMjAwMDAwMDAwMDAwfX0="
},
{
"index_key": "storage.googleapis.com",
"schema_version": 0,
"attributes": {
"disable_dependent_services": null,
"disable_on_destroy": false,
"id": "gen-lang-client-0424120530/storage.googleapis.com",
"project": "gen-lang-client-0424120530",
"service": "storage.googleapis.com",
"timeouts": null
},
"sensitive_attributes": [],
"private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjYwMDAwMDAwMDAwMCwidXBkYXRlIjoxMjAwMDAwMDAwMDAwfX0="
}
]
},
{
"mode": "managed",
"type": "google_pubsub_subscription",
"name": "image_processing_dlq",
"provider": "provider[\"registry.terraform.io/hashicorp/google\"]",
"instances": [
{
"schema_version": 0,
"attributes": {
"ack_deadline_seconds": 10,
"bigquery_config": [],
"cloud_storage_config": [],
"dead_letter_policy": [],
"effective_labels": {
"component": "image-processing-dlq",
"environment": "dev",
"goog-terraform-provisioned": "true",
"service": "sereact"
},
"enable_exactly_once_delivery": false,
"enable_message_ordering": false,
"expiration_policy": [
"autogenerate_revision_name": false,
"id": "locations/us-central1/namespaces/gen-lang-client-0424120530/services/sereact",
"location": "us-central1",
"metadata": [
{
"ttl": "2678400s"
"annotations": {},
"effective_annotations": {
"run.googleapis.com/ingress": "all",
"run.googleapis.com/ingress-status": "all",
"run.googleapis.com/operation-id": "d2cc9d17-1252-4660-a3c8-d5c20351c717",
"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"
},
"effective_labels": {
"cloud.googleapis.com/location": "us-central1"
},
"generation": 3,
"labels": {},
"namespace": "gen-lang-client-0424120530",
"resource_version": "AAY12wTEYMI",
"self_link": "/apis/serving.knative.dev/v1/namespaces/761163285547/services/sereact",
"terraform_labels": {},
"uid": "3825dcdf-9b6b-4f9c-bc6d-2434a25e141b"
}
],
"filter": "",
"id": "projects/gen-lang-client-0424120530/subscriptions/image-processing-topic-dlq-subscription",
"labels": {
"component": "image-processing-dlq",
"environment": "dev",
"service": "sereact"
},
"message_retention_duration": "2592000s",
"name": "image-processing-topic-dlq-subscription",
"name": "sereact",
"project": "gen-lang-client-0424120530",
"push_config": [],
"retain_acked_messages": true,
"retry_policy": [],
"terraform_labels": {
"component": "image-processing-dlq",
"environment": "dev",
"goog-terraform-provisioned": "true",
"service": "sereact"
},
"status": [
{
"conditions": [
{
"message": "",
"reason": "",
"status": "True",
"type": "Ready"
},
{
"message": "",
"reason": "",
"status": "True",
"type": "ConfigurationsReady"
},
{
"message": "",
"reason": "",
"status": "True",
"type": "RoutesReady"
}
],
"latest_created_revision_name": "sereact-00001-nnx",
"latest_ready_revision_name": "sereact-00001-nnx",
"observed_generation": 3,
"traffic": [
{
"latest_revision": true,
"percent": 100,
"revision_name": "sereact-00001-nnx",
"tag": "",
"url": ""
}
],
"url": "https://sereact-p64zpdtkta-uc.a.run.app"
}
],
"template": [
{
"metadata": [
{
"annotations": {
"autoscaling.knative.dev/maxScale": "3"
},
"generation": 0,
"labels": {
"run.googleapis.com/startupProbeType": "Custom"
},
"name": "",
"namespace": "",
"resource_version": "",
"self_link": "",
"uid": ""
}
],
"spec": [
{
"container_concurrency": 80,
"containers": [
{
"args": [],
"command": [],
"env": [
{
"name": "API_KEY_SECRET",
"value": "",
"value_from": [
{
"secret_key_ref": [
{
"key": "latest",
"name": "sereact-api-key-secret"
}
]
}
]
},
{
"name": "FIRESTORE_CREDENTIALS_FILE",
"value": "/var/secrets/google/key.json",
"value_from": []
},
{
"name": "FIRESTORE_PROJECT_ID",
"value": "gen-lang-client-0424120530",
"value_from": []
},
{
"name": "GCS_BUCKET_NAME",
"value": "gen-lang-client-0424120530-images",
"value_from": []
},
{
"name": "GOOGLE_APPLICATION_CREDENTIALS",
"value": "/var/secrets/google/key.json",
"value_from": []
},
{
"name": "LOG_LEVEL",
"value": "INFO",
"value_from": []
},
{
"name": "VECTOR_DB_API_KEY",
"value": "",
"value_from": [
{
"secret_key_ref": [
{
"key": "latest",
"name": "sereact-vector-db-key"
}
]
}
]
},
{
"name": "VECTOR_DB_ENVIRONMENT",
"value": "gcp-starter",
"value_from": []
},
{
"name": "VECTOR_DB_INDEX_NAME",
"value": "image-embeddings",
"value_from": []
}
],
"env_from": [],
"image": "gcr.io/gen-lang-client-0424120530/sereact-api:latest",
"liveness_probe": [],
"name": "",
"ports": [
{
"container_port": 8000,
"name": "http1",
"protocol": ""
}
],
"resources": [
{
"limits": {
"cpu": "1",
"memory": "1Gi"
},
"requests": {}
}
],
"startup_probe": [
{
"failure_threshold": 10,
"grpc": [],
"http_get": [
{
"http_headers": [],
"path": "/",
"port": 8000
}
],
"initial_delay_seconds": 20,
"period_seconds": 5,
"tcp_socket": [],
"timeout_seconds": 1
}
],
"volume_mounts": [
{
"mount_path": "/var/secrets/google",
"name": "gcp-sa-key"
}
],
"working_dir": ""
}
],
"node_selector": {},
"service_account_name": "761163285547-compute@developer.gserviceaccount.com",
"serving_state": "",
"timeout_seconds": 300,
"volumes": [
{
"csi": [],
"empty_dir": [],
"name": "gcp-sa-key",
"nfs": [],
"secret": [
{
"default_mode": 0,
"items": [
{
"key": "latest",
"mode": 0,
"path": "key.json"
}
],
"secret_name": "sereact-gcp-sa-key"
}
]
}
]
}
]
}
],
"timeouts": null,
"topic": "projects/gen-lang-client-0424120530/topics/image-processing-topic-dlq"
},
"sensitive_attributes": [],
"private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInVwZGF0ZSI6MTIwMDAwMDAwMDAwMH19",
"dependencies": [
"google_pubsub_topic.image_processing_dlq"
]
}
]
},
{
"mode": "managed",
"type": "google_pubsub_topic",
"name": "image_processing",
"provider": "provider[\"registry.terraform.io/hashicorp/google\"]",
"instances": [
{
"schema_version": 0,
"attributes": {
"effective_labels": {
"component": "image-processing",
"environment": "dev",
"goog-terraform-provisioned": "true",
"service": "sereact"
},
"id": "projects/gen-lang-client-0424120530/topics/image-processing-topic",
"ingestion_data_source_settings": [],
"kms_key_name": "",
"labels": {
"component": "image-processing",
"environment": "dev",
"service": "sereact"
},
"message_retention_duration": "",
"message_storage_policy": [],
"name": "image-processing-topic",
"project": "gen-lang-client-0424120530",
"schema_settings": [],
"terraform_labels": {
"component": "image-processing",
"environment": "dev",
"goog-terraform-provisioned": "true",
"service": "sereact"
},
"timeouts": null
},
"sensitive_attributes": [],
"private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInVwZGF0ZSI6MTIwMDAwMDAwMDAwMH19"
}
]
},
{
"mode": "managed",
"type": "google_pubsub_topic",
"name": "image_processing_dlq",
"provider": "provider[\"registry.terraform.io/hashicorp/google\"]",
"instances": [
{
"schema_version": 0,
"attributes": {
"effective_labels": {
"component": "image-processing-dlq",
"environment": "dev",
"goog-terraform-provisioned": "true",
"service": "sereact"
},
"id": "projects/gen-lang-client-0424120530/topics/image-processing-topic-dlq",
"ingestion_data_source_settings": [],
"kms_key_name": "",
"labels": {
"component": "image-processing-dlq",
"environment": "dev",
"service": "sereact"
},
"message_retention_duration": "",
"message_storage_policy": [],
"name": "image-processing-topic-dlq",
"project": "gen-lang-client-0424120530",
"schema_settings": [],
"terraform_labels": {
"component": "image-processing-dlq",
"environment": "dev",
"goog-terraform-provisioned": "true",
"service": "sereact"
},
"timeouts": null
},
"sensitive_attributes": [],
"private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInVwZGF0ZSI6MTIwMDAwMDAwMDAwMH19"
}
]
},
{
"mode": "managed",
"type": "google_pubsub_topic_iam_binding",
"name": "image_processing_publisher",
"provider": "provider[\"registry.terraform.io/hashicorp/google\"]",
"instances": [
{
"schema_version": 0,
"attributes": {
"condition": [],
"etag": "BwY14zaElfE=",
"id": "projects/gen-lang-client-0424120530/topics/image-processing-topic/roles/pubsub.publisher",
"members": [
"serviceAccount:761163285547-compute@developer.gserviceaccount.com"
],
"project": "gen-lang-client-0424120530",
"role": "roles/pubsub.publisher",
"topic": "projects/gen-lang-client-0424120530/topics/image-processing-topic"
},
"sensitive_attributes": [],
"private": "bnVsbA==",
"dependencies": [
"data.google_project.current",
"google_pubsub_topic.image_processing"
]
}
]
},
{
"mode": "managed",
"type": "google_storage_bucket",
"name": "app_bucket",
"provider": "provider[\"registry.terraform.io/hashicorp/google\"]",
"instances": [
{
"schema_version": 3,
"attributes": {
"autoclass": [],
"cors": [],
"custom_placement_config": [],
"default_event_based_hold": false,
"effective_labels": {
"goog-terraform-provisioned": "true"
},
"enable_object_retention": false,
"encryption": [],
"force_destroy": false,
"hierarchical_namespace": [
"traffic": [
{
"enabled": false
"latest_revision": true,
"percent": 100,
"revision_name": "",
"tag": "",
"url": ""
}
],
"id": "sereact-storage-bucket",
"labels": null,
"lifecycle_rule": [],
"location": "US-CENTRAL1",
"logging": [],
"name": "sereact-storage-bucket",
"project": "gen-lang-client-0424120530",
"project_number": 761163285547,
"public_access_prevention": "inherited",
"requester_pays": false,
"retention_policy": [],
"rpo": null,
"self_link": "https://www.googleapis.com/storage/v1/b/sereact-storage-bucket",
"soft_delete_policy": [
{
"effective_time": "2025-05-24T15:17:40.181Z",
"retention_duration_seconds": 604800
}
],
"storage_class": "STANDARD",
"terraform_labels": {
"goog-terraform-provisioned": "true"
},
"time_created": "2025-05-24T15:17:40.181Z",
"timeouts": null,
"uniform_bucket_level_access": true,
"updated": "2025-05-24T15:17:40.181Z",
"url": "gs://sereact-storage-bucket",
"versioning": [],
"website": []
]
},
"sensitive_attributes": [],
"private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjo2MDAwMDAwMDAwMDAsInJlYWQiOjI0MDAwMDAwMDAwMCwidXBkYXRlIjoyNDAwMDAwMDAwMDB9LCJzY2hlbWFfdmVyc2lvbiI6IjMifQ==",
"dependencies": [
"google_project_service.services"
]
"private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInVwZGF0ZSI6MTIwMDAwMDAwMDAwMH0sInNjaGVtYV92ZXJzaW9uIjoiMiJ9"
}
]
},
{
"mode": "managed",
"type": "google_compute_instance",
"name": "vector_db_vm_with_static_ip",
"provider": "provider[\"registry.terraform.io/hashicorp/google\"]",
"instances": []
}
],
"check_results": null

View File

@ -58,6 +58,18 @@ variable "qdrant_api_key" {
default = ""
}
variable "vector_db_environment" {
description = "Vector database environment (e.g., gcp-starter for Pinecone)"
type = string
default = "gcp-starter"
}
variable "vector_db_index_name" {
description = "Vector database index name for image embeddings"
type = string
default = "image-embeddings"
}
variable "allowed_cidr_blocks" {
description = "CIDR blocks allowed to access the vector database"
type = string