Learning Personalized Prompts for Healthcare Guidance
EMNLP 2026 Main Conference
Note on data: The dataset is not released due to a data-sharing agreement with the collaborating hospital. This repository contains code only; the data formats required to run the pipeline are documented in Data format reference.
- Fine-tune the predictor LLM with LLaMA-Factory.
- Generate and save predictions for the train/valid/test splits as
*_prediction.jsonl. - Train the policy network with REINFORCE + BERTScore (
train_policy.py). - Run inference / baseline (
main.py,evaluate_llms.py).
- BERT: place a
bert-base-uncasedmodel under./bert-base-uncased/. - LLM API keys: fill in the API key of the LLM you use in
utils.py(get_llm_answersupports GLM, GPT, and Gemini).
Fine-tune an open-weight LLM with LLaMA-Factory using LoRA, so that it predicts a patient's condition from their longitudinal exam indicators. For installation and the SFT workflow, refer to the LLaMA-Factory documentation. Train on the train split, select the best checkpoint on the valid split, and evaluate on the test split.
Prepare the fine-tuning data in LLaMA-Factory's Alpaca format:
instruction(string): the task instruction.- Refer to Figure 3 in the paper for the exact prompt template.
input(string): the patient's longitudinal exam indicators, one visit per line.output(string): the predicted condition in the output format defined in the paper.- Refer to Figure 3 in the paper for the exact output format.
Register the dataset and run training/export following the LLaMA-Factory documentation.
Run the fine-tuned model on train.txt, valid.txt, and test.txt, and save the results as train_prediction.jsonl, valid_prediction.jsonl, and test_prediction.jsonl (one JSON object per line).
Each line must contain a predict field (string) holding the model's predicted condition. load_predictions extracts the condition from between the first [ and ] in that field.
python train_policy.py --llm <LLM> --gpu <GPU>This trains the patient encoder and the policy network with REINFORCE, using BERTScore against the reference suggestions (*_per_suggestion.json) as the reward. Training is on the train split; the model is evaluated on the valid split periodically, and the checkpoint with the best valid-set F1 is saved as best_encoder.pth / best_policy_net.pth. Final evaluation is on the test split.
# Interactive personalized-prompt demo (requires best_encoder.pth / best_policy_net.pth)
python main.py --llm <LLM> --gpu <GPU>
# Baseline: raw exam indicators only
python evaluate_llms.py --llm <LLM>The scripts pair the per-split files positionally: load_features reads *.txt in file order, load_labels returns labels sorted by patient id, and load_predictions / load_references read their files in order. Keep all files for a split in the same patient order (e.g., ascending patient id).
Plain text. Each patient record consists of:
- a header line with 3 whitespace-separated fields:
<patient_id> <date> <time>. - one visit line per visit after the header; each visit line contains 35 comma-separated numeric values.
The number of visits varies per patient (up to 45). load_features pads shorter sequences to 45 rows with zero rows.
Plain text. One <patient_id> <label_id> pair per line.
Plain text. One <disease_name> <label_id> per line (12 diseases, label ids 0-11).
JSON lines. Each line is a JSON object with a predict field (string) containing the predicted condition inside square brackets.
JSON array. Each element is an object with an output field (string) holding the reference suggestion, used as the reference for reward and evaluation.
The hospital dataset is not released due to a data-sharing agreement with the collaborating hospital. The formats above are sufficient to run the pipeline on your own data.