import base64 import httpx from api.config import settings LLM_URL = settings.llm.groq_url LLM_API_KEY = settings.llm.groq_token LLM_MODEL = settings.llm.ocr_model LLM_TEMPERATURE = settings.llm.ocr_temperature LLM_MAX_TOKENS = settings.llm.max_tokens def _ocr_mock_response() -> str: return "J'ai mal à la tête et de la fièvre depuis 3 jours, je tousse beaucoup et j'ai du mal à respirer." def _ocr_robust_fallback_response(status_code: int, error_text: str) -> str: return f"Le service d'extraction de texte est temporairement indisponible (erreur {status_code}). Veuillez contacter votre administrateur ou réessayer plus tard." def _ocr_debug_response(status_code: int, error_text: str) -> str: return f"DEBUG: OCR extraction failed with status {status_code}. {error_text}" async def extract_text_from_image(image_bytes: bytes) -> str: # encodage en base 64 pour envoyer l'image dans le payload JSON image_b64 = base64.b64encode(image_bytes).decode("utf-8") headers = { "Authorization": f"Bearer {LLM_API_KEY}", "Content-Type": "application/json", } messages = [ { "role": "user", "content": [ { "type": "text", "text": "Extract all text from this image. Return only the extracted text, nothing else." }, { "type": "image_url", "image_url": { "url": f"data:image/jpeg;base64,{image_b64}" } } ] } ] payload = { "model": LLM_MODEL, "messages": messages, "max_tokens": LLM_MAX_TOKENS, "temperature": LLM_TEMPERATURE, # low temp for extraction (deterministic, not creative) } try: async with httpx.AsyncClient(timeout=30) as client: response = await client.post(LLM_URL, json=payload, headers=headers) except httpx.HTTPError as exc: error_text = str(exc) print("HF ERROR: HTTP exception during OCR request:", error_text) if settings.debug_mode: return _ocr_debug_response(-1, error_text) if settings.robust_mode: return _ocr_robust_fallback_response(-1, error_text) raise if response.status_code == 200: try: generated = response.json()["choices"][0]["message"]["content"] return generated.strip() except Exception as exc: error_text = str(exc) print("HF ERROR: malformed OCR response:", error_text) if settings.debug_mode: return _ocr_debug_response(response.status_code, error_text) if settings.robust_mode: return _ocr_robust_fallback_response(response.status_code, error_text) raise print("HF ERROR:", response.status_code, response.text) if settings.debug_mode: return _ocr_debug_response(response.status_code, response.text) if settings.robust_mode: if response.status_code == 402: return _ocr_mock_response() return _ocr_robust_fallback_response(response.status_code, response.text) response.raise_for_status() return ""