yangd05's picture
Replace Llama 8B with GPT-OSS 20B in model list
b493f7d
import os
import gradio as gr
from huggingface_hub import InferenceClient
MODELS = {
"Qwen/Qwen2.5-72B-Instruct": "Qwen 2.5 72B (free)",
"nvidia/Llama-3.1-Nemotron-70B-Instruct-HF": "Nemotron 70B (requires provider)",
"openai/gpt-oss-20b": "GPT-OSS 20B (free)",
}
SYSTEM_PROMPT = """
You are an expert medical assistant AI capable of modifying clinical documents to user specifications. Your primary objective is to make minimal alterations to the source document, ensuring that only explicitly stated information is utilized to fulfill user requests.
To accomplish this task, you will extract five key sections from the input radiology report, specifically: "CLINICAL INDICATION", "TECHNIQUE", "COMPARISON", "FINDINGS" and "IMPRESSION". If a particular section is not present in the original report, it will be represented as null in the output. The extracted sections will be formatted in YAML with proper indentation to reflect the hierarchy (e.g., subsections indented under FINDINGS, organs indented under each subsection). Do not wrap the output in markdown code fences. Notably, the "CLINICAL INDICATION" section may be referred to by alternative names, such as "History", "Indication", "INDICATION", or "Reason for Study", in the original report. To ensure accuracy, you will exclude any information that is not directly observable from the current imaging study, including patient demographic data, past medical history, and comparisons to prior images or studies.
The generated "FINDINGS" and "IMPRESSION" sections will be crafted to focus solely on the current image or study, without referencing any changes or comparisons to prior images, studies, or external patient knowledge. Any comparative statements will be rephrased as status observations based exclusively on the current image or study. Furthermore, all numbering and bullet points will be removed to maintain a concise and readable format. Please rewrite the "IMPRESSION" section as a bulleted list with indexes 1, 2, 3, 4, etc., and split the content to the left and right of "and" into different bullet points.
For the purposes of organization and clarity, the "FINDINGS" section must be broken down into subsections such as "Chest CT," "Abdomen and Pelvis CT," etc. based on the specific anatomy, and each subsection is broken down into organs (e.g., Liver, Kidneys, Bones, etc.).
Please retain all necessary details, especially ALL numbers or indicators in the report. And please indicate "Normal" instead of "Unremarkable" if any organ is not mentioned in the new report. Each leaf item should end with a period sign.
Examples of inputs and expected outputs:
{
EXAMPLE INPUT:
A CT scan of the chest, abdomen, and pelvis was performed on a patient with a clinical indication of colon cancer follow-up, using 100 ml of IV contrast, but no oral contrast, and the results were compared to a previous study from 01/01/2010. The chest CT showed a right port with its distal tip at the right atrium, and no evidence of lymphadenopathy, with a few subcentimeter nodules in the left lung lower lobes, including one measuring 0.3 cm (series 8, image 245), which were nonspecific. The abdomen and pelvis CT revealed postsurgical and possible post-ablation changes in the liver, with multiple small hypodense lesions, including ones measuring 1.0 cm (series 7, image 255), 0.7 cm (series 7, image 277), 0.8 cm (series 7, image 315), and 0.8 cm (series 7, image 286), which are likely corresponding to diffusion-restricting foci in MRI and suspicious for metastatic disease. Additionally, the scan showed a surgically absent gallbladder, postsurgical changes at the right-sided colon, a few hypodense, nonenhancing cysts in the left kidney, no hydronephrosis bilaterally, and a few prominent periportal and portacaval nodes, including one measuring 1.9 cm x 0.9 cm (series 7, image 323), which are indeterminate. The scan also noted mild calcific atherosclerotic disease of the aorta iliac vessels, degenerative changes of the spine, and a nondistended stomach with wall thickening likely related to underdistension. The impression from the scan is that there are postsurgical and possibly post-ablation changes of the liver, with multiple small hypodense foci within the liver suspicious for metastatic disease, along with other additional findings.
EXPECTED OUTPUT:
CLINICAL INDICATION: Colon cancer, follow up.\nTECHNIQUE: CT chest, abdomen and pelvis, 100 ml IV Contrast was administered. No Oral Contrast was administered.\nCOMPARISON: 01/01/2010\nFINDINGS:\n Chest CT:\n Lines and tubes: Right port with its distal tip at the right atrium.\n Lower neck, where included: Unremarkable.\n ymph nodes: No evidence of lymphadenopathy.\n Pulmonary arteries, aorta, great vessels: Unremarkable.\n Heart, pericardium, coronary arteries: Unremarkable.\n Esophagus: Unremarkable.\n Lungs: A few subcentimeter nodules in the left lung lower lobes such as (0.3 cm) (series 8, image 245), nonspecific.\n Pleura: No pleural effusion.\n Central airways: Patent.\n Chest wall soft tissues: Unremarkable. \nAbdomen and Pelvis CT:\n Liver: Postsurgical and possible post ablation changes in the liver. Multiple 1 cm or smaller hypodense lesions such as (1.0 cm) (series 7, image 255), (0.7 cm) (series 7, image 277) , (0.8 cm) (series 7, image 315) and (0.8 cm) (series 7, image 286); likely corresponding to a diffusion-restricting foci in MRI and suspicious for metastatic disease.\n Bile ducts: No intrahepatic biliary ductal dilatation.\n Gallbladder: Surgically absent.\n Pancreas: Unremarkable.\n Spleen: Unremarkable.\n Adrenals: Bilateral unremarkable.\n Kidneys, ureters: A few hypodense, nonenhancing cysts in the left kidney. No hydronephrosis bilaterally.\n Bladder: Unremarkable.\n Stomach: Nondistended stomach and wall thickening likely related to underdistension.\n Bowel: Postsurgical changes at the right sided colon. No evidence of bowel obstruction.\n Peritoneum: A few prominent periportal and portacaval nodes such as (1.9 cm x 0.9 cm) (series 7, image 323); indeterminate.\n Reproductive Organs: Unremarkable.\n Lymph Nodes: No bulky adenopathy.\n Vessels: Mild calcific atherosclerotic disease of the aorta iliac vessels.\n Abdominal Wall: Unremarkable.\n Bones: Degenerative changes of the spine.\nIMPRESSION:\n1. Post surgical and possibly post ablation changes of the liver. Multiple small hypodense foci within the liver suspicious for metastatic disease.\n2. Additional findings as above.
}
"""
EXAMPLE_REPORT = """\
CLINICAL HISTORY: ABDOMINAL PAIN.
TECHNIQUE: Multiple axial CT images were obtained through the abdomen and pelvis after \
administration of oral contrast material only.
COMMENTS:
There is evidence of diffuse hepatic hypoattenuation compatible with fatty infiltration. There is no \
intra or extrahepatic biliary ductal dilatation. The patient is status post cholecystectomy. The spleen \
is normal. The pancreas is of normal contour and attenuation characteristics. There is no evidence of \
adrenal mass.
Moderate sized fat containing supraumbilical hernia is present.
The kidneys are normal in size, shape and configuration. No renal or ureteral calculi are identified. \
There is no hydroureter or hydronephrosis.
There is no evidence for appendicitis. Several fluid-filled loops of small bowel are present compatible \
with mild enteritis. There is no bowel wall thickening. No evidence for small or large bowel \
obstruction. There is no evidence of abdominal ascites or lymphadenopathy.
There is no evidence of intrinsic or extrinsic bladder mass. There is no pelvic ascites or \
lymphadenopathy.
The uterus and ovaries are grossly unremarkable.
Images of the lung bases show no evidence of pleural or parenchymal mass. There are no pleural \
effusions. Scarring is present in the right middle lobe and lingula as well as both lung bases.
The bony structures are free of lytic or blastic lesions. Multilevel degenerative changes are seen \
involving the thoracolumbar spine.
Scattered calcifications are seen involving the aorta and major branches compatible with \
atherosclerosis."""
def process_report(
report: str,
additional_requirements: str,
model_choice: str,
max_tokens: int,
temperature: float,
top_p: float,
hf_token: gr.OAuthToken | None = None,
):
if not report or not report.strip():
yield "Please paste a radiology report to optimize."
return
token = hf_token.token if hf_token else os.environ.get("HF_TOKEN")
client = InferenceClient(token=token, model=model_choice)
user_message = report.strip()
if additional_requirements and additional_requirements.strip():
user_message += (
"\n\nAdditional requirements:\n" + additional_requirements.strip()
)
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_message},
]
response = ""
for chunk in client.chat_completion(
messages,
max_tokens=max_tokens,
stream=True,
temperature=temperature,
top_p=top_p,
):
choices = chunk.choices
if choices and choices[0].delta.content:
response += choices[0].delta.content
yield response
def load_example():
return EXAMPLE_REPORT
def clear_fields():
return "", "", ""
with gr.Blocks() as demo:
gr.Markdown(
"# 🩻 Radiology Report Optimizer\n"
"Paste a raw radiology report to extract and restructure it into "
"standardized sections: **Clinical Indication**, **Technique**, "
"**Comparison**, **Findings**, and **Impression**."
)
gr.LoginButton()
with gr.Row():
with gr.Column():
report_input = gr.Textbox(
label="Raw Radiology Report",
placeholder="Paste the full radiology report here…",
lines=14,
)
model_dropdown = gr.Dropdown(
choices=list(MODELS.keys()),
value="Qwen/Qwen2.5-72B-Instruct",
label="Model",
)
requirements_input = gr.Textbox(
label="Additional Requirements (optional)",
placeholder=(
"e.g., Focus on liver findings, "
"use Lung-RADS classification…"
),
lines=2,
)
with gr.Accordion("Generation Settings", open=False):
max_tokens = gr.Slider(
minimum=256, maximum=8192, value=4096, step=64,
label="Max new tokens",
)
temperature = gr.Slider(
minimum=0.1, maximum=1.5, value=0.3, step=0.1,
label="Temperature",
)
top_p = gr.Slider(
minimum=0.1, maximum=1.0, value=0.9, step=0.05,
label="Top-p (nucleus sampling)",
)
with gr.Row():
example_btn = gr.Button("📋 Load Example")
clear_btn = gr.Button("🗑️ Clear")
submit_btn = gr.Button("Optimize Report", variant="primary")
stop_btn = gr.Button("⏹ Stop")
with gr.Column():
output = gr.Textbox(
label="Optimized Report",
lines=22,
interactive=False,
buttons=["copy"],
)
example_btn.click(fn=load_example, outputs=report_input)
clear_btn.click(
fn=clear_fields,
outputs=[report_input, requirements_input, output],
)
run_event = submit_btn.click(
fn=process_report,
inputs=[
report_input, requirements_input, model_dropdown,
max_tokens, temperature, top_p,
],
outputs=output,
)
stop_btn.click(fn=None, cancels=[run_event])
if __name__ == "__main__":
demo.launch()