From a31ea1fe5331a6c14e3eae52720d924037d24a0b Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 23 Sep 2025 06:56:31 +0000 Subject: [PATCH] Initial pattern commit --- s3-lambda-bedrock-tf/Diagram.png | Bin 0 -> 95492 bytes s3-lambda-bedrock-tf/README.md | 237 +++++++++++++++++++++ s3-lambda-bedrock-tf/example-pattern.json | 56 +++++ s3-lambda-bedrock-tf/main.tf | 248 ++++++++++++++++++++++ s3-lambda-bedrock-tf/src/app.py | 180 ++++++++++++++++ 5 files changed, 721 insertions(+) create mode 100644 s3-lambda-bedrock-tf/Diagram.png create mode 100644 s3-lambda-bedrock-tf/README.md create mode 100644 s3-lambda-bedrock-tf/example-pattern.json create mode 100644 s3-lambda-bedrock-tf/main.tf create mode 100644 s3-lambda-bedrock-tf/src/app.py diff --git a/s3-lambda-bedrock-tf/Diagram.png b/s3-lambda-bedrock-tf/Diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..6083e2a9e20e685a05fcfa2697d3d06a0b1c631e GIT binary patch literal 95492 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 literal 0 HcmV?d00001 diff --git a/s3-lambda-bedrock-tf/README.md b/s3-lambda-bedrock-tf/README.md new file mode 100644 index 000000000..7810c2791 --- /dev/null +++ b/s3-lambda-bedrock-tf/README.md @@ -0,0 +1,237 @@ +# Serverless Image Analysis and Auto-Tagging with Amazon Bedrock Nova Lite + +![architecture](architecture/architecture.png) + +This pattern implements a serverless image analysis and auto-tagging service using Amazon S3, AWS Lambda and Amazon Bedrock's Nova Lite model. When images are uploaded to an S3 bucket, it automatically triggers a Lambda function that analyzes the image content using Amazon Nova Lite and applies descriptive tags as S3 metadata. + +The Lambda function processes the uploaded image by sending it to Amazon Bedrock's Nova Lite model for analysis. Nova Lite generates 10 descriptive words based on the image content, and these words are automatically applied as S3 object tags, enabling powerful search and organization capabilities for your image collection. + +Learn more about this pattern at Serverless Land Patterns: https://serverlessland.com/patterns/s3-lambda-bedrock-nova + +Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example. + +## Requirements + +* [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources. +* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured +* [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) +* [Terraform](https://learn.hashicorp.com/tutorials/terraform/install-cli?in=terraform/aws-get-started) installed +* [Amazon Bedrock Nova Lite Foundation Model Access](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html#add-model-access) + +Note: The Lambda function uses Python 3.13 runtime. + +## Deployment Instructions + +For this pattern, you need access to Amazon Nova Lite foundation model (Model ID: amazon.nova-lite-v1:0). The default deployment region is us-east-1, but you can customize this using the aws_region variable. + +You must request access to the Nova Lite model before you can use it. If you try to use the model before you have requested access to it, you will receive an error message. + +1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository: + ``` + git clone https://github.com/aws-samples/serverless-patterns + ``` +1. Change directory to the pattern directory: + ``` + cd s3-lambda-bedrock-tf + ``` +1. From the command line, initialize terraform to downloads and installs the providers defined in the configuration: + ``` + terraform init + ``` +1. From the command line, review the planned changes before applying: + ``` + terraform plan + ``` + + Optionally, you can specify a custom AWS region (default is us-east-1): + ``` + terraform plan -var="aws_region=us-west-2" + ``` + +1. From the command line, apply the configuration in the main.tf file: + ``` + terraform apply + ``` + +1. Confirm the deployment by typing `yes` when prompted. + +## Configuration Variables + +The pattern supports the following Terraform variables: + +| Variable | Description | Type | Default | +|----------|-------------|------|---------| +| `aws_region` | AWS region for deployment | string | "us-east-1" | +| `prefix` | Prefix to associate with the resources | string | "s3-lambda-bedrock-tf" | + +### Region Support + +**Important:** Please check documentation for lastest Bedrock models availability + Amazon Bedrock -> User Guide -> Model support by AWS Region in Amazon Bedrock + https://docs.aws.amazon.com/bedrock/latest/userguide/models-regions.html + Amazon Nova Lite is currently available in the following regions: + +Make sure Nova Lite is available in your chosen region before deployment. + +## Testing + +1. Upload an image to the S3 bucket using the AWS CLI. Replace `S3_BUCKET_NAME` with the generated `s3_image_bucket` from Terraform (refer to the Terraform Outputs section): + + ``` + aws s3 cp your-image.jpg s3://S3_BUCKET_NAME/images/ + ``` + + For example: + ``` + aws s3 cp sample-photo.jpg s3://s3-lambda-bedrock-tf-image-analysis-bucket-abc12345/images/ + ``` + +2. Monitor the Lambda function execution in CloudWatch Logs: + + ``` + aws logs tail "/aws/lambda/s3-lambda-bedrock-tf-image-analysis" --follow --format json + ``` + + You should see concise log entries like: + ``` + SUCCESS: images/sample-photo.jpg | Model: amazon.nova-lite-v1:0 | Nova Response: landscape, mountains, sunset, clouds, nature, scenic, outdoor, beautiful, peaceful, horizon | Tags Applied: 10 + ``` + +3. Check the applied tags on your uploaded image: + + ``` + aws s3api get-object-tagging --bucket S3_BUCKET_NAME --key images/your-image.jpg + ``` + + Example response: + ```json + { + "TagSet": [ + { + "Key": "ai-tag-1", + "Value": "landscape" + }, + { + "Key": "ai-tag-2", + "Value": "mountains" + }, + { + "Key": "ai-tag-3", + "Value": "sunset" + } + ] + } + ``` + +4. You can also view the tags in the AWS S3 Console by navigating to your bucket and selecting the uploaded image. + +### Supported Image Formats +- JPEG (.jpg, .jpeg) +- PNG (.png) + +## Architecture Details + +The solution automatically creates: +- S3 bucket with `images/` folder for organized storage +- Lambda function configured with Nova Lite model access +- CloudWatch log group with 14-day retention +- IAM roles and policies with least-privilege access +- S3 event notifications for automatic triggering + +## Cleanup + +1. Change directory to the pattern directory: + ``` + cd serverless-patterns/s3-lambda-bedrock-claude-image-analysis + ``` + +2. Delete all objects from the S3 bucket first: + ``` + aws s3 rm s3://YOUR_BUCKET_NAME --recursive + ``` + +3. Delete all created resources + ``` + terraform destroy + ``` + + Or with custom region: + ``` + terraform destroy -var="aws_region=us-west-2" + ``` + +4. Confirm the destruction by typing `yes` when prompted. + +5. Confirm all created resources has been deleted + ``` + terraform show + ``` + +## Troubleshooting + +### No CloudWatch Logs Appearing +1. Check if the Lambda function is being triggered: + ```bash + aws logs describe-log-groups --log-group-name-prefix "/aws/lambda/s3-lambda-bedrock-tf" + ``` + +2. Verify Lambda function permissions: + ```bash + aws iam get-role --role-name s3-lambda-bedrock-tf-image-analysis-role-* + ``` + +### Nova Lite Access Issues +1. Verify Nova Lite model access in your region: + ```bash + aws bedrock list-foundation-models --region YOUR_REGION --query 'modelSummaries[?contains(modelId, `nova-lite`)]' + ``` + +2. Check if Nova Lite model is accessible: + ```bash + aws bedrock get-foundation-model --model-identifier amazon.nova-lite-v1:0 --region YOUR_REGION + ``` + +3. Request model access in AWS Bedrock console if needed: + - Go to AWS Bedrock Console → Model Access + - Request access to `amazon.nova-lite-v1:0` + - Wait for approval (usually immediate) + +### Lambda Function Debug Steps + +If you see "ValidationException: unsupported input modality" errors: +1. Confirm you're using Nova Lite (not Nova Micro) in the Lambda code +2. Verify model access has been granted in Bedrock console +3. Check that you're deploying in a supported region (us-east-1, us-west-2) + +### No Tags Being Added to S3 Objects +1. Check Lambda execution logs for errors: + ```bash + aws logs filter-log-events --log-group-name "/aws/lambda/s3-lambda-bedrock-tf-image-analysis" --start-time $(date -d '1 hour ago' +%s)000 + ``` + +2. Manually test S3 tagging permissions: + ```bash + aws s3api put-object-tagging --bucket YOUR_BUCKET --key images/test.jpg --tagging 'TagSet=[{Key=test,Value=manual}]' + ``` + +## Log Output Examples + +**Successful Processing:** +``` +SUCCESS: images/nature-photo.jpg | Model: amazon.nova-lite-v1:0 | Nova Response: forest, trees, green, natural, peaceful, woodland, leaves, branches, sunlight, serene | Tags Applied: 10 +``` + +**Failed Processing:** +``` +FAILED: images/corrupted-file.jpg | Model: amazon.nova-lite-v1:0 | Error: An error occurred (ValidationException) when calling the InvokeModel operation +``` + +**Skipped Files:** +``` +SKIPPED: documents/readme.txt - Unsupported file type: txt +``` + +---- +Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +SPDX-License-Identifier: MIT-0 \ No newline at end of file diff --git a/s3-lambda-bedrock-tf/example-pattern.json b/s3-lambda-bedrock-tf/example-pattern.json new file mode 100644 index 000000000..922e178d4 --- /dev/null +++ b/s3-lambda-bedrock-tf/example-pattern.json @@ -0,0 +1,56 @@ +{ + "title": "Amazon S3 images autotagging with AWS Lambda and Amazon Bedrock", + "description": "Create a Lambda function that is triggered for every image file uploaded to S3 and tags the file using Bedrock.", + "language": "Python", + "level": "200", + "framework": "Terraform", + "introBox": { + "headline": "Lambda function triggered for every image file stored to S3", + "text": [ + "The terraform manifest deploys a Lambda function, an S3 bucket and the IAM resources required to run the application.", + "The Lambda function is triggered directly by S3 events when files with .jpg, .jpeg or .png extensions are uploaded to the images/ folder.", + "The Lambda function uses Amazon Bedrock Nova Lite model to analyze images and automatically apply descriptive tags." + ] + }, + "gitHub": { + "template": { + "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/s3-lambda-bedrock-tf", + "templateURL": "serverless-patterns/s3-lambda-bedrock-tf", + "projectFolder": "s3-lambda-bedrock-tf", + "templateFile": "main.tf" + } + }, + "resources": { + "bullets": [ + { + "text": "Using Amazon S3 Event Notifications to invoke Lambda functions", + "link": "https://docs.aws.amazon.com/AmazonS3/latest/userguide/notification-how-to-event-types-and-destinations.html" + } + ] + }, + "deploy": { + "text": [ + "terraform init", + "terraform apply" + ] + }, + "testing": { + "text": [ + "See the GitHub repo for detailed testing instructions." + ] + }, + "cleanup": { + "text": [ + "terraform destroy" + ] + }, + "authors": [ + { + "name": "Oriol Matavacas", + "image": "https://serverlessland.com/assets/images/resources/contributors/oriol-matavacas.jpg", + "bio": "Oriol Matavacas is a Sr. Solutions Architect at AWS based in Barcelona. Oriol primarily supporting customers on the journey to the Cloud. He enjoys building new solutions with scalability, availability and easy to maintain by using serverless.", + "linkedin": "oriol-matavacas-rodriguez-b165868a", + "twitter": "" + } + ] +} diff --git a/s3-lambda-bedrock-tf/main.tf b/s3-lambda-bedrock-tf/main.tf new file mode 100644 index 000000000..3fe302322 --- /dev/null +++ b/s3-lambda-bedrock-tf/main.tf @@ -0,0 +1,248 @@ +variable "aws_region" { + description = "AWS region for deployment" + type = string + default = "us-east-1" +} + +variable "prefix" { + description = "Prefix to associate with the resources" + type = string + default = "s3-lambda-bedrock-tf" +} + +provider "aws" { + region = var.aws_region +} + +resource "random_string" "suffix" { + length = 8 + special = false + upper = false +} + +# Data source for current region +data "aws_region" "current" {} + +# Data source for current caller identity (account ID) +data "aws_caller_identity" "current" {} + +# Create ZIP archive of Lambda function +data "archive_file" "lambda_zip" { + type = "zip" + source_file = "${path.module}/src/app.py" + output_path = "${path.module}/lambda_function.zip" +} + +# S3 bucket for storing images +resource "aws_s3_bucket" "image_bucket" { + bucket = "${lower(var.prefix)}-image-analysis-bucket-${random_string.suffix.result}" + force_destroy = true +} + +# Create images folder in S3 bucket +resource "aws_s3_object" "images_folder" { + bucket = aws_s3_bucket.image_bucket.id + key = "images/" + source = "/dev/null" +} + +# S3 bucket versioning +resource "aws_s3_bucket_versioning" "image_bucket_versioning" { + bucket = aws_s3_bucket.image_bucket.id + versioning_configuration { + status = "Enabled" + } +} + +# S3 bucket server side encryption +resource "aws_s3_bucket_server_side_encryption_configuration" "image_bucket_encryption" { + bucket = aws_s3_bucket.image_bucket.id + + rule { + apply_server_side_encryption_by_default { + sse_algorithm = "AES256" + } + } +} + +# Create CloudWatch Log Group for Lambda +resource "aws_cloudwatch_log_group" "lambda_log_group" { + name = "/aws/lambda/${lower(var.prefix)}-image-analysis" + retention_in_days = 14 + + lifecycle { + prevent_destroy = false + } +} + +# IAM Policy for Lambda function +resource "aws_iam_policy" "lambda_policy" { + name = "${lower(var.prefix)}-ImageAnalysisPolicy-${random_string.suffix.result}" + path = "/" + description = "IAM policy for Lambda function to access S3, Bedrock Nova Lite, and S3 tagging" + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = [ + "s3:GetObjectAcl", + "s3:GetObject", + "s3:ListAllMyBuckets", + "s3:ListBucketVersions", + "s3:GetObjectAttributes", + "s3:ListBucket", + "s3:PutObjectTagging", + "s3:GetObjectTagging" + ] + Resource = [ + aws_s3_bucket.image_bucket.arn, + "${aws_s3_bucket.image_bucket.arn}/*" + ] + }, + { + Effect = "Allow" + Action = [ + "bedrock:InvokeModel", + "bedrock:InvokeModelWithResponseStream" + ] + Resource = [ + "arn:aws:bedrock:${var.aws_region}::foundation-model/amazon.nova-lite-v1:0" + ] + }, + { + Effect = "Allow" + Action = [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + "logs:DescribeLogGroups", + "logs:DescribeLogStreams" + ] + Resource = [ + "arn:aws:logs:${var.aws_region}:${data.aws_caller_identity.current.account_id}:log-group:/aws/lambda/${lower(var.prefix)}-image-analysis", + "arn:aws:logs:${var.aws_region}:${data.aws_caller_identity.current.account_id}:log-group:/aws/lambda/${lower(var.prefix)}-image-analysis:*" + ] + } + ] + }) +} + +# IAM role for Lambda function +resource "aws_iam_role" "lambda_role" { + name = "${lower(var.prefix)}-image-analysis-role-${random_string.suffix.result}" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "lambda.amazonaws.com" + } + } + ] + }) +} + +# Attach custom policy to Lambda role +resource "aws_iam_role_policy_attachment" "lambda_policy_attachment" { + policy_arn = aws_iam_policy.lambda_policy.arn + role = aws_iam_role.lambda_role.name +} + +# Attach basic execution policy for CloudWatch logs +resource "aws_iam_role_policy_attachment" "lambda_basic_execution" { + policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + role = aws_iam_role.lambda_role.name +} + +# Lambda function +resource "aws_lambda_function" "image_analysis_function" { + filename = data.archive_file.lambda_zip.output_path + function_name = "${lower(var.prefix)}-image-analysis" + role = aws_iam_role.lambda_role.arn + handler = "app.lambda_handler" + source_code_hash = data.archive_file.lambda_zip.output_base64sha256 + runtime = "python3.13" + timeout = 120 + memory_size = 1024 + description = "Lambda to analyze images using Amazon Nova Lite and add descriptive tags" + + environment { + variables = { + LOG_LEVEL = "INFO" + AWS_REGION_CUSTOM = var.aws_region + NOVA_MODEL_ID = "amazon.nova-lite-v1:0" + } + } + + depends_on = [ + aws_iam_role_policy_attachment.lambda_policy_attachment, + aws_iam_role_policy_attachment.lambda_basic_execution, + aws_cloudwatch_log_group.lambda_log_group + ] +} + +# Lambda permission for S3 to invoke the function +resource "aws_lambda_permission" "s3_invoke" { + statement_id = "AllowExecutionFromS3Bucket" + action = "lambda:InvokeFunction" + function_name = aws_lambda_function.image_analysis_function.function_name + principal = "s3.amazonaws.com" + source_arn = aws_s3_bucket.image_bucket.arn +} + +# S3 bucket notification for images +resource "aws_s3_bucket_notification" "bucket_notification" { + bucket = aws_s3_bucket.image_bucket.id + + # Lambda function trigger for JPG images + lambda_function { + lambda_function_arn = aws_lambda_function.image_analysis_function.arn + events = ["s3:ObjectCreated:Put"] + filter_prefix = "images/" + filter_suffix = ".jpg" + } + + # Lambda function trigger for JPEG images + lambda_function { + lambda_function_arn = aws_lambda_function.image_analysis_function.arn + events = ["s3:ObjectCreated:Put"] + filter_prefix = "images/" + filter_suffix = ".jpeg" + } + + # Lambda function trigger for PNG images + lambda_function { + lambda_function_arn = aws_lambda_function.image_analysis_function.arn + events = ["s3:ObjectCreated:Put"] + filter_prefix = "images/" + filter_suffix = ".png" + } + + depends_on = [aws_lambda_permission.s3_invoke] +} + +# Outputs +output "lambda_function_arn" { + description = "The ARN of the Lambda function" + value = aws_lambda_function.image_analysis_function.arn +} + +output "s3_image_bucket" { + description = "The S3 bucket for image uploads" + value = aws_s3_bucket.image_bucket.id +} + +output "cloudwatch_log_group" { + description = "The CloudWatch Log Group for Lambda function" + value = aws_cloudwatch_log_group.lambda_log_group.name +} + +output "aws_region" { + description = "The AWS region used for deployment" + value = var.aws_region +} \ No newline at end of file diff --git a/s3-lambda-bedrock-tf/src/app.py b/s3-lambda-bedrock-tf/src/app.py new file mode 100644 index 000000000..7bf208a08 --- /dev/null +++ b/s3-lambda-bedrock-tf/src/app.py @@ -0,0 +1,180 @@ +import json +import boto3 +import base64 +from urllib.parse import unquote_plus +import logging +import os + +# Configure logging to ensure CloudWatch visibility +logging.basicConfig( + level=logging.INFO, + format='%(levelname)s - %(message)s', + force=True +) +logger = logging.getLogger(__name__) +logger.setLevel(logging.INFO) + +# Constants +SUPPORTED_EXTENSIONS = ['jpg', 'jpeg', 'png'] +NOVA_MODEL_ID = os.environ.get('NOVA_MODEL_ID', 'amazon.nova-lite-v1:0') +AWS_REGION = os.environ.get('AWS_REGION_CUSTOM', 'us-east-1') + +def lambda_handler(event, context): + """ + Lambda handler for processing image uploads using Amazon Nova Lite + """ + try: + # Extract S3 information + record = event["Records"][0] + bucket_name = str(record["s3"]["bucket"]["name"]) + file_key = unquote_plus(str(record["s3"]["object"]["key"])) + + # Check file extension + file_extension = file_key.lower().split('.')[-1] + if file_extension not in SUPPORTED_EXTENSIONS: + print(f"SKIPPED: {file_key} - Unsupported file type: {file_extension}") + return {"statusCode": 200, "body": "File type not supported"} + + # Process the image + image_bytes = read_s3_image(bucket_name, file_key) + tags = analyze_image_with_nova(image_bytes, file_key) + applied_tags = apply_tags_to_s3_object(bucket_name, file_key, tags) + + # Success log + print(f"SUCCESS: {file_key} | Model: {NOVA_MODEL_ID} | Nova Response: {', '.join(tags)} | Tags Applied: {len(applied_tags)}") + + return { + "statusCode": 200, + "body": json.dumps({ + "processed": True, + "file": file_key, + "model": NOVA_MODEL_ID, + "tags_count": len(applied_tags) + }) + } + + except Exception as e: + file_key = "unknown" + try: + file_key = unquote_plus(str(event["Records"][0]["s3"]["object"]["key"])) + except: + pass + + print(f"FAILED: {file_key} | Model: {NOVA_MODEL_ID} | Error: {str(e)}") + + return { + "statusCode": 500, + "body": json.dumps({ + "processed": False, + "file": file_key, + "error": str(e) + }) + } + + +def determine_image_format(filename): + """Determine image format based on file extension""" + extension = filename.lower().split('.')[-1] + format_mapping = {'jpg': 'jpeg', 'jpeg': 'jpeg', 'png': 'png'} + return format_mapping.get(extension, 'jpeg') + + +def analyze_image_with_nova(image_bytes, filename): + """Use Amazon Nova Lite to analyze image and return descriptive tags""" + try: + bedrock_runtime = boto3.client("bedrock-runtime", region_name=AWS_REGION) + + # Prepare request + image_base64 = base64.b64encode(image_bytes).decode('utf-8') + image_format = determine_image_format(filename) + + nova_request = { + "messages": [ + { + "role": "user", + "content": [ + { + "image": { + "format": image_format, + "source": {"bytes": image_base64} + } + }, + { + "text": "Analyze this image and provide exactly 10 descriptive single words that best describe what you see. Return only the words separated by commas, no explanations." + } + ] + } + ], + "inferenceConfig": { + "maxTokens": 100, + "temperature": 0.1 + } + } + + # Call Nova Lite + response = bedrock_runtime.invoke_model( + modelId=NOVA_MODEL_ID, + contentType="application/json", + accept="application/json", + body=json.dumps(nova_request) + ) + + # Parse response + response_data = json.loads(response.get("body").read()) + + if ("output" in response_data and + "message" in response_data["output"] and + "content" in response_data["output"]["message"] and + response_data["output"]["message"]["content"]): + + content = response_data["output"]["message"]["content"] + if isinstance(content, list) and len(content) > 0: + analysis_text = content[0].get("text", "") + else: + analysis_text = str(content) + + # Process into clean tags + tags = [word.strip().lower() for word in analysis_text.split(",")] + tags = [tag for tag in tags if tag and len(tag) > 0 and tag.replace('-', '').replace('_', '').isalnum()] + return tags[:10] + + return get_fallback_tags() + + except Exception: + return get_fallback_tags() + + +def get_fallback_tags(): + """Return fallback tags when Nova fails""" + return ["image", "photo", "content", "visual", "media", "file", "upload", "data", "picture", "object"] + + +def read_s3_image(bucket, key): + """Read image file from S3 bucket""" + s3_client = boto3.client("s3") + s3_object = s3_client.get_object(Bucket=bucket, Key=key) + return s3_object["Body"].read() + + +def apply_tags_to_s3_object(bucket, key, tag_words): + """Apply AI-generated tags to S3 object""" + s3_client = boto3.client("s3") + + # Create S3 tag set + tag_set = [] + for i, word in enumerate(tag_words[:10]): + clean_word = ''.join(c for c in word if c.isalnum() or c in ['-', '_']).strip() + if clean_word: + tag_set.append({ + 'Key': f'ai-tag-{i+1}', + 'Value': clean_word[:256] + }) + + if tag_set: + s3_client.put_object_tagging( + Bucket=bucket, + Key=key, + Tagging={'TagSet': tag_set} + ) + + return tag_set \ No newline at end of file