Spaces:
Running
Running
Sunil Surendra Singh
commited on
Commit
•
3253a7e
1
Parent(s):
65f6ddd
added genre and story style input params
Browse files- README.md +3 -1
- app.py +82 -33
- assets/story-teller-app.png +2 -2
- assets/story-teller-examples.png +2 -2
- config.py +35 -0
- model.py +16 -8
README.md
CHANGED
@@ -30,7 +30,7 @@ BLIP Image2Text model details can be found [here](https://huggingface.co/Sof22/i
|
|
30 |
|
31 |
* It's important to note that this sample demonstration app is hosted on the free tiers of Huggingface Spaces, which means it is functional but may exhibit slower performance.
|
32 |
* Additionally, when using the app for the first time or after an extended period (more than 1 hour), you might encounter an "Internal Error" message or receive a story unrelated to the provided image. This is a normal occurrence during the model loading process. Please wait a few seconds and try again; it should function as intended.
|
33 |
-
* Please be aware that due to cost and resource constraints, the app currently has a maximum story length limit of
|
34 |
|
35 |
App UI is shown below:
|
36 |
|
@@ -38,6 +38,8 @@ App UI is shown below:
|
|
38 |
|
39 |
**Dark Mode Toggle**: Activate it to switch between dark and light mode.
|
40 |
**Image Selector**: Click on it to pick an image from your computer, or drag and drop an image onto it directly. Click the 'X' to clear the selection and resets the app.
|
|
|
|
|
41 |
**Story Length (in words) Slider**: Adjust the slider to specify the desired length of the generated story.
|
42 |
**Creativity Index Slider**: Modify the slider to indicate the desired level of creativity for the generated story. A range between 0.5 and 0.7 is recommended. Setting it to 1.0 results in highly creative, sometimes amusing output.
|
43 |
**Generate Story Button**: Press this button to initiate the story generation process.
|
|
|
30 |
|
31 |
* It's important to note that this sample demonstration app is hosted on the free tiers of Huggingface Spaces, which means it is functional but may exhibit slower performance.
|
32 |
* Additionally, when using the app for the first time or after an extended period (more than 1 hour), you might encounter an "Internal Error" message or receive a story unrelated to the provided image. This is a normal occurrence during the model loading process. Please wait a few seconds and try again; it should function as intended.
|
33 |
+
* Please be aware that due to cost and resource constraints, the app currently has a maximum story length limit of 200 words per request.
|
34 |
|
35 |
App UI is shown below:
|
36 |
|
|
|
38 |
|
39 |
**Dark Mode Toggle**: Activate it to switch between dark and light mode.
|
40 |
**Image Selector**: Click on it to pick an image from your computer, or drag and drop an image onto it directly. Click the 'X' to clear the selection and resets the app.
|
41 |
+
**Story Genre Dropdown**: Select the desired story genre from the dropdown list.
|
42 |
+
**Story Writing Style Dropdown**: Select the desired story writing style from the dropdown list.
|
43 |
**Story Length (in words) Slider**: Adjust the slider to specify the desired length of the generated story.
|
44 |
**Creativity Index Slider**: Modify the slider to indicate the desired level of creativity for the generated story. A range between 0.5 and 0.7 is recommended. Setting it to 1.0 results in highly creative, sometimes amusing output.
|
45 |
**Generate Story Button**: Press this button to initiate the story generation process.
|
app.py
CHANGED
@@ -30,21 +30,25 @@ def create_interface():
|
|
30 |
api_name=False,
|
31 |
)
|
32 |
with gr.Row():
|
33 |
-
with gr.Column(
|
34 |
gr.Markdown(
|
35 |
"""
|
36 |
-
# Storyteller
|
37 |
**This app can craft captivating narratives from captivating images,
|
38 |
-
potentially surpassing even Shakespearean standards.
|
39 |
-
|
40 |
-
|
|
|
|
|
|
|
|
|
41 |
<br>
|
42 |
-
***Please exercise patience, as the models employed are extensive
|
43 |
-
require a few seconds to load. If you encounter an unrelated
|
44 |
-
it is likely still loading; wait a moment and try again.***
|
45 |
"""
|
46 |
)
|
47 |
-
with gr.Column(
|
48 |
max_count = gr.Textbox(
|
49 |
label="Max allowed OpenAI requests:",
|
50 |
value=app_config.openai_max_access_count,
|
@@ -63,21 +67,34 @@ def create_interface():
|
|
63 |
image = gr.Image(
|
64 |
type="filepath",
|
65 |
)
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
with gr.Row():
|
82 |
submit_button = gr.Button(
|
83 |
value="Generate Story", elem_classes="orange-button"
|
@@ -87,24 +104,56 @@ def create_interface():
|
|
87 |
story = gr.Textbox(
|
88 |
label="Story:",
|
89 |
placeholder="Generated story will appear here.",
|
90 |
-
lines=
|
91 |
)
|
92 |
with gr.Row():
|
93 |
with gr.Accordion("Expand for examples:", open=False):
|
94 |
gr.Examples(
|
95 |
examples=[
|
96 |
-
[
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
101 |
],
|
102 |
-
|
103 |
-
|
|
|
|
|
104 |
)
|
105 |
submit_button.click(
|
106 |
fn=model.generate_story,
|
107 |
-
inputs=[image, word_count, creativity],
|
108 |
outputs=[story, max_count, curr_count, available_count],
|
109 |
)
|
110 |
clear_button.click(
|
|
|
30 |
api_name=False,
|
31 |
)
|
32 |
with gr.Row():
|
33 |
+
with gr.Column():
|
34 |
gr.Markdown(
|
35 |
"""
|
36 |
+
# The Storyteller
|
37 |
**This app can craft captivating narratives from captivating images,
|
38 |
+
potentially surpassing even Shakespearean standards.
|
39 |
+
<br>
|
40 |
+
Select an `Image` that inspires a story, choose a `Story Genre`,
|
41 |
+
`Story Writing Style`, `Story Length (up to 200 words)`, and
|
42 |
+
adjust the `Creativity Index` to enhance its creative flair. Then
|
43 |
+
hit `Generate Story` button.
|
44 |
+
Alternatively, just select one the pre-configured `Examples`**
|
45 |
<br>
|
46 |
+
***Please exercise patience, as the models employed are extensive
|
47 |
+
and may require a few seconds to load. If you encounter an unrelated
|
48 |
+
story, it is likely still loading; wait a moment and try again.***
|
49 |
"""
|
50 |
)
|
51 |
+
with gr.Column():
|
52 |
max_count = gr.Textbox(
|
53 |
label="Max allowed OpenAI requests:",
|
54 |
value=app_config.openai_max_access_count,
|
|
|
67 |
image = gr.Image(
|
68 |
type="filepath",
|
69 |
)
|
70 |
+
with gr.Row():
|
71 |
+
with gr.Column():
|
72 |
+
genre = gr.Dropdown(
|
73 |
+
label="Story Genre: ",
|
74 |
+
value="Poetry",
|
75 |
+
choices=app_config.genre,
|
76 |
+
)
|
77 |
+
style = gr.Dropdown(
|
78 |
+
label="Story Writing Style:",
|
79 |
+
value="Cinematic",
|
80 |
+
choices=app_config.writing_style_list,
|
81 |
+
)
|
82 |
+
with gr.Column():
|
83 |
+
# Word Count Slider
|
84 |
+
word_count = gr.Slider(
|
85 |
+
label="Story Length (words):",
|
86 |
+
minimum=30,
|
87 |
+
maximum=200,
|
88 |
+
value=50,
|
89 |
+
step=10,
|
90 |
+
)
|
91 |
+
creativity = gr.Slider(
|
92 |
+
label="Creativity Index:",
|
93 |
+
minimum=0.3,
|
94 |
+
maximum=1.0,
|
95 |
+
value=0.7,
|
96 |
+
step=0.1,
|
97 |
+
)
|
98 |
with gr.Row():
|
99 |
submit_button = gr.Button(
|
100 |
value="Generate Story", elem_classes="orange-button"
|
|
|
104 |
story = gr.Textbox(
|
105 |
label="Story:",
|
106 |
placeholder="Generated story will appear here.",
|
107 |
+
lines=21,
|
108 |
)
|
109 |
with gr.Row():
|
110 |
with gr.Accordion("Expand for examples:", open=False):
|
111 |
gr.Examples(
|
112 |
examples=[
|
113 |
+
[
|
114 |
+
"assets/examples/cheetah-deer.jpg",
|
115 |
+
"Horror",
|
116 |
+
"Narrative",
|
117 |
+
80,
|
118 |
+
0.5,
|
119 |
+
],
|
120 |
+
[
|
121 |
+
"assets/examples/man-child-pet-dog.jpg",
|
122 |
+
"Fiction",
|
123 |
+
"Formal",
|
124 |
+
100,
|
125 |
+
0.6,
|
126 |
+
],
|
127 |
+
[
|
128 |
+
"assets/examples/man-child.jpeg",
|
129 |
+
"Children Literature",
|
130 |
+
"Symbolic",
|
131 |
+
120,
|
132 |
+
1.0,
|
133 |
+
],
|
134 |
+
[
|
135 |
+
"assets/examples/men-fighting.jpg",
|
136 |
+
"Comedy",
|
137 |
+
"Experimental",
|
138 |
+
60,
|
139 |
+
0.4,
|
140 |
+
],
|
141 |
+
[
|
142 |
+
"assets/examples/teacher-school.jpg",
|
143 |
+
"Surrealism",
|
144 |
+
"Non-linear",
|
145 |
+
80,
|
146 |
+
0.7,
|
147 |
+
],
|
148 |
],
|
149 |
+
fn=model.generate_story,
|
150 |
+
inputs=[image, genre, style, word_count, creativity],
|
151 |
+
outputs=[story, max_count, curr_count, available_count],
|
152 |
+
run_on_click=True,
|
153 |
)
|
154 |
submit_button.click(
|
155 |
fn=model.generate_story,
|
156 |
+
inputs=[image, genre, style, word_count, creativity],
|
157 |
outputs=[story, max_count, curr_count, available_count],
|
158 |
)
|
159 |
clear_button.click(
|
assets/story-teller-app.png
CHANGED
Git LFS Details
|
Git LFS Details
|
assets/story-teller-examples.png
CHANGED
Git LFS Details
|
Git LFS Details
|
config.py
CHANGED
@@ -17,6 +17,41 @@ class AppConfig:
|
|
17 |
OPENAI_KEY = os.getenv("OPENAI_KEY")
|
18 |
I2T_API_URL = os.getenv("I2T_API_URL")
|
19 |
MONGO_CONN_STR = os.getenv("MONGO_CONN_STR")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
|
21 |
|
22 |
app_config = AppConfig()
|
|
|
17 |
OPENAI_KEY = os.getenv("OPENAI_KEY")
|
18 |
I2T_API_URL = os.getenv("I2T_API_URL")
|
19 |
MONGO_CONN_STR = os.getenv("MONGO_CONN_STR")
|
20 |
+
genre_list = genre = [
|
21 |
+
"Adventure",
|
22 |
+
"Children Literature",
|
23 |
+
"Comedy",
|
24 |
+
"Drama",
|
25 |
+
"Fantasy",
|
26 |
+
"Fiction",
|
27 |
+
"Horror",
|
28 |
+
"Mystery",
|
29 |
+
"Non-fiction",
|
30 |
+
"Poetry",
|
31 |
+
"Romance",
|
32 |
+
"Satire",
|
33 |
+
"Surrealism",
|
34 |
+
"Urban Fantasy",
|
35 |
+
]
|
36 |
+
writing_style_list = [
|
37 |
+
"Cinematic",
|
38 |
+
"Conversational",
|
39 |
+
"Descriptive",
|
40 |
+
"Experimental",
|
41 |
+
"First-Person",
|
42 |
+
"Formal",
|
43 |
+
"Informal",
|
44 |
+
"Metaphorical",
|
45 |
+
"Minimalist",
|
46 |
+
"Narrative",
|
47 |
+
"Non-linear",
|
48 |
+
"Objective",
|
49 |
+
"Sensory",
|
50 |
+
"Stream of Consciousness",
|
51 |
+
"Symbolic",
|
52 |
+
"Third-Person Limited",
|
53 |
+
"Third-Person Omniscient",
|
54 |
+
]
|
55 |
|
56 |
|
57 |
app_config = AppConfig()
|
model.py
CHANGED
@@ -22,7 +22,7 @@ def __image2text(image):
|
|
22 |
return response
|
23 |
|
24 |
|
25 |
-
def __text2story(image_desc, word_count, creativity):
|
26 |
""" "Generates a short story based on image description text prompt"""
|
27 |
## chat LLM model
|
28 |
story_model = ChatOpenAI(
|
@@ -32,13 +32,15 @@ def __text2story(image_desc, word_count, creativity):
|
|
32 |
)
|
33 |
## chat message prompts
|
34 |
sys_prompt = PromptTemplate(
|
35 |
-
template="You are an expert
|
36 |
-
|
37 |
-
|
|
|
|
|
38 |
)
|
39 |
system_msg_prompt = SystemMessagePromptTemplate(prompt=sys_prompt)
|
40 |
human_prompt = PromptTemplate(
|
41 |
-
template="{
|
42 |
)
|
43 |
human_msg_prompt = HumanMessagePromptTemplate(prompt=human_prompt)
|
44 |
chat_prompt = ChatPromptTemplate.from_messages(
|
@@ -46,11 +48,13 @@ def __text2story(image_desc, word_count, creativity):
|
|
46 |
)
|
47 |
## LLM chain
|
48 |
story_chain = LLMChain(llm=story_model, prompt=chat_prompt)
|
49 |
-
response = story_chain.run(
|
|
|
|
|
50 |
return response
|
51 |
|
52 |
|
53 |
-
def generate_story(image_file, word_count, creativity):
|
54 |
"""Generates a story given an image"""
|
55 |
# read image as bytes arrayS
|
56 |
with open(image_file, "rb") as f:
|
@@ -59,7 +63,11 @@ def generate_story(image_file, word_count, creativity):
|
|
59 |
image_desc = __image2text(image=input_image)
|
60 |
# generate story from caption
|
61 |
story = __text2story(
|
62 |
-
image_desc=image_desc,
|
|
|
|
|
|
|
|
|
63 |
)
|
64 |
# increment the openai access counter and compute count stats
|
65 |
mongo.increment_curr_access_count()
|
|
|
22 |
return response
|
23 |
|
24 |
|
25 |
+
def __text2story(image_desc, genre, style, word_count, creativity):
|
26 |
""" "Generates a short story based on image description text prompt"""
|
27 |
## chat LLM model
|
28 |
story_model = ChatOpenAI(
|
|
|
32 |
)
|
33 |
## chat message prompts
|
34 |
sys_prompt = PromptTemplate(
|
35 |
+
template="""You are an expert story writer, write a maximum of {word_count}
|
36 |
+
words long story in {genre} genre in {style} writing style, based on the user
|
37 |
+
provided story-context.
|
38 |
+
""",
|
39 |
+
input_variables=["word_count", "genre", "style"],
|
40 |
)
|
41 |
system_msg_prompt = SystemMessagePromptTemplate(prompt=sys_prompt)
|
42 |
human_prompt = PromptTemplate(
|
43 |
+
template="story-context: {context}", input_variables=["context"]
|
44 |
)
|
45 |
human_msg_prompt = HumanMessagePromptTemplate(prompt=human_prompt)
|
46 |
chat_prompt = ChatPromptTemplate.from_messages(
|
|
|
48 |
)
|
49 |
## LLM chain
|
50 |
story_chain = LLMChain(llm=story_model, prompt=chat_prompt)
|
51 |
+
response = story_chain.run(
|
52 |
+
genre=genre, style=style, word_count=word_count, context=image_desc
|
53 |
+
)
|
54 |
return response
|
55 |
|
56 |
|
57 |
+
def generate_story(image_file, genre, style, word_count, creativity):
|
58 |
"""Generates a story given an image"""
|
59 |
# read image as bytes arrayS
|
60 |
with open(image_file, "rb") as f:
|
|
|
63 |
image_desc = __image2text(image=input_image)
|
64 |
# generate story from caption
|
65 |
story = __text2story(
|
66 |
+
image_desc=image_desc,
|
67 |
+
genre=genre,
|
68 |
+
style=style,
|
69 |
+
word_count=word_count,
|
70 |
+
creativity=creativity,
|
71 |
)
|
72 |
# increment the openai access counter and compute count stats
|
73 |
mongo.increment_curr_access_count()
|