Rathapoom's picture
Update app.py
86cda4c verified
#!/usr/bin/env python
# encoding: utf-8
import spaces
import torch
import argparse
from transformers import AutoModel, AutoTokenizer
import gradio as gr
from PIL import Image
import os
import traceback
import re
# Argparser
parser = argparse.ArgumentParser(description='Food Calcium Analysis Demo')
parser.add_argument('--device', type=str, default='cuda', help='cuda or mps')
args = parser.parse_args()
device = args.device
assert device in ['cuda', 'mps']
# Load model
model_path = 'openbmb/MiniCPM-V-2_6'
model = AutoModel.from_pretrained(model_path, trust_remote_code=True, torch_dtype=torch.bfloat16)
model = model.to(device=device)
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
model.eval()
ERROR_MSG = "Error, please retry"
model_name = 'Food Calcium Analyzer'
def encode_image(image):
if image is not None:
if not isinstance(image, Image.Image):
image = Image.open(image).convert("RGB")
max_size = 448*16
if max(image.size) > max_size:
w, h = image.size
if w > h:
new_w, new_h = max_size, int(h * max_size / w)
else:
new_h, new_w = max_size, int(w * max_size / h)
image = image.resize((new_w, new_h), resample=Image.BICUBIC)
return image
return None
@spaces.GPU(duration=120)
def chat(image, food_name, params=None):
try:
system_prompt = """You are an AI assistant specialized in analyzing food and estimating calcium content. Follow these steps:
1. Identify the food (if image is provided) or use the given food name.
2. List the main ingredients.
3. Estimate the calcium content for each main ingredient.
4. Calculate the total estimated calcium content.
Here's an example of a good analysis:
อาหาร: ข้าวกะเพราหมูสับไข่ดาว
ส่วนประกอบหลัก: ข้าวสวย, หมูสับผัดกะเพรา, ไข่ดาว
ปริมาณแคลเซียมโดยประมาณ:
- ข้าวสวย (1 จาน): 10 มิลลิกรัม
- หมูสับผัดกะเพรา (100 กรัม): 15 มิลลิกรัม
- ไข่ดาว (1 ฟอง): 25 มิลลิกรัม
ปริมาณแคลเซียมรวมโดยประมาณ: 50 มิลลิกรัม
Now, analyze the given food in a similar manner, being as accurate as possible."""
if image:
user_message = f"{system_prompt}\n\nUser: Analyze this food image and estimate its calcium content."
content = [encode_image(image), user_message]
else:
user_message = f"{system_prompt}\n\nUser: Analyze this food and estimate its calcium content: {food_name}"
content = user_message
messages = [
{"role": "user", "content": content}
]
answer = model.chat(
image=None,
msgs=messages,
tokenizer=tokenizer,
**params
)
return process_answer(answer)
except Exception as e:
print(e)
traceback.print_exc()
return ERROR_MSG
def process_answer(answer):
# Extract food name
food_name_match = re.search(r'อาหาร: (.*?)(?:\n|$)', answer)
food_name = food_name_match.group(1) if food_name_match else "ไม่สามารถระบุชื่ออาหารได้"
# Extract main ingredients
ingredients_match = re.search(r'ส่วนประกอบหลัก: (.*?)(?:\n|$)', answer)
ingredients = ingredients_match.group(1) if ingredients_match else "ไม่สามารถระบุส่วนประกอบได้"
# Extract calcium content for each component
calcium_contents = re.findall(r'- (.*?): (\d+) มิลลิกรัม', answer)
# Extract total calcium
total_calcium_match = re.search(r'ปริมาณแคลเซียมรวมโดยประมาณ: (\d+) มิลลิกรัม', answer)
total_calcium = total_calcium_match.group(1) if total_calcium_match else "ไม่สามารถระบุปริมาณรวมได้"
# Format the result
result = f"อาหาร: {food_name}\n"
result += f"ส่วนประกอบหลัก: {ingredients}\n\n"
result += "ปริมาณแคลเซียมโดยประมาณ:\n"
for component, calcium in calcium_contents:
result += f"- {component}: {calcium} มิลลิกรัม\n"
result += f"\nปริมาณแคลเซียมรวมโดยประมาณ: {total_calcium} มิลลิกรัม"
return result
def analyze_food(image, food_name):
if image is None and not food_name:
return "กรุณาอัปโหลดรูปภาพอาหารหรือระบุชื่ออาหาร"
params = {
'sampling': True,
'top_p': 0.8,
'top_k': 100,
'temperature': 0.7,
'repetition_penalty': 1.05,
"max_new_tokens": 2048,
"max_inp_length": 4352
}
result = chat(image, food_name, params)
return result
css = """
.example label { font-size: 16px; }
"""
introduction = """
## วิเคราะห์ปริมาณแคลเซียมในอาหาร
แอปพลิเคชันนี้วิเคราะห์อาหารเพื่อประมาณปริมาณแคลเซียม
ฟีเจอร์:
1. อัปโหลดรูปภาพอาหาร หรือ
2. พิมพ์ชื่ออาหาร
3. รับข้อมูลชื่ออาหาร ส่วนประกอบ และปริมาณแคลเซียม
4. การวิเคราะห์ที่แม่นยำด้วย AI
อัปโหลดรูปภาพอาหารหรือพิมพ์ชื่ออาหารของคุณด้านล่างเพื่อเริ่มการวิเคราะห์
"""
with gr.Blocks(css=css) as demo:
gr.Markdown(value=introduction)
with gr.Row():
with gr.Column():
image_input = gr.Image(type="pil", label="อัปโหลดรูปภาพอาหาร (ไม่บังคับ)")
food_name_input = gr.Textbox(label="หรือพิมพ์ชื่ออาหาร (ถ้าไม่มีรูปภาพ)")
analyze_button = gr.Button("วิเคราะห์อาหาร")
with gr.Column():
result_output = gr.Textbox(label="ผลการวิเคราะห์", lines=10)
analyze_button.click(analyze_food, inputs=[image_input, food_name_input], outputs=[result_output])
with gr.Accordion("วิธีใช้งาน", open=False):
gr.Markdown("""
1. อัปโหลดรูปภาพอาหาร หรือพิมพ์ชื่ออาหารในช่องที่กำหนด
2. กดปุ่ม 'วิเคราะห์อาหาร'
3. รอสักครู่ให้ AI ประมวลผล
4. ดูผลลัพธ์ที่แสดง ซึ่งประกอบด้วย:
- ชื่ออาหาร
- ส่วนประกอบหลัก
- ปริมาณแคลเซียมในแต่ละส่วนประกอบ
- ปริมาณแคลเซียมรวมโดยประมาณ
หมายเหตุ: หากใช้รูปภาพ ควรใช้รูปที่ชัดเจนของอาหารจานเดียวหรือมื้อเดียวเพื่อผลลัพธ์ที่แม่นยำ
""")
demo.launch()