Skip to content

Commit

Permalink
Improved documentation (#132)
Browse files Browse the repository at this point in the history
  • Loading branch information
gsarti authored Apr 6, 2022
1 parent f5fc04b commit e2398ab
Show file tree
Hide file tree
Showing 18 changed files with 595 additions and 111 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ jobs:

steps:
- uses: actions/checkout@v3

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
Expand Down
40 changes: 24 additions & 16 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,22 @@ VERSION := latest
.PHONY: help
help:
@echo "Commands:"
@echo "poetry-download : downloads and installs the poetry package manager"
@echo "poetry-remove : removes the poetry package manager"
@echo "install : installs required dependencies"
@echo "install-dev : installs the dev dependencies for the project"
@echo "check-style : run checks on all files without fixing them."
@echo "fix-style : run checks on files and potentially modifies them."
@echo "check-safety : run safety checks on all tests."
@echo "lint : run linting on all files (check-style + check-safety)"
@echo "test : run all tests."
@echo "codecov : check coverage of all the code."
@echo "docs : serve generated documentation locally."
@echo "docker-build : builds docker image for the package."
@echo "docker-remove : removes built docker image."
@echo "clean : cleans all unecessary files."
@echo "poetry-download : downloads and installs the poetry package manager"
@echo "poetry-remove : removes the poetry package manager"
@echo "install : installs required dependencies"
@echo "install-dev : installs the dev dependencies for the project"
@echo "check-style : run checks on all files without fixing them."
@echo "fix-style : run checks on files and potentially modifies them."
@echo "check-safety : run safety checks on all tests."
@echo "lint : run linting on all files (check-style + check-safety)"
@echo "test : run all tests."
@echo "codecov : check coverage of all the code."
@echo "build-docs : build sphinx documentation."
@echo "serve-docs : serve documentation locally."
@echo "docs : build and serve generated documentation locally."
@echo "docker-build : builds docker image for the package."
@echo "docker-remove : removes built docker image."
@echo "clean : cleans all unecessary files."

#* Poetry
.PHONY: poetry-download
Expand Down Expand Up @@ -89,11 +91,17 @@ codecov:
poetry run pytest --cov inseq --cov-report html

#* Docs
.PHONY: docs
docs:
.PHONY: build-docs
build-docs:
cd docs && make html SPHINXOPTS="-W -j 4"

.PHONY: serve-docs
serve-docs:
cd docs/_build/html && python3 -m http.server 8080

.PHONY: docs
docs: build-docs serve-docs

#* Docker
# Example: make docker VERSION=latest
# Example: make docker IMAGE=some_name VERSION=0.1.0
Expand Down
43 changes: 41 additions & 2 deletions docs/source/_static/inseq.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
function addIcon() {
const inseqLogo = "_static/inseq_logo.png";
const inseqLogo = "/_static/inseq_logo.png";
const link = document.createElement("a");
const indexpath = "/index.html";
link.setAttribute("href", indexpath);
const image = document.createElement("img");
image.setAttribute("src", inseqLogo);
image.setAttribute("alt", "Inseq logo");
image.style.width = "80%"
image.style.paddingRight = "10%";
link.appendChild(image);
const desc = document.createElement("p");
desc.innerHTML = "Interpretability for sequence-to-sequence models 🔍";
desc.style.color = "black";
desc.style.paddingLeft = "20px";
desc.style.paddingTop = "10px";
desc.style.width = "80%"

const div = document.createElement("div");
div.appendChild(image);
div.appendChild(link);
div.appendChild(desc);
div.style.textAlign = 'center';
div.style.paddingTop = '30px';

Expand Down Expand Up @@ -40,10 +54,35 @@ function addCustomFooter() {
document.querySelector("footer").appendChild(customFooter);
}

function resizeHtmlExamples() {
var examples = document.getElementsByClassName("html-example");
for (const ex of examples) {
const iframe = ex.firstElementChild;
const zoom = iframe.getAttribute("scale")
const origHeight = iframe.contentWindow.document.body.scrollHeight
const origWidth = iframe.contentWindow.document.body.scrollWidth
ex.style.height = ((origHeight * zoom) + 50) + "px";
const frameHeight = origHeight / zoom
const frameWidth = origWidth / zoom
// add extra 50 pixels - in reality need just a bit more
iframe.style.height = frameHeight + "px"
// set the width of the iframe as the width of the iframe content
iframe.style.width = frameWidth + 'px';
iframe.style.zoom = zoom;
iframe.style.MozTransform = `scale(${zoom})`;
iframe.style.WebkitTransform = `scale(${zoom})`;
iframe.style.transform = `scale(${zoom})`;
iframe.style.MozTransformOrigin = "0 0";
iframe.style.WebkitTransformOrigin = "0 0";
iframe.style.transformOrigin = "0 0";
}
}


function onLoad() {
addIcon();
addCustomFooter();
resizeHtmlExamples();
}

window.addEventListener("load", onLoad);
23 changes: 9 additions & 14 deletions docs/source/_static/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -159,15 +159,11 @@ a {
display: inline;
vertical-align: middle;
margin-right: 16px;
max-width: 200px;
max-width: 160px;
width: 100%;
margin-bottom: 0;
}

.wy-nav-content-wrap {
margin-left: 340px;
}


@media only screen and (max-width: 768px) {
.wy-nav-side {
Expand All @@ -181,15 +177,6 @@ a {

.wy-nav-content-wrap.shift {
left: 340px;
top: 75px;
}

.wy-nav-content-wrap {
z-index: 10;
}

.inseq_header {
display: inline;
}

}
Expand Down Expand Up @@ -337,3 +324,11 @@ a.copybtn {
font-size: 18px;
color: black;
}

.html-example {
width: 100%;
}

.html-example > iframe {
width: 100%;
}
9 changes: 0 additions & 9 deletions docs/source/_templates/layout.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
{% extends "!layout.html" %} {% block extrahead %}
<!-- <link href="{{ pathto("_static/style.css", True) }}" rel="stylesheet" type="text/css"> -->
{% endblock %} {% block extrabody %}
<div class="inseq_header no-print">
<a id="header-logo" href="https://inseq.readthedocs.io/">
<img
src="https://github.com/inseq-team/inseq/blob/3ede9f8ce07f6e0db076f77a8a62c4d3347ce293/docs/source/images/inseq_logo.png"
alt="inseq logo", height="50"
/>
</a>
</div>

{% endblock %}
8 changes: 6 additions & 2 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@


_PATH_ROOT = Path(__file__).parent.parent.parent.absolute()
_PATH_SRC = Path(_PATH_ROOT, "inseq")
sys.path.insert(0, str(_PATH_SRC.absolute()))
# _PATH_SRC = Path(_PATH_ROOT, "inseq")
sys.path.insert(0, str(_PATH_ROOT.absolute()))

# -- Project information -----------------------------------------------------

Expand Down Expand Up @@ -89,6 +89,9 @@
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = None

# Permalinks
html_permalinks_icon = "<i class='fas fa-link'></i>"

# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = True

Expand Down Expand Up @@ -137,6 +140,7 @@
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = [
"images",
"html_outputs",
"_static",
"_static/style.css",
"_static/hk-grotesk-pro/HKGroteskPro-Bold.woff2",
Expand Down
67 changes: 67 additions & 0 deletions docs/source/examples/pair_comparison.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
..
Copyright 2022 The Inseq Team. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.

##########################################
Comparing Attributions with PairAggregator
##########################################

Inseq support minimal pair analysis via the `PairAggregator </main_classes/data_classes.html#pairaggregator>`_ component.

Here is an example of using ``PairAggregator`` to produce a heatmap to visualize the score difference between two ``FeatureAttributionSequenceOutput`` objects:

.. code-block:: python
import inseq
from inseq.data.aggregator import AggregatorPipeline, ContiguousSpanAggregator, SequenceAttributionAggregator, PairAggregator
# Load the EN-FR translation model and attach the IG method
model = inseq.load_model("Helsinki-NLP/opus-mt-en-fr", "integrated_gradients")
# Perform the attribution with forced decoding. Return convergence deltas, probabilities and target attributions.
out = model.attribute(
[
"The manager told the hairdresser that the haircut he made her was terrible.",
"The manager told the hairdresser that the haircut he made her was terrible.",
],
[
"Le gérant a dit au coiffeur que la coupe de cheveux qu'il lui a faite était terrible.",
"La gérante a dit au coiffeur que la coupe de cheveux qu'il lui a faite était terrible.",
],
n_steps=300,
return_convergence_delta=True,
attribute_target=True,
output_step_probabilities=True,
internal_batch_size=100,
include_eos_baseline=False,
)
# Aggregation pipeline composed by two steps:
# 1. Aggregate contiguous tokens across all attribution dimensions
# 2. Aggregate the last dimension of the neuron-level attribution to make it token-level
squeezesum = AggregatorPipeline([ContiguousSpanAggregator, SequenceAttributionAggregator])
# Simply aggregate over the last dimension for the masculine variant
masculine = out.sequence_attributions[0].aggregate(aggregator=SequenceAttributionAggregator)
# For the feminine variant, we also use the contiguous span aggregator to merge "▁gérant" "e"
# in a single token to match masculine shape
feminine = out.sequence_attributions[1].aggregate(aggregator=squeezesum, target_spans=(1, 3))
# Take the diff of the scores of the two attribution and show it
masculine.show(aggregator=PairAggregator, paired_attr=feminine)
.. raw:: html

<div class="html-example">
<iframe frameborder="0" scale="0.75" src="/_static/pair_comparison.htm"></iframe>
</div>
46 changes: 46 additions & 0 deletions docs/source/html_outputs/pair_comparison.htm

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions docs/source/html_outputs/winomt_example.htm

Large diffs are not rendered by default.

27 changes: 22 additions & 5 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,34 @@ Here is an example of using Inseq to attribute an English-to-Italian translation
import inseq
model = inseq.load_model("Helsinki-NLP/opus-mt-en-it", "integrated_gradients")
model = inseq.load_model("Helsinki-NLP/opus-mt-en-fr", "integrated_gradients")
out = model.attribute(
"The developer argued with the designer because she did not like the design.",
return_convergence_delta=True,
n_steps=100
"The developer argued with the designer because she did not like the design.",
n_steps=300,
return_convergence_delta=True,
output_step_probabilities=True,
internal_batch_size=100,
include_eos_baseline=False,
)
out.show()
.. raw:: html

<div class="html-example">
<iframe frameborder="0" scale="0.75" src="/_static/winomt_example.htm"></iframe>
</div>


.. toctree::
:maxdepth: 2
:caption: Using 🐛 Inseq

examples/pair_comparison

.. toctree::
:maxdepth: 4
:caption: Main Classes

main_classes/models
main_classes/data_classes
main_classes/feature_attribution
main_classes/gradient_attribution
Loading

0 comments on commit e2398ab

Please sign in to comment.