From 10e67b400c91467b7eaf03bd8b7f49359b2c47ca Mon Sep 17 00:00:00 2001 From: svlandeg Date: Tue, 18 Aug 2020 13:38:43 +0200 Subject: [PATCH 01/33] output_file required, spacy-transformers prefered instead of required --- spacy/cli/init_config.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/spacy/cli/init_config.py b/spacy/cli/init_config.py index 7d80eb289..79c4acd11 100644 --- a/spacy/cli/init_config.py +++ b/spacy/cli/init_config.py @@ -39,7 +39,7 @@ class RecommendationSchema(BaseModel): @init_cli.command("config") def init_config_cli( # fmt: off - output_file: Path = Arg("-", help="File to save config.cfg to (or - for stdout)", allow_dash=True), + output_file: Path = Arg(..., help="File to save config.cfg to (or - for stdout, disabling logging)", allow_dash=True), lang: Optional[str] = Opt("en", "--lang", "-l", help="Two-letter code of the language to use"), pipeline: Optional[str] = Opt("tagger,parser,ner", "--pipeline", "-p", help="Comma-separated names of trainable pipeline components to include in the model (without 'tok2vec' or 'transformer')"), optimize: Optimizations = Opt(Optimizations.efficiency.value, "--optimize", "-o", help="Whether to optimize for efficiency (faster inference, smaller model, lower memory consumption) or higher accuracy (potentially larger and slower model). This will impact the choice of architecture, pretrained weights and related hyperparameters."), @@ -128,6 +128,8 @@ def init_config( "word_vectors": reco["word_vectors"], "has_letters": has_letters, } + if variables["transformer_data"] and not cpu: + variables["transformer_data"] = prefer_spacy_transformers(msg) base_template = template.render(variables).strip() # Giving up on getting the newlines right in jinja for now base_template = re.sub(r"\n\n\n+", "\n\n", base_template) @@ -144,8 +146,6 @@ def init_config( for label, value in use_case.items(): msg.text(f"- {label}: {value}") use_transformer = bool(template_vars.use_transformer) - if use_transformer: - require_spacy_transformers(msg) with show_validation_error(hint_fill=False): config = util.load_config_from_str(base_template) nlp, _ = util.load_model_from_config(config, auto_fill=True) @@ -167,12 +167,13 @@ def save_config(config: Config, output_file: Path, is_stdout: bool = False) -> N print(f"{COMMAND} train {output_file.parts[-1]} {' '.join(variables)}") -def require_spacy_transformers(msg: Printer) -> None: +def prefer_spacy_transformers(msg: Printer) -> bool: try: import spacy_transformers # noqa: F401 except ImportError: - msg.fail( - "Using a transformer-based pipeline requires spacy-transformers " - "to be installed.", - exits=1, + msg.info( + "Recommend to install 'spacy-transformers' to create a more efficient " + "transformer-based pipeline." ) + return False + return True From e60442d83a0129762959bca92119d79818f760b4 Mon Sep 17 00:00:00 2001 From: Ines Montani Date: Fri, 21 Aug 2020 11:51:31 +0200 Subject: [PATCH 02/33] Adjust label casing in displaCy NER visualizer (resolves #4866) - Accept any case for label names in ents and colors option, even if actual predicted label uses different casing - Don't text-transform: uppercase visually, if it's important to users that the label is represented as-is in the UI --- spacy/displacy/render.py | 4 +++- spacy/displacy/templates.py | 4 ++-- spacy/tests/test_displacy.py | 16 +++++++++++++++- website/docs/api/top-level.md | 2 +- website/docs/usage/visualizers.md | 8 ++++---- 5 files changed, 25 insertions(+), 9 deletions(-) diff --git a/spacy/displacy/render.py b/spacy/displacy/render.py index 69f6df8f0..07550f9aa 100644 --- a/spacy/displacy/render.py +++ b/spacy/displacy/render.py @@ -252,8 +252,10 @@ class EntityRenderer: colors.update(user_color) colors.update(options.get("colors", {})) self.default_color = DEFAULT_ENTITY_COLOR - self.colors = colors + self.colors = {label.upper(): color for label, color in colors.items()} self.ents = options.get("ents", None) + if self.ents is not None: + self.ents = [ent.upper() for ent in self.ents] self.direction = DEFAULT_DIR self.lang = DEFAULT_LANG template = options.get("template") diff --git a/spacy/displacy/templates.py b/spacy/displacy/templates.py index ff99000f4..b9cbf717b 100644 --- a/spacy/displacy/templates.py +++ b/spacy/displacy/templates.py @@ -51,14 +51,14 @@ TPL_ENTS = """ TPL_ENT = """ {text} - {label} + {label} """ TPL_ENT_RTL = """ {text} - {label} + {label} """ diff --git a/spacy/tests/test_displacy.py b/spacy/tests/test_displacy.py index adac0f7c3..1fa0eeaa1 100644 --- a/spacy/tests/test_displacy.py +++ b/spacy/tests/test_displacy.py @@ -1,6 +1,6 @@ import pytest from spacy import displacy -from spacy.displacy.render import DependencyRenderer +from spacy.displacy.render import DependencyRenderer, EntityRenderer from spacy.tokens import Span from spacy.lang.fa import Persian @@ -97,3 +97,17 @@ def test_displacy_render_wrapper(en_vocab): assert html.endswith("/div>TEST") # Restore displacy.set_render_wrapper(lambda html: html) + + +def test_displacy_options_case(): + ents = ["foo", "BAR"] + colors = {"FOO": "red", "bar": "green"} + renderer = EntityRenderer({"ents": ents, "colors": colors}) + text = "abcd" + labels = ["foo", "bar", "FOO", "BAR"] + spans = [{"start": i, "end": i + 1, "label": labels[i]} for i in range(len(text))] + result = renderer.render_ents("abcde", spans, None).split("\n\n") + assert "red" in result[0] and "foo" in result[0] + assert "green" in result[1] and "bar" in result[1] + assert "red" in result[2] and "FOO" in result[2] + assert "green" in result[3] and "BAR" in result[3] diff --git a/website/docs/api/top-level.md b/website/docs/api/top-level.md index 61fca6ec5..89c53cce3 100644 --- a/website/docs/api/top-level.md +++ b/website/docs/api/top-level.md @@ -257,7 +257,7 @@ If a setting is not present in the options, the default value will be used. | Name | Description | | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `ents` | Entity types to highlight or `None` for all types (default). ~~Optional[List[str]]~~ | -| `colors` | Color overrides. Entity types in uppercase should be mapped to color names or values. ~~Dict[str, str]~~ | +| `colors` | Color overrides. Entity types should be mapped to color names or values. ~~Dict[str, str]~~ | | `template` 2.2 | Optional template to overwrite the HTML used to render entity spans. Should be a format string and can use `{bg}`, `{text}` and `{label}`. See [`templates.py`](https://github.com/explosion/spaCy/blob/master/spacy/displacy/templates.py) for examples. ~~Optional[str]~~ | By default, displaCy comes with colors for all entity types used by diff --git a/website/docs/usage/visualizers.md b/website/docs/usage/visualizers.md index f33340063..4ba0112b6 100644 --- a/website/docs/usage/visualizers.md +++ b/website/docs/usage/visualizers.md @@ -121,10 +121,10 @@ import DisplacyEntHtml from 'images/displacy-ent2.html' The entity visualizer lets you customize the following `options`: -| Argument | Description | -| -------- | -------------------------------------------------------------------------------------------------------------------------- | -| `ents` | Entity types to highlight (`None` for all types). Defaults to `None`. ~~Optional[List[str]]~~ | `None` | -| `colors` | Color overrides. Entity types in uppercase should be mapped to color names or values. Defaults to `{}`. ~~Dict[str, str]~~ | +| Argument | Description | +| -------- | ------------------------------------------------------------------------------------------------------------- | +| `ents` | Entity types to highlight (`None` for all types). Defaults to `None`. ~~Optional[List[str]]~~ | `None` | +| `colors` | Color overrides. Entity types should be mapped to color names or values. Defaults to `{}`. ~~Dict[str, str]~~ | If you specify a list of `ents`, only those entity types will be rendered – for example, you can choose to display `PERSON` entities. Internally, the visualizer From 79af7dcd6dfbd5c73c3a667f236c440e85f132fc Mon Sep 17 00:00:00 2001 From: Ines Montani Date: Fri, 21 Aug 2020 12:06:19 +0200 Subject: [PATCH 03/33] Small wording adjustments [ci skip] --- spacy/cli/init_config.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/spacy/cli/init_config.py b/spacy/cli/init_config.py index 79c4acd11..273838906 100644 --- a/spacy/cli/init_config.py +++ b/spacy/cli/init_config.py @@ -39,7 +39,7 @@ class RecommendationSchema(BaseModel): @init_cli.command("config") def init_config_cli( # fmt: off - output_file: Path = Arg(..., help="File to save config.cfg to (or - for stdout, disabling logging)", allow_dash=True), + output_file: Path = Arg(..., help="File to save config.cfg to or - for stdout (will only output config and no additional logging info)", allow_dash=True), lang: Optional[str] = Opt("en", "--lang", "-l", help="Two-letter code of the language to use"), pipeline: Optional[str] = Opt("tagger,parser,ner", "--pipeline", "-p", help="Comma-separated names of trainable pipeline components to include in the model (without 'tok2vec' or 'transformer')"), optimize: Optimizations = Opt(Optimizations.efficiency.value, "--optimize", "-o", help="Whether to optimize for efficiency (faster inference, smaller model, lower memory consumption) or higher accuracy (potentially larger and slower model). This will impact the choice of architecture, pretrained weights and related hyperparameters."), @@ -128,8 +128,13 @@ def init_config( "word_vectors": reco["word_vectors"], "has_letters": has_letters, } - if variables["transformer_data"] and not cpu: - variables["transformer_data"] = prefer_spacy_transformers(msg) + if variables["transformer_data"] and not has_spacy_transformers(): + msg.warn( + "To generate a more effective transformer-based config (GPU-only), " + "install the spacy-transformers package and re-run this command. " + "The config generated now does not use transformers." + ) + variables["transformer_data"] = None base_template = template.render(variables).strip() # Giving up on getting the newlines right in jinja for now base_template = re.sub(r"\n\n\n+", "\n\n", base_template) @@ -167,13 +172,10 @@ def save_config(config: Config, output_file: Path, is_stdout: bool = False) -> N print(f"{COMMAND} train {output_file.parts[-1]} {' '.join(variables)}") -def prefer_spacy_transformers(msg: Printer) -> bool: +def has_spacy_transformers() -> bool: try: import spacy_transformers # noqa: F401 + + return True except ImportError: - msg.info( - "Recommend to install 'spacy-transformers' to create a more efficient " - "transformer-based pipeline." - ) return False - return True From 52bd3a8b48d354de57c1eb59d78abdb32c3e3a30 Mon Sep 17 00:00:00 2001 From: Ines Montani Date: Fri, 21 Aug 2020 13:22:59 +0200 Subject: [PATCH 04/33] Update docs [ci skip] --- website/docs/api/morphology.md | 2 +- website/docs/api/token.md | 4 +- website/docs/api/top-level.md | 17 ++ website/docs/usage/embeddings-transformers.md | 4 + website/docs/usage/v3.md | 182 ++++++++++++++++-- 5 files changed, 190 insertions(+), 19 deletions(-) diff --git a/website/docs/api/morphology.md b/website/docs/api/morphology.md index 1b2e159d0..5d5324061 100644 --- a/website/docs/api/morphology.md +++ b/website/docs/api/morphology.md @@ -7,7 +7,7 @@ source: spacy/morphology.pyx Store the possible morphological analyses for a language, and index them by hash. To save space on each token, tokens only know the hash of their morphological analysis, so queries of morphological attributes are delegated to -this class. See [`MorphAnalysis`](/api/morphology#morphansalysis) for the +this class. See [`MorphAnalysis`](/api/morphology#morphanalysis) for the container storing a single morphological analysis. ## Morphology.\_\_init\_\_ {#init tag="method"} diff --git a/website/docs/api/token.md b/website/docs/api/token.md index 4a8e6eba7..0860797aa 100644 --- a/website/docs/api/token.md +++ b/website/docs/api/token.md @@ -450,8 +450,8 @@ The L2 norm of the token's vector representation. | `pos_` | Coarse-grained part-of-speech from the [Universal POS tag set](https://universaldependencies.org/docs/u/pos/). ~~str~~ | | `tag` | Fine-grained part-of-speech. ~~int~~ | | `tag_` | Fine-grained part-of-speech. ~~str~~ | -| `morph` | Morphological analysis. ~~MorphAnalysis~~ | -| `morph_` | Morphological analysis in the Universal Dependencies [FEATS]https://universaldependencies.org/format.html#morphological-annotation format. ~~str~~ | +| `morph` 3 | Morphological analysis. ~~MorphAnalysis~~ | +| `morph_` 3 | Morphological analysis in the Universal Dependencies [FEATS]https://universaldependencies.org/format.html#morphological-annotation format. ~~str~~ | | `dep` | Syntactic dependency relation. ~~int~~ | | `dep_` | Syntactic dependency relation. ~~str~~ | | `lang` | Language of the parent document's vocabulary. ~~int~~ | diff --git a/website/docs/api/top-level.md b/website/docs/api/top-level.md index 89c53cce3..9c65b2982 100644 --- a/website/docs/api/top-level.md +++ b/website/docs/api/top-level.md @@ -632,6 +632,23 @@ validate its contents. | `path` | Path to the model's `meta.json`. ~~Union[str, Path]~~ | | **RETURNS** | The model's meta data. ~~Dict[str, Any]~~ | +### util.get_installed_models {#util.get_installed_models tag="function" new="3"} + +List all model packages installed in the current environment. This will include +any spaCy model that was packaged with [`spacy package`](/api/cli#package). +Under the hood, model packages expose a Python entry point that spaCy can check, +without having to load the model. + +> #### Example +> +> ```python +> model_names = util.get_installed_models() +> ``` + +| Name | Description | +| ----------- | ---------------------------------------------------------------------------------- | +| **RETURNS** | The string names of the models installed in the current environment. ~~List[str]~~ | + ### util.is_package {#util.is_package tag="function"} Check if string maps to a package installed via pip. Mainly used to validate diff --git a/website/docs/usage/embeddings-transformers.md b/website/docs/usage/embeddings-transformers.md index c2727f5b1..70562cf7e 100644 --- a/website/docs/usage/embeddings-transformers.md +++ b/website/docs/usage/embeddings-transformers.md @@ -11,6 +11,10 @@ next: /usage/training +If you're looking for details on using word vectors and semantic similarity, +check out the +[linguistic features docs](/usage/linguistic-features#vectors-similarity). + The key difference between [word vectors](#word-vectors) and contextual language diff --git a/website/docs/usage/v3.md b/website/docs/usage/v3.md index 837818a83..3111bf38e 100644 --- a/website/docs/usage/v3.md +++ b/website/docs/usage/v3.md @@ -10,6 +10,32 @@ menu: ## Summary {#summary} + + +
+ +
+ + + +- [Summary](#summary) +- [New features](#features) +- [Training & config system](#features-training) +- [Transformer-based pipelines](#features-transformers) +- [Custom models](#features-custom-models) +- [End-to-end project workflows](#features-projects) +- [New built-in components](#features-pipeline-components) +- [New custom component API](#features-components) +- [Python type hints](#features-types) +- [New methods & attributes](#new-methods) +- [New & updated documentation](#new-docs) +- [Backwards incompatibilities](#incompat) +- [Migrating from spaCy v2.x](#migrating) + + + +
+ ## New Features {#features} ### New training workflow and config system {#features-training} @@ -28,6 +54,8 @@ menu: ### Transformer-based pipelines {#features-transformers} +![Pipeline components listening to shared embedding component](../images/tok2vec-listener.svg) + - **Usage:** [Embeddings & Transformers](/usage/embeddings-transformers), @@ -46,8 +74,53 @@ menu: ### Custom models using any framework {#features-custom-models} + + + + +- **Thinc: ** + [Wrapping PyTorch, TensorFlow & MXNet](https://thinc.ai/docs/usage-frameworks) +- **API:** [Model architectures](/api/architectures), [`Pipe`](/api/pipe) + + + ### Manage end-to-end workflows with projects {#features-projects} + + +> #### Example +> +> ```cli +> # Clone a project template +> $ python -m spacy project clone example +> $ cd example +> # Download data assets +> $ python -m spacy project assets +> # Run a workflow +> $ python -m spacy project run train +> ``` + +spaCy projects let you manage and share **end-to-end spaCy workflows** for +different **use cases and domains**, and orchestrate training, packaging and +serving your custom models. You can start off by cloning a pre-defined project +template, adjust it to fit your needs, load in your data, train a model, export +it as a Python package and share the project templates with your team. spaCy +projects also make it easy to **integrate with other tools** in the data science +and machine learning ecosystem, including [DVC](/usage/projects#dvc) for data +version control, [Prodigy](/usage/projects#prodigy) for creating labelled data, +[Streamlit](/usage/projects#streamlit) for building interactive apps, +[FastAPI](/usage/projects#fastapi) for serving models in production, +[Ray](/usage/projects#ray) for parallel training, +[Weights & Biases](/usage/projects#wandb) for experiment tracking, and more! + + + - **Usage:** [spaCy projects](/usage/projects), @@ -59,6 +132,16 @@ menu: ### New built-in pipeline components {#features-pipeline-components} +spaCy v3.0 includes several new trainable and rule-based components that you can +add to your pipeline and customize for your use case: + +> #### Example +> +> ```python +> nlp = spacy.blank("en") +> nlp.add_pipe("lemmatizer") +> ``` + | Name | Description | | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [`SentenceRecognizer`](/api/sentencerecognizer) | Trainable component for sentence segmentation. | @@ -78,15 +161,37 @@ menu: ### New and improved pipeline component APIs {#features-components} -- `Language.factory`, `Language.component` -- `Language.analyze_pipes` -- Adding components from other models +> #### Example +> +> ```python +> @Language.component("my_component") +> def my_component(doc): +> return doc +> +> nlp.add_pipe("my_component") +> nlp.add_pipe("ner", source=other_nlp) +> nlp.analyze_pipes(pretty=True) +> ``` + +Defining, configuring, reusing, training and analyzing pipeline components is +now easier and more convenient. The `@Language.component` and +`@Language.factory` decorators let you register your component, define its +default configuration and meta data, like the attribute values it assigns and +requires. Any custom component can be included during training, and sourcing +components from existing pretrained models lets you **mix and match custom +pipelines**. The `nlp.analyze_pipes` method outputs structured information about +the current pipeline and its components, including the attributes they assign, +the scores they compute during training and whether any required attributes +aren't set. - **Usage:** [Custom components](/usage/processing-pipelines#custom_components), - [Defining components during training](/usage/training#config-components) -- **API:** [`Language`](/api/language) + [Defining components for training](/usage/training#config-components) +- **API:** [`@Language.component`](/api/language#component), + [`@Language.factory`](/api/language#factory), + [`Language.add_pipe`](/api/language#add_pipe), + [`Language.analyze_pipes`](/api/language#analyze_pipes) - **Implementation:** [`spacy/language.py`](https://github.com/explosion/spaCy/tree/develop/spacy/language.py) @@ -136,13 +241,14 @@ in your config and see validation errors if the argument values don't match. -### New methods, attributes and commands +### New methods, attributes and commands {#new-methods} The following methods, attributes and commands are new in spaCy v3.0. | Name | Description | | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | [`Token.lex`](/api/token#attributes) | Access a token's [`Lexeme`](/api/lexeme). | +| [`Token.morph`](/api/token#attributes) [`Token.morph_`](/api/token#attributes) | Access a token's morphological analysis. | | [`Language.select_pipes`](/api/language#select_pipes) | Contextmanager for enabling or disabling specific pipeline components for a block. | | [`Language.analyze_pipes`](/api/language#analyze_pipes) | [Analyze](/usage/processing-pipelines#analysis) components and their interdependencies. | | [`Language.resume_training`](/api/language#resume_training) | Experimental: continue training a pretrained model and initialize "rehearsal" for components that implement a `rehearse` method to prevent catastrophic forgetting. | @@ -153,9 +259,52 @@ The following methods, attributes and commands are new in spaCy v3.0. | [`Pipe.score`](/api/pipe#score) | Method on trainable pipeline components that returns a dictionary of evaluation scores. | | [`registry`](/api/top-level#registry) | Function registry to map functions to string names that can be referenced in [configs](/usage/training#config). | | [`util.load_meta`](/api/top-level#util.load_meta) [`util.load_config`](/api/top-level#util.load_config) | Updated helpers for loading a model's [`meta.json`](/api/data-formats#meta) and [`config.cfg`](/api/data-formats#config). | +| [`util.get_installed_models`](/api/top-level#util.get_installed_models) | Names of all models installed in the environment. | | [`init config`](/api/cli#init-config) [`init fill-config`](/api/cli#init-fill-config) [`debug config`](/api/cli#debug-config) | CLI commands for initializing, auto-filling and debugging [training configs](/usage/training). | | [`project`](/api/cli#project) | Suite of CLI commands for cloning, running and managing [spaCy projects](/usage/projects). | +### New and updated documentation {#new-docs} + + + +
+ +To help you get started with spaCy v3.0 and the new features, we've added +several new or rewritten documentation pages, including a new usage guide on +[embeddings, transformers and transfer learning](/usage/embeddings-transformers), +a guide on [training models](/usage/training) rewritten from scratch, a page +explaining the new [spaCy projects](/usage/projects) and updated usage +documentation on +[custom pipeline components](/usage/processing-pipelines#custom-components). +We've also added a bunch of new illustrations and new API reference pages +documenting spaCy's machine learning [model architectures](/api/architectures) +and the expected [data formats](/api/data-formats). API pages about +[pipeline components](/api/#architecture-pipeline) now include more information, +like the default config and implementation, and we've adopted a more detailed +format for documenting argument and return types. + +
+ +[![Library architecture](../images/architecture.svg)](/api) + +
+ + + +- **Usage: ** [Embeddings & Transformers](/usage/embeddings-transformers), + [Training models](/usage/training), [Projects](/usage/projects), + [Custom pipeline components](/usage/processing-pipelines#custom-components) +- **API Reference: ** [Library architecture](/api), + [Model architectures](/api/architectures), [Data formats](/api/data-formats) +- **New Classes: ** [`Example`](/api/example), [`Tok2Vec`](/api/tok2vec), + [`Transformer`](/api/transformer), [`Lemmatizer`](/api/lemmatizer), + [`Morphologizer`](/api/morphologizer), + [`AttributeRuler`](/api/attributeruler), + [`SentenceRecognizer`](/api/sentencerecognizer), [`Pipe`](/api/pipe), + [`Corpus`](/api/corpus) + + + ## Backwards Incompatibilities {#incompat} As always, we've tried to keep the breaking changes to a minimum and focus on @@ -212,15 +361,16 @@ Note that spaCy v3.0 now requires **Python 3.6+**. ### Removed or renamed API {#incompat-removed} -| Removed | Replacement | -| ------------------------------------------------------ | ----------------------------------------------------------------------------------------- | -| `Language.disable_pipes` | [`Language.select_pipes`](/api/language#select_pipes) | -| `GoldParse` | [`Example`](/api/example) | -| `GoldCorpus` | [`Corpus`](/api/corpus) | -| `KnowledgeBase.load_bulk` `KnowledgeBase.dump` | [`KnowledgeBase.from_disk`](/api/kb#from_disk) [`KnowledgeBase.to_disk`](/api/kb#to_disk) | -| `spacy debug-data` | [`spacy debug data`](/api/cli#debug-data) | -| `spacy profile` | [`spacy debug profile`](/api/cli#debug-profile) | -| `spacy link` `util.set_data_path` `util.get_data_path` | not needed, model symlinks are deprecated | +| Removed | Replacement | +| -------------------------------------------------------- | ----------------------------------------------------------------------------------------- | +| `Language.disable_pipes` | [`Language.select_pipes`](/api/language#select_pipes) | +| `GoldParse` | [`Example`](/api/example) | +| `GoldCorpus` | [`Corpus`](/api/corpus) | +| `KnowledgeBase.load_bulk` `KnowledgeBase.dump` | [`KnowledgeBase.from_disk`](/api/kb#from_disk) [`KnowledgeBase.to_disk`](/api/kb#to_disk) | +| `spacy init-model` | [`spacy init model`](/api/cli#init-model) | +| `spacy debug-data` | [`spacy debug data`](/api/cli#debug-data) | +| `spacy profile` | [`spacy debug profile`](/api/cli#debug-profile) | +| `spacy link`, `util.set_data_path`, `util.get_data_path` | not needed, model symlinks are deprecated | The following deprecated methods, attributes and arguments were removed in v3.0. Most of them have been **deprecated for a while** and many would previously @@ -236,7 +386,7 @@ on them. | `Language.tagger`, `Language.parser`, `Language.entity` | [`Language.get_pipe`](/api/language#get_pipe) | | keyword-arguments like `vocab=False` on `to_disk`, `from_disk`, `to_bytes`, `from_bytes` | `exclude=["vocab"]` | | `n_threads` argument on [`Tokenizer`](/api/tokenizer), [`Matcher`](/api/matcher), [`PhraseMatcher`](/api/phrasematcher) | `n_process` | -| `verbose` argument on [`Language.evaluate`] | logging | +| `verbose` argument on [`Language.evaluate`](/api/language#evaluate) | logging (`DEBUG`) | | `SentenceSegmenter` hook, `SimilarityHook` | [user hooks](/usage/processing-pipelines#custom-components-user-hooks), [`Sentencizer`](/api/sentencizer), [`SentenceRecognizer`](/api/sentenceregognizer) | ## Migrating from v2.x {#migrating} From aa6a7cd6e72bfd8515b7c3b6ddb4c0951c6513e6 Mon Sep 17 00:00:00 2001 From: Ines Montani Date: Fri, 21 Aug 2020 13:49:18 +0200 Subject: [PATCH 05/33] Update docs and consistency [ci skip] --- CONTRIBUTING.md | 12 +++++------ README.md | 5 ++--- spacy/tokenizer.pyx | 4 ++-- website/docs/usage/embeddings-transformers.md | 2 +- website/docs/usage/index.md | 4 ++-- website/docs/usage/linguistic-features.md | 14 ++++++------- website/docs/usage/processing-pipelines.md | 20 +++++++++---------- website/docs/usage/rule-based-matching.md | 10 +++++----- website/docs/usage/training.md | 2 +- website/docs/usage/v3.md | 5 +++-- website/src/styles/layout.sass | 5 ++++- 11 files changed, 43 insertions(+), 40 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 81cfbf8cb..0abde2abf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,7 +5,7 @@ Thanks for your interest in contributing to spaCy πŸŽ‰ The project is maintained by [@honnibal](https://github.com/honnibal) and [@ines](https://github.com/ines), and we'll do our best to help you get started. This page will give you a quick -overview of how things are organised and most importantly, how to get involved. +overview of how things are organized and most importantly, how to get involved. ## Table of contents @@ -195,7 +195,7 @@ modules in `.py` files, not Cython modules in `.pyx` and `.pxd` files.** ### Code formatting [`black`](https://github.com/ambv/black) is an opinionated Python code -formatter, optimised to produce readable code and small diffs. You can run +formatter, optimized to produce readable code and small diffs. You can run `black` from the command-line, or via your code editor. For example, if you're using [Visual Studio Code](https://code.visualstudio.com/), you can add the following to your `settings.json` to use `black` for formatting and auto-format @@ -286,7 +286,7 @@ Code that interacts with the file-system should accept objects that follow the If the function is user-facing and takes a path as an argument, it should check whether the path is provided as a string. Strings should be converted to `pathlib.Path` objects. Serialization and deserialization functions should always -accept **file-like objects**, as it makes the library io-agnostic. Working on +accept **file-like objects**, as it makes the library IO-agnostic. Working on buffers makes the code more general, easier to test, and compatible with Python 3's asynchronous IO. @@ -384,7 +384,7 @@ of Python and C++, with additional complexity and syntax from numpy. The many "traps for new players". Working in Cython is very rewarding once you're over the initial learning curve. As with C and C++, the first way you write something in Cython will often be the performance-optimal approach. In contrast, -Python optimisation generally requires a lot of experimentation. Is it faster to +Python optimization generally requires a lot of experimentation. Is it faster to have an `if item in my_dict` check, or to use `.get()`? What about `try`/`except`? Does this numpy operation create a copy? There's no way to guess the answers to these questions, and you'll usually be dissatisfied with your results β€” so @@ -400,7 +400,7 @@ Python. If it's not fast enough the first time, just switch to Cython. - [PEP 8 Style Guide for Python Code](https://www.python.org/dev/peps/pep-0008/) (python.org) - [Official Cython documentation](http://docs.cython.org/en/latest/) (cython.org) - [Writing C in Cython](https://explosion.ai/blog/writing-c-in-cython) (explosion.ai) -- [Multi-threading spaCy’s parser and named entity recogniser](https://explosion.ai/blog/multithreading-with-cython) (explosion.ai) +- [Multi-threading spaCy’s parser and named entity recognizer](https://explosion.ai/blog/multithreading-with-cython) (explosion.ai) ## Adding tests @@ -412,7 +412,7 @@ name. For example, tests for the `Tokenizer` can be found in all test files and test functions need to be prefixed with `test_`. When adding tests, make sure to use descriptive names, keep the code short and -concise and only test for one behaviour at a time. Try to `parametrize` test +concise and only test for one behavior at a time. Try to `parametrize` test cases wherever possible, use our pre-defined fixtures for spaCy components and avoid unnecessary imports. diff --git a/README.md b/README.md index 1fece1e5a..cef2a1fdd 100644 --- a/README.md +++ b/README.md @@ -49,9 +49,8 @@ It's commercial open-source software, released under the MIT license. ## πŸ’¬ Where to ask questions -The spaCy project is maintained by [@honnibal](https://github.com/honnibal) and -[@ines](https://github.com/ines), along with core contributors -[@svlandeg](https://github.com/svlandeg) and +The spaCy project is maintained by [@honnibal](https://github.com/honnibal), +[@ines](https://github.com/ines), [@svlandeg](https://github.com/svlandeg) and [@adrianeboyd](https://github.com/adrianeboyd). Please understand that we won't be able to provide individual support via email. We also believe that help is much more valuable if it's shared publicly, so that more people can benefit from diff --git a/spacy/tokenizer.pyx b/spacy/tokenizer.pyx index a13299fff..9fda1800b 100644 --- a/spacy/tokenizer.pyx +++ b/spacy/tokenizer.pyx @@ -47,9 +47,9 @@ cdef class Tokenizer: `infix_finditer` (callable): A function matching the signature of `re.compile(string).finditer` to find infixes. token_match (callable): A boolean function matching strings to be - recognised as tokens. + recognized as tokens. url_match (callable): A boolean function matching strings to be - recognised as tokens after considering prefixes and suffixes. + recognized as tokens after considering prefixes and suffixes. EXAMPLE: >>> tokenizer = Tokenizer(nlp.vocab) diff --git a/website/docs/usage/embeddings-transformers.md b/website/docs/usage/embeddings-transformers.md index 70562cf7e..33385ff51 100644 --- a/website/docs/usage/embeddings-transformers.md +++ b/website/docs/usage/embeddings-transformers.md @@ -184,7 +184,7 @@ yourself. For details on how to get started with training your own model, check out the [training quickstart](/usage/training#quickstart). - | Name | Description | | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `width` | The width of the vectors produced by the "upstream" [`Tok2Vec`](/api/tok2vec) component. ~~int~~ | | `upstream` | A string to identify the "upstream" `Tok2Vec` component to communicate with. The upstream name should either be the wildcard string `"*"`, or the name of the `Tok2Vec` component. You'll almost never have multiple upstream `Tok2Vec` components, so the wildcard string will almost always be fine. ~~str~~ | -| **CREATES** | The model using the architecture. ~~Model~~ | +| **CREATES** | The model using the architecture. ~~Model[List[Doc], List[Floats2d]]~~ | ### spacy.MultiHashEmbed.v1 {#MultiHashEmbed} @@ -139,15 +137,13 @@ definitions depending on the `Vocab` of the `Doc` object passed in. Vectors from pretrained static vectors can also be incorporated into the concatenated representation. - - | Name | Description | | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `width` | The output width. Also used as the width of the embedding tables. Recommended values are between `64` and `300`. ~~int~~ | | `rows` | The number of rows for the embedding tables. Can be low, due to the hashing trick. Embeddings for prefix, suffix and word shape use half as many rows. Recommended values are between `2000` and `10000`. ~~int~~ | | `also_embed_subwords` | Whether to use the `PREFIX`, `SUFFIX` and `SHAPE` features in the embeddings. If not using these, you may need more rows in your hash embeddings, as there will be increased chance of collisions. ~~bool~~ | | `also_use_static_vectors` | Whether to also use static word vectors. Requires a vectors table to be loaded in the [Doc](/api/doc) objects' vocab. ~~bool~~ | -| **CREATES** | The model using the architecture. ~~Model~~ | +| **CREATES** | The model using the architecture. ~~Model[List[Doc], List[Floats2d]]~~ | ### spacy.CharacterEmbed.v1 {#CharacterEmbed} @@ -178,15 +174,13 @@ concatenated. A hash-embedded vector of the `NORM` of the word is also concatenated on, and the result is then passed through a feed-forward network to construct a single vector to represent the information. - - | Name | Description | | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `width` | The width of the output vector and the `NORM` hash embedding. ~~int~~ | | `rows` | The number of rows in the `NORM` hash embedding table. ~~int~~ | | `nM` | The dimensionality of the character embeddings. Recommended values are between `16` and `64`. ~~int~~ | | `nC` | The number of UTF-8 bytes to embed per word. Recommended values are between `3` and `8`, although it may depend on the length of words in the language. ~~int~~ | -| **CREATES** | The model using the architecture. ~~Model~~ | +| **CREATES** | The model using the architecture. ~~Model[List[Doc], List[Floats2d]]~~ | ### spacy.MaxoutWindowEncoder.v1 {#MaxoutWindowEncoder} @@ -277,12 +271,10 @@ Embed [`Doc`](/api/doc) objects with their vocab's vectors table, applying a learned linear projection to control the dimensionality. See the documentation on [static vectors](/usage/embeddings-transformers#static-vectors) for details. - - | Name | Β Description | | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `nO` | Defaults to `None`. ~~Optional[int]~~ | -| `nM` | Defaults to `None`. ~~Optional[int]~~ | +| `nO` | The output width of the layer, after the linear projection. ~~Optional[int]~~ | +| `nM` | The width of the static vectors. ~~Optional[int]~~ | | `dropout` | Optional dropout rate. If set, it's applied per dimension over the whole batch. Defaults to `None`. ~~Optional[float]~~ | | `init_W` | The [initialization function](https://thinc.ai/docs/api-initializers). Defaults to [`glorot_uniform_init`](https://thinc.ai/docs/api-initializers#glorot_uniform_init). ~~Callable[[Ops, Tuple[int, ...]]], FloatsXd]~~ | | `key_attr` | Defaults to `"ORTH"`. ~~str~~ | @@ -311,7 +303,22 @@ architectures into your training config. > stride = 96 > ``` - +Load and wrap a transformer model from the Huggingface transformers library. +You can any transformer that has pretrained weights and a PyTorch +implementation. The `name` variable is passed through to the underlying +library, so it can be either a string or a path. If it's a string, the +pretrained weights will be downloaded via the transformers library if they are +not already available locally. + +In order to support longer documents, the `TransformerModel` layer allows you +to pass in a `get_spans` function that will divide up the `Doc` objects before +passing them through the transformer. Your spans are allowed to overlap or +exclude tokens. + +This layer outputs a `FullTransformerBatch` dataclass. In order to plug the +layer into most architectures, you'll probably need to map the raw transformer +output to token-aligned vectors using a layer such as `trfs2arrays`. + | Name | Description | | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -541,8 +548,6 @@ specific data and challenge. Stacked ensemble of a bag-of-words model and a neural network model. The neural network has an internal CNN Tok2Vec layer and uses attention. - - | Name | Description | | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `exclusive_classes` | Whether or not categories are mutually exclusive. ~~bool~~ | @@ -554,7 +559,7 @@ network has an internal CNN Tok2Vec layer and uses attention. | `ngram_size` | Determines the maximum length of the n-grams in the BOW model. For instance, `ngram_size=3`would give unigram, trigram and bigram features. ~~int~~ | | `dropout` | The dropout rate. ~~float~~ | | `nO` | Output dimension, determined by the number of different labels. If not set, the [`TextCategorizer`](/api/textcategorizer) component will set it when `begin_training` is called. ~~Optional[int]~~ | -| **CREATES** | The model using the architecture. ~~Model~~ | +| **CREATES** | The model using the architecture. ~~Model[List[Doc], Floats2d]~~ | ### spacy.TextCatCNN.v1 {#TextCatCNN} @@ -581,14 +586,12 @@ A neural network model where token vectors are calculated using a CNN. The vectors are mean pooled and used as features in a feed-forward network. This architecture is usually less accurate than the ensemble, but runs faster. - - | Name | Description | | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `exclusive_classes` | Whether or not categories are mutually exclusive. ~~bool~~ | | `tok2vec` | The [`tok2vec`](#tok2vec) layer of the model. ~~Model~~ | | `nO` | Output dimension, determined by the number of different labels. If not set, the [`TextCategorizer`](/api/textcategorizer) component will set it when `begin_training` is called. ~~Optional[int]~~ | -| **CREATES** | The model using the architecture. ~~Model~~ | +| **CREATES** | The model using the architecture. ~~Model[List[Doc], Floats2d]~~ | ### spacy.TextCatBOW.v1 {#TextCatBOW} @@ -606,15 +609,13 @@ architecture is usually less accurate than the ensemble, but runs faster. An ngram "bag-of-words" model. This architecture should run much faster than the others, but may not be as accurate, especially if texts are short. - - | Name | Description | | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `exclusive_classes` | Whether or not categories are mutually exclusive. ~~bool~~ | | `ngram_size` | Determines the maximum length of the n-grams in the BOW model. For instance, `ngram_size=3`would give unigram, trigram and bigram features. ~~int~~ | | `no_output_layer` | Whether or not to add an output layer to the model (`Softmax` activation if `exclusive_classes` is `True`, else `Logistic`. ~~bool~~ | | `nO` | Output dimension, determined by the number of different labels. If not set, the [`TextCategorizer`](/api/textcategorizer) component will set it when `begin_training` is called. ~~Optional[int]~~ | -| **CREATES** | The model using the architecture. ~~Model~~ | +| **CREATES** | The model using the architecture. ~~Model[List[Doc], Floats2d]~~ | ## Entity linking architectures {#entitylinker source="spacy/ml/models/entity_linker.py"} @@ -659,13 +660,11 @@ into the "real world". This requires 3 main components: The `EntityLinker` model architecture is a Thinc `Model` with a [`Linear`](https://thinc.ai/api-layers#linear) output layer. - - | Name | Description | | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `tok2vec` | The [`tok2vec`](#tok2vec) layer of the model. ~~Model~~ | | `nO` | Output dimension, determined by the length of the vectors encoding each entity in the KB. If the `nO` dimension is not set, the entity linking component will set it when `begin_training` is called. ~~Optional[int]~~ | -| **CREATES** | The model using the architecture. ~~Model~~ | +| **CREATES** | The model using the architecture. ~~Model[List[Doc], Floats2d]~~ | ### spacy.EmptyKB.v1 {#EmptyKB} From f5bcc102686e443e46147b400cec32136a609f75 Mon Sep 17 00:00:00 2001 From: Matthew Honnibal Date: Fri, 21 Aug 2020 15:34:54 +0200 Subject: [PATCH 09/33] Update architectures --- website/docs/api/architectures.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/docs/api/architectures.md b/website/docs/api/architectures.md index 993f25bbc..c74737b66 100644 --- a/website/docs/api/architectures.md +++ b/website/docs/api/architectures.md @@ -315,9 +315,9 @@ to pass in a `get_spans` function that will divide up the `Doc` objects before passing them through the transformer. Your spans are allowed to overlap or exclude tokens. -This layer outputs a `FullTransformerBatch` dataclass. In order to plug the -layer into most architectures, you'll probably need to map the raw transformer -output to token-aligned vectors using a layer such as `trfs2arrays`. +This layer is usually used directly by the `Transformer` component, which +allows you to share the transformer weights across your pipeline. For a layer +that's configured for use in other components, see `Tok2VecTransformer`. | Name | Description | From af36d77d01866d310b0258f69d11a23d829dc231 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 21 Aug 2020 15:56:03 +0200 Subject: [PATCH 10/33] fix typo in docstring --- spacy/tests/regression/test_issue4501-5000.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spacy/tests/regression/test_issue4501-5000.py b/spacy/tests/regression/test_issue4501-5000.py index 0d4ce9a30..d16ecc1e6 100644 --- a/spacy/tests/regression/test_issue4501-5000.py +++ b/spacy/tests/regression/test_issue4501-5000.py @@ -65,7 +65,7 @@ def test_issue4590(en_vocab): def test_issue4651_with_phrase_matcher_attr(): - """Test that the EntityRuler PhraseMatcher is deserialize correctly using + """Test that the EntityRuler PhraseMatcher is deserialized correctly using the method from_disk when the EntityRuler argument phrase_matcher_attr is specified. """ @@ -87,7 +87,7 @@ def test_issue4651_with_phrase_matcher_attr(): def test_issue4651_without_phrase_matcher_attr(): - """Test that the EntityRuler PhraseMatcher is deserialize correctly using + """Test that the EntityRuler PhraseMatcher is deserialized correctly using the method from_disk when the EntityRuler argument phrase_matcher_attr is not specified. """ From 74cb6d39d0d1f00af10a9b521aec36206baf457f Mon Sep 17 00:00:00 2001 From: Ines Montani Date: Fri, 21 Aug 2020 16:11:38 +0200 Subject: [PATCH 11/33] Update docs [ci skip] --- website/docs/api/architectures.md | 49 +++++++-------- website/docs/usage/architectures.md | 92 +++++++++++++++++++++++++++++ website/meta/sidebars.json | 5 ++ website/meta/type-annotations.json | 2 + website/src/styles/code.module.sass | 2 +- 5 files changed, 125 insertions(+), 25 deletions(-) create mode 100644 website/docs/usage/architectures.md diff --git a/website/docs/api/architectures.md b/website/docs/api/architectures.md index c74737b66..fd88434f1 100644 --- a/website/docs/api/architectures.md +++ b/website/docs/api/architectures.md @@ -114,7 +114,7 @@ argument that connects to the shared `tok2vec` component in the pipeline. | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `width` | The width of the vectors produced by the "upstream" [`Tok2Vec`](/api/tok2vec) component. ~~int~~ | | `upstream` | A string to identify the "upstream" `Tok2Vec` component to communicate with. The upstream name should either be the wildcard string `"*"`, or the name of the `Tok2Vec` component. You'll almost never have multiple upstream `Tok2Vec` components, so the wildcard string will almost always be fine. ~~str~~ | -| **CREATES** | The model using the architecture. ~~Model[List[Doc], List[Floats2d]]~~ | +| **CREATES** | The model using the architecture. ~~Model[List[Doc], List[Floats2d]]~~ | ### spacy.MultiHashEmbed.v1 {#MultiHashEmbed} @@ -143,7 +143,7 @@ representation. | `rows` | The number of rows for the embedding tables. Can be low, due to the hashing trick. Embeddings for prefix, suffix and word shape use half as many rows. Recommended values are between `2000` and `10000`. ~~int~~ | | `also_embed_subwords` | Whether to use the `PREFIX`, `SUFFIX` and `SHAPE` features in the embeddings. If not using these, you may need more rows in your hash embeddings, as there will be increased chance of collisions. ~~bool~~ | | `also_use_static_vectors` | Whether to also use static word vectors. Requires a vectors table to be loaded in the [Doc](/api/doc) objects' vocab. ~~bool~~ | -| **CREATES** | The model using the architecture. ~~Model[List[Doc], List[Floats2d]]~~ | +| **CREATES** | The model using the architecture. ~~Model[List[Doc], List[Floats2d]]~~ | ### spacy.CharacterEmbed.v1 {#CharacterEmbed} @@ -180,7 +180,7 @@ construct a single vector to represent the information. | `rows` | The number of rows in the `NORM` hash embedding table. ~~int~~ | | `nM` | The dimensionality of the character embeddings. Recommended values are between `16` and `64`. ~~int~~ | | `nC` | The number of UTF-8 bytes to embed per word. Recommended values are between `3` and `8`, although it may depend on the length of words in the language. ~~int~~ | -| **CREATES** | The model using the architecture. ~~Model[List[Doc], List[Floats2d]]~~ | +| **CREATES** | The model using the architecture. ~~Model[List[Doc], List[Floats2d]]~~ | ### spacy.MaxoutWindowEncoder.v1 {#MaxoutWindowEncoder} @@ -273,8 +273,8 @@ on [static vectors](/usage/embeddings-transformers#static-vectors) for details. | Name | Β Description | | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `nO` | The output width of the layer, after the linear projection. ~~Optional[int]~~ | -| `nM` | The width of the static vectors. ~~Optional[int]~~ | +| `nO` | The output width of the layer, after the linear projection. ~~Optional[int]~~ | +| `nM` | The width of the static vectors. ~~Optional[int]~~ | | `dropout` | Optional dropout rate. If set, it's applied per dimension over the whole batch. Defaults to `None`. ~~Optional[float]~~ | | `init_W` | The [initialization function](https://thinc.ai/docs/api-initializers). Defaults to [`glorot_uniform_init`](https://thinc.ai/docs/api-initializers#glorot_uniform_init). ~~Callable[[Ops, Tuple[int, ...]]], FloatsXd]~~ | | `key_attr` | Defaults to `"ORTH"`. ~~str~~ | @@ -303,22 +303,23 @@ architectures into your training config. > stride = 96 > ``` -Load and wrap a transformer model from the Huggingface transformers library. -You can any transformer that has pretrained weights and a PyTorch -implementation. The `name` variable is passed through to the underlying -library, so it can be either a string or a path. If it's a string, the -pretrained weights will be downloaded via the transformers library if they are -not already available locally. - -In order to support longer documents, the `TransformerModel` layer allows you -to pass in a `get_spans` function that will divide up the `Doc` objects before -passing them through the transformer. Your spans are allowed to overlap or -exclude tokens. - -This layer is usually used directly by the `Transformer` component, which -allows you to share the transformer weights across your pipeline. For a layer -that's configured for use in other components, see `Tok2VecTransformer`. +Load and wrap a transformer model from the +[HuggingFace `transformers`](https://huggingface.co/transformers) library. You +can any transformer that has pretrained weights and a PyTorch implementation. +The `name` variable is passed through to the underlying library, so it can be +either a string or a path. If it's a string, the pretrained weights will be +downloaded via the transformers library if they are not already available +locally. +In order to support longer documents, the +[TransformerModel](/api/architectures#TransformerModel) layer allows you to pass +in a `get_spans` function that will divide up the [`Doc`](/api/doc) objects +before passing them through the transformer. Your spans are allowed to overlap +or exclude tokens. This layer is usually used directly by the +[`Transformer`](/api/transformer) component, which allows you to share the +transformer weights across your pipeline. For a layer that's configured for use +in other components, see +[Tok2VecTransformer](/api/architectures#Tok2VecTransformer). | Name | Description | | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -559,7 +560,7 @@ network has an internal CNN Tok2Vec layer and uses attention. | `ngram_size` | Determines the maximum length of the n-grams in the BOW model. For instance, `ngram_size=3`would give unigram, trigram and bigram features. ~~int~~ | | `dropout` | The dropout rate. ~~float~~ | | `nO` | Output dimension, determined by the number of different labels. If not set, the [`TextCategorizer`](/api/textcategorizer) component will set it when `begin_training` is called. ~~Optional[int]~~ | -| **CREATES** | The model using the architecture. ~~Model[List[Doc], Floats2d]~~ | +| **CREATES** | The model using the architecture. ~~Model[List[Doc], Floats2d]~~ | ### spacy.TextCatCNN.v1 {#TextCatCNN} @@ -591,7 +592,7 @@ architecture is usually less accurate than the ensemble, but runs faster. | `exclusive_classes` | Whether or not categories are mutually exclusive. ~~bool~~ | | `tok2vec` | The [`tok2vec`](#tok2vec) layer of the model. ~~Model~~ | | `nO` | Output dimension, determined by the number of different labels. If not set, the [`TextCategorizer`](/api/textcategorizer) component will set it when `begin_training` is called. ~~Optional[int]~~ | -| **CREATES** | The model using the architecture. ~~Model[List[Doc], Floats2d]~~ | +| **CREATES** | The model using the architecture. ~~Model[List[Doc], Floats2d]~~ | ### spacy.TextCatBOW.v1 {#TextCatBOW} @@ -615,7 +616,7 @@ others, but may not be as accurate, especially if texts are short. | `ngram_size` | Determines the maximum length of the n-grams in the BOW model. For instance, `ngram_size=3`would give unigram, trigram and bigram features. ~~int~~ | | `no_output_layer` | Whether or not to add an output layer to the model (`Softmax` activation if `exclusive_classes` is `True`, else `Logistic`. ~~bool~~ | | `nO` | Output dimension, determined by the number of different labels. If not set, the [`TextCategorizer`](/api/textcategorizer) component will set it when `begin_training` is called. ~~Optional[int]~~ | -| **CREATES** | The model using the architecture. ~~Model[List[Doc], Floats2d]~~ | +| **CREATES** | The model using the architecture. ~~Model[List[Doc], Floats2d]~~ | ## Entity linking architectures {#entitylinker source="spacy/ml/models/entity_linker.py"} @@ -664,7 +665,7 @@ The `EntityLinker` model architecture is a Thinc `Model` with a | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `tok2vec` | The [`tok2vec`](#tok2vec) layer of the model. ~~Model~~ | | `nO` | Output dimension, determined by the length of the vectors encoding each entity in the KB. If the `nO` dimension is not set, the entity linking component will set it when `begin_training` is called. ~~Optional[int]~~ | -| **CREATES** | The model using the architecture. ~~Model[List[Doc], Floats2d]~~ | +| **CREATES** | The model using the architecture. ~~Model[List[Doc], Floats2d]~~ | ### spacy.EmptyKB.v1 {#EmptyKB} diff --git a/website/docs/usage/architectures.md b/website/docs/usage/architectures.md new file mode 100644 index 000000000..e9dddfed7 --- /dev/null +++ b/website/docs/usage/architectures.md @@ -0,0 +1,92 @@ +--- +title: Layers and Model Architectures +teaser: Power spaCy components with custom neural networks +menu: + - ['Type Signatures', 'type-sigs'] + - ['Defining Sublayers', 'sublayers'] + - ['PyTorch & TensorFlow', 'frameworks'] + - ['Trainable Components', 'components'] +--- + +​ A **model architecture** is a function that wires up a +[Thinc `Model`](https://thinc.ai/docs/api-model) instance, which you can then +use in a component or as a layer of a larger network. You can use Thinc as a +thin wrapper around frameworks such as PyTorch, TensorFlow or MXNet, or you can +implement your logic in Thinc directly. ​ spaCy's built-in components will never +construct their `Model` instances themselves, so you won't have to subclass the +component to change its model architecture. You can just **update the config** +so that it refers to a different registered function. Once the component has +been created, its model instance has already been assigned, so you cannot change +its model architecture. The architecture is like a recipe for the network, and +you can't change the recipe once the dish has already been prepared. You have to +make a new one. ​ + +## Type signatures {#type-sigs} + +​ The Thinc `Model` class is a **generic type** that can specify its input and +output types. Python uses a square-bracket notation for this, so the type +~~Model[List, Dict]~~ says that each batch of inputs to the model will be a +list, and the outputs will be a dictionary. Both `typing.List` and `typing.Dict` +are also generics, allowing you to be more specific about the data. For +instance, you can write ~~Model[List[Doc], Dict[str, float]]~~ to specify that +the model expects a list of [`Doc`](/api/doc) objects as input, and returns a +dictionary mapping strings to floats. Some of the most common types you'll see +are: ​ + +| Type | Description | +| ------------------ | ---------------------------------------------------------------------------------------------------- | +| ~~List[Doc]~~ | A batch of [`Doc`](/api/doc) objects. Most components expect their models to take this as input. | +| ~~Floats2d~~ | A two-dimensional `numpy` or `cupy` array of floats. Usually 32-bit. | +| ~~Ints2d~~ | A two-dimensional `numpy` or `cupy` array of integers. Common dtypes include uint64, int32 and int8. | +| ~~List[Floats2d]~~ | A list of two-dimensional arrays, generally with one array per `Doc` and one row per token. | +| ~~Ragged~~ | A container to handle variable-length sequence data in an unpadded contiguous array. | +| ~~Padded~~ | A container to handle variable-length sequence data in a passed contiguous array. | + +The model type-signatures help you figure out which model architectures and +components can fit together. For instance, the +[`TextCategorizer`](/api/textcaregorizer) class expects a model typed +~~Model[List[Doc], Floats2d]~~, because the model will predict one row of +category probabilities per `Doc`. In contrast, the `Tagger` class expects a +model typed ~~Model[List[Doc], List[Floats2d]]~~, because it needs to predict +one row of probabilities per token. ​ There's no guarantee that two models with +the same type-signature can be used interchangeably. There are many other ways +they could be incompatible. However, if the types don't match, they almost +surely _won't_ be compatible. This little bit of validation goes a long way, +especially if you configure your editor or other tools to highlight these errors +early. Thinc will also verify that your types match correctly when your config +file is processed at the beginning of training. ​ + +## Defining sublayers {#sublayers} + +​ Model architecture functions often accept sublayers as arguments, so that you +can try substituting a different layer into the network. Depending on how the +architecture function is structured, you might be able to define your network +structure entirely through the [config system](/usage/training#config), using +layers that have already been defined. ​The +[transformers documentation](/usage/embeddings-transformers#transformers) +section shows a common example of swapping in a different sublayer. In most NLP +neural network models, the most important parts of the network are what we refer +to as the +[embed and encode](https://explosion.ai/blog/embed-encode-attend-predict) steps. +These steps together compute dense, context-sensitive representations of the +tokens. Most of spaCy's default architectures accept a `tok2vec` layer as an +argument, so you can control this important part of the network separately. This +makes it easy to switch between transformer, CNN, BiLSTM or other feature +extraction approaches. And if you want to define your own solution, all you need +to do is register a ~~Model[List[Doc], List[Floats2d]]~~ architecture function, +and you'll be able to try it out in any of spaCy components. ​ + +### Registering new architectures + +- Recap concept, link to config docs. ​ + +## Wrapping PyTorch, TensorFlow and other frameworks {#frameworks} + +- Explain concept +- Link off to notebook ​ + +## Models for trainable components {#components} + +- Interaction with `predict`, `get_loss` and `set_annotations` +- Initialization life-cycle with `begin_training`. +- Link to relation extraction notebook. diff --git a/website/meta/sidebars.json b/website/meta/sidebars.json index c830619c5..4840eb537 100644 --- a/website/meta/sidebars.json +++ b/website/meta/sidebars.json @@ -24,6 +24,11 @@ "tag": "new" }, { "text": "Training Models", "url": "/usage/training", "tag": "new" }, + { + "text": "Layers & Model Architectures", + "url": "/usage/architectures", + "tag": "new" + }, { "text": "spaCy Projects", "url": "/usage/projects", "tag": "new" }, { "text": "Saving & Loading", "url": "/usage/saving-loading" }, { "text": "Visualizers", "url": "/usage/visualizers" } diff --git a/website/meta/type-annotations.json b/website/meta/type-annotations.json index 3cfcf5f75..b1d94403d 100644 --- a/website/meta/type-annotations.json +++ b/website/meta/type-annotations.json @@ -29,6 +29,8 @@ "Optimizer": "https://thinc.ai/docs/api-optimizers", "Model": "https://thinc.ai/docs/api-model", "Ragged": "https://thinc.ai/docs/api-types#ragged", + "Padded": "https://thinc.ai/docs/api-types#padded", + "Ints2d": "https://thinc.ai/docs/api-types#types", "Floats2d": "https://thinc.ai/docs/api-types#types", "Floats3d": "https://thinc.ai/docs/api-types#types", "FloatsXd": "https://thinc.ai/docs/api-types#types", diff --git a/website/src/styles/code.module.sass b/website/src/styles/code.module.sass index 2d213d001..aa1f499dd 100644 --- a/website/src/styles/code.module.sass +++ b/website/src/styles/code.module.sass @@ -67,7 +67,7 @@ border: 0 // Special style for types in API tables - td > &:last-child + td:not(:first-child) > &:last-child display: block border-top: 1px dotted var(--color-subtle) border-radius: 0 From 2cc4640385523f8b077d374b118cf83de91f7d87 Mon Sep 17 00:00:00 2001 From: Ines Montani Date: Fri, 21 Aug 2020 16:21:55 +0200 Subject: [PATCH 12/33] Update docs [ci skip] --- .../docs/usage/{architectures.md => layers-architectures.md} | 3 ++- website/docs/usage/training.md | 2 +- website/docs/usage/v3.md | 4 +++- website/meta/sidebars.json | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) rename website/docs/usage/{architectures.md => layers-architectures.md} (98%) diff --git a/website/docs/usage/architectures.md b/website/docs/usage/layers-architectures.md similarity index 98% rename from website/docs/usage/architectures.md rename to website/docs/usage/layers-architectures.md index e9dddfed7..8d26a4139 100644 --- a/website/docs/usage/architectures.md +++ b/website/docs/usage/layers-architectures.md @@ -6,6 +6,7 @@ menu: - ['Defining Sublayers', 'sublayers'] - ['PyTorch & TensorFlow', 'frameworks'] - ['Trainable Components', 'components'] +next: /usage/projects --- ​ A **model architecture** is a function that wires up a @@ -44,7 +45,7 @@ are: ​ The model type-signatures help you figure out which model architectures and components can fit together. For instance, the -[`TextCategorizer`](/api/textcaregorizer) class expects a model typed +[`TextCategorizer`](/api/textcategorizer) class expects a model typed ~~Model[List[Doc], Floats2d]~~, because the model will predict one row of category probabilities per `Doc`. In contrast, the `Tagger` class expects a model typed ~~Model[List[Doc], List[Floats2d]]~~, because it needs to predict diff --git a/website/docs/usage/training.md b/website/docs/usage/training.md index 116561cd2..00eb2b882 100644 --- a/website/docs/usage/training.md +++ b/website/docs/usage/training.md @@ -1,6 +1,6 @@ --- title: Training Models -next: /usage/projects +next: /usage/layers-architectures menu: - ['Introduction', 'basics'] - ['Quickstart', 'quickstart'] diff --git a/website/docs/usage/v3.md b/website/docs/usage/v3.md index d71ecba31..b017dcdab 100644 --- a/website/docs/usage/v3.md +++ b/website/docs/usage/v3.md @@ -292,7 +292,9 @@ format for documenting argument and return types. - **Usage: ** [Embeddings & Transformers](/usage/embeddings-transformers), - [Training models](/usage/training), [Projects](/usage/projects), + [Training models](/usage/training), + [Layers & Architectures](/usage/layers-architectures), + [Projects](/usage/projects), [Custom pipeline components](/usage/processing-pipelines#custom-components), [Custom tokenizers](/usage/linguistic-features#custom-tokenizer) - **API Reference: ** [Library architecture](/api), diff --git a/website/meta/sidebars.json b/website/meta/sidebars.json index 4840eb537..94fbc2492 100644 --- a/website/meta/sidebars.json +++ b/website/meta/sidebars.json @@ -26,7 +26,7 @@ { "text": "Training Models", "url": "/usage/training", "tag": "new" }, { "text": "Layers & Model Architectures", - "url": "/usage/architectures", + "url": "/usage/layers-architectures", "tag": "new" }, { "text": "spaCy Projects", "url": "/usage/projects", "tag": "new" }, From e92bd6e1c1d480214c9bdabfdd869b22f1ac317a Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 21 Aug 2020 17:42:19 +0200 Subject: [PATCH 13/33] alphabetize training lists --- website/docs/api/data-formats.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/website/docs/api/data-formats.md b/website/docs/api/data-formats.md index 8b67aa263..56ce663ec 100644 --- a/website/docs/api/data-formats.md +++ b/website/docs/api/data-formats.md @@ -131,22 +131,22 @@ process that are used when you run [`spacy train`](/api/cli#train). | Name | Description | | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `seed` | The random seed. Defaults to variable `${system.seed}`. ~~int~~ | -| `dropout` | The dropout rate. Defaults to `0.1`. ~~float~~ | | `accumulate_gradient` | Whether to divide the batch up into substeps. Defaults to `1`. ~~int~~ | +| `batcher` | Callable that takes an iterator of [`Doc`](/api/doc) objects and yields batches of `Doc`s. Defaults to [`batch_by_words`](/api/top-level#batch_by_words). ~~Callable[[Iterator[Doc], Iterator[List[Doc]]]]~~ | +| `dev_corpus` | Callable that takes the current `nlp` object and yields [`Example`](/api/example) objects. Defaults to [`Corpus`](/api/corpus). ~~Callable[[Language], Iterator[Example]]~~ | +| `dropout` | The dropout rate. Defaults to `0.1`. ~~float~~ | +| `eval_frequency` | How often to evaluate during training (steps). Defaults to `200`. ~~int~~ | +| `frozen_components` | Pipeline component names that are "frozen" and shouldn't be updated during training. See [here](/usage/training#config-components) for details. Defaults to `[]`. ~~List[str]~~ | | `init_tok2vec` | Optional path to pretrained tok2vec weights created with [`spacy pretrain`](/api/cli#pretrain). Defaults to variable `${paths.init_tok2vec}`. ~~Optional[str]~~ | -| `raw_text` | Optional path to a jsonl file with unlabelled text documents for a [rehearsal](/api/language#rehearse) step. Defaults to variable `${paths.raw}`. ~~Optional[str]~~ | -| `vectors` | Model name or path to model containing pretrained word vectors to use, e.g. created with [`init model`](/api/cli#init-model). Defaults to `null`. ~~Optional[str]~~ | -| `patience` | How many steps to continue without improvement in evaluation score. Defaults to `1600`. ~~int~~ | | `max_epochs` | Maximum number of epochs to train for. Defaults to `0`. ~~int~~ | | `max_steps` | Maximum number of update steps to train for. Defaults to `20000`. ~~int~~ | -| `eval_frequency` | How often to evaluate during training (steps). Defaults to `200`. ~~int~~ | -| `score_weights` | Score names shown in metrics mapped to their weight towards the final weighted score. See [here](/usage/training#metrics) for details. Defaults to `{}`. ~~Dict[str, float]~~ | -| `frozen_components` | Pipeline component names that are "frozen" and shouldn't be updated during training. See [here](/usage/training#config-components) for details. Defaults to `[]`. ~~List[str]~~ | -| `train_corpus` | Callable that takes the current `nlp` object and yields [`Example`](/api/example) objects. Defaults to [`Corpus`](/api/corpus). ~~Callable[[Language], Iterator[Example]]~~ | -| `dev_corpus` | Callable that takes the current `nlp` object and yields [`Example`](/api/example) objects. Defaults to [`Corpus`](/api/corpus). ~~Callable[[Language], Iterator[Example]]~~ | -| `batcher` | Callable that takes an iterator of [`Doc`](/api/doc) objects and yields batches of `Doc`s. Defaults to [`batch_by_words`](/api/top-level#batch_by_words). ~~Callable[[Iterator[Doc], Iterator[List[Doc]]]]~~ | | `optimizer` | The optimizer. The learning rate schedule and other settings can be configured as part of the optimizer. Defaults to [`Adam`](https://thinc.ai/docs/api-optimizers#adam). ~~Optimizer~~ | +| `patience` | How many steps to continue without improvement in evaluation score. Defaults to `1600`. ~~int~~ | +| `raw_text` | Optional path to a jsonl file with unlabelled text documents for a [rehearsal](/api/language#rehearse) step. Defaults to variable `${paths.raw}`. ~~Optional[str]~~ | +| `score_weights` | Score names shown in metrics mapped to their weight towards the final weighted score. See [here](/usage/training#metrics) for details. Defaults to `{}`. ~~Dict[str, float]~~ | +| `seed` | The random seed. Defaults to variable `${system.seed}`. ~~int~~ | +| `train_corpus` | Callable that takes the current `nlp` object and yields [`Example`](/api/example) objects. Defaults to [`Corpus`](/api/corpus). ~~Callable[[Language], Iterator[Example]]~~ | +| `vectors` | Model name or path to model containing pretrained word vectors to use, e.g. created with [`init model`](/api/cli#init-model). Defaults to `null`. ~~Optional[str]~~ | ### pretraining {#config-pretraining tag="section,optional"} From 518a1f97f32ca63615567a50d6716f4ba5885acc Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 21 Aug 2020 17:55:15 +0200 Subject: [PATCH 14/33] remove outdated TODO's --- website/docs/api/data-formats.md | 2 -- website/docs/usage/training.md | 5 ----- 2 files changed, 7 deletions(-) diff --git a/website/docs/api/data-formats.md b/website/docs/api/data-formats.md index 56ce663ec..727c0f35c 100644 --- a/website/docs/api/data-formats.md +++ b/website/docs/api/data-formats.md @@ -127,8 +127,6 @@ $ python -m spacy train config.cfg --paths.train ./corpus/train.spacy This section defines settings and controls for the training and evaluation process that are used when you run [`spacy train`](/api/cli#train). - - | Name | Description | | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `accumulate_gradient` | Whether to divide the batch up into substeps. Defaults to `1`. ~~int~~ | diff --git a/website/docs/usage/training.md b/website/docs/usage/training.md index 116561cd2..5f188a75a 100644 --- a/website/docs/usage/training.md +++ b/website/docs/usage/training.md @@ -104,11 +104,6 @@ workflows, from data preprocessing to training and packaging your model. ## Training config {#config} - - Training config files include all **settings and hyperparameters** for training your model. Instead of providing lots of arguments on the command line, you only need to pass your `config.cfg` file to [`spacy train`](/api/cli#train). Under From c6659e37d8a1d3754c52f2333631e75fcc96720e Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 21 Aug 2020 18:02:20 +0200 Subject: [PATCH 15/33] small fixes --- website/docs/usage/training.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/website/docs/usage/training.md b/website/docs/usage/training.md index 5f188a75a..d738cfd04 100644 --- a/website/docs/usage/training.md +++ b/website/docs/usage/training.md @@ -35,8 +35,8 @@ ready-to-use spaCy models. The recommended way to train your spaCy models is via the [`spacy train`](/api/cli#train) command on the command line. It only needs a single [`config.cfg`](#config) **configuration file** that includes all settings -and hyperparameters. You can optionally [overwritten](#config-overrides) -settings on the command line, and load in a Python file to register +and hyperparameters. You can optionally [overwrite](#config-overrides) settings +on the command line, and load in a Python file to register [custom functions](#custom-code) and architectures. This quickstart widget helps you generate a starter config with the **recommended settings** for your specific use case. It's also available in spaCy as the @@ -82,7 +82,7 @@ $ python -m spacy init fill-config base_config.cfg config.cfg Instead of exporting your starter config from the quickstart widget and auto-filling it, you can also use the [`init config`](/api/cli#init-config) -command and specify your requirement and settings and CLI arguments. You can now +command and specify your requirement and settings as CLI arguments. You can now add your data and run [`train`](/api/cli#train) with your config. See the [`convert`](/api/cli#convert) command for details on how to convert your data to spaCy's binary `.spacy` format. You can either include the data paths in the @@ -121,9 +121,10 @@ Some of the main advantages and features of spaCy's training config are: functions like [model architectures](/api/architectures), [optimizers](https://thinc.ai/docs/api-optimizers) or [schedules](https://thinc.ai/docs/api-schedules) and define arguments that are - passed into them. You can also register your own functions to define - [custom architectures](#custom-functions), reference them in your config and - tweak their parameters. + passed into them. You can also + [register your own functions](#custom-functions) to define custom + architectures or methods, reference them in your config and tweak their + parameters. - **Interpolation.** If you have hyperparameters or other settings used by multiple components, define them once and reference them as [variables](#config-interpolation). From dc98f69b57dd5b786dffbbefc9cfc23ea53dc724 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 21 Aug 2020 18:10:21 +0200 Subject: [PATCH 16/33] alphabetize registries --- website/docs/api/top-level.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/website/docs/api/top-level.md b/website/docs/api/top-level.md index 9c65b2982..797fa0191 100644 --- a/website/docs/api/top-level.md +++ b/website/docs/api/top-level.md @@ -299,20 +299,20 @@ factories. | Registry name | Description | | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `architectures` | Registry for functions that create [model architectures](/api/architectures). Can be used to register custom model architectures and reference them in the `config.cfg`. | -| `factories` | Registry for functions that create [pipeline components](/usage/processing-pipelines#custom-components). Added automatically when you use the `@spacy.component` decorator and also reads from [entry points](/usage/saving-loading#entry-points). | -| `tokenizers` | Registry for tokenizer factories. Registered functions should return a callback that receives the `nlp` object and returns a [`Tokenizer`](/api/tokenizer) or a custom callable. | -| `languages` | Registry for language-specific `Language` subclasses. Automatically reads from [entry points](/usage/saving-loading#entry-points). | -| `lookups` | Registry for large lookup tables available via `vocab.lookups`. | -| `displacy_colors` | Registry for custom color scheme for the [`displacy` NER visualizer](/usage/visualizers). Automatically reads from [entry points](/usage/saving-loading#entry-points). | | `assets` | Registry for data assets, knowledge bases etc. | -| `callbacks` | Registry for custom callbacks to [modify the `nlp` object](/usage/training#custom-code-nlp-callbacks) before training. | -| `readers` | Registry for training and evaluation data readers like [`Corpus`](/api/corpus). | | `batchers` | Registry for training and evaluation [data batchers](#batchers). | -| `optimizers` | Registry for functions that create [optimizers](https://thinc.ai/docs/api-optimizers). | -| `schedules` | Registry for functions that create [schedules](https://thinc.ai/docs/api-schedules). | -| `layers` | Registry for functions that create [layers](https://thinc.ai/docs/api-layers). | -| `losses` | Registry for functions that create [losses](https://thinc.ai/docs/api-loss). | +| `callbacks` | Registry for custom callbacks to [modify the `nlp` object](/usage/training#custom-code-nlp-callbacks) before training. | +| `displacy_colors` | Registry for custom color scheme for the [`displacy` NER visualizer](/usage/visualizers). Automatically reads from [entry points](/usage/saving-loading#entry-points). | +| `factories` | Registry for functions that create [pipeline components](/usage/processing-pipelines#custom-components). Added automatically when you use the `@spacy.component` decorator and also reads from [entry points](/usage/saving-loading#entry-points). | | `initializers` | Registry for functions that create [initializers](https://thinc.ai/docs/api-initializers). | +| `languages` | Registry for language-specific `Language` subclasses. Automatically reads from [entry points](/usage/saving-loading#entry-points). | +| `layers` | Registry for functions that create [layers](https://thinc.ai/docs/api-layers). | +| `lookups` | Registry for large lookup tables available via `vocab.lookups`. | +| `losses` | Registry for functions that create [losses](https://thinc.ai/docs/api-loss). | +| `optimizers` | Registry for functions that create [optimizers](https://thinc.ai/docs/api-optimizers). | +| `readers` | Registry for training and evaluation data readers like [`Corpus`](/api/corpus). | +| `schedules` | Registry for functions that create [schedules](https://thinc.ai/docs/api-schedules). | +| `tokenizers` | Registry for tokenizer factories. Registered functions should return a callback that receives the `nlp` object and returns a [`Tokenizer`](/api/tokenizer) or a custom callable. | ### spacy-transformers registry {#registry-transformers} From ad2332d4b7758aeccc97fbf05fcd03097d51ae2e Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 21 Aug 2020 18:10:31 +0200 Subject: [PATCH 17/33] alphabetize registries --- website/docs/usage/training.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/website/docs/usage/training.md b/website/docs/usage/training.md index d738cfd04..f3d349b56 100644 --- a/website/docs/usage/training.md +++ b/website/docs/usage/training.md @@ -222,21 +222,21 @@ passed to the component factory as arguments. This lets you configure the model settings and hyperparameters. If a component block defines a `source`, the component will be copied over from an existing pretrained model, with its existing weights. This lets you include an already trained component in your -model pipeline, or update a pretrained components with more data specific to +model pipeline, or update a pretrained component with more data specific to your use case. ```ini ### config.cfg (excerpt) [components] -# "parser" and "ner" are sourced from pretrained model +# "parser" and "ner" are sourced from a pretrained model [components.parser] source = "en_core_web_sm" [components.ner] source = "en_core_web_sm" -# "textcat" and "custom" are created blank from built-in / custom factory +# "textcat" and "custom" are created blank from a built-in / custom factory [components.textcat] factory = "textcat" @@ -290,7 +290,7 @@ batch_size = 128 ``` To refer to a function instead, you can make `[training.batch_size]` its own -section and use the `@` syntax specify the function and its arguments – in this +section and use the `@` syntax to specify the function and its arguments – in this case [`compounding.v1`](https://thinc.ai/docs/api-schedules#compounding) defined in the [function registry](/api/top-level#registry). All other values defined in the block are passed to the function as keyword arguments when it's initialized. From da48c6a2a2c67d1087e073cd92530449a03dc904 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 21 Aug 2020 18:25:26 +0200 Subject: [PATCH 18/33] several small updates --- website/docs/usage/training.md | 35 +++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/website/docs/usage/training.md b/website/docs/usage/training.md index f3d349b56..fcc1a44d2 100644 --- a/website/docs/usage/training.md +++ b/website/docs/usage/training.md @@ -222,8 +222,8 @@ passed to the component factory as arguments. This lets you configure the model settings and hyperparameters. If a component block defines a `source`, the component will be copied over from an existing pretrained model, with its existing weights. This lets you include an already trained component in your -model pipeline, or update a pretrained component with more data specific to -your use case. +model pipeline, or update a pretrained component with more data specific to your +use case. ```ini ### config.cfg (excerpt) @@ -290,11 +290,11 @@ batch_size = 128 ``` To refer to a function instead, you can make `[training.batch_size]` its own -section and use the `@` syntax to specify the function and its arguments – in this -case [`compounding.v1`](https://thinc.ai/docs/api-schedules#compounding) defined -in the [function registry](/api/top-level#registry). All other values defined in -the block are passed to the function as keyword arguments when it's initialized. -You can also use this mechanism to register +section and use the `@` syntax to specify the function and its arguments – in +this case [`compounding.v1`](https://thinc.ai/docs/api-schedules#compounding) +defined in the [function registry](/api/top-level#registry). All other values +defined in the block are passed to the function as keyword arguments when it's +initialized. You can also use this mechanism to register [custom implementations and architectures](#custom-functions) and reference them from your configs. @@ -722,9 +722,9 @@ a stream of items into a stream of batches. spaCy has several useful built-in [batching strategies](/api/top-level#batchers) with customizable sizes, but it's also easy to implement your own. For instance, the following function takes the stream of generated [`Example`](/api/example) objects, and removes those which -have the exact same underlying raw text, to avoid duplicates within each batch. -Note that in a more realistic implementation, you'd also want to check whether -the annotations are exactly the same. +have the same underlying raw text, to avoid duplicates within each batch. Note +that in a more realistic implementation, you'd also want to check whether the +annotations are the same. > #### config.cfg > @@ -839,8 +839,8 @@ called the **gold standard**. It's initialized with a [`Doc`](/api/doc) object that will hold the predictions, and another `Doc` object that holds the gold-standard annotations. It also includes the **alignment** between those two documents if they differ in tokenization. The `Example` class ensures that spaCy -can rely on one **standardized format** that's passed through the pipeline. -Here's an example of a simple `Example` for part-of-speech tags: +can rely on one **standardized format** that's passed through the pipeline. For +instance, let's say we want to define gold-standard part-of-speech tags: ```python words = ["I", "like", "stuff"] @@ -852,9 +852,10 @@ reference = Doc(vocab, words=words).from_array("TAG", numpy.array(tag_ids, dtype example = Example(predicted, reference) ``` -Alternatively, the `reference` `Doc` with the gold-standard annotations can be -created from a dictionary with keyword arguments specifying the annotations, -like `tags` or `entities`. Using the `Example` object and its gold-standard +As this is quite verbose, there's an alternative way to create the reference +`Doc` with the gold-standard annotations. The function `Example.from_dict` takes +a dictionary with keyword arguments specifying the annotations, like `tags` or +`entities`. Using the resulting `Example` object and its gold-standard annotations, the model can be updated to learn a sentence of three words with their assigned part-of-speech tags. @@ -879,7 +880,7 @@ example = Example.from_dict(predicted, {"tags": tags}) Here's another example that shows how to define gold-standard named entities. The letters added before the labels refer to the tags of the [BILUO scheme](/usage/linguistic-features#updating-biluo) – `O` is a token -outside an entity, `U` an single entity unit, `B` the beginning of an entity, +outside an entity, `U` a single entity unit, `B` the beginning of an entity, `I` a token inside an entity and `L` the last token of an entity. ```python @@ -954,7 +955,7 @@ dictionary of annotations: ```diff text = "Facebook released React in 2014" annotations = {"entities": ["U-ORG", "O", "U-TECHNOLOGY", "O", "U-DATE"]} -+ example = Example.from_dict(nlp.make_doc(text), {"entities": entities}) ++ example = Example.from_dict(nlp.make_doc(text), annotations) - nlp.update([text], [annotations]) + nlp.update([example]) ``` From 262552010d431937c7258d27b3e6a7ee82b8bceb Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 21 Aug 2020 18:34:02 +0200 Subject: [PATCH 19/33] context manager with space (for consistency) --- website/docs/usage/processing-pipelines.md | 4 ++-- website/docs/usage/v3.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/website/docs/usage/processing-pipelines.md b/website/docs/usage/processing-pipelines.md index a863c6c32..614f113b3 100644 --- a/website/docs/usage/processing-pipelines.md +++ b/website/docs/usage/processing-pipelines.md @@ -265,7 +265,7 @@ for doc in nlp.pipe(texts, disable=["tagger", "parser"]): If you need to **execute more code** with components disabled – e.g. to reset the weights or update only some components during training – you can use the -[`nlp.select_pipes`](/api/language#select_pipes) contextmanager. At the end of +[`nlp.select_pipes`](/api/language#select_pipes) context manager. At the end of the `with` block, the disabled pipeline components will be restored automatically. Alternatively, `select_pipes` returns an object that lets you call its `restore()` method to restore the disabled components when needed. This @@ -274,7 +274,7 @@ blocks. ```python ### Disable for block -# 1. Use as a contextmanager +# 1. Use as a context manager with nlp.select_pipes(disable=["tagger", "parser"]): doc = nlp("I won't be tagged and parsed") doc = nlp("I will be tagged and parsed") diff --git a/website/docs/usage/v3.md b/website/docs/usage/v3.md index d71ecba31..8aad49cd1 100644 --- a/website/docs/usage/v3.md +++ b/website/docs/usage/v3.md @@ -249,7 +249,7 @@ The following methods, attributes and commands are new in spaCy v3.0. | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | [`Token.lex`](/api/token#attributes) | Access a token's [`Lexeme`](/api/lexeme). | | [`Token.morph`](/api/token#attributes) [`Token.morph_`](/api/token#attributes) | Access a token's morphological analysis. | -| [`Language.select_pipes`](/api/language#select_pipes) | Contextmanager for enabling or disabling specific pipeline components for a block. | +| [`Language.select_pipes`](/api/language#select_pipes) | Context manager for enabling or disabling specific pipeline components for a block. | | [`Language.analyze_pipes`](/api/language#analyze_pipes) | [Analyze](/usage/processing-pipelines#analysis) components and their interdependencies. | | [`Language.resume_training`](/api/language#resume_training) | Experimental: continue training a pretrained model and initialize "rehearsal" for components that implement a `rehearse` method to prevent catastrophic forgetting. | | [`@Language.factory`](/api/language#factory) [`@Language.component`](/api/language#component) | Decorators for [registering](/usage/processing-pipelines#custom-components) pipeline component factories and simple stateless component functions. | @@ -336,13 +336,13 @@ Note that spaCy v3.0 now requires **Python 3.6+**. [training config](/usage/training#config). - [`Language.add_pipe`](/api/language#add_pipe) now takes the **string name** of the component factory instead of the component function. -- **Custom pipeline components** now needs to be decorated with the +- **Custom pipeline components** now need to be decorated with the [`@Language.component`](/api/language#component) or [`@Language.factory`](/api/language#factory) decorator. - [`Language.update`](/api/language#update) now takes a batch of [`Example`](/api/example) objects instead of raw texts and annotations, or `Doc` and `GoldParse` objects. -- The `Language.disable_pipes` contextmanager has been replaced by +- The `Language.disable_pipes` context manager has been replaced by [`Language.select_pipes`](/api/language#select_pipes), which can explicitly disable or enable components. - The [`Language.update`](/api/language#update), From 942adf0f4d4bd0eeccecfcaa4f74f4794340d52b Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 21 Aug 2020 18:36:02 +0200 Subject: [PATCH 20/33] comma --- website/docs/usage/v3.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/website/docs/usage/v3.md b/website/docs/usage/v3.md index 8aad49cd1..9fec3204f 100644 --- a/website/docs/usage/v3.md +++ b/website/docs/usage/v3.md @@ -249,7 +249,7 @@ The following methods, attributes and commands are new in spaCy v3.0. | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | [`Token.lex`](/api/token#attributes) | Access a token's [`Lexeme`](/api/lexeme). | | [`Token.morph`](/api/token#attributes) [`Token.morph_`](/api/token#attributes) | Access a token's morphological analysis. | -| [`Language.select_pipes`](/api/language#select_pipes) | Context manager for enabling or disabling specific pipeline components for a block. | +| [`Language.select_pipes`](/api/language#select_pipes) | Context manager for enabling or disabling specific pipeline components for a block. | | [`Language.analyze_pipes`](/api/language#analyze_pipes) | [Analyze](/usage/processing-pipelines#analysis) components and their interdependencies. | | [`Language.resume_training`](/api/language#resume_training) | Experimental: continue training a pretrained model and initialize "rehearsal" for components that implement a `rehearse` method to prevent catastrophic forgetting. | | [`@Language.factory`](/api/language#factory) [`@Language.component`](/api/language#component) | Decorators for [registering](/usage/processing-pipelines#custom-components) pipeline component factories and simple stateless component functions. | @@ -362,16 +362,16 @@ Note that spaCy v3.0 now requires **Python 3.6+**. ### Removed or renamed API {#incompat-removed} -| Removed | Replacement | -| -------------------------------------------------------- | ----------------------------------------------------------------------------------------- | -| `Language.disable_pipes` | [`Language.select_pipes`](/api/language#select_pipes) | -| `GoldParse` | [`Example`](/api/example) | -| `GoldCorpus` | [`Corpus`](/api/corpus) | -| `KnowledgeBase.load_bulk` `KnowledgeBase.dump` | [`KnowledgeBase.from_disk`](/api/kb#from_disk) [`KnowledgeBase.to_disk`](/api/kb#to_disk) | -| `spacy init-model` | [`spacy init model`](/api/cli#init-model) | -| `spacy debug-data` | [`spacy debug data`](/api/cli#debug-data) | -| `spacy profile` | [`spacy debug profile`](/api/cli#debug-profile) | -| `spacy link`, `util.set_data_path`, `util.get_data_path` | not needed, model symlinks are deprecated | +| Removed | Replacement | +| -------------------------------------------------------- | ------------------------------------------------------------------------------------------ | +| `Language.disable_pipes` | [`Language.select_pipes`](/api/language#select_pipes) | +| `GoldParse` | [`Example`](/api/example) | +| `GoldCorpus` | [`Corpus`](/api/corpus) | +| `KnowledgeBase.load_bulk`, `KnowledgeBase.dump` | [`KnowledgeBase.from_disk`](/api/kb#from_disk), [`KnowledgeBase.to_disk`](/api/kb#to_disk) | +| `spacy init-model` | [`spacy init model`](/api/cli#init-model) | +| `spacy debug-data` | [`spacy debug data`](/api/cli#debug-data) | +| `spacy profile` | [`spacy debug profile`](/api/cli#debug-profile) | +| `spacy link`, `util.set_data_path`, `util.get_data_path` | not needed, model symlinks are deprecated | The following deprecated methods, attributes and arguments were removed in v3.0. Most of them have been **deprecated for a while** and many would previously From f102164a1f32c28b1c96f3b46a24d188c2398db1 Mon Sep 17 00:00:00 2001 From: Ines Montani Date: Fri, 21 Aug 2020 19:34:06 +0200 Subject: [PATCH 21/33] Update docs [ci skip] --- website/docs/api/cli.md | 2 +- website/docs/usage/layers-architectures.md | 78 +++++++++++++++------- 2 files changed, 54 insertions(+), 26 deletions(-) diff --git a/website/docs/api/cli.md b/website/docs/api/cli.md index 9cadb2f0f..551147929 100644 --- a/website/docs/api/cli.md +++ b/website/docs/api/cli.md @@ -123,7 +123,7 @@ $ python -m spacy init config [output_file] [--lang] [--pipeline] [--optimize] [ | Name | Description | | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `output_file` | Path to output `.cfg` file. If not set, the config is written to stdout so you can pipe it forward to a file. ~~Path (positional)~~ | +| `output_file` | Path to output `.cfg` file or `-` to write the config to stdout (so you can pipe it forward to a file). Note that if you're writing to stdout, no additional logging info is printed. ~~Path (positional)~~ | | `--lang`, `-l` | Optional code of the [language](/usage/models#languages) to use. Defaults to `"en"`. ~~str (option)~~ | | `--pipeline`, `-p` | Comma-separated list of trainable [pipeline components](/usage/processing-pipelines#built-in) to include in the model. Defaults to `"tagger,parser,ner"`. ~~str (option)~~ | | `--optimize`, `-o` | `"efficiency"` or `"accuracy"`. Whether to optimize for efficiency (faster inference, smaller model, lower memory consumption) or higher accuracy (potentially larger and slower model). This will impact the choice of architecture, pretrained weights and related hyperparameters. Defaults to `"efficiency"`. ~~str (option)~~ | diff --git a/website/docs/usage/layers-architectures.md b/website/docs/usage/layers-architectures.md index 8d26a4139..d9f80ce14 100644 --- a/website/docs/usage/layers-architectures.md +++ b/website/docs/usage/layers-architectures.md @@ -22,8 +22,29 @@ its model architecture. The architecture is like a recipe for the network, and you can't change the recipe once the dish has already been prepared. You have to make a new one. ​ + + ## Type signatures {#type-sigs} + + +> #### Example +> +> ```python +> @spacy.registry.architectures.register("spacy.Tagger.v1") +> def build_tagger_model( +> tok2vec: Model[List[Doc], List[Floats2d]], nO: Optional[int] = None +> ) -> Model[List[Doc], List[Floats2d]]: +> t2v_width = tok2vec.get_dim("nO") if tok2vec.has_dim("nO") else None +> output_layer = Softmax(nO, t2v_width, init_W=zero_init) +> softmax = with_array(output_layer) +> model = chain(tok2vec, softmax) +> model.set_ref("tok2vec", tok2vec) +> model.set_ref("softmax", output_layer) +> model.set_ref("output_layer", output_layer) +> return model +> ``` + ​ The Thinc `Model` class is a **generic type** that can specify its input and output types. Python uses a square-bracket notation for this, so the type ~~Model[List, Dict]~~ says that each batch of inputs to the model will be a @@ -43,39 +64,46 @@ are: ​ | ~~Ragged~~ | A container to handle variable-length sequence data in an unpadded contiguous array. | | ~~Padded~~ | A container to handle variable-length sequence data in a passed contiguous array. | -The model type-signatures help you figure out which model architectures and -components can fit together. For instance, the +The model type signatures help you figure out which model architectures and +components can **fit together**. For instance, the [`TextCategorizer`](/api/textcategorizer) class expects a model typed ~~Model[List[Doc], Floats2d]~~, because the model will predict one row of -category probabilities per `Doc`. In contrast, the `Tagger` class expects a -model typed ~~Model[List[Doc], List[Floats2d]]~~, because it needs to predict -one row of probabilities per token. ​ There's no guarantee that two models with -the same type-signature can be used interchangeably. There are many other ways -they could be incompatible. However, if the types don't match, they almost -surely _won't_ be compatible. This little bit of validation goes a long way, -especially if you configure your editor or other tools to highlight these errors -early. Thinc will also verify that your types match correctly when your config -file is processed at the beginning of training. ​ +category probabilities per [`Doc`](/api/doc). In contrast, the +[`Tagger`](/api/tagger) class expects a model typed ~~Model[List[Doc], +List[Floats2d]]~~, because it needs to predict one row of probabilities per +token. + +There's no guarantee that two models with the same type signature can be used +interchangeably. There are many other ways they could be incompatible. However, +if the types don't match, they almost surely _won't_ be compatible. This little +bit of validation goes a long way, especially if you +[configure your editor](https://thinc.ai/docs/usage-type-checking) or other +tools to highlight these errors early. Thinc will also verify that your types +match correctly when your config file is processed at the beginning of training. ## Defining sublayers {#sublayers} -​ Model architecture functions often accept sublayers as arguments, so that you -can try substituting a different layer into the network. Depending on how the -architecture function is structured, you might be able to define your network -structure entirely through the [config system](/usage/training#config), using -layers that have already been defined. ​The +​ Model architecture functions often accept **sublayers as arguments**, so that +you can try **substituting a different layer** into the network. Depending on +how the architecture function is structured, you might be able to define your +network structure entirely through the [config system](/usage/training#config), +using layers that have already been defined. ​The [transformers documentation](/usage/embeddings-transformers#transformers) -section shows a common example of swapping in a different sublayer. In most NLP -neural network models, the most important parts of the network are what we refer -to as the +section shows a common example of swapping in a different sublayer. + +In most neural network models for NLP, the most important parts of the network +are what we refer to as the [embed and encode](https://explosion.ai/blog/embed-encode-attend-predict) steps. These steps together compute dense, context-sensitive representations of the -tokens. Most of spaCy's default architectures accept a `tok2vec` layer as an -argument, so you can control this important part of the network separately. This -makes it easy to switch between transformer, CNN, BiLSTM or other feature -extraction approaches. And if you want to define your own solution, all you need -to do is register a ~~Model[List[Doc], List[Floats2d]]~~ architecture function, -and you'll be able to try it out in any of spaCy components. ​ +tokens. Most of spaCy's default architectures accept a +[`tok2vec` embedding layer](/api/architectures#tok2vec-arch) as an argument, so +you can control this important part of the network separately. This makes it +easy to **switch between** transformer, CNN, BiLSTM or other feature extraction +approaches. And if you want to define your own solution, all you need to do is +register a ~~Model[List[Doc], List[Floats2d]]~~ architecture function, and +you'll be able to try it out in any of spaCy components. ​ + + ### Registering new architectures From 27f81109d605b3f90517e4a05cf56094c0874969 Mon Sep 17 00:00:00 2001 From: Ines Montani Date: Fri, 21 Aug 2020 20:02:18 +0200 Subject: [PATCH 22/33] Update docs [ci skip] --- website/docs/images/thinc_mypy.jpg | Bin 0 -> 155643 bytes website/docs/usage/layers-architectures.md | 51 +++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 website/docs/images/thinc_mypy.jpg diff --git a/website/docs/images/thinc_mypy.jpg b/website/docs/images/thinc_mypy.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c0f7ee636a8058fd5cec3711dbbb21e66a818f03 GIT binary patch literal 155643 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 + +If you're using a modern editor like Visual Studio Code, you can +[set up `mypy`](https://thinc.ai/docs/usage-type-checking#install) with the +custom Thinc plugin and get live feedback about mismatched types as you write +code. + +[![](../images/thinc_mypy.jpg)](https://thinc.ai/docs/usage-type-checking#linting) + + + ## Defining sublayers {#sublayers} ​ Model architecture functions often accept **sublayers as arguments**, so that @@ -111,8 +122,48 @@ you'll be able to try it out in any of spaCy components. ​ ## Wrapping PyTorch, TensorFlow and other frameworks {#frameworks} + + +Thinc allows you to wrap models written in other machine learning frameworks +like PyTorch, TensorFlow and MXNet using a unified +[`Model`](https://thinc.ai/docs/api-model) API. As well as **wrapping whole +models**, Thinc lets you call into an external framework for just **part of your +model**: you can have a model where you use PyTorch just for the transformer +layers, using "native" Thinc layers to do fiddly input and output +transformations and add on task-specific "heads", as efficiency is less of a +consideration for those parts of the network. + +Thinc uses a special class, [`Shim`](https://thinc.ai/docs/api-model#shim), to +hold references to external objects. This allows each wrapper space to define a +custom type, with whatever attributes and methods are helpful, to assist in +managing the communication between Thinc and the external library. The +[`Model`](/docs/api-model#model) class holds `shim` instances in a separate +list, and communicates with the shims about updates, serialization, changes of +device, etc. + +The wrapper will receive each batch of inputs, convert them into a suitable form +for the underlying model instance, and pass them over to the shim, which will +**manage the actual communication** with the model. The output is then passed +back into the wrapper, and converted for use in the rest of the network. The +equivalent procedure happens during backpropagation. Array conversion is handled +via the [DLPack](https://github.com/dmlc/dlpack) standard wherever possible, so +that data can be passed between the frameworks **without copying the data back** +to the host device unnecessarily. + +| Framework | Wrapper layer | Shim | DLPack | +| -------------- | ------------------------------------------------------------------------- | --------------------------------------------------------- | --------------- | +| **PyTorch** | [`PyTorchWrapper`](https://thinc.ai/docs/api-layers#pytorchwrapper) | [`PyTorchShim`](https://thinc.ai/docs/api-model#shims) | βœ… | +| **TensorFlow** | [`TensorFlowWrapper`](https://thinc.ai/docs/api-layers#tensorflowwrapper) | [`TensorFlowShim`](https://thinc.ai/docs/api-model#shims) | ❌ 1 | +| **MXNet** | [`MXNetWrapper`](https://thinc.ai/docs/api-layers#mxnetwrapper) | [`MXNetShim`](https://thinc.ai/docs/api-model#shims) | βœ… | + +1. DLPack support in TensorFlow is now + [available](<(https://github.com/tensorflow/tensorflow/issues/24453)>) but + still experimental. + + ## Models for trainable components {#components} From ff5ba14d06e8a3576515a91e07583eba775f19f0 Mon Sep 17 00:00:00 2001 From: Ines Montani Date: Sat, 22 Aug 2020 12:26:50 +0200 Subject: [PATCH 23/33] Remove font [ci skip] --- website/src/fonts/jetBrainsmono-italic.woff | Bin 69120 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 website/src/fonts/jetBrainsmono-italic.woff diff --git a/website/src/fonts/jetBrainsmono-italic.woff b/website/src/fonts/jetBrainsmono-italic.woff deleted file mode 100644 index f3ddf4db5f385bfbd08e7a745e51faefa54345a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69120 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 From 9740f1712baf4a9e51e7db7f7efbb61af060de07 Mon Sep 17 00:00:00 2001 From: Ines Montani Date: Sat, 22 Aug 2020 12:27:02 +0200 Subject: [PATCH 24/33] Re-add font with lowercase name [ci skip] --- website/src/fonts/jetbrainsmono-italic.woff | Bin 0 -> 69120 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 website/src/fonts/jetbrainsmono-italic.woff diff --git a/website/src/fonts/jetbrainsmono-italic.woff b/website/src/fonts/jetbrainsmono-italic.woff new file mode 100644 index 0000000000000000000000000000000000000000..f3ddf4db5f385bfbd08e7a745e51faefa54345a4 GIT binary patch literal 69120 zcmZsCWmsHI%;*Be-5pxoin|wgN^y60U3^=-XmPjVPH}g4cNTYdhr920zx(f=CzEO1ZtjfX;08lhR zc=RA>^nH2#!_?l`2>_tP0RZ4^Ag_7;zFEy>>f!bo00jqW3($aIG0i;Mt%Z}NJ%r{9 z;p+ha&~UT3ac3-zU7a8_5(v-#lMlnv&dUM-p#KQ~bR+_xQjIRfZbPihjm-dnLjnjN z7X-O63+EB7AVdi5JETqtK`Ou>1V<}-H%|!74FLEA85?@(%Rb$joues)?=&9(fZv7S zHDAwkoV~FpMCRKtNW0JfA)-B2vV*a`IfPaW88f60*i7MJV{a!%S4dwE5FWG_h)lYz zI%73XF6I!KQAHu`{?o%k_;>~x;6HnyK=8i{8UPDT0j&>!hOvODhm@@_-2fPvNtj7U zxeBuifB^tJp-hd;jEpu-oJ@v{j69rg5REZpE15=&zYobW4Vz9G8yN!vK0dljG3=zM zxUpeeJ#19S0ufRYpyQE5WpmKXu=3%HlVD^5t16CaNF#rR0lSOL1umJ+?4fYov>Z{|R6J;c2zK4ua;>k81Xc=#^XWH9GYsHAU%k+N2 zPz$)^gZ$tx$=DLbOh^dHlHV|=x4Ki!2g3=P4Eu~0SEu`*rd$v=k}f&e5fG9Za0~nT zsHrOcE%2Y%S5MQV+sD?-bFZFN&oZ~3{aX}%A$6Mi5=!bk$2OShG(%sM>Ab*qP@wNL zO`WXoJkPbb?lk+gaou@Q=t1amiZVv%YK~*F{d<8VQfo_a} z-!m!!r`b}Nis^u23a9x>q_*q+S5NEdICDmg_Ujd5$MzdAJh|WXGQOeT%{scs+x03r z=wpW?aZ*hf`w#t~Xx3*>04B^&Xn@Yf$D~0@J1gZ_Lpv+SScCm4caPlwhs!}kDB;By z0=3YPDLn69trRq5V*!%j(MtlbIQwo7kSW6bAGOCoH!tSFw%pq9qATu>eu=RG6X;T< zs1l*O!hf9UNwXgON<2qg1wWYI%yw4R;##krvc_(_gf8}KeUmp_*$-}%5liT!3fgZI zV%gR4Mx^+dH240sC7TT={otx78L!W~pP%MeKREGTud=*r5T36}D+zvHWYE#Kwbr*U zR&01`0Hdu)`q*83U9PE^>o4R5Pqw(dMqeyc6=u1toLoG&K-n&*lV zdBw(&G_cQ0aIoXw_Nt6Q@{J7v?mGdhz{dla&zKf30f~Jt`LNiigsalyz znNmAk`|W~s9?iJU?Ywds_Zh$2@l3^FtSPNhCLeHXCefD1VZHfbQ)F}wa4&@+p?YGm z&{|@@3bDce!r6V*_)E>plQVeFMaT#c`4f>92CoZg2_Ucu$oPru1Vh$^?1{d?_ERO+ z1OwX$Y3wIoH6W=ANehP92>JA<(5oXAM%dv6!Iq=e-W0!MHgLiRLoBw97OV*pCmF)% ziT#3{@RNUPxKm(~Ey9R6o29Y!@NhpTl!agrKhS{-6(s9P(m$Zxy;C$C9?Ql!(a2Kt(npW&U25fpmct7 z=L#JXoaF2rLbv=T%WD+lMQWGsJv0nqB9k9P(u&?Q-P00Uh`ux3S%OYCy;*|u2-7#M zI%UQicz4-FEFX!#v}^lR)hnQt2;35X#OW9-DSKr058v2!BtgT5>Xu}W9W{wnR>O#r z;9(o7#M|kk_@|hG8Pf+mc>JnD^GDkZ@nv+Fy(Zd@@@3fBB}^HC7}+EKs__}Wb`$>(0q-Bw1Oz>#Ip_*e7FL=|-fBQOp!HYh zl;bA5ClV;&w=q)6pfdVRw@Wpd9sEnTvlCe)>VixYB3TeVL@k(afhkoX7;=HvxpKv+ zRUtaL239y}!AZG_{>WC?{9(+02Ro3wqd`50|9VoLzUU$HTxmB!o&SX2MD&C**gDz9 z^~4vBy4a2p4v_d0)c40OAE)GiQU+$`H_8_d8M95Tn!pSy;IQ;0XTU&FfJM$0j}@j) zFn8{HKqEe>_`x);8*uaOmcnn$-$d3g8|9xG6Fy_V%|DHDeB@SB$|aPBpbFEMH^t>| z9;rfmB3FHau#-Eco@55mJe&HDVO^$=BxJ)pSG^tR{t1SA%Kge&eU20*P86XrxLy*3 zD$;eBZvnucDWCDeaJyTjPH_+VO$nL5g5qTh;+M^ScNLhCE-RtM%|cJc#kxcYGCRJI zj=Wsg$`$`8_AL!>EG8;VJkA>^k+g}@R6Ch7aMxIWz@0OFi&rXFJ!DO1&M7;zXh|l+ z_lz^h*E}SBHrt$iZt%DF=jdAG8OmpGhM0D=?h3Oo>d0~+)r*E(qMWsLT-$ZSw*k=) zp8Fpccf{BI9eaA+(T1A#)09n8%Y$XB)~{2{J~QCDDwuX4h;Mi1Q6ae-*9lh-W|7_r zpJ!~`DVBM+MgKg%^~eC;JNvb&DrgA?C0`m4vQ=ikO6p^?+OS^xKi+b@+%Ue9#qu0K zE~N~fPTSR?P{oudqppgZoK?E!Dv?P0LuQ8J4XrK19lwJU10xh~pvdQ!QV5*pI9jbk zsQ9)z_00`VYJaNUP2?>&bMi8Jz`;CLXdG-wJ!KA=cfU}LIi_5fbQ-eX23QovS@s%l zTAyxScibpGGLpC4J&D1gF}>l=uf!d(7vw~<*n0jO(l{1jSXHmbLKEVb*?s)I(QyXQy0JhDpzgVFt z#%c($H@?y~ds#;G$X&NlHo1ofwzRITr;a!SJAJ@@DGM#i`h=R3?k>Ho0wd!tjOz|_ z{txjYvxb=q&nNBoG0!}Hxtu2vPc|K?7r%~o1|RwSzuM%99D)!J3X$+bhy&4L{$`;# zhOmgkswGZQxgmPuqvZ9JSF@j@Y#85%dV04BZnsF2UBpZdqN`*N{P?HQXQ_OO0pCyW z?6nrP{B~8;I?;A=`~ix}a#_5))bTWpzAD>FOm%PU5%@BGd*-#zm*ACVF?f?vlp8Fp zyn%cXg84l57S36>+(z(22Ma>}dJy_xRu`=q1l08Hs~-@NrKxN+js*~y^3<|r;JBYT}P{_P@hSuDQRYiJL ziVYtK88+QEIdOC$R_j6!YwZaG5cqcUQ-$y@fEB{>&(if7tIw5-a2-x;N^MjK2M- z*umHi{u8e$v)R%q@W|Q6{zA7`?X8K;@GCGtZpKCTB1~q{youyoqKQ@khNd02Eo&Zf z3*m0->y1hyx!Z~Cc?p!7c^S*UT^bZc4b}MX9+G6HVjJL(dtncQbcfV)vXtsgem96OhsS98duo+C$-F)8Gvhcgo# zPMQLsZ`eGjCg&+*>c1+=GWIjXj-Kf*V!GQw3g?!G&*Ks>@ya!+A` zN>{Jmf6lv=Mh4@y)xN=s!-{iun9K+j>R#ey!Mz|`$V}o0BJ4h+Yz6!dI0~>XAFua9 zgr$Tvy$;)XllAg+&DL%_VxXt%cGs=$G~)+;<8ahP)|p>fF!4S{V#d)!FatsWN3D5P zb*KP`gpt=mfeyqD!qP3~*+^`ERq+fQcbn){h|OYO)LJX!4*dj@wg#Jr>}f#x|A_&U*7LO zG`Q=JvQE#kyA!mWIw{hZfSl%gmQQFmGZ^3xR*^XJ?v=Hs2YbNfF&L)<82JyF!B`h#s5!&R!kHS+~=f=&Uq{f>7dc%ES&nxoxW%?`y+rsXWC` zvs0x&@S;SZ(O6ZQLR6OqYSBhdm9H1>HN?HCSOUJz7k*n_eL#%2?|w^jkdl?=n~&AS zt-fl@Ysh~33eos$&d~h@@fy#NgWk)T0n3;v_Wbhrml^CAFuY6Sr_;F(?Zu7#;D@L) zpMMv@_t`5zB!Rzg;uaUxU}w$D^>QjdKSRyWK#3d{T{56}WpXu(4f#$_v*X?s_iiPe z1LBoytMwW&^8I1~#{-+fwa0()%ON}q(+hf8<(D1EL1bbdZpeLjM*+Ps@gR|4hO3!t z3GR&vT|t#kP1mV2H{DV;dq`+YKq2_Y?h5*B7Ih3qvz??XONv)7m^!iuC^RSW_sS;a z=F^((y0%gD&0X-xF0ijX&qw;sk7aFfVk6-H9J8R$FkO8IWPMizbI*z4|ruJsd z5rgFKT?~w_bJa4}Bd2jz(@BSfx@kmlC~v~MPLJA9kgLmY+*9Bl%0Lsm*+%S^KQ;^l zLs<)NoC#)>xyy<5r;4Q5&(Jz+gD3EmKpjKAY(;D1Tw`2(iQdx888~iA!IS}+orF6t zzHca<6{ybLDVVkKR8whvC5@M^&zC&pyKFSKinBb5OR)COq_g_)@px;+4$*OBdupN0 zMS8AhLT3Jt`|vy)MwL6a2Q>Soj&fsdUwm*~^?WyzX20*ETqGhbswfO@IilGPveG!} zOEdIA769s(j&s2v^QM9uz}UCeiAG~A9k=rkwk9hJ>ut@c)3j3}KSLDS!0cbmFlg{7 z*aDU{wQjV^^uSDKaI!^m3tuW<^6c(|f{BUu;DsD?W0?Hw*qEpB`CdLXU=(2b51PiqH){$~+T=6RsOvUKu4ldi!jIGyjCx>?**I zK85s9N;*!aErhiCEk$#{6bbP#5ESFXOYNh8^1_J_wU3;g2xNXLFr*KkncwwN+Ho#r zbBR4GE!ccsq%#uWeS7DB)~z{yw0W5{%k1|5(Ef1dMU@sgnWXfKR9(AR^$%v|(Cqdq zo>{drKH&A+e>;abz}3p;FpBoX&_no%OaW!$tjAh!P~FaNDyPu^Hjoi}ZOGI)eyic* zS6_Uv5Je0Dc>cVS%ih4~f@-a9bHKee!tLZ-W5bvkX^AnzAH?;B57fMwzxQeFPqO_W z9|2baQ?S36PdJ=Y==af|mkf`as^(x&-joKTa2V#T;Lbk)x41a++}N);{^*ZpybF#9 zHrguPxU`t+yQDv%DAG2=6 z`ivakU((JQ43ylv8lT`|X>+wdNV5$M6%_fx27*!MCXo z0tO}?M~a}*-#@~NW1~reGiYXx!p`S}uHGsLYFuW>;Eei=@Y4Ax>NR zLcn3oj|JO+#aC}G&>8Ju7(19UbuYilVtkP57E=O8!_*|QIF30(30dEOiNuxd=?b&= zG(3iul^fvFY(A)oF!Z{G?%$#Z574^(tI91&?82@K_r0s=tCJagX?)@1<}N;|4@S7@ z7HbI(G;s!N=OyuLK2R^hH>qcqSvNhYuBkEX9E^YbKL7FilNx}{fzrs<$RTWeY5|{4N*F;HVd4q=vIFfQB{FK5(mwkgU3qSK zoMA?tFz}aN>deUs@^GDb-O(GS)xy5DY;l>UI8BEQ!k{Jx13QBqx&>w}f#KNH#?8*o zmGgZ~{ip+4H#TH$kdsph(N!=nGEOZLXGbcx5LcR3-b5aw9&8^}!(^{JA=%`<)DkPj z2@`e_4J9%x>iaOK4tVCJn~ojqBtK=nE|Rkr-4%8w1hwpR7#m~4FX4l=IwV`^H`VbzTx;>IsxYfC=MB_D4H9gd~RlPm8b%-D(dJjg@IDOu)QYgep zTef+BZgH3wcwOLV6X~@E58|=yZ5N1RQwOlIC|YFkts;Xm$5o5lRelxH6>$$f`mr_8 z#IWUR`IM8sD6M|1xN&vMLu}y?9Zz`D{0(Eucgj@D z5$r`ag~333^twEx^YW9!kO|Sj9Ei*2<;Bc;NaUL8OGg-u*~T~L;Iu~D@Ygh&w>Agx z+3S{^DUkP5SsmCa?rv|u^UuOI%<$C*XI?gZ@`^+(`1tc4XlFh9!Lwe^YTG?NLNn_+ zGs!n^T*+8LkZw)oO8*w;Kag_N1FuuMsg|>o@?(!b{E#=xf6c>}D~jG=5i^*HD~`~~ zYEZM?;IPa}UWz8h_yraPsRD>W2aH!#B=`J?A*zM|^<61TVYx@tr*9e;^2M9NCV zlIKJ=dk2Td(uErOo}y?YTM=}px$MjJW*uQ2v7|=Rn9OZ|A*1U$Vd^bE%dF%KvUK5q zCS}aXDtsiCUGZJvHMIYTsv};4UlDP<_y4JKsA|cxDzmYJ^YB2kNH+zHw_I9xnvj>V z-8)h~Srn+5t+~onXo-j@lytVt>35CN6=5UaIr~?4V`Fa_qjeXjO~ZW zh`}*04J;Dm3rAswoUi|D+B?;+_xw57PLafHP=UWprd;OCd*K|-DM9=>+k7|Gnx-X> zv}{b_{U?`)Pp9p3x|N;j@8@$3bKGY!1q0QJ*>|*E)IQ2Nogr?DHs+r-D@mNs3e2um zZ`LzLGlq{Q+4d7yEXUfmMs=%8c|PK)Qbf9Rx#F~0gF1YNkE|_5kU>wkqx2mno|<>& zxE>1W;Iwx3Ce#Ord}K3c8Qbs6yV3NGdOoqkb*+36&3p21gtBg!t}1PuR$|3yZb>hP z6HFV)NR=GP6M9OZXtu$_e^0h4RP8&NiV`9S1FsRob%bKm!H38hA%v|4|T)mdp&+lB@+&0)a%&xsJk|af^Q1W#X(IIw7Dp8>u13RR-;8DX!6z2$tIpyIzF%pDB{ z2eB>-DHmsME;*13l~7#en^3xsmE4qnD-ad$KX+@B^LDv85j}7DnYk)>@C>@_NvGX) z-Y2n0C^B>$Th0h1eLNjdJ8al|7w2)6HQY0BPeCf^t|zB)^|;aIIbh3PDgOxg!ydp_ z%HuaBfwfx}JJHmo;p>V}L@4a~W5i{o=535VS(SN~`y?&@g=wtUb?04`JC#O8IbYBv zdNOCNdua@iTA9H77J1|Z$?x{y^pM;*88%v@Z`?@a`78uFQhIPIPI%E;Gh!b^@1svP zH5XV~Iu2)|(X>AJ1T$Vpd^`UNR+IWRiVl*l4y!@wL*fMO6wzTZ&JsVZ>^R9?&+7w% z?y#{ZB*sk@#?&OY1q}zE)SMqSAgJP3~4pzTafJz^fSy#ZNovnlZR zmNPX+f8)1^x2)eGQ7AvL3RN)`PE}~{(h$G?X}hJ&GR!qBG%N(k5e=vRE!xMQQ;Q+$ zH7N0L$XZfoqwdBfgl%*j<>9Z?HCRJ(pTX+<@sEn%gq{^r?31W#NBmNUkJU$k9-O`D z?xaGj_G6{Pbx3ygj^5ikL~WOa`-d|e}e^t6x;GCYv})y>Q^^Z?qIfYSd5!_qvYo2 z=4)04XCqVJQ47g?(}VzVWpOQLkxvsvvDf}7@hHbt${!=_$|cGzX2};a$%5iu@~9PZ zxj(9Cu#7{Aj$~BiAPY#D+a-G23R_p}tr7e=F7vlBxO8jH7Cq?*{OwM6Uv+_rUh}J# zFTZVyQQZ<4>nrmTqDRQpZKUxMDo$iVVSYt_D(JnC(aYT#iK!eK;~Z@bF@kqM(%d25 zXM@6bCKWfJbN=eADBx{utuGDVhUQjBm#jA^$!~*gyRO%(m-;9rpe(xFGSTbwc`CK6 zt|^*;6yLhxLVV`gYj6O)32B3s1))i9QdwbEWnlgO%@mAVdE)tV74xvEVyrbhwnD_S^KD@OMoq9||`v*UC}K~e3$ z^!nnej~i*ry>f$qh!(3z?Dn_V0ZvZL2G;Vi(=lhq2&n4zGNyHF(`EY^ zSMtqz6D5cl_n8t8(K+^QcwDk6F94_LWnP~i>Y=2STN62uJl^>ixygdmjQf12#Hg?TRL zUp{QkG`M1!i_vrU!yiOD4t*>)5<*BRj?~wkOKY<6hsXfgF5PIyp28<@Tgg7_0pwBIe?nqsu%<0yTwml;l*q7SO_6WLlz-G6q3&;GvK zqauAQcU*v8(TJ#dce^c$gvyTeYzT6~G1R|nrMu;ylJd4)q8y7Bo$tjU2P@m~hQp)< z@sixB+A-9+<_^Zu%#w#Lv8~j@s&a>J4{?fH*m8y%esk?&yuNTa#F=u+seP1U+`hw}`hZfu($6rC)K-u`s8jqf2Z{$&2XQ$!$Cj zQv9>%e!_|&5!?-vSo`cmeO-n89ZJa!&3>gq@L)>_ne1)MU_#1-{g0A@^`Gkw)iWa! zu0xaq6obFWZqeXee5-HhhY0opisViKpe@{2w2dCaL!MTptL$k_H?jNiw0Wz+ihj;T zF?om4!qyyZ&zWMWdNa8{{NbL{<};x`lo{8*b$$!inn@5 zdHC^_Nt(vSGTeasd6f$L-$H9+6rp>W5SVdQUJbYS>;bE}(z|)bTfHwIx1IdAgMp!h z9`JOV(RR)`Gp{wv;mbzBf&Y%a9T0DTN2K>JHyF|8ko|<~VwmLkC5<_t_Vb#{ZW1MM zt~HUyzs!)D%Y!D(diq0p=OR9N> z75ZcKGd#fl5K*QNc`_O8*%K;g3a0K=17q;28MwcEpVi7EQ2*av5;5q1HkMV26dM}W zX)@!Jbvj);Myb-@06&wyGbBsn3aQ=;0OUr~%MVxe=zhX%Sy}x}E3GUIC8{he0nUdW z+u|Pc`{j4&uuMhV>a-iQKFhy--8UlTZ-OWLCB0?3ggm%Ip(pjECXYrc6FRfyhLS0V zKjZF3>0VTF>;Ko?L}uGZ)ow(wLYBbxhXuOpAHF#fQzZ`c)S_{Y!uC|N!j%5u8Z+}5 z8g!ZaMx*KdC0|_|M!O0{t-+f0(R16Fy20hzv+;Y6)djCHL@igc#oAtaaPq^B_!Fye zQp^tWld!|ccoXTvcCKKg4_5<7S0VN9Tn)nI~mi>NkQAz`tL=0yhZ=@CZ>< zRp$kcVeS&2Wi_SYZu*U)2-N4fhfUH}5Fe%(3=s-=;L2 z)WiWCn-SZRAqpCP;La08hapOutIzoxPv8SZpfR{^NOWuB(iXslXV&ep1Pjt(rL}_o z@=30n_WIt~6JXKhL;!fpg{ccw4cG~64?NC+HWS%k5TX)#zA?QldK!hAA@nEc^qB?G z``x8Se>8~nf+j%B`bQhvlMnch@iUeq&hSO(pDy7<1*?9$)jothR0HdQ1;BV9VxP|r z_Mc`$xojD7d2(5DIdYlwf&{bmh&Al>9mub9y?UN!2a6qEd%u%wG8Z$kGsQ10zE3q} z_vPrI!Vnq+E^eWEVuJ%3w}dW3x9l&gdPjG)x-5QF9r~e@gvvV+R(7d3Nr4@q2!*7_ zi*a8E4?7O8$c_m4S`fKl9#05w)pme@xe)$gQ+(?<&TmAtQL$38RWdByAE@fZQ4@2G z#~z-)l#cZ>i#Tq@j|UAA0^sji%K<2P7eGh5)djoNfA*_N7H_%Q|3Z)H4=OX`*cSK( zq+bRkL;2Y$Ev8V2mzhW|yOWK2WT}3;IqX4^Z5wB8%4X&LF_EJyik9*|GEKpxiAr|n z0$Z$nTJi#$Ch=)3ZBisZCXqh|etow{Cym~vLH8Pw?nY8AC{?S1t0zL&H4z-AS};0R zh$!JXYna<#(M~U7#x^dDtQv1TX_$(%Rn_(AZnJldtS5d}U8nicx-y-`*0deQk=3;M z3m>Wv^BX7ITJPD~uzt`bQ>x%(#O_Vp5p6PenpJM1N;uBYVB2J>1QS9K9)fuk>%#8? z!B}5OCQI2(Xcb>Y22I(0c5A&I+OaCxBitZk{gEVFI7zjfVrskf-zcUgMO ze;e(O)1Q2CUxBeSx6iQE>?1!vu+eSZs}Z!W|>}rjfl`qpR2ZuZ~RHC=Jng9<@$^#}_^e)p5{D&I+sM=z9T7v@jpyaX zs1&k>$tVm*{e$Y@YBXgS{aSqXR_kny_ErG^98SRXh8v-qlelRq_!~|S`CkA`us%%C zt)dF_6#A^edyI6wMtvV8)p<-G#jqz++7##8Bj$|XXfzD?!1kU0FkgM%&5QcEYl7S_ zM{KMzPtH7}1dAwD^)Rl^Oq#G&xpe^AsFpvrAOD)@ zA2#Xd;JKtr!A|5v?FF0)lyw;btqH+<1cHC>SYO%a6~hV88Zp0BMOi80_xYC zBXjfapOx0JVIttK!Y=jFlo{jaV57P13(P$XvlHN*& zi8?Z%1ujtJ;;)lH*KHq*4UM>)g(=fDv}I#x=qlC<}6|>bB3< zyws{XLLm)uB|50l<1fAS1iSk(_s%e3l4sQ2RfDsBA?mK&oJ+2*xq1CjU@`z1@nc-K z@bB#OF24w!Pdx5#1rwtfijt`;g4-&og{^x!k-bu}=v1MZ^X=GrWWuZzBBMW(lgcvw z1Hd8+!6yKyfdK<*g(U|7QA2?K!39M-VzaykuN7A z80(J}Qjn=|C0BZVVQ_g#0m4dFCoLZZLfkaPdYq+PLJ|K;NYV3yc4N}~UELyj*Z zpQde%Sj>WyPdu)J<8ra>gG{iRmr@L3JXt4o_u_e;=iymb*w4$~$ApLoU;-a>h9lIKJbVKVn{!Tkdf*}C7oBU-k_SyoJ@NA&pe zinfg^jbbuK?fdupryZV2g~-^j)%DrV>#%N3*YhVFhW?GAm@W7(@#NoS4?=X7668vQ ztb>jtnVloV2E;y%t{G6l46*(?E*%NK{;u7%=eA^z=Y-ujud^UVHHj(G7-c9~$>y?I zO_fS=1HvYELZOn8xa_VN@94~J)?8BiiF+j@?cz5$Pa(7kgK_#erHL-b1yNEFX4KliuD;Mk*SKbg_3u-pVkKJl?D~P zJ?_IedFXx^x?0}zIlw;q=RU5d?0K$~k(TacV28m>`Q2()i&3f5+M)DwceDr(>pt`z z)$X!nEX%X8AC3u&WoP?KliDbm(W?+BJ)qzVcHY@RF!V`$E^Rl zfa*w8AHOzz#}l?zsmu$~z8jbp5OTHNf+LiUo9&5X}ukrDsntP%f9Znif_?toVFUDTrH;m5)5I&dS??^K6yW8gda*B|6! z=br$i-+snj6Ax*g~9@YVIOGf1?g(|EmDwRQhvq17oT@QA*djyOzaDKfOHoehDj6CnA=j_nfxDB;$!Gr^BM759N`ho$Pur|f$y zLtvW^`8YZWdaXv79Tn1x4?Wn5|+c-x?Oav^u0jveFsWP8fbhvS6TPlx&Q?enU_LW&VTFI zu*5D;!es(%zyYs^trv?>@58@FaU5@_UkTak<5D^`t|LsH#smlZ1sBI|TJb5g3`Zj? zu?B_$!ulx9Rt{h;C4KMIaWkf{vG3fSHSn44T)^S+FWF|EQk^$_{#PD@GYzDIc@J*r zc7u(2+#=5FYieGsJ|8pn9O_%!6xH0Jir6lYIU-7N_-HtU45hfcuobASm}-r_7l$#Pe=>c8nmm4n`B98TO> z%He>9xS*UuvA(I<=0Jw$srUOnuq31ReC|ZjseV2~Qzql#!LngejKhj?US|g*PN^u+ zX88(S%CDJuS$*D}X!z%$e^8pJ7RX~yhS$PsCPg})@R&G_yrRLW6hH!EA*Y?6f|?|( z^-0hCUi>*t4ydt3o`htw2O?qZh~Bl-!lQu0{bHiFT%o3351X#URgpbOj52?}C+lS~ zp(?gTL8r%VPODLN^sLr)_=BXmW+j;eXNTRdTguH(B3sz$v$}yQ%=cN9Su)#Q3j3~+ zuNbacW#c>iILiAi8vGs=3nV)?J0moU|ISEB)!eblZgiuv-Tggw8Z(wPGfRE)O)cWh zv7@*-i5(k;|BYbqae!)Q`8i(VmrqX>>MSijD@`o<{!9Ahc~80B&U&#C+{{bG-$G<8 zN=M0?nS=_!9MD%{y90*keNj3I3vst?&UlHi=DczJh;{wQE>LEl3{~>2yBYo^#LYi- zGmY2c>k0ha^oRz&Z1*!6+CMp;d?%wD81;Ym#a9zmE=5KtMpE&@R)reDX$fL-s?-um zzi)yX8C}E8LQ*;p4{67v%sYf-zJ#I zktXaeTnbrupTZTL8dmtwhpX7{Rhs7qLynRbbP`MF$rojkf^_eutZh9Nm|E`V?OZ}j z#ry2R7|qww>^SjO7;~!n$LI^hL`4+y5AC)Kf{9h;;PyW*Y_@fnBVJPDn7Mp*968Sf zT;Tw8QMyC=hol?%HSjg-vGU4y{C-@XJkD*Y6MZfkclYmOEJUWh-wy9}vl=Vlc-yed#0S4`sb^_D-l|AMvv z`+)8Z6I#W!E8+EhqE6c%67U?7M1Ea6VhfGaebFIQkx@}rg^f6bwt5w*#Ow*{852@e z9DSiOy`}rkFY&La8Jvhhmp8cB1T}oe+1T9>9l{QtFHaI0H@T}=pYi43_;Z1K($Li3 zY(AKFpRBhw$EE`&V3hU%_+xV`>;_y>y`ruPYTNd_J zY%N{k{z!n8M=s_~33*O#M`4Ygpi08?9W@Lwc)LZ$s3m7trWn8P)zt8=QSMM}At z7yZBNrPSEp@(AQwFANmkX@->6^rQ^ec=QR!41~RDg!an4PW6R>0##)A4ntXO0*CsZ zRZ}PKyhT2EZpCtm92qyz1%*;6(p#rNlv0fWbp^>;E^)~j%F_>%6KPezh!%b7CtS%W zz#$>BhdBW9_eeOF9dbtH{7?8kE~JF-B7UtmB?~bE!r<8R&8iAzKCk$%FSWy`=rVS3 zK^D!9o3&Fsc;N#(Xq7kiyueK%TAR8!MB@mg?uJe_{YxIWeu)8@4QIlIsO26WG)A9U zA8ln{qtGbO<(m6U1E^F`!jG}@-g9+FH>9t~6x8R{W%&ht5c!|j_J+ionq%@5s0g7G zl6WuX4|?m4JbFPElHf=!OIJlzHD+y2v2Q^y(Io>?7xb|W0aQ;=KzZLFXpFx9j5N8im0bqCYgOsI!-5Mo|**$x83Q{STgU|&SJfX!w!>7$?H9wqwSbNvxoA@-l#obK!(VD2tJMtz*Jf zlVQtSR4QImG{)EMr{xj8)GrT8*P!NF!WvpdfgwBZJ;HaAHge$u501_-3E)*1b;^{Wi|DgNXF!ey}E=In9XdHGRFz+5v3(IEN zL;p2tn%BO2`50sCR3mR}cS$Fqd7VO^lsNCT(!JZM_3-o1lcIH>9;oz&>Y|Pp7=@*J zyXK0Jj^rBL5n)B!X2n_LLHdC0N|(8+4LNOYId)b$-rN6HdZ=FC0B>tk{-WSvxZ70C zvhUl69cEkR{BJRA2Wk656kqWL=x?_vVF{8}?xn8wjfnGMF`iw_$*rO%nyXFzgdXr? zyB%6Os3uwQ@gRY>2viW{A38&QWGG4EH9B8SPPgpJS-eF3<{04=+6S`iX-#bE13C6I zGFD)H1Rgan-Si#@ZqKSTl4O6=SI2duUi7Mxd0lk_2Z3OnQ#UZA+hz5vlxNZ}lc}S< z;~yC%Z}qW2^JBEfXJSWbnAgi$J2!Q|T)jIMD6c?6S0de47Lk&x`E9}PVBFs~FES*1 zVtOONo>hpTGFBpL25Ac?Jw7vfpHy|70>&J_Xk327BWbwrNl?JqQTT%Z|4@rO5hLR8qdi>VUb8)D_w|Lv`7v}nB!{ZGY z0s|{bl<;~nt=V`^IkJr@qc1tof%h_}}FA_!U%jDm4;OV4T4I1{G@ zv1UH0J&yJekHbesP~@E0L5^xj7cm79TTYiwZ?B~_y8C?TMpM`_|I;ZaU_<>^-EOUW zs7bwKp`PU@w2&4P`!{l#C#VoOEN5m_AJfkZL=JVo&j1C@UZf(TrC7?JI}^&rN&Rru z&AujE)pz!u;yjrjKCAUD=t6hBKR;$nljCq*y zqt!6v3Vn(TXEQ|+F^~>KHM!ImCzcU-!%72N%xHslEA~8oDAqDHmCuMSs&_C|RW>#22Sh#lN=Gyv?{SN$IWhHYyapp%RZU~E z4>h2$mz@nQAi`Iyd?!_XSiVQ4@lM$$IRht{x~yzH}6RUvXQO3Vsm znTQUFaV@tPRq{0<{RWL(j4E`>`O1eZC3VzVGNN;(>3ZB;KT6G#f0^RWcf+3H&BFQ4 zrYnQYJwM#b;$6ud_7Lmo?B8amowE~_p)VhK`%v#Gx_r+aiQ#8_p3d&A!xucBj>P6v zes5KfcD~_$*wHuL4_neyMn=v1VMCsGAD>&GX_AZ&Oxns>Z%=ZEBkg@x2G?LOEMC8V z(i%|hZC&HTpAq}1`V;df^LaOfc6m_RC6C8V_+zHMuw0)1k9%Q9|NriV9ewM2Vf8oL z3v1RZ`I{2OmF$JhshFI(N{uC3VRPD+daRaul=&s+7q3g4zlwLPFUE4?;lSm9Vj2&k z&@>!g#%HoXagPOV|GDa0ju%g?tb75x!JBVD@%dg!bk<9U!B4sGd#P)FWa}D)-9h#k}2z@#8_Tj`G&+#c!&*szxV=x$U^>eu@>3={Ny2MBb z*KDYwD!~r8=(qAQLAarbavHY zrL`%j&B^er?Fruv4{Hk#^99kA2?m`?mr;`&5& z=-NAv?+paUjwi#R`muu()4eCgvlIT_;h9mJKQS^h3KSAtmPPs!R6;9UcR8q1O%`Hd zohVE>k3z^2%4n143$j$>+BE#zl0}i`jp17Un95+R!7u77qDR&=Tr!?yCAOoBTggJH z@hV%aHx%3NrBAGUsmOr$RAx_?+7Ny76Wljzpc8Hsa$7BVxf^V{@Kj(bTmuX&R%SWH zh2a8PttKbkxGotd5VQqv4T$QpF~T2Kk~o|+ik9#BF;~)Jd#ty2~@=3g=4nF}x%Ckz?c|1O!1WP| zP2Y1kr`13#ej4i|MZpT7AyQYvuc@f_HU#DRh#tr zr2}`&?aS~u^sa?@wluWeuDnD$4@{K@77~8n!o-%{Vuj?w(KF8kc(F594aM>Osgn2} zHsOy$QQVjKVnU<9(>>7D&LIhOc!> zgUoB|6eT1>2hB%*3mlJfxj^>;wIO` z@Gjf_Rb(n8a-Ydw0T)OB>dQS&u?yKbz} z7po71Be-1`*Nlw%WrSW807LOLGWSz+X~#7)f8qSgjcvN!<@8VWZl6|syrk_N(VS&Q z2JqwpUv%Y>$$hiYja#=iwThbd?2)&(Hr-*QfKx`?<6{){fMfRu=9qzaT;eijl+ZtF z#_8)4e-Px}T$~G3KwGLgNPv)?#hZjj^M@}1I8nKmuZL=Kp*d36v?S|#@{coYAl*;9 zJNqVVNnXlSd#QWxFzwv6%^&1P@2;`=+q$==vR|Rg_nk@(=JrskoCivtL|!WdPuL&& zA@*V)T|Eu=@Lnt-_ugY{z@^Z@Uv#v7?`2 z#YQ-lO5oJm6bDjV2f1?q9=FS)f|EEb;s6mwn>bdkeBzhehtJ~VWMxfDU7)hIweDQD z+4b-IQomkt4;W$CYU z>b(kTp#|wEt}1t>VK@gjoWIC$;iA7t;Y0(D^hbml z(UzoKe$0M6J(pf|?&I5nXVbH;cOItaE6Zxpw)l=V=A$_w_6S>6UORAF>JM}43q`rL zVYM&kw=uYE=&sFX@>`zaGN9`N*e+5sb}L2AP%77+j9}OTgkPqkYTopc)W!le1xDGi zwJ$=Q*1EVxT`^ZI+Sm}O57%*}mX`(nIgOSK1-ABS1{T*%L!;Yts^R-`kT}hw#B{#F zaPnE{hgHlW_4s5?j}9Ksyg5HSksJS-)T69KFeRuN;Wk66G5$G~!WFSL#eq}^#jkQz ziYVZ9uNMJG(tJdMd`pU&-R62HPj_2>;v}hA@4K!o$oM~xiez{H?8@sWufy2OWgtJK zQE-aA{P{ImOvfyv5HuZbrg!ipE0(ZBMbC7Yp5uA{$@}s*Ul3=TQ9oT`{IW*_LSMf! zoj01qHEh27y7(*xZf(Vgw9a{qWSogZ_aEgkee}>nr+)mA6SpkVGSS<<@sZt805FrtmGi8M^nrzP}^`s$F(oIn;syqLN zixql@^Bv7XwDt#_{}Sfn&CUw(KCx|P8?n!3|MSL~8^0~Y1OjCMw1aj+Gwi<{t))Qn zGr=-OL?z92$V7NlX#Q+hB_=rWt;WBlyyli)8dY2~G&S&)&Xc;R;!2Zxaej{%x}p?1 z*w~&iS{~ZappI`Jqm`kmh&sM!ZkJ7SBpT{BGS%M43%I^6Zy_9=fiP-r5-SUuN)-j!?l<;N=6{)@PDWL1ua1_G@S}wQ{I0e9 zENd7Wu4pD%YbQ%Y!=kdEAH*4Pj_^F3ED}%FmKW!*W zt)0=4eN5fhzn?Tu2k?weh#x-Le}t7AXLLfi1p?pl{o#3j;Px|kLg#{U&II4C>LIMG z(?eJ(=^<2`@X}tvN@=e^(qm6R>f{*x6!+$Ku|HoWsv^(lP=zw(Tz;oEHbdn(9d5`L zOcjNLI(pHBDI^SAI%T5elWwgw>|o`1QU`T5)jHWrNZFR}<8(kj1kvd2c-H-CedlSr%|KySjJ!GaMo<8nC`FFPWWiPVdS9Wo^ zf6HF2>=j#Prf;fmL2ro-oUMsD>$v=p(d?}u5-J}{`P|tbZ`jP|i-tTxe)JehG?V>xQDivi^EnBC_TvGOe&pjk1{I(0FfLv5)okkLH%q zDw?hP{0I6Bw6{fzajdS5ztwK|m-jpPYi)~W8|(M^|9fJ;SS%as_XaK;7t3dLmBTv( zGSwFSZ}E5Tjlh)gSN?nw#=y1L%H)}?fr2|s<=YQ+fVf;MD#UXi zlexW&3kL4FkV9ga%TUgZcJgu{Cm)^}uUm61uvkVM6zkFf z%7~*wBxT>)GA7?(Mey%UD}q(&syAN~ymV>pRY9YdzLPfQYznt5XWx4leDE3Buhf2T;u^Pbil zY3JU_Kqy=xwgDJ<_}FzK1|gp!HW8;ery(9M;IjT0;IS#d@L2LPOV}>FU z(-|O?lIyuO@^--=Fvu-d=l63;QkBp<*P%@{8f4_$8`0rD3eQDYj zi!M4yeRTWOHs-wHsBL<@CeqrdT9Yn^eK6tnP0miHs_LdyTSb-Ta1JHizUeux!-0Ig zKs;vMA|98xS+@z)?HGI_Ij0^w*3`>tmy#MC)WIr&7}b^N?ld!1^}G>A2dY<3|l0ub$`eCc$ftI1Hrva%YbiP{OF_J{o7T zWL=EyFLeR14bd2GYzQ}mo5jvy(BuImsRsF>UNe`?`RqzJPWE;6GOKYQX?)*6qRr7V zyerYwH(}lDy5(rStG<88y4QXF$lP&8em&=LO(y+;!AxRyZgWR`dVi{|TbxcxAKw%2 z6GxP$cX)k3;FjFke>?uxg52A<%6nbwAt zM}WXSG2ZFlLm4De-5_c!6;~q^V>Lq4AfxA713|wVf5{0O1ZAYmVrmfJ@*^%X1Oxn` zWN>&hi+{oSh4OUybI#}DwC93zpx5IeEpfj=bYqE*;epo8v$2|Wg zr==z)o!UT48y9ttS@<0hjecroW1MAQSh(S89hhWYGV%CGkxVZlZkof$H6I4`&;uVc zl7BMSUZCVWSgfiQkB8c3Wn%V$(Z-_jWseZ4a($+c$`f5{s%rDs&IRU;b?ct)iY zyECOnRB*4^Gp4@7=F)XqbN%JPItyz9^qnch_i>#22**Q3zP5cePHWNEE*JK$%e}Jw z66fbrB>p_ROYWil1pwkBNMFEtGh5Q%%`Qs(S0=oh-6Qc|OPuqAv8b(NuXY2wRnq^T zb?~2>ano~uw$5{ZZhCIm^jz8J;;~(xC3$dEUa1jQ1(dCIq8A7a!z`ny{p_&W|4Q&j!GzP-B>n)D(wpm8JD&56u5m7UVC{3!albql&GP4>?Z0^6 z$!V+A<$m|up8MFzeO8;#{ZUdy?3etNmHtcFm$E;(&tFp=xDSZooBVlU{H;L-8Zb@l z%2cSPoG#gv)fmLRRl2o$&AnC9$>e6LQ@gIJ{<_kgh5b_#`%UE@>CJvSSLK=WF*zpn zT!NSEk9tkwsOJ)Tsb`GiH8fg$o_b)t^VDJEJoPjGZ+q_n7-w-Tj_>T(uJ@vHI_Y#x zy`7{}vvhKii)8yO7g=(Vi;OK}3>affH^q=*2uXm@5(tp@5>kK!2SXot>SXQ8znapZYU9yw}0D z;`&G7nl+=GFEn_(o;?NrJSpRQ!_P~v{~yNp&shwAVXl+zXjBMvd7A zR8&Bb>5%5NSVKesV?!M=fkXs`H#)J%3YB*gg%D+w=-UzsS%Xf0`on}U7z9pR2zVjb z&Te20*O-&>NI9#&%oB^n{AO#ZVeZV401pSHXU+x%*-efDkF`U2qgilvR#r9iw~t9s zURqKmwOAK5SB;fbmX#!1B>Hky)FM5X4pk%~4eeznUm)N~)I1m}_WGlI{vf}BFTo4+ zm$(;+R*8zBm5R9I$~%|PNeKi1Vbs`}6kyHVjY(^;mYl=JBowt%yJ=}_Lz>!^<*l(A z(GKB~vT6x0@TJD2vZAS|OuyviI^eOpMPm=VM~~@+CvGT_7~Ad6 zS%^ybaYkVrb^6jdQN8RDx7(zk6vAl9MqICSerz$g+pc~+dgW#oVeH*|?7bLXr~S$r z7SI2s%@|?q;P6rwQKvbrzM0$0ZsxeTh#nu5jvMhobxBl$E00nwJ}6cm#o8ZWk(xhd zSD$2n85~{?{Yl_}adtHaZ$F!(71B5Oggv_vfdbG=h#<@YU7GRZWP5b(_oL77*f>fF zuQi?0>RsntAHtf)pTztK&rctu{hXeDjPqrZs6d3ZM3!|(W`%u0xM`|XT;*i+bo!ls zw+o}BVZ1rFMJYv(Tns9Qj#wCiC+>~nyk1>dA8N45%K_DBLn#7#2gMDY8#v5LL9EJ`_20)xHgg?z=}K3!v9=^stkwGOq`-@p0sC8Ir! z?L+N#a20G*zX*%@>x1e$VT1Y@Y|#29&SW3jTU$s^rW5V0ZU9QrhK2%wube@P9M4VA z<%aFGf~;cumCX2DqbOzh2G>e0(iI=)Glo~=kl-A9t7Y(t<=ZZXF}kF8(IyLB(lcfs zty@;pmtL^mJm$FVg7JL<{AHudv62~E`*x(atZ^u9z00~>a!c26%|La1%aV>Qm#kjq z^3091YLkpuBPH4_UYZ|gRVmhkw}2M21sV>H^gBb)e;BW2>X(_5)&=8->7`Q%xNrRM z)O&JqOYzJ2X5W^y9mdLyz@l5-@FAP1m=Q0(y3rCh^s6${<_t;K;0Hc0DMZ-bYn67(JF zpl%y}zfWr3ZFRC9ob1F7LxzX8Mo_q;dLpbg4i|kVF^-_66SA-$sBoVYurIM|IdeV+E5pmXfq}uCF(V%AM9Rj zEd6}V79sAsVT*O0bAMV?G~$ z*m_`qzH@oz4=!h8`#|p>Jg(;U>1iVt5G98=z4z#`Zv0#~qlAc*>=l4BAm=(ab54jz zOh`gbze(u|4cF@7q2`UlTZF2yD%#UJoa|=Xv`}mrUF8q_;~yTSxx)f%Bq1L$Io*Ve5PjXx zZyUlz{B_YOf*#hol;pvT=n(M*|E1O(ST}k3#X#Ql9aD*%4pPqL zWf8_TB|t<0MAVH-bO(P)8*5Gn2E}v~Ig8M!$~i|5!swjEL05^p z1m&Nh2SwAT$7R#*WA;~?CTC+aQA6J`d>V8F;@9;aJ8_dTjtvl5V#8QO!J`Eu7#9>x zMtePkgi1VR-ZDJ&pwY#gPZvIlBdi~QA(X?&e{fw>b#_!RISy}z(RBycshQSACKGM0 zudYQRWtV#Vsg1i>FI~=@f;>ufz4|K8|MYz}cMNb}+BmuLnXru#1$13MLMTCv0XIl< z+72oW!giBHk!)xWpYNG*!k*CXrR~_lQgrAJl$Kze#FBVvoV(>FBi;xqNV%CNuZ8-Y z6VGd8i``RPWf_BTQ%`0E^;$1jc5Kh}t6XCl_~%$k_Cma(r%uZDb3h`F<_p9kF@zB26D`|#3ruv7iuU~T-cYz;@$-%n2)aat)Eo0F@gKhulT01yR^817*}sHo*~ z$*EO>z&ElhBrRu2GRd?nw>M^1%JPnirwV+)3KAuC4_UnIpqOtaS<=RBv(qCjUU1d$ z^||~=`FTvZUkuLsIlLM7i;|2>V1WuidEhP(1w1*bY{yBB;Z12y9prc?IM%)-;ypXC zW-2eo%Iu&K@a^pk!y|h(Y!k<{7Wh~Tym||qH}9Y?Bbw?nyD!|hs>r9Ie*N%OZoAe7 zBW@9&&l+auzJL$p$9gmJJW$f9`E(FME7<1{Ml@CcL)8!gwO?tH!i*5o*^3bNU?}d7 zF}5-xTWO&>6=V5mxEL#nuyFT&J7nyKt2_-G>J|(LEn|&BESg^2+DzZQdiAusrfNmM z*ROsZs{Een+TKR>JGcU4_>D9A7n54DUq7o&1VR*n>|u;Tw`-ywbFcu8Z+%**HlD#> z*@NPCB8psFFXazwgS&zc?vfHhN@`1Lq7fY2QQV`)!7XYV@`845;mpzW!M{Q*THUtx z;M$hee#hjhB||Lo_C>4HX>*qlkJYyGi)H2FBLDrkMpM6W>*%hPOM>hy+r|r4b+y9* zk26u-)vn%-SAI4{*FRjO6i->mAQ1`@HDYX|-j|zhOWh@v>{6vLq`e9Kgndd&IRjqf zWc|OUy9LX@g_&O+9BV%K#Xazm>RZxT3+-%%jC*~L*V{YZHkHsKG=sRb+hc0#$ocsU zah`}_roA9gfFV6`Aet03|Ara8TpI~t1(_p8qKq}rMH~5FKYL;@M6`fg7;V2`A7I|u z^*U#a&Ec6QJ&^(w=Xhim@BC!rg}GQv$kSSkro21~Aw5?TC89*d-9!-hU@hl|&0xC> z02Q#Rtc;MdWLY9oQBvgfaKng6IbBu-VP@QVa2y+6+n6h0172?0-u9YDi~G5Exz+!g zUubKwY(yEeTysHIKfB{n_~=28v#DiKMolfw96ieR15O(4%0r?u#t;9S38Fe}H}H7iWP%4w1!CiH}eZE{|2#K59- zeTv#H9sBFZpNH0Nu1?%te0O7KQA6#$#rHOK%Wx=bGq+bOjumTZqPJ6t+}m99hNYtN z!!=sWQ{3aSVcaK__g4LE6QGIn2#+!^UYCmv5J74a#xq>l1F5a4iWdibUbllZK)s@% zOCORMNy;^_XimQCCaN6KbCcH})^8B}pBk#KmtZ7O)ovN{U9>7Oyp~!=*AHFT*icj3 zZ5{I*SZ7(>=kgpawJFhvY+X=Mni*W!4~usXm_s~f zOO84JAnfW|kz-r>;)N3xu@e)QZOoSVvpX+NxAX@~77mQ5i+rw~1N}PZ=K1^M`1{`M za}e;)GxmJ~)32}(lQeNAyH)6ncB>$+baO}J&|sVydvwYA?sQ^BqUBv9_pTV}OINL^ zYJ(71US)sk8|rUQoH)Vzvu64q)J^LdrH3=C4gJI<3Zh9ky`Dl8C8DV*<{axL;uzPZ zIN)(P?c67|5gIHy1EZ(pT#vz7j4Uh0u>9@F#5nD2Xl(0mtiRHJsHL;Is--Gp8TVba zx@Gmq&_d|x6s%WmQdabpl&4wzu~lugWfjrVzSRr6dsd60m}+#mmv1m)PRD7I6p_VG ziy)GmKe9&vLPA{7?V!0uU_k$peKh>6Dww~=XHhe8@kM$te=7nFUHN+tZmR7)bd06- z?S>>wp|AV!@{%A-s1F-^LKkDabz)nK*rZD(rtzw+wmoMJe|DOsBtxVG-N( z^}YY`p50e&r-}dg5A{v;H*e(5Lh|}PnLm!F|BJ1E;wVoGY-gc)ZD*nRY-cVEj_#YW zo#l*Y*rz^+r@Sg;ZHLQ8##Vf-x@g-*X@@L{j*gDb zA5Xow{((QK--7f@A77ud!66Nde1C=1b{9~avB5DU_U~itJ@I>*`0a0}Ui{0P@jgZJ z;Lo=4h32>MjlctpMhqm9hQZ67`=DSk=5sHH|D2kW#X~ePC;mP5UmpDY`1gayZSV)% zad>|9YGYrKpOf7=XP@!2dAunQg?*2{YDv;ey2Ra(y5`YmHhhDaCs=Xe$W=abIXOvg@gEM-3s<;>pu30zJKw8 zJ6(>Zwk5rHI@#vn^t7>$O<@P`&rRI6k|4pkHoZ{Jrsvabdhxk7y>=~_Io#gaKe|m| zr%336_R3VTP|KL;xOMe%kN>g99CA&QC;>RQYk+RsL!D=~Z7+1rwmrs7KU*=j0&RN< zwFdr8t(mdyEux7$+g|7#ZF}q24P8F8Z0O+7S_Ux;zrojxZLgaq=Gyi`Z`HOpvS#q$ z-~fBA8EoWuC*VcxW!Uz#FioK!P)rz@% z4xlB=1%e1ec^1CVYzrS|F7kWr0Y`w9uo@P=g55=?b+(U;RXn_Qi(tQcv%R%Xfvpdh z(ZqKK7dhS8t;3D=if#F`gp#mczk?Lv&XR|(tmj(yLWR4WLBF%eRWxgtGnzgv9@|zh z<6gz#d`u3P!M|naprYIL79uThbvf6r7n)<&^SB8qDRP&3N|{;Du2I80ml~Q`&&Zj3Zvw0?d>kLqEr2B7{&#i*pmHVypi<>v z20(KUlvJPrP_gb>c5LwKM%ShcJRD0&3dGBMDx~$jtuS$Xai`Z(vt&KIp#JCP3s=|0 zYGg}Ulsh(2;?w5YGui(_=WhSQ*-)9+{-^jx)>gc;VtK^^hOx{{mbcWsvkppQO|lG? zn9w+J{P^+3U0zGozisAj`8=xqy&)5jQ#Bi!^=U9BqG*v)lfZbFlq=Qp0cq#sqCg+n>x@APH&K z0_&LjhHbP-M|1rOb3nG$H7)L~%9gwBjjh-O)B}vTMwI+|c6=VbVxin?G#B5)&7VV0 zPB3C9MbLYsj2{A&K~z96iNYQX^a;cSldQqUJ|`jQN{zA@kN8=X@acjj7-wws*iKKa zK@Th@4%qSghOtfKwylma`$udavAe;!t`GjUdWkK}j8JtJPeaSnKJ^#0i$(Jr%wnVg zN<6Gjx@psy?SY{)+5wjurlyZ62Y@T}Yd*6ey&$ZOb)@YTHE0yy|HCdF&#Cbpm1tb%QW=Y&*0W+b3nPNO4 zz8zO;xJQIJvsB}m0?iDC!ae`F{Q!otu@|xs_t|7^ zU_P4#IarW_l!o(iu&{Y9n4g2?nYuf-Y}u{w4|SEnO?D?_6P#|0c70%P89*xNG~RW2=1rySE>JB~f&sUEHVs zZgD1=^f19ksNstx5DRLQCP0EC#fvKqLblZiDn#jHLN0bM+yn@OR9P^|?l((d_$UX2Gnum~af zMNsbK%J3X2{1HhcN9KEGR0~p5PwIn7W+Sh5n@wf4jJ4VlbIrMYN=dgA*!C6K{@z5p zz_@SM=q|C&nr(*n*?;1$>NVGEIT-5&Hm_zSrMKPXhoT*q^Hhw#U%J{XXZJ7fgfcw~ z<9~QuwQc(e81&}89E{qKBey^)(pvZBaC<}()3YGSR6ZfmhUh?j-M07d=(4!Wzevlz z#H{tZ(3wNMUz6t^#@98t-l4bZy7o!B0oOa|#VG(tvIGZm;hSrb{MA~7Nd*Y0Lqkx& zmv>S!2tku6P%G)@|8nMfBcRgBg+oH)b8LZli__4N^j5a}wKt+jM;Gx)IoZT2qc61 zk$NuWX57ahq6s8HlqP4=Dl6PEQr1GY#A4_h8EcL;)mGfd(AHIC>euU-k zME1eUyC#;ev!rNGThDrSSRHM1czVn& z3;rA~b{3WMH*L;_Da`wYyd;Sfa+$($GB9$O``kGa8N~* zCMSq17k0E{)>+5Ax9!@nQ?RTb`93VSZ~oK3-qxn{vc8=MH!%U#clD}ghY650?iFM1 zHcfttf=D?IA|>K(o;Mdm9Pt2Px!5s;u&3h~e7(wpF^+N>7xNtOX65Q$xM(5E`8r0s+7@IjCfeCP==c%yu%<7LeOlNw+zQ2mDEW5wz-LD;oRJtn_eHulhM z@JY2d@o55_Uz?Ez7*7Vc0TkDYqJ*d5ks#M0K_nthqV6e=lhYE!?MY%pdW_5ERp#sf z<$My2X$3u4Pu7UeRqaE=qSblJ1*1FZ80}2=4qB`%KyzZDXKV=^vD0_F9!stpDhV## ze(B~_wT+AVmb%&QRdprYi6kME@BO=YEc67fF3q5YIU|Ay!la(xN)*xT#E<0#gMO5151WBTWO{v zv)Ll_r!5z3DDm%~fTa4A5DIS{4iydT?arHxAT5|nN*M_ zl0h#c52d02xjitHM!XAWrRPp05><`WvN?YbOk- z-mQBD>qt*clVDynnb~lGu(_RWQksSK6x%9^F6iuEXAu^3EL>}a-;LUBt2?~@@k>Wn zdA-Z_IIK%r+@6jNO&gXu-PF_2oauI9qVrz$YtFWg6^lHs){Yg6kq;)gPxs3?J^&zG zZxsolA`hOZx0Gj#p2G)$WK1#h*$B|Fp?V5`Of+I!(XF}H(Js)g|4{wOnRyLhyuh|dNRQ`Ja8LU|$H zmP0Qn`SUWH<)@PWDimpFMPF8b&u{dMX8Bp<)zk^llE|-SH~h3H&hr;czXLuGOF)7D zn*P+(6gvS%=(AH(JVYV>zIFP2a4&ST-~W{R9rAylWWPVo%m4Ybzi(mi?}r}t`(IA` z`vfb04~PHiX@B3u%KsDp{jaC}eK-64!~FNxPK*C-4E}Tc_t#Hbe%JJM@Ff5JZ_}Tg zdL4fko}GH#`27eguhHj?LimJ|XW`w{CM=s9vu!vpX4_g=b)H8f$n;X7$U43(gO@EU znp>43T2)zEBo8Y}YZD7sEod|OqANr+-ch8CXdwJ&BmFTCo~=nG4M_Mt)|N%+jqyPaQ@Ws!|aRnm}>y;+Pvje)wxHb+b0>_-ehnq z$Q4ghka(=70FUP@OM)b09ik{)qQ{fR8JEZD%^G{7YqgL7#?v_STzAIDF%zXH#wZtc znXF-qTw-v5rb{5*4DLur;LraOa5a}TcTmgLB`m(!K)j-=H5T#3t^Em*sroK|u%p>) zS-7%4T~gj!8;-ghuko?@Io7t(*KYEZFAY8XRhQ>_OL=8oTxRdJ3G9PkvN7csdNrNFcN(2R>)b+}!T8D08E_!u zW-ICpkY4?(`z%X*P-$b#Gud~2mIz#4i9G*uElJ}TE(d{fy}^zSG(v&$FpSDWjymi# zT2&nz!}BT+xsK!n%8^H&xo?A0EwM;~TDC0dT~1AHwdEC?mUb_Ofy!{Az9L*%F9qU} znzndlO)Gt(RZ;4rimP)`Ta)5w=vL&aiUrGB>TEJK6_?h=O3LDqdm^ctvht=H-rqll zySOa&kqV6DgI+-v03JDzpuT`=f~F}B>r^8o94ZQ6Z^w%C-o_@)K4=%nNB`^C%fXvh ze$eD>Ds94UPgK^mCn{^x!ZPgQvZbL%Sr=oEZ>wyp4_CI;5t4U)Mj+mdivSq9yo;i0 z5{1-7eeivdHB}a<)eAsUr%Z?9?!bUGyS{F_@UbqC()GI_k+{e-4VIf$%6N>g zM(nYyZbyR-+|}}5es}x80`*Ux3sW_Axx6RXYB9BBmQ>d;<3uQ0)~e;0F=&OJ;xF*_ zTaEV9A?=u3tKNJIRj5TdLa^5^F#&EnUuw{T$YwJqfq5G-%jRsUHWRcJl%HY4T_Q-q#6oa)wjsqRH9r7pIq(x)c-Kvva!8v8DD^hA2BkK68B@{u_- zb*Wz+{n0@7@h>3_g*<+%Bn>d4Q85I9Xf;!$qGm|zLm?;%2Z&WR$yU=5Vp0^-C1x81 ziv>wRh$!GXnc6|NQhAan7K<`M6veWQSQHBq6gwlMfuTpv9}e%B{?ovbP0Dp|0TALc zKMc6#>>x&2k5!5yA@y}N)m1#|yjUqlN{WkuEcln52t;r@%t79VDM*1Qf3`Q~`jnza zw#o0*26%z>s;vilpdu8ht0)bdH$7l_-n6~CVYu(fxqW*_W3^Ql6kli>9WNptw?QTYf8KkDZ2}o0v z_G}#}lgBtss?pPy$2-UEBt?)VZe9t6&^#Hc4pl`X80g>c#S<@a%{rKG`D;1Dr<$N> z6)S=P?eftxe6oa#2a3bb#Q}#T(`|#nZdrST0)g^(jHfMiodI;{Pb*#l+jL4tY zMR_r&fOyIw9xfo>y1MtZMrZKfKY%B94Zy60NBRlSnecL%d$d$~O+MlR7TGzrYb zCJW*L>@blClX+%?RYN&P|j$Qhr+q%B23LdrwISWy)14*}+QY-Z-1bb8jo z-P|NQt2N&$YsqY|(EiSA9oKHzD>$xR@7`)q@Ow`!?RJ@(JJ)YrEOFpc(jW9H^X#$aCLE3Aiq~UQ5>9`5BfuKd$P2$r87ZzuEJQJJyB$3%~ zGTk{-f`=z9#?c;)u=y_-@H=A8nAVBr!cNRnu?^KarNADeS1%r)6zo@RaF3O>FoP29 z@4D6jpE0`lkxi?;{`LE%$)^@|xlE1i>)G1nz(B@38D&GO*+!_FB(BUA%Z;@k5&yKeYIGKl{i2 z_yx?zk7Iv)iOokBv$@e(I5(PQ;snRc+?eA-Ir>_0DBN7)G#nI zp_d56opBhGVQwmf)FnIMZ#(u2pTK7yWp<Q4_z;ZojdOxw@)1NhNX?!Ys()w98Z3E`$PMK>w}LT`f|K< z^L1W?mzur_zRKWv89c9r!3*Y0OUZN~7o)C!;@t>kwd3FsIb8JRJ7a-I4t}{TzU6xF z`tUy=jwZf**Y~5CXN0wRjJ2a4Jo1a`5)fc^#kN!GRTUk+F7KyVK6dNtb`4{jN?`-U6T1Er5{k_eS z%XDD0es)u8t7n=5cVz3+3`cB5$B+aFv&EIdvDqKg{q~(2hrd@W8M{ zAVe6^BueqNwS@zW55Y8y$$=?`oa?vMHV2|jrQ6L{q zn!5+WDh|c=#{R5e%WCI7ppv=)=aiz1zo0y4af~oTMRnK?pMuKl^t4fiQWuA@jD3!r z0}P+qYKQMK7zBu$mDzX>WmpDJJMGfSkm(1QW&3xmOa-oi<|~KFyu`}Fuha?~{Ayy5 zoCfDjOt*Z`Th)(0p8a%AKX$S5|KQ~n(yBqQ3xJqV&|!E5;P~afMhuPZAP&#VUfYR7EBy=S*GMPU~)jbI*>o!_?hf3_JSYfpdg&f7@W;-3C?pmGWl?T zsPIEd1?9Bz4_GNUa^q83_#t~7$aAddHwDxD&w6$6-1oJLZlfk5X_io{NunY;mz@St zX7AvL#-m9#p-B84lDi)L^ZqyB9sE-D>Z`B+iM{`%0a zM@{^_>Wx3X`YL;II=r7$!Cw$A_phcDVa{bi54KcC6CN-y2djUE1tR^?w1Gy;c{A0<)hr<@sKbZ8!)_Z0SdSvff0x*W?Ja+V+F{3G_L}Y-3!2Octxk2cHytQq89e?a}dn0(^mgSNJ5fTPLOB3 zRZ{@}OvIFj%d2bSk*rNBsVFP2uH&*vUBUE`2e@w8j9$@pevW}BO_T^Q1c^u` zG}H+K=UL6Cj|!_B8XB4#nwuJHSdNoWNpUbziH8UTRN~KB%>-sLc$TSWm)R~u^-S(h zRn>^7p0O`xYnpKA&ape`J*zhA%BIp@?RTS^Hb>c<`jGI6Q|qu@*Rpnf5cMo=E|H*6 zWkZI^msUyyL%sZ47?6A=Sq_-3RnO^K)%1tob{GXDL1r4yaK*-ZSTZWy4DEKjNLf~PvG0Pbp=qz z16zqNT^*dBRyQ!5e#CH!QpeO+2?3d2@qkmyb?DR<+ky&Ahuy-SDJM~qBoF0c!dr;h zW-;$(GYH5c)u?15ib>h&0Gq93rPoafv5x!LsIgk{w3B||qAgdF|AJ3}mF$@pj9zY( z*+WP!k0?V0^RpTYQg`mp&*%fj@)KVXK_`z8(U+%uc46yPx@Fd?RQ*D;POL__LH};5 z8rCdU-wjthwD=+F(buW!caVJQPx<|Svp1yU9`a-AhOdz%6{kKr{d3UtPHwfB{<#*D zSACqVY2D;*5`_~}cxsozi6_|ir!JiSJDJkHKluzH{P&M(zdwM#53zDr(6y|Ou9#j( z2!9TD^ab|ZN}~1S7WT~J^hI9wqga;00~%hB(K!4e53hp-czuGET}zu-*;7+*@_J8k zydGuW3)=T5Q6*tl4qJdz)7!LqPnDB;c!c#>l09=FN#k{@k)&CMJYij~A-F+M1{V?zBp9Mh5W29#NFjxa11^L7WA&7~SRJ79UV zvBmp(o13DQgbXa|9qe1t(blw}xu+&s*%)oe86TYrQ-e=ud{h)E9mh#Go|csO8LaTL ze^Y6pl@e}r!m3I(qSXJe!!g&1U!2Zt|Ka&fna4KW<1(3@_ilK8;>JSbzGN6WMRg&W zfH!Fqmw;s?k~_OmNdy341P|B9BMOLSkVI)0HBtT8K!l*-(pdK@>_J7|P4wqXkb4Xd z1(vv6gkY{=SD7oMc`~!=EHR6sdG565$in0R$=mnVzESUrwO5tL+pC23sTb`uaq8lD zTUA9Io8CUqN8w8b_rmH&*y~-lmVqDSb>%;h0oE%{L_)C z*X^|b*w`_++^&usp)UK>7az+$lzseh_C^StJj&t&rs$^`*c-HM$$Db5+Kw^|MCnpi zt0|WXN05OB_pks?3JyDEa{_j1UG915ma{&Noy(h0DEOUR@JEb)dYg=P(Uf&+{bu@x z_0-Qd3m4f=?Y?OJMN_xf=s#_la$1G(mQx?F3U^<+?oyfCXIbSZSnarl-N;;gnr1p~11x2zfdN+EdGN-t{`8xM?%mlw6(3S17`z4dB z&JX|0#9*{66jFbKVldOPud!WGJT+@;ELDE7sir)5?X~6Eh|uO{U%3@?clExOeZ|Yl z%a@j1xJ8qI>z<$BV?1YX#`eEB{RB{IGUnYUI01yIujsbpB&j7$ zDK~hET{wEUsaj!4(IQ-RnrqdMFwGk&j;d2I!WMquWQJ_VmDdaE9cap5teN?DS}xX= zCumDNeJvWirxr2w>0uZTQ}r8Q=BDn^^2e^xZT@(<;-A9Y41WChmo0>F+UU0HPO^Y3 zhmhv0u#|u|V1WZca1mm2k;x+Pl7QJ8*zI>yGwx?dW^uQcmVTF}J^DPPw6MQ-dEfE{J>6Z5 z2pw&$7PBk)kz%Dh&pz)z-O6d6-sH#wuo`V zc3+{!Pv65Iv@=uwDePVvZE3cs8y3U&p}J+z&dvJ|cCMrnbk_OYA2aOxcjWc@Evq(8 z{jcLap^D=bp{(BLVPl=~Pg*B+_`pes)k$!nVNxWD5p8zs=_l-9wU(^(d)a zZ?WJ3etzV+G}CSr#b5YSCX0E`yl~`PER>p9jF4C|#+DmrTx|q2>SI`J?>uDoB8`#U zG^{Nyn$;^$PsLL!-V2{H&>C!jzyg2210^lVc?P5h7a@m3ij=+J;qnK{uX9BTWypr;hv1K+gNR7S#3KZoW5+H9_RFpkT^*}R5RT) zBQYFytH7z@R47uxH=CZs>m}oUk4@0Xswk%i~I=Jy#wd;ssEvD+D&T zbf)WE3-Z3i;-2k(@OVl+OcJqSkW5roHq<6k$(G7^C0lv39ktMDIyG>XPSqStB=)uL zH*ij!d0VCC2n7Ij0Zg~!Qo(iVPkz@A9p*c-5y$51b)9V9>AHl z)L1lT@JD=(+QmJmh3EnV#o&6j2N@~L=fcSh5`F+vJ~BTjD*Gk55Rw@f2o5i>ohf~# z0X|=_`GG9#>ss19(Akl0XN_*nn<#XH2|sI{h`0kdU*tK;8tNiWAQ8iAQqY(BTmf3Y z>Atn_wM#_DRU@vk5T59x3l}WiWHGBJ7GG+)u290^%YEm*DJRYqqlRM$eR+JXExh@1 zdE)UE3oYKZu4R2aMhD|%+W|FxTzxp_E5gU;&-Iw5wWN`xNSZvO^>BMhQNSTmCg+_Z zU+q}Uih$f5E-fn#1?>usGaKtD5l5QO4r?<&@o=#ya&|O++p)-;qYOvSMj>ZxHTLt_@8kL zX6;JklSg&Bc9TA`h%6<8WHotBqwV5Etg<5Pk!e|JF>|GqIZd2)MimLEQkSfa*F>u$ zRpo9gQrYD|lFCTu5Tm3|(kZ<#_d|XGPVY0rH-I4Bw+;<0Tef&{Cezb1w0daus+G$I zmkq91zIf^4r2|Vci!w}e>gnt0>s`>@g(D(Qb2@v!)Ss?jBKg;X{)yyYy{9Q~^55t7 z7dY~73VTj{E&oRELvY}|abxsmL67G5D*mBm;UD#S-(sJxB_m`L87Di*ZfMZ@cetgg zp{}MX5irqsG*XVeVB&q?b@N_Ouot>goy{GM>H7BCw(8cT--$i#^Jraa!oJ2nWL>4` zy`7!;v7jjS`MK1Y2NL`Kx`~Nx+ct0BxN+UOY<6g9V)w-E3wCYWxozi;?VHCpk8jBHRKGE1#Fk?qHwg)G`g zzJfk5jJ9YieTPP)2B(dRc7XyFVK>3(2xKR!1|=)qE~|jY;!%T;wJ4ALgcpA1zlpN6 zXWr7<{X^F6so;Y=!HGTr>j_0-f z*YF3%QuO5R=?7>^SVUS#JGt#M4WO*}KdIrVRH{A2ghIX;$ThskW7tSie&vh=$aesY zBQea-BpWLWf+-^jJ6HNV-J!9kN5L+>~nIs-X3&btlkB+_ea9_X?-S7x> zwH|&1|Cr*LGp`C!ND0(tpBmag|7t(=+Fj^5`85228HCvh=1-`fAZQof`L@<|;@>w& zJM1TJIBi{1FR(q#S6E#RjQ?r3$fCe~cX{e*3c#~VVLB^;Z2(A+Qot|}va;~sRwfl(U$eCWw9vHI~G zra+t+4M_%~kfV}`f(WQ3gd$0%*SaIS38$EjU*wyst#Gs&@`Um0t@lnlh zZ(d(Nw&Ab&>zzDq6FVjb@%uH?x54LxMj~TwHCdnnI!hV;WL_7Qx$kY8myzak`%ay@ zK>ht?aMxAvezl%p`K7G<<3@RDPI(V6AB+N|y#CMZ0~VI&f>W2l58x;2MOW!D)ellX z{WNAd!q{3>AxRKu(k0_`F+`|9kBT4=%@yY;(ReCCBBj1!OneF4L04$!5$F^}&xEbJ z#B-yZ#3hGUmN6n-EZSGyY8i7~w8r1>A6z2_9S1kEyQQnBdKXP5`Wm}Ua6q=i>rLu@ zQ@VEbPRq?Vnbt3}Rop#xvFWCp&BKcJ|m=HZ5!;+!uVDZlsf>oYZ4fo01}* zM--scZ3U4E7L!OtLWQAXFNGCmfs*Bf@)I|?;0yi2s(4L996id2!VKwhv@)qA(^~Wm zW^`xvmmssVV@t%qOxiNp4{s)yFJIBt-BUZ!w$m+Gs+KKZk?LMhzoTuZQ&2zC-CDCG z*_EmpsDi50NZ&|V*+}1p%37DFH?^T}W2k(6--hyPw`W;r)j(ZSM{=N!5P_swU$hFt zq>-daANu_^*I;jShh+hTo-&U>Krs3Qgri0`6T-?gR#z1TF~&+j?-nJYO3VD00NZF#SR3JaS{1LV?Clrqhd23q{OdLeW3;8Qx_H4N!G76@yT`qJSWr*I zTYKV_Hzg|ViS%L`ahc)`%9PE&p~vl8zt?orP0ISE9*;|@YL>xd@@?#Kd4~6x_U|`s zSmg2?{)1_tEzxFuvdt>KVIE8qY=30>3Hm-BH@%6pl3SngOVn)21-`DfDVT=j~)53TJ75%V7K?#S8=Xs zsH?3`;-v5PR(g1-Kc~4|3qNB_^ID6e?MB?mg4mOvn-G*WmNhQ+Qk?JFwPivaquuGA zH5TO~mXEmDOJT8v(yJX~#YeYTSjNdfRsTeP)sD+|Z*E_(tdD=Ncw0Iav~Su&VEVJu zLp&Z$3FcstfXezNt|-ogoKeOx?#}{6i^5dw_C%s?Zv+GV=pjjU#Bn=-<18>Vm)j>< zZjHW&><_stTb6&={^35WlVz6a%O%ygeR$i#<=LL`VfDbq3pJnMa?FL9%ZHeY0eOUB zBxyUghzf?3*F!^*Tx6&g(o*FPxc%;un8h5fh5UFexRu8+!l8+CofcSv;j4{HBZB7- zXh(DRauc=NsZ08t{bA9(It2&pYO5=?QW7WagEpsKaNM+Gbf-WQ4yC%Ov(2Rhlf`1C zJ8KJfZ7a)8#MecNOR{B^b!9Hk`ibEcE)TY;lMs3tqi+yTud#UiE=3loN%tHEI-Vc4 z$z7~P&Wfg$KFa><8B3frtte2pvFusfvo7|k{D~b@`%lWBwSCt0S=(nn+celT!Co(} zUi~%wmQZ5V^I#T{C|Q{4vze(NX{;&(D2%Yksul~UVh0b+-Dz4?QjFmZilZe_R*s!W zPH>~1ozXOvV^FVQIM+DSI}?d_VR6=$b+A|4FGnT>$2)f%b-ZGGrTFWetIV{cWu2C9p>ZDglOL*lo2? zvzZYrFDO{vUI`vp2f5WhEJ)m(zEVFh+^UJ72+_2Y77;6;*mQ|PaLbF}{L1Jm6EWwv->LQ6QZe?E$G_GrNdG1&+ z(V0zV;^A!Ap|mW?YUfAW$bOol3El4*Bg_E%8VKS?CDz^OCBgB-u9n1{Pob=NKr8x- zR;kOZ@T~S;&6kewtAT0uj{u2j`Eqsm5)lP-yPW@ghz>u3DxB^e0mo7BuBcXDutPGY zKEs6YFwo)O3}YKAr@u}w7i^5a3DQ8`ld&`~z)ld2W9UuV@qO;VVFK9<1Z1+uW}#r! zB*R?Aw=~npiYQ0Vy#x!zT3%k2EKigtDp`=(8c!s`nqik2LuuT^J1)tX%IHbH9+T2h z-krgyCT{4SM@N2Tn;J3kuJpPV_YJjlX`Q=wQQx9>sGl2I#XI=&8zdSorCpC@AIl0y z?+k40(7O1>8&5oz>*b1eH)>Edj6N3$Hq2&&k}(EAEI@&0ij{I}9#H`TBAJ}K=!x*g zxLqb0L#YV!w8EHFgLK<7k3f>)Zj-n4?dZw~ie>qwi$^#2ZN67kdls#?$U;0yW%cXB z@bs768+(2Jy8fN*PdzofY#|G7oJ?7@G1E`RX_U4RD`AcX5!Q$PT!3{6xbrt7eK&e) zmd$vyi@@E_*@g1>>lCs^_;n0O7LTTlNUhMhvHUBxuaxum@#nJ7J*S;Lx*00z;2F*U z$@&?f7InCopFJW#Hj;Nx3w1DD<b~NmwI4m)1A*IH zZ@WEp+k0Ezds{0Xf4j+gD$vFJJb5|Usp(IlnZbu?&BR@D-pTROOeFysaF9;U8l%;!4j^#Caeddj`wnPcXrf^)G!)|lDfK%chr5w3|ms$OD)JEloVxR!mvEKBfR z+~6n;mM1?lsQyQBpn~5ck1f`HI0fSrnJz^r<--KINub8z9;BgwbS&a$xKjKb?#rtG zlGXE0GoEc?JnO}{iugsL`xPI73g8fw0mopz&lnE8RG}z`zxLhrF8e8D=0mRMMSnh5L9^o*}gYL@p+f1XDTkoBxwn_f=9 za`AXNu1K;H2udvG)j=2h(4jtA$x1`G|M`jMH*19n(yyAmCFu`YSqJ(VnN6YqD+>6p z6!|X?8zkY<+5SMBl3$*|OT93ggTH(Rz9PVU@bj@o`0&PT%z{8;iUbsD#ADw7*;IoQg}sewSGQk z4B*)32Y!u1Sc@T^Ad_?8IPG3yiPZD@y0=;~J`8Qq6ZnT(~Cuj?N zi1eNLsHjiG7^HAAp0u(6yzMhrQ_ALX z);`qL?6C|kSdnU~?&@wadGy6jPOv{-0FnZQ4evm)69}woLkuC7IiZV zy3M)8+$Mb?M>DvLoBAqW!~u!3x(*|sVIFu9=CG=Srg6yA5rerv&+K~r*v$iWYO)X9 zJa+T(r-Yv2;Zt81dKmtHW-uohOdF}rB+LTEK=AV&bN0G@E>Y(8Ljcrmy$VE_39i%* zSE{NVers26e%Y;l9u7Y>4A;U%!&&u9yVWmp+s)T7FV??zV~PLx?n^MgVs^(R>6T)Td*pqMn69q5B`;qc z0VDo*5Kq2&c+_1AgmhyNeqjd@guay++i?M3r3Fba>WR5!Jff`SL(?*s>q8ks)OZe# zbqW_;>FXTpbY4B489-|ybw0(GWe<2MOeam=2FfJfHvF^q0g<{3J@+ z$YSy!JI7H(B{2hL6V=l**IGfc0LT(d5}BCHvT2gjQ~-<&YzMQMZnr6v2dpX0qza!# z6NnN1kKM5+c`;=>CamgI@W@bmdn^_R5YoQ5eNk^utS#1BUmJ)9ScXBrPY<(?@t{0~ zVfLetB3x#n-2|!PnJ4I{@xav?YPF2?b!e9xSI}K6)JcmKI{NYL!CAl7#U(54VHJ+Y`?wzlv$H97nDB^8zZHn|ypYess@)8A$EUa8YNMi!Daj3Qso z_$o`RRFuRm>sK!6Yi~-Ltd<<d!{0!^irB70xiL>;C@&B?gA zIa%9`_bvQ>k=X$a#pR3^wO^?a9Z**iVej?uY;&#R>Tm1SFX}S-;_o{8B{Or3#CO%y zP-SwBrMly#rSbY|VHOtRF5Lu0a~CijltXgM9pVR{kWNQy8f4VmvCB47%7o7GH; zph(i}8TsZ6C1=Tab@N_ry~tO;e6iTu&F&9xTcfQLwN+wkdKl}LSl!F9Zk(6&1GA@{ zmx@R*lH~Ieb2T=?h)39cF7CQyhi1Jx^#|;J^MwqL6_+kPj1{^atitWX9*%*QgMwZ~ zKgz&{W?OX7fFqCslL-*qq@JOGas~>ZF=c8VDpX9pX{V;+1++M>#WJ6MjlFHq@xmQV zgCa5r5)lgUA{;NBI?DXi;fqAiJQVt@hExHa5UJ^DL%*i<8qP124AAx57S_USEFwWC zo82>*N)qoo9ub#F*mq&VBBZ!|48Kwhzjl6}I}gbmmXu+|O(W_e8+-|EUmQ`xI5v=P z{W45q7~>9_;b(L?v67|Q@x5ZcY`sL&pbc{Ztl^2?^6d?IzZjMVj9v=)mWGX4_k?xA z&EKJUa$s_DK(oD3w#Hp=*sX4PI)=xn4U?5gG2wJh;L_YtGBZvu+<0aMKEl{V;9(8~ zf+nk65xC`?N{nVawcMcyZB_VJZNpWwLC<{e0Z!>4Glg;mL0g1jSHN#m3pDCp%&b#4 z*&iJFciWpI0w=u1x45r^R+MFLu{|=f7JG(X=^yRPnW?g9xuQ3#4?9eewCjN^TCKEv zp}%ChK{}VGK;(K&el&&xOCc(2GpYT4#~8AosenIbul}cog&w8_vX>qs^>YkvK^zb{ z7a^4nq5m23?a#@p@J_gc$M&isCx{7Gk0-c~0{ICc@Zovj@a%H+V+Y3&4x!{?Jx>+d zMf{i%79Xd8&%51R(@g1cPQJ|wt>Xo!5?ELyex~Pjf{KwfNR%{Ub_G__ESLlk2~6VB zND@ccMU=K%6$|TTX-zCvRAjRe5^Ib#)KnEkiz>q*ThJEpxcK=(o6P4e<9uO7-aVP; z`-6#&stWdkxPGJVnEMTEj)kk!`7iapc(}S9?{ZhoMv!1UzmW0#BJz&R(Kb+Q9bi@B zKuy*dr6Tx%h|&5 z^VjIX^xQQ&LqRmv+SzhS+)@I#T*v<8H+2#f%B9DfZktws76wCDW3{o%kFE z)ct(IWs%0HDNz%s_|W8k|9$d975Wk^gQf+~!z}b)}QQ zj1Y1(+7@v~+gjPJvZNcf2g4AreGVSX%1UwZP%lgbgNn3D-TtlGS{f-v097PPyXd9F zgA}v^P?tpz2vAgchO}(xr(1e@{E-+69cDpnlcSL~*1>Jeks#$2SiFBXJ4UHK11mx` z!N9|lzyICdR|7$_n3c@F((ht86pfC9S{re{*ACcUl+YowiNXq96jI9Pa5^sFPnuo8 zQx@U&hBh2Zi6o?fpO9=zxsN?p8;5XEeQ*KnEG|||*}+wk5)8sbpL$<$gx1u4OWlt3 zGFiBa+aN+2wyLDSqbCtVntHu{q^A^bV+@hvX_xqlI_-yA^_N)?U~>I1wp^ZO9}M`QrvP(YyIWN(6I0TS`{mO?)?tUVIN924tT&?=_vL#t-8s`{>`PpO+mUyGP&&k@ zi^p0iDX5qo&Ojo2nRpEN{ZV(sAFV{;3CgE<*TI8YXTtUc@TAsx@F4F_^?^QZZhwNc z`J=4O5%fZ{%M?gik;kThEV6P`5QQNM*m7CI4-5lQ+=zh@3%3^t$n#QAOmT_xO1BB+Z*D!d+-lLFs=cLS`Td^#79 z0sSR@KaQ*!4lEEOIfkrLf5912lPQ%@IrHhU9Csd?BVXR7eb(}+tKXsfrf)m*9#va} z?wdM7kEq{y&L~5wPOGy(#BDqbTM3zY{*JRh|INJTVe46+r+4N*|BtgiFEr*o&kCRQ z`S0YO|2EwxG@kAGZ;Kb?!53aTD}1R+e;&4;!}GA!Xs^(S&!1bL35~fvBZKqQ;f=ae zgX7~Iq1>}~pW)fNAA4-pv&YZy?D3ag%6}H>&d^TA%>M!z{3iWb$_w47t zcBbdQ#e`X>9|W6iH`tf&r?FRLT(pIZY-toCS8wfpsa4vhQhK)D=dxFGU$8OF_}*8nLUJ*=j9fvkCfAdj$gSkv z@*sJH{4@DDd7ONPe3pEHe1$wmzD0;P+Lj8=c}f2d{O)j1kMaN7{(iOe z|6ZSkV~cWsU+K;Leg18}BNNjn)j$28#ykIu{D9d$o+tlKeo6j={EqyQ{Dr(u{+pa6 z(;$EXR&atBf=~+OfO=IeG(rl}&<%aC2$sSitcJBP0-InQcEWDB5H5zx;0m}Ju7{i8 zR(LnO=l?zYDgD25oK5|*zd!#gb@TuK`$fe|RawWNz+`wkhcaq!4d&ynoUh+ZmVe%33G4e_BBzc;A zj(mxHm3)JIn-K6v{i$Qtb9?@at;OI0~@SNp5rvwc^95Y=fcW_d3lt`|x5f1txX?;ZmM9K&jj0DKT z$!Mb9JgF+bZLrmVHD3Vkd{`W@9JzE-8SO(lotqtjwMT2q`(dkCJ@1+pkyhU?-JOrC zmFHBKL`lch*s0COxv-<#@-fe0Z<=64`CD$C`E9=5SBMp@g-0Yn}gMXXQNIca< z_s#SdsKksIp0)W1F|YMAZ9kwloe&~$n9uRCXC_YE`_}h0L69{oy#i!6Kc+B3v>fS* ztWm(N`QCdYISL3I`xEMGk4=1gg8hFC9B>~a@QI&ERct|OVii(yw{BONf8P;7X#_=b zBEup8R#vB_iZT7slT833YLVn63THYG!fBvk2Va|D!sFkLBXV2-p876B3}KTWBVIY! z5>SyIH4?qddln?l`AXn4;3lC16UUJNKb}D0$QrMY4G!B(qL~U2<{kWcmvLZj9pGcg zquTIiLk$p590xiNpri7c4y+(Rj$@l4Id%5`vBCR>Owq@dCQ~F%S$;N&;CAi^&j*YH zZ#HGQbn)j&n4FYRZ5oSVpBwfJKDGn^5&InLm>0Ie25zQiaaLgCE5{6svK%h?F~ZID znFt^;)FmQNN!VR5h2`}bVvY1bvzc1MXTyodek@c>EoOvPZ3fQyyvDHwLPemv&xAG7 z1K$yAW+1%%IHL+fTxjLvc!H0)JiMJq^W2yN0nTx};Y^IJ(8inI0u-%$#38S!Hua}S zf2>b$i-2QX+ee~;w)H2n+GN0>A|o>3*+@LTAmmrb#WvvJ(VL}PoNvb=#2d$|5?XS4_j$eHAy#_PPjhDu@Zioqv_j&jcaErzJV ze+U_c)nmG}!WW@=yruds&ec$k*}Yft6#P@!}_B* z$G$P~5qjh!6Z`oj%jryj+>JEI$!Y;m7>d9}i3oYJ#E{i9%~xx**3&QQjn`x=_L(8C z5!{SeC4{#gfr_)_bxx|HrmYKACY?~C&dBQ-JwW7w>9nW+^7Q}?(a`=8Dwj$+Og?7w z^px3)2+j<%^c0H{m=;Hz1sx5Y7_99p|IjvnqrPxc^acJyBV6JHpKxUq=#-i z{T?88W<f zAA&vDSdzCMy^~PXrU1xt04O+2OrOo6rTJhq9TcB)RF*2 zNZw2D3haz;K0o!Q{-21fFBmD`{`$1;!N2_a4B7qNw`{8s=y9Trv2VWxTThhX0gt}K z%KT`8=;e9+Z?U{yy|D)U?pwF@bR9R!-*IlXBAlsN{V&0zIa85Q{=09vJXWvSy2SIb zb&2%PQ!jG*y(L>2ss)=F2D+&X%k%nQe~aZs`j@E}a&q~6Y-QqcnlNl_cbsGS6p9&j z^GmGFd3GN0Jj!d;zg_mL7mpKTEO6Zl^;Og?wK-o;haw2vz9P)FhG;8Fgx7NXB?gaK zYxqjt7#j!=rJB|@RIUWz&Rzl--d=eC5u83yS{Q~ep(eyN6NGmjZB21dx~I!5yk7sG zv=c`F^3d_Oubl#=3G9lup`8fkZLvpoaXvHTguxr9gC#83Bq`K*rJsT1wIX%@{P$lx)6 z2EjPI^KGX=E#A(2+jhSE5s}eEB7rFB1L2%E2)p!F8{^%8&)copwJBPN^}PwhQhYA( zwf!TU65sy4O^!N({-43-)Yf4$g6Hp=o-#Y zmxBJZV-(g|^pUV35|KfYcN=qfVI_PPH-x_fD>8VdWumYSZU2eL1dm2hS(^!DJv%V2 zk_EY-j#QhWNg|<)UT)!x`S$ar&hc+MU+QqrQ^w5CoNuFiDS&-mvgO=S=3wz8HMCO? z+;_Iz=eXCaJNLcv&_htiUhT%7;UI{Vh5304Fn)da-B8C~XiU;zoS0q%TZPNc#gBTH z#ST6N-#GaT_!h!AKD~?SujA(qLpS}v*WiPvWO$I|`RCYkYvx<{3GPv%1y3We#uth5 zQ+Mcxl=Ac7z|82q_MVAobl}3SiGd65TQ|{t(K7YsJR3|7o^gtAlxUeefy}^5B-jx? zbZtU-U3-^Cqq{z^c4A=JMcotY?z;ft<@w*(QAgKXNOPxD1<;SF+KJ7_56cN{Jcu!C zExJqjqD%L7O|1REE@(#-nQi(WhV3lBB0FE37`Bd41kT{H4{LzfEHZ|Gvx_nh0hi!# z0|7<`x_siEwG&+z4n(1yA&Za^Z(Y_+Z(y)5AQIZAB}z{lvbqgY{+=vt%05;l{J!d3 z%SlmS20XeiJM}|W_AyrSRMD)mPP8vOZB~mS>M>9A&Rh9BTA&`Roxx!-r~Cl^sL+!I zyZUsYK2-+1s^l|;_QAjTys5;^P|!F?~HylXoBL; zo~xfuK75Ve&Iljv9)^7izI%@N>-z@Ke%5^h1OIc~m&k{&*&NRZ-@spoubd^HzM-hM z>9uK#LDXPd^7ld%jHzzuuUgHs4I#XKRw`#XBBT%xpac*Pf#Akrp#p5IbFtOha)yDN z!Q=I_;Stph0xg=^gMMjhktRd!Eat%m`Z8%HOUPYM7lR<>f@!xA5G^8Dj^IAOD3~XS z2&nK|C=l5~CW$1OwqpQZ7S>pnd4S^u3T758EJp|xF>EiPvW3o5aFlg7S=8U%$xul} zk_k_;((SjI!&*wN!syz;RJtt}FG|SI>d2#i%?c&OPmuq9zqoj**=k!*-O(j_ZNvT5 z&4L}oWlP4caJ7r0YX)osms~Hk2R?e;1dUWyH!5DbxVq6qU%p^dhy{yGhofB`*6`t> z)zR>PRAI|3I=DyuM6h_(=-}0ROQNvu*8A1n7EeWaedA$^yT7HCP!eHhhx-_9t4SOA zT*l!7NvN-@5;4UY9n!LP)(}CIMBxAtMGP1~dwI4?vK@es&Xp#RW&PgB0#mD%kdB;7 zkxcbGPmhz_!#uoaA7G*vUrh}mHElJm4CCsUuOaF&n=#!)Fq+JxeLBf*av_DHI-UK# zU@%SDZ@GvvwC|2hJ6r0uH7{E&c+HF2;_sWgJ7}Qrab_Q?V^u|EhWqmd;t&YQ< zZ+&>Av1M_u+jDK(a;IfcTY5v&@_v_Fwnvkl4NcX5KBE4jzUqHj7GLX-Dk?R;9cO&o z&tt2(_`FRBw}e5*N&zTcKvyy5Pr4+;-(Z@Q5XGPuAgD-!7nO)^ELJ9odo@^MgrT42p>k5m7Qpn9$s$NG9bvqF}I->$utt*AcFU zUq`4JXFfIqNy2s_2))uOAS(wKX4+b-SjNnXGP5iSq!$)gSWMI)!!3oAVGE;UlE?PO zI5W8z-$>&qPVtpI#BEUbVAcZivm0+9m!yuBH6n+LqI1D^SLeojd?$St-NX zQ)M>?d34G4T;L=lJP~%)?2vT{{>-lAUs#bB_*xH8|Q3;krN^cZR0d{G{L-69PzDSWCvV-@=NFBzR9#TM05?}$%3yx7s zBqp=S(;>)`S=Pd9VVqIaLItuWnINRABi*K@31g`+Q_)CC5ht2WCmPAo$_P6ZEFek} zi6x_yi7JexF(f;V2l#iLKo{r)dw7OQW7pdsXlk#H)@0)Cfu8hz#ld!WdpJs8&QT^u zsaNyJvuDGJ`eb#F;{(Tz!PaGg{jmz%j)Ma{e!D`#=m%CBpg`@Q0EU*31$1b`e9;1c zLSZ-FQuJq|%4(Cz6gGwZ?tq8;m*5t-9utzOgv?6}Bed|C0E!Y#qFDTLPxFKcMAO8E z&a7K|Epo2LEdQ=jS4qIfk3q<}-pJ1#fMMYDzQB$E>k?`m zU)00j+j?ta^$V(_@U^~nkEK7Wy{9tG(dtY~CB|xh4t@mR6ikIW7mLLTC}h3a8*XIJ zqzNUL!H?)>!F0B@p1A}`n8Md{tZ+&Pz#O;r7(QQP`FoxadQV%Ygms3-?i^!@e+Z$* zv*#KYniUri#KEziu{+s|k^7oc>);x!_Yli%)XiY=b@Um-ej72r5g#KG7sG4k(J+P5IIrEAF`wXJYZ)>tlB)&S*Y zkyqJ7$LmEi2w;^51`dwb$QG-00DfE~B*ATS6tj!V4s{I)#qmmGmwr)y%A#L( zSKSz>a9mLZ&rT)an_aiux>Q{TJH7rBCZ{{-J|QYj2lAF{`tR^6qen5R#Q0t1Au7p8 zd^)5rcbG<~fHpl!tboME1_%N-GN9f9!kUtjlFE`uFj?t|x=h?>(;YBoFE7XMDY|wQlfOL|EoEzZ^%u)LP{e+K-Re|nVnOr3`u;;JUs-vm zKXYi+^NG@*|GYGTzNAcF-beqH*hwep&U9cij%seIGDz+j{B-*$1E9QBr$ZX5@}_M9|x}k2rZIs%4oaXyv1#bi@P_`m`I0i=s(% zg-dka_B9n1DAOzIE9#PQSGg-(6yTEG%$ggRbHJ^avX&w1X)V<{3aNoX)qeWE4GjH_ z{Jnc;XXnmt?LDYB+``(zu+`qjyLa{U?CRFu2cpGKVT;)tp|jf3bk?~j4`cc47|(~} z{J3fJ!yD5lVJF>9>;-25kuwBVu{et}jNX=5Z~l$xP2<5A$?S57DBn`+w|lHMK0x-0gB<)+Yi)nSPUAKu1V131qx(WhQzQ z9Evxf5u{xk0cot0N1RK`8eUAsH8&<}BaO9nSM{&V1QU%{^z|NWxaqRqzQc{lK;NqV zt7_{SBXtS(SObqwc*(RCc1-^S6yZD5SDyM5F+WM@v!_1AquOJwU!G3U*!0sR^uI5z zeTbB@xb_|+uDz(mwVx-f{mo&g#c2;)Ed3Vy!s>9?!9F`c z2~H^lpd5`Nslr06$udQwh-k8ig{5?h$l`^XMMSfQBqKH@Tq`LN!_d((uXQ9n+d6WZ z;M)IXJM|-G^QdMvkG&T&>xhY4M>?5xWKDl{i(mr~mJTuVNHsH$yhtO_>ITKjZ6l^) z&FCTCdjE>G#X-$FlD6fnBYt;h6|;_<3Kp;42*+|p5l^JNrIqKz{T-7X5k}iMSxq*P z-Q=~5r@=%`Furx|@X+#sN|V);vyZgPz^F>$fC6Y#mVl7*mBeHcwmU3lyC?}l=}MQ) zDOjy}-v~KdNm?&$I`S5aXPW0N$@G?)QX(s57eui_MEgng=FQn`B08JjR)=y75LWGORST*SNLJZ>mvi&SJ^ork?DKHD|V6M?U#U#v20XjX`obxq;k9 z?uDvMU|oYru)}-rIC}GyhYwu5Z&{_)WzX?Qzg5OX8)FiiLb0k8e&oC%WjfCUWZYq*`Nc(6+-LSmISyKI`|UU0c<9j3 z5OUG&_uhWbjkn!+?9dH|jtpHsbnwzk_FuGn*Y<6j#}b2y6-x(Zb5-$qbJg3=dxiHW zPo0$y&!0D%ACI_s#4I`!TReV-r`|4nQwir5EI#)WUjivg3ELWD*TXZ>HuiOO;K~3hH zus_p?e}4`rjSoUh+I0yec(-`I>|UW~ZZ>M>CM!Pb?u(vr{>c7`q$VzLu-gj0__ox} z)?q}iWv&<*vBtT`i&-scu0%sEV`*@g_VyPn%h49!L?=XXO;n?*Jd}f6FS7>lriX4u zcs59ee=gm)a`52f>}f#DH_HaisqrTqBeHZ;{u(&+X_fXYG_M>7y_CXi_{DS#mB#tl zNy(U$lz90Zx<|PGZSeSv-QY@Zj0{xNYXX8712k)aK;{<;I>wbo0_bWMl(R&{LaH+* zLacG@m=q_oAs|g3#}g??RSR;dus$689;B&rc^W%5nRMj;XZhigL7Z~ddur4?ka#q^Mm$DIy=Q`z54dK zkNz#3{A;nd>?KFa-;(cAtBS+2;PtUo+#I{6-OgEFJz5p4(0sD!f#1 zYgl9UgUokO1MJeh%?GIuMYMx#1)X`;Q24!HV>9i)?O)^J9v+{aNZ2T3#DlC1hQ5b2 z3N!`=A@(+%Me9&*0-Sf-XE6yox6EXN(w>n#liW2EB#5JD&C;MaY{(P~m?k+&HhLEJ zG{j+TeY~u9Bbp7l>0NUKD<2gGM@i>H98aM85m{}vz*^S?w~||V3-8j=DG8Bgp^0;w zdir9;doE5mzdh*PBiy`RNU)U@R zc5#lwm-g$DZpaN50_(h!>1cO&GU}7W3uP=PC9{<0@LJYh346N47muIDZznG=r_gO2 z|9Z%wqF-;)JaW5oaoMEo_bbyQ8uSH9?d0LjN15Qrh&^(KO9$F20U@XypNWwh4|NC% zdP-|y0eAoUXUox(07i(>5`vw$L4Q!~9=yKQ?(p7;piI?A&(oqvz7>gLo~1_0{%qNP z9mXZZ`&dq->TtH{-LSLTiJn7}cumuPgxU0mgY7MA*c4T)Vtp2sj-Qpk*s-}07M$q` zD}=3zIt*Jjqz`s#Hz5wvh{!hRS>Sky%gkl(q?}7QwAbZAh2=t0+O(*llaS2|p&D?{ z4{6zTL@}j34~COfq{B`{Z?7(@;!s0Eisvqij=_aFNUi==G_)F#HCuTBD_bjiX3Jy2 zB!?-xnmf)f7nI4-?J-AIaEX!2Ztnn2aMNk-TR2c-ye(MHHmoF>ifZAz&ajbZri5B;1m2EcW0^m=t6nqM_Ni+t-)t;oS~ljmZ8zg9 zkT7-$e6T0R2q9&X_#v z4K*b(G|W;_ZRY+^>Bkzl<$fNvR(t1m;`#LzirsCuDGfMqr53C~wpOsGY}{aLXBsc$ zw_auJS5P9VI6@QF0^RpH0x#6bhg}yMZ0JkONtTYp(c2drg*7@YjILAi9T)Rtx%hDB zBi&)@9FZc*RaMv#mIN&Oar;4vqPcnPL5+nrerZ@VFF7otw3Yf<@l_KR1@R1P)L_rE z+!N<@5OrDeU@t%ZZ%2T{6vk@aKtNbDQ!(M9u`g*hGLR6p_i7!XB5mAR_uf54)XM*O ze;AVXUOBIJHl9bL&k|6IZ3(xT?^=l5|*?aks)@n$42U(0axA!IjdvPO-OH2|`_jjg?5n3T&+;}5=`w(ARbq-4842j=)vu3)1?l2n5IQuKSLb_No-YkXT}G8 z?q#3kW%3nst*SUxg}?ulyR|7#NOzl~X_0+% zCs-)4x-s&AF`B!){j(>wGl_=BuOHu?VOz`jv5QgKF6dJEIl#&26q)&s6q4CCJKg)p zt^*LDXVDrm>NUl5&;QFcI-lL2m?Vc0sa5%wt^Y@KWe3RmCGs0b>_P##WA5pN@LzR< zgwB#lF?WaK0jN|!4^zdI#F_?#_3;JK=W%tL>wOdA_5r`xK%3v*CBaau#utCzP>u>{Z>JO!s3{mA`;nR&lkV{Q{9fw?OZKE> zWRNI1!|A#4Q;fny6)YJ(;(WNfgoBk6ck`^*J(w0#AoETm+0R<;Q0pc3n`Mn9IEw2jd+YsB2OUezE^Hn z)Mj@3u(j=?Rmd>LDdAS>#8HhrP4jbU2PZGHAWg~U;3mgNqH`GobjyOsoYIr?2+h(0 zh!EYhB|EPE{Y;u(*5!D9zGL@a+#@U>1vt-~dYQ{kz(s$KaxE8RxGSYN5$nF1|C44Gv!ty7Q>t zX~yECl_sBwEyj1&MesJ)al|jlGkA2e&B4^+Zm^`t{ zGOPMNK#prUS`^zxK&M8z1!@tsN6CiiOTq5n=BiH_0ll=3H;MYWsMH1NEro?#GB8QY zc)72$v`BLwKeErv>7MlQ2;g8iP1CP#87)#=Wg-ZvU%4`!kFXRhOL5F-?T+x_S0O9cml9M5nX62TO3YIc31^gY-S9)J> zInGN(Oex)#Xg&Hob#P6qwC4?)NlG*!AK&})YHD8e8D7{+YKj(iU5_U5d4!b+PlZ4- z8;wjX$|DAG^|EmROpuv|Y<+PW9FzjzYnD?|Fff-bnhq0J+aY^n2nLdwXRw*Qbg z$65%c3>$ig8pzt>VN0mXx(Xfn;wU4wqqNH=$*OI-r@gc`LL2{wz*ED`o$%D%2;HBS z>=kttzF(%MVNiA-A;ommXHi2nBOJ)g@-beO+EMY+bV;GDtliys*ss?16_g-T*Bs`) zfx5@G5%dLh%s88{)BF0yOzV@C>PZpxb$^Nc^SEPNMKRNGb@70j?-|`4vgUq0YsD3n z(?qJsiY5`G((=fQDesR~o2QGF;XWi}gZr^3&7_J1qf#9bq57F!M%pF#G zTP>g9?>Qi3z&btU;Ebs_p8Q>DH*!IuhovGOf`rMBr1jW`6XO9%pi+E!O@w0ZHeP`p zT$O`ErMsAw;g}qA=0VUNYgPD3+C%kvvHEN2yJIP0D)d{4Q-`@YD&?Y- z$HWR`&$6Y*--vj*|5|`UHk?LL-oCa8$(X-B3_cLP(56}bxXS~qO?ulqRBU@Mybn>& z01ni)+K0qRmRDq^m%%=bTbNKM1nX46$NN*zld&n|W-);^LwnlUZ~Tfr;JG;TnmOgiBo z+&Ye+i3{)AVLh8;x2P0<=ZKvu5Sj%qMCuB;>XQ{#qns z&Gg_jCQmgaZ%<7&2g-EpLdEf!vn~R__ueg0)JMLi@%5M49e~aCm%p-VR_t%3B zrPk)Gef?#~j__RlhbEg>MpJ+0-J<1{!@M=X07vBw4!bs#nAPptne%1f^GVOmu(RXv zd1skC^YGLt)exb7ZTU~O59-%F4=*e3g6Z}pST*NDX}jt3XVr%AgRyaD%0*e}0b(C^ zB+8L=Fke|pHy8Mk%m@wbrlpV6y$h4W@R_oRQ+HTmxsI;IR)Cv@mS2t2lY5=MP*_Qx z<#`3QdxXKcp%5K%QXiatbXg7C_4m_Y&6|CSI`{WQRL@%IEwt8-u;<|}L*$t;b7Fky zqr@R1VC`N?I&c4ga;uUc*$z3sMuB8n7e#gtXX*{xB%2g?dcd51AKPMPi|Q!ZEP^G7 zXXp)aR_b=I(kT{oJpItWXt0h$`qzOfg`Dmu<--aM9k0?*4C~Omo&)vyAxmdv@i4>H zOYj{OLS)}B%JE*7XcJ}q17Pr$wYrl>qxDW1GiDAnyS%5dnUuepxDll6-v~#Gr21wl z-9|iisv_AicCB!9Pex3g4T1D(1ywGWg@KndsS)T$L!DinYlZ(F@5Z}N*ouD6l}bC+vFH-y4;|eC0m3~|K?&m*IH$!7`Kq^ z>RZVlzHJauAY#gq9wFc&s1@Z(J#YqF-Gd!lDA*PY^@VO1CtN%-hs7|P9q;Ivaw#!X zi19F}A2JMwSQiX_j`P)s#U_0=<#l_A`;OLf_(YxFVG4_TC6yY4SO}8EFS2pSp*~Jx`uD$ovWyk?tDMjjl1;RN1|49=9*qEkPzcxvilfD zQK-?QdJNC0bs2cpCE(s%un$vYfU<>(udESx38gjQ{rw_$!_2{x8I)tZ2I0s9B|-^y zFq3lgs`T>-264Ls>e@Qz1@H(^F)PlIX$F+Kkl%fR10I8*B%VgEq|pOT|LnoPHk9c2 zRDrTh&1>g_XQ{Z6faZ11#>luyXPSie9U1OmTPhRuJNl2Y8|zfn8)Rl2luQxToTW9B zTCEDWM~$wQzYkmE!S9ccV=SUPpF#y^VrXkKl5pY2?R*f`86Xp;85V3o<;abd5oT*M^`sKqxzm^@=+hs8Aj}{?w^b zp4Z#K@V+pe;Cwq=qh$S|$9Y@OOquiP*aiBu?XuKfSz1N5MS1g#n|Cd)qfmC;M3R{pngh~#x6;WEbKL=J&5=UBceR>Bf zy0>9_+n1g@ffMmRA|@6ZA`UZmR?yT`9zVJ8Ca1?#56!70+Mw6)Pv^y}rKfGQ)YUWQlQC&8Dyt?zh)_&S zQn$nKUQg4MBr-1X=b_4)2N}#}e<<`ZFW|#=>#|haSX#XlK}0o?5S)nbj;v)hFX%P zZg;SwUz9){B2^2ZD*P4&;(XgWh>E`54&-;(NsD){*`JChl=qfj7VFNA?#0iEDi?962jG)3Obitpr?!va*VEub#_Rai zQkk}8M^L9Ah--3U!c~AwYuY$GK0#i5=pH$^Xn~+G5Lq9*w&t>!t3AkqdI8y|=w1W= zwVHoSv@s=4vjT37BiW=1D#54`$iXk?2;sG3U6oT2*9yYpYi>T=eXf36e~TMlBFW<` zF8DazdlIw7#*kvOQk5*(c@rjuSQE>99%dj0|~YIY?k%IFyi_idWpO@Y#+a&H|E!4eIwVF z#E$rB?DJfZl#~Rs6C;db(omnIWGfI0; zo|KW5o|(<;SFp&WADNh%k=w*Qtu2DOAs#e}h<0Dh5o=o;!G%ms686i=<0-X$GiqXK)NAw@XZ##x7R&oz$un+3<&UoZA!nGW*^dLcI>hro+wV( z83xASEv1a9&h^^M)oRm&F2KQ2 zmF0ng)PdVC{ghI1;S*?4K4{im_NucEG=xQ#tJTWm-t4T~l9I*=pUl(zl z!Zo>~sg~2iWw!;UOb&Ip`l4(H16)tVxa5tjvU+R@SHj5lh{Z_nP&y+1!0V9y>)10J$Uv*67IPuH6rLa+3X2+0Xx01RzTltb!@gX{t zUR8&X^nv!4NS@~i3;JE?Hwk4j#W$7_T+G0u-EGgss(a0^x0|_#QqrxAU<+J>E6Fz55GwQ9)@W>)REXZ@%Cbrq2ttTc&sy>wtsgbj~0UfV6UQXIh;k%m2#Y zW^r8hUcx=``q&5=aYWuET*`nKoFH-d^2q?=SwA*f@9WSGv?8)kUNleua#YvSPHas>vG+H62rn%rq>)h<(FIAl-?;w&;6H>D5gQTYE z6aPUfM(-x2$(R;X{zZOhvX%XGf6ym2~PPd#Vg0|wlQc8P9-qQz$>`bV`dxg&YA;JAU)T^c|{q-mUnJb`rh zAJJndkmaJZ)#N1VZT)H<*ygTdTV@KP8i1Rk;5-@LWpny~zdl_Mu(<-Qb387mkn@Zo z1hSAgMWDWo+#S&!f=%zqmKH2u3I*#pHQx&CK4g3Flkp{ohmtY;D?YVC8WEy7Nyk8L zAizbY=Y^BHS{7O@dstSc!NYhVd{USc{>dEw&JT)VRGs+Cj6xX;Jm-B+fwJWh28HAH zz4J0lxKA3>%cjHS>Y*X)<-^!LSIp+aZ3qtQv!8)W&rS50i%j>&asi8`&(xBNruUtY zhx5&Po7aY|v+Y~Iq&O6-I$AZ%%3wh^y$;4Z&Y1R^!a;dr1nod&yrhTm5SIkQmcP(= zN?E+A%>ps8xVg{_HJ+*5eroDGn3< zfI1c8gXFikG5+SGsE&>Wg~wMRoAZ*2e$}HOtET3pb_hEM{`T72MplaQ3QAh(%)xC0 z9!=-#evp0a6<)w;^OA~AJA>RHvmK(2m#LVDg-#gF12@fvM3|#6N3v#j0RyE>Yy0LN1F_Hx0Cde<;z2xeeS3H?~J7!opkm2JH-*i@8L+rvoZ?*o6V(` zZqf4E(CpkD!t|?U-rjTYV1Jy1!~3~>C$Elelu8M3{{7+z7Z;i^^6k+#+M==y0%K{c@FDmUSCZq4)E@+0L28B{!SF=|ag8WM8s{sX zkk9K!N>7T;6=_R@MQ{D*KX|ow_2XqN9CD*ceTK0@;P9z>RNeI`^*jWd85_YKiL=QI zDdGnVH+<0k21eKt^$;vd*P8Er*YkD(HB&mzcGmZf5{X-UMKaUZahQ(`1LlkZfJRgAE1BcOf zzz1XQ$f|fDpws5wrD6>nn5Ftt#gO0ZMK-6k{8mEqPtm-xF^v}&lT_+t)jAy(IGUvr z^w52a(}%6idOi2>ydH*;pwutxO9T7sL|5qTyIn7LU7=@&2-D)B?p`m8vo_eLLxcSW z!0c*Lv8Po7c!kjK1Hc2;?J30spA$u6Y`vZlsfant!{;rP5Lo0Ma*(StZsZopwWw7F zmG;W?ELaxF^`_Ua7^B$qp_)|ZnWB_UrgWDog(0M@GipleCzbXs+bm(@$lUzSyr}vG z3KJI-JhH=r%Z?>cjioAB{3id-#~hYTpoaNV_7cfW8XF~&hP!p3Oon3&B+M*jsJV&7 zsk+fCU>Dd(1Qo4Wn~(~MmU0hnS|!|xf(Voj2F$@(l`5eLb2CbomE;W(BBTsi!Aa=% z;Jqvg5>Qttd=xsac!mZogshV{%b&GeYLYD0jovid*431coiu5@P4T!irDDgkDP~t* zYKJrKGuPxmtvsN!-ANV&J?vqlBJ)Y)9URxa#yt>woe8VN^f>TeweAuQs7TTytzL{s zn+ns4zt1K=FYoTlONT%Os)4{E`!3ye#XVTYUb?gQ#?YBy>eJ^XNiP*23_{LJS;iJ5LAFpR7 zIKoD1CFAR8Oe12zh?wD}Q$`2jPoqd<{-^=EFo{%I0S{adw5v9=PKb=BF+(f0#h^T<=qoVeU+?z)fZu)oZilV1d^^ZT4_PA4 zQ9Imu%_oB6Q!L%_30W2Bo6d6FJ8p%hpZ#GLkiF-x+Y@iip;Lr?KV1)^lGM6$pJ9bO zIdnSXdKokE2@SW})XWL+VR0EuIF-hnhRHT*1HRz^9&Auicu-MD!+evm+0=(TlpGOn z$b96aV_W{JsyN&U=yMrW4|iH0n`ws+4JPs8B}-w&{J#n5x{BMQXrXQZ*GV5TqXsi+ z(y-C`_5m1oM56!z0B{8~&^6T6)z!CMbghf#%HBDq0OELn0>x{!a^-~L&)K|Jc-b*5 z#-$wQb-Lt*1_rSH3#0fy&v8H9AOQg>49aZ%KuGeW>d;Oa@cx-}0qjkI0Q`OT)H0AQ zkp%Y0-Sk@X6%+~DhSDE-BoC|(N+c-MPE z!~T6;8G&$V-l6wR^ZQ=#1A$5xo%tnhbmjXxu=PSx9zX0lGV{;_UKy|Wb&1&B$v=ms zRtYEDcq|d{cz?g>#IHz+$K}SQv$59}8pxdaae=XPk>($&y#GB4!!hQrD>QPuFuQR! z4;PO|9mGv_UO=pxWG|~np_J*|kSPos2#hD@e_;7YC%&!_n!AQWF^`^Xn zSiy@H^?HdN16}{KXPg&$*kZI#eMcpF|TDV2V>2Gj_m)Z5^ zjKXF5hH#{Y;EXP~O?^HOJGld(7J%{Ymq_*R#=P<0a8zb?=I7Cjx~hv>EZ~TI=g7x; z9*I+pQ0eP(rWm8Jqs=y})57dIuwXM;LTZg*e$k66@G^0zzJiEI(6DUT7qZ7H)Z@9` zQpOF9GQFu>_j^;ESiZNvG z9w}i(?xGXEkmd!$IBEJGVxwop6Mwqb=(-}^97mgj^j(om$hRW^%;a)%mI{?*5s6E$l=53F16Dwf4Ba%(v za+>AB7jdPmUHuHR-N`VENLX4@H{!BLqa|{~srjoOQyvMvD~v^`sRVo3RlQ&7LsVKD zZj-OKgjaIqxae70Qh$w{>Wpj}ym^<*=7{%Dz44n)H>ks%PkBi3WwrbuX1%2j{~I(n z1Upx#^M77mv?gH*`>NJWw{cu51Hm!0^d<;qz(a*Z4~24qdrp zOWvcB95`c*d)i6hq2odFqKo{t?+m-4%TO1&2b)J9cxu4i*`sU-Slel&o63P(`SP;D zVKj1`WlS&ooMM5R)G$Wsd;;@DqJ90(SVY+e1pk)~8K5`QU*PfHVx!s0LiRV8HbO#v_ijB|-i1B@ySl}RcRmS)-wOX?g}g)S+cfj*)VhQ9w+j^Mu_Y zxDzFp4{#*-8U>~g$;{=Z;+>eqbcEF6-I=9K%q~Vdb8=7NE}S{j zcu)HV2Imh2E5pM=_P3XX!sO#P1sTvqoD5K^g?a8HYXyzj{p-oFh@LQMNdG2DrZBb0 zP$kL2Kx(Yt1MUyT+tNl0ko#fM(Qfq_&bT9`T{-=q(*3^rY^B< zLz{k&osV^ujh6M6EtgfDjh)S%H6I>XMq79kp@up8MvN}Occ8RV+gsFL@vtvgYcT%rR zy41W$!DEIDf2+x6lb8B`YZaFQ&r}}?6=O_C?Di~eC7UCKeqy)-Qv)f4b)l$ZxNVqj z=x$h9*jcy|xB;pctIpg^H@8A>;htLE#5+klQ@AHIBN`(eBVZ#VBPLMzdgZmUsuY*V z(U53C9sLq}6orA6zIcBi4};=mQ84*6P9X&J2quG)YEfYO)mkBB_6R?RFzV16R0mCj~`vIA8jLa{GQ3L7ghsg23XoON&E!EYkh5fCWAXQ?PUn(f6vU%aMD20 z$qLhKy=((*{eOqI2EB$8ZZkWfI(0nLbtY?284+(m+Wam0arg^tqi#dMkwJuf0DxCP z5`q5tV)a7phO`E?hPVd02CEWi<8$Mg5#kef5VQ;BB4iM32$>UB#pUED3oXpG&7J78 z50V-{8fXu~hHAmDP+6;LT5eL;VvT|#z=Ndt9?fgZYqs;bi@J-v1DAt6`4;n8k^-iK z9SNx9s@MX#LRSWE-IBMWb_4$K3FE69BG`*A3o}a{CvqhS*o%9MdyD8P%7(jzJB4cs z741jv2k$4P`A3A>0vZhf())V(dJonao6Bp|sp(Db~#M z0m}~QRNyhI!LH~cxWl_6!6VQk?K3z#Iy=+LcnX6B9Rtl1seZs|&}NoQHk4?~wp;ehdCPnkeebWmDBDFTY2azb zT|=|uGP5(tGo7dw1M&`X=qKbiuUoKNn9Iycql(>$WR98+A0L7mG#!*3=sjn3 zs`m(uncr|KQ|?jR{H>5Y6XK3d99wpUy62KUG-g zmfd1id1!f%dCYlocnxaxV|8TBuOMpR%=OyxXmjsS6KXSP)B43_26+Z&#>)n-W?f~N zWx{1JZ2J9I)1lR>QNVeg(XC94)o)(vKVa8-famOTuF-1^?>D8H1VtGJ@ z`?~AGvH~vRLE_X8tukNIFOMc2tlLhsYF^XpMBfa@?4jL>xN_wj{y=&Gx4|P%L#hN- zym8zI+!5Tt+zHq@ZDRFc_hgpFr6!5~J0X%G>MFA@Qz*MR(>~)mYe@sbusC*amRNqn zl@^mb0r;(TpjW_H07C$808oHGfU$pU0ipl^{+z?20005}`PBi2iTQ=>;D_gSCVgyO zTwE?#wtyj4fHim#FsbLcWVr7E(bUA(I#4wTJZCS1edXYuu@@^pj zn(XqJnBbV1G(|d?E4`)+av~j^`wzYX{yJS`fZ+~{acCr!lQN4WXdTbNz%U!8JbFRx z+;#F}N9|_@lKwq-BVtS@D$}B%v-$d#JJ0-|(SRK95 zLZ5FIBH5LbR~k3dcQY`(bTh{(7`T=!p)^w%2mGY3uI*wp{KT}0&*jVGXCGbvI+bd; z+wR+6;R7Ysf>#g=QY85YV1q=TXqrM`R)1JV2#PF(2O#+&TL~EA5z#fg0brFMjNT%u z>?-V!<{ZftHsF^rI>G&S7Pjo)$5h;_YW?&OHlRVK*0bnury5ewyl>@ zM<1b`J+4vB`z@Q|HlB#?seY(rP4YP^mDuFy=Jpk3P<~iO-DZjxWIH+x-m+r0=K5Ed@FrZ!G)==$cV7 z42@eF8?)LIq#nWNKHP)$6QTPk$>Ot=Yw);rOpxEt_$My@L81B08xO4R7 zZYol@gL#RTb3$_nw3^3NL(a+JD93KD0Hyryq~5gJejH&mrv4PIhNZ$G67jfjq&(fQ zgf}{iUVJ&(!lJ8X@IT6j#Y(mZR7&-H>4AEbie=OJ{QxItOIqWEm1b;*O^AP4_Umaq zzFXx5yrcYFVS zv!zD>O*;xd5J@|ZHjHlKFIJpt9ISR6ibyE!Pee9vI2xb8CwCuCk%tZvE>2d)O^jhQ z&mo^qkCNsjfMO^YjOlcgSdvF6rQT?iBqif`N>9T9MLC{lfTAidW`v@4OhNH@c!;%g zv>&qhd5G5IL>|-mxkvN!S`+SBUSHmhSzb5Hj>T@MAoX{w1`Gt*Fv2Qmb*@c&O(}*e zXzhd-q3N`upn5$AdLckh5D*!lHic?p%6#Lq=~s}r2|0)I3xy|OKYlTRMQE$0Fo-f$+=Hd?sM`AKq_ZN~a7*D1%*!1NSPbgQaH&_o8Q*FfI zU^ri{H{hnlp{&3X*rBgQ?@!hxj7D*mOlNl3o{cwQwOns{+@6j#pw(=5e%zi-v?Sv8 z{QUhy0EQbz_-#bJ*YX=S8_iQ+FJ}J#|9f$JzJY;*0)+&J28n;|?~M$P4pESk5|tE} z7MU2E8l4=U9$}!PBBdm!CaEZ^Dy=N9F8^X@Wol{uK=_9={Z8BX`k!#DHG9OgPA@Ap zU$u+({ARskWUR?LnBb*0@~BdmxI%RbbGbhH>DnphgKL)$&TW+t=P7lBYfntZZJhxW z8k62KQ1AOT#fMT40c%whX`xJ?B1tmN5RiduLf)A+<_#F4AuEgW89U3dZsWo87;5Wr zRst7>k$xPVA@u@;#(iu;`>uSY^BTs+ePUz#uKK0(1_<|kbcFk^Y{v5%O6PrirTeZ* z&R|$7^)c(_YgdFPO~2f%I76>k%{arL+U;0FH%|yvL%+-@SwpW#X%Jm6d1+ZzVpIKM zv}qd@%c?#t$nym3%aSCD%90?&vc8m%pQ&TCaY#9wtk4(p-pYVk$EsyO`UmO%E^+rY zpY(O+?PjZw^h{Q#1mq;t_+-RX zgcSd3a!U&<^UI5?^U8{<3MyP2i)?gF4K4M}jji>}jI0bSOm22_@LYLAf9n-MnJW9Y ztnYqUv^FL(TyS3>k2Yd-eE#_J_Y>sn?<2;`&(qi2-$RCrkCT_1pJS%0ud}zizk>z~ z50exdAEPEKFEckgKf^{#Pg7T0U*lx|0QUjOgUJ527?y^D={cqPtM|3$i;T7A>NzuZ z;STXca)oOCBJw5k#d3ujz52M-Iu4g(!=KYm)`Hi%8}t z`V2}vy0sW8XS!gvT(7qpspk6le9YH}9gQ0MI}HuS=gS7CY4jOMLZK8?M65R~Y}F)chZN)qlFw4X>~=b$UL$(;WKI zs36n5T%_e;J~E0Mh!C+6ic&~4HizB$WE)gUwPuIi#dH@~Og5*--T71pTu!&=$K3^u zP`Ox>Sh>w>NjkS9!ATw|z|A)YtNQ&-Lm|r(GF+F7qSSB(1Ta=nu9rvn4Fbj@_t+*P z9Ct_vrO)Y6MdQ7R+>5$en{{KnjPkS)SJXW9MRQHbNl(^ii&pg`>A8A&oKn+k>38mm zzTxJi?k2YNLk)d|0eMN8<%r@c2bO?KcR5-ITz-qoNzYeH%gpoX!!xZZT)^{ivxb<5 z54CZ~all%hS{>^r`b6~E=_>Zue!1R1(~=Wu$pR;SipzvNq=9ty z8NjV)fA9DRw=$-(SWWjE>n5{75}W2UUJ)RO&}PaD&u->}2?_A}BBPe)MA65Mn`}BYxaq+F-ItJ&3s( ztEQb;kl{B2PwE)hGS8Yy{DVk6n<8eaX(LDq+z zNcv@2)QqUIsm!4#6Vw%~no6dJ9}ChN=kFWYv;GtKH zxwvqWb=owTg%%hjE8fsQ^rE_A!E_jVoWg%;MvVe*4QqMPInjH;NoWH=DtF^4|DSWb zcL_L9T7QU1T|kP^@9_Y@NZmgSs=bi;IUcmW2$H&>P^x^7G+gL?z}}Bt401cGaRai* zf`nEk(;;B=h}O7S6xeH16TeIyEqAb5(enu%d7Z>X7OCKtkizb*`1j&MZ%)Z)IN~P- zv9HcARGAc?6q6t(c7YI_07lD|0|FAWl?Qs%%GKLMX4M;3+x>p3t~`MlzV&!+{eFK8 z3T88ncfWtmW-v06=tVj6|GBeBr?tqKIIvADc;5&;QyQnhZZ(FogBKc#Fh45A=Xp*RwR!Wje2I<1paO{ZPPbjK@AC8dBB zDVW8B{bX~;`^_1aP1Aqisu*{d5KAg!0iBaKWJ{+<_(@-U73r&Vo4mY`zqyZfko1!b zX+n))wD87ef^iGZXRO|IhbI{UJr_bf7lu6-$~_kjR9Ez|Y(^N{AJuf=#+Ulkj~m^0 z&n}K-Cx?EfP}ES&EFYmw>cI2v#2o*DY|kK>JB&kgBim!^K~Y?8LcUEpcM5n7jYA*D zQR*S9KV__3z8?jN{Ry+Y^q9;`iQ>&uIlOK1u*99gZ$j8TxryYv=U@5H?D(UZoPrtZ zQj+(f-NL64TY^y%_YtFC66FE`p9y0aZ&py_Roh%)^(k@S3{8Fcf@cuhB&pt{5rxr(auSlsx(9+uc($E zRyFNceHO0GF^Hhm(d;X^8|lQGjNHvc-Q5scvLc^&zS&v%T|6;mlSHwL1W^7ULH6% zQXX^Xp~#+ZGriV%rll13tY{6Xs8=0}Cy3D~aEp7=Bg?oDebwz{DV;Y;54#t5qSsl3 z@~aWxk#CH|pJU`jgAPlE;cxNE2l_=bRlT)S6W9BZPV8S96>%D$-cV?GVG2M#Cnh4> zuqDPO8c*=viKd}E>BB)Fg*yWwHS&7I9yU~_@(eih!9Dr}x(wy>gKa~wf{FxOBF&%% zAfUsJr=QsU#`OU}_kl?B90+s>Gv4LYC;dY}&mU>RIf);3lF6eNy5zf);3l4(Ng&=z{?mf)N;lLvRF+LDcs~;24DN8=whVpba{p z3wodr24DzAUMu|fY_)cvo_Td`cNZILI_%}6=^!yUUrE?bjdK%dM+$uHh-I$OWWYi}4Nzg^gM z6LF|i!4K0*oI=|K-7-NddJd6a_wI^2)?={M+$y?X-r_eV7j_=F2T-N%sE!}I9=DH+T?|zcR{x#kO4&>+SLD#h0cQCfM z!8ttC6~cSDoSS0VZ($lIh*%lbX6)?VWc%-wfAm$J7w2~FnI*f3}9~WjhzeNha<56GtOgA z)aw7U@6-=Q+i*jM<-*oKrC18S#dzkLGJIhs_g|jGe|EZd)TiI)yC&fWMjsC;2$Z?6 z9w5-Ld5A#6Gya50DJR`S2MSitrD!-SB~t7)&oW4CnnU6NJ)lzKLrnW)C9)bhnjzh* z()I3mJs?IcP0%97255p7Xn+65uS1%TS_}=<5|7oe?G8L@l5A<}AZDv0FFLzDoX4mf zd(BVAR`Z+j397fPB)jYKg+31!({=2!H>1ATWxL%mw|;b&_ix5aG9v&00RRF2{{Rno z0b?KqL<3;}Ljcn)1_mZI28RDWOi%uQV>0;v?Y|F$1OzfY0m|KCQv3fKB#U69=)Hxc z`!7_#I}qA4*fU!HpTy|;zXQf+wqu;i?7`R#0LU&U-T(l20jyTncH2x29;&%ll@z9c znaID_94bzCFC5d_bk}ppt)wOAe)lTRz392R3y_j~`ODgpFoQC{_W>*@6rkAm zy#V0N4>7v^21~nt@$s37(?R$V;(Z@;_2_56=ohV)JTNT_MSw!fjgByc4qXQgg%Eyp zFsGy?EeG=o+Mn~4s&F-yHH4v?UoVhz4r-lSkgjAZ7ghk>f~}cItH!7I~Hp@ zqgBJb1GJQGr)-qTCQ)qphe4-iu&09sg?SsR+UI;&)4JXEk#68%Q2|v@s7HjUPjC6yCtd89E_HxHLI+DJ-NXd6lfDBN*vN3rtbG2(V(7K7 zIAf7fLkuzHN@k07VrbhBx6EiK@MT~HfNQ%x*-YZ4SBisu3J0{^5xK0*{j`;?1QgPZ zFn90~jTRMxeKQUYDBx;G306TI0H1(sVZbioMq2Hl>I{qu?YT47(clcJ(}OgeonqLM z^aMQwFP0IsyJQQK8-ifs+7V&YS{ZF*DMl^{$A=UpDC(l1QI!JvJTffu9%V7570l2O zkEtY=^ROLlI5@7z6#&QdYd(M$)FB+_-45->(|%1TTBW1_anPd7IH5y`L%<25&B00a zX3tLw?Tz3ejvUHQ4wluMZU4<~rZg?mms5R3C1O(V`^n^_Mk8`@!VVZxuI?sd{4-8J zXw)PSk}W@B`UtNZ$G~aFXDmr!y|tOyDTKbMCLknDs=rCv)6Kf1g^3VlNqlJ(D;>iy z(r#6iNJP%t^KnwT;NhrraYWL{xqubYgjB=#n>P(HAXioAS{z?y%(Ld?+IvFi_JbL(eCMg?d_eP(`cdd;&cT81l_!ZQK7`fFhWm3sc40f$K`ZK@G7?Bjjd?C4Kg~4T0#% z9!~`wwj~yI)FyL5M<%U9zU7^bi6oHsl-#5qOUkfGI7y^gLbxc2p0g5EI~ugbE{1yiWyTx=$0his!q&{6?E%tszfZ< zJy!lqyG7fQU0&qeX$oEu1=Z}b?+Cua%ME-%SNZEp^l#`mqf*9~w0^5_p2Rz5(IdKH zGnP@0t@nxt8voaGU1T*7L}3)}!et3e8AVorySoOr;I6^l7Zckc|E<^b?5jSv>cwS9 z97z;{pj#Lf92iR!TmZ%e2PSBGgh?7OMFXa3z)YeT1VM*1D><)JqUh|}oMhML=^R?1 z^ID|yTB7q>W@eYL!c4HrOt8jGuujt}Y|wx-4cMdsTg(eOrETVU?J&=4SF&q+bPny) zc^%Ms9nyIn=`n7Mp1@pQwK~&xZP=U}X)b)@!sb$&o1#;%SlNz@ zksa4Y@*ABK2De6nJ0rop+UDrI2UeCp8p)rGj}1}{c}S0llj+Lq|NcUG2v7|B14 z8Q7h+F)%n9DzY+YfjAC4ek^V*W*ll966~y8 zP@y0uFD5%SJvMn(un>>aKH&p`2Y3%~9$<4|U}fM2iU~UHV{m{%h}cdBW(EeAjVg>C zfe{-VIwC;)6qk(}ApQ;x2A}{~L8SCXb&$|5js^xs7Ke`H5SRoAIPe58c`#Y9X|PGL mvhr!|VEo^@fu(mN6NAfU))Y1d7Z(6az%lUv000310002hVU5cG literal 0 HcmV?d00001 From c7c9b0451f9b0858d800fcb178d2f457564de986 Mon Sep 17 00:00:00 2001 From: Ines Montani Date: Sat, 22 Aug 2020 13:52:52 +0200 Subject: [PATCH 25/33] Update docs [ci skip] --- website/docs/api/architectures.md | 28 ++++++-- website/docs/usage/layers-architectures.md | 2 +- website/docs/usage/training.md | 82 ++-------------------- website/src/styles/layout.sass | 5 +- 4 files changed, 29 insertions(+), 88 deletions(-) diff --git a/website/docs/api/architectures.md b/website/docs/api/architectures.md index fd88434f1..3089fa1b3 100644 --- a/website/docs/api/architectures.md +++ b/website/docs/api/architectures.md @@ -11,9 +11,17 @@ menu: - ['Entity Linking', 'entitylinker'] --- -TODO: intro and how architectures work, link to -[`registry`](/api/top-level#registry), -[custom functions](/usage/training#custom-functions) usage etc. +A **model architecture** is a function that wires up a +[`Model`](https://thinc.ai/docs/api-model) instance, which you can then use in a +pipeline component or as a layer of a larger network. This page documents +spaCy's built-in architectures that are used for different NLP tasks. All +trainable [built-in components](/api#architecture-pipeline) expect a `model` +argument defined in the config and document their the default architecture. +Custom architectures can be registered using the +[`@spacy.registry.architectures`](/api/top-level#regsitry) decorator and used as +part of the [training config](/usage/training#custom-functions). Also see the +usage documentation on +[layers and model architectures](/usage/layers-architectures). ## Tok2Vec architectures {#tok2vec-arch source="spacy/ml/models/tok2vec.py"} @@ -284,8 +292,18 @@ on [static vectors](/usage/embeddings-transformers#static-vectors) for details. The following architectures are provided by the package [`spacy-transformers`](https://github.com/explosion/spacy-transformers). See the -[usage documentation](/usage/embeddings-transformers) for how to integrate the -architectures into your training config. +[usage documentation](/usage/embeddings-transformers#transformers) for how to +integrate the architectures into your training config. + + + +Note that in order to use these architectures in your config, you need to +install the +[`spacy-transformers`](https://github.com/explosion/spacy-transformers). See the +[installation docs](/usage/embeddings-transformers#transformers-installation) +for details and system requirements. + + ### spacy-transformers.TransformerModel.v1 {#TransformerModel} diff --git a/website/docs/usage/layers-architectures.md b/website/docs/usage/layers-architectures.md index 1ee0f4fae..eebcc4681 100644 --- a/website/docs/usage/layers-architectures.md +++ b/website/docs/usage/layers-architectures.md @@ -9,7 +9,7 @@ menu: next: /usage/projects --- -​ A **model architecture** is a function that wires up a +​A **model architecture** is a function that wires up a [Thinc `Model`](https://thinc.ai/docs/api-model) instance, which you can then use in a component or as a layer of a larger network. You can use Thinc as a thin wrapper around frameworks such as PyTorch, TensorFlow or MXNet, or you can diff --git a/website/docs/usage/training.md b/website/docs/usage/training.md index c04d3ca77..59766bada 100644 --- a/website/docs/usage/training.md +++ b/website/docs/usage/training.md @@ -6,8 +6,7 @@ menu: - ['Quickstart', 'quickstart'] - ['Config System', 'config'] - ['Custom Functions', 'custom-functions'] - - ['Transfer Learning', 'transfer-learning'] - - ['Parallel Training', 'parallel-training'] + # - ['Parallel Training', 'parallel-training'] - ['Internal API', 'api'] --- @@ -92,16 +91,6 @@ spaCy's binary `.spacy` format. You can either include the data paths in the $ python -m spacy train config.cfg --output ./output --paths.train ./train.spacy --paths.dev ./dev.spacy ``` - - ## Training config {#config} Training config files include all **settings and hyperparameters** for training @@ -400,13 +389,11 @@ recipe once the dish has already been prepared. You have to make a new one. spaCy includes a variety of built-in [architectures](/api/architectures) for different tasks. For example: - - | Architecture | Description | | ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [HashEmbedCNN](/api/architectures#HashEmbedCNN) | Build spaCy’s "standard" embedding layer, which uses hash embedding with subword features and a CNN with layer-normalized maxout. ~~Model[List[Doc], List[Floats2d]]~~ | | [TransitionBasedParser](/api/architectures#TransitionBasedParser) | Build a [transition-based parser](https://explosion.ai/blog/parsing-english-in-python) model used in the default [`EntityRecognizer`](/api/entityrecognizer) and [`DependencyParser`](/api/dependencyparser). ~~Model[List[Docs], List[List[Floats2d]]]~~ | -| [TextCatEnsemble](/api/architectures#TextCatEnsemble) | Stacked ensemble of a bag-of-words model and a neural network model with an internal CNN embedding layer. Used in the default [`TextCategorizer`](/api/textcategorizer). ~~Model~~ | +| [TextCatEnsemble](/api/architectures#TextCatEnsemble) | Stacked ensemble of a bag-of-words model and a neural network model with an internal CNN embedding layer. Used in the default [`TextCategorizer`](/api/textcategorizer). ~~Model[List[Doc], Floats2d]~~ | @@ -755,71 +742,10 @@ def filter_batch(size: int) -> Callable[[Iterable[Example]], Iterator[List[Examp return create_filtered_batches ``` - - ### Defining custom architectures {#custom-architectures} -## Transfer learning {#transfer-learning} - - - -### Using transformer models like BERT {#transformers} - -spaCy v3.0 lets you use almost any statistical model to power your pipeline. You -can use models implemented in a variety of frameworks. A transformer model is -just a statistical model, so the -[`spacy-transformers`](https://github.com/explosion/spacy-transformers) package -actually has very little work to do: it just has to provide a few functions that -do the required plumbing. It also provides a pipeline component, -[`Transformer`](/api/transformer), that lets you do multi-task learning and lets -you save the transformer outputs for later use. - - - -For more details on how to integrate transformer models into your training -config and customize the implementations, see the usage guide on -[training transformers](/usage/embeddings-transformers#transformers-training). - -### Pretraining with spaCy {#pretraining} - - - -## Parallel Training with Ray {#parallel-training} - - - ## Internal training API {#api} @@ -880,8 +806,8 @@ example = Example.from_dict(predicted, {"tags": tags}) Here's another example that shows how to define gold-standard named entities. The letters added before the labels refer to the tags of the [BILUO scheme](/usage/linguistic-features#updating-biluo) – `O` is a token -outside an entity, `U` a single entity unit, `B` the beginning of an entity, -`I` a token inside an entity and `L` the last token of an entity. +outside an entity, `U` a single entity unit, `B` the beginning of an entity, `I` +a token inside an entity and `L` the last token of an entity. ```python doc = Doc(nlp.vocab, words=["Facebook", "released", "React", "in", "2014"]) diff --git a/website/src/styles/layout.sass b/website/src/styles/layout.sass index b71eccd80..775523190 100644 --- a/website/src/styles/layout.sass +++ b/website/src/styles/layout.sass @@ -363,7 +363,7 @@ body [id]:target color: var(--color-red-medium) background: var(--color-red-transparent) - &.italic, &.comment + &.italic font-style: italic @@ -384,11 +384,9 @@ body [id]:target // Settings for ini syntax (config files) [class*="language-ini"] color: var(--syntax-comment) - font-style: italic !important .token color: var(--color-subtle) - font-style: normal !important .gatsby-highlight-code-line @@ -426,7 +424,6 @@ body [id]:target .cm-comment color: var(--syntax-comment) - font-style: italic .cm-keyword color: var(--syntax-keyword) From d97695d09d7cce01df5171fc4e6e55ff39cf79f0 Mon Sep 17 00:00:00 2001 From: Matthew Honnibal Date: Sat, 22 Aug 2020 15:41:35 +0200 Subject: [PATCH 26/33] Update embeddings-transformers.md --- website/docs/usage/embeddings-transformers.md | 55 ++++++++++++++++--- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/website/docs/usage/embeddings-transformers.md b/website/docs/usage/embeddings-transformers.md index 33385ff51..04b79007c 100644 --- a/website/docs/usage/embeddings-transformers.md +++ b/website/docs/usage/embeddings-transformers.md @@ -9,11 +9,24 @@ menu: next: /usage/training --- - +spaCy supports a number of transfer and multi-task learning workflows that can +often help improve your pipeline's efficiency or accuracy. Transfer learning +refers to techniques such as word vector tables and language model pretraining. +These techniques can be used to import knowledge from raw text into your +pipeline, so that your models are able to generalize better from your +annotated examples. -If you're looking for details on using word vectors and semantic similarity, -check out the -[linguistic features docs](/usage/linguistic-features#vectors-similarity). +You can convert word vectors from popular tools like FastText and Gensim, or +you can load in any pretrained transformer model if you install our +`spacy-transformers` integration. You can also do your own language model pretraining +via the `spacy pretrain` command. You can even share your transformer or other +contextual embedding model across multiple components, which can make long +pipelines several times more efficient. + +In order to use transfer learning, you'll need to have at least a few annotated +examples for all of the classes you're trying to predict. If you don't, you +could try using a "one-shot learning" approach using +[vectors and similarity](/usage/linguistic-features#vectors-similarity). @@ -57,19 +70,47 @@ of performance. ## Shared embedding layers {#embedding-layers} - +You can share a single token-to-vector embedding model between multiple +components using the `Tok2Vec` component. Other components in +your pipeline can "connect" to the `Tok2Vec` component by including a _listener layer_ +within their model. At the beginning of training, the `Tok2Vec` component will +grab a reference to the relevant listener layers in the rest of your pipeline. +Then, when the `Tok2Vec` component processes a batch of documents, it will pass +forward its predictions to the listeners, allowing the listeners to reuse the +predictions when they are eventually called. A similar mechanism is used to +pass gradients from the listeners back to the `Tok2Vec` model. The +`Transformer` component and `TransformerListener` layer do the same thing for +transformer models, making it easy to share a single transformer model across +your whole pipeline. + +Training a single transformer or other embedding layer for use with multiple +components is termed _multi-task learning_. Multi-task learning is sometimes +less consistent, and the results are generally harder to reason about (as there's +more going on). You'll usually want to compare your accuracy against a single-task +approach to understand whether the weight-sharing is impacting your accuracy, +and whether you can address the problem by adjusting the hyper-parameters. We +are not currently aware of any foolproof recipe. + +The main disadvantage of sharing weights between components is flexibility. +If your components are independent, you can train pipelines separately and +merge them together much more easily. Shared weights also make it more +difficult to resume training of only part of your pipeline. If you train only +part of your pipeline, you risk hurting the accuracy of the other components, +as you'll be changing the shared embedding layer those components are relying +on. + ![Pipeline components using a shared embedding component vs. independent embedding layers](../images/tok2vec.svg) | Shared | Independent | | ------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | | βœ… **smaller:** models only need to include a single copy of the embeddings | ❌ **larger:** models need to include the embeddings for each component | -| βœ… **faster:** | ❌ **slower:** | +| βœ… **faster:** embed the documents once for your whole pipeline | ❌ **slower:** rerun the embedding for each component | | ❌ **less composable:** all components require the same embedding component in the pipeline | βœ… **modular:** components can be moved and swapped freely | +| ?? **accuracy:** weight sharing may increase or decrease accuracy, depending on your task and data, but usually the impact is small | ![Pipeline components listening to shared embedding component](../images/tok2vec-listener.svg) - ## Using transformer models {#transformers} From 37ebff6997a749ecd9f91bc0d93aa6031fbd5ed9 Mon Sep 17 00:00:00 2001 From: Ines Montani Date: Sat, 22 Aug 2020 16:47:03 +0200 Subject: [PATCH 27/33] Update docs [ci skip] --- website/docs/usage/embeddings-transformers.md | 83 +++++++++---------- website/docs/usage/linguistic-features.md | 2 +- 2 files changed, 40 insertions(+), 45 deletions(-) diff --git a/website/docs/usage/embeddings-transformers.md b/website/docs/usage/embeddings-transformers.md index 04b79007c..d535982d7 100644 --- a/website/docs/usage/embeddings-transformers.md +++ b/website/docs/usage/embeddings-transformers.md @@ -9,23 +9,23 @@ menu: next: /usage/training --- -spaCy supports a number of transfer and multi-task learning workflows that can -often help improve your pipeline's efficiency or accuracy. Transfer learning +spaCy supports a number of **transfer and multi-task learning** workflows that +can often help improve your pipeline's efficiency or accuracy. Transfer learning refers to techniques such as word vector tables and language model pretraining. These techniques can be used to import knowledge from raw text into your -pipeline, so that your models are able to generalize better from your -annotated examples. +pipeline, so that your models are able to generalize better from your annotated +examples. -You can convert word vectors from popular tools like FastText and Gensim, or -you can load in any pretrained transformer model if you install our -`spacy-transformers` integration. You can also do your own language model pretraining -via the `spacy pretrain` command. You can even share your transformer or other -contextual embedding model across multiple components, which can make long -pipelines several times more efficient. - -In order to use transfer learning, you'll need to have at least a few annotated -examples for all of the classes you're trying to predict. If you don't, you -could try using a "one-shot learning" approach using +You can convert **word vectors** from popular tools like +[FastText](https://fasttext.cc) and [Gensim](https://radimrehurek.com/gensim), +or you can load in any pretrained **transformer model** if you install +[`spacy-transformers`](https://github.com/explosion/spacy-transformers). You can +also do your own language model pretraining via the +[`spacy pretrain`](/api/cli#pretrain) command. You can even **share** your +transformer or other contextual embedding model across multiple components, +which can make long pipelines several times more efficient. To use transfer +learning, you'll need at least a few annotated examples for what you're trying +to predict. Otherwise, you could try using a "one-shot learning" approach using [vectors and similarity](/usage/linguistic-features#vectors-similarity). @@ -70,35 +70,13 @@ of performance. ## Shared embedding layers {#embedding-layers} -You can share a single token-to-vector embedding model between multiple -components using the `Tok2Vec` component. Other components in -your pipeline can "connect" to the `Tok2Vec` component by including a _listener layer_ -within their model. At the beginning of training, the `Tok2Vec` component will -grab a reference to the relevant listener layers in the rest of your pipeline. -Then, when the `Tok2Vec` component processes a batch of documents, it will pass -forward its predictions to the listeners, allowing the listeners to reuse the -predictions when they are eventually called. A similar mechanism is used to -pass gradients from the listeners back to the `Tok2Vec` model. The -`Transformer` component and `TransformerListener` layer do the same thing for -transformer models, making it easy to share a single transformer model across -your whole pipeline. - -Training a single transformer or other embedding layer for use with multiple -components is termed _multi-task learning_. Multi-task learning is sometimes -less consistent, and the results are generally harder to reason about (as there's -more going on). You'll usually want to compare your accuracy against a single-task -approach to understand whether the weight-sharing is impacting your accuracy, -and whether you can address the problem by adjusting the hyper-parameters. We -are not currently aware of any foolproof recipe. - -The main disadvantage of sharing weights between components is flexibility. -If your components are independent, you can train pipelines separately and -merge them together much more easily. Shared weights also make it more -difficult to resume training of only part of your pipeline. If you train only -part of your pipeline, you risk hurting the accuracy of the other components, -as you'll be changing the shared embedding layer those components are relying -on. - +spaCy lets you share a single embedding layer and reuse it across multiple +components. This is also known as **multi-task learning**. Sharing weights +between components can make your pipeline run a lot faster and result in a much +smaller models size, as you only need a single copy of the embeddings. However, +it can make the pipeline less modular and make it more difficult to swap +components or retrain parts of the pipeline, since all components depend on the +same weights. ![Pipeline components using a shared embedding component vs. independent embedding layers](../images/tok2vec.svg) @@ -107,10 +85,27 @@ on. | βœ… **smaller:** models only need to include a single copy of the embeddings | ❌ **larger:** models need to include the embeddings for each component | | βœ… **faster:** embed the documents once for your whole pipeline | ❌ **slower:** rerun the embedding for each component | | ❌ **less composable:** all components require the same embedding component in the pipeline | βœ… **modular:** components can be moved and swapped freely | -| ?? **accuracy:** weight sharing may increase or decrease accuracy, depending on your task and data, but usually the impact is small | + +a single token-to-vector embedding model between multiple components using the +[`Tok2Vec`](/api/tok2vec) component. Other components in your pipeline can +"connect" this component by including a **listener layer** like +[Tok2VecListener](/api/architectures#Tok2VecListener) within their model. ![Pipeline components listening to shared embedding component](../images/tok2vec-listener.svg) +At the beginning of training, the [`Tok2Vec`](/api/tok2vec) component will grab +a reference to the relevant listener layers in the rest of your pipeline. When +it processes a batch of documents, it will pass forward its predictions to the +listeners, allowing the listeners to **reuse the predictions** when they are +eventually called. A similar mechanism is used to pass gradients from the +listeners back to the model. The [`Transformer`](/api/transformer) component and +[TransformerListener](/api/architectures#TransformerListener) layer do the same +thing for transformer models, making it easy to share a single transformer model +across your whole pipeline. + + + + ## Using transformer models {#transformers} diff --git a/website/docs/usage/linguistic-features.md b/website/docs/usage/linguistic-features.md index f52c2b2ad..f2ec48d63 100644 --- a/website/docs/usage/linguistic-features.md +++ b/website/docs/usage/linguistic-features.md @@ -1550,7 +1550,7 @@ import Vectors101 from 'usage/101/\_vectors-similarity.md' ### Adding word vectors {#adding-vectors} Custom word vectors can be trained using a number of open-source libraries, such -as [Gensim](https://radimrehurek.com/gensim), [Fast Text](https://fasttext.cc), +as [Gensim](https://radimrehurek.com/gensim), [FastText](https://fasttext.cc), or Tomas Mikolov's original [Word2vec implementation](https://code.google.com/archive/p/word2vec/). Most word vector libraries output an easy-to-read text-based format, where each line From adcf790b96446aabdc8f2bc78491cc52cb35843d Mon Sep 17 00:00:00 2001 From: Ines Montani Date: Sat, 22 Aug 2020 17:04:16 +0200 Subject: [PATCH 28/33] Update docs[ci skip] --- website/docs/images/layers-architectures.svg | 97 ++++++++++++++++++++ website/docs/usage/layers-architectures.md | 10 +- website/src/styles/readnext.module.sass | 2 +- 3 files changed, 103 insertions(+), 6 deletions(-) create mode 100644 website/docs/images/layers-architectures.svg diff --git a/website/docs/images/layers-architectures.svg b/website/docs/images/layers-architectures.svg new file mode 100644 index 000000000..22e705ba1 --- /dev/null +++ b/website/docs/images/layers-architectures.svg @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/website/docs/usage/layers-architectures.md b/website/docs/usage/layers-architectures.md index eebcc4681..4f91b1595 100644 --- a/website/docs/usage/layers-architectures.md +++ b/website/docs/usage/layers-architectures.md @@ -20,9 +20,9 @@ so that it refers to a different registered function. Once the component has been created, its model instance has already been assigned, so you cannot change its model architecture. The architecture is like a recipe for the network, and you can't change the recipe once the dish has already been prepared. You have to -make a new one. ​ +make a new one. - +![Diagram of a pipeline component with its model](../images/layers-architectures.svg) ## Type signatures {#type-sigs} @@ -137,9 +137,9 @@ Thinc uses a special class, [`Shim`](https://thinc.ai/docs/api-model#shim), to hold references to external objects. This allows each wrapper space to define a custom type, with whatever attributes and methods are helpful, to assist in managing the communication between Thinc and the external library. The -[`Model`](/docs/api-model#model) class holds `shim` instances in a separate -list, and communicates with the shims about updates, serialization, changes of -device, etc. +[`Model`](https://thinc.ai/docs/api-model#model) class holds `shim` instances in +a separate list, and communicates with the shims about updates, serialization, +changes of device, etc. The wrapper will receive each batch of inputs, convert them into a suitable form for the underlying model instance, and pass them over to the shim, which will diff --git a/website/src/styles/readnext.module.sass b/website/src/styles/readnext.module.sass index 23aa7f016..aef91c09e 100644 --- a/website/src/styles/readnext.module.sass +++ b/website/src/styles/readnext.module.sass @@ -12,7 +12,7 @@ background: var(--color-subtle-light) color: var(--color-subtle-dark) border-radius: 50% - padding: 0.5rem + padding: 0.5rem 0.65rem 0.5rem 0 transition: color 0.2s ease float: right margin-left: 3rem From 048de64d4c29408a24cbd55c466cbca446068f49 Mon Sep 17 00:00:00 2001 From: Matthew Honnibal Date: Sat, 22 Aug 2020 17:11:28 +0200 Subject: [PATCH 29/33] Suggest edits --- website/docs/usage/embeddings-transformers.md | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/website/docs/usage/embeddings-transformers.md b/website/docs/usage/embeddings-transformers.md index d535982d7..4f40104c4 100644 --- a/website/docs/usage/embeddings-transformers.md +++ b/website/docs/usage/embeddings-transformers.md @@ -70,13 +70,14 @@ of performance. ## Shared embedding layers {#embedding-layers} -spaCy lets you share a single embedding layer and reuse it across multiple -components. This is also known as **multi-task learning**. Sharing weights -between components can make your pipeline run a lot faster and result in a much -smaller models size, as you only need a single copy of the embeddings. However, -it can make the pipeline less modular and make it more difficult to swap -components or retrain parts of the pipeline, since all components depend on the -same weights. +spaCy lets you share a single transformer or other token-to-vector ("tok2vec") +embedding layer between multiple components. You can even update the shared layer, +performing **multi-task learning**. Reusing the tok2vec layer between components +can make your pipeline run a lot faster and result in much +smaller models. However, it can make the pipeline less modular and make it more +difficult to swap components or retrain parts of the pipeline. Multi-task +learning can affect your accuracy (either positively or negatively), and may +require some retuning of your hyper-parameters. ![Pipeline components using a shared embedding component vs. independent embedding layers](../images/tok2vec.svg) @@ -86,10 +87,11 @@ same weights. | βœ… **faster:** embed the documents once for your whole pipeline | ❌ **slower:** rerun the embedding for each component | | ❌ **less composable:** all components require the same embedding component in the pipeline | βœ… **modular:** components can be moved and swapped freely | -a single token-to-vector embedding model between multiple components using the -[`Tok2Vec`](/api/tok2vec) component. Other components in your pipeline can -"connect" this component by including a **listener layer** like -[Tok2VecListener](/api/architectures#Tok2VecListener) within their model. +You can share a single transformer or other tok2vec model between multiple components +by adding a [`Transformer`](/api/transformer) or [`Tok2Vec`](/api/tok2vec) component +near the start of your pipeline. Components later in the pipeline can "connect" +to it by including a **listener layer** like [Tok2VecListener](/api/architectures#Tok2VecListener) +within their model. ![Pipeline components listening to shared embedding component](../images/tok2vec-listener.svg) @@ -100,8 +102,9 @@ listeners, allowing the listeners to **reuse the predictions** when they are eventually called. A similar mechanism is used to pass gradients from the listeners back to the model. The [`Transformer`](/api/transformer) component and [TransformerListener](/api/architectures#TransformerListener) layer do the same -thing for transformer models, making it easy to share a single transformer model -across your whole pipeline. +thing for transformer models, but the `Transformer` component will also save the +transformer outputs to the `doc._.trf_data` extension attribute, giving you +access to them after the pipeline has finished running. From 98a9e063b695c020fde8b876ec97fe914723fd0b Mon Sep 17 00:00:00 2001 From: Ines Montani Date: Sat, 22 Aug 2020 17:15:05 +0200 Subject: [PATCH 30/33] Update docs [ci skip] --- website/docs/usage/embeddings-transformers.md | 25 ++++++++++--------- website/docs/usage/layers-architectures.md | 13 ++++++++++ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/website/docs/usage/embeddings-transformers.md b/website/docs/usage/embeddings-transformers.md index 4f40104c4..7648a5d45 100644 --- a/website/docs/usage/embeddings-transformers.md +++ b/website/docs/usage/embeddings-transformers.md @@ -71,10 +71,10 @@ of performance. ## Shared embedding layers {#embedding-layers} spaCy lets you share a single transformer or other token-to-vector ("tok2vec") -embedding layer between multiple components. You can even update the shared layer, -performing **multi-task learning**. Reusing the tok2vec layer between components -can make your pipeline run a lot faster and result in much -smaller models. However, it can make the pipeline less modular and make it more +embedding layer between multiple components. You can even update the shared +layer, performing **multi-task learning**. Reusing the tok2vec layer between +components can make your pipeline run a lot faster and result in much smaller +models. However, it can make the pipeline less modular and make it more difficult to swap components or retrain parts of the pipeline. Multi-task learning can affect your accuracy (either positively or negatively), and may require some retuning of your hyper-parameters. @@ -87,11 +87,11 @@ require some retuning of your hyper-parameters. | βœ… **faster:** embed the documents once for your whole pipeline | ❌ **slower:** rerun the embedding for each component | | ❌ **less composable:** all components require the same embedding component in the pipeline | βœ… **modular:** components can be moved and swapped freely | -You can share a single transformer or other tok2vec model between multiple components -by adding a [`Transformer`](/api/transformer) or [`Tok2Vec`](/api/tok2vec) component -near the start of your pipeline. Components later in the pipeline can "connect" -to it by including a **listener layer** like [Tok2VecListener](/api/architectures#Tok2VecListener) -within their model. +You can share a single transformer or other tok2vec model between multiple +components by adding a [`Transformer`](/api/transformer) or +[`Tok2Vec`](/api/tok2vec) component near the start of your pipeline. Components +later in the pipeline can "connect" to it by including a **listener layer** like +[Tok2VecListener](/api/architectures#Tok2VecListener) within their model. ![Pipeline components listening to shared embedding component](../images/tok2vec-listener.svg) @@ -102,9 +102,10 @@ listeners, allowing the listeners to **reuse the predictions** when they are eventually called. A similar mechanism is used to pass gradients from the listeners back to the model. The [`Transformer`](/api/transformer) component and [TransformerListener](/api/architectures#TransformerListener) layer do the same -thing for transformer models, but the `Transformer` component will also save the -transformer outputs to the `doc._.trf_data` extension attribute, giving you -access to them after the pipeline has finished running. +thing for transformer models, but the `Transformer` component will also save the +transformer outputs to the +[`Doc._.trf_data`](/api/transformer#custom_attributes) extension attribute, +giving you access to them after the pipeline has finished running. diff --git a/website/docs/usage/layers-architectures.md b/website/docs/usage/layers-architectures.md index 4f91b1595..aa398f752 100644 --- a/website/docs/usage/layers-architectures.md +++ b/website/docs/usage/layers-architectures.md @@ -170,3 +170,16 @@ to the host device unnecessarily. - Interaction with `predict`, `get_loss` and `set_annotations` - Initialization life-cycle with `begin_training`. - Link to relation extraction notebook. + +```python +def update(self, examples): + docs = [ex.predicted for ex in examples] + refs = [ex.reference for ex in examples] + predictions, backprop = self.model.begin_update(docs) + gradient = self.get_loss(predictions, refs) + backprop(gradient) + +def __call__(self, doc): + predictions = self.model([doc]) + self.set_annotations(predictions) +``` From f27aecac1451fd0339def7891be8231efb844978 Mon Sep 17 00:00:00 2001 From: Ines Montani Date: Sun, 23 Aug 2020 11:57:56 +0200 Subject: [PATCH 31/33] Update formatting [ci skip] --- website/docs/usage/saving-loading.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/usage/saving-loading.md b/website/docs/usage/saving-loading.md index b5e0f4370..3f9435f5e 100644 --- a/website/docs/usage/saving-loading.md +++ b/website/docs/usage/saving-loading.md @@ -243,7 +243,7 @@ file `data.json` in its subdirectory: ### Directory structure {highlight="2-3"} └── /path/to/model β”œβ”€β”€ my_component # data serialized by "my_component" - | └── data.json + β”‚ └── data.json β”œβ”€β”€ ner # data for "ner" component β”œβ”€β”€ parser # data for "parser" component β”œβ”€β”€ tagger # data for "tagger" component From 9bdc9e81f5f8affe464d1ff3c6bc35c08aa2a0d6 Mon Sep 17 00:00:00 2001 From: Ines Montani Date: Sun, 23 Aug 2020 12:14:02 +0200 Subject: [PATCH 32/33] Fix error message [ci skip] --- spacy/cli/_util.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spacy/cli/_util.py b/spacy/cli/_util.py index 9d3ae0913..d1686c051 100644 --- a/spacy/cli/_util.py +++ b/spacy/cli/_util.py @@ -110,7 +110,9 @@ def load_project_config(path: Path) -> Dict[str, Any]: msg.fail(invalid_err, e, exits=1) errors = validate(ProjectConfigSchema, config) if errors: - msg.fail(invalid_err, "\n".join(errors), exits=1) + msg.fail(invalid_err) + print("\n".join(errors)) + sys.exit(1) validate_project_commands(config) # Make sure directories defined in config exist for subdir in config.get("directories", []): From e5598676053c4fc759a8298cf3532260f371dbf2 Mon Sep 17 00:00:00 2001 From: Matthew Honnibal Date: Sun, 23 Aug 2020 18:32:09 +0200 Subject: [PATCH 33/33] Allow spacy project to push and pull to/from remote storage (#5949) * Add utils for working with remote storage * WIP add remote_cache for project * WIP add push and pull commands * Use pathy in remote_cache * Updarte util * Update remote_cache * Update util * Update project assets * Update pull script * Update push script * Fix type annotation in util * Work on remote storage * Remove site and env hash * Fix imports * Fix type annotation * Require pathy * Require pathy * Fix import * Add a util to handle project variable substitution * Import push and pull commands * Fix pull command * Fix push command * Fix tarfile in remote_storage * Improve printing * Fiddle with status messages * Set version to v3.0.0a9 * Draft docs for spacy project remote storages * Update docs [ci skip] * Use Thinc config to simplify and unify template variables * Auto-format * Don't import Pathy globally for now Causes slow and annoying Google Cloud warning * Tidy up test * Tidy up and update tests * Update to latest Thinc * Update docs * variables -> vars * Update docs [ci skip] * Update docs [ci skip] Co-authored-by: Ines Montani --- pyproject.toml | 5 +- requirements.txt | 3 +- setup.cfg | 5 +- spacy/about.py | 2 +- spacy/cli/__init__.py | 2 + spacy/cli/_util.py | 62 +++++++++- spacy/cli/project/assets.py | 18 +-- spacy/cli/project/dvc.py | 12 +- spacy/cli/project/pull.py | 36 ++++++ spacy/cli/project/push.py | 48 ++++++++ spacy/cli/project/remote_storage.py | 169 ++++++++++++++++++++++++++ spacy/cli/project/run.py | 50 ++------ spacy/schemas.py | 2 +- spacy/tests/test_cli.py | 23 +++- spacy/util.py | 4 +- website/docs/api/cli.md | 86 +++++++++++++ website/docs/images/projects.svg | 91 ++++++++++++++ website/docs/usage/projects.md | 182 ++++++++++++++++++++++++---- website/docs/usage/v3.md | 14 ++- website/src/components/table.js | 5 +- 20 files changed, 712 insertions(+), 107 deletions(-) create mode 100644 spacy/cli/project/pull.py create mode 100644 spacy/cli/project/push.py create mode 100644 spacy/cli/project/remote_storage.py create mode 100644 website/docs/images/projects.svg diff --git a/pyproject.toml b/pyproject.toml index 9a646d0d7..77deb44b0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,9 +6,10 @@ requires = [ "cymem>=2.0.2,<2.1.0", "preshed>=3.0.2,<3.1.0", "murmurhash>=0.28.0,<1.1.0", - "thinc>=8.0.0a28,<8.0.0a30", + "thinc>=8.0.0a29,<8.0.0a40", "blis>=0.4.0,<0.5.0", "pytokenizations", - "smart_open>=2.0.0,<3.0.0" + "smart_open>=2.0.0,<3.0.0", + "pathy" ] build-backend = "setuptools.build_meta" diff --git a/requirements.txt b/requirements.txt index 181cb2101..5aafd83dd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ # Our libraries cymem>=2.0.2,<2.1.0 preshed>=3.0.2,<3.1.0 -thinc>=8.0.0a28,<8.0.0a30 +thinc>=8.0.0a29,<8.0.0a40 blis>=0.4.0,<0.5.0 ml_datasets>=0.1.1 murmurhash>=0.28.0,<1.1.0 @@ -9,6 +9,7 @@ wasabi>=0.7.1,<1.1.0 srsly>=2.1.0,<3.0.0 catalogue>=0.0.7,<1.1.0 typer>=0.3.0,<0.4.0 +pathy # Third party dependencies numpy>=1.15.0 requests>=2.13.0,<3.0.0 diff --git a/setup.cfg b/setup.cfg index d56eab3a6..8b4819ed8 100644 --- a/setup.cfg +++ b/setup.cfg @@ -34,18 +34,19 @@ setup_requires = cymem>=2.0.2,<2.1.0 preshed>=3.0.2,<3.1.0 murmurhash>=0.28.0,<1.1.0 - thinc>=8.0.0a28,<8.0.0a30 + thinc>=8.0.0a29,<8.0.0a40 install_requires = # Our libraries murmurhash>=0.28.0,<1.1.0 cymem>=2.0.2,<2.1.0 preshed>=3.0.2,<3.1.0 - thinc>=8.0.0a28,<8.0.0a30 + thinc>=8.0.0a29,<8.0.0a40 blis>=0.4.0,<0.5.0 wasabi>=0.7.1,<1.1.0 srsly>=2.1.0,<3.0.0 catalogue>=0.0.7,<1.1.0 typer>=0.3.0,<0.4.0 + pathy # Third-party dependencies tqdm>=4.38.0,<5.0.0 numpy>=1.15.0 diff --git a/spacy/about.py b/spacy/about.py index 77b00eb48..56bb016c3 100644 --- a/spacy/about.py +++ b/spacy/about.py @@ -1,6 +1,6 @@ # fmt: off __title__ = "spacy-nightly" -__version__ = "3.0.0a8" +__version__ = "3.0.0a9" __release__ = True __download_url__ = "https://github.com/explosion/spacy-models/releases/download" __compatibility__ = "https://raw.githubusercontent.com/explosion/spacy-models/master/compatibility.json" diff --git a/spacy/cli/__init__.py b/spacy/cli/__init__.py index 2b21e2f2b..8aea6ef45 100644 --- a/spacy/cli/__init__.py +++ b/spacy/cli/__init__.py @@ -21,6 +21,8 @@ from .project.clone import project_clone # noqa: F401 from .project.assets import project_assets # noqa: F401 from .project.run import project_run # noqa: F401 from .project.dvc import project_update_dvc # noqa: F401 +from .project.push import project_push # noqa: F401 +from .project.pull import project_pull # noqa: F401 @app.command("link", no_args_is_help=True, deprecated=True, hidden=True) diff --git a/spacy/cli/_util.py b/spacy/cli/_util.py index d1686c051..b527ac2a0 100644 --- a/spacy/cli/_util.py +++ b/spacy/cli/_util.py @@ -1,4 +1,5 @@ -from typing import Dict, Any, Union, List, Optional +from typing import Dict, Any, Union, List, Optional, TYPE_CHECKING +import sys from pathlib import Path from wasabi import msg import srsly @@ -8,11 +9,13 @@ from typer.main import get_command from contextlib import contextmanager from thinc.config import Config, ConfigValidationError from configparser import InterpolationError -import sys from ..schemas import ProjectConfigSchema, validate from ..util import import_file +if TYPE_CHECKING: + from pathy import Pathy # noqa: F401 + PROJECT_FILE = "project.yml" PROJECT_LOCK = "project.lock" @@ -93,11 +96,12 @@ def parse_config_overrides(args: List[str]) -> Dict[str, Any]: return result -def load_project_config(path: Path) -> Dict[str, Any]: +def load_project_config(path: Path, interpolate: bool = True) -> Dict[str, Any]: """Load the project.yml file from a directory and validate it. Also make sure that all directories defined in the config exist. path (Path): The path to the project directory. + interpolate (bool): Whether to substitute project variables. RETURNS (Dict[str, Any]): The loaded project.yml. """ config_path = path / PROJECT_FILE @@ -119,9 +123,25 @@ def load_project_config(path: Path) -> Dict[str, Any]: dir_path = path / subdir if not dir_path.exists(): dir_path.mkdir(parents=True) + if interpolate: + err = "project.yml validation error" + with show_validation_error(title=err, hint_fill=False): + config = substitute_project_variables(config) return config +def substitute_project_variables(config: Dict[str, Any], overrides: Dict = {}): + key = "vars" + config.setdefault(key, {}) + config[key].update(overrides) + # Need to put variables in the top scope again so we can have a top-level + # section "project" (otherwise, a list of commands in the top scope wouldn't) + # be allowed by Thinc's config system + cfg = Config({"project": config, key: config[key]}) + interpolated = cfg.interpolate() + return dict(interpolated["project"]) + + def validate_project_commands(config: Dict[str, Any]) -> None: """Check that project commands and workflows are valid, don't contain duplicates, don't clash and only refer to commands that exist. @@ -232,3 +252,39 @@ def get_sourced_components(config: Union[Dict[str, Any], Config]) -> List[str]: for name, cfg in config.get("components", {}).items() if "factory" not in cfg and "source" in cfg ] + + +def upload_file(src: Path, dest: Union[str, "Pathy"]) -> None: + """Upload a file. + + src (Path): The source path. + url (str): The destination URL to upload to. + """ + dest = ensure_pathy(dest) + with dest.open(mode="wb") as output_file: + with src.open(mode="rb") as input_file: + output_file.write(input_file.read()) + + +def download_file(src: Union[str, "Pathy"], dest: Path, *, force: bool = False) -> None: + """Download a file using smart_open. + + url (str): The URL of the file. + dest (Path): The destination path. + force (bool): Whether to force download even if file exists. + If False, the download will be skipped. + """ + if dest.exists() and not force: + return None + src = ensure_pathy(src) + with src.open(mode="rb") as input_file: + with dest.open(mode="wb") as output_file: + output_file.write(input_file.read()) + + +def ensure_pathy(path): + """Temporary helper to prevent importing Pathy globally (which can cause + slow and annoying Google Cloud warning).""" + from pathy import Pathy # noqa: F811 + + return Pathy(path) diff --git a/spacy/cli/project/assets.py b/spacy/cli/project/assets.py index 3be784e04..60cf95160 100644 --- a/spacy/cli/project/assets.py +++ b/spacy/cli/project/assets.py @@ -4,10 +4,10 @@ from wasabi import msg import re import shutil import requests -import smart_open from ...util import ensure_path, working_dir from .._util import project_cli, Arg, PROJECT_FILE, load_project_config, get_checksum +from .._util import download_file # TODO: find a solution for caches @@ -44,16 +44,14 @@ def project_assets(project_dir: Path) -> None: if not assets: msg.warn(f"No assets specified in {PROJECT_FILE}", exits=0) msg.info(f"Fetching {len(assets)} asset(s)") - variables = config.get("variables", {}) for asset in assets: - dest = asset["dest"].format(**variables) + dest = asset["dest"] url = asset.get("url") checksum = asset.get("checksum") if not url: # project.yml defines asset without URL that the user has to place check_private_asset(dest, checksum) continue - url = url.format(**variables) fetch_asset(project_path, url, dest, checksum) @@ -132,15 +130,3 @@ def convert_asset_url(url: str) -> str: ) return converted return url - - -def download_file(url: str, dest: Path, chunk_size: int = 1024) -> None: - """Download a file using smart_open. - - url (str): The URL of the file. - dest (Path): The destination path. - chunk_size (int): The size of chunks to read/write. - """ - with smart_open.open(url, mode="rb") as input_file: - with dest.open(mode="wb") as output_file: - output_file.write(input_file.read()) diff --git a/spacy/cli/project/dvc.py b/spacy/cli/project/dvc.py index 7386339d9..e0f6cd430 100644 --- a/spacy/cli/project/dvc.py +++ b/spacy/cli/project/dvc.py @@ -99,7 +99,6 @@ def update_dvc_config( if ref_hash == config_hash and not force: return False # Nothing has changed in project.yml, don't need to update dvc_config_path.unlink() - variables = config.get("variables", {}) dvc_commands = [] config_commands = {cmd["name"]: cmd for cmd in config.get("commands", [])} for name in workflows[workflow]: @@ -122,7 +121,7 @@ def update_dvc_config( dvc_commands.append(join_command(full_cmd)) with working_dir(path): dvc_flags = {"--verbose": verbose, "--quiet": silent} - run_dvc_commands(dvc_commands, variables, flags=dvc_flags) + run_dvc_commands(dvc_commands, flags=dvc_flags) with dvc_config_path.open("r+", encoding="utf8") as f: content = f.read() f.seek(0, 0) @@ -131,23 +130,16 @@ def update_dvc_config( def run_dvc_commands( - commands: List[str] = tuple(), - variables: Dict[str, str] = {}, - flags: Dict[str, bool] = {}, + commands: List[str] = tuple(), flags: Dict[str, bool] = {}, ) -> None: """Run a sequence of DVC commands in a subprocess, in order. commands (List[str]): The string commands without the leading "dvc". - variables (Dict[str, str]): Dictionary of variable names, mapped to their - values. Will be used to substitute format string variables in the - commands. flags (Dict[str, bool]): Conditional flags to be added to command. Makes it easier to pass flags like --quiet that depend on a variable or command-line setting while avoiding lots of nested conditionals. """ for command in commands: - # Substitute variables, e.g. "./{NAME}.json" - command = command.format(**variables) command = split_command(command) dvc_command = ["dvc", *command] # Add the flags if they are set to True diff --git a/spacy/cli/project/pull.py b/spacy/cli/project/pull.py new file mode 100644 index 000000000..1bf608c40 --- /dev/null +++ b/spacy/cli/project/pull.py @@ -0,0 +1,36 @@ +from pathlib import Path +from wasabi import msg +from .remote_storage import RemoteStorage +from .remote_storage import get_command_hash +from .._util import project_cli, Arg +from .._util import load_project_config + + +@project_cli.command("pull") +def project_pull_cli( + # fmt: off + remote: str = Arg("default", help="Name or path of remote storage"), + project_dir: Path = Arg(Path.cwd(), help="Location of project directory. Defaults to current working directory.", exists=True, file_okay=False), + # fmt: on +): + """Retrieve any precomputed outputs from a remote storage that are available. + You can alias remotes in your project.yml by mapping them to storage paths. + A storage can be anything that the smart-open library can upload to, e.g. + gcs, aws, ssh, local directories etc + """ + for url, output_path in project_pull(project_dir, remote): + if url is not None: + msg.good(f"Pulled {output_path} from {url}") + + +def project_pull(project_dir: Path, remote: str, *, verbose: bool = False): + config = load_project_config(project_dir) + if remote in config.get("remotes", {}): + remote = config["remotes"][remote] + storage = RemoteStorage(project_dir, remote) + for cmd in config.get("commands", []): + deps = [project_dir / dep for dep in cmd.get("deps", [])] + cmd_hash = get_command_hash("", "", deps, cmd["script"]) + for output_path in cmd.get("outputs", []): + url = storage.pull(output_path, command_hash=cmd_hash) + yield url, output_path diff --git a/spacy/cli/project/push.py b/spacy/cli/project/push.py new file mode 100644 index 000000000..0b070c9d8 --- /dev/null +++ b/spacy/cli/project/push.py @@ -0,0 +1,48 @@ +from pathlib import Path +from wasabi import msg +from .remote_storage import RemoteStorage +from .remote_storage import get_content_hash, get_command_hash +from .._util import load_project_config +from .._util import project_cli, Arg + + +@project_cli.command("push") +def project_push_cli( + # fmt: off + remote: str = Arg("default", help="Name or path of remote storage"), + project_dir: Path = Arg(Path.cwd(), help="Location of project directory. Defaults to current working directory.", exists=True, file_okay=False), + # fmt: on +): + """Persist outputs to a remote storage. You can alias remotes in your project.yml + by mapping them to storage paths. A storage can be anything that the smart-open + library can upload to, e.g. gcs, aws, ssh, local directories etc + """ + for output_path, url in project_push(project_dir, remote): + if url is None: + msg.info(f"Skipping {output_path}") + else: + msg.good(f"Pushed {output_path} to {url}") + + +def project_push(project_dir: Path, remote: str): + """Persist outputs to a remote storage. You can alias remotes in your project.yml + by mapping them to storage paths. A storage can be anything that the smart-open + library can upload to, e.g. gcs, aws, ssh, local directories etc + """ + config = load_project_config(project_dir) + if remote in config.get("remotes", {}): + remote = config["remotes"][remote] + storage = RemoteStorage(project_dir, remote) + for cmd in config.get("commands", []): + cmd_hash = get_command_hash( + "", "", [project_dir / dep for dep in cmd.get("deps", [])], cmd["script"] + ) + for output_path in cmd.get("outputs", []): + output_loc = project_dir / output_path + if output_loc.exists(): + url = storage.push( + output_path, + command_hash=cmd_hash, + content_hash=get_content_hash(output_loc), + ) + yield output_path, url diff --git a/spacy/cli/project/remote_storage.py b/spacy/cli/project/remote_storage.py new file mode 100644 index 000000000..e7e7cbbe8 --- /dev/null +++ b/spacy/cli/project/remote_storage.py @@ -0,0 +1,169 @@ +from typing import Optional, List, Dict, TYPE_CHECKING +import os +import site +import hashlib +import urllib.parse +import tarfile +from pathlib import Path + +from .._util import get_hash, get_checksum, download_file, ensure_pathy +from ...util import make_tempdir + +if TYPE_CHECKING: + from pathy import Pathy # noqa: F401 + + +class RemoteStorage: + """Push and pull outputs to and from a remote file storage. + + Remotes can be anything that `smart-open` can support: AWS, GCS, file system, + ssh, etc. + """ + + def __init__(self, project_root: Path, url: str, *, compression="gz"): + self.root = project_root + self.url = ensure_pathy(url) + self.compression = compression + + def push(self, path: Path, command_hash: str, content_hash: str) -> "Pathy": + """Compress a file or directory within a project and upload it to a remote + storage. If an object exists at the full URL, nothing is done. + + Within the remote storage, files are addressed by their project path + (url encoded) and two user-supplied hashes, representing their creation + context and their file contents. If the URL already exists, the data is + not uploaded. Paths are archived and compressed prior to upload. + """ + loc = self.root / path + if not loc.exists(): + raise IOError(f"Cannot push {loc}: does not exist.") + url = self.make_url(path, command_hash, content_hash) + if url.exists(): + return None + tmp: Path + with make_tempdir() as tmp: + tar_loc = tmp / self.encode_name(str(path)) + mode_string = f"w:{self.compression}" if self.compression else "w" + with tarfile.open(tar_loc, mode=mode_string) as tar_file: + tar_file.add(str(loc), arcname=str(path)) + with tar_loc.open(mode="rb") as input_file: + with url.open(mode="wb") as output_file: + output_file.write(input_file.read()) + return url + + def pull( + self, + path: Path, + *, + command_hash: Optional[str] = None, + content_hash: Optional[str] = None, + ) -> Optional["Pathy"]: + """Retrieve a file from the remote cache. If the file already exists, + nothing is done. + + If the command_hash and/or content_hash are specified, only matching + results are returned. If no results are available, an error is raised. + """ + dest = self.root / path + if dest.exists(): + return None + url = self.find(path, command_hash=command_hash, content_hash=content_hash) + if url is None: + return url + else: + # Make sure the destination exists + if not dest.parent.exists(): + dest.parent.mkdir(parents=True) + tmp: Path + with make_tempdir() as tmp: + tar_loc = tmp / url.parts[-1] + download_file(url, tar_loc) + mode_string = f"r:{self.compression}" if self.compression else "r" + with tarfile.open(tar_loc, mode=mode_string) as tar_file: + # This requires that the path is added correctly, relative + # to root. This is how we set things up in push() + tar_file.extractall(self.root) + return url + + def find( + self, + path: Path, + *, + command_hash: Optional[str] = None, + content_hash: Optional[str] = None, + ) -> Optional["Pathy"]: + """Find the best matching version of a file within the storage, + or `None` if no match can be found. If both the creation and content hash + are specified, only exact matches will be returned. Otherwise, the most + recent matching file is preferred. + """ + name = self.encode_name(str(path)) + if command_hash is not None and content_hash is not None: + url = self.make_url(path, command_hash, content_hash) + urls = [url] if url.exists() else [] + elif command_hash is not None: + urls = list((self.url / name / command_hash).iterdir()) + else: + urls = list((self.url / name).iterdir()) + if content_hash is not None: + urls = [url for url in urls if url.parts[-1] == content_hash] + return urls[-1] if urls else None + + def make_url(self, path: Path, command_hash: str, content_hash: str) -> "Pathy": + """Construct a URL from a subpath, a creation hash and a content hash.""" + return self.url / self.encode_name(str(path)) / command_hash / content_hash + + def encode_name(self, name: str) -> str: + """Encode a subpath into a URL-safe name.""" + return urllib.parse.quote_plus(name) + + +def get_content_hash(loc: Path) -> str: + return get_checksum(loc) + + +def get_command_hash( + site_hash: str, env_hash: str, deps: List[Path], cmd: List[str] +) -> str: + """Create a hash representing the execution of a command. This includes the + currently installed packages, whatever environment variables have been marked + as relevant, and the command. + """ + hashes = [site_hash, env_hash] + [get_checksum(dep) for dep in sorted(deps)] + hashes.extend(cmd) + creation_bytes = "".join(hashes).encode("utf8") + return hashlib.md5(creation_bytes).hexdigest() + + +def get_site_hash(): + """Hash the current Python environment's site-packages contents, including + the name and version of the libraries. The list we're hashing is what + `pip freeze` would output. + """ + site_dirs = site.getsitepackages() + if site.ENABLE_USER_SITE: + site_dirs.extend(site.getusersitepackages()) + packages = set() + for site_dir in site_dirs: + site_dir = Path(site_dir) + for subpath in site_dir.iterdir(): + if subpath.parts[-1].endswith("dist-info"): + packages.add(subpath.parts[-1].replace(".dist-info", "")) + package_bytes = "".join(sorted(packages)).encode("utf8") + return hashlib.md5sum(package_bytes).hexdigest() + + +def get_env_hash(env: Dict[str, str]) -> str: + """Construct a hash of the environment variables that will be passed into + the commands. + + Values in the env dict may be references to the current os.environ, using + the syntax $ENV_VAR to mean os.environ[ENV_VAR] + """ + env_vars = {} + for key, value in env.items(): + if value.startswith("$"): + env_vars[key] = os.environ.get(value[1:], "") + else: + env_vars[key] = value + return get_hash(env_vars) diff --git a/spacy/cli/project/run.py b/spacy/cli/project/run.py index 5c66095aa..6e1deeeee 100644 --- a/spacy/cli/project/run.py +++ b/spacy/cli/project/run.py @@ -44,7 +44,6 @@ def project_run( dry (bool): Perform a dry run and don't execute commands. """ config = load_project_config(project_dir) - variables = config.get("variables", {}) commands = {cmd["name"]: cmd for cmd in config.get("commands", [])} workflows = config.get("workflows", {}) validate_subcommand(commands.keys(), workflows.keys(), subcommand) @@ -54,22 +53,20 @@ def project_run( project_run(project_dir, cmd, force=force, dry=dry) else: cmd = commands[subcommand] - variables = config.get("variables", {}) for dep in cmd.get("deps", []): - dep = dep.format(**variables) if not (project_dir / dep).exists(): err = f"Missing dependency specified by command '{subcommand}': {dep}" err_kwargs = {"exits": 1} if not dry else {} msg.fail(err, **err_kwargs) with working_dir(project_dir) as current_dir: - rerun = check_rerun(current_dir, cmd, variables) + rerun = check_rerun(current_dir, cmd) if not rerun and not force: msg.info(f"Skipping '{cmd['name']}': nothing changed") else: msg.divider(subcommand) - run_commands(cmd["script"], variables, dry=dry) + run_commands(cmd["script"], dry=dry) if not dry: - update_lockfile(current_dir, cmd, variables) + update_lockfile(current_dir, cmd) def print_run_help(project_dir: Path, subcommand: Optional[str] = None) -> None: @@ -115,23 +112,15 @@ def print_run_help(project_dir: Path, subcommand: Optional[str] = None) -> None: def run_commands( - commands: List[str] = tuple(), - variables: Dict[str, Any] = {}, - silent: bool = False, - dry: bool = False, + commands: List[str] = tuple(), silent: bool = False, dry: bool = False, ) -> None: """Run a sequence of commands in a subprocess, in order. commands (List[str]): The string commands. - variables (Dict[str, Any]): Dictionary of variable names, mapped to their - values. Will be used to substitute format string variables in the - commands. silent (bool): Don't print the commands. dry (bool): Perform a dry run and don't execut anything. """ for command in commands: - # Substitute variables, e.g. "./{NAME}.json" - command = command.format(**variables) command = split_command(command) # Not sure if this is needed or a good idea. Motivation: users may often # use commands in their config that reference "python" and we want to @@ -173,15 +162,12 @@ def validate_subcommand( ) -def check_rerun( - project_dir: Path, command: Dict[str, Any], variables: Dict[str, Any] -) -> bool: +def check_rerun(project_dir: Path, command: Dict[str, Any]) -> bool: """Check if a command should be rerun because its settings or inputs/outputs changed. project_dir (Path): The current project directory. command (Dict[str, Any]): The command, as defined in the project.yml. - variables (Dict[str, Any]): The variables defined in the project.yml. RETURNS (bool): Whether to re-run the command. """ lock_path = project_dir / PROJECT_LOCK @@ -197,19 +183,16 @@ def check_rerun( # If the entry in the lockfile matches the lockfile entry that would be # generated from the current command, we don't rerun because it means that # all inputs/outputs, hashes and scripts are the same and nothing changed - return get_hash(get_lock_entry(project_dir, command, variables)) != get_hash(entry) + return get_hash(get_lock_entry(project_dir, command)) != get_hash(entry) -def update_lockfile( - project_dir: Path, command: Dict[str, Any], variables: Dict[str, Any] -) -> None: +def update_lockfile(project_dir: Path, command: Dict[str, Any]) -> None: """Update the lockfile after running a command. Will create a lockfile if it doesn't yet exist and will add an entry for the current command, its script and dependencies/outputs. project_dir (Path): The current project directory. command (Dict[str, Any]): The command, as defined in the project.yml. - variables (Dict[str, Any]): The variables defined in the project.yml. """ lock_path = project_dir / PROJECT_LOCK if not lock_path.exists(): @@ -217,13 +200,11 @@ def update_lockfile( data = {} else: data = srsly.read_yaml(lock_path) - data[command["name"]] = get_lock_entry(project_dir, command, variables) + data[command["name"]] = get_lock_entry(project_dir, command) srsly.write_yaml(lock_path, data) -def get_lock_entry( - project_dir: Path, command: Dict[str, Any], variables: Dict[str, Any] -) -> Dict[str, Any]: +def get_lock_entry(project_dir: Path, command: Dict[str, Any]) -> Dict[str, Any]: """Get a lockfile entry for a given command. An entry includes the command, the script (command steps) and a list of dependencies and outputs with their paths and file hashes, if available. The format is based on the @@ -231,12 +212,11 @@ def get_lock_entry( project_dir (Path): The current project directory. command (Dict[str, Any]): The command, as defined in the project.yml. - variables (Dict[str, Any]): The variables defined in the project.yml. RETURNS (Dict[str, Any]): The lockfile entry. """ - deps = get_fileinfo(project_dir, command.get("deps", []), variables) - outs = get_fileinfo(project_dir, command.get("outputs", []), variables) - outs_nc = get_fileinfo(project_dir, command.get("outputs_no_cache", []), variables) + deps = get_fileinfo(project_dir, command.get("deps", [])) + outs = get_fileinfo(project_dir, command.get("outputs", [])) + outs_nc = get_fileinfo(project_dir, command.get("outputs_no_cache", [])) return { "cmd": f"{COMMAND} run {command['name']}", "script": command["script"], @@ -245,20 +225,16 @@ def get_lock_entry( } -def get_fileinfo( - project_dir: Path, paths: List[str], variables: Dict[str, Any] -) -> List[Dict[str, str]]: +def get_fileinfo(project_dir: Path, paths: List[str]) -> List[Dict[str, str]]: """Generate the file information for a list of paths (dependencies, outputs). Includes the file path and the file's checksum. project_dir (Path): The current project directory. paths (List[str]): The file paths. - variables (Dict[str, Any]): The variables defined in the project.yml. RETURNS (List[Dict[str, str]]): The lockfile entry for a file. """ data = [] for path in paths: - path = path.format(**variables) file_path = project_dir / path md5 = get_checksum(file_path) if file_path.exists() else None data.append({"path": path, "md5": md5}) diff --git a/spacy/schemas.py b/spacy/schemas.py index 3eef814c6..170342b54 100644 --- a/spacy/schemas.py +++ b/spacy/schemas.py @@ -303,7 +303,7 @@ class ProjectConfigCommand(BaseModel): class ProjectConfigSchema(BaseModel): # fmt: off - variables: Dict[StrictStr, Union[str, int, float, bool]] = Field({}, title="Optional variables to substitute in commands") + vars: Dict[StrictStr, Any] = Field({}, title="Optional variables to substitute in commands") assets: List[ProjectConfigAsset] = Field([], title="Data assets") workflows: Dict[StrictStr, List[StrictStr]] = Field({}, title="Named workflows, mapped to list of project commands to run in order") commands: List[ProjectConfigCommand] = Field([], title="Project command shortucts") diff --git a/spacy/tests/test_cli.py b/spacy/tests/test_cli.py index 89ce740e0..104c7c516 100644 --- a/spacy/tests/test_cli.py +++ b/spacy/tests/test_cli.py @@ -6,9 +6,12 @@ from spacy.schemas import ProjectConfigSchema, RecommendationSchema, validate from spacy.cli.pretrain import make_docs from spacy.cli.init_config import init_config, RECOMMENDATIONS from spacy.cli._util import validate_project_commands, parse_config_overrides -from spacy.util import get_lang_class +from spacy.cli._util import load_project_config, substitute_project_variables +from thinc.config import ConfigValidationError import srsly +from .util import make_tempdir + def test_cli_converters_conllu2json(): # from NorNE: https://github.com/ltgoslo/norne/blob/3d23274965f513f23aa48455b28b1878dad23c05/ud/nob/no_bokmaal-ud-dev.conllu @@ -295,6 +298,24 @@ def test_project_config_validation2(config, n_errors): assert len(errors) == n_errors +def test_project_config_interpolation(): + variables = {"a": 10, "b": {"c": "foo", "d": True}} + commands = [ + {"name": "x", "script": ["hello ${vars.a} ${vars.b.c}"]}, + {"name": "y", "script": ["${vars.b.c} ${vars.b.d}"]}, + ] + project = {"commands": commands, "vars": variables} + with make_tempdir() as d: + srsly.write_yaml(d / "project.yml", project) + cfg = load_project_config(d) + assert cfg["commands"][0]["script"][0] == "hello 10 foo" + assert cfg["commands"][1]["script"][0] == "foo true" + commands = [{"name": "x", "script": ["hello ${vars.a} ${vars.b.e}"]}] + project = {"commands": commands, "vars": variables} + with pytest.raises(ConfigValidationError): + substitute_project_variables(project) + + @pytest.mark.parametrize( "args,expected", [ diff --git a/spacy/util.py b/spacy/util.py index 5eff82866..736f4d805 100644 --- a/spacy/util.py +++ b/spacy/util.py @@ -1,5 +1,5 @@ from typing import List, Union, Dict, Any, Optional, Iterable, Callable, Tuple -from typing import Iterator, Type, Pattern, TYPE_CHECKING +from typing import Iterator, Type, Pattern, Generator, TYPE_CHECKING from types import ModuleType import os import importlib @@ -610,7 +610,7 @@ def working_dir(path: Union[str, Path]) -> None: @contextmanager -def make_tempdir() -> None: +def make_tempdir() -> Generator[Path, None, None]: """Execute a block in a temporary directory and remove the directory and its contents at the end of the with block. diff --git a/website/docs/api/cli.md b/website/docs/api/cli.md index 551147929..7ce95c019 100644 --- a/website/docs/api/cli.md +++ b/website/docs/api/cli.md @@ -847,6 +847,92 @@ $ python -m spacy project run [subcommand] [project_dir] [--force] [--dry] | `--help`, `-h` | Show help message and available arguments. ~~bool (flag)~~ | | **EXECUTES** | The command defined in the `project.yml`. | +### project push {#project-push tag="command"} + +Upload all available files or directories listed as in the `outputs` section of +commands to a remote storage. Outputs are archived and compressed prior to +upload, and addressed in the remote storage using the output's relative path +(URL encoded), a hash of its command string and dependencies, and a hash of its +file contents. This means `push` should **never overwrite** a file in your +remote. If all the hashes match, the contents are the same and nothing happens. +If the contents are different, the new version of the file is uploaded. Deleting +obsolete files is left up to you. + +Remotes can be defined in the `remotes` section of the +[`project.yml`](/usage/projects#project-yml). Under the hood, spaCy uses the +[`smart-open`](https://github.com/RaRe-Technologies/smart_open) library to +communicate with the remote storages, so you can use any protocol that +`smart-open` supports, including [S3](https://aws.amazon.com/s3/), +[Google Cloud Storage](https://cloud.google.com/storage), SSH and more, although +you may need to install extra dependencies to use certain protocols. + +```cli +$ python -m spacy project push [remote] [project_dir] +``` + +> #### Example +> +> ```cli +> $ python -m spacy project push my_bucket +> ``` +> +> ```yaml +> ### project.yml +> remotes: +> my_bucket: 's3://my-spacy-bucket' +> ``` + +| Name | Description | +| -------------- | --------------------------------------------------------------------------------------- | +| `remote` | The name of the remote to upload to. Defaults to `"default"`. ~~str (positional)~~ | +| `project_dir` | Path to project directory. Defaults to current working directory. ~~Path (positional)~~ | +| `--help`, `-h` | Show help message and available arguments. ~~bool (flag)~~ | +| **UPLOADS** | All project outputs that exist and are not already stored in the remote. | + +### project pull {#project-pull tag="command"} + +Download all files or directories listed as `outputs` for commands, unless they +are not already present locally. When searching for files in the remote, `pull` +won't just look at the output path, but will also consider the **command +string** and the **hashes of the dependencies**. For instance, let's say you've +previously pushed a model checkpoint to the remote, but now you've changed some +hyper-parameters. Because you've changed the inputs to the command, if you run +`pull`, you won't retrieve the stale result. If you train your model and push +the outputs to the remote, the outputs will be saved alongside the prior +outputs, so if you change the config back, you'll be able to fetch back the +result. + +Remotes can be defined in the `remotes` section of the +[`project.yml`](/usage/projects#project-yml). Under the hood, spaCy uses the +[`smart-open`](https://github.com/RaRe-Technologies/smart_open) library to +communicate with the remote storages, so you can use any protocol that +`smart-open` supports, including [S3](https://aws.amazon.com/s3/), +[Google Cloud Storage](https://cloud.google.com/storage), SSH and more, although +you may need to install extra dependencies to use certain protocols. + +```cli +$ python -m spacy project pull [remote] [project_dir] +``` + +> #### Example +> +> ```cli +> $ python -m spacy project pull my_bucket +> ``` +> +> ```yaml +> ### project.yml +> remotes: +> my_bucket: 's3://my-spacy-bucket' +> ``` + +| Name | Description | +| -------------- | --------------------------------------------------------------------------------------- | +| `remote` | The name of the remote to download from. Defaults to `"default"`. ~~str (positional)~~ | +| `project_dir` | Path to project directory. Defaults to current working directory. ~~Path (positional)~~ | +| `--help`, `-h` | Show help message and available arguments. ~~bool (flag)~~ | +| **DOWNLOADS** | All project outputs that do not exist locally and can be found in the remote. | + ### project dvc {#project-dvc tag="command"} Auto-generate [Data Version Control](https://dvc.org) (DVC) config file. Calls diff --git a/website/docs/images/projects.svg b/website/docs/images/projects.svg new file mode 100644 index 000000000..8de5f9ef6 --- /dev/null +++ b/website/docs/images/projects.svg @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/website/docs/usage/projects.md b/website/docs/usage/projects.md index 30e4394d1..1aaaeb3af 100644 --- a/website/docs/usage/projects.md +++ b/website/docs/usage/projects.md @@ -5,9 +5,12 @@ menu: - ['Intro & Workflow', 'intro'] - ['Directory & Assets', 'directory'] - ['Custom Projects', 'custom'] + - ['Remote Storage', 'remote'] - ['Integrations', 'integrations'] --- +## Introduction and workflow {#intro hidden="true"} + > #### πŸͺ Project templates > > Our [`projects`](https://github.com/explosion/projects) repo includes various @@ -19,20 +22,17 @@ spaCy projects let you manage and share **end-to-end spaCy workflows** for different **use cases and domains**, and orchestrate training, packaging and serving your custom models. You can start off by cloning a pre-defined project template, adjust it to fit your needs, load in your data, train a model, export -it as a Python package and share the project templates with your team. spaCy -projects can be used via the new [`spacy project`](/api/cli#project) command. -For an overview of the available project templates, check out the -[`projects`](https://github.com/explosion/projects) repo. spaCy projects also -[integrate](#integrations) with many other cool machine learning and data -science tools to track and manage your data and experiments, iterate on demos -and prototypes and ship your models into production. +it as a Python package, upload your outputs to a remote storage and share your +results with your team. spaCy projects can be used via the new +[`spacy project`](/api/cli#project) command and we provide templates in our +[`projects`](https://github.com/explosion/projects) repo. -## Introduction and workflow {#intro} - +![Illustration of project workflow and commands](../images/projects.svg) + ```yaml ### project.yml -variables: - BATCH_SIZE: 128 +vars: + batch_size: 128 commands: - name: evaluate script: - - 'python scripts/custom_evaluation.py {BATCH_SIZE} ./training/model-best ./corpus/eval.json' + - 'python scripts/custom_evaluation.py ${batch_size} ./training/model-best ./corpus/eval.json' deps: - 'training/model-best' - 'corpus/eval.json' @@ -421,6 +446,114 @@ assets: checksum: '5113dc04e03f079525edd8df3f4f39e3' ``` +## Remote Storage {#remote} + +You can persist your project outputs to a remote storage using the +[`project push`](/api/cli#project-push) command. This can help you **export** +your model packages, **share** work with your team, or **cache results** to +avoid repeating work. The [`project pull`](/api/cli#project-pull) command will +download any outputs that are in the remote storage and aren't available +locally. + +You can list one or more remotes in the `remotes` section of your +[`project.yml`](#project-yml) by mapping a string name to the URL of the +storage. Under the hood, spaCy uses the +[`smart-open`](https://github.com/RaRe-Technologies/smart_open) library to +communicate with the remote storages, so you can use any protocol that +`smart-open` supports, including [S3](https://aws.amazon.com/s3/), +[Google Cloud Storage](https://cloud.google.com/storage), SSH and more, although +you may need to install extra dependencies to use certain protocols. + +> #### Example +> +> ```cli +> $ python -m spacy project pull local +> ``` + +```yaml +### project.yml +remotes: + default: 's3://my-spacy-bucket' + local: '/mnt/scratch/cache' + stuff: 'ssh://myserver.example.com/whatever' +``` + + + +Inside the remote storage, spaCy uses a clever **directory structure** to avoid +overwriting files. The top level of the directory structure is a URL-encoded +version of the output's path. Within this directory are subdirectories named +according to a hash of the command string and the command's dependencies. +Finally, within those directories are files, named according to an MD5 hash of +their contents. + + + + +```yaml +└── urlencoded_file_path # Path of original file + β”œβ”€β”€ some_command_hash # Hash of command you ran + β”‚ β”œβ”€β”€ some_content_hash # Hash of file content + β”‚ └── another_content_hash + └── another_command_hash + └── third_content_hash +``` + + + +For instance, let's say you had the following command in your `project.yml`: + +```yaml +### project.yml +- name: train + help: 'Train a spaCy model using the specified corpus and config' + script: + - 'spacy train ./config.cfg --output training/' + deps: + - 'corpus/train' + - 'corpus/dev' + - 'config.cfg' + outputs: + - 'training/model-best' +``` + +> #### Example +> +> ``` +> └── s3://my-spacy-bucket/training%2Fmodel-best +> └── 1d8cb33a06cc345ad3761c6050934a1b +> └── d8e20c3537a084c5c10d95899fe0b1ff +> ``` + +After you finish training, you run [`project push`](/api/cli#project-push) to +make sure the `training/model-best` output is saved to remote storage. spaCy +will then construct a hash from your command script and the listed dependencies, +`corpus/train`, `corpus/dev` and `config.cfg`, in order to identify the +execution context of your output. It would then compute an MD5 hash of the +`training/model-best` directory, and use those three pieces of information to +construct the storage URL. + +```cli +$ python -m spacy project run train +$ python -m spacy project push +``` + +If you change the command or one of its dependencies (for instance, by editing +the [`config.cfg`](/usage/training#config) file to tune the hyperparameters, a +different creation hash will be calculated, so when you use +[`project push`](/api/cli#project-push) you won't be overwriting your previous +file. The system even supports multiple outputs for the same file and the same +context, which can happen if your training process is not deterministic, or if +you have dependencies that aren't represented in the command. + +In summary, the [`spacy project`](/api/cli#project) remote storages are designed +to make a particular set of trade-offs. Priority is placed on **convenience**, +**correctness** and **avoiding data loss**. You can use +[`project push`](/api/cli#project-push) freely, as you'll never overwrite remote +state, and you don't have to come up with names or version numbers. However, +it's up to you to manage the size of your remote storage, and to remove files +that are no longer relevant to you. + ## Integrations {#integrations} ### Data Version Control (DVC) {#dvc} @@ -517,16 +650,17 @@ and evaluation set. ```yaml ### project.yml -variables: - PRODIGY_DATASET: 'ner_articles' - PRODIGY_LABELS: 'PERSON,ORG,PRODUCT' - PRODIGY_MODEL: 'en_core_web_md' +vars: + prodigy: + dataset: 'ner_articles' + labels: 'PERSON,ORG,PRODUCT' + model: 'en_core_web_md' commands: - name: annotate - script: - - 'python -m prodigy ner.correct {PRODIGY_DATASET} ./assets/raw_data.jsonl {PRODIGY_MODEL} --labels {PRODIGY_LABELS}' - - 'python -m prodigy data-to-spacy ./corpus/train.json ./corpus/eval.json --ner {PRODIGY_DATASET}' + - 'python -m prodigy ner.correct ${vars.prodigy.dataset} ./assets/raw_data.jsonl ${vars.prodigy.model} --labels ${vars.prodigy.labels}' + - 'python -m prodigy data-to-spacy ./corpus/train.json ./corpus/eval.json --ner ${vars.prodigy.dataset}' - 'python -m spacy convert ./corpus/train.json ./corpus/train.spacy' - 'python -m spacy convert ./corpus/eval.json ./corpus/eval.spacy' - deps: diff --git a/website/docs/usage/v3.md b/website/docs/usage/v3.md index aea1d892c..2a47fd264 100644 --- a/website/docs/usage/v3.md +++ b/website/docs/usage/v3.md @@ -104,11 +104,15 @@ spaCy projects let you manage and share **end-to-end spaCy workflows** for different **use cases and domains**, and orchestrate training, packaging and serving your custom models. You can start off by cloning a pre-defined project template, adjust it to fit your needs, load in your data, train a model, export -it as a Python package and share the project templates with your team. spaCy -projects also make it easy to **integrate with other tools** in the data science -and machine learning ecosystem, including [DVC](/usage/projects#dvc) for data -version control, [Prodigy](/usage/projects#prodigy) for creating labelled data, -[Streamlit](/usage/projects#streamlit) for building interactive apps, +it as a Python package, upload your outputs to a remote storage and share your +results with your team. + +![Illustration of project workflow and commands](../images/projects.svg) + +spaCy projects also make it easy to **integrate with other tools** in the data +science and machine learning ecosystem, including [DVC](/usage/projects#dvc) for +data version control, [Prodigy](/usage/projects#prodigy) for creating labelled +data, [Streamlit](/usage/projects#streamlit) for building interactive apps, [FastAPI](/usage/projects#fastapi) for serving models in production, [Ray](/usage/projects#ray) for parallel training, [Weights & Biases](/usage/projects#wandb) for experiment tracking, and more! diff --git a/website/src/components/table.js b/website/src/components/table.js index 3f41a587b..bd3d663f3 100644 --- a/website/src/components/table.js +++ b/website/src/components/table.js @@ -5,6 +5,8 @@ import Icon from './icon' import { isString } from './util' import classes from '../styles/table.module.sass' +const FOOT_ROW_REGEX = /^(RETURNS|YIELDS|CREATES|PRINTS|EXECUTES|UPLOADS|DOWNLOADS)/ + function isNum(children) { return isString(children) && /^\d+[.,]?[\dx]+?(|x|ms|mb|gb|k|m)?$/i.test(children) } @@ -43,7 +45,6 @@ function isDividerRow(children) { } function isFootRow(children) { - const rowRegex = /^(RETURNS|YIELDS|CREATES|PRINTS|EXECUTES)/ if (children.length && children[0].props.name === 'td') { const cellChildren = children[0].props.children if ( @@ -52,7 +53,7 @@ function isFootRow(children) { cellChildren.props.children && isString(cellChildren.props.children) ) { - return rowRegex.test(cellChildren.props.children) + return FOOT_ROW_REGEX.test(cellChildren.props.children) } } return false