Go into skills and copy paste the dff_template_skill
folder. Remember that the correct naming is very important, so you should give your folder a clear name so that others could see the name and understand the main idea of your skill. An example of a clear name is dff_get_book_information_skill
. In this folder replace all mentions of dff_template_skill
with the name of your skill.
You should then go to assistant_dists/distribution_name/docker-compose.override.yml
, find WAIT_HOSTS
,and add your skill and a port which is not taken. Thus, if you are working with the main Dream distribution, you go to assistant_dists/dream/docker-compose.override.yml, and add dff-your-name-skill:port
to WAIT_HOSTS.
Make sure you add your skill right before dff-template-skill:8120
.Notice that here we use dash instead of underscore (and in the future you should always pay attention to whether it is needed to use dash or underscore, such extra attention will definitely save you from unexpected bugs). The thing is, underscores are used in skills’ names which in turn are used in Python code to refer to the Dialog State. Docker containers, meanwhile, are named using dashes.
At the end of the same file find configuration of dff-template-skill
:
dff-template-skill:
env_file: [.env]
build:
args:
SERVICE_PORT: 8120
SERVICE_NAME: dff_template_skill
context: .
dockerfile: ./skills/dff_template_skill/Dockerfile
command: gunicorn --workers=1 server:app -b 0.0.0.0:8120 --reload
deploy:
resources:
limits:
memory: 128M
reservations:
memory: 128M
Copy and paste. Then:
If you are going to use some big models in your skill, you can also change memory: memory in limits is the maximum memory that can be used by your skill before it’s killed, memory in reservations is the amount of memory that needs to be reserved for your skill.
Go to assistant_dists/distribution_name/dev.yml
, find dff-template-skill
, and copy-paste it (remember that we always paste it right before dff-template-skill
):
dff-template-skill:
volumes:
- "./skills/dff_template_skill:/src"
- "./common:/src/common"
ports:
- 8120:8120
Change both dff-template-skill
and dff_template_skill
and don’t forget about ports.
Now go to assistant_dists/distribution_name/pipeline_conf.json
, copy-paste:
"dff_template_skill": {
"connector": {
"protocol": "http",
"timeout": 2,
"url": "http://dff-template-skill:8120/respond"
},
"dialog_formatter": "state_formatters.dp_formatters:dff_template_skill_formatter",
"response_formatter": "state_formatters.dp_formatters:skill_with_attributes_formatter_service",
"previous_services": [
"skill_selectors"
],
"state_manager_method": "add_hypothesis"
}
Then change the name URL (both name and port), dff_template_skill
in dialog_formatter
.
Go to state_formatters/dp_formatters.py
, copy dff_template_skill_formatter, paste it, rename according to your skill (like in the previous step), and change the skill name in return.
def dff_template_skill_formatter(dialog: Dict) -> List[Dict]:
return utils.dff_formatter(dialog, "dff_template_skill")
Skill-Selector
needs to know when to include your skill in the list of skills that can provide the next response of the bot. There are three options:
skill_selectors/rule_based_selector/connector.py
and add your skill name into skills_for_uttr.templates/regexes/entities/detected topics
:skill_selectors/rule_based_selector/connector.py
, add the name of your skill to the list of available skills. To add patterns that will trigger your skill you have to go to common folder, and addcommon/movies.py
contains:MOVIE_COMPILED_PATTERN = re.compile(
r"(movie|film|picture|series|tv[ -]?show|reality[ -]?show|netflix|\btv\b|"
r"comedy|comedies|thriller|animation|anime|talk[ -]?show|cartoon|drama|"
r"fantasy|watch\b|watching\b|watched\b|youtube|\byou tube\b)",
re.IGNORECASE,
)
In the future if you need to add any custom functions connected to your skill, it is a good idea to code them in the same file. Now in the same folder (common
) you can find skills_turn_on_topics_and_patterns.py
,and here you can import the templates that you’ve added and add your skill name and its triggers into SKILL_TRIGGERS
, for example:
"dff_movie_skill": {
"compiled_patterns": [MOVIE_COMPILED_PATTERN],
"previous_bot_patterns": [MOVIE_COMPILED_PATTERN],
"detected_topics": [
"Entertainment_Movies",
"Entertainment_General",
"Movies_TV",
"Celebrities",
"Art_Event",
"Entertainment",
"Fashion",
],
"intents": [],
},
skill_selectors/rule_based_selector/connector.py
add conditions for including your skill to the skills_for_uttr
list.Now it’s time to code your skill. Go to you skill folder, open scenario, and here you can see:
main.py
– here you can code your skill using Dialog Flow Framework (DFF). In DFF a dialog is represented as a graph with nodes corresponding to bot responses, where we can specify the text of bot response, the processing functions needed (e.g., slot-filling), and the conditions for transitioning to other nodes.condition.py
– for your custom conditions that you want to use to move between nodes.processing.py
– for your custom functions for processing of utterances.response.py
– for you custom functions you want to use when providing a response.When the scenario of your skill is ready, go to server.py
in your skill folder. In order to create test configs, uncomment three lines in respond function, and make sure that the line that activates test is commented.
Now you need to talk with your skill, so you have to build the bot with needed distribution:
docker-compose -f docker-compose.yml -f assistant_dists/dream/docker-compose.override.yml -f assistant_dists/dream/dev.yml -f assistant_dists/dream/proxy.yml up --build
This command will NOT build all Dream services locally, because they can be accessed via proxy, so the only service that will be built locally is your skill. Remember to change dream to another distribution if needed. When the bot is up, you can talk to it. In a separate terminal tab run:
docker-compose exec agent python -m deeppavlov_agent.run agent.channel=cmd agent.pipeline_config=assistant_dists/dream/pipeline_conf.json
Now chat with your skill. Each turn information that bot receives is saved into tests folder in *_in.json
file, and the information about the bot’s answer is saved in *_out.json
. These files are overwritten after each turn. It’s better to think of several cases you want to test, just name files differently (test_1_in
,test_2_in
, etc.) If your skill works fine, you can stop chatting and comment those three lines. If something is wrong, you can fix it and then try chatting again.
Let’s suppose everything is fine and now you have both *_in.json
file with user’s requests and *_out.json
with expected bot’s answers. Now you can uncomment this line to activate tests. Tests are run each time you build skill, even when you build it without the rest of the bot. Don’t forget to comment the line that activates the skill when you change the skill, and remember to rewrite tests when the changes are done.
docker-compose -f docker-compose.yml -f assistant_dists/dream/docker-compose.override.yml -f assistant_dists/dream/dev.yml up --build dff-your-skill
docker-compose -f docker-compose.yml -f assistant_dists/dream/docker-compose.override.yml -f assistant_dists/dream/dev.yml logs -f dff-your-skill
docker-compose -f docker-compose.yml -f assistant_dists/dream/docker-compose.override.yml -f assistant_dists/dream/dev.yml restart dff-your-skill