Spaces:
Sleeping
Sleeping
Update main.py
Browse files
main.py
CHANGED
|
@@ -10,7 +10,7 @@ from dotenv import load_dotenv
|
|
| 10 |
from flask import Flask, request, make_response
|
| 11 |
from typing import Dict, List, Union
|
| 12 |
import json
|
| 13 |
-
|
| 14 |
# Initialize Flask App
|
| 15 |
app = Flask(__name__)
|
| 16 |
|
|
@@ -120,7 +120,6 @@ def handle_media_message(messenger, data, message_type, mobile):
|
|
| 120 |
# Download media content based on type
|
| 121 |
if message_type == "image":
|
| 122 |
media_url = messenger.get_image_url(data)
|
| 123 |
-
print(media_url)
|
| 124 |
elif message_type == "document":
|
| 125 |
media_url = messenger.get_document_url(data)
|
| 126 |
elif message_type == "audio":
|
|
@@ -139,9 +138,28 @@ def handle_media_message(messenger, data, message_type, mobile):
|
|
| 139 |
messenger.send_message("Sorry, I couldn't process your media.", mobile)
|
| 140 |
return None
|
| 141 |
|
| 142 |
-
#
|
| 143 |
-
|
| 144 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 145 |
|
| 146 |
except Exception as e:
|
| 147 |
logger.error(f"Error handling media message: {str(e)}")
|
|
@@ -186,8 +204,9 @@ carts: Dict[str, List[Dict]] = {}
|
|
| 186 |
class ShoppingAssistant:
|
| 187 |
def __init__(self):
|
| 188 |
self.product_data = product_data
|
|
|
|
| 189 |
|
| 190 |
-
def analyze_content(self, content: Union[str, bytes], content_type: str, budget: float = None) -> dict:
|
| 191 |
try:
|
| 192 |
if content_type == "text":
|
| 193 |
response = model.generate_content(
|
|
@@ -195,14 +214,10 @@ class ShoppingAssistant:
|
|
| 195 |
specific products needed, and any budget constraints. Request: {content}"""
|
| 196 |
)
|
| 197 |
else: # For images, documents, etc.
|
| 198 |
-
response = vision_model.generate_content(
|
| 199 |
-
[
|
| 200 |
-
"Analyze this content and extract shopping-related information, products needed, and any specifications.",
|
| 201 |
-
content
|
| 202 |
-
]
|
| 203 |
-
)
|
| 204 |
|
| 205 |
analysis = response.text
|
|
|
|
| 206 |
|
| 207 |
# Second pass to find specific products
|
| 208 |
products_prompt = f"""Based on this analysis: {analysis}
|
|
@@ -211,7 +226,15 @@ class ShoppingAssistant:
|
|
| 211 |
Return only product names and prices that match the request."""
|
| 212 |
|
| 213 |
products_response = model.generate_content(products_prompt)
|
| 214 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 215 |
|
| 216 |
except Exception as e:
|
| 217 |
logger.error(f"Error in content analysis: {str(e)}")
|
|
@@ -266,10 +289,10 @@ def hook():
|
|
| 266 |
|
| 267 |
if message_type == "text":
|
| 268 |
message = messenger.get_message(data)
|
| 269 |
-
result = shopping_assistant.analyze_content(message, "text")
|
| 270 |
|
| 271 |
if "error" in result:
|
| 272 |
-
messenger.send_message(
|
| 273 |
return "OK", 200
|
| 274 |
|
| 275 |
if not result["products"]:
|
|
@@ -283,7 +306,6 @@ def hook():
|
|
| 283 |
products_text += f"\nTotal: ${result['total']:.2f}"
|
| 284 |
|
| 285 |
# Send interactive message with buttons
|
| 286 |
-
# Create and send reply buttons
|
| 287 |
buttons = [
|
| 288 |
{"id": "add_to_cart", "title": "Add to Cart"},
|
| 289 |
{"id": "cancel", "title": "Cancel"}
|
|
@@ -295,29 +317,33 @@ def hook():
|
|
| 295 |
)
|
| 296 |
|
| 297 |
elif message_type == "interactive":
|
| 298 |
-
handle_interactive_message(messenger, data, mobile, carts)
|
| 299 |
|
| 300 |
elif message_type in ["image", "document", "audio"]:
|
| 301 |
media_content = handle_media_message(messenger, data, message_type, mobile)
|
| 302 |
if media_content:
|
| 303 |
-
result = shopping_assistant.analyze_content(media_content, message_type)
|
| 304 |
-
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
|
| 308 |
-
|
| 309 |
-
|
| 310 |
-
|
| 311 |
-
|
| 312 |
-
|
| 313 |
-
|
| 314 |
-
|
| 315 |
-
|
| 316 |
-
|
| 317 |
-
|
| 318 |
-
|
| 319 |
-
|
| 320 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 321 |
|
| 322 |
return "OK", 200
|
| 323 |
|
|
|
|
| 10 |
from flask import Flask, request, make_response
|
| 11 |
from typing import Dict, List, Union
|
| 12 |
import json
|
| 13 |
+
from PIL import Image
|
| 14 |
# Initialize Flask App
|
| 15 |
app = Flask(__name__)
|
| 16 |
|
|
|
|
| 120 |
# Download media content based on type
|
| 121 |
if message_type == "image":
|
| 122 |
media_url = messenger.get_image_url(data)
|
|
|
|
| 123 |
elif message_type == "document":
|
| 124 |
media_url = messenger.get_document_url(data)
|
| 125 |
elif message_type == "audio":
|
|
|
|
| 138 |
messenger.send_message("Sorry, I couldn't process your media.", mobile)
|
| 139 |
return None
|
| 140 |
|
| 141 |
+
# Ensure image is in a compatible format
|
| 142 |
+
try:
|
| 143 |
+
img = Image.open(io.BytesIO(response.content))
|
| 144 |
+
|
| 145 |
+
# Convert to RGB if needed
|
| 146 |
+
if img.mode != 'RGB':
|
| 147 |
+
img = img.convert('RGB')
|
| 148 |
+
|
| 149 |
+
# Resize large images to reduce processing time
|
| 150 |
+
max_size = (1024, 1024)
|
| 151 |
+
img.thumbnail(max_size)
|
| 152 |
+
|
| 153 |
+
# Save to a BytesIO object
|
| 154 |
+
img_byte_arr = io.BytesIO()
|
| 155 |
+
img.save(img_byte_arr, format='JPEG')
|
| 156 |
+
img_byte_arr = img_byte_arr.getvalue()
|
| 157 |
+
|
| 158 |
+
return img_byte_arr
|
| 159 |
+
except Exception as img_error:
|
| 160 |
+
logger.error(f"Image processing error: {img_error}")
|
| 161 |
+
messenger.send_message("Sorry, I had trouble processing the image.", mobile)
|
| 162 |
+
return None
|
| 163 |
|
| 164 |
except Exception as e:
|
| 165 |
logger.error(f"Error handling media message: {str(e)}")
|
|
|
|
| 204 |
class ShoppingAssistant:
|
| 205 |
def __init__(self):
|
| 206 |
self.product_data = product_data
|
| 207 |
+
self.last_analyzed_products = {}
|
| 208 |
|
| 209 |
+
def analyze_content(self, content: Union[str, bytes], content_type: str, mobile: str, budget: float = None) -> dict:
|
| 210 |
try:
|
| 211 |
if content_type == "text":
|
| 212 |
response = model.generate_content(
|
|
|
|
| 214 |
specific products needed, and any budget constraints. Request: {content}"""
|
| 215 |
)
|
| 216 |
else: # For images, documents, etc.
|
| 217 |
+
response = vision_model.generate_content(content)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 218 |
|
| 219 |
analysis = response.text
|
| 220 |
+
logger.info(f"Image analysis result: {analysis}")
|
| 221 |
|
| 222 |
# Second pass to find specific products
|
| 223 |
products_prompt = f"""Based on this analysis: {analysis}
|
|
|
|
| 226 |
Return only product names and prices that match the request."""
|
| 227 |
|
| 228 |
products_response = model.generate_content(products_prompt)
|
| 229 |
+
logger.info(f"Products response: {products_response.text}")
|
| 230 |
+
|
| 231 |
+
result = self.format_recommendations(products_response.text, budget)
|
| 232 |
+
|
| 233 |
+
# Store last analyzed products for this mobile number
|
| 234 |
+
if mobile:
|
| 235 |
+
self.last_analyzed_products[mobile] = result["products"]
|
| 236 |
+
|
| 237 |
+
return result
|
| 238 |
|
| 239 |
except Exception as e:
|
| 240 |
logger.error(f"Error in content analysis: {str(e)}")
|
|
|
|
| 289 |
|
| 290 |
if message_type == "text":
|
| 291 |
message = messenger.get_message(data)
|
| 292 |
+
result = shopping_assistant.analyze_content(message, "text", mobile)
|
| 293 |
|
| 294 |
if "error" in result:
|
| 295 |
+
messenger.send_message("Sorry, I couldn't process your request.", mobile)
|
| 296 |
return "OK", 200
|
| 297 |
|
| 298 |
if not result["products"]:
|
|
|
|
| 306 |
products_text += f"\nTotal: ${result['total']:.2f}"
|
| 307 |
|
| 308 |
# Send interactive message with buttons
|
|
|
|
| 309 |
buttons = [
|
| 310 |
{"id": "add_to_cart", "title": "Add to Cart"},
|
| 311 |
{"id": "cancel", "title": "Cancel"}
|
|
|
|
| 317 |
)
|
| 318 |
|
| 319 |
elif message_type == "interactive":
|
| 320 |
+
handle_interactive_message(messenger, data, mobile, carts, shopping_assistant)
|
| 321 |
|
| 322 |
elif message_type in ["image", "document", "audio"]:
|
| 323 |
media_content = handle_media_message(messenger, data, message_type, mobile)
|
| 324 |
if media_content:
|
| 325 |
+
result = shopping_assistant.analyze_content(media_content, message_type, mobile)
|
| 326 |
+
|
| 327 |
+
# Check if products were found
|
| 328 |
+
if result.get("products"):
|
| 329 |
+
# Format product message
|
| 330 |
+
products_text = "Here are the suggested products:\n\n"
|
| 331 |
+
for product in result["products"]:
|
| 332 |
+
products_text += f"- {product['product']}: ${product['price']}\n"
|
| 333 |
+
products_text += f"\nTotal: ${result['total']:.2f}"
|
| 334 |
+
|
| 335 |
+
# Create and send reply buttons
|
| 336 |
+
buttons = [
|
| 337 |
+
{"id": "add_to_cart", "title": "Add to Cart"},
|
| 338 |
+
{"id": "cancel", "title": "Cancel"}
|
| 339 |
+
]
|
| 340 |
+
button_message = create_reply_button_message(products_text, buttons)
|
| 341 |
+
messenger.send_reply_button(
|
| 342 |
+
recipient_id=mobile,
|
| 343 |
+
button=button_message
|
| 344 |
+
)
|
| 345 |
+
else:
|
| 346 |
+
messenger.send_message("I couldn't find any matching products in the image.", mobile)
|
| 347 |
|
| 348 |
return "OK", 200
|
| 349 |
|