Spaces:
Sleeping
Sleeping
File size: 3,220 Bytes
88c4bb0 | 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 | import time
import sys
import base64
from io import BytesIO
import traceback
from PIL import Image
from .llm_client import gemini_client, groq_client
def extract_text_from_image(image: Image.Image) -> str:
"""
Extracts text, handwriting, and structural info from an image using a cascading fallback strategy.
Tier 1: Google Gemini 2.5 Flash
Tier 2: Groq Llama 3.2 11B Vision
"""
prompt = "Extract all text, handwriting, and structural information from this image perfectly as markdown. Ignore non-informational background elements or formatting artifacts. Render all mathematical formulas strictly using LaTeX."
print("LOG: [Vision Client] -> Started...")
start_time = time.time()
# Tier 1: Gemini 2.5 Flash
if gemini_client:
try:
print("Attempting Tier 1 Vision (Google Gemini 2.5 Flash)...")
response = gemini_client.models.generate_content(
model="gemini-2.5-flash",
contents=[image, prompt]
)
elapsed = time.time() - start_time
print(f"LOG: [Vision Client] -> Completed in {elapsed:.2f}s (Gemini)")
return response.text if response.text else ""
except Exception as e:
print(f"[Tier 1 Vision Error] Gemini failed: {e}", file=sys.stderr)
else:
print("[Tier 1 Vision Warning] Gemini API Key missing.", file=sys.stderr)
# Tier 2: Groq Llama Vision Fallback
if groq_client:
try:
print("Attempting Tier 2 Vision (Groq llama-3.2-11b-vision-preview)...")
# Convert PIL image to base64
buffered = BytesIO()
if image.mode != "RGB":
image = image.convert("RGB")
image.save(buffered, format="JPEG")
base64_image = base64.b64encode(buffered.getvalue()).decode('utf-8')
response = groq_client.chat.completions.create(
model="llama-3.2-11b-vision-preview",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": prompt},
{
"type": "image_url",
"image_url": {
"url": f"data:image/jpeg;base64,{base64_image}"
}
}
]
}
]
)
elapsed = time.time() - start_time
print(f"LOG: [Vision Client] -> Completed in {elapsed:.2f}s (Groq)")
return response.choices[0].message.content
except Exception as e:
print(f"[Tier 2 Vision Error] Groq failed: {e}", file=sys.stderr)
else:
print("[Tier 2 Vision Warning] Groq API Key missing.", file=sys.stderr)
# Total Failure
print("[CRITICAL Vision] All Vision endpoints failed.", file=sys.stderr)
elapsed = time.time() - start_time
print(f"LOG: [Vision Client] -> Completed in {elapsed:.2f}s (Failed)")
return "[Error: Vision extraction failed. All OCR endpoints are currently unreachable.]"
|