Comfoa commited on
Commit
03edaaf
·
1 Parent(s): ad6b9b4

fix: remove failing Groq Vision API, use only free OCR.space API for scanned document OCR

Browse files
Files changed (1) hide show
  1. backend/parsers/llm_summarizer.py +4 -55
backend/parsers/llm_summarizer.py CHANGED
@@ -311,61 +311,10 @@ class LLMSummarizer:
311
  return await self._summarize_with_text(minutes)
312
  raise RuntimeError("No image data and no text fallback.")
313
 
314
- # Try free Groq Vision API (Llama 3.2 11B Vision) to read text from images.
315
- # No JSON mode needed — just raw text extraction. Then text model summarizes.
316
- import base64
317
- print("[OCR] Using Groq Vision API to read text from images...")
318
- vision_text = ""
319
- try:
320
- max_pages = min(len(image_bytes_list), 3)
321
- content = [{"type": "text", "text": "Extract ALL readable text from these scanned city council meeting pages. Transcribe everything exactly as you see it. Preserve the layout."}]
322
- for i in range(max_pages):
323
- img_b64 = base64.b64encode(image_bytes_list[i]).decode("utf-8")
324
- mime = "image/png" if image_bytes_list[i][:4] == b'\x89PNG' else "image/jpeg"
325
- content.append({"type": "image_url", "image_url": {"url": f"data:{mime};base64,{img_b64}"}})
326
- vr = self.deepseek_client.chat.completions.create(
327
- model="llama-3.2-11b-vision-preview",
328
- messages=[{"role": "user", "content": content}],
329
- temperature=0.0, max_tokens=4096,
330
- )
331
- vision_text = vr.choices[0].message.content or ""
332
- print(f"[VISION] Extracted {len(vision_text)} chars from {max_pages} pages")
333
- print(f"[VISION] First 200 chars: {vision_text[:200]}")
334
- except Exception as e:
335
- print(f"[VISION] Failed: {e}")
336
-
337
- if vision_text and len(vision_text.strip()) > 50:
338
- minutes.raw_text = vision_text.strip()
339
- user_content = (
340
- f"Please summarize the following city council meeting minutes "
341
- f"for {minutes.city}, {minutes.state} on "
342
- f"{minutes.meeting_date.strftime('%B %d, %Y')}.\n\n"
343
- f"Meeting Type: {minutes.meeting_type}\n"
344
- f"Title: {minutes.title}\n\n"
345
- f"The following text was extracted from scanned document images by an AI vision model:\n\n"
346
- f"{vision_text.strip()[:self.MAX_OCR_TEXT_CHARS]}\n\n"
347
- f"Return ONLY valid JSON matching the specified structure. "
348
- f"Do not include any text outside the JSON object."
349
- )
350
- response = self.deepseek_client.chat.completions.create(
351
- model=self.text_model,
352
- messages=[{"role": "system", "content": MINUTES_SYSTEM_PROMPT}, {"role": "user", "content": user_content}],
353
- temperature=0.0, max_tokens=4096, response_format={"type": "json_object"},
354
- )
355
- result = json.loads(response.choices[0].message.content)
356
- return SummaryResponse(
357
- minutes_id=minutes.id, meeting_date=minutes.meeting_date, meeting_type=minutes.meeting_type,
358
- big_picture=result.get("big_picture", ""),
359
- summary=result.get("summary", "No summary available."),
360
- key_decisions=[d if isinstance(d, dict) else {"description": d} for d in result.get("key_decisions", [])],
361
- budget_items=[d if isinstance(d, dict) else {"description": d} for d in result.get("budget_items", [])],
362
- public_comment_opportunities=[d if isinstance(d, dict) else {"description": d} for d in result.get("public_comment_opportunities", [])],
363
- items=[d if isinstance(d, dict) else {"description": d} for d in result.get("items", [])],
364
- what_you_can_do=[d if isinstance(d, dict) else {"description": d} for d in result.get("what_you_can_do", [])],
365
- )
366
-
367
- # Fallback: OCR.space (synchronous API call)
368
- print("[OCR] Vision failed, trying free OCR.space API")
369
  ocr_parts = []
370
  for i, img_bytes in enumerate(image_bytes_list[:5]):
371
  page_text = self._ocr_with_ocrspace(img_bytes)
 
311
  return await self._summarize_with_text(minutes)
312
  raise RuntimeError("No image data and no text fallback.")
313
 
314
+ # Use free OCR.space API to extract text from scanned images.
315
+ # Works on Vercel Lambda with no local binaries needed.
316
+ # Rate limit: 25k requests/month free tier, no API key required.
317
+ print("[OCR] Extracting text via free OCR.space API...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
318
  ocr_parts = []
319
  for i, img_bytes in enumerate(image_bytes_list[:5]):
320
  page_text = self._ocr_with_ocrspace(img_bytes)