From c9afeb1938893a12d02a2a7739b7c853a7ae9d6b Mon Sep 17 00:00:00 2001 From: charanw Date: Tue, 9 Dec 2025 20:14:05 -0600 Subject: [PATCH 01/11] Add BHCToAVS model for patient-friendly summaries Introduces the BHCToAVS model, which converts clinical Brief Hospital Course (BHC) notes into After-Visit Summaries (AVS) using a fine-tuned Mistral 7B model with LoRA adapters. Adds model implementation, documentation, an example usage script, and unit tests. --- docs/api/models.rst | 1 + docs/api/models/pyhealth.models.BHCToAVS.rst | 11 +++ examples/bhc_to_avs_example.py | 21 +++++ pyhealth/models/__init__.py | 3 +- pyhealth/models/bhc_to_avs.py | 98 ++++++++++++++++++++ tests/core/test_bhc_to_avs.py | 36 +++++++ 6 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 docs/api/models/pyhealth.models.BHCToAVS.rst create mode 100644 examples/bhc_to_avs_example.py create mode 100644 pyhealth/models/bhc_to_avs.py create mode 100644 tests/core/test_bhc_to_avs.py diff --git a/docs/api/models.rst b/docs/api/models.rst index a0df0d94..4ab9d6ed 100644 --- a/docs/api/models.rst +++ b/docs/api/models.rst @@ -8,6 +8,7 @@ We implement the following models for supporting multiple healthcare predictive :maxdepth: 3 models/pyhealth.models.BaseModel + models/pyhealth.models.BHCToAVS models/pyhealth.models.LogisticRegression models/pyhealth.models.MLP models/pyhealth.models.CNN diff --git a/docs/api/models/pyhealth.models.BHCToAVS.rst b/docs/api/models/pyhealth.models.BHCToAVS.rst new file mode 100644 index 00000000..59449318 --- /dev/null +++ b/docs/api/models/pyhealth.models.BHCToAVS.rst @@ -0,0 +1,11 @@ +pyhealth.models.bhc_to_avs +========================== + +BHCToAVS +------------------------------ + +.. autoclass:: pyhealth.models.bhc_to_avs.BHCToAVS + :members: + :inherited-members: + :show-inheritance: + :undoc-members: \ No newline at end of file diff --git a/examples/bhc_to_avs_example.py b/examples/bhc_to_avs_example.py new file mode 100644 index 00000000..ef438622 --- /dev/null +++ b/examples/bhc_to_avs_example.py @@ -0,0 +1,21 @@ +from pyhealth.models.bhc_to_avs import BHCToAVS + +# Initialize the model +model = BHCToAVS() + +# Example Brief Hospital Course (BHC) text with common clinical abbreviations generated synthetically via ChatGPT 5.1 +bhc = ( + "Pt admitted with acute onset severe epigastric pain and hypotension. " + "Labs notable for elevated lactate, WBC 18K, mild AST/ALT elevation, and Cr 1.4 (baseline 0.9). " + "CT A/P w/ contrast demonstrated peripancreatic fat stranding c/w acute pancreatitis; " + "no necrosis or peripancreatic fluid collection. " + "Pt received aggressive IVFs, electrolyte repletion, IV analgesia, and NPO status initially. " + "Serial abd exams remained benign with no rebound or guarding. " + "BP stabilized, lactate downtrended, and pt tolerated ADAT to low-fat diet without recurrence of sx. " + "Discharged in stable condition w/ instructions for GI f/u and outpatient CMP in 1 week." +) + +# Generate a patient-friendly After-Visit Summary +print(model.predict(bhc)) + +# Expected output: A simplified, patient-friendly summary explaining the hospital stay without medical jargon. \ No newline at end of file diff --git a/pyhealth/models/__init__.py b/pyhealth/models/__init__.py index 5c3683bc..659bb7f8 100644 --- a/pyhealth/models/__init__.py +++ b/pyhealth/models/__init__.py @@ -1,6 +1,7 @@ from .adacare import AdaCare, AdaCareLayer from .agent import Agent, AgentLayer from .base_model import BaseModel +from .bhc_to_avs import BHCToAVS from .cnn import CNN, CNNLayer from .concare import ConCare, ConCareLayer from .contrawr import ContraWR, ResBlock2D @@ -26,4 +27,4 @@ from .transformer import Transformer, TransformerLayer from .transformers_model import TransformersModel from .vae import VAE -from .sdoh import SdohClassifier \ No newline at end of file +from .sdoh import SdohClassifier diff --git a/pyhealth/models/bhc_to_avs.py b/pyhealth/models/bhc_to_avs.py new file mode 100644 index 00000000..b57e6fbf --- /dev/null +++ b/pyhealth/models/bhc_to_avs.py @@ -0,0 +1,98 @@ +# Author: Charan Williams +# NetID: charanw2 +# Description: Converts clinical brief hospital course (BHC) data to after visit summaries using a fine-tuned Mistral 7B model. + +from typing import Dict, Any +from dataclasses import dataclass, field +import torch +from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline +from peft import PeftModelForCausalLM +from pyhealth.models.base_model import BaseModel + +_PROMPT = """Summarize for the patient what happened during the hospital stay: + +### Brief Hospital Course: +{bhc} + +### Patient Summary: +""" + +# System prompt used during inference +_SYSTEM_PROMPT = ( + "You are a clinical summarization model. Produce accurate, patient-friendly summaries " + "using only information from the doctor's note. Do not add new details.\n\n" +) + +# Prompt used during fine-tuning +_PROMPT = ( + "Summarize for the patient what happened during the hospital stay based on this doctor's note:\n" + "{bhc}\n\n" + "Summary for the patient:\n" +) + +@dataclass +class BHCToAVS(BaseModel): + base_model_id: str = field(default="mistralai/Mistral-7B-Instruct") + """HuggingFace repo containing the base Mistral 7B model.""" + + adapter_model_id: str = field(default="williach31/mistral-7b-bhc-to-avs-lora") + """HuggingFace repo containing only LoRA adapter weights.""" + + def _get_pipeline(self): + """Create and cache the text-generation pipeline.""" + if not hasattr(self, "_pipeline"): + # Load base model + base = AutoModelForCausalLM.from_pretrained( + self.base_model_id, + torch_dtype=torch.bfloat16, + device_map="auto" + ) + + # Load LoRA adapter + model = PeftModelForCausalLM.from_pretrained( + base, + self.adapter_model_id, + torch_dtype=torch.bfloat16 + ) + + tokenizer = AutoTokenizer.from_pretrained(self.base_model_id) + + # Create HF pipeline + self._pipeline = pipeline( + "text-generation", + model=model, + tokenizer=tokenizer, + device_map="auto", + model_kwargs={"torch_dtype": torch.bfloat16} + ) + + return self._pipeline + + def predict(self, bhc_text: str) -> str: + """ + Generate an After-Visit Summary (AVS) from a Brief Hospital Course (BHC) note. + + Parameters + ---------- + bhc_text : str + Raw BHC text. + + Returns + ------- + str + Patient-friendly summary. + """ + + prompt = _SYSTEM_PROMPT + _PROMPT.format(bhc=bhc_text) + + pipe = self._get_pipeline() + outputs = pipe( + prompt, + max_new_tokens=512, + temperature=0.0, + eos_token_id=[pipe.tokenizer.eos_token_id], + pad_token_id=pipe.tokenizer.eos_token_id, + ) + + # Output is a single text string + return outputs[0]["generated_text"].strip() \ No newline at end of file diff --git a/tests/core/test_bhc_to_avs.py b/tests/core/test_bhc_to_avs.py new file mode 100644 index 00000000..04c45fbf --- /dev/null +++ b/tests/core/test_bhc_to_avs.py @@ -0,0 +1,36 @@ +from tests.base import BaseTestCase +from pyhealth.models.bhc_to_avs import BHCToAVS + + +class TestBHCToAVS(BaseTestCase): + """Unit tests for the BHCToAVS model.""" + + def setUp(self): + self.set_random_seed() + + def test_predict(self): + """Test the predict method of BHCToAVS.""" + bhc_text = ( + "Patient admitted with abdominal pain. Imaging showed no acute findings. " + "Pain improved with supportive care and the patient was discharged in stable condition." + ) + model = BHCToAVS() + try: + + summary = model.predict(bhc_text) + + # Output must be type str + self.assertIsInstance(summary, str) + + # Output should not be empty + self.assertGreater(len(summary.strip()), 0) + + # Output should be different from input + self.assertNotIn(bhc_text[:40], summary) + + except OSError as e: + # Allow test to pass if model download fails on e.g. on GitHub workflows + if "gated repo" in str(e).lower() or "404" in str(e): + pass + else: + raise e From 66f37d9bf6f0f4b582cb3340be9f1f2329e467ac Mon Sep 17 00:00:00 2001 From: Charan <109322104+charanw@users.noreply.github.com> Date: Mon, 29 Dec 2025 11:18:34 -0600 Subject: [PATCH 02/11] Remove redundant device_map paramter Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- pyhealth/models/bhc_to_avs.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyhealth/models/bhc_to_avs.py b/pyhealth/models/bhc_to_avs.py index b57e6fbf..9d71562e 100644 --- a/pyhealth/models/bhc_to_avs.py +++ b/pyhealth/models/bhc_to_avs.py @@ -62,7 +62,6 @@ def _get_pipeline(self): "text-generation", model=model, tokenizer=tokenizer, - device_map="auto", model_kwargs={"torch_dtype": torch.bfloat16} ) From d7cf144e95056ecbfe67474d9f273ab103ad8b34 Mon Sep 17 00:00:00 2001 From: Charan <109322104+charanw@users.noreply.github.com> Date: Mon, 29 Dec 2025 11:19:44 -0600 Subject: [PATCH 03/11] Add input validation for bhc_text Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- pyhealth/models/bhc_to_avs.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pyhealth/models/bhc_to_avs.py b/pyhealth/models/bhc_to_avs.py index 9d71562e..62f4bd85 100644 --- a/pyhealth/models/bhc_to_avs.py +++ b/pyhealth/models/bhc_to_avs.py @@ -82,6 +82,13 @@ def predict(self, bhc_text: str) -> str: Patient-friendly summary. """ + # Validate input to provide clear error messages and avoid unexpected failures. + if bhc_text is None: + raise ValueError("bhc_text must not be None.") + if not isinstance(bhc_text, str): + raise TypeError(f"bhc_text must be a string, got {type(bhc_text).__name__}.") + if not bhc_text.strip(): + raise ValueError("bhc_text must be a non-empty string.") prompt = _SYSTEM_PROMPT + _PROMPT.format(bhc=bhc_text) pipe = self._get_pipeline() From c0747cdb7701eb5134b4a32f8e482f03d4ff106c Mon Sep 17 00:00:00 2001 From: Charan <109322104+charanw@users.noreply.github.com> Date: Mon, 29 Dec 2025 11:21:28 -0600 Subject: [PATCH 04/11] Remove unused imports Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- pyhealth/models/bhc_to_avs.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyhealth/models/bhc_to_avs.py b/pyhealth/models/bhc_to_avs.py index 62f4bd85..034db3df 100644 --- a/pyhealth/models/bhc_to_avs.py +++ b/pyhealth/models/bhc_to_avs.py @@ -2,7 +2,6 @@ # NetID: charanw2 # Description: Converts clinical brief hospital course (BHC) data to after visit summaries using a fine-tuned Mistral 7B model. -from typing import Dict, Any from dataclasses import dataclass, field import torch from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline From ad3842abef871a4074ebfd9b2d1c733f1423ad13 Mon Sep 17 00:00:00 2001 From: Charan <109322104+charanw@users.noreply.github.com> Date: Mon, 29 Dec 2025 11:23:16 -0600 Subject: [PATCH 05/11] Set return_full_text to false to avoid returning input Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- pyhealth/models/bhc_to_avs.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyhealth/models/bhc_to_avs.py b/pyhealth/models/bhc_to_avs.py index 034db3df..c1b27937 100644 --- a/pyhealth/models/bhc_to_avs.py +++ b/pyhealth/models/bhc_to_avs.py @@ -97,6 +97,7 @@ def predict(self, bhc_text: str) -> str: temperature=0.0, eos_token_id=[pipe.tokenizer.eos_token_id], pad_token_id=pipe.tokenizer.eos_token_id, + return_full_text=False, ) # Output is a single text string From 18fbe2ca989f60cc08bc357589e880280a2595e6 Mon Sep 17 00:00:00 2001 From: charanw Date: Mon, 29 Dec 2025 11:26:01 -0600 Subject: [PATCH 06/11] Remove redundant _PROMPT --- pyhealth/models/bhc_to_avs.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/pyhealth/models/bhc_to_avs.py b/pyhealth/models/bhc_to_avs.py index b57e6fbf..8fb236f0 100644 --- a/pyhealth/models/bhc_to_avs.py +++ b/pyhealth/models/bhc_to_avs.py @@ -9,14 +9,6 @@ from peft import PeftModelForCausalLM from pyhealth.models.base_model import BaseModel -_PROMPT = """Summarize for the patient what happened during the hospital stay: - -### Brief Hospital Course: -{bhc} - -### Patient Summary: -""" - # System prompt used during inference _SYSTEM_PROMPT = ( "You are a clinical summarization model. Produce accurate, patient-friendly summaries " From 24d77be7ab722226d744ad349f263db1078f6205 Mon Sep 17 00:00:00 2001 From: charanw Date: Mon, 29 Dec 2025 12:45:46 -0600 Subject: [PATCH 07/11] Refactor BHCToAVS and test Enhanced the BHCToAVS model with improved docstrings, error handling for Hugging Face token requirements, and more robust pipeline initialization. Updated and expanded the test suite to include both unit tests with a mocked pipeline and an optional integration test for real model inference. --- pyhealth/models/bhc_to_avs.py | 83 +++++++++++++++++++++++++++---- tests/core/test_bhc_to_avs.py | 94 ++++++++++++++++++++++++++++------- 2 files changed, 149 insertions(+), 28 deletions(-) diff --git a/pyhealth/models/bhc_to_avs.py b/pyhealth/models/bhc_to_avs.py index 137cf327..e15a7441 100644 --- a/pyhealth/models/bhc_to_avs.py +++ b/pyhealth/models/bhc_to_avs.py @@ -1,8 +1,27 @@ +""" +BHC to AVS Model + +Generates patient-friendly After Visit Summaries (AVS) from Brief Hospital Course (BHC) +notes using a fine-tuned Mistral 7B model with a LoRA adapter. + +This model requires access to a gated Hugging Face repository. Provide credentials +using one of the following methods: + +1. Set an environment variable: + export HF_TOKEN="hf_..." + +2. Pass the token explicitly when creating the model: + model = BHCToAVS(hf_token="hf_...") + +If no token is provided and the repository is gated, a RuntimeError will be raised. +""" + # Author: Charan Williams # NetID: charanw2 -# Description: Converts clinical brief hospital course (BHC) data to after visit summaries using a fine-tuned Mistral 7B model. + from dataclasses import dataclass, field +import os import torch from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline from peft import PeftModelForCausalLM @@ -21,43 +40,82 @@ "Summary for the patient:\n" ) + @dataclass class BHCToAVS(BaseModel): - base_model_id: str = field(default="mistralai/Mistral-7B-Instruct") + """ + BHCToAVS is a model class designed to generate After-Visit Summaries (AVS) from + Brief Hospital Course (BHC) notes using a pre-trained base model and a LoRA adapter. + Attributes + base_model_id : str + The HuggingFace repository identifier for the base Mistral 7B model. + adapter_model_id : str + The HuggingFace repository identifier for the LoRA adapter weights. + Methods + _get_pipeline(): + Creates and caches a HuggingFace text-generation pipeline using the base model + and LoRA adapter. + predict(bhc_text: str) -> str: + Generates a patient-friendly After-Visit Summary (AVS) from a given Brief + Hospital Course (BHC) note. + """ + + base_model_id: str = field(default="mistralai/Mistral-7B-Instruct-v0.3") """HuggingFace repo containing the base Mistral 7B model.""" adapter_model_id: str = field(default="williach31/mistral-7b-bhc-to-avs-lora") """HuggingFace repo containing only LoRA adapter weights.""" + hf_token: str | None = None + + def _resolve_token(self): + return self.hf_token or os.getenv("HF_TOKEN") + def _get_pipeline(self): """Create and cache the text-generation pipeline.""" if not hasattr(self, "_pipeline"): + # Resolve HuggingFace token + token = self._resolve_token() + + # Throw RuntimeError if token is not found + if token is None: + raise RuntimeError( + "Hugging Face token not found. This model requires access to a gated repository.\n\n" + "Set the HF_TOKEN environment variable or pass hf_token=... when initializing BHCToAVS.\n\n" + "Example:\n" + " export HF_TOKEN='hf_...'\n" + " model = BHCToAVS()\n" + ) + + # Load base model base = AutoModelForCausalLM.from_pretrained( self.base_model_id, torch_dtype=torch.bfloat16, - device_map="auto" + device_map="auto", + token=token, ) # Load LoRA adapter model = PeftModelForCausalLM.from_pretrained( base, self.adapter_model_id, - torch_dtype=torch.bfloat16 + torch_dtype=torch.bfloat16, + token=token, ) - tokenizer = AutoTokenizer.from_pretrained(self.base_model_id) + tokenizer = AutoTokenizer.from_pretrained(self.base_model_id, token=token) # Create HF pipeline self._pipeline = pipeline( "text-generation", model=model, tokenizer=tokenizer, - model_kwargs={"torch_dtype": torch.bfloat16} + model_kwargs={"torch_dtype": torch.bfloat16}, ) return self._pipeline - + def predict(self, bhc_text: str) -> str: """ Generate an After-Visit Summary (AVS) from a Brief Hospital Course (BHC) note. @@ -77,20 +135,23 @@ def predict(self, bhc_text: str) -> str: if bhc_text is None: raise ValueError("bhc_text must not be None.") if not isinstance(bhc_text, str): - raise TypeError(f"bhc_text must be a string, got {type(bhc_text).__name__}.") + raise TypeError( + f"bhc_text must be a string, got {type(bhc_text).__name__}." + ) if not bhc_text.strip(): raise ValueError("bhc_text must be a non-empty string.") prompt = _SYSTEM_PROMPT + _PROMPT.format(bhc=bhc_text) pipe = self._get_pipeline() + eos_id = pipe.tokenizer.eos_token_id outputs = pipe( prompt, max_new_tokens=512, temperature=0.0, - eos_token_id=[pipe.tokenizer.eos_token_id], - pad_token_id=pipe.tokenizer.eos_token_id, + eos_token_id=eos_id, + pad_token_id=eos_id, return_full_text=False, ) # Output is a single text string - return outputs[0]["generated_text"].strip() \ No newline at end of file + return outputs[0]["generated_text"].strip() diff --git a/tests/core/test_bhc_to_avs.py b/tests/core/test_bhc_to_avs.py index 04c45fbf..e1951a57 100644 --- a/tests/core/test_bhc_to_avs.py +++ b/tests/core/test_bhc_to_avs.py @@ -1,36 +1,96 @@ +""" +Unit tests for the BHCToAVS model. + +These tests validate both the unit-level behavior of the predict method +(using a mocked pipeline) and an optional integration path that runs +against the real Hugging Face model when credentials are provided. +""" + +import os +import unittest +from unittest.mock import patch + from tests.base import BaseTestCase from pyhealth.models.bhc_to_avs import BHCToAVS +class _DummyPipeline: + """ + Lightweight mock pipeline used to simulate Hugging Face text generation. + + This avoids downloading models or requiring authentication during unit tests. + """ + + def __call__(self, prompt, **kwargs): + """Return a fixed, deterministic generated response.""" + return [ + { + "generated_text": "Your pain improved with supportive care and you were discharged in good condition." + } + ] + + class TestBHCToAVS(BaseTestCase): - """Unit tests for the BHCToAVS model.""" + """Unit and integration tests for the BHCToAVS model.""" def setUp(self): + """Set a deterministic random seed before each test.""" self.set_random_seed() - def test_predict(self): - """Test the predict method of BHCToAVS.""" + def test_predict_unit(self): + """ + Test the predict method using a mocked pipeline. + + This test verifies that: + - The model returns a string output + - The output is non-empty + - The output differs from the input text + """ + bhc_text = ( "Patient admitted with abdominal pain. Imaging showed no acute findings. " "Pain improved with supportive care and the patient was discharged in stable condition." ) - model = BHCToAVS() - try: + with patch.object(BHCToAVS, "_get_pipeline", return_value=_DummyPipeline()): + model = BHCToAVS() summary = model.predict(bhc_text) - # Output must be type str - self.assertIsInstance(summary, str) + # Output must be type str + self.assertIsInstance(summary, str) + + # Output should not be empty + self.assertGreater(len(summary.strip()), 0) + + # Output should be different from input + self.assertNotIn(bhc_text[:40], summary) + + @unittest.skipUnless( + os.getenv("RUN_BHC_TO_AVS_INTEGRATION") == "1" and os.getenv("HF_TOKEN"), + "Integration test disabled. Set RUN_BHC_TO_AVS_INTEGRATION=1 and HF_TOKEN to enable.", + ) + def test_predict_integration(self): + """ + Integration test for the BHCToAVS model. + + This test runs the full inference pipeline using the real Hugging Face model. + It requires the HF_TOKEN environment variable to be set and is skipped by default. + """ + + # For Mistral weights, you will need HF_TOKEN set in the environment. + bhc_text = ( + "Patient admitted with abdominal pain. Imaging showed no acute findings. " + "Pain improved with supportive care and the patient was discharged in stable condition." + ) + + model = BHCToAVS() + summary = model.predict(bhc_text) - # Output should not be empty - self.assertGreater(len(summary.strip()), 0) + # Output must be type str + self.assertIsInstance(summary, str) - # Output should be different from input - self.assertNotIn(bhc_text[:40], summary) + # Output should not be empty + self.assertGreater(len(summary.strip()), 0) - except OSError as e: - # Allow test to pass if model download fails on e.g. on GitHub workflows - if "gated repo" in str(e).lower() or "404" in str(e): - pass - else: - raise e + # Output should be different from input + self.assertNotIn(bhc_text[:40], summary) From 6afb92f5fbe8fe3e4ce6ef01b80ac892cbb14f0f Mon Sep 17 00:00:00 2001 From: charanw Date: Mon, 29 Dec 2025 12:52:43 -0600 Subject: [PATCH 08/11] Add __post_init__ to ensure BaseModel initialization Introduces a __post_init__ method in BHCToAVS to call the BaseModel initializer, ensuring proper nn.Module setup. Also updates docstring formatting and attribute documentation for clarity. --- pyhealth/models/bhc_to_avs.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pyhealth/models/bhc_to_avs.py b/pyhealth/models/bhc_to_avs.py index e15a7441..11b87de9 100644 --- a/pyhealth/models/bhc_to_avs.py +++ b/pyhealth/models/bhc_to_avs.py @@ -46,11 +46,15 @@ class BHCToAVS(BaseModel): """ BHCToAVS is a model class designed to generate After-Visit Summaries (AVS) from Brief Hospital Course (BHC) notes using a pre-trained base model and a LoRA adapter. + Attributes base_model_id : str The HuggingFace repository identifier for the base Mistral 7B model. adapter_model_id : str The HuggingFace repository identifier for the LoRA adapter weights. + hf_token : str | None + HuggingFace access token for gated repositories. + Methods _get_pipeline(): Creates and caches a HuggingFace text-generation pipeline using the base model @@ -61,13 +65,13 @@ class BHCToAVS(BaseModel): """ base_model_id: str = field(default="mistralai/Mistral-7B-Instruct-v0.3") - """HuggingFace repo containing the base Mistral 7B model.""" - adapter_model_id: str = field(default="williach31/mistral-7b-bhc-to-avs-lora") - """HuggingFace repo containing only LoRA adapter weights.""" - hf_token: str | None = None + def __post_init__(self): + # Ensure nn.Module (via BaseModel) is initialized + super().__init__() + def _resolve_token(self): return self.hf_token or os.getenv("HF_TOKEN") @@ -87,7 +91,6 @@ def _get_pipeline(self): " model = BHCToAVS()\n" ) - # Load base model base = AutoModelForCausalLM.from_pretrained( self.base_model_id, From 02e33e27080036997bb15abcd2ed2956b8e885f2 Mon Sep 17 00:00:00 2001 From: Charan <109322104+charanw@users.noreply.github.com> Date: Mon, 29 Dec 2025 13:03:31 -0600 Subject: [PATCH 09/11] Update docs/api/models/pyhealth.models.BHCToAVS.rst Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- docs/api/models/pyhealth.models.BHCToAVS.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/models/pyhealth.models.BHCToAVS.rst b/docs/api/models/pyhealth.models.BHCToAVS.rst index 59449318..5c8d197b 100644 --- a/docs/api/models/pyhealth.models.BHCToAVS.rst +++ b/docs/api/models/pyhealth.models.BHCToAVS.rst @@ -1,5 +1,5 @@ -pyhealth.models.bhc_to_avs -========================== +pyhealth.models.BHCToAVS +======================== BHCToAVS ------------------------------ From 982dfa1cfa6049e9a162d554695de5d6918f9f9b Mon Sep 17 00:00:00 2001 From: Charan <109322104+charanw@users.noreply.github.com> Date: Mon, 29 Dec 2025 13:03:42 -0600 Subject: [PATCH 10/11] Update pyhealth/models/bhc_to_avs.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- pyhealth/models/bhc_to_avs.py | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/pyhealth/models/bhc_to_avs.py b/pyhealth/models/bhc_to_avs.py index 11b87de9..3cac5385 100644 --- a/pyhealth/models/bhc_to_avs.py +++ b/pyhealth/models/bhc_to_avs.py @@ -47,21 +47,18 @@ class BHCToAVS(BaseModel): BHCToAVS is a model class designed to generate After-Visit Summaries (AVS) from Brief Hospital Course (BHC) notes using a pre-trained base model and a LoRA adapter. - Attributes - base_model_id : str - The HuggingFace repository identifier for the base Mistral 7B model. - adapter_model_id : str - The HuggingFace repository identifier for the LoRA adapter weights. - hf_token : str | None - HuggingFace access token for gated repositories. - - Methods - _get_pipeline(): - Creates and caches a HuggingFace text-generation pipeline using the base model - and LoRA adapter. - predict(bhc_text: str) -> str: - Generates a patient-friendly After-Visit Summary (AVS) from a given Brief - Hospital Course (BHC) note. + Attributes: + base_model_id (str): The HuggingFace repository identifier for the base + Mistral 7B model. + adapter_model_id (str): The HuggingFace repository identifier for the LoRA + adapter weights. + hf_token (str | None): HuggingFace access token for gated repositories. + + Methods: + _get_pipeline(): Creates and caches a HuggingFace text-generation pipeline + using the base model and LoRA adapter. + predict(bhc_text: str) -> str: Generates a patient-friendly After-Visit + Summary (AVS) from a given Brief Hospital Course (BHC) note. """ base_model_id: str = field(default="mistralai/Mistral-7B-Instruct-v0.3") From 4ad294b269573649bddc3be502516595f124a273 Mon Sep 17 00:00:00 2001 From: Charan <109322104+charanw@users.noreply.github.com> Date: Mon, 29 Dec 2025 13:04:07 -0600 Subject: [PATCH 11/11] Update pyhealth/models/bhc_to_avs.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- pyhealth/models/bhc_to_avs.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pyhealth/models/bhc_to_avs.py b/pyhealth/models/bhc_to_avs.py index 3cac5385..d12a2744 100644 --- a/pyhealth/models/bhc_to_avs.py +++ b/pyhealth/models/bhc_to_avs.py @@ -132,8 +132,6 @@ def predict(self, bhc_text: str) -> str: """ # Validate input to provide clear error messages and avoid unexpected failures. - if bhc_text is None: - raise ValueError("bhc_text must not be None.") if not isinstance(bhc_text, str): raise TypeError( f"bhc_text must be a string, got {type(bhc_text).__name__}."