Feature Extraction
Transformers
Safetensors
chest2vec
text-embeddings
retrieval
radiology
chest
qwen
custom_code
Instructions to use chest2vec/chest2vec_4B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use chest2vec/chest2vec_4B with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("feature-extraction", model="chest2vec/chest2vec_4B", trust_remote_code=True)# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("chest2vec/chest2vec_4B", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
Upload README.md with huggingface_hub
Browse files
README.md
CHANGED
|
@@ -5,211 +5,69 @@ tags:
|
|
| 5 |
- radiology
|
| 6 |
- chest
|
| 7 |
- qwen
|
|
|
|
|
|
|
| 8 |
library_name: transformers
|
|
|
|
| 9 |
---
|
| 10 |
|
| 11 |
# chest2vec_4B
|
| 12 |
|
| 13 |
-
|
|
|
|
|
|
|
| 14 |
|
| 15 |
-
|
| 16 |
-
- **Inference helper**: `chest2vec.py`
|
| 17 |
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
## Model Architecture
|
| 21 |
-
|
| 22 |
-
Chest2Vec is a two-stage model:
|
| 23 |
-
1. **Base**: Qwen/Qwen3-Embedding-4B (downloaded at runtime)
|
| 24 |
-
2. **LoRA Adapter**: Contrastive LoRA adapter trained with multi-positive sigmoid loss
|
| 25 |
-
3. **Pooling**: Last-token pooling (EOS token) for global embeddings
|
| 26 |
-
|
| 27 |
-
The model produces **global embeddings only** (no section-specific embeddings).
|
| 28 |
-
|
| 29 |
-
## Installation
|
| 30 |
-
|
| 31 |
-
Install the package and all dependencies:
|
| 32 |
-
|
| 33 |
-
```bash
|
| 34 |
-
# Install PyTorch with CUDA 12.6 support
|
| 35 |
-
pip install torch==2.6.0 torchvision==0.21.0 torchaudio==2.6.0 --index-url https://download.pytorch.org/whl/cu126
|
| 36 |
-
|
| 37 |
-
# Install transformers and trl
|
| 38 |
-
pip install transformers==4.57.3 trl==0.9.3
|
| 39 |
-
|
| 40 |
-
# Install deepspeed
|
| 41 |
-
pip install deepspeed==0.16.9
|
| 42 |
-
|
| 43 |
-
# Install flash-attention
|
| 44 |
-
pip install https://github.com/Dao-AILab/flash-attention/releases/download/v2.8.3/flash_attn-2.8.3+cu12torch2.6cxx11abiTRUE-cp310-cp310-linux_x86_64.whl
|
| 45 |
-
|
| 46 |
-
# Install chest2vec package
|
| 47 |
-
pip install chest2vec
|
| 48 |
-
```
|
| 49 |
-
|
| 50 |
-
Or use the installation script:
|
| 51 |
-
|
| 52 |
-
```bash
|
| 53 |
-
bash install_deps.sh
|
| 54 |
-
```
|
| 55 |
-
|
| 56 |
-
## Requirements
|
| 57 |
-
|
| 58 |
-
This model **requires FlashAttention-2** (CUDA) by default, which is automatically installed with the package.
|
| 59 |
-
|
| 60 |
-
## Quickstart
|
| 61 |
-
|
| 62 |
-
### Installation + Loading
|
| 63 |
|
| 64 |
```python
|
| 65 |
-
from
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
```
|
| 70 |
|
| 71 |
-
##
|
| 72 |
-
|
| 73 |
-
```python
|
| 74 |
-
instructions = ["Find findings about the lungs."]
|
| 75 |
-
queries = ["Consolidation in the right lower lobe."]
|
| 76 |
-
|
| 77 |
-
out = m.embed_instruction_query(instructions, queries, max_len=512, batch_size=8)
|
| 78 |
-
|
| 79 |
-
# Global embedding (last-token pooling)
|
| 80 |
-
emb = out.embedding # [N, H]
|
| 81 |
-
```
|
| 82 |
|
| 83 |
-
|
| 84 |
|
| 85 |
```python
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
"Pleural effusion on the left.",
|
| 89 |
-
"Cardiomediastinal silhouette is normal."
|
| 90 |
-
]
|
| 91 |
-
|
| 92 |
-
cand_out = m.embed_texts(candidates, max_len=512, batch_size=16)
|
| 93 |
-
|
| 94 |
-
cand_emb = cand_out.embedding # [N, H]
|
| 95 |
```
|
| 96 |
|
| 97 |
-
|
| 98 |
|
| 99 |
-
|
| 100 |
-
# Query embeddings
|
| 101 |
-
q = out.embedding # [Nq, H]
|
| 102 |
|
| 103 |
-
|
| 104 |
-
|
| 105 |
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
# idx: [Nq, k] - indices of top-k candidates
|
| 110 |
|
| 111 |
-
|
| 112 |
-
print(f"Top-5 indices: {idx[0]}")
|
| 113 |
-
```
|
| 114 |
|
| 115 |
-
|
| 116 |
|
| 117 |
-
|
| 118 |
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
m = Chest2Vec.from_pretrained(
|
| 123 |
-
repo_id_or_path: str, # Hugging Face repo ID or local path
|
| 124 |
-
device: str = "cuda:0", # Device to load model on
|
| 125 |
-
use_4bit: bool = False, # Use 4-bit quantization
|
| 126 |
-
force_flash_attention_2: bool = True
|
| 127 |
-
)
|
| 128 |
-
```
|
| 129 |
|
| 130 |
-
##
|
| 131 |
-
|
| 132 |
-
Embed instruction-query pairs. Returns `EmbedOutput` with:
|
| 133 |
-
- `embedding`: `[N, H]` - global embeddings (L2-normalized, last-token pooling)
|
| 134 |
-
|
| 135 |
-
```python
|
| 136 |
-
out = m.embed_instruction_query(
|
| 137 |
-
instructions: List[str],
|
| 138 |
-
queries: List[str],
|
| 139 |
-
max_len: int = 512,
|
| 140 |
-
batch_size: int = 16
|
| 141 |
-
)
|
| 142 |
-
```
|
| 143 |
-
|
| 144 |
-
### `embed_texts()`
|
| 145 |
-
|
| 146 |
-
Embed plain texts (for document/candidate encoding).
|
| 147 |
-
|
| 148 |
-
```python
|
| 149 |
-
out = m.embed_texts(
|
| 150 |
-
texts: List[str],
|
| 151 |
-
max_len: int = 512,
|
| 152 |
-
batch_size: int = 16
|
| 153 |
-
)
|
| 154 |
-
```
|
| 155 |
-
|
| 156 |
-
Returns `EmbedOutput` with:
|
| 157 |
-
- `embedding`: `[N, H]` - global embeddings (L2-normalized, last-token pooling)
|
| 158 |
-
|
| 159 |
-
### `cosine_topk()`
|
| 160 |
-
|
| 161 |
-
Static method for efficient top-k cosine similarity search.
|
| 162 |
-
|
| 163 |
-
```python
|
| 164 |
-
scores, idx = Chest2Vec.cosine_topk(
|
| 165 |
-
query_emb: torch.Tensor, # [Nq, H]
|
| 166 |
-
cand_emb: torch.Tensor, # [Nd, H]
|
| 167 |
-
k: int = 10,
|
| 168 |
-
device: str = "cuda"
|
| 169 |
-
)
|
| 170 |
-
```
|
| 171 |
-
|
| 172 |
-
## Model Files
|
| 173 |
-
|
| 174 |
-
- `chest2vec.py` - Model class and inference utilities
|
| 175 |
-
- `chest2vec_config.json` - Model configuration
|
| 176 |
-
- `contrastive/` - LoRA adapter directory
|
| 177 |
-
- `adapter_config.json` - LoRA adapter configuration
|
| 178 |
-
- `adapter_model.safetensors` - LoRA adapter weights
|
| 179 |
-
|
| 180 |
-
## Citation
|
| 181 |
-
|
| 182 |
-
If you use this model, please cite:
|
| 183 |
-
|
| 184 |
-
```bibtex
|
| 185 |
-
@misc{chest2vec_4b_chest,
|
| 186 |
-
title={Chest2Vec: Global Embeddings for Chest X-Ray Reports},
|
| 187 |
-
author={Your Name},
|
| 188 |
-
year={2024},
|
| 189 |
-
howpublished={\url{https://huggingface.co/lukeingawesome/chest2vec_4b_chest}}
|
| 190 |
-
}
|
| 191 |
-
```
|
| 192 |
-
|
| 193 |
-
## License
|
| 194 |
-
|
| 195 |
-
[Specify your license here]
|
| 196 |
-
|
| 197 |
-
## Usage (🤗 transformers)
|
| 198 |
-
|
| 199 |
-
```python
|
| 200 |
-
from transformers import AutoModel
|
| 201 |
-
|
| 202 |
-
# base Qwen3-Embedding weights download automatically; needs trust_remote_code
|
| 203 |
-
model = AutoModel.from_pretrained("chest2vec/chest2vec_4B", trust_remote_code=True)
|
| 204 |
-
|
| 205 |
-
emb = model.embed_texts([
|
| 206 |
-
"Frontal chest radiograph. No focal consolidation. No pneumothorax. Heart size normal.",
|
| 207 |
-
])
|
| 208 |
-
emb # [N, H] L2-normalized report embedding (last-token / EOS pooling)
|
| 209 |
-
|
| 210 |
-
# similarity
|
| 211 |
-
(emb[0] @ emb[1]) # cosine similarity (rows are unit-norm)
|
| 212 |
-
```
|
| 213 |
|
| 214 |
-
|
| 215 |
-
|
|
|
|
| 5 |
- radiology
|
| 6 |
- chest
|
| 7 |
- qwen
|
| 8 |
+
base_model:
|
| 9 |
+
- Qwen/Qwen3-Embedding-4B
|
| 10 |
library_name: transformers
|
| 11 |
+
pipeline_tag: feature-extraction
|
| 12 |
---
|
| 13 |
|
| 14 |
# chest2vec_4B
|
| 15 |
|
| 16 |
+
Chest-radiology **text embedding** model: [`Qwen/Qwen3-Embedding-4B`](https://huggingface.co/Qwen/Qwen3-Embedding-4B)
|
| 17 |
+
contrastively LoRA-adapted for chest CT / CXR report retrieval. Embedding = left-padding-aware
|
| 18 |
+
last-token (EOS) pooling + L2-norm. **Embedding dim: 2560.**
|
| 19 |
|
| 20 |
+
## Self-contained `AutoModel`
|
|
|
|
| 21 |
|
| 22 |
+
The LoRA adapter is **merged into the weights** (`model.safetensors`) and the tokenizer is bundled,
|
| 23 |
+
so loading needs **no `chest2vec` package and no download of the base Qwen3-Embedding weights**:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
|
| 25 |
```python
|
| 26 |
+
from transformers import AutoModel, AutoTokenizer
|
| 27 |
+
model = AutoModel.from_pretrained("chest2vec/chest2vec_4B", trust_remote_code=True).eval()
|
| 28 |
+
tok = AutoTokenizer.from_pretrained("chest2vec/chest2vec_4B", trust_remote_code=True)
|
| 29 |
+
|
| 30 |
+
docs = ["Bibasilar atelectasis with small bilateral pleural effusions. Cardiomegaly."]
|
| 31 |
+
doc_emb = model.embed_texts(docs, tokenizer=tok) # [N, 2560], L2-normalized
|
| 32 |
+
|
| 33 |
+
# instruction-conditioned query
|
| 34 |
+
q_emb = model.embed_instruction_query(
|
| 35 |
+
"Retrieve the chest CT report that is similar to the given report.",
|
| 36 |
+
["pleural effusion and cardiomegaly"], tokenizer=tok)
|
| 37 |
+
vals, idx = model.cosine_topk(q_emb, doc_emb, k=5)
|
| 38 |
```
|
| 39 |
|
| 40 |
+
## Matryoshka embeddings
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
|
| 42 |
+
Matryoshka (MRL)-trained — truncate to **512** or **256** dims (keep first *N* dims, re-normalize):
|
| 43 |
|
| 44 |
```python
|
| 45 |
+
emb512 = model.embed_texts(docs, tokenizer=tok, dim=512)
|
| 46 |
+
emb256 = model.embed_texts(docs, tokenizer=tok, dim=256)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
```
|
| 48 |
|
| 49 |
+
Recommended dims: **2560 (full) · 512 · 256** (`config.matryoshka_dims`). Use the same `dim` for query and corpus.
|
| 50 |
|
| 51 |
+
## Recommended instructions
|
|
|
|
|
|
|
| 52 |
|
| 53 |
+
Instruction-conditioned (`Instruct: {instruction}\nQuery: {report}`). Apply to the **query** side;
|
| 54 |
+
embed the corpus without an instruction. Trained on chest **CT and CXR** across these families:
|
| 55 |
|
| 56 |
+
**Retrieval** — `Retrieve the chest CT report that is similar to the given report.` ·
|
| 57 |
+
`Retrieve the CXR report that is similar to the given report.` ·
|
| 58 |
+
`Retrieve the CXR report that is similar to the given report with prior reference omitted.`
|
|
|
|
| 59 |
|
| 60 |
+
**Summarization** — `Summarize the following chest CT report` · `Summarize the following CXR report` · `Summarize the given report.`
|
|
|
|
|
|
|
| 61 |
|
| 62 |
+
**Entity extraction (leaf)** — `Given the following chest CT report, extract the presence/absence of entities` · `Given the following CXR report, extract the presence/absence of entities`
|
| 63 |
|
| 64 |
+
**Entity extraction (upper/coarse)** — `Given the following chest CT report, extract the presence/absence of upper-level entities` · `Given the following CXR report, extract the presence/absence of upper class entities`
|
| 65 |
|
| 66 |
+
**Anatomy-specific** — `From the following chest {CT report | X-ray report}, extract and return only the findings related to {REGION}, ignoring all information about other structures.`
|
| 67 |
+
- CT regions: lungs · airways and trachea · pleura · mediastinum and hilum · cardiovascular system · chest wall · bones and spine · upper abdomen · lower neck
|
| 68 |
+
- CXR regions: lungs and airways · pleura · hila and mediastinum · cardiovascular system · musculoskeletal structures and chest wall · tubes, catheters, and support devices · abdomen
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
|
| 70 |
+
## Details
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
|
| 72 |
+
- **Base:** Qwen/Qwen3-Embedding-4B (Apache-2.0) — architecture rebuilt from the bundled config; merged weights loaded from this repo. Default attention `sdpa` (use `flash_attention_2` on Ampere+ for speed).
|
| 73 |
+
- Merged weights reproduce the original adapter-based embeddings to **cosine ≥ 0.999**.
|