Spaces:
Running
Running
import gradio as gr | |
from transformers import pipeline | |
from PIL import Image | |
import torch | |
import os | |
import spaces | |
# --- Configuration & Model Loading --- | |
# Use the pipeline, which is more robust as seen in the working example | |
print("Loading MedGemma model via pipeline...") | |
model_loaded = False | |
pipe = None | |
try: | |
pipe = pipeline( | |
"image-to-text", | |
model="google/medgemma-4b-it", | |
model_kwargs={"torch_dtype": torch.bfloat16}, | |
device_map="auto", | |
token=os.environ.get("HF_TOKEN") | |
) | |
model_loaded = True | |
print("Model loaded successfully!") | |
except Exception as e: | |
print(f"Error loading model: {e}") | |
# --- Core Chatbot Function --- | |
def symptom_checker_chat(user_input, history_for_display, new_image_upload, image_state): | |
""" | |
Manages the conversation using the correct message format derived from the working example. | |
""" | |
if not model_loaded: | |
if user_input: | |
history_for_display.append((user_input, "Error: The model could not be loaded.")) | |
return history_for_display, image_state, None, "" | |
current_image = new_image_upload if new_image_upload is not None else image_state | |
# Build the 'messages' list using the correct format for the pipeline | |
messages = [] | |
# Process the conversation history | |
for user_msg, assistant_msg in history_for_display: | |
messages.append({"role": "user", "content": user_msg}) | |
if assistant_msg: | |
messages.append({"role": "assistant", "content": assistant_msg}) | |
# Add the current user turn | |
messages.append({"role": "user", "content": user_input}) | |
try: | |
# The pipeline call is simpler. We pass the image as the main argument | |
# and the text conversation as the `prompt`. | |
if current_image: | |
# The image goes first, the prompt kwarg contains the conversation history | |
output = pipe(current_image, prompt=messages, generate_kwargs={"max_new_tokens": 512, "do_sample": True, "temperature": 0.7}) | |
else: | |
# If no image, the pipeline can work with just the prompt | |
output = pipe(prompt=messages, generate_kwargs={"max_new_tokens": 512, "do_sample": True, "temperature": 0.7}) | |
# The pipeline output structure contains the full conversation. | |
# We want the content of the last message, which is the model's reply. | |
clean_response = output[0]["generated_text"][-1]['content'] | |
except Exception as e: | |
print(f"Caught a critical exception during generation: {e}", flush=True) | |
clean_response = ( | |
"An error occurred during generation. Details:\n\n" | |
f"```\n{type(e).__name__}: {e}\n```" | |
) | |
history_for_display.append((user_input, clean_response)) | |
return history_for_display, current_image, None, "" | |
# --- Gradio Interface --- | |
with gr.Blocks(theme=gr.themes.Soft(), css="footer {display: none !important}") as demo: | |
gr.Markdown( | |
""" | |
# AI Symptom Checker powered by MedGemma | |
Describe your symptoms below. For visual symptoms (e.g., a skin rash), upload an image. The AI will analyze the inputs and ask clarifying questions if needed. | |
""" | |
) | |
image_state = gr.State(None) | |
chatbot = gr.Chatbot(label="Conversation", height=500, bubble_full_width=False, avatar_images=("user.png", "bot.png")) | |
chat_history = gr.State([]) | |
with gr.Row(): | |
image_box = gr.Image(type="pil", label="Upload Image of Symptom (Optional)") | |
with gr.Row(): | |
text_box = gr.Textbox(label="Describe your symptoms...", placeholder="e.g., I have a rash on my arm that is red and itchy...", scale=4) | |
submit_btn = gr.Button("Send", variant="primary", scale=1) | |
def clear_all(): | |
return [], None, None, "" | |
clear_btn = gr.Button("Start New Conversation") | |
clear_btn.click(fn=clear_all, outputs=[chat_history, image_state, image_box, text_box], queue=False) | |
def on_submit(user_input, display_history, new_image, persisted_image): | |
if not user_input.strip() and not new_image: | |
return display_history, persisted_image, None, "" | |
return symptom_checker_chat(user_input, display_history, new_image, persisted_image) | |
# Event Handlers for submit button and enter key | |
submit_btn.click( | |
fn=on_submit, | |
inputs=[text_box, chat_history, image_box, image_state], | |
outputs=[chat_history, image_state, image_box, text_box] | |
) | |
text_box.submit( | |
fn=on_submit, | |
inputs=[text_box, chat_history, image_box, image_state], | |
outputs=[chat_history, image_state, image_box, text_box] | |
) | |
if __name__ == "__main__": | |
demo.launch(debug=True) | |