Update app.py
Browse files
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.
|
| 4 |
Tác giả: Hoàng Tấn Thiên
|
| 5 |
"""
|
| 6 |
|
|
@@ -68,7 +68,7 @@ if SUPABASE_AVAILABLE and SUPABASE_URL and SUPABASE_KEY:
|
|
| 68 |
except Exception as e:
|
| 69 |
print(f"Warning: Không thể kết nối Supabase: {e}")
|
| 70 |
|
| 71 |
-
app = FastAPI(title="HT_MATH_WEB API", version="9.
|
| 72 |
|
| 73 |
app.add_middleware(
|
| 74 |
CORSMiddleware,
|
|
@@ -122,30 +122,34 @@ def check_rate_limit(request: Request):
|
|
| 122 |
print(f"[RateLimit] IP {client_ip} requesting too fast.")
|
| 123 |
ip_rate_limits[client_ip] = now
|
| 124 |
|
| 125 |
-
# ===== SAFE PROMPTS (
|
| 126 |
-
# Đã đổi
|
|
|
|
| 127 |
|
| 128 |
-
DIRECT_GEMINI_PROMPT_TEXT_ONLY = r"""
|
| 129 |
-
|
| 130 |
-
Yêu cầu:
|
| 131 |
-
- Trích xuất nội dung văn bản để lưu trữ dữ liệu.
|
| 132 |
-
- Giữ nguyên các thông số, dữ liệu toán học.
|
| 133 |
-
- Định dạng Markdown rõ ràng.
|
| 134 |
-
- KHÔNG thêm lời bình luận.
|
| 135 |
-
"""
|
| 136 |
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
|
|
|
|
|
|
|
|
|
| 140 |
|
| 141 |
-
|
| 142 |
-
1. Nếu gặp nội dung giống sách giáo khoa hoặc tài liệu có bản quyền, hãy VIẾT LẠI (paraphrase) lời dẫn nhưng GIỮ NGUYÊN công thức toán học và số liệu.
|
| 143 |
-
2. Trình bày công thức toán trong dấu `$`. Ví dụ: $x^2 + 2x = 0$.
|
| 144 |
-
3. Đảm bảo cấu trúc bài tập rõ ràng (Câu 1, Câu 2...).
|
| 145 |
-
4. Nếu hình ảnh mờ hoặc bị cắt, hãy cố gắng phục hồi dựa trên ngữ cảnh toán học.
|
| 146 |
|
| 147 |
-
|
| 148 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 149 |
|
| 150 |
# ===== STITCHING ALGORITHM =====
|
| 151 |
def stitch_text(text_a: str, text_b: str, min_overlap_chars: int = 20) -> str:
|
|
@@ -243,7 +247,7 @@ async def root():
|
|
| 243 |
|
| 244 |
return {
|
| 245 |
"status": "ok",
|
| 246 |
-
"service": "HT_MATH_WEB API v9.
|
| 247 |
"keys_loaded": key_manager.get_key_count(),
|
| 248 |
"pandoc": pandoc_status,
|
| 249 |
"tesseract": tesseract_status
|
|
@@ -314,7 +318,8 @@ async def process_image_with_gemini(image: Image.Image, model_id: str, prompt: s
|
|
| 314 |
if not api_key: raise ValueError("No API Key")
|
| 315 |
genai.configure(api_key=api_key)
|
| 316 |
|
| 317 |
-
|
|
|
|
| 318 |
model = genai.GenerativeModel(model_id, generation_config=generation_config)
|
| 319 |
|
| 320 |
# Gọi API
|
|
@@ -337,7 +342,6 @@ async def process_image_with_gemini(image: Image.Image, model_id: str, prompt: s
|
|
| 337 |
continue
|
| 338 |
if attempt == max_retries - 1:
|
| 339 |
print(f"Error Gemini: {e}")
|
| 340 |
-
# Nếu lỗi mạng/quota quá nhiều, cũng fallback luôn cho chắc
|
| 341 |
return await fallback_ocr_tesseract(image)
|
| 342 |
|
| 343 |
return ""
|
|
|
|
| 1 |
"""
|
| 2 |
Backend API cho HT_MATH_WEB - Chạy trên Hugging Face Spaces (Docker Version)
|
| 3 |
+
Phiên bản: 9.1 (Strict OCR - Anti-Hallucination)
|
| 4 |
Tác giả: Hoàng Tấn Thiên
|
| 5 |
"""
|
| 6 |
|
|
|
|
| 68 |
except Exception as e:
|
| 69 |
print(f"Warning: Không thể kết nối Supabase: {e}")
|
| 70 |
|
| 71 |
+
app = FastAPI(title="HT_MATH_WEB API", version="9.1")
|
| 72 |
|
| 73 |
app.add_middleware(
|
| 74 |
CORSMiddleware,
|
|
|
|
| 122 |
print(f"[RateLimit] IP {client_ip} requesting too fast.")
|
| 123 |
ip_rate_limits[client_ip] = now
|
| 124 |
|
| 125 |
+
# ===== SAFE PROMPTS (STRICT OCR - NO CHATTER) =====
|
| 126 |
+
# Đã thay đổi toàn bộ Prompt theo hướng "Máy OCR lạnh lùng"
|
| 127 |
+
# Loại bỏ hoàn toàn vai trò "Trợ lý ảo" để tránh nói nhảm.
|
| 128 |
|
| 129 |
+
DIRECT_GEMINI_PROMPT_TEXT_ONLY = r"""Đóng vai một CÔNG CỤ OCR CHUYÊN DỤNG cho văn bản hành chính Việt Nam.
|
| 130 |
+
NHIỆM VỤ: Trích xuất nguyên văn (Verbatim) nội dung trong ảnh.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 131 |
|
| 132 |
+
QUY TẮC BẤT DI BẤT DỊCH (CẤM VI PHẠM):
|
| 133 |
+
1. TUYỆT ĐỐI KHÔNG thêm lời dẫn đầu (như "Dưới đây là...", "Chào bạn...", "Văn bản này nói về...").
|
| 134 |
+
2. TUYỆT ĐỐI KHÔNG thêm lời kết luận hay nhận xét, đánh giá.
|
| 135 |
+
3. KHÔNG thay đổi từ ngữ, KHÔNG diễn giải (paraphrase), KHÔNG tóm tắt. Phải giữ nguyên văn kể cả lỗi chính tả của bản gốc.
|
| 136 |
+
4. Giữ nguyên cấu trúc dòng, đoạn, số hiệu, ngày tháng, quốc hiệu, tiêu ngữ.
|
| 137 |
+
5. Nếu chữ quá mờ không đọc được, hãy điền ký hiệu `[...]`. KHÔNG ĐƯỢC TỰ Ý ĐOÁN MÒ HAY BỊA ĐẶT NỘI DUNG.
|
| 138 |
|
| 139 |
+
ĐẦU RA: Chỉ trả về văn bản thô. Không Markdown dư thừa nếu không cần thiết."""
|
|
|
|
|
|
|
|
|
|
|
|
|
| 140 |
|
| 141 |
+
DIRECT_GEMINI_PROMPT_LATEX = r"""Đóng vai công cụ số hóa tài liệu Toán học chính xác tuyệt đối.
|
| 142 |
+
NHIỆM VỤ: Chuyển đổi ảnh sang Markdown + LaTeX.
|
| 143 |
+
|
| 144 |
+
QUY TẮC:
|
| 145 |
+
1. Công thức toán học PHẢI nằm trong dấu `$`. Ví dụ: $x^2 + 1 = 0$.
|
| 146 |
+
2. KHÔNG thêm lời dẫn thừa (như "Kết quả là:", "Đây là bài giải:").
|
| 147 |
+
3. GIỮ NGUYÊN VĂN đề bài và lời giải. KHÔNG tóm tắt, KHÔNG viết lại theo văn phong khác.
|
| 148 |
+
4. Nếu ảnh bị cắt hoặc mờ:
|
| 149 |
+
- Nếu là công thức toán có thể suy luận logic: Hãy phục hồi.
|
| 150 |
+
- Nếu là văn bản/tên riêng: Điền `[...]`.
|
| 151 |
+
|
| 152 |
+
CHỈ TRẢ VỀ NỘI DUNG MARKDOWN."""
|
| 153 |
|
| 154 |
# ===== STITCHING ALGORITHM =====
|
| 155 |
def stitch_text(text_a: str, text_b: str, min_overlap_chars: int = 20) -> str:
|
|
|
|
| 247 |
|
| 248 |
return {
|
| 249 |
"status": "ok",
|
| 250 |
+
"service": "HT_MATH_WEB API v9.1 (Strict Mode)",
|
| 251 |
"keys_loaded": key_manager.get_key_count(),
|
| 252 |
"pandoc": pandoc_status,
|
| 253 |
"tesseract": tesseract_status
|
|
|
|
| 318 |
if not api_key: raise ValueError("No API Key")
|
| 319 |
genai.configure(api_key=api_key)
|
| 320 |
|
| 321 |
+
# Giảm temperature xuống 0.0 để model trở nên máy móc nhất có thể (Deterministic)
|
| 322 |
+
generation_config = {"temperature": 0.0, "top_p": 1.0, "max_output_tokens": 8192}
|
| 323 |
model = genai.GenerativeModel(model_id, generation_config=generation_config)
|
| 324 |
|
| 325 |
# Gọi API
|
|
|
|
| 342 |
continue
|
| 343 |
if attempt == max_retries - 1:
|
| 344 |
print(f"Error Gemini: {e}")
|
|
|
|
| 345 |
return await fallback_ocr_tesseract(image)
|
| 346 |
|
| 347 |
return ""
|