Instructions to use lion-ai/medextractor-liquid with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use lion-ai/medextractor-liquid with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("token-classification", model="lion-ai/medextractor-liquid", trust_remote_code=True)# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("lion-ai/medextractor-liquid", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
MedExtractor Liquid
A 359M-parameter encoder that extracts user-defined fields from clinical and biomedical text. You pass a text and a list of fields (name, type, description). One forward pass returns, for every field, a span from the text or null; list fields return all matching spans.
- Zero-shot biomedical NER: on 15 corpora absent from training it averages 64.1 F1, level with a prompted Gemma 4 31B (64.0) at 1/87 of its size and 10.5 points above the best GLiNER model.
- Your own fields: handles field names and descriptions it was not trained on.
- Fast: about 545 clinical notes per second on one GPU: 8–14× the GLiNER models and about 60× Gemma 4 31B served with vLLM on the same card. On a CPU it takes about 0.3 s per note.
- One model for NER, extractive QA and slot filling, with the same interface.
Actual model output on a synthetic note: 12 user-defined fields filled with spans from the text, and one field the note does not mention returned as null.
Not a medical device. Trained and evaluated only on public datasets and synthetic notes, never on real patient records. Verify every output before using it in care.
Usage
from transformers import AutoModel
model = AutoModel.from_pretrained("lion-ai/medextractor-liquid", trust_remote_code=True) # add .to("cuda") for speed
note = ("A 67-year-old woman was admitted on 03/12/2025 with shortness of breath. Her mother had breast cancer. "
"Medications: metformin 850 mg twice daily, ramipril 5 mg in the morning. Atorvastatin was stopped because of muscle pain.")
fields = [
("age", "number", "patient age in years"),
("admission_date", "date", "date of admission"),
("current_drugs", "list[text]", "drugs the patient takes now"),
("stopped_drugs", "list[text]", "discontinued drugs"),
("ramipril_dose", "text", "dose of ramipril"),
("cancer", "text", "cancer of the patient (not relatives)"),
]
print(model.extract(note, fields))
# {"age": "67", "admission_date": "03/12/2025", "current_drugs": ["metformin", "ramipril"], "stopped_drugs": ["Atorvastatin"], "ramipril_dose": "5 mg", "cancer": null}
- Descriptions can be in any language and may state a span convention, for example
"protein, as the outermost (longest) mention". - Thresholds:
null_threshold(default 0.3) andlist_threshold(default 0.6). For NER with bare entity labels,list_threshold=0.3works better. - Spans:
with_spans=Trueadds character offsets, a score andp_null.
Model details
| Base model | LFM2.5-Encoder-350M with an extraction head |
| Parameters | 359M |
| Input | up to 2048 tokens and 24 fields per pass (longer texts are truncated) |
| Field types | text, number, date, duration, list[...] |
| Language | English |
Evaluation
All numbers are on locked test splits, scored once after every choice had been fixed on dev data. We ran every competitor ourselves on the same records. Full per-dataset tables and the protocol are in EVALUATION.md.
Zero-shot biomedical NER. The 15 corpora are absent from the training data. Each system gets the corpus entity types as labels, and the metric is strict span micro-F1. On four corpora the same frozen convention rules are applied to every system: the official BC2GM scorer, plus rules for JNLPBA, Linnaeus and AnatEM (see EVALUATION.md). Without these rules MedExtractor Liquid averages 60.8, against 52.5 for the best GLiNER model.
| Dataset | MedExtractor Nano | Gemma 4 31B | GLiNER-BioMed bi-large | GLiNER-BioMed large | gliner-bi-large v2.0 | gliner-bi-base v2.0 | gliner-bi-small v2.0 | GLiNER2 large |
|---|---|---|---|---|---|---|---|---|
| Parameters | 359M | 31.3B | 569M | 478M | 530M | 194M | 108M | 486M |
| AnatEM | 50.8 | 50.5 | 45.2 | 36.7 | 47.4 | 48.2 | 50.5 | 32.5 |
| BC2GM | 84.1 | 79.8 | 75.7 | 69.8 | 77.3 | 78.1 | 77.6 | 67.1 |
| BioInfer | 43.9 | 30.5 | 31.9 | 28.6 | 20.5 | 12.3 | 17.8 | 31.5 |
| BioNLP BB | 46.5 | 56.2 | 40.8 | 44.0 | 40.0 | 41.8 | 40.4 | 40.3 |
| BioNLP CG | 67.5 | 65.2 | 52.9 | 55.9 | 55.8 | 53.3 | 50.2 | 42.7 |
| BioNLP ID | 65.8 | 76.6 | 50.3 | 54.9 | 55.1 | 50.3 | 54.7 | 49.9 |
| BioNLP PC | 74.4 | 72.4 | 62.6 | 64.5 | 66.4 | 62.1 | 59.3 | 45.7 |
| CellFinder | 60.1 | 59.2 | 43.1 | 44.2 | 49.4 | 45.6 | 42.5 | 39.4 |
| CPI | 66.1 | 68.0 | 56.9 | 60.6 | 56.3 | 57.6 | 55.7 | 56.9 |
| JNLPBA | 62.7 | 57.5 | 63.5 | 52.2 | 61.7 | 57.1 | 58.5 | 50.2 |
| Linnaeus | 74.2 | 78.0 | 59.0 | 56.4 | 58.9 | 57.2 | 55.2 | 65.6 |
| miRNA | 71.7 | 77.0 | 61.9 | 69.5 | 61.8 | 47.5 | 47.1 | 57.0 |
| OSIRIS | 43.0 | 43.5 | 31.7 | 31.9 | 28.5 | 20.1 | 17.7 | 30.1 |
| PDR | 66.7 | 62.7 | 56.1 | 59.1 | 57.3 | 55.9 | 56.1 | 53.5 |
| ProGene | 83.5 | 83.0 | 62.8 | 67.7 | 67.0 | 66.1 | 63.9 | 61.5 |
| Average | 64.1 | 64.0 | 53.0 | 53.1 | 53.6 | 50.2 | 49.8 | 48.3 |
Clinical notes with user-defined fields (English notes; share of fields with a correct or overlapping value):
| Fields | MedExtractor Liquid | GLiNER2 large | Gemma 4 31B |
|---|---|---|---|
| Seen field kinds | 76.1 | 63.2 | 69.6 |
| Held-out field families | 60.6 | 45.0 | 78.8 |
Seen kinds also occur in our training data. Held-out families (smoking, physician and department, referral and follow-up) were never generated for training. The GLiNER-BioMed and gliner-bi models are not in this table: they are NER models that return every mention of an entity type, with no notion of one value per field or of an empty field.
Speed (500 synthetic clinical notes of about 310 tokens, 12 fields, one NVIDIA RTX PRO 6000; model loading excluded):
| Model | Parameters | Notes per second |
|---|---|---|
| MedExtractor Liquid | 359M | 545 |
| gliner-bi-large v2.0 | 530M | 67 |
| GLiNER-BioMed bi-large | 569M | 48 |
| GLiNER2 large | 486M | 40 |
| Gemma 4 31B (vLLM, FP8) | 31.3B | 9 |
Every encoder runs its library's batched inference with batch size 32; the GLiNER models get the 12 field descriptions as entity labels. Gemma runs with vLLM continuous batching. On a CPU (16 threads, AMD Threadripper PRO 7975WX), MedExtractor Liquid processes 3.5 notes per second.
Limitations
- On field families far from training, a prompted 31B LLM is clearly better (78.8 against 60.6).
- Without the convention rules, BC2GM, JNLPBA and AnatEM trail the best GLiNER model by 7–10 points. JNLPBA stays 0.8 below it even with them.
- The clinical evaluation uses synthetic notes only. The model has no real-world clinical validation.
Training
- Data: 1.25M records from 93 sources:
- public QA, NER, slot-filling, biomedical and clinical datasets;
- programmatic clinical notes;
- notes and annotations generated with Gemma 4 31B.
- Decontamination: texts that share a sentence with any evaluation split were removed. The evaluated corpora and held-out field families are not in training. Other human-annotated biomedical corpora with similar entity types are.
- Procedure: two-stage fine-tuning of encoder and head. The released weights average two seeds. Training ran on one NVIDIA RTX PRO 6000.
License
The weights are a derivative of LFM2.5-Encoder-350M under the LFM Open License v1.0 (LICENSE). Commercial use is licensed only for organisations below USD 10M annual revenue. The training data also includes non-commercial datasets (MultiNERD, the DDI corpus, parts of MRQA) and Gemma-generated data (Gemma terms of use), so treat this release as non-commercial / research use.
- Downloads last month
- 83
Model tree for lion-ai/medextractor-liquid
Base model
LiquidAI/LFM2.5-350M-Base