Spaces:
Sleeping
Sleeping
progress on defining the main story state flow
Browse files- README.md +1 -1
- adaptors/voice.py +30 -4
- helpers/__init__.py +28 -0
- homeros.py +3 -0
- main.py +76 -6
README.md
CHANGED
@@ -34,7 +34,7 @@ It puts the user in charge of a how the story is going to develop.
|
|
34 |
## Story schema
|
35 |
|
36 |
- STRING `uuid` = uuid of this story
|
37 |
-
- STRING `status` = 'not_started' / '
|
38 |
- TEXT `world` = text description of the world
|
39 |
- TEXT `hero` = text description of the hero of the story
|
40 |
- TEXT `plot` = high level description of the plot. without chapters or anything like that. we can use this to later break down into chapters and get smarter about story ark management with a second LLM
|
|
|
34 |
## Story schema
|
35 |
|
36 |
- STRING `uuid` = uuid of this story
|
37 |
+
- STRING `status` = 'not_started' / 'checking_magic_word' / 'defining_metadata' / 'ongoing' / 'finished' ...etc.
|
38 |
- TEXT `world` = text description of the world
|
39 |
- TEXT `hero` = text description of the hero of the story
|
40 |
- TEXT `plot` = high level description of the plot. without chapters or anything like that. we can use this to later break down into chapters and get smarter about story ark management with a second LLM
|
adaptors/voice.py
CHANGED
@@ -10,8 +10,8 @@ from pprint import pprint
|
|
10 |
import json
|
11 |
|
12 |
url = "https://play.ht/api/v2/tts"
|
13 |
-
user_id = os.environ[
|
14 |
-
api_key = os.environ[
|
15 |
|
16 |
headers = {
|
17 |
"accept": "text/event-stream",
|
@@ -20,7 +20,33 @@ headers = {
|
|
20 |
"X-USER-ID": user_id
|
21 |
}
|
22 |
|
23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
payload = {
|
25 |
"quality": "medium",
|
26 |
"output_format": "mp3",
|
@@ -32,7 +58,7 @@ def say_it(text, voice):
|
|
32 |
|
33 |
response = requests.post(url, stream=True, headers=headers, json=payload)
|
34 |
|
35 |
-
stream_url = response.headers[
|
36 |
logger.debug(f"stream_url = {stream_url}")
|
37 |
|
38 |
resp = requests.get(stream_url, stream=True, headers=headers)
|
|
|
10 |
import json
|
11 |
|
12 |
url = "https://play.ht/api/v2/tts"
|
13 |
+
user_id = os.environ["PLAYHT_USERID"]
|
14 |
+
api_key = os.environ["PLAYHT_SECRETKEY"]
|
15 |
|
16 |
headers = {
|
17 |
"accept": "text/event-stream",
|
|
|
20 |
"X-USER-ID": user_id
|
21 |
}
|
22 |
|
23 |
+
voices = ["dylan"]
|
24 |
+
|
25 |
+
#TODO pre-generate these with dylan and save locally
|
26 |
+
fixed_sayings = {
|
27 |
+
"welcome": [""], #also ask magic word here
|
28 |
+
"wrong_magic_word": [""],
|
29 |
+
"let_me_ask_questions": [""],
|
30 |
+
"ask_world": [""],
|
31 |
+
"ask_hero": [""],
|
32 |
+
"ask_plot": [""],
|
33 |
+
"ask_ending": [""],
|
34 |
+
"ask_style": [""],
|
35 |
+
"its_the_end": [""],
|
36 |
+
"no_more_story": [""]
|
37 |
+
}
|
38 |
+
|
39 |
+
'''
|
40 |
+
return an old file from a dictionary of pre-generated sayings
|
41 |
+
'''
|
42 |
+
def say_fixed(fixed_msg, voice):
|
43 |
+
#We need to keep a repository of fixed messages generated in our key voices and for each have a file URL
|
44 |
+
return
|
45 |
+
|
46 |
+
'''
|
47 |
+
generate new saying with play.ht
|
48 |
+
'''
|
49 |
+
def say_new(text, voice):
|
50 |
payload = {
|
51 |
"quality": "medium",
|
52 |
"output_format": "mp3",
|
|
|
58 |
|
59 |
response = requests.post(url, stream=True, headers=headers, json=payload)
|
60 |
|
61 |
+
stream_url = response.headers["content-location"]
|
62 |
logger.debug(f"stream_url = {stream_url}")
|
63 |
|
64 |
resp = requests.get(stream_url, stream=True, headers=headers)
|
helpers/__init__.py
CHANGED
@@ -1,4 +1,32 @@
|
|
1 |
import uuid
|
|
|
|
|
|
|
|
|
2 |
|
3 |
def gen_unique_id():
|
4 |
return str(uuid.uuid4())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import uuid
|
2 |
+
import os
|
3 |
+
import random
|
4 |
+
|
5 |
+
magic_w = os.environ["MAGICWORD"]
|
6 |
|
7 |
def gen_unique_id():
|
8 |
return str(uuid.uuid4())
|
9 |
+
|
10 |
+
def check_magic_word(w):
|
11 |
+
return magic_w in w
|
12 |
+
|
13 |
+
def get_fixed_msg(msg_type):
|
14 |
+
|
15 |
+
fixed_sayings = {
|
16 |
+
"welcome": ["Welcome! What's the magic word?"], #also ask magic word here
|
17 |
+
"wrong_magic_word": ["Magic word is wrong. Try again."],
|
18 |
+
"ask_world": ["Let me ask you some questions first. What kind of world should your story unfold in?"],
|
19 |
+
"ask_hero": ["Who should the hero be?"],
|
20 |
+
"ask_plot": ["Can you describe the plot in a few words?"],
|
21 |
+
"ask_ending": ["What kind of ending would you like? A happy one? A tragic one? Something else?"],
|
22 |
+
"ask_style": ["What kind of storytelling style do you wnat? Funny? Poetic?"],
|
23 |
+
"its_the_end": ["And this is the end of our story. Thank you for listening."],
|
24 |
+
"no_more_story": ["I'm sorry, this story has ended."]
|
25 |
+
}
|
26 |
+
|
27 |
+
if msg_type in fixed_sayings:
|
28 |
+
saying = random.choice(fixed_sayings[msg_type])
|
29 |
+
return saying
|
30 |
+
|
31 |
+
else:
|
32 |
+
raise Exception(f"fixed saying with msg_type {msg_type} not found")
|
homeros.py
CHANGED
@@ -1,3 +1,6 @@
|
|
|
|
|
|
|
|
1 |
def start_story(story):
|
2 |
return story
|
3 |
|
|
|
1 |
+
def init_story(story):
|
2 |
+
return story
|
3 |
+
|
4 |
def start_story(story):
|
5 |
return story
|
6 |
|
main.py
CHANGED
@@ -3,23 +3,93 @@ from pprint import pprint
|
|
3 |
import json
|
4 |
from loguru import logger
|
5 |
from dotenv import load_dotenv
|
6 |
-
import helpers
|
7 |
load_dotenv()
|
|
|
8 |
|
9 |
-
from homeros import start_story, continue_story, finish_story, define_metadata
|
10 |
|
|
|
|
|
|
|
11 |
def do_homeros(user_input, story):
|
12 |
|
13 |
pprint(story)
|
14 |
|
|
|
15 |
if story["status"] == "not_started":
|
16 |
-
|
17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
|
19 |
else:
|
20 |
-
|
|
|
|
|
21 |
|
22 |
-
return
|
23 |
|
24 |
demo = gr.Blocks()
|
25 |
|
|
|
3 |
import json
|
4 |
from loguru import logger
|
5 |
from dotenv import load_dotenv
|
|
|
6 |
load_dotenv()
|
7 |
+
import helpers
|
8 |
|
9 |
+
from homeros import init_story, start_story, continue_story, finish_story, define_metadata
|
10 |
|
11 |
+
'''
|
12 |
+
Here we manage the flow and state of the story
|
13 |
+
'''
|
14 |
def do_homeros(user_input, story):
|
15 |
|
16 |
pprint(story)
|
17 |
|
18 |
+
# story hasn't started
|
19 |
if story["status"] == "not_started":
|
20 |
+
logger.debug("status: initiating a new story")
|
21 |
+
next_message = helpers.get_fixed_msg("welcome")
|
22 |
+
story = init_story(story)
|
23 |
+
story["status"] = "checking_magic_word"
|
24 |
+
|
25 |
+
# we are checking the magic word or it is wrong and we need to ask for it again
|
26 |
+
elif story["status"] == "checking_magic_word" or story["status"] == "wrong_magic_word":
|
27 |
+
logger.debug("status: checking magic word")
|
28 |
+
magic_word_correct = helpers.check_magic_word(user_input)
|
29 |
+
if magic_word_correct:
|
30 |
+
story["status"] = "defining_metadata_world"
|
31 |
+
next_message = helpers.get_fixed_msg("ask_world")
|
32 |
+
else:
|
33 |
+
story["status"] = "wrong_magic_word"
|
34 |
+
next_message = helpers.get_fixed_msg("wrong_magic_word")
|
35 |
+
|
36 |
+
# defining the world
|
37 |
+
elif story["status"] == "defining_metadata_world":
|
38 |
+
logger.debug("status: magic word is wrong")
|
39 |
+
story = define_metadata(user_input, "world", story)
|
40 |
+
story["status"] = "defining_metadata_hero"
|
41 |
+
next_message = helpers.get_fixed_msg("ask_hero")
|
42 |
+
|
43 |
+
# defining the hero
|
44 |
+
elif story["status"] == "defining_metadata_hero":
|
45 |
+
logger.debug("status: defining the hero")
|
46 |
+
story = define_metadata(user_input, "hero", story)
|
47 |
+
story["status"] = "defining_metadata_plot"
|
48 |
+
next_message = helpers.get_fixed_msg("ask_plot")
|
49 |
+
|
50 |
+
# defining the plot
|
51 |
+
elif story["status"] == "defining_metadata_plot":
|
52 |
+
logger.debug("status: defining the plot")
|
53 |
+
story = define_metadata(user_input, "plot", story)
|
54 |
+
story["status"] = "defining_metadata_ending"
|
55 |
+
next_message = helpers.get_fixed_msg("ask_ending")
|
56 |
+
|
57 |
+
# defining the ending
|
58 |
+
elif story["status"] == "defining_metadata_ending":
|
59 |
+
logger.debug("status: defining the ending")
|
60 |
+
story = define_metadata(user_input, "ending", story)
|
61 |
+
story["status"] = "defining_metadata_style"
|
62 |
+
next_message = helpers.get_fixed_msg("ask_style")
|
63 |
+
|
64 |
+
# defining the style and starting the story with the first chunk
|
65 |
+
elif story["status"] == "defining_metadata_style":
|
66 |
+
logger.debug("status: defining the style")
|
67 |
+
story = define_metadata(user_input, "style", story)
|
68 |
+
story["status"] = "ongoing"
|
69 |
+
story = start_story(story)
|
70 |
+
next_message = story["chunks"][-1]
|
71 |
+
|
72 |
+
# we are in the middle of the story - evaluate if time to end, or continue
|
73 |
+
elif story["status"] == "ongoing":
|
74 |
+
if helpers.its_time_to_end(story):
|
75 |
+
story = finish_story(story)
|
76 |
+
story["status"] = "finished"
|
77 |
+
else:
|
78 |
+
story = continue_story(story)
|
79 |
+
story["status"] = "ongoing"
|
80 |
+
next_message = story["chunks"][-1]
|
81 |
+
|
82 |
+
# story has ended, but the user still inputting. tell them it's over
|
83 |
+
elif story["status"] == "ended":
|
84 |
+
next_message = helpers.get_fixed_msg("no_more_story")
|
85 |
+
story["status"] = "finished"
|
86 |
|
87 |
else:
|
88 |
+
raise Exception("strange story status")
|
89 |
+
logger.error(f"we have a story status {story['status']} we didn't catch...")
|
90 |
+
logger.debug(story)
|
91 |
|
92 |
+
return next_message, story
|
93 |
|
94 |
demo = gr.Blocks()
|
95 |
|