Skip to content

Commit 6384e2e

Browse files
committed
initial bot working
1 parent 7627ceb commit 6384e2e

9 files changed

+365
-31
lines changed

actions/setup_recurrent_payment.py

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
from datetime import datetime
2+
from typing import List, Optional
3+
4+
from rasa.shared.nlu.training_data.message import Message
5+
from rasa_sdk import Action, Tracker
6+
from rasa_sdk.events import EventType, SlotSet
7+
from rasa_sdk.executor import CollectingDispatcher
8+
from rasa_sdk.types import DomainDict
9+
10+
from rasa.nlu.extractors.duckling_entity_extractor import DucklingEntityExtractor
11+
from typing import List, Optional
12+
13+
duckling_config = {**DucklingEntityExtractor.get_default_config(),
14+
"url": "https://rasa:[email protected]",
15+
"dimensions": ["time"]}
16+
duckling = DucklingEntityExtractor(duckling_config)
17+
18+
19+
def parse_datetime(text: str) -> Optional[datetime]:
20+
msg = Message.build(text)
21+
duckling.process([msg])
22+
if len(msg.data["entities"]) == 0:
23+
return None
24+
25+
parsed_value = msg.data["entities"][0]["value"]
26+
if isinstance(parsed_value, dict):
27+
parsed_value = parsed_value["from"]
28+
29+
return datetime.fromisoformat(parsed_value)
30+
31+
32+
class ValidatePaymentStartDate(Action):
33+
def name(self) -> str:
34+
return "validate_recurrent_payment_start_date"
35+
36+
def run(
37+
self,
38+
dispatcher: CollectingDispatcher,
39+
tracker: Tracker,
40+
domain: DomainDict,
41+
) -> List[EventType]:
42+
current_value = tracker.get_slot("recurrent_payment_start_date")
43+
if current_value is None:
44+
return []
45+
46+
start_date = parse_datetime(current_value)
47+
start_date_timezone = start_date.tzinfo if start_date else None
48+
if start_date is None or (start_date and start_date < datetime.now(tz=start_date_timezone)):
49+
dispatcher.utter_message(response="utter_invalid_date")
50+
return [SlotSet("recurrent_payment_start_date", None)]
51+
52+
return [SlotSet("recurrent_payment_start_date", start_date.isoformat())]
53+
54+
55+
class ValidatePaymentEndDate(Action):
56+
def name(self) -> str:
57+
return "validate_recurrent_payment_end_date"
58+
59+
def run(
60+
self,
61+
dispatcher: CollectingDispatcher,
62+
tracker: Tracker,
63+
domain: DomainDict,
64+
) -> List[EventType]:
65+
current_value = tracker.get_slot("recurrent_payment_end_date")
66+
if current_value is None:
67+
return []
68+
69+
end_date = parse_datetime(current_value)
70+
if end_date is None:
71+
dispatcher.utter_message(response="utter_invalid_date")
72+
return [SlotSet("recurrent_payment_end_date", None)]
73+
74+
start_date = tracker.get_slot("recurrent_payment_start_date")
75+
if start_date is not None and end_date < datetime.fromisoformat(start_date):
76+
dispatcher.utter_message(response="utter_invalid_date")
77+
return [SlotSet("recurrent_payment_end_date", None)]
78+
79+
return [SlotSet("recurrent_payment_end_date", end_date.isoformat())]
80+
81+
82+
class ExecutePayment(Action):
83+
def name(self) -> str:
84+
return "action_execute_recurrent_payment"
85+
86+
def run(
87+
self,
88+
dispatcher: CollectingDispatcher,
89+
tracker: Tracker,
90+
domain: DomainDict,
91+
) -> List[EventType]:
92+
# set-up payment logic here
93+
return [SlotSet("setup_recurrent_payment_successful", True)]

config.yml

+42-31
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,51 @@
11
version: "3.1"
22
language: en
33
pipeline:
4-
- name: WhitespaceTokenizer
5-
- name: RegexFeaturizer
6-
- name: LexicalSyntacticFeaturizer
7-
- name: CountVectorsFeaturizer
8-
- name: CountVectorsFeaturizer
9-
analyzer: "char_wb"
10-
min_ngram: 1
11-
max_ngram: 4
12-
- name: DIETClassifier
13-
epochs: 100
14-
- name: FallbackClassifier
15-
threshold: 0.7
16-
- name: DucklingEntityExtractor
17-
url: http://localhost:8000
18-
dimensions:
19-
- amount-of-money
20-
- time
21-
- number
22-
- name: SpacyNLP
23-
model: "en_core_web_md"
24-
case_sensitive: false
25-
- name: "SpacyEntityExtractor"
26-
# Note: It is not possible to use the SpacyTokenizer + SpacyFeaturizer in
27-
# combination with the WhitespaceTokenizer, and as a result the
28-
# PERSON extraction by Spacy is not very robust.
29-
# Because of this, the nlu training data is annotated as well, and the
30-
# DIETClassifier will also extract PERSON entities .
31-
dimensions: ["PERSON"]
32-
- name: EntitySynonymMapper
4+
- name: WhitespaceTokenizer
5+
- name: RegexFeaturizer
6+
- name: LexicalSyntacticFeaturizer
7+
- name: CountVectorsFeaturizer
8+
- name: CountVectorsFeaturizer
9+
analyzer: "char_wb"
10+
min_ngram: 1
11+
max_ngram: 4
12+
- name: DIETClassifier
13+
epochs: 50
14+
- name: FallbackClassifier
15+
threshold: 0.7
16+
- name: DucklingEntityExtractor
17+
url: http://localhost:8000
18+
dimensions:
19+
- amount-of-money
20+
- time
21+
- number
22+
# - name: SpacyNLP
23+
# model: "en_core_web_md"
24+
# case_sensitive: false
25+
# - name: "SpacyEntityExtractor"
26+
# # Note: It is not possible to use the SpacyTokenizer + SpacyFeaturizer in
27+
# # combination with the WhitespaceTokenizer, and as a result the
28+
# # PERSON extraction by Spacy is not very robust.
29+
# # Because of this, the nlu training data is annotated as well, and the
30+
# # DIETClassifier will also extract PERSON entities .
31+
# dimensions: ["PERSON"]
32+
- name: EntitySynonymMapper
33+
- name: LLMCommandGenerator
34+
llm:
35+
# model_name: gpt-3.5-turbo
36+
model_name: gpt-4
37+
request_timeout: 7
38+
39+
3340
policies:
3441
- name: AugmentedMemoizationPolicy
3542
- name: TEDPolicy
36-
epochs: 40
43+
epochs: 20
3744
- name: RulePolicy
3845
core_fallback_threshold: 0.4
3946
core_fallback_action_name: "action_default_fallback"
40-
enable_fallback_prediction: True
47+
enable_fallback_prediction: true
48+
- name: rasa.core.policies.flow_policy.FlowPolicy
49+
priority: 7
50+
51+
assistant_id: 20231006-123431-deterministic-pressure

data/flows/dummy.yml

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
flows:
2+
dummy_transfer_money:
3+
description: Help user make a one time money transfer to someone
4+
name: dummy_transfer_money
5+
steps: []

data/flows/replace_card.yml

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
flows:
2+
replace_card:
3+
description: The user needs to replace their card.
4+
name: replace_card
5+
steps:
6+
- collect: confirm_correct_card
7+
ask_before_filling: true
8+
next:
9+
- if: "confirm_correct_card"
10+
then:
11+
- link: "replace_eligible_card"
12+
- else:
13+
- action: utter_relevant_card_not_linked
14+
next: END

data/flows/replace_eligible_card.yml

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
flows:
2+
replace_eligible_card:
3+
description: Never predict StartFlow for this flow, users are not able to trigger it themselves.
4+
name: replace eligible card
5+
steps:
6+
- collect: replacement_reason
7+
next:
8+
- if: replacement_reason == "lost"
9+
then:
10+
- collect: was_card_used_fraudulently
11+
ask_before_filling: true
12+
next:
13+
- if: was_card_used_fraudulently
14+
then:
15+
- action: utter_report_fraud
16+
next: END
17+
- else: start_replacement
18+
- if: "replacement_reason == 'damaged'"
19+
then: start_replacement
20+
- else:
21+
- action: utter_unknown_replacement_reason_handover
22+
next: END
23+
- id: start_replacement
24+
action: utter_will_cancel_and_send_new
25+
- action: utter_new_card_has_been_ordered
+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
flows:
2+
setup_recurrent_payment:
3+
name: setup recurrent payment
4+
description: This flow let users to set up a recurring payment, which can either be a direct debit or a standing order.
5+
steps:
6+
- collect: recurrent_payment_type
7+
rejections:
8+
- if: not ({"direct debit" "standing order"} contains recurrent_payment_type)
9+
utter: utter_invalid_recurrent_payment_type
10+
description: the type of payment
11+
- collect: recurrent_payment_recipient
12+
utter: utter_ask_recipient
13+
description: the name of a person
14+
- collect: recurrent_payment_amount_of_money
15+
description: the amount of money without any currency designation
16+
- collect: recurrent_payment_frequency
17+
description: the frequency of the payment
18+
rejections:
19+
- if: not ({"monthly" "yearly"} contains recurrent_payment_frequency)
20+
utter: utter_invalid_recurrent_payment_frequency
21+
- collect: recurrent_payment_start_date
22+
description: the start date of the payment
23+
- collect: recurrent_payment_end_date
24+
description: the end date of the payment
25+
rejections:
26+
- if: recurrent_payment_end_date < recurrent_payment_start_date
27+
utter: utter_invalid_recurrent_payment_end_date
28+
- collect: recurrent_payment_confirmation
29+
description: accepts True or False
30+
ask_before_filling: true
31+
next:
32+
- if: not recurrent_payment_confirmation
33+
then:
34+
- action: utter_payment_cancelled
35+
next: END
36+
- else: "execute_payment"
37+
- id: "execute_payment"
38+
action: action_execute_recurrent_payment
39+
next:
40+
- if: setup_recurrent_payment_successful
41+
then:
42+
- action: utter_payment_complete
43+
next: END
44+
- else: "payment_failed"
45+
- id: "payment_failed"
46+
action: utter_payment_failed
47+
- action: utter_failed_payment_handover
48+
- action: utter_failed_handoff
File renamed without changes.

domain/replace_card.yml

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
version: "3.1"
2+
3+
slots:
4+
confirm_correct_card:
5+
type: bool
6+
mappings:
7+
- type: custom
8+
replacement_reason:
9+
type: categorical
10+
values:
11+
- lost
12+
- damaged
13+
mappings:
14+
- type: custom
15+
was_card_used_fraudulently:
16+
type: bool
17+
mappings:
18+
- type: custom
19+
20+
responses:
21+
utter_ask_confirm_correct_card:
22+
- text: I've found the card with number ****3452 on file. Is this the card you want to replace?
23+
utter_relevant_card_not_linked:
24+
- text: "Seems like I don't have the card you're asking about on file."
25+
utter_ask_replacement_reason:
26+
- text: "Why do you need to replace your card?"
27+
buttons:
28+
- title: "Lost"
29+
payload: "lost"
30+
- title: "Damaged"
31+
payload: "damaged"
32+
utter_ask_was_card_used_fraudulently:
33+
- text: "Is it possible that someone else has managed to use your card?"
34+
utter_will_cancel_and_send_new:
35+
- text: "Alright, I'll cancel your card and send you a new one."
36+
utter_new_card_has_been_ordered:
37+
- text: "Your new card should arrive in 3 to 5 business days in a white envelope."
38+
utter_report_fraud:
39+
- text: "I am sorry to hear that. Unfortunately, I can't directly handle fraudulently used cards. Please go to FinX.com/disputes, to report the fraud on your account."
40+
utter_unknown_replacement_reason_handover:
41+
- text: "Let me connect you to an agent, to get the details of what happened to your card."
42+
utter_failed_handoff:
43+
- text: "I am sorry, I was not able to connect you to an agent. I have created a support ticket for you. Someone will reach out to you shortly."

0 commit comments

Comments
 (0)