Spaces:
Sleeping
Sleeping
voice generation and first story working
Browse files- README.md +4 -2
- __test.py +36 -1
- adaptors/llm.py +16 -9
- adaptors/voice.py +11 -28
- data/stories.db +0 -0
- helpers/__init__.py +31 -10
- homeros.py +10 -3
- main.py +20 -8
- prompts/__init__.py +1 -0
- prompts/paraphraser.py +19 -0
README.md
CHANGED
@@ -72,12 +72,14 @@ It puts the user in charge of a how the story is going to develop.
|
|
72 |
- [x] Set up flow management
|
73 |
- [x] Add SQlite DB and save stories
|
74 |
- [x] GPT-4 story generation in a gradio interface
|
75 |
-
- [
|
76 |
-
- [
|
77 |
- [ ] Interchange text input for whisper
|
|
|
78 |
- [ ] Dockerfile and deploy (including magic word for access control)
|
79 |
|
80 |
## Enhancements
|
81 |
|
82 |
- [ ] Add option to download the full story as one .mp3
|
|
|
83 |
- [ ] Add meta-moderator role to manage story ark better
|
|
|
72 |
- [x] Set up flow management
|
73 |
- [x] Add SQlite DB and save stories
|
74 |
- [x] GPT-4 story generation in a gradio interface
|
75 |
+
- [x] Do the evaluator (if it's time to end)
|
76 |
+
- [x] Inerchange text output for play.ht voice generation
|
77 |
- [ ] Interchange text input for whisper
|
78 |
+
- [ ] Clear input on submit
|
79 |
- [ ] Dockerfile and deploy (including magic word for access control)
|
80 |
|
81 |
## Enhancements
|
82 |
|
83 |
- [ ] Add option to download the full story as one .mp3
|
84 |
+
- [ ] Add option to download full story text
|
85 |
- [ ] Add meta-moderator role to manage story ark better
|
__test.py
CHANGED
@@ -5,9 +5,44 @@ from adaptors.db import get_story, get_all_stories
|
|
5 |
from pprint import pprint
|
6 |
import json
|
7 |
from loguru import logger
|
|
|
8 |
|
9 |
def all_s():
|
10 |
for s in get_all_stories():
|
11 |
pprint(s.to_dict())
|
12 |
|
13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
from pprint import pprint
|
6 |
import json
|
7 |
from loguru import logger
|
8 |
+
from adaptors.voice import say_new
|
9 |
|
10 |
def all_s():
|
11 |
for s in get_all_stories():
|
12 |
pprint(s.to_dict())
|
13 |
|
14 |
+
|
15 |
+
def say(text):
|
16 |
+
pprint(text)
|
17 |
+
return say_new(text)
|
18 |
+
|
19 |
+
|
20 |
+
long_text = '''
|
21 |
+
In a distant and rarely trodden corner of Middle Earth, there
|
22 |
+
resided an unlikely hero, known to the local forest critters by the '
|
23 |
+
rather unusual name, Slippersnail. Unlike the courageous Hobbits or '
|
24 |
+
the formidable Elves, Slippersnail was of a forgotten forest folk, '
|
25 |
+
a tiny creature, small as a sparrow with an oversized leaf as an '
|
26 |
+
umbrella and a snail shell for his home. You could hardly tell if
|
27 |
+
he was a gnome, a brownie or something else, for his kind was
|
28 |
+
scarcely remembered, even in the oldest songs of the Elves.
|
29 |
+
|
30 |
+
Slippersnail, barely tall enough to poke his head above the
|
31 |
+
bracken, lived an unassuming life, busily brewing his famous
|
32 |
+
dandelion tea and tending to his miniature garden filled with
|
33 |
+
colorful nocturnal glow-flowers. One morning, as Slippersnail was
|
34 |
+
pruning his glow-flowers, he found a peculiar golden leaf which
|
35 |
+
glittered so brightly it could outshine the glow-flowers by far.
|
36 |
+
Soon he discovered that the leaf had a magical property: it could
|
37 |
+
create light as bright as a day where the darkness had fallen.
|
38 |
+
|
39 |
+
The news of the magical leaf reached the ears of the Dark Lord in
|
40 |
+
the East. Coveting the leaf to manipulate it for his evil motives,
|
41 |
+
Sauron dispatched a band of his malevolent minions in search of
|
42 |
+
Slippersnail and his leaf.
|
43 |
+
Unaware of the danger, Slippersnail saw the shadow creeping over
|
44 |
+
his garden now. But, what do you think should our little hero do
|
45 |
+
next?
|
46 |
+
'''
|
47 |
+
|
48 |
+
say(long_text)
|
adaptors/llm.py
CHANGED
@@ -4,12 +4,14 @@ an abstraction over GPT-4 for easy substitution later if needed
|
|
4 |
|
5 |
import openai
|
6 |
import os
|
|
|
7 |
|
8 |
openai.api_key = os.getenv('OPENAI_KEY')
|
9 |
|
10 |
-
|
11 |
-
MODEL = 'gpt-3.5-turbo'
|
12 |
|
|
|
13 |
def answer(system_message, user_and_assistant_messages):
|
14 |
messages = [{
|
15 |
"role":"system",
|
@@ -18,11 +20,16 @@ def answer(system_message, user_and_assistant_messages):
|
|
18 |
|
19 |
messages.extend(user_and_assistant_messages)
|
20 |
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
|
|
|
|
|
|
|
|
|
|
28 |
|
|
|
4 |
|
5 |
import openai
|
6 |
import os
|
7 |
+
from tenacity import retry, wait_random_exponential, stop_after_attempt
|
8 |
|
9 |
openai.api_key = os.getenv('OPENAI_KEY')
|
10 |
|
11 |
+
MODEL = 'gpt-4'
|
12 |
+
#MODEL = 'gpt-3.5-turbo'
|
13 |
|
14 |
+
@retry(wait=wait_random_exponential(multiplier=1, max=40), stop=stop_after_attempt(3))
|
15 |
def answer(system_message, user_and_assistant_messages):
|
16 |
messages = [{
|
17 |
"role":"system",
|
|
|
20 |
|
21 |
messages.extend(user_and_assistant_messages)
|
22 |
|
23 |
+
try:
|
24 |
+
chat_completion = openai.ChatCompletion.create(
|
25 |
+
model=MODEL,
|
26 |
+
messages=messages
|
27 |
+
)
|
28 |
+
output = chat_completion.choices[0].message.content
|
29 |
+
return output
|
30 |
+
|
31 |
+
except Exception as e:
|
32 |
+
print("Unable to generate ChatCompletion response")
|
33 |
+
print(f"Exception: {e}")
|
34 |
+
return e
|
35 |
|
adaptors/voice.py
CHANGED
@@ -6,8 +6,10 @@ import requests
|
|
6 |
import sseclient
|
7 |
from loguru import logger
|
8 |
import os
|
|
|
9 |
from pprint import pprint
|
10 |
import json
|
|
|
11 |
|
12 |
url = "https://play.ht/api/v2/tts"
|
13 |
user_id = os.environ["PLAYHT_USERID"]
|
@@ -20,33 +22,12 @@ headers = {
|
|
20 |
"X-USER-ID": user_id
|
21 |
}
|
22 |
|
23 |
-
|
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",
|
@@ -59,13 +40,15 @@ def say_new(text, voice):
|
|
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)
|
65 |
|
66 |
client = sseclient.SSEClient(resp)
|
67 |
for event in client.events():
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
|
|
|
|
|
|
|
6 |
import sseclient
|
7 |
from loguru import logger
|
8 |
import os
|
9 |
+
import helpers
|
10 |
from pprint import pprint
|
11 |
import json
|
12 |
+
from tenacity import retry, wait_random_exponential, stop_after_attempt
|
13 |
|
14 |
url = "https://play.ht/api/v2/tts"
|
15 |
user_id = os.environ["PLAYHT_USERID"]
|
|
|
22 |
"X-USER-ID": user_id
|
23 |
}
|
24 |
|
25 |
+
valid_voices = ["dylan"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
|
27 |
'''
|
28 |
generate new saying with play.ht
|
29 |
'''
|
30 |
+
def say_new(text, voice="dylan"):
|
31 |
payload = {
|
32 |
"quality": "medium",
|
33 |
"output_format": "mp3",
|
|
|
40 |
response = requests.post(url, stream=True, headers=headers, json=payload)
|
41 |
|
42 |
stream_url = response.headers["content-location"]
|
|
|
43 |
|
44 |
resp = requests.get(stream_url, stream=True, headers=headers)
|
45 |
|
46 |
client = sseclient.SSEClient(resp)
|
47 |
for event in client.events():
|
48 |
+
if event.data:
|
49 |
+
#pprint(event.data)
|
50 |
+
if helpers.is_valid_json(event.data): # play.ht api is unrealiable
|
51 |
+
e = json.loads(event.data)
|
52 |
+
if e["stage"] == "complete":
|
53 |
+
return(e["url"])
|
54 |
+
|
data/stories.db
CHANGED
Binary files a/data/stories.db and b/data/stories.db differ
|
|
helpers/__init__.py
CHANGED
@@ -1,9 +1,24 @@
|
|
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 |
|
@@ -13,20 +28,26 @@ def check_magic_word(w):
|
|
13 |
def get_fixed_msg(msg_type):
|
14 |
|
15 |
fixed_sayings = {
|
16 |
-
"welcome": ["Welcome!
|
17 |
-
"wrong_magic_word": ["
|
18 |
-
"ask_world": ["
|
19 |
-
"ask_hero": ["
|
20 |
-
"ask_plot": ["
|
21 |
-
"ask_ending": ["
|
22 |
-
"ask_style": ["
|
23 |
-
"its_the_end": ["And this is the end of our story. Thank you for
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
|
31 |
else:
|
32 |
raise Exception(f"fixed saying with msg_type {msg_type} not found")
|
|
|
1 |
import uuid
|
2 |
import os
|
3 |
import random
|
4 |
+
import prompts
|
5 |
+
import json
|
6 |
+
from adaptors.llm import answer
|
7 |
+
|
8 |
+
from adaptors.voice import say_new
|
9 |
|
10 |
magic_w = os.environ["MAGICWORD"]
|
11 |
|
12 |
+
'''
|
13 |
+
check if valid JSON
|
14 |
+
'''
|
15 |
+
def is_valid_json(input_string):
|
16 |
+
try:
|
17 |
+
json_object = json.loads(input_string)
|
18 |
+
except json.JSONDecodeError:
|
19 |
+
return False
|
20 |
+
return True
|
21 |
+
|
22 |
def gen_unique_id():
|
23 |
return str(uuid.uuid4())
|
24 |
|
|
|
28 |
def get_fixed_msg(msg_type):
|
29 |
|
30 |
fixed_sayings = {
|
31 |
+
"welcome": ["Welcome, welcome my friend! I'd be happy to tell you a story. But one thing first... Do you know the magic word?"],
|
32 |
+
"wrong_magic_word": ["Oh, my dear, I'm very sorry. But it looks like you don't know the magic word. And I'm afraid I can't tell you the story without the magic word. Please ask around for the magic word and try again then. I'll wait here."],
|
33 |
+
"ask_world": ["Wonderful! That is right... Get ready for a great story that you and I can create together. But before we start, let me ask you a few questions first. What kind of world would you like our story to unfold in? Maybe Middle Earth with elves and orcs? Or a distant future world full of space travel? It can be anything. Just tell me."],
|
34 |
+
"ask_hero": ["That sounds great. And who should our hero be?"],
|
35 |
+
"ask_plot": ["Splendid! Now let's think about the plot of our story. Can you describe in just a few words what our story should be all about. Maybe the hero finds the love of their life? Or maybe they travel far and wide to discover their powers and find friends... it can be anything you want. Just say it and we will make it happen."],
|
36 |
+
"ask_ending": ["That is great. And what kind of ending would you like our story to have? A happy one? A tragic one? Something else?"],
|
37 |
+
"ask_style": ["I see. Now lastly, what kind of storytelling style do you like most? Would you like our story to be funny? Or Epic? Or Poetic? You can decide!"],
|
38 |
+
"its_the_end": ["And this is the end of our story. Thank you, my dear, for making it with me."],
|
39 |
+
"no_more_story": ["I'm very sorry, my dear, but this story has ended. But you can come back again later and we will make another great story together."]
|
40 |
}
|
41 |
|
42 |
if msg_type in fixed_sayings:
|
43 |
saying = random.choice(fixed_sayings[msg_type])
|
44 |
+
system_message = prompts.get('paraphraser')
|
45 |
+
paraphrased = answer(system_message, [{
|
46 |
+
"role" : "user",
|
47 |
+
"content" : saying
|
48 |
+
}])
|
49 |
+
audio = say_new(paraphrased)
|
50 |
+
return audio
|
51 |
|
52 |
else:
|
53 |
raise Exception(f"fixed saying with msg_type {msg_type} not found")
|
homeros.py
CHANGED
@@ -6,8 +6,9 @@ from pprint import pprint
|
|
6 |
from helpers import gen_unique_id
|
7 |
import prompts
|
8 |
from adaptors.llm import answer
|
|
|
9 |
|
10 |
-
MAX_STORY_LEN =
|
11 |
|
12 |
'''
|
13 |
initiates a new story and saves in DB
|
@@ -52,6 +53,10 @@ def continue_story(user_input, story_data):
|
|
52 |
"content": user_input
|
53 |
})
|
54 |
next_chunk_text = create_next_chunk_text(user_input, story)
|
|
|
|
|
|
|
|
|
55 |
next_chunk_audio = create_next_chunk_audio(next_chunk_text)
|
56 |
messages.append({
|
57 |
"role":"assistant",
|
@@ -61,6 +66,8 @@ def continue_story(user_input, story_data):
|
|
61 |
"text" : next_chunk_text,
|
62 |
"audio_url" : next_chunk_audio
|
63 |
})
|
|
|
|
|
64 |
story.chunks = json.dumps(chunks)
|
65 |
story.messages = json.dumps(messages)
|
66 |
story.status = "ongoing"
|
@@ -135,7 +142,7 @@ def evaluate_story(story):
|
|
135 |
evaluation = {}
|
136 |
story_len = len(story["chunks"])
|
137 |
logger.debug(story_len)
|
138 |
-
evaluation["is_time_to_end"] = story_len
|
139 |
|
140 |
return evaluation
|
141 |
|
@@ -144,4 +151,4 @@ def evaluate_story(story):
|
|
144 |
turns next story chunk into audio and returns a URL
|
145 |
'''
|
146 |
def create_next_chunk_audio(text):
|
147 |
-
return
|
|
|
6 |
from helpers import gen_unique_id
|
7 |
import prompts
|
8 |
from adaptors.llm import answer
|
9 |
+
from adaptors.voice import say_new
|
10 |
|
11 |
+
MAX_STORY_LEN = 3 #after how many chunks we force the story to end
|
12 |
|
13 |
'''
|
14 |
initiates a new story and saves in DB
|
|
|
53 |
"content": user_input
|
54 |
})
|
55 |
next_chunk_text = create_next_chunk_text(user_input, story)
|
56 |
+
|
57 |
+
if len(chunks) == 0:
|
58 |
+
next_chunk_text = "May our story begin!\n\n"+next_chunk_text
|
59 |
+
|
60 |
next_chunk_audio = create_next_chunk_audio(next_chunk_text)
|
61 |
messages.append({
|
62 |
"role":"assistant",
|
|
|
66 |
"text" : next_chunk_text,
|
67 |
"audio_url" : next_chunk_audio
|
68 |
})
|
69 |
+
pprint(chunks)
|
70 |
+
pprint(messages)
|
71 |
story.chunks = json.dumps(chunks)
|
72 |
story.messages = json.dumps(messages)
|
73 |
story.status = "ongoing"
|
|
|
142 |
evaluation = {}
|
143 |
story_len = len(story["chunks"])
|
144 |
logger.debug(story_len)
|
145 |
+
evaluation["is_time_to_end"] = story_len >= MAX_STORY_LEN
|
146 |
|
147 |
return evaluation
|
148 |
|
|
|
151 |
turns next story chunk into audio and returns a URL
|
152 |
'''
|
153 |
def create_next_chunk_audio(text):
|
154 |
+
return say_new(text)
|
main.py
CHANGED
@@ -8,12 +8,25 @@ import helpers
|
|
8 |
|
9 |
from homeros import init_story, start_story, continue_story, finish_story, define_metadata, evaluate_story
|
10 |
|
|
|
|
|
11 |
'''
|
12 |
Here we manage the flow and state of the story
|
13 |
'''
|
14 |
def do_homeros(user_input, story):
|
15 |
|
16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
|
18 |
# story hasn't started
|
19 |
if story["status"] == "not_started":
|
@@ -67,7 +80,7 @@ def do_homeros(user_input, story):
|
|
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":
|
@@ -79,7 +92,7 @@ def do_homeros(user_input, story):
|
|
79 |
story = continue_story(user_input, story)
|
80 |
story["status"] = "ongoing"
|
81 |
|
82 |
-
next_message = story["chunks"][-1]["
|
83 |
|
84 |
# story has ended, but the user still inputting. tell them it's over
|
85 |
elif story["status"] == "finished":
|
@@ -113,14 +126,12 @@ with demo:
|
|
113 |
"full_story_text": ""
|
114 |
})
|
115 |
|
116 |
-
pprint(story.value)
|
117 |
-
|
118 |
with gr.Row():
|
119 |
gr.Markdown('''
|
120 |
# HOMEROS
|
121 |
|
122 |
This demo is exploring the future of interactive storytelling.
|
123 |
-
It puts the user in charge and
|
124 |
|
125 |
Hit "Tell me!" to get started.
|
126 |
|
@@ -135,8 +146,9 @@ When Homeros asks you something - hit record, answer with your voice and then hi
|
|
135 |
)
|
136 |
|
137 |
with gr.Row():
|
138 |
-
story_chunk = gr.
|
139 |
-
label="storyteller says"
|
|
|
140 |
)
|
141 |
|
142 |
with gr.Row():
|
|
|
8 |
|
9 |
from homeros import init_story, start_story, continue_story, finish_story, define_metadata, evaluate_story
|
10 |
|
11 |
+
DEFAULT_PARAMS = True
|
12 |
+
|
13 |
'''
|
14 |
Here we manage the flow and state of the story
|
15 |
'''
|
16 |
def do_homeros(user_input, story):
|
17 |
|
18 |
+
# if default params is true - skip the asking, including magic word and just start the story
|
19 |
+
if DEFAULT_PARAMS and len(story["chunks"]) == 0:
|
20 |
+
story = init_story(story)
|
21 |
+
story = define_metadata("J.R.R. Tolkien's Middle Earth", "world", story)
|
22 |
+
story = define_metadata("I don't know. Please choose something unusual.", "hero", story)
|
23 |
+
story = define_metadata("I don't know. Please choose something unusual.", "plot", story)
|
24 |
+
story = define_metadata("Happy", "ending", story)
|
25 |
+
story = define_metadata("epic", "style", story)
|
26 |
+
story["status"] = "ongoing"
|
27 |
+
story = start_story(story)
|
28 |
+
next_message = story["chunks"][-1]["audio_url"]
|
29 |
+
return next_message, story
|
30 |
|
31 |
# story hasn't started
|
32 |
if story["status"] == "not_started":
|
|
|
80 |
story = define_metadata(user_input, "style", story)
|
81 |
story["status"] = "ongoing"
|
82 |
story = start_story(story)
|
83 |
+
next_message = story["chunks"][-1]["audio_url"]
|
84 |
|
85 |
# we are in the middle of the story - evaluate if time to end, or continue
|
86 |
elif story["status"] == "ongoing":
|
|
|
92 |
story = continue_story(user_input, story)
|
93 |
story["status"] = "ongoing"
|
94 |
|
95 |
+
next_message = story["chunks"][-1]["audio_url"]
|
96 |
|
97 |
# story has ended, but the user still inputting. tell them it's over
|
98 |
elif story["status"] == "finished":
|
|
|
126 |
"full_story_text": ""
|
127 |
})
|
128 |
|
|
|
|
|
129 |
with gr.Row():
|
130 |
gr.Markdown('''
|
131 |
# HOMEROS
|
132 |
|
133 |
This demo is exploring the future of interactive storytelling.
|
134 |
+
It puts the user in charge and blurs the boundary between the reader and the author.
|
135 |
|
136 |
Hit "Tell me!" to get started.
|
137 |
|
|
|
146 |
)
|
147 |
|
148 |
with gr.Row():
|
149 |
+
story_chunk = gr.Audio(
|
150 |
+
label="storyteller says",
|
151 |
+
autoplay=True
|
152 |
)
|
153 |
|
154 |
with gr.Row():
|
prompts/__init__.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
from pprint import pprint
|
2 |
from . import storyteller_general
|
|
|
3 |
|
4 |
'''
|
5 |
basic function that substitues variables in the prompt template and returns a ready prompt
|
|
|
1 |
from pprint import pprint
|
2 |
from . import storyteller_general
|
3 |
+
from . import paraphraser
|
4 |
|
5 |
'''
|
6 |
basic function that substitues variables in the prompt template and returns a ready prompt
|
prompts/paraphraser.py
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from string import Template
|
2 |
+
|
3 |
+
'''
|
4 |
+
paraphraser prompt
|
5 |
+
'''
|
6 |
+
|
7 |
+
template = Template('''
|
8 |
+
|
9 |
+
You are a system that helps paraphrase questions and sayings slightly, without changing style or key message. Your paraphrasing should be minimal. Occasionally you can even return unchanged messages.
|
10 |
+
|
11 |
+
The words and terms that shouldn't be changed under any circumstances and should remain in your paraphrased version unchanged:
|
12 |
+
- magic word
|
13 |
+
- hero
|
14 |
+
- plot
|
15 |
+
- world
|
16 |
+
|
17 |
+
The user gives you text and you return back a paraphrased version of the same text. Only return the paraphrased vesion and nothing else.
|
18 |
+
|
19 |
+
''')
|