Spaces:
Sleeping
Sleeping
import gradio as gr | |
import pandas as pd | |
from datasets import load_dataset | |
from openai import OpenAI | |
from PIL import Image | |
import io | |
import base64 | |
import logging | |
# Set up logging | |
logging.basicConfig(level=logging.INFO) | |
logger = logging.getLogger(__name__) | |
# App version | |
APP_VERSION = "1.0.0" | |
logger.info(f"Starting Radiology Teaching App v{APP_VERSION}") | |
try: | |
# Load only 10 rows from the dataset | |
logger.info("Loading MIMIC-CXR dataset...") | |
dataset = load_dataset("itsanmolgupta/mimic-cxr-dataset", split="train").select(range(10)) | |
df = pd.DataFrame(dataset) | |
logger.info(f"Successfully loaded {len(df)} cases") | |
except Exception as e: | |
logger.error(f"Error loading dataset: {str(e)}") | |
raise | |
def encode_image_to_base64(image_bytes): | |
return base64.b64encode(image_bytes).decode('utf-8') | |
def analyze_report(user_findings, ground_truth_findings, ground_truth_impression, api_key): | |
if not api_key: | |
return "Please provide a DeepSeek API key to analyze the report." | |
try: | |
client = OpenAI(api_key=api_key, base_url="https://api.deepseek.com") | |
logger.info("Analyzing report with DeepSeek...") | |
prompt = f"""You are an expert radiologist reviewing a trainee's chest X-ray report. | |
Trainee's Findings: | |
{user_findings} | |
Ground Truth Findings: | |
{ground_truth_findings} | |
Ground Truth Impression: | |
{ground_truth_impression} | |
Please provide: | |
1. Number of important findings missed by the trainee (list them) | |
2. Quality assessment of the trainee's report (structure, completeness, accuracy) | |
3. Constructive feedback for improvement | |
Format your response in clear sections.""" | |
response = client.chat.completions.create( | |
model="deepseek-chat", | |
messages=[ | |
{"role": "system", "content": "You are an expert radiologist providing constructive feedback."}, | |
{"role": "user", "content": prompt} | |
], | |
stream=False | |
) | |
return response.choices[0].message.content | |
except Exception as e: | |
logger.error(f"Error in report analysis: {str(e)}") | |
return f"Error analyzing report: {str(e)}" | |
def load_random_case(hide_ground_truth): | |
try: | |
# Randomly select a case from our dataset | |
random_case = df.sample(n=1).iloc[0] | |
logger.info("Loading random case...") | |
# Get the image, findings, and impression | |
image = random_case['image'] | |
findings = "" if hide_ground_truth else random_case['findings'] | |
impression = "" if hide_ground_truth else random_case['impression'] | |
return image, findings, impression | |
except Exception as e: | |
logger.error(f"Error loading random case: {str(e)}") | |
return None, "Error loading case", "Error loading case" | |
def process_case(image, user_findings, hide_ground_truth, api_key, current_findings="", current_impression=""): | |
if hide_ground_truth: | |
return "", "", "" | |
else: | |
analysis = analyze_report(user_findings, current_findings, current_impression, api_key) | |
return current_findings, current_impression, analysis | |
# Create the Gradio interface | |
with gr.Blocks() as demo: | |
gr.Markdown(f"# Radiology Report Training System v{APP_VERSION}") | |
gr.Markdown("### Practice your chest X-ray reading and reporting skills") | |
with gr.Row(): | |
with gr.Column(): | |
image_display = gr.Image(label="Chest X-ray Image", type="pil") | |
api_key_input = gr.Textbox(label="DeepSeek API Key", type="password") | |
hide_truth = gr.Checkbox(label="Hide Ground Truth", value=False) | |
load_btn = gr.Button("Load Random Case") | |
with gr.Column(): | |
user_findings_input = gr.Textbox(label="Your Findings", lines=10, placeholder="Type or dictate your findings here...") | |
ground_truth_findings = gr.Textbox(label="Ground Truth Findings", lines=5, interactive=False) | |
ground_truth_impression = gr.Textbox(label="Ground Truth Impression", lines=5, interactive=False) | |
analysis_output = gr.Textbox(label="Analysis and Feedback", lines=10, interactive=False) | |
submit_btn = gr.Button("Submit Report") | |
# Event handlers | |
load_btn.click( | |
fn=load_random_case, | |
inputs=[hide_truth], | |
outputs=[image_display, ground_truth_findings, ground_truth_impression] | |
) | |
submit_btn.click( | |
fn=process_case, | |
inputs=[ | |
image_display, | |
user_findings_input, | |
hide_truth, | |
api_key_input, | |
ground_truth_findings, | |
ground_truth_impression | |
], | |
outputs=[ | |
ground_truth_findings, | |
ground_truth_impression, | |
analysis_output | |
] | |
) | |
hide_truth.change( | |
fn=lambda x: ("", "", "") if x else (ground_truth_findings.value, ground_truth_impression.value, ""), | |
inputs=[hide_truth], | |
outputs=[ground_truth_findings, ground_truth_impression, analysis_output] | |
) | |
logger.info("Starting Gradio interface...") | |
demo.launch() |