Spaces:
Build error
Build error
Update app.py
Browse files
app.py
CHANGED
|
@@ -6,7 +6,7 @@ import io
|
|
| 6 |
from PIL import Image
|
| 7 |
import torch
|
| 8 |
from transformers import AutoProcessor, AutoModelForCausalLM
|
| 9 |
-
from ctransformers import AutoModelForCausalLM as CAutoModelForCausalLM
|
| 10 |
|
| 11 |
# --- CẤU HÌNH VÀ TẢI MÔ HÌNH (PHIÊN BẢN ỔN ĐỊNH NHẤT CHO CPU) ---
|
| 12 |
device = "cpu"
|
|
@@ -25,17 +25,15 @@ ocr_model = AutoModelForCausalLM.from_pretrained(
|
|
| 25 |
)
|
| 26 |
print("Tải xong mô hình OCR.")
|
| 27 |
|
| 28 |
-
# 2.
|
| 29 |
print("Đang tải mô hình LLM (Llama-3-8B GGUF for CPU)...")
|
| 30 |
-
# Sử dụng phiên bản GGUF được tối ưu cho CPU
|
| 31 |
llm_model_id = "QuantFactory/Meta-Llama-3-8B-Instruct-GGUF"
|
| 32 |
-
llm_model_file = "Meta-Llama-3-8B-Instruct.Q4_K_M.gguf"
|
| 33 |
llm = CAutoModelForCausalLM.from_pretrained(
|
| 34 |
llm_model_id,
|
| 35 |
model_file=llm_model_file,
|
| 36 |
model_type="llama",
|
| 37 |
-
|
| 38 |
-
gpu_layers=0, # Không dùng GPU
|
| 39 |
context_length=4096
|
| 40 |
)
|
| 41 |
print("Tải xong mô hình LLM.")
|
|
@@ -47,6 +45,7 @@ def run_ocr(image: Image.Image) -> str:
|
|
| 47 |
if image is None: return "Lỗi: Vui lòng cung cấp hình ảnh."
|
| 48 |
prompt = "<OCR>"
|
| 49 |
inputs = ocr_processor(text=prompt, images=image, return_tensors="pt").to(device)
|
|
|
|
| 50 |
generated_ids = ocr_model.generate(
|
| 51 |
input_ids=inputs["input_ids"],
|
| 52 |
pixel_values=inputs["pixel_values"],
|
|
@@ -58,19 +57,14 @@ def run_ocr(image: Image.Image) -> str:
|
|
| 58 |
return parsed_text['<OCR>']
|
| 59 |
|
| 60 |
def extract_order_from_text(text: str) -> dict:
|
| 61 |
-
# Cập nhật prompt cho Llama 3 GGUF
|
| 62 |
prompt = f"""<|begin_of_text|><|start_header_id|>system<|end_header_id|>
|
| 63 |
You are an expert assistant that only outputs valid JSON. Extract order information from the text. The JSON object must contain "ten_khach_hang" (string, null if not found) and "danh_sach_hang" (an array of items). Each item must have "ten_hang" (string), "so_luong" (number), "don_vi" (string), "ma_hang" (string, null if not found), and "ghi_chu" (string, null if not found).<|eot_id|><|start_header_id|>user<|end_header_id|>
|
| 64 |
Text Content:
|
| 65 |
{text}<|eot_id|><|start_header_id|>assistant<|end_header_id|>
|
| 66 |
"""
|
| 67 |
-
|
| 68 |
response_text = llm(prompt, max_new_tokens=1024, temperature=0.1, stop=["<|eot_id|>"])
|
| 69 |
-
|
| 70 |
try:
|
| 71 |
-
# Làm sạch output thô từ GGUF model
|
| 72 |
json_str = response_text.strip()
|
| 73 |
-
# Tìm vị trí bắt đầu và kết thúc của JSON
|
| 74 |
start = json_str.find('{')
|
| 75 |
end = json_str.rfind('}') + 1
|
| 76 |
if start != -1 and end != 0:
|
|
@@ -81,17 +75,13 @@ def extract_order_from_text(text: str) -> dict:
|
|
| 81 |
|
| 82 |
def create_excel_file(order_data: dict):
|
| 83 |
if not order_data or "danh_sach_hang" not in order_data or not order_data["danh_sach_hang"]: return None
|
| 84 |
-
# Đổi tên key cho phù hợp với DataFrame
|
| 85 |
flat_data = []
|
| 86 |
customer = order_data.get('ten_khach_hang', 'N/A')
|
| 87 |
for item in order_data['danh_sach_hang']:
|
| 88 |
flat_data.append({
|
| 89 |
-
'Khách hàng': customer,
|
| 90 |
-
'
|
| 91 |
-
'
|
| 92 |
-
'Số lượng': item.get('so_luong'),
|
| 93 |
-
'Đơn vị': item.get('don_vi'),
|
| 94 |
-
'Ghi chú': item.get('ghi_chu')
|
| 95 |
})
|
| 96 |
df = pd.DataFrame(flat_data)
|
| 97 |
output = io.BytesIO()
|
|
@@ -121,7 +111,7 @@ def process_image_and_extract(image):
|
|
| 121 |
print(traceback_str)
|
| 122 |
return f"Lỗi nghiêm trọng: {error_str}", None, None
|
| 123 |
|
| 124 |
-
# --- XÂY DỰNG GIAO DIỆN GRADIO
|
| 125 |
with gr.Blocks(theme=gr.themes.Soft()) as app:
|
| 126 |
gr.Markdown("# Ứng dụng Trích xuất Đơn hàng từ Ảnh chụp màn hình")
|
| 127 |
gr.Markdown("Chụp màn hình email/tin nhắn đặt hàng, sau đó dán (Ctrl+V) vào ô bên dưới và nhấn 'Xử lý'.")
|
|
|
|
| 6 |
from PIL import Image
|
| 7 |
import torch
|
| 8 |
from transformers import AutoProcessor, AutoModelForCausalLM
|
| 9 |
+
from ctransformers import AutoModelForCausalLM as CAutoModelForCausalLM
|
| 10 |
|
| 11 |
# --- CẤU HÌNH VÀ TẢI MÔ HÌNH (PHIÊN BẢN ỔN ĐỊNH NHẤT CHO CPU) ---
|
| 12 |
device = "cpu"
|
|
|
|
| 25 |
)
|
| 26 |
print("Tải xong mô hình OCR.")
|
| 27 |
|
| 28 |
+
# 2. DÙNG CTRANSFORMERS ĐỂ TẢI GGUF
|
| 29 |
print("Đang tải mô hình LLM (Llama-3-8B GGUF for CPU)...")
|
|
|
|
| 30 |
llm_model_id = "QuantFactory/Meta-Llama-3-8B-Instruct-GGUF"
|
| 31 |
+
llm_model_file = "Meta-Llama-3-8B-Instruct.Q4_K_M.gguf"
|
| 32 |
llm = CAutoModelForCausalLM.from_pretrained(
|
| 33 |
llm_model_id,
|
| 34 |
model_file=llm_model_file,
|
| 35 |
model_type="llama",
|
| 36 |
+
gpu_layers=0,
|
|
|
|
| 37 |
context_length=4096
|
| 38 |
)
|
| 39 |
print("Tải xong mô hình LLM.")
|
|
|
|
| 45 |
if image is None: return "Lỗi: Vui lòng cung cấp hình ảnh."
|
| 46 |
prompt = "<OCR>"
|
| 47 |
inputs = ocr_processor(text=prompt, images=image, return_tensors="pt").to(device)
|
| 48 |
+
# SỬA LỖI ĐÁNH MÁY Ở ĐÂY
|
| 49 |
generated_ids = ocr_model.generate(
|
| 50 |
input_ids=inputs["input_ids"],
|
| 51 |
pixel_values=inputs["pixel_values"],
|
|
|
|
| 57 |
return parsed_text['<OCR>']
|
| 58 |
|
| 59 |
def extract_order_from_text(text: str) -> dict:
|
|
|
|
| 60 |
prompt = f"""<|begin_of_text|><|start_header_id|>system<|end_header_id|>
|
| 61 |
You are an expert assistant that only outputs valid JSON. Extract order information from the text. The JSON object must contain "ten_khach_hang" (string, null if not found) and "danh_sach_hang" (an array of items). Each item must have "ten_hang" (string), "so_luong" (number), "don_vi" (string), "ma_hang" (string, null if not found), and "ghi_chu" (string, null if not found).<|eot_id|><|start_header_id|>user<|end_header_id|>
|
| 62 |
Text Content:
|
| 63 |
{text}<|eot_id|><|start_header_id|>assistant<|end_header_id|>
|
| 64 |
"""
|
|
|
|
| 65 |
response_text = llm(prompt, max_new_tokens=1024, temperature=0.1, stop=["<|eot_id|>"])
|
|
|
|
| 66 |
try:
|
|
|
|
| 67 |
json_str = response_text.strip()
|
|
|
|
| 68 |
start = json_str.find('{')
|
| 69 |
end = json_str.rfind('}') + 1
|
| 70 |
if start != -1 and end != 0:
|
|
|
|
| 75 |
|
| 76 |
def create_excel_file(order_data: dict):
|
| 77 |
if not order_data or "danh_sach_hang" not in order_data or not order_data["danh_sach_hang"]: return None
|
|
|
|
| 78 |
flat_data = []
|
| 79 |
customer = order_data.get('ten_khach_hang', 'N/A')
|
| 80 |
for item in order_data['danh_sach_hang']:
|
| 81 |
flat_data.append({
|
| 82 |
+
'Khách hàng': customer, 'Mã hàng': item.get('ma_hang'),
|
| 83 |
+
'Tên hàng': item.get('ten_hang'), 'Số lượng': item.get('so_luong'),
|
| 84 |
+
'Đơn vị': item.get('don_vi'), 'Ghi chú': item.get('ghi_chu')
|
|
|
|
|
|
|
|
|
|
| 85 |
})
|
| 86 |
df = pd.DataFrame(flat_data)
|
| 87 |
output = io.BytesIO()
|
|
|
|
| 111 |
print(traceback_str)
|
| 112 |
return f"Lỗi nghiêm trọng: {error_str}", None, None
|
| 113 |
|
| 114 |
+
# --- XÂY DỰNG GIAO DIỆN GRADIO ---
|
| 115 |
with gr.Blocks(theme=gr.themes.Soft()) as app:
|
| 116 |
gr.Markdown("# Ứng dụng Trích xuất Đơn hàng từ Ảnh chụp màn hình")
|
| 117 |
gr.Markdown("Chụp màn hình email/tin nhắn đặt hàng, sau đó dán (Ctrl+V) vào ô bên dưới và nhấn 'Xử lý'.")
|