annotuneagent 0.1.0__tar.gz → 0.1.1__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.
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/CHANGELOG.md +19 -3
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/CITATION.cff +1 -1
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/PKG-INFO +23 -7
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/README.md +20 -5
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/docs/index.md +8 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/docs/installation.md +10 -10
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/docs/quickstart.md +4 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/docs/tutorials/index.md +12 -1
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/docs/tutorials/load_model.ipynb +8 -7
- annotuneagent-0.1.1/docs/tutorials/report.md +126 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/pyproject.toml +2 -1
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/__init__.py +6 -3
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/_version.py +1 -1
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/decide.py +40 -7
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/local_lora.py +215 -35
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/workflow.py +20 -5
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent.egg-info/SOURCES.txt +1 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/tests/test_cli.py +7 -6
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/tests/test_decide.py +14 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/tests/test_local_lora.py +130 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/tests/test_version.py +2 -2
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/tests/test_workflow.py +43 -1
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/.github/workflows/publish.yml +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/.github/workflows/tests.yml +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/.gitignore +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/.readthedocs.yaml +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/LICENSE +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/MANIFEST.in +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/SECURITY.md +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/docs/_static/css/custom.css +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/docs/_templates/README.md +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/docs/api/index.md +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/docs/conf.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/docs/marker_sources.md +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/docs/requirements.txt +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/docs/tutorials/pbmc8k_annotation.ipynb +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/setup.cfg +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/__main__.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/annotate.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/arbitrate.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/cli.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/evaluate.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/evidence.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/granularity/__init__.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/granularity/cl_dag.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/granularity/ontology_map.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/granularity/relations.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/hypotheses.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/marker_plot.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/markers.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/markers.tsv +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/mltools.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/ontology/cl_isa.json +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/ontology/granularity_policy.yaml +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/ontology/ontology_map.jsonl +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/prepare.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/py.typed +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/read.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/tokenizer/LICENSE +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/tokenizer/merges.txt +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/tokenizer/tokenizer.json +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/tokenizer/tokenizer_config.json +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/tokenizer/vocab.json +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/src/annotuneagent/votes.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/tests/test_annotate.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/tests/test_evaluate.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/tests/test_evidence.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/tests/test_granularity.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/tests/test_markers.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/tests/test_mltools.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/tests/test_prepare.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/tests/test_read.py +0 -0
- {annotuneagent-0.1.0 → annotuneagent-0.1.1}/tests/test_votes.py +0 -0
|
@@ -4,10 +4,26 @@ All notable changes to this project are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## [0.1.1] - 2026-11-09
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- A running server is checked with `/props` and `/lora-adapters` when `/proc`
|
|
12
|
+
is unavailable, so Windows and macOS can reuse a server this package did
|
|
13
|
+
not start.
|
|
14
|
+
- A `TaskEndpoint` URL calls `/completion` and enables one LoRA adapter for
|
|
15
|
+
that request. When `maxlen` is omitted, name allows 2048 tokens and ML
|
|
16
|
+
allows 8192. An ML prompt does not fit in the name limit.
|
|
17
|
+
- A model request waits 600 seconds. `ANNOTUNE_TIMEOUT` or the `timeout`
|
|
18
|
+
argument overrides it. Health checks stay at 2 seconds.
|
|
19
|
+
- On Windows, a process check does not call `os.kill`.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
8
22
|
|
|
9
|
-
-
|
|
10
|
-
|
|
23
|
+
- The load-model tutorial points Windows users to
|
|
24
|
+
[AnnoTuneLoader](https://github.com/leelieber2025/AnnoTuneLoader).
|
|
25
|
+
- A tutorial explains each field of the `run` report. The `Queries` paragraph
|
|
26
|
+
is text to paste into another model.
|
|
11
27
|
|
|
12
28
|
## [0.1.0] - 2026-11-09
|
|
13
29
|
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: annotuneagent
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: Cluster-level cell-type annotation from marker, name, and ML results
|
|
5
5
|
Author-email: "Zhao Li (李钊)" <leelieber@gmail.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
7
7
|
Project-URL: Homepage, https://github.com/leelieber2025/AnnoTuneAgent
|
|
8
|
-
Project-URL: Documentation, https://
|
|
8
|
+
Project-URL: Documentation, https://annotuneagent.readthedocs.io/
|
|
9
9
|
Project-URL: Changelog, https://github.com/leelieber2025/AnnoTuneAgent/blob/main/CHANGELOG.md
|
|
10
10
|
Project-URL: Source, https://github.com/leelieber2025/AnnoTuneAgent
|
|
11
11
|
Project-URL: Issues, https://github.com/leelieber2025/AnnoTuneAgent/issues
|
|
12
12
|
Project-URL: PyPI, https://pypi.org/project/annotuneagent/
|
|
13
|
+
Project-URL: Zenodo, https://doi.org/10.5281/zenodo.24092828
|
|
13
14
|
Keywords: single-cell,RNA-seq,cell type annotation,marker genes,bioinformatics
|
|
14
15
|
Classifier: Development Status :: 3 - Alpha
|
|
15
16
|
Classifier: Intended Audience :: Science/Research
|
|
@@ -52,11 +53,15 @@ Dynamic: license-file
|
|
|
52
53
|
|
|
53
54
|
# AnnoTuneAgent
|
|
54
55
|
|
|
56
|
+
[](https://pypi.org/project/annotuneagent/)
|
|
57
|
+
[](https://pepy.tech/project/annotuneagent)
|
|
58
|
+
[](https://pypi.org/project/annotuneagent/)
|
|
59
|
+
[](https://annotuneagent.readthedocs.io/en/latest/?badge=latest)
|
|
60
|
+
[](https://github.com/leelieber2025/AnnoTuneAgent/actions/workflows/tests.yml)
|
|
55
61
|
[](LICENSE)
|
|
56
|
-
[](https://app.readthedocs.org/projects/annotuneagent/)
|
|
62
|
+
[](https://doi.org/10.5281/zenodo.24092828)
|
|
58
63
|
|
|
59
|
-
Documentation: [Read the Docs](https://
|
|
64
|
+
Documentation: [Read the Docs](https://annotuneagent.readthedocs.io/en/latest/).
|
|
60
65
|
|
|
61
66
|
**Cluster-level cell-type annotation for single-cell RNA-seq, with two
|
|
62
67
|
fine-tuned language models that run locally.**
|
|
@@ -127,7 +132,13 @@ Harmony, and Scanorama. If you select one that is missing, `prepare` prints
|
|
|
127
132
|
the install command and leaves the matrix unchanged. See
|
|
128
133
|
[Installation](docs/installation.md).
|
|
129
134
|
|
|
130
|
-
From a checkout:
|
|
135
|
+
From a checkout:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
git clone https://github.com/leelieber2025/AnnoTuneAgent.git
|
|
139
|
+
cd AnnoTuneAgent
|
|
140
|
+
pip install -e ".[dev]"
|
|
141
|
+
```
|
|
131
142
|
|
|
132
143
|
## First run
|
|
133
144
|
|
|
@@ -196,7 +207,12 @@ The tokenizer is installed with the package. See
|
|
|
196
207
|
|
|
197
208
|
## Status
|
|
198
209
|
|
|
199
|
-
**0.1.
|
|
210
|
+
**0.1.1 (Alpha).** Import as `import annotuneagent as ata`.
|
|
211
|
+
|
|
212
|
+
## Citation
|
|
213
|
+
|
|
214
|
+
For the software record, cite the [Zenodo DOI](https://doi.org/10.5281/zenodo.24092828).
|
|
215
|
+
Pin the package version used in the analysis, for example `annotuneagent==0.1.1`.
|
|
200
216
|
|
|
201
217
|
## License
|
|
202
218
|
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
# AnnoTuneAgent
|
|
2
2
|
|
|
3
|
+
[](https://pypi.org/project/annotuneagent/)
|
|
4
|
+
[](https://pepy.tech/project/annotuneagent)
|
|
5
|
+
[](https://pypi.org/project/annotuneagent/)
|
|
6
|
+
[](https://annotuneagent.readthedocs.io/en/latest/?badge=latest)
|
|
7
|
+
[](https://github.com/leelieber2025/AnnoTuneAgent/actions/workflows/tests.yml)
|
|
3
8
|
[](LICENSE)
|
|
4
|
-
[](https://app.readthedocs.org/projects/annotuneagent/)
|
|
9
|
+
[](https://doi.org/10.5281/zenodo.24092828)
|
|
6
10
|
|
|
7
|
-
Documentation: [Read the Docs](https://
|
|
11
|
+
Documentation: [Read the Docs](https://annotuneagent.readthedocs.io/en/latest/).
|
|
8
12
|
|
|
9
13
|
**Cluster-level cell-type annotation for single-cell RNA-seq, with two
|
|
10
14
|
fine-tuned language models that run locally.**
|
|
@@ -75,7 +79,13 @@ Harmony, and Scanorama. If you select one that is missing, `prepare` prints
|
|
|
75
79
|
the install command and leaves the matrix unchanged. See
|
|
76
80
|
[Installation](docs/installation.md).
|
|
77
81
|
|
|
78
|
-
From a checkout:
|
|
82
|
+
From a checkout:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
git clone https://github.com/leelieber2025/AnnoTuneAgent.git
|
|
86
|
+
cd AnnoTuneAgent
|
|
87
|
+
pip install -e ".[dev]"
|
|
88
|
+
```
|
|
79
89
|
|
|
80
90
|
## First run
|
|
81
91
|
|
|
@@ -144,7 +154,12 @@ The tokenizer is installed with the package. See
|
|
|
144
154
|
|
|
145
155
|
## Status
|
|
146
156
|
|
|
147
|
-
**0.1.
|
|
157
|
+
**0.1.1 (Alpha).** Import as `import annotuneagent as ata`.
|
|
158
|
+
|
|
159
|
+
## Citation
|
|
160
|
+
|
|
161
|
+
For the software record, cite the [Zenodo DOI](https://doi.org/10.5281/zenodo.24092828).
|
|
162
|
+
Pin the package version used in the analysis, for example `annotuneagent==0.1.1`.
|
|
148
163
|
|
|
149
164
|
## License
|
|
150
165
|
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# AnnoTuneAgent Documentation
|
|
2
2
|
|
|
3
|
+
[](https://pypi.org/project/annotuneagent/)
|
|
4
|
+
[](https://pepy.tech/project/annotuneagent)
|
|
5
|
+
[](https://pypi.org/project/annotuneagent/)
|
|
6
|
+
[](https://github.com/leelieber2025/AnnoTuneAgent/actions/workflows/tests.yml)
|
|
7
|
+
[](https://github.com/leelieber2025/AnnoTuneAgent/blob/main/LICENSE)
|
|
8
|
+
[](https://doi.org/10.5281/zenodo.24092828)
|
|
9
|
+
|
|
3
10
|
AnnoTuneAgent annotates clustered scRNA-seq. `prepare` runs QC, gene
|
|
4
11
|
selection, and Leiden clustering. `run` collects three results for each
|
|
5
12
|
cluster: a marker score, a name-model result, and an ML-model result. A
|
|
@@ -52,6 +59,7 @@ scFair supplies the gene list and the resolution is half of its suggestion.
|
|
|
52
59
|
| {doc}`installation`, {doc}`quickstart` | Install, then a first call |
|
|
53
60
|
| {doc}`tutorials/pbmc8k_annotation` | PBMC 8k: `prepare`, then the name and ML models |
|
|
54
61
|
| {doc}`tutorials/load_model` | Download the weights and run a local or remote model server |
|
|
62
|
+
| {doc}`tutorials/report` | What each part of the `run` report is for, including the text to paste |
|
|
55
63
|
| {doc}`api/index` | Function signatures |
|
|
56
64
|
| {doc}`marker_sources` | Marker reference sources and verification decisions |
|
|
57
65
|
|
|
@@ -6,14 +6,21 @@ Python 3.10–3.13.
|
|
|
6
6
|
pip install annotuneagent
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
From a checkout, `pip install -e .` installs this tree instead.
|
|
10
|
-
|
|
11
9
|
```python
|
|
12
10
|
import annotuneagent as ata
|
|
13
11
|
print(ata.__version__)
|
|
14
12
|
```
|
|
15
13
|
|
|
16
|
-
The version is set in `src/annotuneagent/_version.py` (currently **0.1.
|
|
14
|
+
The version is set in `src/annotuneagent/_version.py` (currently **0.1.1**).
|
|
15
|
+
|
|
16
|
+
From a checkout:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
git clone https://github.com/leelieber2025/AnnoTuneAgent.git
|
|
20
|
+
cd AnnoTuneAgent
|
|
21
|
+
pip install -e ".[dev]"
|
|
22
|
+
pip install -e ".[docs]"
|
|
23
|
+
```
|
|
17
24
|
|
|
18
25
|
## Dependencies
|
|
19
26
|
|
|
@@ -32,13 +39,6 @@ package. These are optional:
|
|
|
32
39
|
If you select an optional method and its package is missing, `prepare` prints
|
|
33
40
|
the install command and leaves the matrix unchanged. ComBat is part of Scanpy.
|
|
34
41
|
|
|
35
|
-
Other extras:
|
|
36
|
-
|
|
37
|
-
```bash
|
|
38
|
-
pip install -e ".[docs]" # build this documentation from a checkout
|
|
39
|
-
pip install -e ".[dev]" # pytest and ruff
|
|
40
|
-
```
|
|
41
|
-
|
|
42
42
|
## Model weights
|
|
43
43
|
|
|
44
44
|
The GGUF weights are not in the Python package. Download them from the
|
|
@@ -184,6 +184,10 @@ panel, not to each gene separately.
|
|
|
184
184
|
and UMAP and dotplot calls. Edit the order or labels and rerun the snippet to
|
|
185
185
|
regenerate the plots.
|
|
186
186
|
|
|
187
|
+
{doc}`tutorials/report` explains every report field. The printed `Queries`
|
|
188
|
+
block is text to paste into another model. The heading is the local note.
|
|
189
|
+
The paragraph under it is the question.
|
|
190
|
+
|
|
187
191
|
A Cell Ontology id is the exact map row for the written label. An unreviewed id
|
|
188
192
|
is marked pending.
|
|
189
193
|
|
|
@@ -5,10 +5,11 @@ figures and the UMAP. `run` collects the marker score, the name-model result,
|
|
|
5
5
|
and the ML-model result, and writes the title. The model server stays loaded
|
|
6
6
|
between calls.
|
|
7
7
|
|
|
8
|
-
|
|
|
8
|
+
| Page | Contents |
|
|
9
9
|
|----------|----------|
|
|
10
10
|
| {doc}`pbmc8k_annotation` | Public PBMC 8k: `prepare`, then the name and ML models |
|
|
11
11
|
| {doc}`load_model` | Download the weights, then use a local server or connect to a remote one |
|
|
12
|
+
| {doc}`report` | What each part of the `run` report is for, including the text to paste |
|
|
12
13
|
|
|
13
14
|
{doc}`pbmc8k_annotation` uses the public 10x PBMC 8k count matrix (7,750 cells),
|
|
14
15
|
not the Scanpy PBMC 3k set. The matrix contains cells only, so AmbiDose is off.
|
|
@@ -42,6 +43,15 @@ Run a local server at `http://127.0.0.1:8080`, or connect to a remote one.
|
|
|
42
43
|
Needs GGUF files or a running server
|
|
43
44
|
:::
|
|
44
45
|
|
|
46
|
+
:::{grid-item-card} Read the report
|
|
47
|
+
:link: report
|
|
48
|
+
:link-type: doc
|
|
49
|
+
|
|
50
|
+
The `Queries` block is text to paste into another model.
|
|
51
|
+
+++
|
|
52
|
+
No extra install
|
|
53
|
+
:::
|
|
54
|
+
|
|
45
55
|
::::
|
|
46
56
|
|
|
47
57
|
```{toctree}
|
|
@@ -50,4 +60,5 @@ Needs GGUF files or a running server
|
|
|
50
60
|
|
|
51
61
|
pbmc8k_annotation
|
|
52
62
|
load_model
|
|
63
|
+
report
|
|
53
64
|
```
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"| | Use it when |\n",
|
|
13
13
|
"|---|---|\n",
|
|
14
14
|
"| Local | You download the weights and run `llama-server` on this computer |\n",
|
|
15
|
-
"| Remote |
|
|
15
|
+
"| Remote | One `llama-server` is already running with both adapters |\n",
|
|
16
16
|
"\n",
|
|
17
17
|
"With `models`, the marker score, the name model, and the ML model each return a result. A judgment reads the three results and writes the title. The title is a dictionary name. The name model copies a cell-type name from the marker dictionary. The ML model is trained on machine-learning measurements of the cluster, differential expression and marker-panel statistics, and copies a candidate name. A cluster can stay unnamed. Without `models`, only the marker score is collected."
|
|
18
18
|
]
|
|
@@ -36,7 +36,9 @@
|
|
|
36
36
|
"|---|---|\n",
|
|
37
37
|
"| Linux with an NVIDIA GPU | Supported. Steps below. |\n",
|
|
38
38
|
"| macOS (Apple silicon or Intel) | Supported. Use the macOS steps below. The Metal build uses the GPU automatically. |\n",
|
|
39
|
-
"| Windows |
|
|
39
|
+
"| Windows | This package does not start `llama-server`. Use [AnnoTuneLoader](https://github.com/leelieber2025/AnnoTuneLoader). |\n",
|
|
40
|
+
"\n",
|
|
41
|
+
"On Windows, download [AnnoTuneLoader.exe](https://github.com/leelieber2025/AnnoTuneLoader/raw/main/AnnoTuneLoader.exe) and double-click it. Choose the base, the name adapter, and the ML adapter. The server listens at `http://127.0.0.1:8080`. Leave the window open while you annotate. On that computer, `local_models(model_root)` reuses the server when those three files match. Another computer uses the Remote section below.\n",
|
|
40
42
|
"\n",
|
|
41
43
|
"**Linux, CUDA 12.8.** Unpack the server and the CUDA runtime next to each other.\n",
|
|
42
44
|
"\n",
|
|
@@ -202,7 +204,7 @@
|
|
|
202
204
|
"source": [
|
|
203
205
|
"## Remote\n",
|
|
204
206
|
"\n",
|
|
205
|
-
"Use this when
|
|
207
|
+
"Use this when one `llama-server` is already running with both adapters, including one started by [AnnoTuneLoader](https://github.com/leelieber2025/AnnoTuneLoader) on another machine. Point both tasks at that server. Each request calls `/completion` and enables one adapter. No local GGUF files are required. Name prompts must fit in 2048 tokens. ML prompts must fit in 8192. Those limits apply when `maxlen` is omitted."
|
|
206
208
|
]
|
|
207
209
|
},
|
|
208
210
|
{
|
|
@@ -214,11 +216,10 @@
|
|
|
214
216
|
"source": [
|
|
215
217
|
"import annotuneagent as ata\n",
|
|
216
218
|
"\n",
|
|
217
|
-
"
|
|
218
|
-
"ml_url = \"http://ML_HOST:8080\"\n",
|
|
219
|
+
"server = \"http://SERVER:8080\"\n",
|
|
219
220
|
"models = ata.ModelChain(\n",
|
|
220
|
-
" name=ata.TaskEndpoint(url=
|
|
221
|
-
" ml=ata.TaskEndpoint(url=
|
|
221
|
+
" name=ata.TaskEndpoint(url=server),\n",
|
|
222
|
+
" ml=ata.TaskEndpoint(url=server),\n",
|
|
222
223
|
")"
|
|
223
224
|
]
|
|
224
225
|
},
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Read the report
|
|
2
|
+
|
|
3
|
+
`run` returns a dictionary and prints a `Queries` block. Each block is one
|
|
4
|
+
cluster that still has a question: it has no title, or the title is written
|
|
5
|
+
and `hint` is set. AnnoTuneAgent does not send this text to the name model,
|
|
6
|
+
the ML model, or any other service. Copy the paragraph under the heading and
|
|
7
|
+
paste it into another model.
|
|
8
|
+
|
|
9
|
+
## The heading
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
cluster 0 monocyte no marker passed
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The three fields are the cluster id, the written title, and the hint. A
|
|
16
|
+
cluster with no title prints `no label` in the middle. The heading stays in
|
|
17
|
+
the notebook. It is not part of the question.
|
|
18
|
+
|
|
19
|
+
`no marker passed` means the title `monocyte` was written, and none of its
|
|
20
|
+
cited markers passed the expression check. The name stays. The dotplot still
|
|
21
|
+
draws the best-measured cited genes for that type.
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
cluster 2 CD14-positive monocyte conflict: marker neutrophil
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The written title is `CD14-positive monocyte`. The marker score named
|
|
28
|
+
`neutrophil`, and that name is not on the same Cell Ontology lineage as the
|
|
29
|
+
title. The hint records the other call. The same line can name the name model
|
|
30
|
+
or the ML model, for example `conflict: ML pericyte`. Several disagreements
|
|
31
|
+
are joined with commas.
|
|
32
|
+
|
|
33
|
+
## The paragraph to paste
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
human, 1728 cells. What cell type is this cluster?
|
|
37
|
+
Enriched versus other cells: HLA-DRA (in 1.00, out 0.62, logfc 2.46); HLA-DRB1 (in 0.99, out 0.65, logfc 2.15); CD74 (in 1.00, out 0.93, logfc 1.84); LGALS2 (in 0.74, out 0.15, logfc 3.40); HLA-DPB1 (in 0.95, out 0.56, logfc 2.08); HLA-DRB5 (in 0.94, out 0.53, logfc 1.96); PID1 (in 0.70, out 0.19, logfc 2.78); CPVL (in 0.84, out 0.36, logfc 2.07); HLA-DPA1 (in 0.96, out 0.58, logfc 1.98); LYZ (in 1.00, out 0.65, logfc 3.01).
|
|
38
|
+
Also detected: CD14 (in 0.87, out 0.42, logfc 1.71); FCN1 (in 0.99, out 0.59, logfc 1.83); CSF1R (in 0.62, out 0.31, logfc 1.16); S100A8 (in 1.00, out 0.57, logfc 2.39); VCAN (in 0.94, out 0.50, logfc 1.59); S100A4 (in 1.00, out 0.95, logfc 0.81); ANXA1 (in 0.81, out 0.69, logfc 0.35).
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The first line is the species, the tissue when `run` was given one, the
|
|
42
|
+
number of cells, and the question. Paste from this line through `Also
|
|
43
|
+
detected`.
|
|
44
|
+
|
|
45
|
+
`Enriched versus other cells` lists up to 10 genes that are higher in this
|
|
46
|
+
cluster than in the other cells, in Wilcoxon order. `in` is the fraction of
|
|
47
|
+
cells in the cluster where the gene is detected. `out` is that fraction in
|
|
48
|
+
the other cells. `logfc` is the Scanpy log fold change.
|
|
49
|
+
|
|
50
|
+
`Also detected` lists markers of dictionary programs that are on in this
|
|
51
|
+
cluster, detected in at least half of its cells, and not already in the
|
|
52
|
+
enriched list. The list stops at 16 genes.
|
|
53
|
+
|
|
54
|
+
A reply from the other model is not written back into `adata` or the report.
|
|
55
|
+
Use it when you decide whether to keep or change the title in
|
|
56
|
+
`annotation_code`.
|
|
57
|
+
|
|
58
|
+
The same paragraph is `query` on `report["clusters"]` and on
|
|
59
|
+
`report["review"]`.
|
|
60
|
+
|
|
61
|
+
## One row per cluster
|
|
62
|
+
|
|
63
|
+
`report["clusters"]` has one row per cluster. The columns stay separate. A
|
|
64
|
+
title is not a vote count.
|
|
65
|
+
|
|
66
|
+
| Column | What it is |
|
|
67
|
+
|---|---|
|
|
68
|
+
| `cluster` | Leiden id |
|
|
69
|
+
| `cells` | Cells in that cluster |
|
|
70
|
+
| `marker` | Name from the marker score, or none |
|
|
71
|
+
| `name` | First name copied by the name model. `failed` when the call failed. The action when the reply named nothing |
|
|
72
|
+
| `ml` | First name copied by the ML model. `escalate` when it abstains. `failed` when the call failed |
|
|
73
|
+
| `label` | Title written onto the cells. Empty when the cluster stays unnamed |
|
|
74
|
+
| `hint` | The question printed after the title. Empty when there is nothing to ask |
|
|
75
|
+
| `query` | The paragraph to paste. Present when the cluster is unnamed or `hint` is set |
|
|
76
|
+
| `reason` | Why the title was written or withheld |
|
|
77
|
+
| `ontology` | Cell Ontology id for the written title. `pending` means the id is not a reviewed row |
|
|
78
|
+
|
|
79
|
+
`adata.obs["annotune_label"]` is the title. `adata.obs["annotune_hint"]` is
|
|
80
|
+
the hint on every cell of that cluster. `adata.obs["annotune_final_status"]`
|
|
81
|
+
is `named`, `review`, or `escalate`. Clusters that share a title also share
|
|
82
|
+
one id in `adata.obs["annotune_cluster"]`. The Leiden column is kept.
|
|
83
|
+
|
|
84
|
+
## What to read first
|
|
85
|
+
|
|
86
|
+
`report["review"]` is the clusters to read first. The order is a reading
|
|
87
|
+
order, not an accuracy score.
|
|
88
|
+
|
|
89
|
+
| Priority | Which clusters |
|
|
90
|
+
|---|---|
|
|
91
|
+
| 0 | No title |
|
|
92
|
+
| 1 | A conflict, or close marker scores |
|
|
93
|
+
| 2 | A model call failed |
|
|
94
|
+
| 3 | Fewer than 20 cells |
|
|
95
|
+
| 4 | Any other hint |
|
|
96
|
+
|
|
97
|
+
`report["queue"]` lists only clusters with no title. A titled cluster with a
|
|
98
|
+
hint is in `review`, and on `annotune_hint`, and it is not in `queue`.
|
|
99
|
+
|
|
100
|
+
## The rest of the report
|
|
101
|
+
|
|
102
|
+
| Field | What it is |
|
|
103
|
+
|---|---|
|
|
104
|
+
| `records` | The working record for each cluster, including model rounds and the marker ranking |
|
|
105
|
+
| `dropped_hypotheses` | Dictionary types left out because a positive marker is missing from the matrix |
|
|
106
|
+
| `subclusters` | The second split of a cluster that was not settled. Empty when `subcluster=False` |
|
|
107
|
+
| `arbitration` | Clusters that were not given the status `named` |
|
|
108
|
+
| `merged` | Titles that were given one `annotune_cluster` id |
|
|
109
|
+
| `all_labeled` | True when every cell has a title |
|
|
110
|
+
| `written` | True when at least one cell has a title |
|
|
111
|
+
| `label_key` | The `obs` column that holds the title. `None` when nothing was written |
|
|
112
|
+
| `marker_dict` | Genes drawn in the dotplot, in column order |
|
|
113
|
+
| `marker_validation` | Measurement of each cited gene, and why it was kept or left out |
|
|
114
|
+
| `marker_status` | Per written type. `no_marker_passed_expression_check` is the check behind `no marker passed` |
|
|
115
|
+
| `marker_thresholds` | The cutoffs used for that check |
|
|
116
|
+
| `dotplot` | Path of the PDF when `dotplot_path` was set |
|
|
117
|
+
| `doublets` | Doublet summary stored by `prepare` |
|
|
118
|
+
| `tissue` | Tissue page passed to `run` |
|
|
119
|
+
| `tissues` | Tissue pages available for the species |
|
|
120
|
+
| `annotation_code` | Python that redraws the UMAP and the dotplot from the written titles |
|
|
121
|
+
|
|
122
|
+
`annotation_code` copies the titles into `cluster2celltype`. Clusters with no
|
|
123
|
+
title are left out of that map and listed under `cluster_choices` when the
|
|
124
|
+
record has candidate names. Edit the map or `fine_order`, then run the
|
|
125
|
+
snippet on the annotated object. {doc}`../quickstart` records the expression
|
|
126
|
+
cutoffs used for the dotplot.
|
|
@@ -71,11 +71,12 @@ annotuneagent = "annotuneagent.cli:main"
|
|
|
71
71
|
|
|
72
72
|
[project.urls]
|
|
73
73
|
Homepage = "https://github.com/leelieber2025/AnnoTuneAgent"
|
|
74
|
-
Documentation = "https://
|
|
74
|
+
Documentation = "https://annotuneagent.readthedocs.io/"
|
|
75
75
|
Changelog = "https://github.com/leelieber2025/AnnoTuneAgent/blob/main/CHANGELOG.md"
|
|
76
76
|
Source = "https://github.com/leelieber2025/AnnoTuneAgent"
|
|
77
77
|
Issues = "https://github.com/leelieber2025/AnnoTuneAgent/issues"
|
|
78
78
|
PyPI = "https://pypi.org/project/annotuneagent/"
|
|
79
|
+
Zenodo = "https://doi.org/10.5281/zenodo.24092828"
|
|
79
80
|
|
|
80
81
|
[tool.setuptools.packages.find]
|
|
81
82
|
where = ["src"]
|
|
@@ -27,9 +27,12 @@ those candidates.
|
|
|
27
27
|
``local_models`` takes the directory containing the Q6_K base and the name and
|
|
28
28
|
ml adapters. The tokenizer is installed with the package. The server is
|
|
29
29
|
``http://127.0.0.1:8080`` unless ``url`` or ``ANNOTUNE_URL`` says otherwise.
|
|
30
|
-
A matching
|
|
31
|
-
``TaskEndpoint(url=...)``
|
|
32
|
-
|
|
30
|
+
A matching server is reused. When the process list is unavailable, the check
|
|
31
|
+
reads ``/props`` and ``/lora-adapters``. ``TaskEndpoint(url=...)`` calls
|
|
32
|
+
``/completion`` on that server and enables one adapter per request.
|
|
33
|
+
``attach`` connects to an existing service without loading weights.
|
|
34
|
+
Model requests wait 600 seconds unless ``timeout`` or ``ANNOTUNE_TIMEOUT``
|
|
35
|
+
says otherwise.
|
|
33
36
|
"""
|
|
34
37
|
|
|
35
38
|
from __future__ import annotations
|
|
@@ -628,10 +628,27 @@ def hit_names(payload: dict[str, object]) -> set[str]:
|
|
|
628
628
|
return {str(item["name"]) for item in payload.get("dictionary_hits") or []}
|
|
629
629
|
|
|
630
630
|
|
|
631
|
-
def fetch_name(
|
|
632
|
-
|
|
633
|
-
|
|
631
|
+
def fetch_name(
|
|
632
|
+
url: str,
|
|
633
|
+
payload: dict[str, object],
|
|
634
|
+
timeout: float | None = None,
|
|
635
|
+
*,
|
|
636
|
+
maxlen: int = 2048,
|
|
637
|
+
tokenizer: str | None = None,
|
|
638
|
+
) -> Decision:
|
|
639
|
+
"""Name task on ``/completion``. One adapter is enabled for this request."""
|
|
640
|
+
from .local_lora import complete_url
|
|
641
|
+
|
|
642
|
+
text = complete_url(
|
|
643
|
+
url,
|
|
644
|
+
"name",
|
|
645
|
+
SYSTEM_NAME,
|
|
646
|
+
payload,
|
|
647
|
+
maxlen=maxlen,
|
|
648
|
+
timeout=timeout,
|
|
649
|
+
tokenizer=tokenizer,
|
|
634
650
|
)
|
|
651
|
+
return parse_decision(text, hit_names(payload))
|
|
635
652
|
|
|
636
653
|
|
|
637
654
|
def candidate_names(payload: dict[str, object]) -> set[str]:
|
|
@@ -644,11 +661,27 @@ def candidate_names(payload: dict[str, object]) -> set[str]:
|
|
|
644
661
|
return names
|
|
645
662
|
|
|
646
663
|
|
|
647
|
-
def fetch_ml(
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
664
|
+
def fetch_ml(
|
|
665
|
+
url: str,
|
|
666
|
+
payload: dict[str, object],
|
|
667
|
+
timeout: float | None = None,
|
|
668
|
+
*,
|
|
669
|
+
maxlen: int = 8192,
|
|
670
|
+
tokenizer: str | None = None,
|
|
671
|
+
) -> MlResult:
|
|
672
|
+
"""ML task on ``/completion``. One adapter is enabled for this request."""
|
|
673
|
+
from .local_lora import complete_url
|
|
674
|
+
|
|
675
|
+
text = complete_url(
|
|
676
|
+
url,
|
|
677
|
+
"ml",
|
|
678
|
+
SYSTEM_ML,
|
|
679
|
+
payload,
|
|
680
|
+
maxlen=maxlen,
|
|
681
|
+
timeout=timeout,
|
|
682
|
+
tokenizer=tokenizer,
|
|
651
683
|
)
|
|
684
|
+
return parse_ml(text, candidate_names(payload))
|
|
652
685
|
|
|
653
686
|
|
|
654
687
|
def _negative_high(row: dict | None) -> bool:
|