RadGraph-IT 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- radgraph_it-1.0.0/.gitignore +36 -0
- radgraph_it-1.0.0/CHANGELOG.md +38 -0
- radgraph_it-1.0.0/LICENSE +23 -0
- radgraph_it-1.0.0/LICENSES/Third-Party.md +41 -0
- radgraph_it-1.0.0/PKG-INFO +159 -0
- radgraph_it-1.0.0/README.md +115 -0
- radgraph_it-1.0.0/pyproject.toml +146 -0
- radgraph_it-1.0.0/scripts/publish_model.py +219 -0
- radgraph_it-1.0.0/src/radgraphit/__init__.py +47 -0
- radgraph_it-1.0.0/src/radgraphit/api.py +168 -0
- radgraph_it-1.0.0/src/radgraphit/artifacts/__init__.py +5 -0
- radgraph_it-1.0.0/src/radgraphit/artifacts/manifest.py +290 -0
- radgraph_it-1.0.0/src/radgraphit/artifacts/registry.py +24 -0
- radgraph_it-1.0.0/src/radgraphit/artifacts/resolver.py +200 -0
- radgraph_it-1.0.0/src/radgraphit/cli.py +131 -0
- radgraph_it-1.0.0/src/radgraphit/core/__init__.py +1 -0
- radgraph_it-1.0.0/src/radgraphit/core/errors.py +46 -0
- radgraph_it-1.0.0/src/radgraphit/core/models.py +116 -0
- radgraph_it-1.0.0/src/radgraphit/inference/__init__.py +5 -0
- radgraph_it-1.0.0/src/radgraphit/inference/backends/__init__.py +1 -0
- radgraph_it-1.0.0/src/radgraphit/inference/backends/base.py +13 -0
- radgraph_it-1.0.0/src/radgraphit/inference/backends/dygie_v2/__init__.py +11 -0
- radgraph_it-1.0.0/src/radgraphit/inference/backends/dygie_v2/backend.py +32 -0
- radgraph_it-1.0.0/src/radgraphit/inference/backends/dygie_v2/device.py +46 -0
- radgraph_it-1.0.0/src/radgraphit/inference/backends/dygie_v2/feedforward.py +25 -0
- radgraph_it-1.0.0/src/radgraphit/inference/backends/dygie_v2/loader.py +165 -0
- radgraph_it-1.0.0/src/radgraphit/inference/backends/dygie_v2/model.py +101 -0
- radgraph_it-1.0.0/src/radgraphit/inference/backends/dygie_v2/ner_head.py +75 -0
- radgraph_it-1.0.0/src/radgraphit/inference/backends/dygie_v2/pruner.py +27 -0
- radgraph_it-1.0.0/src/radgraphit/inference/backends/dygie_v2/relation_head.py +147 -0
- radgraph_it-1.0.0/src/radgraphit/inference/backends/dygie_v2/span_extractor.py +51 -0
- radgraph_it-1.0.0/src/radgraphit/inference/backends/dygie_v2/spans.py +20 -0
- radgraph_it-1.0.0/src/radgraphit/inference/backends/dygie_v2/tokenizer_embedder.py +123 -0
- radgraph_it-1.0.0/src/radgraphit/inference/backends/dygie_v2/transformer_block.py +62 -0
- radgraph_it-1.0.0/src/radgraphit/inference/backends/dygie_v2/vocab.py +123 -0
- radgraph_it-1.0.0/src/radgraphit/inference/decoder.py +53 -0
- radgraph_it-1.0.0/src/radgraphit/inference/service.py +80 -0
- radgraph_it-1.0.0/src/radgraphit/inference/tokenizer.py +60 -0
- radgraph_it-1.0.0/src/radgraphit/py.typed +0 -0
- radgraph_it-1.0.0/src/radgraphit/serialization/__init__.py +15 -0
- radgraph_it-1.0.0/src/radgraphit/serialization/radgraph_xl.py +135 -0
- radgraph_it-1.0.0/tests/fixtures/README.md +6 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.eggs/
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
.venv/
|
|
9
|
+
venv/
|
|
10
|
+
.mypy_cache/
|
|
11
|
+
.ruff_cache/
|
|
12
|
+
.pytest_cache/
|
|
13
|
+
.coverage
|
|
14
|
+
htmlcov/
|
|
15
|
+
coverage.xml
|
|
16
|
+
|
|
17
|
+
# Model artifacts / weights / data — MUST NOT be committed.
|
|
18
|
+
# The model bundle (config.json, vocab.json, model_manifest.json, best.pt / model.safetensors)
|
|
19
|
+
# lives on the Hugging Face Hub, never in this repository.
|
|
20
|
+
*.pt
|
|
21
|
+
*.pth
|
|
22
|
+
*.bin
|
|
23
|
+
*.safetensors
|
|
24
|
+
*.tar.gz
|
|
25
|
+
/models/
|
|
26
|
+
/artifacts/
|
|
27
|
+
/data/
|
|
28
|
+
|
|
29
|
+
# Local caches
|
|
30
|
+
.hf_cache/
|
|
31
|
+
.radgraphit_cache/
|
|
32
|
+
|
|
33
|
+
# OS / editor
|
|
34
|
+
.DS_Store
|
|
35
|
+
.idea/
|
|
36
|
+
.vscode/
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project
|
|
5
|
+
adheres to [Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
- Pin the model bundle and encoder to immutable Hugging Face commit revisions.
|
|
11
|
+
- Require a checksum-backed manifest for every local and remote model bundle.
|
|
12
|
+
- Download only manifest-declared bundle files and construct the encoder without redundant
|
|
13
|
+
pretrained-weight downloads.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- Harden manifest paths, checksums, schema/version parsing, and encoder consistency checks.
|
|
17
|
+
- Normalize checkpoint, vocabulary, I/O, and inference failures into the public error hierarchy.
|
|
18
|
+
- Run the real pinned checkpoint against a committed synthetic golden output in CI.
|
|
19
|
+
- Align pre-commit, Python 3.13 coverage, CLI input validation, and documented cache size.
|
|
20
|
+
|
|
21
|
+
## [1.0.0]
|
|
22
|
+
|
|
23
|
+
First public release.
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
- Public Python API `radgraphit.RadGraphIT`: `from_pretrained()` (Hugging Face Hub),
|
|
27
|
+
`from_local()` (local bundle), and direct lazy construction; `predict()` accepts a string or a
|
|
28
|
+
sequence of strings and preserves input order; `predictor(...)` is an alias of `predict()`.
|
|
29
|
+
- Output in the canonical **RadGraph-XL** dictionary format: stable entity ordering, deterministic
|
|
30
|
+
relation ordering, no dangling edges.
|
|
31
|
+
- Italian RadGraph-XL compatibility tokenizer (exact equivalent of
|
|
32
|
+
`radgraph_xl_preprocess_report`).
|
|
33
|
+
- `dygie_v2` inference backend: pure-PyTorch port of the Italian v2 model (shared encoder, span
|
|
34
|
+
extractor, NER head, relation head), on CPU or CUDA.
|
|
35
|
+
- Automatic anonymous model download from the public Hugging Face Hub repository
|
|
36
|
+
(`radgraphIT/Radgraph-IT-v1`), cached after the first use.
|
|
37
|
+
- CLI `radgraphit predict`: reports as arguments, from `--input-file` (one per line), or from
|
|
38
|
+
stdin; JSON output on stdout.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Daniel Rabottini (therabo)
|
|
4
|
+
Copyright (c) 2026 Edoardo Avenia (edoardoavenia)
|
|
5
|
+
Copyright (c) 2026 Rocco Angelella (roccoangelella)
|
|
6
|
+
|
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
in the Software without restriction, including without limitation the rights
|
|
10
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
furnished to do so, subject to the following conditions:
|
|
13
|
+
|
|
14
|
+
The above copyright notice and this permission notice shall be included in all
|
|
15
|
+
copies or substantial portions of the Software.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
|
+
SOFTWARE.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Third-Party
|
|
2
|
+
|
|
3
|
+
This file collects provenance and attributions. It does **not** declare weights, datasets, or
|
|
4
|
+
clinical texts redistributable, and it does **not** automatically copy any third-party license. The
|
|
5
|
+
package code itself is licensed under MIT (see the root `LICENSE` file); this file concerns the
|
|
6
|
+
third-party components it builds on.
|
|
7
|
+
|
|
8
|
+
## RadGraph-XL output format and serializer
|
|
9
|
+
|
|
10
|
+
The output dictionary and the serialization logic (`postprocess_reports` / `get_entity`) derive from
|
|
11
|
+
the official **RadGraph / RadGraph-XL** package from Stanford AIMI / StanfordMIMI.
|
|
12
|
+
|
|
13
|
+
- Upstream repository: `radgraph` package (Stanford), distributed under the MIT license.
|
|
14
|
+
|
|
15
|
+
Citation:
|
|
16
|
+
|
|
17
|
+
> Delbrouck et al. "RadGraph-XL: A Large-Scale Expert-Annotated Dataset for Entity and Relation
|
|
18
|
+
> Extraction from Radiology Reports." Findings of the ACL 2024, pp. 12902–12915.
|
|
19
|
+
> https://aclanthology.org/2024.findings-acl.765
|
|
20
|
+
|
|
21
|
+
## Inference backend (`dygie_v2`)
|
|
22
|
+
|
|
23
|
+
An inference-only PyTorch port of the Italian v2 model (internal project "RadGraph-XL-IT",
|
|
24
|
+
`training_v2`), which is itself a pure-PyTorch reimplementation of the DyGIE++ architecture
|
|
25
|
+
(NER + relations) without AllenNLP.
|
|
26
|
+
|
|
27
|
+
- DyGIE / DyGIE++ architecture: Wadden et al., "Entity, Relation, and Event Extraction with
|
|
28
|
+
Contextualized Span Representations", EMNLP 2019.
|
|
29
|
+
- Pre-trained encoder: fetched at runtime from the Hugging Face Hub (e.g. `IVN-RIN/medBIT-r3-plus`);
|
|
30
|
+
subject to the license of its own repository on the Hub. Not redistributed by this package.
|
|
31
|
+
|
|
32
|
+
## Model, weights, and data
|
|
33
|
+
|
|
34
|
+
The model weights, the datasets, and any clinical text are **not** included in this repository or in
|
|
35
|
+
the wheel/sdist, and are not declared redistributable. The model bundle is hosted separately on the
|
|
36
|
+
Hugging Face Hub and is subject to the licenses/terms declared in that repository.
|
|
37
|
+
|
|
38
|
+
## Runtime dependencies
|
|
39
|
+
|
|
40
|
+
`torch`, `transformers`, `nltk`, `huggingface_hub` are subject to their respective licenses
|
|
41
|
+
(BSD-3-Clause, Apache-2.0, Apache-2.0, Apache-2.0 respectively, unless changed upstream).
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: RadGraph-IT
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: RadGraph graph inference for Italian radiology reports, with output in the canonical RadGraph-XL format.
|
|
5
|
+
Project-URL: Homepage, https://github.com/therabo/RadGraph-IT
|
|
6
|
+
Project-URL: Repository, https://github.com/therabo/RadGraph-IT
|
|
7
|
+
Project-URL: Issues, https://github.com/therabo/RadGraph-IT/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/therabo/RadGraph-IT/blob/main/CHANGELOG.md
|
|
9
|
+
Author: Daniel Rabottini, Edoardo Avenia, Rocco Angelella
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
License-File: LICENSES/Third-Party.md
|
|
13
|
+
Keywords: information-extraction,italian,nlp,radgraph,radiology
|
|
14
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
15
|
+
Classifier: Intended Audience :: Healthcare Industry
|
|
16
|
+
Classifier: Intended Audience :: Science/Research
|
|
17
|
+
Classifier: Natural Language :: Italian
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
25
|
+
Classifier: Typing :: Typed
|
|
26
|
+
Requires-Python: >=3.10
|
|
27
|
+
Requires-Dist: huggingface-hub>=0.23
|
|
28
|
+
Requires-Dist: nltk>=3.8
|
|
29
|
+
Requires-Dist: packaging>=23
|
|
30
|
+
Requires-Dist: torch>=2.1
|
|
31
|
+
Requires-Dist: transformers>=4.39
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
34
|
+
Requires-Dist: mypy>=1.11; extra == 'dev'
|
|
35
|
+
Requires-Dist: pre-commit>=3.5; extra == 'dev'
|
|
36
|
+
Requires-Dist: pytest-cov>=5; extra == 'dev'
|
|
37
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
38
|
+
Requires-Dist: ruff==0.16.0; extra == 'dev'
|
|
39
|
+
Requires-Dist: safetensors>=0.4; extra == 'dev'
|
|
40
|
+
Requires-Dist: twine>=5; extra == 'dev'
|
|
41
|
+
Provides-Extra: safetensors
|
|
42
|
+
Requires-Dist: safetensors>=0.4; extra == 'safetensors'
|
|
43
|
+
Description-Content-Type: text/markdown
|
|
44
|
+
|
|
45
|
+
# RadGraph-IT 🇮🇹
|
|
46
|
+
|
|
47
|
+
**RadGraph** graph inference for **Italian** radiology reports, with output in the canonical
|
|
48
|
+
**RadGraph-XL** format.
|
|
49
|
+
|
|
50
|
+
`radgraphit` takes one or more Italian radiology reports, runs the Italian DyGIE v2 model
|
|
51
|
+
(PyTorch: shared encoder, span extractor, NER head, and relation head), and returns the graph of
|
|
52
|
+
entities and relations as the RadGraph-XL-compatible dictionary.
|
|
53
|
+
|
|
54
|
+
- **Package / import / CLI name:** `radgraphit` · **Python:** `>= 3.10` · **Device:** CPU or CUDA
|
|
55
|
+
- **Model:** downloaded automatically from pinned Hugging Face revisions on first use
|
|
56
|
+
(~445 MB / 424 MiB plus small tokenizer/config files, then cached)
|
|
57
|
+
|
|
58
|
+
## Installation
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pip install radgraphit
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Usage — Python API
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from radgraphit import RadGraphIT
|
|
68
|
+
|
|
69
|
+
predictor = RadGraphIT()
|
|
70
|
+
annotations = predictor.predict(
|
|
71
|
+
"Non si evidenziano segni di pneumotorace dopo la rimozione del drenaggio toracico."
|
|
72
|
+
)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`predict` accepts a **string** or a **sequence of strings** and preserves order.
|
|
76
|
+
`predictor(report)` is an alias for `predictor.predict(report)`:
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
annotations = predictor(["referto 1", "referto 2"]) # batch, order preserved
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Usage — CLI
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
# report as an argument
|
|
86
|
+
radgraphit predict "Non si evidenzia pneumotorace."
|
|
87
|
+
|
|
88
|
+
# from a file (one report per line), or from stdin
|
|
89
|
+
radgraphit predict --input-file reports.txt
|
|
90
|
+
echo "Nessuna evidenza di pneumotorace." | radgraphit predict
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The result is written as JSON to stdout.
|
|
94
|
+
|
|
95
|
+
## Output
|
|
96
|
+
|
|
97
|
+
For the input `["Non si evidenzia pneumotorace ..."]` the output has this shape (top-level keys
|
|
98
|
+
`"0"`, `"1"`, … in input order):
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
{
|
|
102
|
+
"0": {
|
|
103
|
+
"text": "<normalized tokens, space-separated>",
|
|
104
|
+
"entities": {
|
|
105
|
+
"1": {
|
|
106
|
+
"tokens": "<span tokens>",
|
|
107
|
+
"label": "Observation::definitely absent",
|
|
108
|
+
"start_ix": 3,
|
|
109
|
+
"end_ix": 3,
|
|
110
|
+
"relations": [["located_at", "2"]],
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
"data_source": None,
|
|
114
|
+
"data_split": "inference",
|
|
115
|
+
},
|
|
116
|
+
"1": {"...": "..."},
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
- The indices (`start_ix`, `end_ix`) are **token-level, zero-based, and inclusive**.
|
|
121
|
+
- Relations are directed *source → target* lists `[label, target_entity_id]`.
|
|
122
|
+
- The output is deterministic: entities and relations are stably ordered.
|
|
123
|
+
|
|
124
|
+
## Citation
|
|
125
|
+
|
|
126
|
+
The output format and the serializer derive from the official **RadGraph / RadGraph-XL** package
|
|
127
|
+
(see [`Third-Party`](LICENSES/Third-Party.md)). If you use this package, please cite
|
|
128
|
+
both this work and the RadGraph-XL paper:
|
|
129
|
+
|
|
130
|
+
```bibtex
|
|
131
|
+
@software{radgraphit,
|
|
132
|
+
author = "Daniel Rabottini and Edoardo Avenia and Rocco Angelella",
|
|
133
|
+
title = "{RadGraph-IT}: {RadGraph} graph inference for {Italian} radiology reports",
|
|
134
|
+
year = "2026",
|
|
135
|
+
version = "1.0.0",
|
|
136
|
+
url = "https://github.com/therabo/RadGraph-IT",
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
```bibtex
|
|
141
|
+
@inproceedings{delbrouck-etal-2024-radgraph,
|
|
142
|
+
title = "{R}ad{G}raph-{XL}: A Large-Scale Expert-Annotated Dataset for Entity and Relation
|
|
143
|
+
Extraction from Radiology Reports",
|
|
144
|
+
author = "Delbrouck, Jean-Benoit and Chambon, Pierre and Chen, Zhihong and Varma, Maya and
|
|
145
|
+
Johnston, Andrew and Blankemeier, Louis and Van Veen, Dave and Bui, Tan and
|
|
146
|
+
Truong, Steven and Langlotz, Curtis",
|
|
147
|
+
booktitle = "Findings of the Association for Computational Linguistics ACL 2024",
|
|
148
|
+
year = "2024",
|
|
149
|
+
url = "https://aclanthology.org/2024.findings-acl.765",
|
|
150
|
+
pages = "12902--12915",
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## License
|
|
155
|
+
|
|
156
|
+
See the [`MIT License`](LICENSE) and [`Third-Party`](LICENSES/Third-Party.md) notices.
|
|
157
|
+
|
|
158
|
+
> **Not a medical device.** The output is an automatic extraction of entities and relations from
|
|
159
|
+
> text and does not constitute a diagnosis, a report, or a clinical opinion.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# RadGraph-IT 🇮🇹
|
|
2
|
+
|
|
3
|
+
**RadGraph** graph inference for **Italian** radiology reports, with output in the canonical
|
|
4
|
+
**RadGraph-XL** format.
|
|
5
|
+
|
|
6
|
+
`radgraphit` takes one or more Italian radiology reports, runs the Italian DyGIE v2 model
|
|
7
|
+
(PyTorch: shared encoder, span extractor, NER head, and relation head), and returns the graph of
|
|
8
|
+
entities and relations as the RadGraph-XL-compatible dictionary.
|
|
9
|
+
|
|
10
|
+
- **Package / import / CLI name:** `radgraphit` · **Python:** `>= 3.10` · **Device:** CPU or CUDA
|
|
11
|
+
- **Model:** downloaded automatically from pinned Hugging Face revisions on first use
|
|
12
|
+
(~445 MB / 424 MiB plus small tokenizer/config files, then cached)
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install radgraphit
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage — Python API
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
from radgraphit import RadGraphIT
|
|
24
|
+
|
|
25
|
+
predictor = RadGraphIT()
|
|
26
|
+
annotations = predictor.predict(
|
|
27
|
+
"Non si evidenziano segni di pneumotorace dopo la rimozione del drenaggio toracico."
|
|
28
|
+
)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`predict` accepts a **string** or a **sequence of strings** and preserves order.
|
|
32
|
+
`predictor(report)` is an alias for `predictor.predict(report)`:
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
annotations = predictor(["referto 1", "referto 2"]) # batch, order preserved
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Usage — CLI
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# report as an argument
|
|
42
|
+
radgraphit predict "Non si evidenzia pneumotorace."
|
|
43
|
+
|
|
44
|
+
# from a file (one report per line), or from stdin
|
|
45
|
+
radgraphit predict --input-file reports.txt
|
|
46
|
+
echo "Nessuna evidenza di pneumotorace." | radgraphit predict
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The result is written as JSON to stdout.
|
|
50
|
+
|
|
51
|
+
## Output
|
|
52
|
+
|
|
53
|
+
For the input `["Non si evidenzia pneumotorace ..."]` the output has this shape (top-level keys
|
|
54
|
+
`"0"`, `"1"`, … in input order):
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
{
|
|
58
|
+
"0": {
|
|
59
|
+
"text": "<normalized tokens, space-separated>",
|
|
60
|
+
"entities": {
|
|
61
|
+
"1": {
|
|
62
|
+
"tokens": "<span tokens>",
|
|
63
|
+
"label": "Observation::definitely absent",
|
|
64
|
+
"start_ix": 3,
|
|
65
|
+
"end_ix": 3,
|
|
66
|
+
"relations": [["located_at", "2"]],
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"data_source": None,
|
|
70
|
+
"data_split": "inference",
|
|
71
|
+
},
|
|
72
|
+
"1": {"...": "..."},
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
- The indices (`start_ix`, `end_ix`) are **token-level, zero-based, and inclusive**.
|
|
77
|
+
- Relations are directed *source → target* lists `[label, target_entity_id]`.
|
|
78
|
+
- The output is deterministic: entities and relations are stably ordered.
|
|
79
|
+
|
|
80
|
+
## Citation
|
|
81
|
+
|
|
82
|
+
The output format and the serializer derive from the official **RadGraph / RadGraph-XL** package
|
|
83
|
+
(see [`Third-Party`](LICENSES/Third-Party.md)). If you use this package, please cite
|
|
84
|
+
both this work and the RadGraph-XL paper:
|
|
85
|
+
|
|
86
|
+
```bibtex
|
|
87
|
+
@software{radgraphit,
|
|
88
|
+
author = "Daniel Rabottini and Edoardo Avenia and Rocco Angelella",
|
|
89
|
+
title = "{RadGraph-IT}: {RadGraph} graph inference for {Italian} radiology reports",
|
|
90
|
+
year = "2026",
|
|
91
|
+
version = "1.0.0",
|
|
92
|
+
url = "https://github.com/therabo/RadGraph-IT",
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
```bibtex
|
|
97
|
+
@inproceedings{delbrouck-etal-2024-radgraph,
|
|
98
|
+
title = "{R}ad{G}raph-{XL}: A Large-Scale Expert-Annotated Dataset for Entity and Relation
|
|
99
|
+
Extraction from Radiology Reports",
|
|
100
|
+
author = "Delbrouck, Jean-Benoit and Chambon, Pierre and Chen, Zhihong and Varma, Maya and
|
|
101
|
+
Johnston, Andrew and Blankemeier, Louis and Van Veen, Dave and Bui, Tan and
|
|
102
|
+
Truong, Steven and Langlotz, Curtis",
|
|
103
|
+
booktitle = "Findings of the Association for Computational Linguistics ACL 2024",
|
|
104
|
+
year = "2024",
|
|
105
|
+
url = "https://aclanthology.org/2024.findings-acl.765",
|
|
106
|
+
pages = "12902--12915",
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## License
|
|
111
|
+
|
|
112
|
+
See the [`MIT License`](LICENSE) and [`Third-Party`](LICENSES/Third-Party.md) notices.
|
|
113
|
+
|
|
114
|
+
> **Not a medical device.** The output is an automatic extraction of entities and relations from
|
|
115
|
+
> text and does not constitute a diagnosis, a report, or a clinical opinion.
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.27"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "RadGraph-IT"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "RadGraph graph inference for Italian radiology reports, with output in the canonical RadGraph-XL format."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE", "LICENSES/Third-Party.md"]
|
|
13
|
+
authors = [
|
|
14
|
+
{ name = "Daniel Rabottini" },
|
|
15
|
+
{ name = "Edoardo Avenia" },
|
|
16
|
+
{ name = "Rocco Angelella" },
|
|
17
|
+
]
|
|
18
|
+
keywords = [
|
|
19
|
+
"radiology",
|
|
20
|
+
"nlp",
|
|
21
|
+
"information-extraction",
|
|
22
|
+
"radgraph",
|
|
23
|
+
"italian",
|
|
24
|
+
]
|
|
25
|
+
classifiers = [
|
|
26
|
+
"Development Status :: 5 - Production/Stable",
|
|
27
|
+
"Intended Audience :: Science/Research",
|
|
28
|
+
"Intended Audience :: Healthcare Industry",
|
|
29
|
+
"Natural Language :: Italian",
|
|
30
|
+
"Operating System :: OS Independent",
|
|
31
|
+
"Programming Language :: Python :: 3",
|
|
32
|
+
"Programming Language :: Python :: 3.10",
|
|
33
|
+
"Programming Language :: Python :: 3.11",
|
|
34
|
+
"Programming Language :: Python :: 3.12",
|
|
35
|
+
"Programming Language :: Python :: 3.13",
|
|
36
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
37
|
+
"Typing :: Typed",
|
|
38
|
+
# License is declared via the SPDX 'license' field (PEP 639); no legacy "License ::" classifier.
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
# Minimal runtime footprint: the encoder backend (torch + transformers), the compatibility
|
|
42
|
+
# tokenizer (nltk), and the standard model download path (huggingface_hub). Nothing else.
|
|
43
|
+
dependencies = [
|
|
44
|
+
"torch>=2.1",
|
|
45
|
+
"transformers>=4.39",
|
|
46
|
+
"nltk>=3.8",
|
|
47
|
+
"huggingface_hub>=0.23",
|
|
48
|
+
"packaging>=23",
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
[project.optional-dependencies]
|
|
52
|
+
# Safer future weight format; the current v2 checkpoint is a .pt.
|
|
53
|
+
safetensors = ["safetensors>=0.4"]
|
|
54
|
+
dev = [
|
|
55
|
+
"pytest>=8",
|
|
56
|
+
"pytest-cov>=5",
|
|
57
|
+
"ruff==0.16.0",
|
|
58
|
+
"mypy>=1.11",
|
|
59
|
+
"build>=1.2",
|
|
60
|
+
"twine>=5",
|
|
61
|
+
"safetensors>=0.4",
|
|
62
|
+
"pre-commit>=3.5",
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
[project.urls]
|
|
66
|
+
Homepage = "https://github.com/therabo/RadGraph-IT"
|
|
67
|
+
Repository = "https://github.com/therabo/RadGraph-IT"
|
|
68
|
+
Issues = "https://github.com/therabo/RadGraph-IT/issues"
|
|
69
|
+
Changelog = "https://github.com/therabo/RadGraph-IT/blob/main/CHANGELOG.md"
|
|
70
|
+
|
|
71
|
+
[project.scripts]
|
|
72
|
+
radgraphit = "radgraphit.cli:main"
|
|
73
|
+
|
|
74
|
+
[tool.hatch.build.targets.wheel]
|
|
75
|
+
packages = ["src/radgraphit"]
|
|
76
|
+
|
|
77
|
+
[tool.hatch.build.targets.sdist]
|
|
78
|
+
# Keep the distribution lean: ship the package, notices, changelog, and maintainer manifest tool.
|
|
79
|
+
# Never ship weights, datasets, or clinical text (there are none in the tree anyway).
|
|
80
|
+
include = [
|
|
81
|
+
"src/radgraphit",
|
|
82
|
+
"LICENSE",
|
|
83
|
+
"README.md",
|
|
84
|
+
"CHANGELOG.md",
|
|
85
|
+
"LICENSES",
|
|
86
|
+
"scripts/publish_model.py",
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
[tool.ruff]
|
|
90
|
+
line-length = 100
|
|
91
|
+
target-version = "py310"
|
|
92
|
+
src = ["src", "tests"]
|
|
93
|
+
|
|
94
|
+
[tool.ruff.lint]
|
|
95
|
+
select = ["E", "F", "W", "I", "UP", "B", "C4", "SIM", "PTH", "RUF"]
|
|
96
|
+
ignore = [
|
|
97
|
+
"B008", # function call in default argument — intentional for registry defaults
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
[tool.ruff.lint.per-file-ignores]
|
|
101
|
+
"src/radgraphit/inference/backends/dygie_v2/*" = ["N812"]
|
|
102
|
+
|
|
103
|
+
[tool.ruff.lint.isort]
|
|
104
|
+
known-first-party = ["radgraphit"]
|
|
105
|
+
|
|
106
|
+
[tool.mypy]
|
|
107
|
+
# Assume 3.12 so mypy can parse the installed third-party stubs (numpy, pulled in via torch, ships
|
|
108
|
+
# PEP 695 `type` statements that don't parse under a 3.10 target). The real >=3.10 floor is enforced
|
|
109
|
+
# by ruff (target-version = "py310") and by the CI test matrix (3.10/3.11/3.12).
|
|
110
|
+
python_version = "3.12"
|
|
111
|
+
strict = true
|
|
112
|
+
warn_unused_configs = true
|
|
113
|
+
files = ["src/radgraphit"]
|
|
114
|
+
# torch/transformers/nltk/huggingface_hub ship incomplete or no stubs; don't fail typecheck on
|
|
115
|
+
# their missing type information (our own code stays fully typed).
|
|
116
|
+
[[tool.mypy.overrides]]
|
|
117
|
+
module = [
|
|
118
|
+
"transformers.*",
|
|
119
|
+
"nltk.*",
|
|
120
|
+
"huggingface_hub.*",
|
|
121
|
+
"safetensors.*",
|
|
122
|
+
]
|
|
123
|
+
ignore_missing_imports = true
|
|
124
|
+
|
|
125
|
+
[[tool.mypy.overrides]]
|
|
126
|
+
# The vendored/adapted DyGIE-v2 backend is a faithful port of upstream PyTorch modules; hold it
|
|
127
|
+
# to import-time typing but relax the strictest rules that fight idiomatic nn.Module code.
|
|
128
|
+
module = ["radgraphit.inference.backends.dygie_v2.*"]
|
|
129
|
+
disallow_any_generics = false
|
|
130
|
+
warn_return_any = false
|
|
131
|
+
|
|
132
|
+
[tool.pytest.ini_options]
|
|
133
|
+
minversion = "8.0"
|
|
134
|
+
testpaths = ["tests"]
|
|
135
|
+
addopts = "-ra"
|
|
136
|
+
markers = [
|
|
137
|
+
"integration: opt-in tests that require a real v2 checkpoint (see RADGRAPHIT_TEST_MODEL_DIR).",
|
|
138
|
+
]
|
|
139
|
+
|
|
140
|
+
[tool.coverage.run]
|
|
141
|
+
branch = true
|
|
142
|
+
source = ["radgraphit"]
|
|
143
|
+
|
|
144
|
+
[tool.coverage.report]
|
|
145
|
+
fail_under = 80
|
|
146
|
+
show_missing = true
|