how to handle rasa form confirmation or denying from actions.py - rasa-core

based on the story below:
## certif deny_repeat_affirm_stop
* greet
- utter_greet
* request_certificate
- certificate_form
- form{"name": "certificate_form"}
- form{"name": null}
- utter_did_that_help
* deny
- utter_ask_again
* request_certificate
- certificate_form
- form{"name": "certificate_form"}
- form{"name": null}
- utter_did_that_help
* affirm
- utter_noworries
* goodbye
- utter_goodbye
- action_restart
i need to post (rest api) the form to an service, how can i do that from actions.py when the user affirms:
*affirm
im looking for a trick or something can help me to read the *affirm in actions.py

You can use custom actions for that.
Your domain.yml file should look like:
intents:
- affirm
actions:
- action_affirm
Your stories.md file should look like:
* affirm
- action_affirm
You actions.py file should look like:
from rasa_core_sdk import Action
from rasa_core_sdk.events import SlotSet
class ActionAffirm(Action):
def name(self):
return 'action_affirm'
def run(self, dispatcher, tracker, domain):
#Do Something you want
...

Related

Need to call custom action when form is requesting for sots

am using rasa 1.9.5.
I have a form that gets activated and it will ask for the slots to fill. When it is asking for a slot to fill it's calling utter_slots_name. But my requirement is, I need to call custom action instead like action_slots_name.
I need to call custom action for all slot filling questions.
NLU:
## intent:greet
- Hi
- Hello
- I need a help
- just need help
- can you server me
## intent: greeting_with_name
- Hi I am [sharath](name), I need some services
- Hi myself [sharath](name), Need some services
- Hi this is [sharath](name), need some services
## intent: are_u_bot
- are you a bot?
- are you a human?
- am I talking to a bot?
- am I talking to a human?
## intent: my_name_is
- my name is [sharath](name)
- [sharath](name)
- I am [sharath](name)
- Myself [sharath](name)
Stories:
## bot challenge
* bot_challenge
- utter_iamabot
## happy path
* greet
- action_greeting
- user_details
- form{"name":"user_details"}
- form{"name":null}
- action_askfor_services
Domain:
actions:
- action_askfor_services
- action_slots_name
- user_details
- action_greeting
intents:
- greet
- bot_challenge
- my_name_is
- greeting_with_name
form:
- user_details
entities:
- name
- phoneNo
- tenentId
- language
slots:
language:
type: text
name:
type: text
phoneNo:
type: text
tenentId:
type: text
requested_slot:
type: text
responses:
utter_iamabot:
- text: I am a bot, powered by Rasa.
utter_bye:
- text: bye
session_config:
carry_over_slots_to_new_session: true
session_expiration_time: 60

form is not activated in Rasa 2.0

I'm trying to integrate a form in my rasa chatbot.
In domain.yml, I have included the following:
I declared the slots:
slots:
question1:
type: text
question2:
type: text
question3:
type: text
the questions that the form is supposed to send to the user:
utter_ask_question1:
- text:" first question goes here"
utter_ask_question2:
- text:" second question goes here"
utter_ask_question3:
- text:" third question goes here"
defined the form as:
forms:
user_quiz_form:
question1:
- type: from_text
# entity: date
question2:
- type: from_text
question3:
- type: from_text
the actions section also contains :
actions:
- action_submit
- user_quiz_form
The file rules.yml contains:
- rule: Activate quiz form
steps:
- intent: quiz
- action: utter_quiz
- action: user_quiz_form
- active_loop: user_quiz_form
- rule: Submit quiz form
condition:
- active_loop: user_quiz_form
steps:
- action: user_quiz_form
- active_loop: null
- slot_was_set:
- requested_slot: null
- action: action_submit
and actions.py is:
from typing import Any, Text, Dict, List
from rasa_sdk import Action, Tracker
from rasa_sdk.events import SlotSet, EventType
from rasa_sdk.executor import CollectingDispatcher
import webbrowser
class ValidateForm(Action):
def name(self) -> Text:
return "user_quiz_form"
def run(
self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
) -> List[EventType]:
required_slots = ["question1","question2", "question3"]
for slot_name in required_slots:
if tracker.slots.get(slot_name) is None:
# The slot is not filled yet. Request the user to fill this slot next.
return [SlotSet("requested_slot", slot_name)]
return [SlotSet("requested_slot", None)]
class ActionSubmit(Action):
def name(self) -> Text:
return "action_submit"
def run(
self,
dispatcher,
tracker: Tracker,
domain: "DomainDict",
) -> List[Dict[Text, Any]]:
print("****************SUBMIT*****************")
dispatcher.utter_message(template="utter_quiz_thanks", date=tracker.slots.get("question1"))
return []
When the form is triggered, it doesn't' ask the questions to the user and returns utter_quiz_thanks with None as question1 value.
Is this the same indentation you're using in your domain.yml? If so, you're missing some indents; the slots underneath the form need to be indented (see below for an example). My guess is that you're launching the form correctly, but due to the indent issues your assistant is treating it as a form with 0 questions.
forms:
restaurant_form:
cuisine:
- type: from_entity
entity: cuisine
num_people:
- type: from_entity
entity: number

Accessing Ansible variables in molecule test, TestInfra

I picked up molecule while researching around inspec and how to use it in ansible. I found molecule very cool and adopted it. I wanted to use it in 2 ways.
1- When developing a role or playbook
2- After a particular playbook have been run on production.
On number 1: I found this very useful question/ressponse on stackoverflow and that has helped me shape my thinking.I put my variable file for the role kafka under group_vars/all as suggested in the stackoverflow post
- kafka
- - molecule
- - - default
- - - - molecule.yml
- - - - playbook.yml
- - - - ...
- - - - group_vars
- - - - - all.yml
- - - - tests
- - - - - test_default.py
- - tasks
- - - main.yml
- - ....
test_default.py
import os
import testinfra.utils.ansible_runner
import pytest
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')
#pytest.fixture()
def AnsibleVars(host):
all_vars = host.ansible.get_variables()
return all_vars
def test_hosts_file(host):
f = host.file('/etc/hosts')
assert f.exists
assert f.user == 'root'
assert f.group == 'root'
def test_downloaded_binary(host, AnsibleVars):
# arch = host.file(AnsibleVars['kafka_archive_temp'])
result = host.ansible('debug','var=kafka_archive_temp')
arch = host.file(result['kafka_archive_temp'])
assert arch.exists
assert arch.is_file
def test_installation_directory(host,AnsibleVars):
# dir = host.file(AnsibleVars['kafka_final_path'])
result = host.ansible('debug','var=kafka_final_path')
dir = host.file(result['kafka_final_path'])
assert dir.exists
assert dir.is_directory
assert dir.user == AnsibleVars['kafka_user_on_os']
assert dir.group == AnsibleVars['kafka_group_on_os']
def test_user_created(host,AnsibleVars):
user = host.user(AnsibleVars['kafka_user_on_os'])
assert user.name == AnsibleVars['kafka_user_on_os']
assert user.group == AnsibleVars['kafka_group_on_os']
group_vars/all.yml
kafka_version: "2.2.1"
kafka_file_name: "kafka_2.12-{{ kafka_version }}.tgz"
kafka_user_on_os: kafka
kafka_group_on_os: kafka
kafka_zookeeper_service: zookeeper
kafka_service: kafka
kafka_log_folder: /var/log/kafka
kafka_zookeeper_port: 2181
kafka_archive_temp: "/tmp/{{ kafka_file_name }}"
kafka_final_path: "/usr/local/kafka/{{ kafka_version }}"
kafka_get_binaries_details:
- {
dest: "{{ kafka_archive_temp }}",
url: "http://www-us.apache.org/dist/kafka/2.2.1/kafka_2.12-2.2.1.tgz"
}
....
molecule verify
molecule verify
--> Validating schema /Users/joseph/Engineering/configuration-management-ansible/roles/kafka/molecule/default/molecule.yml.
Validation completed successfully.
--> Test matrix
└── default
└── verify
--> Scenario: 'default'
--> Action: 'verify'
--> Executing Testinfra tests found in /Users/joseph/Engineering/configuration-management-ansible/roles/kafka/molecule/default/tests/...
============================= test session starts ==============================
platform darwin -- Python 3.7.4, pytest-5.1.2, py-1.8.0, pluggy-0.12.0
rootdir: /Users/joseph/Engineering/configuration-management-ansible/roles/kafka/molecule/default
plugins: testinfra-3.1.0
collected 8 items
tests/test_default.py ........ [100%]
============================== 8 passed in 18.34s ==============================
Verifier completed successfully.
However the method host.ansible.get_variables() could not resolve a variable inside another variable like : kafka_final_path: "/usr/local/kafka/{{ kafka_version }}".
I ended up using the following:
result = host.ansible('debug','var=kafka_final_path')
dir = host.file(result['kafka_final_path'])
to get the value of kafka_final_path.
Question 1.1: Looking at how there is a need of a little manipulation before a variable of a variable get be retrieved with all needed interpolation, I am wondering there is any better way of writing these tests?
Question 2.1: On number 2, I would like to create a different scenario for testing like for EC2 on AWS. On those playbooks, I use external variable files passed to ansible-playbook since they have higher precedence. I am wondering in that case how I would access those variables from the external vars_files in testinfra?

Stuck on create symlink at /etc/service/kibana to /etc/sv/kibana when running kitchen test on CentOS 6.7

my problem here is I got stuck on the kibana create symlink instead of continue running on the the code below which is elasticsearch recipe and logstash recipe. Can anybody know why this is happening cause I don't have any idea whats going on about this issue. Thanks Guys :) Happy coding...
my metadata.rb
depends 'java'
depends 'elasticsearch'
depends 'kibana_lwrp'
depends 'ucarp'
depends 'python'
my recipes/default.rb
include_recipe 'java'
include_recipe 'kibana_lwrp::install'
include_recipe 'my_elkstack::elasticsearch'
include_recipe 'my_elkstack::logstash'
This is the logs:
Recipe: kibana_lwrp::install
* runit_service[kibana] action enable
* ruby_block[restart_service] action nothing (skipped due to action :nothing)
* ruby_block[restart_log_service] action nothing (skipped due to action :nothing)
* directory[/etc/sv/kibana] action create
- create new directory /etc/sv/kibana
- change mode from '' to '0755'
* template[/etc/sv/kibana/run] action create
- create new file /etc/sv/kibana/run
- update content in file /etc/sv/kibana/run from none to f0df85
--- /etc/sv/kibana/run 2016-09-20 05:44:45.352159387 +0000
+++ /etc/sv/kibana/.chef-run20160920-128-15s890o 2016-09-20 05:44:45.352159387 +0000
## -1 +1,8 ##
+#!/bin/sh
+
+cd /opt/kibana/current
+exec 2>&1
+
+exec chpst -u kibana /opt/kibana/current/bin/kibana
+
- change mode from '' to '0755'
* directory[/etc/sv/kibana/log] action create
- create new directory /etc/sv/kibana/log
* directory[/etc/sv/kibana/log/main] action create
- create new directory /etc/sv/kibana/log/main
- change mode from '' to '0755'
* directory[/var/log/kibana] action create
- create new directory /var/log/kibana
- change mode from '' to '0755'
* template[/etc/sv/kibana/log/config] action create
- create new file /etc/sv/kibana/log/config
- update content in file /etc/sv/kibana/log/config from none to e3b0c4
(no diff)
- change mode from '' to '0644'
* link[/var/log/kibana/config] action create
- create symlink at /var/log/kibana/config to /etc/sv/kibana/log/config
* template[/etc/sv/kibana/log/run] action create
- create new file /etc/sv/kibana/log/run
- update content in file /etc/sv/kibana/log/run from none to e64148
--- /etc/sv/kibana/log/run 2016-09-20 05:44:45.368159387 +0000
+++ /etc/sv/kibana/log/.chef-run20160920-128-punoc6 2016-09-20 05:44:45.368159387 +0000
## -1 +1,3 ##
+#!/bin/sh
+exec svlogd -tt ./main
- change mode from '' to '0755'
* directory[/etc/sv/kibana/env] action create
- create new directory /etc/sv/kibana/env
- change mode from '' to '0755'
* ruby_block[zap extra env files for kibana service] action run (skipped due to only_if)
* template[/etc/sv/kibana/check] action create (skipped due to only_if)
* template[/etc/sv/kibana/finish] action create (skipped due to only_if)
* directory[/etc/sv/kibana/control] action create
- create new directory /etc/sv/kibana/control
- change mode from '' to '0755'
* link[/etc/init.d/kibana] action create
- create symlink at /etc/init.d/kibana to /sbin/sv
* file[/etc/sv/kibana/down] action nothing (skipped due to action :nothing)
* ruby_block[restart_service] action run
* ruby_block[restart_service] action nothing (skipped due to action :nothing)
* ruby_block[restart_log_service] action nothing (skipped due to action :nothing)
* directory[/etc/sv/kibana] action create (up to date)
* template[/etc/sv/kibana/run] action create (up to date)
* directory[/etc/sv/kibana/log] action create (up to date)
* directory[/etc/sv/kibana/log/main] action create (up to date)
* directory[/var/log/kibana] action create (up to date)
* template[/etc/sv/kibana/log/config] action create (up to date)
* link[/var/log/kibana/config] action create (up to date)
* template[/etc/sv/kibana/log/run] action create (up to date)
* directory[/etc/sv/kibana/env] action create (up to date)
* ruby_block[zap extra env files for kibana service] action run (skipped due to only_if)
* template[/etc/sv/kibana/check] action create (skipped due to only_if)
* template[/etc/sv/kibana/finish] action create (skipped due to only_if)
* directory[/etc/sv/kibana/control] action create (up to date)
* link[/etc/init.d/kibana] action create (up to date)
* file[/etc/sv/kibana/down] action nothing (skipped due to action :nothing)
* directory[/etc/service] action create (up to date)
* link[/etc/service/kibana] action create
- create symlink at /etc/service/kibana to /etc/sv/kibana
This usually means runsvdir isn't picking up the new service. Check that Runit itself has started correctly from whatever the system init daemon is.

Best approach to create recursive treeview dynamically from data API

I'm learning Angular 2, trying to build an expandable tree-view from a (potentially very large) third-party API. The API has an underlying structure like this:
- Home (id: 1053)
- - Rugby League (id: 1054)
- - - Super League (id: 1103)
- - - - Castleford Tigers (id: 1111)
- - - - Catalans Dragons (id: 1110)
- - - - Huddersfield Giants (id: 1116)
- - - - Hull FC (id: 1108)
- - - Championship (id: 1104)
- - - - Batley Bulldogs (id: 1120)
- - - - Bradford Bulls (id: 1118)
- - - - Dewsbury Rams (id: 1124)
- - - - Featherstone Rovers (id: 1121)
- - Football (id: 1056)
- - - Premier League (id: 1057)
- - - - AFC Bournemouth (id: 1059)
- - - - etc
- - - - etc
The API is set up such that I pass an id and it returns a simple JSON array of the children (only) of that node. So, for example I call: http://www.example.com/api/contentNodes/?parentId=1053 and it returns:
[
{"Id":1054,"Name":"Rugby League","HasChildren":true},
{"Id":1056,"Name":"Football","HasChildren":true}
]
(HasChildren represents whether or not the node has child nodes.)
Note, because the data-set will eventually be large I want to 'pull in' more data from the API progressively as the tree branches are opened, rather than dumping the entire data-set in there and rendering that out in my app.
I've set up an Angular 2 app which can be seen here: http://plnkr.co/edit/QQ1OKCbd4pDptpSVbWch?p=preview
The key component is the `app/content-list.component.ts' file:
import {Component, OnInit} from 'angular2/core';
import {ContentNode} from './content-node';
import {ContentService} from './content.service';
#Component({
selector: 'content-list',
template: `
<ol class="tree">
<li *ngFor="#contentNode of contentNodes" class="tree__branch" [ngClass]="{'tree__branch--has-children': contentNode.HasChildren}">
<a *ngIf="contentNode.HasChildren" (click)="toggleBranch(contentNode.Id)" class="toggle">+</a> {{ contentNode.Name }}
</li>
</ol>
<div class="error" *ngIf="errorMessage">{{errorMessage}}</div>
`
})
export class ContentListComponent implements OnInit {
constructor (private _contentService: ContentService) {}
errorMessage: string;
private _startNodeId: number = 1053;
contentNodes: ContentNode[];
ngOnInit() {
this.getContentNodes();
}
getContentNodes() {
this._contentService.getContentNodes(this._startNodeId)
.subscribe(
contentNodes => this.contentNodes = contentNodes,
error => this.errorMessage = <any>error
);
}
toggleBranch(branchId:number){
console.log('branchId: ' + branchId);
}
}
You'll see here that I'm calling my service which returns the JSON as above, by being passed a parentId of 1053.
I've now hit a wall in being able to progressively load the child nodes of the treeview when the + button is clicked, into the nested HTML list (<ol>).
What would be the best approach here, to achieve this in a really neat way?
My next step will be to ensure that the app doesn't make excessive API calls, but my immediate concern is just to get a running treeview hooked up and working.
I've seen this example of a recursive treeview but it seems (a) a little buggy (in that there are empty <ol></ol> elements rendered in the HTML when child nodes are empty etc); and (b) it seems to be set up in a very 'hard-coded' kind of a way and I'm not experienced enough to confidently refactor it.
Many thanks.
Note, for security reasons I can't open up the API to public requests unfortunately, which makes testing this on Plunkr a little difficult, I realise. For the moment my example uses just a static, single level JSON data-set.
in Angular2 you can render directives recursively. This makes rendering the tree very easy.
I've modified your Plunker a little bit just to show the point. It's not the ideal implementation but it works as expected :).
Example:
#Component({
selector: 'tree-view',
template: `
<div *ngFor="#dir of dirs">
<tree-view [dirs]="dir.dirs"></tree-view>
<div>
`,
directives: [TreeView]
})
export class TreeView {
#Input()
private dirs: Array<Directory>;
}
I hope you will like it.
Cheers!

Resources