diff --git a/app/ai_schema.py b/app/ai_schema.py index 65621d1..1500623 100644 --- a/app/ai_schema.py +++ b/app/ai_schema.py @@ -134,26 +134,28 @@ EXTRACTION_PROMPT_TEMPLATE = """Extract product price and stock status from this **PRICE (IMPORTANT - French format):** - **FIRST**: Look for "PRIX DÉTECTÉ:" at the start of text - this is the extracted price -- French prices use COMMA for decimals: "12,99 €" means 12.99 -- Thousands separator is SPACE or DOT: "1 234,56 €" or "1.234,56 €" means 1234.56 +- **The price has already been converted to English format for you** +- French original: "3,99 €" → Already shown to you as: "3.99 €" +- Just extract the number you see (e.g., "3.99" from "PRIX DÉTECTÉ: 3.99 €") - Currency symbol is usually € at the end - Look for: "PRIX DÉTECTÉ:", price tags, "Prix:", "€", numbers near "Ajouter au panier" -- Extract as DECIMAL NUMBER (convert comma to dot): 12,99 -> 12.99 +- Extract as DECIMAL NUMBER: If you see "3.99", return 3.99 - Ignore crossed-out/barré prices (old prices) - If multiple prices, take the current/main price (not the original) -**CRITICAL - Read digits carefully:** -- PAY CLOSE ATTENTION to first digit: "1,99 €" is NOT "9,99 €" -- Double-check: Is it 1, 7, 8, or 9? These look similar -- Small prices (< 5€) are common: 0,99 €, 1,49 €, 1,99 €, 2,99 €, 3,99 €, 4,99 € -- VERIFY the price makes sense for the product type +**CRITICAL - Common mistakes to avoid:** +- "3.99 €" means 3.99 (NOT 399.00, NOT 3990.00) +- "1.99 €" means 1.99 (NOT 199.00, NOT 1990.00) +- "0.99 €" means 0.99 (NOT 99.00, NOT 990.00) +- The decimal point separates euros from cents +- Small prices (< 10€) are very common for everyday items - Examples of valid prices: - * "1,99 €" -> 1.99 (NOT 9.99) - * "0,99 €" -> 0.99 (NOT 9.99) - * "89,99 €" -> 89.99 - * "1 234,56 €" -> 1234.56 - * "PRIX DÉTECTÉ: 89,99 €" -> 89.99 + * "PRIX DÉTECTÉ: 1.99 €" -> 1.99 (NOT 199 or 1990) + * "PRIX DÉTECTÉ: 3.99 €" -> 3.99 (NOT 399 or 3990) + * "0.99 €" -> 0.99 (NOT 99) + * "89.99 €" -> 89.99 (NOT 8999) + * "1234.56 €" -> 1234.56 - If you find ANY price with € symbol, extract it with confidence >= 0.8 - If digits are unclear or blurry, reduce confidence to 0.5-0.7 - If unclear: set null and confidence < 0.5 diff --git a/app/services/browserless_service.py b/app/services/browserless_service.py index a55e98b..708a4b1 100644 --- a/app/services/browserless_service.py +++ b/app/services/browserless_service.py @@ -376,6 +376,15 @@ class BrowserlessService: try: content = await page.inner_text('body') logger.info(f"Extracted {len(content)} chars of visible text from page") + + # Normalize French prices to English format for AI (3,99 € → 3.99 €) + import re + # Replace comma with dot in price patterns: digits,XX € → digits.XX € + content = re.sub(r'(\d+),(\d{2})\s*€', r'\1.\2 €', content) + # Remove spaces in thousands: 1 234.56 → 1234.56 + content = re.sub(r'(\d+)\s(\d{3})', r'\1\2', content) + logger.debug("Normalized French price formats to English") + except Exception as e: # Fallback to HTML content if inner_text fails logger.warning(f"Failed to extract inner_text, falling back to HTML: {e}") @@ -397,8 +406,17 @@ class BrowserlessService: # Prepend extracted price to content if found if extracted_price: - content = f"PRIX DÉTECTÉ: {extracted_price}\n\n{content}" - logger.info(f"Prepended price to content: {extracted_price}") + # Convert French format to English for AI (3,99 → 3.99) + import re + normalized_price = extracted_price + # Replace comma with dot for decimal separator (French to English) + # Pattern: digits, comma, 2 digits → digits, dot, 2 digits + normalized_price = re.sub(r'(\d+),(\d{2})', r'\1.\2', normalized_price) + # Remove spaces in thousands separators if any (1 234,56 → 1234.56) + normalized_price = normalized_price.replace(' ', '') + + content = f"PRIX DÉTECTÉ: {normalized_price}\n\n{content}" + logger.info(f"Prepended normalized price to content: {normalized_price} (original: {extracted_price})") else: logger.warning("Could not extract price from DOM, relying on text/image only") else: