dream
130 строк · 6.0 Кб
1#!/usr/bin/env python
2
3import random
4import re
5
6
7class Teller:
8def __init__(self, stories, phrases, status_constants, logger):
9"""
10The one that tells tales...
11"""
12self.history = []
13self.phrases = phrases
14self.stories = stories
15self.status_constants = status_constants
16self.logger = logger
17
18def get_story(self, sentence):
19"""
20Determine what type of story user requested
21"""
22sentence = sentence.lower()
23if re.search("fun((ny)|(niest)){0,1}", sentence):
24return "funny"
25elif re.search("(horror)|(scary)|(frightening)|(spooky)", sentence):
26return "scary"
27elif re.search("(bedtime)|(good)|(kind)|(baby)|(children)|(good night)|(for kid(s){0,1})", sentence):
28return "bedtime"
29else:
30return None
31
32def choose_story(self, attributes, story_type):
33"""
34Choose a story.
35"""
36already_told_stories = attributes.get("already_told_stories", [])
37try: # Try to get a story that haven't been told already
38story = random.choice(list(set(self.stories[story_type].keys()) - set(already_told_stories)))
39except IndexError: # We run out of stories
40phrase = "Oh, I am sorry, but I've run out of stories. Maybe you have any to share with me?"
41status = self.status_constants["cannot"]
42else: # Tell a story setup
43already_told_stories += [story]
44phrase = self.stories[story_type][story]["setup"] + "..." + random.choice(self.phrases["what_happend_next"])
45status = self.status_constants["must"]
46attributes["state"] = "setup"
47attributes["story"] = story
48attributes["already_told_stories"] = already_told_stories
49return phrase, status, attributes
50
51def tell_punchline(self, story_name):
52for story_type in self.stories:
53for story in self.stories[story_type]:
54if story == story_name:
55return self.stories[story_type][story_name]["punchline"]
56return "Oh, sorry, i lost the track of what I was talking about."
57
58def tell(self, human_sentence, intents, state):
59"""
60Basic logic of story teller
61"""
62phrase = ""
63status = self.status_constants["can"]
64confidence = 0.999
65# Set attributes
66attributes = {}
67# Get intent values
68tell_me_a_story = bool(intents.get("tell_me_a_story", {}).get("detected", False))
69yes = bool(intents.get("yes", {}).get("detected", False))
70no = bool(intents.get("no", {}).get("detected", False))
71# Logging
72self.logger.info(f"Human sentence: {human_sentence}")
73self.logger.info(f"tell_me_a_story: {tell_me_a_story}")
74self.logger.info(f"yes: {yes}")
75self.logger.info(f"no: {no}")
76self.logger.info(f"state: {state}")
77
78# Skill logic
79# We detected an intent firsthand
80if tell_me_a_story or state.get("state", "") == "asked_for_a_story":
81story_type = self.get_story(human_sentence)
82# User didn't specify the type of story
83if story_type is None:
84if state.get("state", "") == "asked_for_a_story":
85phrase = random.choice(self.phrases["which_story"])
86else:
87phrase = random.choice(self.phrases["sure"]) + " " + random.choice(self.phrases["which_story"])
88status = self.status_constants["must"]
89attributes["state"] = "which_story"
90else: # The type of story is already specified in intial intent
91phrase, status, attributes = self.choose_story(attributes, story_type)
92elif state.get("state", "") == "do_you_mind" and yes: # Want a story -> yes
93confidence = 1.0
94phrase = random.choice(self.phrases["which_story"])
95status = self.status_constants["must"]
96attributes["state"] = "which_story"
97elif state.get("state", "") == "do_you_mind" and no: # Want a story -> no
98phrase = random.choice(self.phrases["no"])
99status = self.status_constants["can"]
100elif state.get("state", "") == "do_you_mind": # Didn't get the answer
101phrase = random.choice(self.phrases["which_story"])
102status = self.status_constants["can"]
103attributes["state"] = "which_story"
104confidence = 0.75
105elif state.get("state", "") == "which_story": # Already asked about which story
106story_type = self.get_story(human_sentence)
107# If we couldn't determine the type of story (don't have such stories)
108if story_type is None:
109phrase = random.choice(self.phrases["no_stories"])
110status = self.status_constants["can"]
111else: # Start telling the story
112phrase, status, attributes = self.choose_story(attributes, story_type)
113elif state.get("state", "") == "setup" and yes: # User is still intrigued -> continue
114story_name = state.get("story", "")
115phrase = self.tell_punchline(story_name)
116status = self.status_constants["can"]
117elif state.get("state", "") == "setup" and no: # User is not interested
118phrase = random.choice(self.phrases["no"])
119status = self.status_constants["cannot"]
120elif state.get("state", "") == "setup": # Don't know if user is still interested
121story_name = state.get("story", "")
122phrase = self.tell_punchline(story_name)
123status = self.status_constants["can"]
124confidence = 0.8
125else: # Start of a dialog
126phrase = random.choice(self.phrases["start_phrases"])
127status = self.status_constants["must"]
128confidence = 0.5
129attributes["state"] = "do_you_mind"
130return phrase, confidence, {}, {"short_story_skill_attributes": attributes}, {"can_continue": status}
131