-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for different recipes #10641
Changes from 68 commits
78fc387
661342c
4554cc2
561b282
890812b
e883752
08da835
f78b775
4b8d17a
4d1288a
3f8f471
d967bc2
9332d63
495fc49
3306db5
a057cdc
fc19f83
df2098e
c44ea8c
248d0ea
1b25fa3
1ddc9be
bcb659c
ef42783
3716a7d
a1fa40a
ae9f5e5
49ce5d6
2293bca
ea70d41
47683f7
2ef1118
8e2568a
f20c898
3e93547
154056f
875a17d
22e6e2c
b6b3427
dec37e0
5ac4b08
d4c8836
f44e014
ef6ce21
1f67c2f
b5fde26
5330be7
f79c756
83ae794
3c15a3a
74ab4b2
ad49502
094b49b
1f53e10
de72159
fc66008
7368dd1
8304754
f8ec9da
1b9954a
cb454dd
fa43bac
249a046
1d3dc70
8e631e3
495fb46
e5fa3ca
2b5af0f
fb9479b
2bc6fe5
9c771c8
b43566f
998da42
3a491d4
16a4c24
fa1c2eb
5efdb50
b978569
506f130
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
Support other recipe types. | ||
|
||
This pull request also adds support for graph recipes, see details at | ||
https://rasa.com/docs/rasa/model-configuration check Graph Recipes section. | ||
|
||
Graph recipe is a raw format for specifying executed graph directly. This is | ||
useful if you need a more powerful way to specify your model creation. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
nodes: | ||
nlu_message_converter: | ||
needs: | ||
messages: __message__ | ||
uses: rasa.graph_components.converters.nlu_message_converter.NLUMessageConverter | ||
constructor_name: load | ||
fn: convert_user_message | ||
config: {} | ||
eager: true | ||
is_target: false | ||
is_input: false | ||
resource: null | ||
custom_nlu_target: | ||
needs: | ||
messages: nlu_message_converter | ||
domain: domain_provider | ||
uses: rasa.nlu.classifiers.regex_message_handler.RegexMessageHandler | ||
constructor_name: load | ||
fn: process | ||
config: {} | ||
eager: true | ||
is_target: false | ||
is_input: false | ||
resource: null | ||
domain_provider: | ||
needs: {} | ||
uses: rasa.graph_components.providers.domain_provider.DomainProvider | ||
constructor_name: load | ||
fn: provide_inference | ||
config: {} | ||
eager: true | ||
is_target: false | ||
is_input: false | ||
resource: | ||
name: domain_provider | ||
run_MemoizationPolicy0: | ||
needs: | ||
domain: domain_provider | ||
tracker: __tracker__ | ||
rule_only_data: rule_only_data_provider | ||
uses: rasa.core.policies.memoization.MemoizationPolicy | ||
constructor_name: load | ||
fn: predict_action_probabilities | ||
config: {} | ||
eager: true | ||
is_target: false | ||
is_input: false | ||
resource: | ||
name: train_MemoizationPolicy0 | ||
rule_only_data_provider: | ||
needs: {} | ||
uses: rasa.graph_components.providers.rule_only_provider.RuleOnlyDataProvider | ||
constructor_name: load | ||
fn: provide | ||
config: {} | ||
eager: true | ||
is_target: false | ||
is_input: false | ||
resource: | ||
name: train_RulePolicy1 | ||
custom_core_target: | ||
needs: | ||
policy0: run_MemoizationPolicy0 | ||
domain: domain_provider | ||
tracker: __tracker__ | ||
uses: rasa.core.policies.ensemble.DefaultPolicyPredictionEnsemble | ||
constructor_name: load | ||
fn: combine_predictions_from_kwargs | ||
config: {} | ||
eager: true | ||
is_target: false | ||
is_input: false | ||
resource: null |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
nodes: | ||
finetuning_validator: | ||
needs: | ||
importer: __importer__ | ||
uses: rasa.graph_components.validators.finetuning_validator.FinetuningValidator | ||
constructor_name: create | ||
fn: validate | ||
config: | ||
validate_core: true | ||
validate_nlu: true | ||
eager: false | ||
is_target: false | ||
is_input: true | ||
resource: null | ||
nlu_training_data_provider: | ||
needs: | ||
importer: finetuning_validator | ||
uses: rasa.graph_components.providers.nlu_training_data_provider.NLUTrainingDataProvider | ||
constructor_name: create | ||
fn: provide | ||
config: | ||
language: en | ||
persist: false | ||
eager: false | ||
is_target: false | ||
is_input: true | ||
resource: null |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
# The config recipe. | ||
# https://rasa.com/docs/rasa/model-configuration/ | ||
recipe: graph.v1 | ||
|
||
language: en | ||
|
||
core_target: custom_core_target | ||
|
||
nlu_target: custom_nlu_target | ||
|
||
train_schema: | ||
nodes: | ||
# We skip schema_validator node (we only have this for DefaultV1Recipe | ||
# since we don't do validation for the GraphV1Recipe) | ||
finetuning_validator: | ||
needs: | ||
importer: __importer__ | ||
uses: rasa.graph_components.validators.finetuning_validator.FinetuningValidator | ||
constructor_name: create | ||
fn: validate | ||
config: | ||
validate_core: true | ||
validate_nlu: true | ||
eager: false | ||
is_target: false | ||
is_input: true | ||
resource: null | ||
nlu_training_data_provider: | ||
needs: | ||
importer: finetuning_validator | ||
uses: rasa.graph_components.providers.nlu_training_data_provider.NLUTrainingDataProvider | ||
constructor_name: create | ||
fn: provide | ||
config: | ||
language: en | ||
persist: false | ||
eager: false | ||
is_target: false | ||
is_input: true | ||
resource: null | ||
|
||
predict_schema: | ||
nodes: | ||
nlu_message_converter: | ||
needs: | ||
messages: __message__ | ||
uses: rasa.graph_components.converters.nlu_message_converter.NLUMessageConverter | ||
constructor_name: load | ||
fn: convert_user_message | ||
config: {} | ||
eager: true | ||
is_target: false | ||
is_input: false | ||
resource: null | ||
custom_nlu_target: | ||
needs: | ||
messages: nlu_message_converter | ||
domain: domain_provider | ||
uses: rasa.nlu.classifiers.regex_message_handler.RegexMessageHandler | ||
constructor_name: load | ||
fn: process | ||
config: {} | ||
eager: true | ||
is_target: false | ||
is_input: false | ||
resource: null | ||
domain_provider: | ||
needs: {} | ||
uses: rasa.graph_components.providers.domain_provider.DomainProvider | ||
constructor_name: load | ||
fn: provide_inference | ||
config: {} | ||
eager: true | ||
is_target: false | ||
is_input: false | ||
resource: | ||
name: domain_provider | ||
run_MemoizationPolicy0: | ||
needs: | ||
domain: domain_provider | ||
tracker: __tracker__ | ||
rule_only_data: rule_only_data_provider | ||
uses: rasa.core.policies.memoization.MemoizationPolicy | ||
constructor_name: load | ||
fn: predict_action_probabilities | ||
config: {} | ||
eager: true | ||
is_target: false | ||
is_input: false | ||
resource: | ||
name: train_MemoizationPolicy0 | ||
rule_only_data_provider: | ||
needs: {} | ||
uses: rasa.graph_components.providers.rule_only_provider.RuleOnlyDataProvider | ||
constructor_name: load | ||
fn: provide | ||
config: {} | ||
eager: true | ||
is_target: false | ||
is_input: false | ||
resource: | ||
name: train_RulePolicy1 | ||
custom_core_target: | ||
needs: | ||
policy0: run_MemoizationPolicy0 | ||
domain: domain_provider | ||
tracker: __tracker__ | ||
uses: rasa.core.policies.ensemble.DefaultPolicyPredictionEnsemble | ||
constructor_name: load | ||
fn: combine_predictions_from_kwargs | ||
config: {} | ||
eager: true | ||
is_target: false | ||
is_input: false | ||
resource: null |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -228,7 +228,7 @@ Your graph component's train method must return the value of `resource` so that | |
the training results between trainings. | ||
The `self._model_storage.write_to(self._resource)` context manager provides a path to | ||
a directory where you can persist any data required by your | ||
graph component. | ||
graph component. | ||
|
||
```python | ||
from __future__ import annotations | ||
|
@@ -328,16 +328,16 @@ class MyComponent(GraphComponent): | |
|
||
|
||
## Registering Graph Components with the Model Configuration | ||
To make your graph component available to Rasa Open Source you have to register your | ||
To make your graph component available to Rasa Open Source you may have to register your | ||
graph component with a recipe. Rasa Open Source uses recipes to translate the content | ||
of your model configuration to executable | ||
[graphs](custom-graph-components.mdx#graph-components). | ||
Currently, Rasa Open Source only supports the `default.v1` recipe. | ||
Register your graph component with this recipe by using the `DefaultV1Recipe.register` | ||
Currently, Rasa Open Source supports the `default.v1` and the experimental `graph.v1` recipes. | ||
For `default.v1` recipe, you need to register your graph component by using the `DefaultV1Recipe.register` | ||
decorator: | ||
|
||
:::code language="python" source="docs/sources/data/test_classes/registered_component.py" | ||
highlight="5-9"::: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was failing in current documents so I fixed it. |
||
```python (docs/sources/data/test_classes/registered_component.py) | ||
``` | ||
|
||
Rasa Open Source uses the information provided in the `register` decorator and the | ||
position of your graph component within the configuration file to schedule the execution | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
--- | ||
id: graph-recipe | ||
sidebar_label: Graph Recipe | ||
title: Graph Recipe | ||
description: Learn about Graph Recipe for Rasa Open Source. | ||
abstract: Graph recipes provide a more fine tuned configuration for your executable graphs. | ||
--- | ||
|
||
:::tip Default Recipe or Graph Recipe? | ||
|
||
You will probably only need graph recipes if you're running ML experiments or ablation studies on an existing model. We recommend starting with the default recipe and for many applications that will be all that's needed. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "ablation studies" feels a bit specific? (I had to google it 😁 ) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've used the exact wording from @rctatman actually and I had to google it too :D I think it is good because it has the effect of warning against using graph recipes if the user is not too advanced. |
||
|
||
::: | ||
|
||
We now support graph recipes in addition to the default recipe. Graph recipes provide more granular control over how execution graph schemas are built. | ||
|
||
:::caution New in 3.1 | ||
This feature is experimental. | ||
We introduce experimental features to get feedback from our community, so we encourage you to try it out! | ||
However, the functionality might be changed or removed in the future. | ||
If you have feedback (positive or negative) please share it with us on the [Rasa Forum](https://forum.rasa.com). | ||
|
||
::: | ||
|
||
|
||
## Differences with Default Recipe | ||
|
||
There are some differences between the default recipe and the new graph recipe. Main differences are: | ||
|
||
- Default recipe is named `default.v1` in the config file whereas graph recipes are named `graph.v1`. | ||
- Default recipes provide an easy to use recipe structure whereas graph recipes are more advanced and powerful. | ||
- Default recipes are very opinionated and provide various defaults whereas graph recipes are more explicit. | ||
- Default recipes can auto-configure themselves and dump the defaults used to the file if some sections in `config.yml` are missing, whereas graph recipes do none of this and assume what you see is what you get. There are no surprises with graph recipes. | ||
- Default recipe divides graph configuration into mainly two parts: `pipeline` and `policies`. These can also be described as NLU and core (dialogue management) parts. For graph recipe on the other hand, the separation is between training (ie. `train_schema`) and prediction (ie. `predict_schema`). | ||
|
||
:::tip Starting from scratch? | ||
|
||
If you don't know which recipe to choose, use the default recipe to bootstrap your project fast. If later you find that you need more powerful fine-tuning options, you can always change your recipe to be a graph recipe. | ||
tayfun marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
::: | ||
|
||
## Graph Configuration File Structure | ||
|
||
Graph recipes share `recipe` and `language` keys with the same meaning. Similarities end there as graph recipes do not have `pipeline` or `policies` keys but they do have `train_schema` and `predict_schema` keys for determining the graph nodes during train and predict runs respectively. In addition to this, target nodes for NLU and core can be specified explicitly with graph recipes, these can be declared with `nlu_target` and `core_target`. If targets are omitted, node names used by default recipe will take over, and these are `run_RegexMessageHandler` and `select_prediction` for nlu and core respectively. | ||
|
||
Here's an example graph recipe: | ||
|
||
```yaml-rasa (docs/sources/data/test_config/graph_config_short.yml) | ||
``` | ||
|
||
:::note graph targets | ||
For NLU, default target name of `run_RegexMessageHandler` will be used, while for core (dialogue management) the target will be called `select_prediction` if omitted. Make sure you have graph nodes with relevant names in your schema definitions. | ||
|
||
In a similar fashion, note that the default resource needed by the first graph node is fixed to be `__importer__` (representing configuration, training data etc.) for training task and it is `__message__` (representing the message received) for prediction task. Make sure your first nodes make use of these dependencies. | ||
|
||
::: | ||
|
||
## Graph Node Configuration | ||
|
||
As you can see in the example above, graph recipes are very much explicit and you can configure each graph node as you would like. Here is an explanation of what some of the keys mean: | ||
|
||
- `needs`: You can define here what data your graph node requires and from which parent node. Key is the data name, whereas the value would refer to the node name. | ||
```yaml-rasa | ||
needs: | ||
messages: nlu_message_converter | ||
``` | ||
Current graph node needs `messages` which is provided by `nlu_message_converter` node. | ||
|
||
- `uses`: You can provide the class used to instantiate this node with this key. Please provide the full path in Python path syntax, eg. | ||
|
||
```yaml-rasa | ||
uses: rasa.graph_components.converters.nlu_message_converter.NLUMessageConverter | ||
``` | ||
You are not required to use Rasa internal graph component classes and you | ||
can use your own components here. Refer to [custom graph | ||
components](custom-graph-components.mdx) pages to find out how to write your | ||
own graph components. | ||
|
||
- `constructor_name`: This is the constructor used to instantiate your component. Example: | ||
|
||
```yaml-rasa | ||
constructor_name: load | ||
``` | ||
|
||
- `fn`: This is the function used in executing the graph component. Example: | ||
|
||
```yaml-rasa | ||
fn: combine_predictions_from_kwargs | ||
``` | ||
|
||
- `config`: You can provide any configuration parameters for your components using this key. | ||
|
||
```yaml-rasa | ||
config: | ||
language: en | ||
persist: false | ||
``` | ||
|
||
- `eager`: This determines if your component should be eagerly loaded | ||
when the graph is constructed or if it should wait until the | ||
runtime (this is called lazy instantiation). Usually we always | ||
instantiate lazily during training and eagerly during inference (to | ||
avoid slow first prediction). | ||
|
||
|
||
```yaml-rasa | ||
eager: true | ||
``` | ||
|
||
- `resource`: If given, graph node is loaded from this resource instead of of instantiated from scratch. This is e.g. used to load a trained component for predictions. | ||
|
||
```yaml-rasa | ||
resource: | ||
name: train_RulePolicy1 | ||
``` | ||
|
||
- `is_target`: Boolean value, if `True` then this node can't be pruned | ||
during fingerprinting (it might be replaced with a cached value | ||
though). This | ||
is e.g. used for all components which train as their result always needs | ||
to be added to the model archive so that the data is available during | ||
inference. | ||
|
||
```yaml-rasa | ||
is_target: false | ||
``` | ||
|
||
- `is_input`: Boolean value; nodes with `is_input` are _always_ run (also during the | ||
fingerprint run). This makes sure that we e.g. detect changes in file | ||
contents. | ||
|
||
```yaml-rasa | ||
is_input: false | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess you can use an anchor link to go directly to that section?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a new page not an anchor and I can't link to it because it's not live yet, docs check fails with dead link :D