mirror of
https://github.com/R0m1k3/Priceflow.git
synced 2026-10-11 17:29:14 +02:00
Three critical fixes to resolve AI extraction returning null prices with 0.0 confidence:
1. **Add French price/stock keywords** (app/utils/text.py)
- Added € symbol and French price patterns (12,99 €, 1 234,56 €)
- Added French keywords: prix, coût, promotion, réduction
- Added French stock keywords: ajouter au panier, en stock, rupture, épuisé
- Previously only detected $ and English keywords
2. **Enable full-page screenshots** (app/services/browserless_service.py)
- Changed full_page=False to full_page=True
- Now captures entire page instead of viewport-only
- Prevents missing prices located below the fold
3. **Increase image resolution** (app/utils/image.py)
- Increased MAX_IMAGE_SIZE from 1024px to 2048px
- Preserves fine details in price text for better AI recognition
- Improves readability on dense product pages
These changes fix the issue where AI models returned:
{"price": null, "price_confidence": 0.0, "in_stock": null, "in_stock_confidence": 0.0}
Tested with Amazon.fr product monitoring.
47 lines
1.4 KiB
Python
47 lines
1.4 KiB
Python
import asyncio
|
|
import base64
|
|
import io
|
|
import logging
|
|
|
|
from PIL import Image
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# Image processing constants
|
|
# Increased from 1024 to 2048 to preserve more detail for AI analysis
|
|
MAX_IMAGE_SIZE = 2048
|
|
JPEG_QUALITY = 85
|
|
|
|
|
|
def _process_image(image_path: str) -> str:
|
|
"""
|
|
Synchronous image processing function to be run in an executor.
|
|
"""
|
|
try:
|
|
with Image.open(image_path) as img:
|
|
# Resize if too large (e.g., max dimension 1024)
|
|
if max(img.size) > MAX_IMAGE_SIZE:
|
|
img.thumbnail((MAX_IMAGE_SIZE, MAX_IMAGE_SIZE))
|
|
logger.info(f"Resized image to {img.size}")
|
|
|
|
# Convert to RGB if necessary (e.g. for PNGs with alpha)
|
|
if img.mode in ("RGBA", "P"):
|
|
img_to_process = img.convert("RGB")
|
|
else:
|
|
img_to_process = img
|
|
|
|
buffered = io.BytesIO()
|
|
img_to_process.save(buffered, format="JPEG", quality=JPEG_QUALITY)
|
|
return base64.b64encode(buffered.getvalue()).decode("utf-8")
|
|
except Exception as e:
|
|
logger.error(f"Error encoding image: {e}")
|
|
raise
|
|
|
|
|
|
async def encode_image(image_path: str) -> str:
|
|
"""
|
|
Asynchronously encode image by running blocking code in a thread.
|
|
"""
|
|
loop = asyncio.get_running_loop()
|
|
return await loop.run_in_executor(None, _process_image, image_path)
|