Skip to content

Commit 1cb4760

Browse files
authored
Docs CI (#48)
auto deploy documentation to https://deeppavlov.github.io/AutoIntent/
1 parent 866bb4c commit 1cb4760

File tree

13 files changed

+127
-55
lines changed

13 files changed

+127
-55
lines changed

.github/workflows/build-docs.yaml

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: Build and publish docs
2+
3+
on:
4+
push:
5+
branches:
6+
- dev
7+
workflow_dispatch:
8+
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.ref }}
11+
cancel-in-progress: ${{ github.ref != 'refs/heads/dev' }}
12+
13+
permissions:
14+
contents: write
15+
16+
jobs:
17+
publish:
18+
name: build and publish docs
19+
runs-on: ubuntu-latest
20+
steps:
21+
- uses: actions/checkout@v4
22+
23+
- name: set up python 3.10
24+
uses: actions/setup-python@v5
25+
with:
26+
python-version: "3.10"
27+
28+
- name: setup poetry
29+
run: |
30+
curl -sSL https://install.python-poetry.org | python -
31+
32+
- name: Install pandoc
33+
run: |
34+
sudo apt install pandoc
35+
36+
- name: install dependencies
37+
run: |
38+
poetry install --with docs
39+
40+
- name: build documentation
41+
run: |
42+
make docs
43+
44+
- name: save branch name without slashes
45+
env:
46+
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
47+
run: |
48+
BRANCH_NAME=${{ env.BRANCH_NAME }}
49+
BRANCH_NAME=${BRANCH_NAME////_}
50+
echo BRANCH_NAME=${BRANCH_NAME} >> $GITHUB_ENV
51+
52+
- name: save artifact
53+
uses: actions/upload-artifact@v4
54+
with:
55+
name: ${{ format('github-pages-for-branch-{0}', env.BRANCH_NAME) }}
56+
path: docs/build/
57+
retention-days: 3
58+
59+
- name: deploy website
60+
uses: JamesIves/[email protected]
61+
with:
62+
branch: gh-pages
63+
folder: docs/build/html/
64+
single-commit: True

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ sync:
2929
.PHONY: docs
3030
docs:
3131
$(poetry) sphinx-apidoc -e -E -f --remove-old -o docs/source/apiref autointent
32-
$(poetry) python -m sphinx build docs/source docs/build/html
32+
$(poetry) python -m sphinx build -b doctest docs/source docs/build/html
3333

3434
.PHONY: serve-docs
3535
serve-docs: docs

autointent/context/embedder.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@
1616

1717

1818
class EmbedderDumpMetadata(TypedDict):
19-
"""
20-
Metadata for saving and loading an Embedder instance.
21-
"""
19+
"""Metadata for saving and loading an Embedder instance."""
2220

2321
batch_size: int
2422
"""Batch size used for embedding calculations."""

autointent/metrics/scoring.py

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,28 +33,28 @@ def scoring_log_likelihood(labels: LABELS_VALUE_TYPE, scores: SCORES_VALUE_TYPE,
3333
r"""
3434
Supports multiclass and multilabel cases.
3535
36-
Multiclass case
36+
Multiclass case:
3737
Mean negative cross-entropy for each utterance classification result:
3838
3939
.. math::
4040
41-
\\frac{1}{\\ell}\\sum_{i=1}^{\\ell}\\log(s[y[i]])
41+
\frac{1}{\ell}\sum_{i=1}^{\ell}\log(s[y[i]])
4242
43-
where ``s[y[i]]`` is a predicted score of ``i``\\ th utterance having ground truth label
43+
where ``s[y[i]]`` is the predicted score of the ``i``-th utterance having the ground truth label.
4444
45-
Multilabel case
45+
Multilabel case:
4646
Mean negative binary cross-entropy:
4747
4848
.. math::
4949
50-
\\frac{1}{\\ell}\\sum_{i=1}^\\ell\\sum_{c=1}^C\\Big[y[i,c]\\cdot\\log(s[i,c])+(1-y[i,c])\\cdot\\log(1-s[i,c])\\Big]
50+
\frac{1}{\ell}\sum_{i=1}^\ell\sum_{c=1}^C\Big[y[i,c]\cdot\log(s[i,c])+(1-y[i,c])\cdot\log(1-s[i,c])\Big]
5151
52-
where ``s[i,c]`` is a predicted score of ``i``\\ th utterance having ground truth label ``c``
52+
where ``s[i,c]`` is the predicted score of the ``i``-th utterance having the ground truth label ``c``.
5353
54-
:param labels: ground truth labels for each utterance
55-
:param scores: for each utterance, this list contains scores for each of `n_classes` classes
56-
:param eps: small value to avoid division by zero
57-
:return: Score of the scoring metric
54+
:param labels: Ground truth labels for each utterance.
55+
:param scores: For each utterance, a list containing scores for each of `n_classes` classes.
56+
:param eps: A small value to avoid division by zero.
57+
:return: Score of the scoring metric.
5858
"""
5959
labels_array, scores_array = transform(labels, scores)
6060
scores_array[scores_array == 0] = eps
@@ -82,7 +82,7 @@ def scoring_roc_auc(labels: LABELS_VALUE_TYPE, scores: SCORES_VALUE_TYPE) -> flo
8282
8383
.. math::
8484
85-
\frac{1}{C}\\sum_{k=1}^C ROCAUC(scores[:, k], labels[:, k])
85+
\frac{1}{C}\sum_{k=1}^C ROCAUC(scores[:, k], labels[:, k])
8686
8787
where ``C`` is the number of classes
8888
@@ -196,18 +196,19 @@ def scoring_neg_coverage(labels: LABELS_VALUE_TYPE, scores: SCORES_VALUE_TYPE) -
196196
197197
The result is equivalent to executing the following code:
198198
199-
.. code-block:: python
200-
201-
scores = np.array(scores)
202-
labels = np.array(labels)
203-
204-
n_classes = scores.shape[1]
205-
from scipy.stats import rankdata
206-
int_ranks = rankdata(scores, axis=1) # int ranks are from [1, n_classes]
207-
filtered_ranks = int_ranks * labels # guarantee that 0 labels wont have max rank
208-
max_ranks = np.max(filtered_ranks, axis=1)
209-
float_ranks = (max_ranks - 1) / (n_classes - 1) # float ranks are from [0,1]
210-
res = 1 - np.mean(float_ranks)
199+
>>> def compute_rank_metric():
200+
... import numpy as np
201+
... scores = np.array([[1, 2, 3]])
202+
... labels = np.array([1, 0, 0])
203+
... n_classes = scores.shape[1]
204+
... from scipy.stats import rankdata
205+
... int_ranks = rankdata(scores, axis=1)
206+
... filtered_ranks = int_ranks * labels
207+
... max_ranks = np.max(filtered_ranks, axis=1)
208+
... float_ranks = (max_ranks - 1) / (n_classes - 1)
209+
... return float(1 - np.mean(float_ranks))
210+
>>> print(f"{compute_rank_metric():.1f}")
211+
1.0
211212
212213
:param labels: ground truth labels for each utterance
213214
:param scores: for each utterance, this list contains scores for each of `n_classes` classes

autointent/modules/base.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,7 @@ def score(self, context: Context, metric_fn: METRIC_FN) -> float:
4040

4141
@abstractmethod
4242
def get_assets(self) -> Artifact:
43-
"""
44-
Return useful assets that represent intermediate data into context.
45-
46-
"""
43+
"""Return useful assets that represent intermediate data into context."""
4744

4845
@abstractmethod
4946
def clear_cache(self) -> None:

autointent/modules/prediction/base.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,7 @@ def score(self, context: Context, metric_fn: PredictionMetricFn) -> float:
5353
return metric_fn(labels, self._predictions)
5454

5555
def get_assets(self) -> PredictorArtifact:
56-
"""
57-
Return useful assets that represent intermediate data into context.
58-
59-
"""
56+
"""Return useful assets that represent intermediate data into context."""
6057
return PredictorArtifact(labels=self._predictions)
6158

6259
def clear_cache(self) -> None:

autointent/modules/scoring/dnnc/dnnc.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ class DNNCScorer(ScoringModule):
4949
archivePrefix={arXiv},
5050
primaryClass={cs.CL},
5151
url={https://arxiv.org/abs/2010.13009},
52-
}
52+
}
53+
5354
"""
5455

5556
name = "dnnc"

docs/source/conf.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@
99
import os
1010
import sys
1111

12+
from docs.source.docs_utils.tutorials import generate_tutorial_links_for_notebook_creation
13+
1214
conf_dir = os.path.dirname(os.path.abspath(__file__)) # noqa: PTH100, PTH120
1315

1416
sys.path.insert(0, conf_dir)
1517

1618
from docs_utils.apiref import regenerate_apiref # noqa: E402
17-
from docs_utils.tutorials import generate_tutorial_links_for_notebook_creation # noqa: E402
1819

1920
project = "AutoIntent"
2021
copyright = "2024, DeepPavlov"
@@ -27,10 +28,20 @@
2728
extensions = [
2829
"sphinx.ext.duration",
2930
"sphinx.ext.autodoc",
30-
"sphinx.ext.doctest",
3131
"sphinx.ext.autosummary",
32-
"nbsphinx",
32+
"sphinx.ext.doctest",
33+
"sphinx.ext.intersphinx",
3334
"sphinx.ext.todo",
35+
"sphinx.ext.coverage",
36+
"sphinx.ext.viewcode",
37+
"sphinx.ext.mathjax",
38+
"sphinx.ext.extlinks",
39+
"sphinx.ext.doctest",
40+
"sphinx.ext.viewcode",
41+
"sphinx.ext.githubpages",
42+
"sphinx_autodoc_typehints",
43+
"sphinx_copybutton",
44+
"nbsphinx",
3445
]
3546

3647
templates_path = ["_templates"]
@@ -51,7 +62,7 @@
5162
"private-members": True,
5263
# "special-members": "__call__",
5364
"member-order": "bysource",
54-
# "exclude-members": "_abc_impl, model_fields, model_computed_fields, model_config",
65+
"exclude-members": "_abc_impl, model_fields, model_computed_fields, model_config",
5566
}
5667

5768
# Finding tutorials directories
@@ -60,6 +71,8 @@
6071
:tutorial_name: {{ env.docname }}
6172
"""
6273

74+
mathjax_path = "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"
75+
6376

6477
def setup(_) -> None: # noqa: ANN001
6578
generate_tutorial_links_for_notebook_creation(

docs/source/docs_utils/notebook.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,9 @@
33
from typing import ClassVar, Literal
44

55
import nbformat
6+
from jupytext import jupytext
67
from pydantic import BaseModel
78

8-
try:
9-
from jupytext import jupytext
10-
except ImportError:
11-
jupytext = None
12-
139

1410
class ReplacePattern(BaseModel, abc.ABC):
1511
"""
@@ -78,7 +74,7 @@ class DocumentationLink(ReplacePattern):
7874
USAGE EXAMPLES
7975
--------------
8076
81-
%doclink(api,index_pipeline)) -> ../apiref/index_pipeline.rst
77+
%doclink(api,index_pipeline) -> ../apiref/index_pipeline.rst
8278
8379
%doclink(api,script.core.script) -> ../apiref/chatsky.script.core.script.rst
8480
@@ -243,7 +239,4 @@ def py_percent_to_notebook(text: str) -> nbformat.NotebookNode:
243239
# %% [raw]
244240
# This is a raw cell
245241
"""
246-
if jupytext is None:
247-
msg = "`doc` dependencies are not installed."
248-
raise ModuleNotFoundError(msg)
249242
return jupytext.reads(apply_replace_patterns(text), "py:percent")

docs/source/learn/dialogue_systems.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Dialogue Systems
44
В этом разделе вы познакомитесь с основами построения диалоговых систем.
55

66
Intents
7-
-----
7+
-------
88

99
Диалоговая система в широком смысле --- это текстовый интерфейс взаимодействия с некоторым сервисом (будь то сервис по заказу еды или по получению информации о банковском счете). Обычно сервис поддерживает конечное количество API методов, которые вызываются во время диалога с пользователем. Чтобы определить, какой метод нужен в данный момент диалога используются классификаторы интентов. Если рассуждать в терминах машинного обучения, то это задача классификации текстов.
1010

0 commit comments

Comments
 (0)