| import os |
| from unsloth import FastVisionModel |
| import torch |
| from PIL import Image |
| from datasets import load_dataset |
| from transformers import TextStreamer |
| import matplotlib.pyplot as plt |
| import gradio as gr |
| import random |
| import numpy as np |
|
|
| device = torch.device("cpu") |
|
|
| def set_seed(seed_value=42): |
| random.seed(seed_value) |
| np.random.seed(seed_value) |
| torch.manual_seed(seed_value) |
| |
| |
| torch.backends.cudnn.deterministic = True |
| torch.backends.cudnn.benchmark = False |
|
|
| set_seed(42) |
|
|
| model, tokenizer = FastVisionModel.from_pretrained( |
| "0llheaven/llama-3.2-11B-Vision-Instruct-Finetune", |
| load_in_4bit = True, |
| use_gradient_checkpointing = "unsloth", |
| ) |
|
|
| |
|
|
| instruction = "You are an expert radiographer. Describe accurately what you see in this image." |
|
|
| def predict_radiology_description(image, temperature, use_top_p, top_p_value, use_min_p, min_p_value): |
| try: |
| set_seed(42) |
| messages = [{"role": "user", "content": [ |
| {"type": "image"}, |
| {"type": "text", "text": instruction} |
| ]}] |
| input_text = tokenizer.apply_chat_template(messages, add_generation_prompt=True) |
|
|
| inputs = tokenizer( |
| image, |
| input_text, |
| add_special_tokens=False, |
| return_tensors="pt", |
| ).to(device) |
|
|
| text_streamer = TextStreamer(tokenizer, skip_prompt=True) |
|
|
| generate_kwargs = { |
| "max_new_tokens": 512, |
| "use_cache": True, |
| "temperature": temperature, |
| } |
| if use_top_p: |
| generate_kwargs["top_p"] = top_p_value |
| if use_min_p: |
| generate_kwargs["min_p"] = min_p_value |
|
|
| output_ids = model.generate( |
| **inputs, |
| streamer=text_streamer, |
| **generate_kwargs |
| ) |
|
|
| generated_text = tokenizer.decode(output_ids[0], skip_special_tokens=True) |
| return generated_text.replace("assistant", "\n\nassistant").strip() |
|
|
| except Exception as e: |
| return f"Error: {str(e)}" |
|
|
| with gr.Blocks() as interface: |
| gr.Markdown("<h1><center>Radiology Image Description Generator</center></h1>") |
| gr.Markdown("Upload a radiology image, adjust temperature and top-p, and the model will describe the findings in the image") |
| with gr.Row(): |
| with gr.Column(): |
| image_input = gr.Image(type="pil", label="Upload") |
| with gr.Column(): |
| output_text = gr.Textbox(label="Generated Description") |
|
|
| with gr.Row(): |
| with gr.Column(scale=0.5): |
| temperature_slider = gr.Slider(0.1, 2.0, step=0.1, value=1.0, label="temperature") |
|
|
| use_top_p_checkbox = gr.Checkbox(label="Use top-p", value=True) |
| top_p_slider = gr.Slider(0.1, 1.0, step=0.05, value=0.9, label="top-p") |
|
|
| use_min_p_checkbox = gr.Checkbox(label="Use min-p", value=False) |
| min_p_slider = gr.Slider(0.0, 1.0, step=0.05, value=0.1, label="min-p", visible=False) |
|
|
| |
| use_top_p_checkbox.change( |
| lambda use_top_p: gr.update(visible=use_top_p), |
| inputs=use_top_p_checkbox, |
| outputs=top_p_slider |
| ) |
| use_min_p_checkbox.change( |
| lambda use_min_p: gr.update(visible=use_min_p), |
| inputs=use_min_p_checkbox, |
| outputs=min_p_slider |
| ) |
|
|
| generate_button = gr.Button("Generate Description") |
|
|
| |
| generate_button.click( |
| predict_radiology_description, |
| inputs=[image_input, temperature_slider, use_top_p_checkbox, top_p_slider, use_min_p_checkbox, min_p_slider], |
| outputs=output_text |
| ) |
|
|
| |
| interface.launch(share=True, debug=True) |