hoangthiencm commited on
Commit
d45755e
·
verified ·
1 Parent(s): f79fb54

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +11 -13
app.py CHANGED
@@ -1,6 +1,6 @@
1
  """
2
  Backend API cho HT_MATH_WEB - Chạy trên Hugging Face Spaces (Docker Version)
3
- Phiên bản: 9.8 (Revert to Strict Prompt + Full Features)
4
  Tác giả: Hoàng Tấn Thiên
5
  """
6
 
@@ -27,7 +27,6 @@ import google.generativeai as genai
27
  # --- PANDOC IMPORT ---
28
  try:
29
  import pypandoc
30
- # print(f"INFO: Pandoc version detected: {pypandoc.get_pandoc_version()}")
31
  except ImportError:
32
  print("CRITICAL WARNING: pypandoc module not found.")
33
  except OSError:
@@ -58,7 +57,7 @@ if SUPABASE_AVAILABLE and SUPABASE_URL and SUPABASE_KEY:
58
  except Exception as e:
59
  print(f"Warning: Không thể kết nối Supabase: {e}")
60
 
61
- app = FastAPI(title="HT_MATH_WEB API", version="9.8")
62
 
63
  app.add_middleware(
64
  CORSMiddleware,
@@ -105,7 +104,7 @@ def check_rate_limit(request: Request):
105
  pass
106
  ip_rate_limits[client_ip] = now
107
 
108
- # ===== PROMPTS (KHÔI PHỤC BẢN CHUẨN MỰC) =====
109
  DIRECT_GEMINI_PROMPT_TEXT_ONLY = r"""**TRÍCH XUẤT VĂN BẢN THUẦN TÚY**
110
  ⚠️ YÊU CẦU BẮT BUỘC:
111
  - PHẢI trích xuất TOÀN BỘ nội dung xuất hiện trong ảnh/PDF
@@ -199,7 +198,7 @@ def stitch_text(text_a: str, text_b: str, min_overlap_chars: int = 20) -> str:
199
  for i in range(scan_window, 0, -1):
200
  tail_a = "\n".join(a_lines[-i:]).strip()
201
  head_b = "\n".join(b_lines[:i]).strip()
202
- # So sánh lỏng hơn một chút để tránh lỗi do khoảng trắng thừa
203
  if len(tail_a) >= min_overlap_chars and tail_a.replace(" ","") == head_b.replace(" ",""):
204
  best_overlap_idx = i
205
  break
@@ -207,7 +206,6 @@ def stitch_text(text_a: str, text_b: str, min_overlap_chars: int = 20) -> str:
207
  if best_overlap_idx > 0:
208
  return text_a + "\n" + "\n".join(b_lines[best_overlap_idx:])
209
  else:
210
- # Nếu không tìm thấy điểm nối, nối tiếp luôn bằng 2 dòng trống để an toàn
211
  return text_a + "\n\n" + text_b
212
 
213
  def clean_latex_formulas(text: str) -> str:
@@ -224,7 +222,7 @@ def verify_password(password: str, hashed: str) -> bool:
224
  @app.get("/")
225
  @app.get("/health")
226
  async def root():
227
- return {"status": "ok", "version": "9.8"}
228
 
229
  @app.get("/api/models")
230
  async def get_models():
@@ -315,7 +313,7 @@ async def upload_image(file: UploadFile = File(...)):
315
  async def process_image_with_gemini(image: Image.Image, model_id: str, prompt: str, manager: ApiKeyManager, max_retries: int = 3) -> str:
316
  """Gửi ảnh lên Gemini với settings tắt bộ lọc an toàn để tránh mất nội dung"""
317
 
318
- # Cấu hình tắt bộ lọc an toàn (QUAN TRỌNG ĐỂ KHÔNG BỊ MẤT CHỮ)
319
  safety_settings = [
320
  {"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_NONE"},
321
  {"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_NONE"},
@@ -333,7 +331,6 @@ async def process_image_with_gemini(image: Image.Image, model_id: str, prompt: s
333
  genai.configure(api_key=api_key)
334
  generation_config = {"temperature": 0.0, "top_p": 1.0, "max_output_tokens": 8192}
335
 
336
- # Khởi tạo model kèm safety_settings
337
  model = genai.GenerativeModel(
338
  model_id,
339
  generation_config=generation_config,
@@ -358,9 +355,11 @@ async def process_image_with_gemini(image: Image.Image, model_id: str, prompt: s
358
  return ""
359
 
360
  async def process_large_image(image: Image.Image, model: str, prompt: str, semaphore: asyncio.Semaphore, manager: ApiKeyManager) -> str:
361
- # Chunk height lớn (4096) để đọc 1 lần hết trang A4 tiêu chuẩn (200dpi)
362
- CHUNK_HEIGHT = 4096
363
- OVERLAP_HEIGHT = 256
 
 
364
 
365
  width, height = image.size
366
 
@@ -378,7 +377,6 @@ async def process_large_image(image: Image.Image, model: str, prompt: str, semap
378
  if bottom == height: break
379
  y += (CHUNK_HEIGHT - OVERLAP_HEIGHT)
380
 
381
- # Nếu phải cắt, xử lý từng phần rồi nối lại
382
  async def process_chunk(chunk_img, index):
383
  async with semaphore:
384
  text = await process_image_with_gemini(chunk_img, model, prompt, manager)
 
1
  """
2
  Backend API cho HT_MATH_WEB - Chạy trên Hugging Face Spaces (Docker Version)
3
+ Phiên bản: 9.9 (Forced Split Mode - Fix Missing Content)
4
  Tác giả: Hoàng Tấn Thiên
5
  """
6
 
 
27
  # --- PANDOC IMPORT ---
28
  try:
29
  import pypandoc
 
30
  except ImportError:
31
  print("CRITICAL WARNING: pypandoc module not found.")
32
  except OSError:
 
57
  except Exception as e:
58
  print(f"Warning: Không thể kết nối Supabase: {e}")
59
 
60
+ app = FastAPI(title="HT_MATH_WEB API", version="9.9")
61
 
62
  app.add_middleware(
63
  CORSMiddleware,
 
104
  pass
105
  ip_rate_limits[client_ip] = now
106
 
107
+ # ===== PROMPTS (CHUẨN MỰC) =====
108
  DIRECT_GEMINI_PROMPT_TEXT_ONLY = r"""**TRÍCH XUẤT VĂN BẢN THUẦN TÚY**
109
  ⚠️ YÊU CẦU BẮT BUỘC:
110
  - PHẢI trích xuất TOÀN BỘ nội dung xuất hiện trong ảnh/PDF
 
198
  for i in range(scan_window, 0, -1):
199
  tail_a = "\n".join(a_lines[-i:]).strip()
200
  head_b = "\n".join(b_lines[:i]).strip()
201
+ # So sánh lỏng hơn để tìm điểm trùng
202
  if len(tail_a) >= min_overlap_chars and tail_a.replace(" ","") == head_b.replace(" ",""):
203
  best_overlap_idx = i
204
  break
 
206
  if best_overlap_idx > 0:
207
  return text_a + "\n" + "\n".join(b_lines[best_overlap_idx:])
208
  else:
 
209
  return text_a + "\n\n" + text_b
210
 
211
  def clean_latex_formulas(text: str) -> str:
 
222
  @app.get("/")
223
  @app.get("/health")
224
  async def root():
225
+ return {"status": "ok", "version": "9.9"}
226
 
227
  @app.get("/api/models")
228
  async def get_models():
 
313
  async def process_image_with_gemini(image: Image.Image, model_id: str, prompt: str, manager: ApiKeyManager, max_retries: int = 3) -> str:
314
  """Gửi ảnh lên Gemini với settings tắt bộ lọc an toàn để tránh mất nội dung"""
315
 
316
+ # Cấu hình tắt bộ lọc an toàn
317
  safety_settings = [
318
  {"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_NONE"},
319
  {"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_NONE"},
 
331
  genai.configure(api_key=api_key)
332
  generation_config = {"temperature": 0.0, "top_p": 1.0, "max_output_tokens": 8192}
333
 
 
334
  model = genai.GenerativeModel(
335
  model_id,
336
  generation_config=generation_config,
 
355
  return ""
356
 
357
  async def process_large_image(image: Image.Image, model: str, prompt: str, semaphore: asyncio.Semaphore, manager: ApiKeyManager) -> str:
358
+ # THAY ĐỔI QUAN TRỌNG: Giảm CHUNK_HEIGHT xuống 1500 (Khoảng 2/3 trang A4 @ 200dpi)
359
+ # Điều này ÉP BUỘC code phải cắt trang A4 thành ít nhất 2 phần
360
+ # Giúp AI không bị quá tải và bỏ sót nửa trang sau.
361
+ CHUNK_HEIGHT = 1500
362
+ OVERLAP_HEIGHT = 300
363
 
364
  width, height = image.size
365
 
 
377
  if bottom == height: break
378
  y += (CHUNK_HEIGHT - OVERLAP_HEIGHT)
379
 
 
380
  async def process_chunk(chunk_img, index):
381
  async with semaphore:
382
  text = await process_image_with_gemini(chunk_img, model, prompt, manager)