Spaces:
Runtime error
Runtime error
| #!/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 | |
| 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() |