A QLoRA fine-tuned adapter for Qwen2.5-VL-7B-Instruct optimized for medical document understanding and clinical information extraction from document images.
This adapter was trained on 1,000 medical document samples (PathVQA + MTSamples) using 4-bit NF4 quantization with LoRA rank 64, targeting all attention and MLP layers. It extracts diagnoses, medications with dosages, lab values with reference ranges, vital signs, procedures, and clinical abbreviations from scanned/photographed clinical documents.
Recommendation: For production use, deploy the base model with NF4 quantization (no LoRA). It achieves 83.5% accuracy, requires only 5.7 GB VRAM, and runs 2x faster than FP16. See Analysis for details.
Quick Start
Load with LoRA Adapter (NF4 Quantized)
python
1import torch
2from transformers import AutoProcessor, Qwen2_5_VLForConditionalGeneration, BitsAndBytesConfig
3from peft import PeftModel
4from qwen_vl_utils import process_vision_info
5from PIL import Image
67# NF4 quantization config (same used during training)8bnb_config = BitsAndBytesConfig(9 load_in_4bit=True,10 bnb_4bit_quant_type="nf4",11 bnb_4bit_compute_dtype=torch.bfloat16,12 bnb_4bit_use_double_quant=True,13)1415# Load base model with NF4 quantization16model = Qwen2_5_VLForConditionalGeneration.from_pretrained(17"Qwen/Qwen2.5-VL-7B-Instruct",18 quantization_config=bnb_config,19 device_map="auto",20)2122# Load and merge LoRA adapter23model = PeftModel.from_pretrained(model,"sarathi-balakrishnan/Qwen2.5-VL-7B-Medical-LoRA")24model = model.merge_and_unload()25model.eval()2627processor = AutoProcessor.from_pretrained("Qwen/Qwen2.5-VL-7B-Instruct")2829# Inference30image = Image.open("medical_document.png")31messages =[32{33"role":"user",34"content":[35{"type":"image","image": image},36{"type":"text","text":"Extract all medical diagnoses, medications with dosages, and vital signs from this document."},37],38}39]4041text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)42image_inputs, video_inputs = process_vision_info(messages)43inputs = processor(44 text=[text], images=image_inputs, videos=video_inputs,45 padding=True, return_tensors="pt",46).to(model.device)4748with torch.no_grad():49 output_ids = model.generate(**inputs, max_new_tokens=1024)5051generated_ids = output_ids[0][inputs["input_ids"].shape[1]:]52response = processor.decode(generated_ids, skip_special_tokens=True)53print(response)
Use Base Model Only (Higher Accuracy, Recommended for Production)
python
1# Same as above but skip the PeftModel step:2model = Qwen2_5_VLForConditionalGeneration.from_pretrained(3"Qwen/Qwen2.5-VL-7B-Instruct",4 quantization_config=bnb_config,5 device_map="auto",6)7model.eval()8# ... rest of inference code identical
Sample Use Cases with Example Prompts
Use Case 1: Emergency Department Triage
Upload a referral letter or patient assessment and extract critical information in seconds.
python
1prompt ="""Extract all medical diagnoses, medications with dosages, and vital signs
2from this patient assessment document."""
Sample output (from actual model inference on test image):
**Medical Diagnoses:**
1. Acute coronary syndrome, NSTEMI - Troponin I 2.4 ng/mL
2. Hypertension, uncontrolled
3. Type 2 Diabetes Mellitus (HbA1c 8.2%)
4. Chronic Kidney Disease, Stage 3 (eGFR 42 mL/min)
**Medications Ordered:**
- Aspirin 325 mg PO STAT, then 81 mg PO QD
- Heparin 5000 units IV bolus, then 1000 units/hr
- Metoprolol 25 mg PO BID
- Lisinopril 10 mg PO QD
- Metformin 1000 mg PO BID
- Atorvastatin 80 mg PO QHS
**Vital Signs:**
- BP: 158/94 mmHg
- HR: 102 bpm
- RR: 22/min
- Temp: 98.6 F
- SpO2: 93% on RA
- Weight: 198 lbs
Use Case 2: Radiology Report Parsing
Extract findings, measurements, and impressions from radiology reports.
python
1prompt ="""List all findings from this radiology report including measurements,
2locations, and the radiologist's impression."""
Sample output:
### Findings:
**Lungs:**
- 3.2 x 2.8 cm spiculated mass in the right upper lobe (series 4, image 87)
- Ipsilateral hilar lymphadenopathy measuring 1.8 cm
- Left lung clear. No pleural effusion.
**Mediastinum:**
- Subcarinal lymph node enlarged at 2.1 cm
- No pericardial effusion. Heart size normal.
**Bones:**
- Lytic lesion in T8 vertebral body, 1.2 cm, suspicious for metastatic disease
### Radiologist's Impression:
1. Right upper lobe mass highly suspicious for primary bronchogenic carcinoma. LUNG-RADS 4B.
2. Ipsilateral hilar and subcarinal lymphadenopathy suggesting nodal metastasis (N2 disease).
3. T8 lytic lesion concerning for osseous metastasis.
### Recommendation:
PET/CT and tissue biopsy recommended.
Use Case 3: Prescription Extraction
Extract structured medication information from prescription images.
python
1prompt ="""Extract all prescribed medications with their dosages, directions,
2quantities, and refill counts from this prescription."""
Sample output:
1. **Lisinopril 20 mg tablets**
- Dosage: 1 tablet by mouth once daily in the morning
- Quantity: #30
- Refills: 5
2. **Amlodipine 5 mg tablets**
- Dosage: 1 tablet by mouth once daily
- Quantity: #30
- Refills: 5
3. **Metformin 500 mg tablets**
- Dosage: 1 tablet by mouth twice daily with meals
- Quantity: #60
- Refills: 3
4. **Atorvastatin 40 mg tablets**
- Dosage: 1 tablet by mouth at bedtime
- Quantity: #30
- Refills: 5
5. **Pantoprazole 40 mg delayed-release tablets**
- Dosage: 1 tablet by mouth once daily 30 minutes before breakfast
- Quantity: #30
- Refills: 2
Use Case 4: Laboratory Results Parsing
Extract lab values with units, reference ranges, and abnormal flags.
python
1prompt ="""Extract all lab values with their results, units, reference ranges,
2and flags from this laboratory report."""
Extract diagnoses, medications, and follow-up instructions from discharge documents.
python
1prompt ="""Extract all diagnoses, medications with dosages, and follow-up
2instructions from this discharge summary."""
Sample output:
### Diagnoses:
1. Community-acquired pneumonia (CAP), right lower lobe
2. Acute on chronic systolic heart failure (EF 30%)
3. Atrial fibrillation with RVR
4. COPD exacerbation
### Discharge Medications:
- Metoprolol Succinate: 50 mg PO QD
- Furosemide: 40 mg PO BID
- Potassium Chloride: 20 mEq PO BID
- Apixaban: 5 mg PO BID
- Lisinopril: 5 mg PO QD
- Albuterol MDI: 2 puffs Q4-6H PRN
- Prednisone taper: 40 mg x 5d, 20 mg x 5d, 10 mg x 5d
- Levofloxacin: 750 mg PO QD x 3 more days
### Follow-Up Instructions:
- PCP in 1 week
- Cardiology in 2 weeks
- Repeat CXR in 6 weeks
- Echo in 3 months
Use Case 6: ICU Flowsheet Extraction
Parse complex ICU documentation with ventilator settings, drips, and hemodynamics.
python
1prompt ="""Extract all ventilator settings, hemodynamic parameters, drip rates,
2lab values, intake/output totals, and diagnoses from this ICU flowsheet."""
Sample output (from actual evaluation -- base model achieved 100% accuracy on this case):
Extract complete medication lists with indications and comorbidity mapping.
python
1prompt ="""Extract every medication with its exact dosage, frequency, and indication.
2Also list all comorbidities and relevant lab values."""
Use Case 8: Surgical Operative Note Parsing
python
1prompt ="""Extract the diagnoses, procedure details, operative findings with measurements,
2estimated blood loss, medications with dosages, and postoperative orders."""
Use Case 9: Custom Clinical Analysis
python
1prompt ="""Identify all drug interactions risks from the medications listed in this document.
2Flag any medications that may need dose adjustment based on the lab values shown."""
Use Case 10: Batch Processing for Clinical Research