EDKG-DL 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.
Files changed (38) hide show
  1. edkg_dl-1.0.0/EDKG_DL.egg-info/PKG-INFO +91 -0
  2. edkg_dl-1.0.0/EDKG_DL.egg-info/SOURCES.txt +36 -0
  3. edkg_dl-1.0.0/EDKG_DL.egg-info/dependency_links.txt +1 -0
  4. edkg_dl-1.0.0/EDKG_DL.egg-info/entry_points.txt +3 -0
  5. edkg_dl-1.0.0/EDKG_DL.egg-info/requires.txt +19 -0
  6. edkg_dl-1.0.0/EDKG_DL.egg-info/top_level.txt +1 -0
  7. edkg_dl-1.0.0/LICENSE +36 -0
  8. edkg_dl-1.0.0/MANIFEST.in +1 -0
  9. edkg_dl-1.0.0/PKG-INFO +91 -0
  10. edkg_dl-1.0.0/README.md +52 -0
  11. edkg_dl-1.0.0/edkg_dl/__init__.py +46 -0
  12. edkg_dl-1.0.0/edkg_dl/__main__.py +6 -0
  13. edkg_dl-1.0.0/edkg_dl/api.py +211 -0
  14. edkg_dl-1.0.0/edkg_dl/cli.py +305 -0
  15. edkg_dl-1.0.0/edkg_dl/config.py +330 -0
  16. edkg_dl-1.0.0/edkg_dl/domain/__init__.py +18 -0
  17. edkg_dl-1.0.0/edkg_dl/domain/applicability.py +77 -0
  18. edkg_dl-1.0.0/edkg_dl/domain/causal_chains.py +139 -0
  19. edkg_dl-1.0.0/edkg_dl/domain/pathways.py +82 -0
  20. edkg_dl-1.0.0/edkg_dl/domain/sensitivity.py +75 -0
  21. edkg_dl-1.0.0/edkg_dl/exceptions.py +37 -0
  22. edkg_dl-1.0.0/edkg_dl/features/__init__.py +6 -0
  23. edkg_dl-1.0.0/edkg_dl/features/padel.py +87 -0
  24. edkg_dl-1.0.0/edkg_dl/http_api.py +166 -0
  25. edkg_dl-1.0.0/edkg_dl/hub.py +63 -0
  26. edkg_dl-1.0.0/edkg_dl/java.py +233 -0
  27. edkg_dl-1.0.0/edkg_dl/pipeline.py +255 -0
  28. edkg_dl-1.0.0/edkg_dl/predictors/__init__.py +6 -0
  29. edkg_dl-1.0.0/edkg_dl/predictors/gcn.py +264 -0
  30. edkg_dl-1.0.0/edkg_dl/predictors/registry.py +189 -0
  31. edkg_dl-1.0.0/edkg_dl/reporting/__init__.py +8 -0
  32. edkg_dl-1.0.0/edkg_dl/reporting/_files.py +56 -0
  33. edkg_dl-1.0.0/edkg_dl/reporting/ad_plot.py +136 -0
  34. edkg_dl-1.0.0/edkg_dl/reporting/excel_report.py +308 -0
  35. edkg_dl-1.0.0/edkg_dl/reporting/json_report.py +53 -0
  36. edkg_dl-1.0.0/edkg_dl/schemas.py +402 -0
  37. edkg_dl-1.0.0/pyproject.toml +108 -0
  38. edkg_dl-1.0.0/setup.cfg +4 -0
@@ -0,0 +1,91 @@
1
+ Metadata-Version: 2.4
2
+ Name: EDKG-DL
3
+ Version: 1.0.0
4
+ Summary: Deep Learning framework with causality-integrated Endocrine Disruption Knowledge Graph
5
+ Author-email: haoyuejudy <njutanhaoyue@nju.edu.cn>
6
+ License-Expression: LicenseRef-Custom-Academic-Research
7
+ Project-URL: Homepage, https://edkgdl.com/
8
+ Project-URL: Repository, https://github.com/haoyuejudy/EDKG-DL
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Topic :: Scientific/Engineering :: Chemistry
17
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: huggingface-hub>=0.32
22
+ Requires-Dist: joblib>=1.5.1
23
+ Requires-Dist: networkx>=3.1
24
+ Requires-Dist: numpy<3,>=1.26
25
+ Requires-Dist: padelpy>=0.1.16
26
+ Requires-Dist: pandas>=2.0
27
+ Requires-Dist: platformdirs>=4.3
28
+ Requires-Dist: requests>=2.31
29
+ Requires-Dist: scikit-learn>=1.6.1
30
+ Requires-Dist: torch>=2.0.0
31
+ Requires-Dist: torch-geometric>=2.4
32
+ Requires-Dist: xgboost>=3.0.2
33
+ Requires-Dist: xlsxwriter>=3.1
34
+ Provides-Extra: api
35
+ Requires-Dist: fastapi[standard]>=0.115; extra == "api"
36
+ Provides-Extra: plots
37
+ Requires-Dist: matplotlib>=3.8; extra == "plots"
38
+ Dynamic: license-file
39
+
40
+ # EDKG-DL
41
+
42
+ English | [简体中文](README_zh.md)
43
+
44
+ **D**eep **L**earning framework with causality-integrated **E**ndocrine **D**isruption **K**nowledge **G**raph. Predicts endocrine-disrupting effects (EDC), applicability domain (AD), and sensitive event pathways from compound SMILES using machine learning and an AOP network.
45
+
46
+ Pipeline: PaDEL 2D descriptors/fingerprints → qualitative/quantitative event-endpoint models → dual-track EDC classification (tabular model + graph neural network, GCN) → sensitive event and AOP pathway inference, producing JSON / Excel reports. Results are for research support only and must not replace experimental or regulatory conclusions.
47
+
48
+ ## Installation
49
+
50
+ Install from PyPI (Python ≥ 3.10):
51
+
52
+ ```bash
53
+ pip install edkg-dl
54
+ # or
55
+ uv add edkg-dl
56
+ ```
57
+
58
+ Optional extras: `pip install "edkg-dl[api]"` (HTTP service) and `pip install "edkg-dl[plots]"` (applicability-domain plots). See [installation docs](docs/en/installation.md) for details, including the automatic Temurin JRE download for PaDEL.
59
+
60
+ Model assets (~930 MB) are fetched automatically from [Hugging Face](https://huggingface.co/HaoyueTan/edkg-dl-models) on first use — no manual setup required.
61
+
62
+ ## Quick start
63
+
64
+ CLI:
65
+
66
+ ```bash
67
+ edkg-dl-predict "CCO" # JSON to stdout
68
+ edkg-dl-predict "CCO" -o runs/example --ad-plots # reports + PCA plots
69
+ edkg-dl-predict batch molecules.txt -o runs/batch # batch from a text file
70
+ ```
71
+
72
+ Python:
73
+
74
+ ```python
75
+ from edkg_dl import Predictor
76
+
77
+ predictor = Predictor.from_assets("./models")
78
+ result = predictor.predict("CCO")
79
+ ```
80
+
81
+ ## Documentation
82
+
83
+ | Topic | Link |
84
+ | --- | --- |
85
+ | Installation | [docs/en/installation.md](docs/en/installation.md) |
86
+ | Model assets | [docs/en/assets.md](docs/en/assets.md) |
87
+ | CLI usage | [docs/en/cli.md](docs/en/cli.md) |
88
+ | Python API | [docs/en/python-api.md](docs/en/python-api.md) |
89
+ | HTTP API | [docs/en/http-api.md](docs/en/http-api.md) |
90
+ | Output formats | [docs/en/output.md](docs/en/output.md) |
91
+ | Development | [docs/en/development.md](docs/en/development.md) |
@@ -0,0 +1,36 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ pyproject.toml
5
+ EDKG_DL.egg-info/PKG-INFO
6
+ EDKG_DL.egg-info/SOURCES.txt
7
+ EDKG_DL.egg-info/dependency_links.txt
8
+ EDKG_DL.egg-info/entry_points.txt
9
+ EDKG_DL.egg-info/requires.txt
10
+ EDKG_DL.egg-info/top_level.txt
11
+ edkg_dl/__init__.py
12
+ edkg_dl/__main__.py
13
+ edkg_dl/api.py
14
+ edkg_dl/cli.py
15
+ edkg_dl/config.py
16
+ edkg_dl/exceptions.py
17
+ edkg_dl/http_api.py
18
+ edkg_dl/hub.py
19
+ edkg_dl/java.py
20
+ edkg_dl/pipeline.py
21
+ edkg_dl/schemas.py
22
+ edkg_dl/domain/__init__.py
23
+ edkg_dl/domain/applicability.py
24
+ edkg_dl/domain/causal_chains.py
25
+ edkg_dl/domain/pathways.py
26
+ edkg_dl/domain/sensitivity.py
27
+ edkg_dl/features/__init__.py
28
+ edkg_dl/features/padel.py
29
+ edkg_dl/predictors/__init__.py
30
+ edkg_dl/predictors/gcn.py
31
+ edkg_dl/predictors/registry.py
32
+ edkg_dl/reporting/__init__.py
33
+ edkg_dl/reporting/_files.py
34
+ edkg_dl/reporting/ad_plot.py
35
+ edkg_dl/reporting/excel_report.py
36
+ edkg_dl/reporting/json_report.py
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ edkg-dl-api = edkg_dl.http_api:run
3
+ edkg-dl-predict = edkg_dl.cli:main
@@ -0,0 +1,19 @@
1
+ huggingface-hub>=0.32
2
+ joblib>=1.5.1
3
+ networkx>=3.1
4
+ numpy<3,>=1.26
5
+ padelpy>=0.1.16
6
+ pandas>=2.0
7
+ platformdirs>=4.3
8
+ requests>=2.31
9
+ scikit-learn>=1.6.1
10
+ torch>=2.0.0
11
+ torch-geometric>=2.4
12
+ xgboost>=3.0.2
13
+ xlsxwriter>=3.1
14
+
15
+ [api]
16
+ fastapi[standard]>=0.115
17
+
18
+ [plots]
19
+ matplotlib>=3.8
@@ -0,0 +1 @@
1
+ edkg_dl
edkg_dl-1.0.0/LICENSE ADDED
@@ -0,0 +1,36 @@
1
+ Custom Academic and Research Use License
2
+
3
+ Copyright (c) 2026 Nanjing University
4
+
5
+ All rights reserved.
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 use,
9
+ copy, and distribute the Software in unmodified form solely for non-commercial
10
+ educational and research purposes, subject to the following conditions:
11
+
12
+ 1. The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ 2. The Software must be distributed in its original, unmodified form. No
16
+ modification, adaptation, translation, reverse engineering, decompilation,
17
+ or disassembly of the Software is permitted.
18
+
19
+ 3. The Software may not be used for any commercial purpose, including but not
20
+ limited to use in a production environment, integration into a product for
21
+ sale or service, or use as part of a business operation.
22
+
23
+ 4. No derivative works based upon the Software are permitted.
24
+
25
+ 5. Any use of the Software outside the scope of non-commercial educational and
26
+ research purposes requires a separate commercial license, which may be
27
+ obtained by contacting the copyright holder (Nanjing University) or the
28
+ author.
29
+
30
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ prune test
edkg_dl-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,91 @@
1
+ Metadata-Version: 2.4
2
+ Name: EDKG-DL
3
+ Version: 1.0.0
4
+ Summary: Deep Learning framework with causality-integrated Endocrine Disruption Knowledge Graph
5
+ Author-email: haoyuejudy <njutanhaoyue@nju.edu.cn>
6
+ License-Expression: LicenseRef-Custom-Academic-Research
7
+ Project-URL: Homepage, https://edkgdl.com/
8
+ Project-URL: Repository, https://github.com/haoyuejudy/EDKG-DL
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Topic :: Scientific/Engineering :: Chemistry
17
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: huggingface-hub>=0.32
22
+ Requires-Dist: joblib>=1.5.1
23
+ Requires-Dist: networkx>=3.1
24
+ Requires-Dist: numpy<3,>=1.26
25
+ Requires-Dist: padelpy>=0.1.16
26
+ Requires-Dist: pandas>=2.0
27
+ Requires-Dist: platformdirs>=4.3
28
+ Requires-Dist: requests>=2.31
29
+ Requires-Dist: scikit-learn>=1.6.1
30
+ Requires-Dist: torch>=2.0.0
31
+ Requires-Dist: torch-geometric>=2.4
32
+ Requires-Dist: xgboost>=3.0.2
33
+ Requires-Dist: xlsxwriter>=3.1
34
+ Provides-Extra: api
35
+ Requires-Dist: fastapi[standard]>=0.115; extra == "api"
36
+ Provides-Extra: plots
37
+ Requires-Dist: matplotlib>=3.8; extra == "plots"
38
+ Dynamic: license-file
39
+
40
+ # EDKG-DL
41
+
42
+ English | [简体中文](README_zh.md)
43
+
44
+ **D**eep **L**earning framework with causality-integrated **E**ndocrine **D**isruption **K**nowledge **G**raph. Predicts endocrine-disrupting effects (EDC), applicability domain (AD), and sensitive event pathways from compound SMILES using machine learning and an AOP network.
45
+
46
+ Pipeline: PaDEL 2D descriptors/fingerprints → qualitative/quantitative event-endpoint models → dual-track EDC classification (tabular model + graph neural network, GCN) → sensitive event and AOP pathway inference, producing JSON / Excel reports. Results are for research support only and must not replace experimental or regulatory conclusions.
47
+
48
+ ## Installation
49
+
50
+ Install from PyPI (Python ≥ 3.10):
51
+
52
+ ```bash
53
+ pip install edkg-dl
54
+ # or
55
+ uv add edkg-dl
56
+ ```
57
+
58
+ Optional extras: `pip install "edkg-dl[api]"` (HTTP service) and `pip install "edkg-dl[plots]"` (applicability-domain plots). See [installation docs](docs/en/installation.md) for details, including the automatic Temurin JRE download for PaDEL.
59
+
60
+ Model assets (~930 MB) are fetched automatically from [Hugging Face](https://huggingface.co/HaoyueTan/edkg-dl-models) on first use — no manual setup required.
61
+
62
+ ## Quick start
63
+
64
+ CLI:
65
+
66
+ ```bash
67
+ edkg-dl-predict "CCO" # JSON to stdout
68
+ edkg-dl-predict "CCO" -o runs/example --ad-plots # reports + PCA plots
69
+ edkg-dl-predict batch molecules.txt -o runs/batch # batch from a text file
70
+ ```
71
+
72
+ Python:
73
+
74
+ ```python
75
+ from edkg_dl import Predictor
76
+
77
+ predictor = Predictor.from_assets("./models")
78
+ result = predictor.predict("CCO")
79
+ ```
80
+
81
+ ## Documentation
82
+
83
+ | Topic | Link |
84
+ | --- | --- |
85
+ | Installation | [docs/en/installation.md](docs/en/installation.md) |
86
+ | Model assets | [docs/en/assets.md](docs/en/assets.md) |
87
+ | CLI usage | [docs/en/cli.md](docs/en/cli.md) |
88
+ | Python API | [docs/en/python-api.md](docs/en/python-api.md) |
89
+ | HTTP API | [docs/en/http-api.md](docs/en/http-api.md) |
90
+ | Output formats | [docs/en/output.md](docs/en/output.md) |
91
+ | Development | [docs/en/development.md](docs/en/development.md) |
@@ -0,0 +1,52 @@
1
+ # EDKG-DL
2
+
3
+ English | [简体中文](README_zh.md)
4
+
5
+ **D**eep **L**earning framework with causality-integrated **E**ndocrine **D**isruption **K**nowledge **G**raph. Predicts endocrine-disrupting effects (EDC), applicability domain (AD), and sensitive event pathways from compound SMILES using machine learning and an AOP network.
6
+
7
+ Pipeline: PaDEL 2D descriptors/fingerprints → qualitative/quantitative event-endpoint models → dual-track EDC classification (tabular model + graph neural network, GCN) → sensitive event and AOP pathway inference, producing JSON / Excel reports. Results are for research support only and must not replace experimental or regulatory conclusions.
8
+
9
+ ## Installation
10
+
11
+ Install from PyPI (Python ≥ 3.10):
12
+
13
+ ```bash
14
+ pip install edkg-dl
15
+ # or
16
+ uv add edkg-dl
17
+ ```
18
+
19
+ Optional extras: `pip install "edkg-dl[api]"` (HTTP service) and `pip install "edkg-dl[plots]"` (applicability-domain plots). See [installation docs](docs/en/installation.md) for details, including the automatic Temurin JRE download for PaDEL.
20
+
21
+ Model assets (~930 MB) are fetched automatically from [Hugging Face](https://huggingface.co/HaoyueTan/edkg-dl-models) on first use — no manual setup required.
22
+
23
+ ## Quick start
24
+
25
+ CLI:
26
+
27
+ ```bash
28
+ edkg-dl-predict "CCO" # JSON to stdout
29
+ edkg-dl-predict "CCO" -o runs/example --ad-plots # reports + PCA plots
30
+ edkg-dl-predict batch molecules.txt -o runs/batch # batch from a text file
31
+ ```
32
+
33
+ Python:
34
+
35
+ ```python
36
+ from edkg_dl import Predictor
37
+
38
+ predictor = Predictor.from_assets("./models")
39
+ result = predictor.predict("CCO")
40
+ ```
41
+
42
+ ## Documentation
43
+
44
+ | Topic | Link |
45
+ | --- | --- |
46
+ | Installation | [docs/en/installation.md](docs/en/installation.md) |
47
+ | Model assets | [docs/en/assets.md](docs/en/assets.md) |
48
+ | CLI usage | [docs/en/cli.md](docs/en/cli.md) |
49
+ | Python API | [docs/en/python-api.md](docs/en/python-api.md) |
50
+ | HTTP API | [docs/en/http-api.md](docs/en/http-api.md) |
51
+ | Output formats | [docs/en/output.md](docs/en/output.md) |
52
+ | Development | [docs/en/development.md](docs/en/development.md) |
@@ -0,0 +1,46 @@
1
+ """EDC toxicity prediction and AOP pathway inference."""
2
+
3
+ from .api import BatchPredictionItem, BatchPredictionResult, Predictor
4
+ from .domain import CausalChainPolicy
5
+ from .exceptions import (
6
+ ArtifactIntegrityError,
7
+ ArtifactMissingError,
8
+ ConfigurationError,
9
+ EdkgDlError,
10
+ FeatureExtractionError,
11
+ InvalidSmilesError,
12
+ OutputExistsError,
13
+ PredictionError,
14
+ )
15
+ from .schemas import (
16
+ AOCandidate,
17
+ AOPRelation,
18
+ CausalChainResult,
19
+ EventPrediction,
20
+ PredictionResult,
21
+ SensitiveEvent,
22
+ )
23
+
24
+
25
+ __all__ = [
26
+ "AOCandidate",
27
+ "AOPRelation",
28
+ "ArtifactIntegrityError",
29
+ "ArtifactMissingError",
30
+ "BatchPredictionItem",
31
+ "BatchPredictionResult",
32
+ "ConfigurationError",
33
+ "CausalChainResult",
34
+ "CausalChainPolicy",
35
+ "EdkgDlError",
36
+ "EventPrediction",
37
+ "FeatureExtractionError",
38
+ "InvalidSmilesError",
39
+ "OutputExistsError",
40
+ "PredictionError",
41
+ "PredictionResult",
42
+ "Predictor",
43
+ "SensitiveEvent",
44
+ ]
45
+
46
+ __version__ = "1.0.0"
@@ -0,0 +1,6 @@
1
+ """Package CLI entry point via ``python -m edkg_dl``."""
2
+
3
+ from .cli import main
4
+
5
+
6
+ raise SystemExit(main())
@@ -0,0 +1,211 @@
1
+ """Stable public Python API."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Iterable
6
+ from concurrent.futures import ThreadPoolExecutor
7
+ from dataclasses import dataclass
8
+ from pathlib import Path
9
+ from typing import Any
10
+
11
+ from .config import ProjectPaths
12
+ from .domain import CausalChainPolicy
13
+ from .exceptions import EdkgDlError
14
+ from .hub import download_assets
15
+ from .pipeline import PredictionPipeline
16
+ from .schemas import PredictionResult
17
+
18
+
19
+ @dataclass(frozen=True)
20
+ class BatchPredictionItem:
21
+ """Success or error outcome for one input in a batch request."""
22
+
23
+ index: int
24
+ smiles: str
25
+ result: PredictionResult | None = None
26
+ error_code: str | None = None
27
+ error_message: str | None = None
28
+
29
+ def to_dict(self) -> dict[str, Any]:
30
+ """Serialize a single batch outcome.
31
+
32
+ Returns:
33
+ JSON-compatible batch outcome mapping.
34
+ """
35
+ return {
36
+ "index": self.index,
37
+ "smiles": self.smiles,
38
+ "ok": self.result is not None,
39
+ "result": None if self.result is None else self.result.to_dict(),
40
+ "error": None
41
+ if self.error_code is None
42
+ else {"code": self.error_code, "message": self.error_message},
43
+ }
44
+
45
+
46
+ @dataclass(frozen=True)
47
+ class BatchPredictionResult:
48
+ """Batch prediction result that preserves input order and tolerates partial failures."""
49
+
50
+ items: tuple[BatchPredictionItem, ...]
51
+
52
+ @property
53
+ def succeeded(self) -> int:
54
+ """Return the number of successfully predicted inputs."""
55
+ return sum(item.result is not None for item in self.items)
56
+
57
+ @property
58
+ def failed(self) -> int:
59
+ """Return the number of failed inputs."""
60
+ return len(self.items) - self.succeeded
61
+
62
+ def to_dict(self) -> dict[str, Any]:
63
+ """Serialize the complete batch result.
64
+
65
+ Returns:
66
+ JSON-compatible mapping with counts and per-item outcomes.
67
+ """
68
+ return {
69
+ "total": len(self.items),
70
+ "succeeded": self.succeeded,
71
+ "failed": self.failed,
72
+ "items": [item.to_dict() for item in self.items],
73
+ }
74
+
75
+
76
+ @dataclass
77
+ class Predictor:
78
+ """Reusable prediction facade that caches loaded endpoint models."""
79
+
80
+ pipeline: PredictionPipeline
81
+
82
+ @classmethod
83
+ def from_assets(
84
+ cls,
85
+ asset_dir: str | Path | None = None,
86
+ *,
87
+ max_paths: int = 1_000,
88
+ max_path_length: int | None = None,
89
+ causal_chain_policy: CausalChainPolicy | None = None,
90
+ ) -> Predictor:
91
+ """Create a reusable predictor from an external asset directory.
92
+
93
+ When the resolved asset directory does not contain ``settings.json``,
94
+ the assets are downloaded automatically from the Hugging Face Hub
95
+ into that directory (the per-user cache directory by default).
96
+
97
+ Args:
98
+ asset_dir: Directory containing settings and model artifacts.
99
+ max_paths: Maximum number of sensitive paths to return.
100
+ max_path_length: Maximum number of edges allowed per path;
101
+ unlimited when ``None``.
102
+ causal_chain_policy: Causal-chain validity evaluation policy.
103
+
104
+ Returns:
105
+ Predictor with a reusable pipeline and cached models.
106
+
107
+ Raises:
108
+ EdkgDlError: Raised when configuration or required assets are invalid,
109
+ or when a required automatic download fails.
110
+ """
111
+ paths = ProjectPaths.resolve(asset_dir)
112
+ if not paths.settings.is_file():
113
+ paths = ProjectPaths.resolve(download_assets(paths.asset_root))
114
+ pipeline = PredictionPipeline.from_paths(
115
+ paths,
116
+ max_paths=max_paths,
117
+ max_path_length=max_path_length,
118
+ causal_chain_policy=causal_chain_policy,
119
+ )
120
+ return cls(pipeline)
121
+
122
+ def predict(self, smiles: str) -> PredictionResult:
123
+ """Predict a single molecule.
124
+
125
+ Args:
126
+ smiles: SMILES string describing a single molecule.
127
+
128
+ Returns:
129
+ Complete structured prediction result.
130
+ """
131
+ return self.pipeline.predict(smiles)
132
+
133
+ def predict_many(self, smiles_values: Iterable[str]) -> list[PredictionResult]:
134
+ """Predict multiple molecules while reusing loaded artifacts.
135
+
136
+ Args:
137
+ smiles_values: Iterable of SMILES strings.
138
+
139
+ Returns:
140
+ Prediction results in input order.
141
+ """
142
+ return [self.predict(smiles) for smiles in smiles_values]
143
+
144
+ def predict_batch(
145
+ self,
146
+ smiles_values: Iterable[str],
147
+ *,
148
+ max_items: int = 100,
149
+ max_workers: int = 1,
150
+ ) -> BatchPredictionResult:
151
+ """Run a bounded batch prediction with per-item failure isolation.
152
+
153
+ Args:
154
+ smiles_values: Iterable of SMILES strings.
155
+ max_items: Maximum number of inputs allowed in one batch.
156
+ max_workers: Number of in-process concurrent worker threads.
157
+
158
+ Returns:
159
+ Per-item success or failure outcomes in input order.
160
+
161
+ Raises:
162
+ ValueError: Raised when batch or concurrency bounds are invalid.
163
+ """
164
+ values = list(smiles_values)
165
+ if max_items < 1:
166
+ raise ValueError("max_items must be at least 1")
167
+ if len(values) > max_items:
168
+ raise ValueError(f"batch size exceeds limit of {max_items}")
169
+ if max_workers < 1:
170
+ raise ValueError("max_workers must be at least 1")
171
+
172
+ if max_workers == 1:
173
+ items = tuple(
174
+ self._predict_batch_item(index, smiles) for index, smiles in enumerate(values)
175
+ )
176
+ else:
177
+ with ThreadPoolExecutor(max_workers=max_workers) as executor:
178
+ items = tuple(
179
+ executor.map(
180
+ lambda indexed: self._predict_batch_item(*indexed),
181
+ enumerate(values),
182
+ )
183
+ )
184
+ return BatchPredictionResult(items)
185
+
186
+ def _predict_batch_item(self, index: int, smiles: str) -> BatchPredictionItem:
187
+ """Catch prediction exceptions for one input and convert to a batch outcome.
188
+
189
+ Args:
190
+ index: Zero-based index of the input within the batch.
191
+ smiles: SMILES to predict.
192
+
193
+ Returns:
194
+ Single success outcome or structured error.
195
+ """
196
+ try:
197
+ return BatchPredictionItem(index=index, smiles=smiles, result=self.predict(smiles))
198
+ except EdkgDlError as exc:
199
+ return BatchPredictionItem(
200
+ index=index,
201
+ smiles=smiles,
202
+ error_code=exc.__class__.__name__,
203
+ error_message=str(exc),
204
+ )
205
+ except Exception: # noqa: BLE001 - batch isolation is an API guarantee.
206
+ return BatchPredictionItem(
207
+ index=index,
208
+ smiles=smiles,
209
+ error_code="InternalPredictionError",
210
+ error_message="unexpected prediction failure",
211
+ )