mirror of
https://github.com/awslabs/amazon-bedrock-agentcore-samples.git
synced 2025-09-08 20:50:46 +00:00
102 lines
4.3 KiB
Python
102 lines
4.3 KiB
Python
|
# Plant detection Lambda code - uses Nova Premier to analyze plant images
|
||
|
|
||
|
import json
|
||
|
import boto3
|
||
|
import base64
|
||
|
|
||
|
def lambda_handler(event, context):
|
||
|
try:
|
||
|
print(f"Received event keys: {list(event.keys())}")
|
||
|
|
||
|
# Extract inputs
|
||
|
image_path = event.get('image_path')
|
||
|
image_data = event.get('image_data')
|
||
|
|
||
|
print(f"image_path present: {bool(image_path)}")
|
||
|
print(f"image_data present: {bool(image_data)}")
|
||
|
|
||
|
if not image_path and not image_data:
|
||
|
return {
|
||
|
'statusCode': 400,
|
||
|
'body': json.dumps({'error': 'Either image_path or image_data required'})
|
||
|
}
|
||
|
|
||
|
# Process image input - FIXED LOGIC
|
||
|
image_bytes = None
|
||
|
|
||
|
if image_data:
|
||
|
# Handle base64 image data
|
||
|
print("Processing image_data...")
|
||
|
try:
|
||
|
image_bytes = base64.b64decode(image_data)
|
||
|
print(f"✅ Decoded base64 image: {len(image_bytes)} bytes")
|
||
|
except Exception as e:
|
||
|
return {'statusCode': 400, 'body': json.dumps({'error': f'Invalid base64: {e}'})}
|
||
|
|
||
|
elif image_path:
|
||
|
# Handle image path (S3 or URL only)
|
||
|
print(f"Processing image_path: {image_path}")
|
||
|
if image_path.startswith('s3://'):
|
||
|
try:
|
||
|
s3_client = boto3.client('s3')
|
||
|
bucket = image_path.split('/')[2]
|
||
|
key = '/'.join(image_path.split('/')[3:])
|
||
|
response = s3_client.get_object(Bucket=bucket, Key=key)
|
||
|
image_bytes = response['Body'].read()
|
||
|
print(f"✅ Loaded from S3: {len(image_bytes)} bytes")
|
||
|
except Exception as e:
|
||
|
return {'statusCode': 500, 'body': json.dumps({'error': f'S3 error: {e}'})}
|
||
|
else:
|
||
|
return {'statusCode': 404, 'body': json.dumps({'error': f'Only S3 paths supported: {image_path}'})}
|
||
|
|
||
|
if not image_bytes:
|
||
|
return {'statusCode': 400, 'body': json.dumps({'error': 'No image data processed'})}
|
||
|
|
||
|
# Detect format - CORRECTED
|
||
|
if image_bytes.startswith(b'\xff\xd8\xff'):
|
||
|
image_format = 'jpeg'
|
||
|
elif image_bytes.startswith(b'\x89PNG\r\n\x1a\n'):
|
||
|
image_format = 'png'
|
||
|
else:
|
||
|
image_format = 'jpeg' # Default
|
||
|
|
||
|
|
||
|
print(f"✅ Detected format: {image_format}")
|
||
|
|
||
|
# Call Nova
|
||
|
bedrock_client = boto3.client("bedrock-runtime", region_name="us-east-1")
|
||
|
|
||
|
response = bedrock_client.converse(
|
||
|
modelId="us.amazon.nova-premier-v1:0",
|
||
|
messages=[{
|
||
|
"role": "user",
|
||
|
"content": [
|
||
|
{"image": {"format": image_format, "source": {"bytes": image_bytes}}},
|
||
|
{"text": "Analyze this plant image and provide ONLY valid JSON format: {'plant_type': 'name', 'health_analysis': 'detailed analysis'}. Use specific plant names you inferred from the data, such as: sweet_potato_leaf, tomato, bean, lettuce, pepper, cucumber, spinach, okra, sweet potato, carrot, onion, garlic, herbs. For health_analysis, describe in detail: leaf color (green, yellow, brown, purple), spots (black spots, brown spots, white spots), wilting, malnutrition signs, holes or other symptoms of pest damage, disease symptoms, nutrient deficiency, overall plant condition."}
|
||
|
]
|
||
|
}],
|
||
|
inferenceConfig={"temperature": 0.1, "maxTokens": 300}
|
||
|
)
|
||
|
|
||
|
output = response['output']['message']['content'][0]['text']
|
||
|
|
||
|
try:
|
||
|
json_start = output.find('{')
|
||
|
json_end = output.rfind('}') + 1
|
||
|
json_part = output[json_start:json_end]
|
||
|
parsed = json.loads(json_part)
|
||
|
except:
|
||
|
parsed = {"plant_type": "unknown", "health_analysis": "Parse error"}
|
||
|
|
||
|
return {
|
||
|
'statusCode': 200,
|
||
|
'body': json.dumps({
|
||
|
"plant_name": parsed.get('plant_type', 'unknown'),
|
||
|
"health_issues": parsed.get('health_analysis', 'No analysis')
|
||
|
})
|
||
|
}
|
||
|
|
||
|
except Exception as e:
|
||
|
print(f"Lambda error: {str(e)}")
|
||
|
return {'statusCode': 500, 'body': json.dumps({'error': str(e)})}
|