The rapid evolution of artificial intelligence, especially in large language models (LLMs), has significantly impacted various domains, including healthcare. In chest X-ray (CXR) analysis, previous studies have employed LLMs, but with limitations: either underutilizing the LLMs' capability for multitask learning or lacking clinical accuracy. This article presents M4CXR, a multimodal LLM designed to enhance CXR interpretation. The model is trained on a visual instruction-following dataset that integrates various task-specific datasets in a conversational format. As a result, the model supports multiple tasks such as medical report generation (MRG), visual grounding, and visual question answering (VQA). M4CXR achieves state-of-the-art clinical accuracy in MRG by employing a chain-of-thought (CoT) prompting strategy, in which it identifies findings in CXR images and subsequently generates corresponding reports. The model is adaptable to various MRG scenarios depending on the available inputs, such as single-image, multiimage, and multistudy contexts. In addition to MRG, M4CXR performs visual grounding at a level comparable to specialized models and demonstrates outstanding performance in VQA. Both quantitative and qualitative assessments reveal M4CXR's versatility in MRG, visual grounding, and VQA, while consistently maintaining clinical accuracy.
pip install -r requirements.txt1import torch
2from transformers import AutoModelForCausalLM, AutoProcessor, GenerationConfig
3
4from interface import do_generate, load_image_from_url
5
6
7# Setup
8device = torch.device("cuda")
9dtype = torch.bfloat16
10
11# Load processor, model, and generation config
12processor = AutoProcessor.from_pretrained("Deepnoid/M4CXR-TNNLS", trust_remote_code=True)
13generation_config = GenerationConfig.from_pretrained("Deepnoid/M4CXR-TNNLS")
14model = AutoModelForCausalLM.from_pretrained(
15 "Deepnoid/M4CXR-TNNLS",
16 trust_remote_code=True,
17 torch_dtype=dtype,
18 device_map=device,
19)
20
21# Prepare a batch of images and questions
22images = [
23 load_image_from_url(
24 "https://upload.wikimedia.org/wikipedia/commons/a/a1/Normal_posteroanterior_%28PA%29_chest_radiograph_%28X-ray%29.jpg"
25 ),
26 load_image_from_url(
27 "https://upload.wikimedia.org/wikipedia/commons/a/a1/Normal_posteroanterior_%28PA%29_chest_radiograph_%28X-ray%29.jpg"
28 ),
29]
30questions = [
31 "radiology image: <image> What is the view of this chest X-ray?",
32 "radiology image: <image> Provide a description of the findings in the radiology image.",
33]
34
35# Build prompts with the chat template
36prompts = [
37 processor.apply_chat_template([{"role": "user", "content": q}], tokenize=False)
38 for q in questions
39]
40
41# Generate
42generation_config.do_sample = False
43outputs = do_generate(prompts, images, model, processor, generation_config)
44print(outputs)1findings = (
2 "enlarged cardiomediastinum, cardiomegaly, lung opacity, lung lesion, edema, "
3 "consolidation, pneumonia, atelectasis, pneumothorax, pleural Effusion, "
4 "pleural other, fracture, support devices"
5)1images = [image]
2questions = [
3 f"radiology image: <image> Which of the following findings are present in the radiology image? Findings: {findings}",
4 "Based on the previous conversation, provide a description of the findings in the radiology image.",
5]
6chats = do_generate_multi_turn(questions, images, model, processor, generation_config)1images = [image_pa, image_lat] # e.g., PA + lateral
2image_tokens = " ".join("<image>" for _ in images)
3questions = [
4 f"radiology images: {image_tokens} Which of the following findings are present in the radiology images? Findings: {findings}",
5 "Based on the previous conversation, provide a description of the findings in the radiology images.",
6]
7chats = do_generate_multi_turn(questions, images, model, processor, generation_config)1prior_images = [prior_pa, prior_lat]
2prior_report = "The lungs are clear. There is no pneumothorax."
3follow_up_images = [current_pa, current_lat]
4images = prior_images + follow_up_images
5
6prior_tokens = " ".join("<image>" for _ in prior_images)
7current_tokens = " ".join("<image>" for _ in follow_up_images)
8
9questions = [
10 (
11 f"prior radiology images: {prior_tokens}, prior radiology report: {prior_report} "
12 f"follow-up images: {current_tokens}, The radiology studies are given in chronological order. "
13 f"Which of the following findings are present in the current follow-up radiology images? "
14 f"Findings: {findings}"
15 ),
16 "Based on the previous conversation, provide a description of the findings in the current follow-up radiology images.",
17]
18chats = do_generate_multi_turn(questions, images, model, processor, generation_config)1images = [image]
2phrase = "right lower lobe"
3questions = [
4 f"radiology image: <image> Provide the bounding box coordinate of the region this phrase describes: {phrase}",
5]
6chats = do_generate_multi_turn(questions, images, model, processor, generation_config)1images = [image]
2questions = [
3 f"radiology image: <image> Which of the following findings are present in the radiology image? Findings: {findings}",
4 "Based on the previous conversation, provide a description of the findings in the radiology image.",
5 "Summarize the description in one concise sentence.",
6]
7chats = do_generate_multi_turn(questions, images, model, processor, generation_config)1@article{park2025m4cxr,
2 author={Park, Jonggwon and Kim, Soobum and Yoon, Byungmu and Hyun, Jihun and Choi, Kyoyun},
3 journal={IEEE Transactions on Neural Networks and Learning Systems},
4 title={M4CXR: Exploring Multitask Potentials of Multimodal Large Language Models for Chest X-Ray Interpretation},
5 year={2025},
6 volume={36},
7 number={10},
8 pages={17841-17855},
9 doi={10.1109/TNNLS.2025.3587687}
10}