File size: 3,288 Bytes
7ddb64a
 
 
 
9b0ce22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7ddb64a
 
 
 
 
 
9b0ce22
7ddb64a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9b0ce22
7ddb64a
9b0ce22
 
7ddb64a
 
9b0ce22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7ddb64a
9b0ce22
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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 ""