Update app.py
Browse files
app.py
CHANGED
@@ -34,22 +34,22 @@ def clean_response_text(response_text):
|
|
34 |
cleaned_text = cleaned_text[:-len("```")].strip()
|
35 |
return cleaned_text
|
36 |
|
37 |
-
def generate_ideas(
|
38 |
"""
|
39 |
-
Generate a diverse set of ideas
|
40 |
|
41 |
Args:
|
42 |
-
|
43 |
|
44 |
Returns:
|
45 |
list: A list of ideas as strings.
|
46 |
"""
|
47 |
prompt = f"""
|
48 |
-
|
49 |
-
Each idea should be a short sentence describing a specific scene or concept.
|
50 |
Return the response as a JSON object with a single key 'ideas' containing a list of 5 ideas.
|
51 |
Ensure the response is strictly in JSON format.
|
52 |
-
Example: {{"ideas": ["A neon-lit
|
53 |
"""
|
54 |
try:
|
55 |
response = client.models.generate_content(
|
@@ -68,19 +68,19 @@ def generate_ideas(tag):
|
|
68 |
except Exception as e:
|
69 |
print(f"Error generating ideas: {e}")
|
70 |
return [
|
71 |
-
f"A
|
72 |
-
f"A close-up of {
|
73 |
-
f"A
|
74 |
-
f"A
|
75 |
-
f"An action-packed {
|
76 |
]
|
77 |
|
78 |
-
def generate_item(
|
79 |
"""
|
80 |
Generate a single feed item (image and optionally video) using one of the ideas.
|
81 |
|
82 |
Args:
|
83 |
-
|
84 |
ideas (list): List of ideas to choose from.
|
85 |
generate_video (bool): Whether to generate a video from the image.
|
86 |
max_retries (int): Maximum number of retries if image generation fails.
|
@@ -93,13 +93,13 @@ def generate_item(tag, ideas, generate_video=False, max_retries=3):
|
|
93 |
for attempt in range(max_retries):
|
94 |
selected_idea = random.choice(ideas)
|
95 |
prompt = f"""
|
96 |
-
Based on the idea "{selected_idea}", create content for a TikTok video
|
97 |
Return a JSON object with two keys:
|
98 |
-
- 'caption': A short, viral TikTok-style caption with hashtags.
|
99 |
-
- 'image_prompt': A detailed image prompt for generating a high-quality visual scene.
|
100 |
The image prompt should describe the scene vividly, specify a perspective and style, and ensure no text or letters are included.
|
101 |
Ensure the response is strictly in JSON format.
|
102 |
-
Example: {{"caption": "
|
103 |
"""
|
104 |
try:
|
105 |
response = client.models.generate_content(
|
@@ -118,8 +118,8 @@ def generate_item(tag, ideas, generate_video=False, max_retries=3):
|
|
118 |
image_prompt = response_json['image_prompt']
|
119 |
except Exception as e:
|
120 |
print(f"Error generating item (attempt {attempt + 1}): {e}")
|
121 |
-
text = f"
|
122 |
-
image_prompt = f"A vivid scene of {selected_idea}, in a vibrant pop art style, no text or letters"
|
123 |
|
124 |
# Attempt to generate the image
|
125 |
try:
|
@@ -148,7 +148,8 @@ def generate_item(tag, ideas, generate_video=False, max_retries=3):
|
|
148 |
try:
|
149 |
# Enhance the image prompt for video generation
|
150 |
video_prompt = f"""
|
151 |
-
|
|
|
152 |
using shallow focus on the main subject to emphasize details, in a realistic style with cinematic lighting.
|
153 |
"""
|
154 |
operation = client.models.generate_videos(
|
@@ -160,6 +161,7 @@ def generate_item(tag, ideas, generate_video=False, max_retries=3):
|
|
160 |
number_of_videos=2,
|
161 |
duration_seconds=8,
|
162 |
negative_prompt="blurry, low quality, text, letters",
|
|
|
163 |
)
|
164 |
)
|
165 |
# Wait for videos to generate
|
@@ -167,6 +169,12 @@ def generate_item(tag, ideas, generate_video=False, max_retries=3):
|
|
167 |
time.sleep(20)
|
168 |
operation = client.operations.get(operation)
|
169 |
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
for n, video in enumerate(operation.response.generated_videos):
|
171 |
fname = f'with_image_input{n}.mp4'
|
172 |
print(f"Generated video: {fname}")
|
@@ -200,7 +208,7 @@ def generate_item(tag, ideas, generate_video=False, max_retries=3):
|
|
200 |
'ideas': ideas
|
201 |
}
|
202 |
# Retry with new ideas
|
203 |
-
ideas = generate_ideas(
|
204 |
continue
|
205 |
except Exception as e:
|
206 |
print(f"Error generating image (attempt {attempt + 1}): {e}")
|
@@ -217,33 +225,33 @@ def generate_item(tag, ideas, generate_video=False, max_retries=3):
|
|
217 |
'ideas': ideas
|
218 |
}
|
219 |
# Retry with new ideas
|
220 |
-
ideas = generate_ideas(
|
221 |
continue
|
222 |
|
223 |
-
def start_feed(
|
224 |
"""
|
225 |
-
Start or update the feed based on the
|
226 |
|
227 |
Args:
|
228 |
-
|
229 |
generate_video (bool): Whether to generate a video.
|
230 |
current_index (int): The current item index.
|
231 |
feed_items (list): The current list of feed items.
|
232 |
|
233 |
Returns:
|
234 |
-
tuple: (
|
235 |
"""
|
236 |
-
if not
|
237 |
-
|
238 |
|
239 |
# Set loading state
|
240 |
is_loading = True
|
241 |
-
html_content = generate_html([], False, 0,
|
242 |
share_links = ""
|
243 |
|
244 |
try:
|
245 |
-
ideas = generate_ideas(
|
246 |
-
item = generate_item(
|
247 |
feed_items = [item]
|
248 |
current_index = 0
|
249 |
share_links = generate_share_links(
|
@@ -274,41 +282,41 @@ def start_feed(tag, generate_video, current_index, feed_items):
|
|
274 |
</div>
|
275 |
"""
|
276 |
is_loading = False
|
277 |
-
return
|
278 |
|
279 |
# Set loading state to False and update UI
|
280 |
is_loading = False
|
281 |
-
html_content = generate_html(feed_items, False, current_index,
|
282 |
-
return
|
283 |
|
284 |
-
def load_next(
|
285 |
"""
|
286 |
Load the next item in the feed.
|
287 |
|
288 |
Args:
|
289 |
-
|
290 |
generate_video (bool): Whether to generate a video.
|
291 |
current_index (int): The current item index.
|
292 |
feed_items (list): The current list of feed items.
|
293 |
|
294 |
Returns:
|
295 |
-
tuple: (
|
296 |
"""
|
297 |
is_loading = True
|
298 |
-
html_content = generate_html(feed_items, False, current_index,
|
299 |
share_links = ""
|
300 |
|
301 |
try:
|
302 |
if current_index + 1 < len(feed_items):
|
303 |
current_index += 1
|
304 |
else:
|
305 |
-
ideas = feed_items[-1]['ideas'] if feed_items else generate_ideas(
|
306 |
-
new_item = generate_item(
|
307 |
feed_items.append(new_item)
|
308 |
current_index = len(feed_items) - 1
|
309 |
share_links = generate_share_links(
|
310 |
feed_items[current_index]['image_base64'],
|
311 |
-
feed_items[current_index]['video_base64_list'],
|
312 |
feed_items[current_index]['text']
|
313 |
)
|
314 |
except Exception as e:
|
@@ -332,34 +340,34 @@ def load_next(tag, generate_video, current_index, feed_items):
|
|
332 |
</div>
|
333 |
"""
|
334 |
is_loading = False
|
335 |
-
return
|
336 |
|
337 |
is_loading = False
|
338 |
-
html_content = generate_html(feed_items, False, current_index,
|
339 |
-
return
|
340 |
|
341 |
-
def load_previous(
|
342 |
"""
|
343 |
Load the previous item in the feed.
|
344 |
|
345 |
Args:
|
346 |
-
|
347 |
generate_video (bool): Whether to generate a video (not used here).
|
348 |
current_index (int): The current item index.
|
349 |
feed_items (list): The current list of feed items.
|
350 |
|
351 |
Returns:
|
352 |
-
tuple: (
|
353 |
"""
|
354 |
if current_index > 0:
|
355 |
current_index -= 1
|
356 |
-
html_content = generate_html(feed_items, False, current_index,
|
357 |
share_links = generate_share_links(
|
358 |
feed_items[current_index]['image_base64'],
|
359 |
feed_items[current_index]['video_base64_list'],
|
360 |
feed_items[current_index]['text']
|
361 |
)
|
362 |
-
return
|
363 |
|
364 |
def generate_share_links(image_base64, video_base64_list, caption):
|
365 |
"""
|
@@ -460,7 +468,7 @@ def generate_share_links(image_base64, video_base64_list, caption):
|
|
460 |
"""
|
461 |
return share_links
|
462 |
|
463 |
-
def generate_html(feed_items, scroll_to_latest=False, current_index=0,
|
464 |
"""
|
465 |
Generate an HTML string to display the current feed item with click navigation.
|
466 |
|
@@ -468,18 +476,18 @@ def generate_html(feed_items, scroll_to_latest=False, current_index=0, tag="", i
|
|
468 |
feed_items (list): List of dictionaries containing 'text' and 'image_base64'.
|
469 |
scroll_to_latest (bool): Whether to auto-scroll to the latest item (not used here).
|
470 |
current_index (int): The index of the item to display.
|
471 |
-
|
472 |
is_loading (bool): Whether the feed is currently loading.
|
473 |
|
474 |
Returns:
|
475 |
str: HTML string representing the feed.
|
476 |
"""
|
477 |
loading_messages = [
|
478 |
-
f"Cooking up a {
|
479 |
-
f"Snapping a vibrant {
|
480 |
-
f"Creating a {
|
481 |
-
f"Getting that perfect {
|
482 |
-
f"Bringing {
|
483 |
]
|
484 |
|
485 |
if is_loading:
|
@@ -640,7 +648,7 @@ with gr.Blocks(
|
|
640 |
title="Create Your Feed"
|
641 |
) as demo:
|
642 |
# State variables
|
643 |
-
|
644 |
current_index = gr.State(value=0)
|
645 |
feed_items = gr.State(value=[])
|
646 |
is_loading = gr.State(value=False)
|
@@ -649,7 +657,7 @@ with gr.Blocks(
|
|
649 |
# Input section
|
650 |
with gr.Column(elem_classes="gr-form"):
|
651 |
gr.Markdown("### Create Your Feed")
|
652 |
-
|
653 |
label="Enter Concept or Ideas",
|
654 |
value="",
|
655 |
placeholder="e.g., sushi adventure, neon tech",
|
@@ -667,17 +675,17 @@ with gr.Blocks(
|
|
667 |
|
668 |
# Event handlers
|
669 |
# Handle Enter keypress in the concept input
|
670 |
-
|
671 |
fn=start_feed,
|
672 |
-
inputs=[
|
673 |
-
outputs=[
|
674 |
)
|
675 |
|
676 |
# Handle magic button click to generate next item
|
677 |
magic_button.click(
|
678 |
fn=load_next,
|
679 |
-
inputs=[
|
680 |
-
outputs=[
|
681 |
)
|
682 |
|
683 |
# Hidden button for previous item navigation
|
@@ -686,8 +694,8 @@ with gr.Blocks(
|
|
686 |
# Handle click to go to previous item
|
687 |
previous_button.click(
|
688 |
fn=load_previous,
|
689 |
-
inputs=[
|
690 |
-
outputs=[
|
691 |
)
|
692 |
|
693 |
# Launch the app
|
|
|
34 |
cleaned_text = cleaned_text[:-len("```")].strip()
|
35 |
return cleaned_text
|
36 |
|
37 |
+
def generate_ideas(user_input):
|
38 |
"""
|
39 |
+
Generate a diverse set of ideas based on the user's input concept using the LLM.
|
40 |
|
41 |
Args:
|
42 |
+
user_input (str): The user's input concept or idea (e.g., "blindfolded Rubik's Cube challenge").
|
43 |
|
44 |
Returns:
|
45 |
list: A list of ideas as strings.
|
46 |
"""
|
47 |
prompt = f"""
|
48 |
+
The user has provided the concept: "{user_input}". Based on this concept, generate a list of 5 diverse and creative ideas for a TikTok video that directly relate to "{user_input}".
|
49 |
+
Each idea should be a short sentence describing a specific scene or concept, ensuring the core theme of "{user_input}" is central to each idea.
|
50 |
Return the response as a JSON object with a single key 'ideas' containing a list of 5 ideas.
|
51 |
Ensure the response is strictly in JSON format.
|
52 |
+
Example: {{"ideas": ["A neon-lit Rubik's Cube challenge in the dark", "A blindfolded speedcubing competition with dramatic music"]}}
|
53 |
"""
|
54 |
try:
|
55 |
response = client.models.generate_content(
|
|
|
68 |
except Exception as e:
|
69 |
print(f"Error generating ideas: {e}")
|
70 |
return [
|
71 |
+
f"A dramatic {user_input} scene with cinematic lighting",
|
72 |
+
f"A close-up of {user_input} in a futuristic setting",
|
73 |
+
f"A high-energy {user_input} moment with vibrant colors",
|
74 |
+
f"A serene {user_input} scene with soft focus",
|
75 |
+
f"An action-packed {user_input} challenge with dynamic angles"
|
76 |
]
|
77 |
|
78 |
+
def generate_item(user_input, ideas, generate_video=False, max_retries=3):
|
79 |
"""
|
80 |
Generate a single feed item (image and optionally video) using one of the ideas.
|
81 |
|
82 |
Args:
|
83 |
+
user_input (str): The user's input concept or idea.
|
84 |
ideas (list): List of ideas to choose from.
|
85 |
generate_video (bool): Whether to generate a video from the image.
|
86 |
max_retries (int): Maximum number of retries if image generation fails.
|
|
|
93 |
for attempt in range(max_retries):
|
94 |
selected_idea = random.choice(ideas)
|
95 |
prompt = f"""
|
96 |
+
The user has provided the concept: "{user_input}". Based on this concept and the specific idea "{selected_idea}", create content for a TikTok video.
|
97 |
Return a JSON object with two keys:
|
98 |
+
- 'caption': A short, viral TikTok-style caption with hashtags that reflects "{user_input}".
|
99 |
+
- 'image_prompt': A detailed image prompt for generating a high-quality visual scene, ensuring the theme of "{user_input}" is central.
|
100 |
The image prompt should describe the scene vividly, specify a perspective and style, and ensure no text or letters are included.
|
101 |
Ensure the response is strictly in JSON format.
|
102 |
+
Example: {{"caption": "Blindfolded Rubik's Cube MAGIC! π€― #rubiks", "image_prompt": "A close-up view of a person solving a Rubik's Cube blindfolded, in a dramatic style, no text or letters"}}
|
103 |
"""
|
104 |
try:
|
105 |
response = client.models.generate_content(
|
|
|
118 |
image_prompt = response_json['image_prompt']
|
119 |
except Exception as e:
|
120 |
print(f"Error generating item (attempt {attempt + 1}): {e}")
|
121 |
+
text = f"Amazing {user_input}! π₯ #{user_input.replace(' ', '')}"
|
122 |
+
image_prompt = f"A vivid scene of {selected_idea} related to {user_input}, in a vibrant pop art style, no text or letters"
|
123 |
|
124 |
# Attempt to generate the image
|
125 |
try:
|
|
|
148 |
try:
|
149 |
# Enhance the image prompt for video generation
|
150 |
video_prompt = f"""
|
151 |
+
The user concept is "{user_input}". Based on this and the scene: {image_prompt}, create a video.
|
152 |
+
Use a close-up shot with a slow dolly shot circling around the subject,
|
153 |
using shallow focus on the main subject to emphasize details, in a realistic style with cinematic lighting.
|
154 |
"""
|
155 |
operation = client.models.generate_videos(
|
|
|
161 |
number_of_videos=2,
|
162 |
duration_seconds=8,
|
163 |
negative_prompt="blurry, low quality, text, letters",
|
164 |
+
enhance_prompt=True
|
165 |
)
|
166 |
)
|
167 |
# Wait for videos to generate
|
|
|
169 |
time.sleep(20)
|
170 |
operation = client.operations.get(operation)
|
171 |
|
172 |
+
# Check if operation succeeded and has a valid response
|
173 |
+
if operation.response is None:
|
174 |
+
raise ValueError("Video generation operation failed: No response")
|
175 |
+
if not hasattr(operation.response, 'generated_videos'):
|
176 |
+
raise ValueError("Video generation operation failed: No generated_videos in response")
|
177 |
+
|
178 |
for n, video in enumerate(operation.response.generated_videos):
|
179 |
fname = f'with_image_input{n}.mp4'
|
180 |
print(f"Generated video: {fname}")
|
|
|
208 |
'ideas': ideas
|
209 |
}
|
210 |
# Retry with new ideas
|
211 |
+
ideas = generate_ideas(user_input)
|
212 |
continue
|
213 |
except Exception as e:
|
214 |
print(f"Error generating image (attempt {attempt + 1}): {e}")
|
|
|
225 |
'ideas': ideas
|
226 |
}
|
227 |
# Retry with new ideas
|
228 |
+
ideas = generate_ideas(user_input)
|
229 |
continue
|
230 |
|
231 |
+
def start_feed(user_input, generate_video, current_index, feed_items):
|
232 |
"""
|
233 |
+
Start or update the feed based on the user input.
|
234 |
|
235 |
Args:
|
236 |
+
user_input (str): The user's input concept or idea.
|
237 |
generate_video (bool): Whether to generate a video.
|
238 |
current_index (int): The current item index.
|
239 |
feed_items (list): The current list of feed items.
|
240 |
|
241 |
Returns:
|
242 |
+
tuple: (current_user_input, current_index, feed_items, html_content, share_links, is_loading)
|
243 |
"""
|
244 |
+
if not user_input.strip():
|
245 |
+
user_input = "trending"
|
246 |
|
247 |
# Set loading state
|
248 |
is_loading = True
|
249 |
+
html_content = generate_html([], False, 0, user_input, is_loading)
|
250 |
share_links = ""
|
251 |
|
252 |
try:
|
253 |
+
ideas = generate_ideas(user_input)
|
254 |
+
item = generate_item(user_input, ideas, generate_video=generate_video)
|
255 |
feed_items = [item]
|
256 |
current_index = 0
|
257 |
share_links = generate_share_links(
|
|
|
282 |
</div>
|
283 |
"""
|
284 |
is_loading = False
|
285 |
+
return user_input, current_index, feed_items, html_content, share_links, is_loading
|
286 |
|
287 |
# Set loading state to False and update UI
|
288 |
is_loading = False
|
289 |
+
html_content = generate_html(feed_items, False, current_index, user_input, is_loading)
|
290 |
+
return user_input, current_index, feed_items, html_content, share_links, is_loading
|
291 |
|
292 |
+
def load_next(user_input, generate_video, current_index, feed_items):
|
293 |
"""
|
294 |
Load the next item in the feed.
|
295 |
|
296 |
Args:
|
297 |
+
user_input (str): The user's input concept or idea.
|
298 |
generate_video (bool): Whether to generate a video.
|
299 |
current_index (int): The current item index.
|
300 |
feed_items (list): The current list of feed items.
|
301 |
|
302 |
Returns:
|
303 |
+
tuple: (current_user_input, current_index, feed_items, html_content, share_links, is_loading)
|
304 |
"""
|
305 |
is_loading = True
|
306 |
+
html_content = generate_html(feed_items, False, current_index, user_input, is_loading)
|
307 |
share_links = ""
|
308 |
|
309 |
try:
|
310 |
if current_index + 1 < len(feed_items):
|
311 |
current_index += 1
|
312 |
else:
|
313 |
+
ideas = feed_items[-1]['ideas'] if feed_items else generate_ideas(user_input)
|
314 |
+
new_item = generate_item(user_input, ideas, generate_video=generate_video)
|
315 |
feed_items.append(new_item)
|
316 |
current_index = len(feed_items) - 1
|
317 |
share_links = generate_share_links(
|
318 |
feed_items[current_index]['image_base64'],
|
319 |
+
feed_items[current_index]['video_base64_list'],
|
320 |
feed_items[current_index]['text']
|
321 |
)
|
322 |
except Exception as e:
|
|
|
340 |
</div>
|
341 |
"""
|
342 |
is_loading = False
|
343 |
+
return user_input, current_index, feed_items, html_content, share_links, is_loading
|
344 |
|
345 |
is_loading = False
|
346 |
+
html_content = generate_html(feed_items, False, current_index, user_input, is_loading)
|
347 |
+
return user_input, current_index, feed_items, html_content, share_links, is_loading
|
348 |
|
349 |
+
def load_previous(user_input, generate_video, current_index, feed_items):
|
350 |
"""
|
351 |
Load the previous item in the feed.
|
352 |
|
353 |
Args:
|
354 |
+
user_input (str): The user's input concept or idea.
|
355 |
generate_video (bool): Whether to generate a video (not used here).
|
356 |
current_index (int): The current item index.
|
357 |
feed_items (list): The current list of feed items.
|
358 |
|
359 |
Returns:
|
360 |
+
tuple: (current_user_input, current_index, feed_items, html_content, share_links, is_loading)
|
361 |
"""
|
362 |
if current_index > 0:
|
363 |
current_index -= 1
|
364 |
+
html_content = generate_html(feed_items, False, current_index, user_input, False)
|
365 |
share_links = generate_share_links(
|
366 |
feed_items[current_index]['image_base64'],
|
367 |
feed_items[current_index]['video_base64_list'],
|
368 |
feed_items[current_index]['text']
|
369 |
)
|
370 |
+
return user_input, current_index, feed_items, html_content, share_links, False
|
371 |
|
372 |
def generate_share_links(image_base64, video_base64_list, caption):
|
373 |
"""
|
|
|
468 |
"""
|
469 |
return share_links
|
470 |
|
471 |
+
def generate_html(feed_items, scroll_to_latest=False, current_index=0, user_input="", is_loading=False):
|
472 |
"""
|
473 |
Generate an HTML string to display the current feed item with click navigation.
|
474 |
|
|
|
476 |
feed_items (list): List of dictionaries containing 'text' and 'image_base64'.
|
477 |
scroll_to_latest (bool): Whether to auto-scroll to the latest item (not used here).
|
478 |
current_index (int): The index of the item to display.
|
479 |
+
user_input (str): The user's input concept or idea for loading messages.
|
480 |
is_loading (bool): Whether the feed is currently loading.
|
481 |
|
482 |
Returns:
|
483 |
str: HTML string representing the feed.
|
484 |
"""
|
485 |
loading_messages = [
|
486 |
+
f"Cooking up a {user_input} masterpiece... π³",
|
487 |
+
f"Snapping a vibrant {user_input} moment... πΈ",
|
488 |
+
f"Creating a {user_input} vibe that pops... β¨",
|
489 |
+
f"Getting that perfect {user_input} shot... π₯",
|
490 |
+
f"Bringing {user_input} to life... π"
|
491 |
]
|
492 |
|
493 |
if is_loading:
|
|
|
648 |
title="Create Your Feed"
|
649 |
) as demo:
|
650 |
# State variables
|
651 |
+
current_user_input = gr.State(value="")
|
652 |
current_index = gr.State(value=0)
|
653 |
feed_items = gr.State(value=[])
|
654 |
is_loading = gr.State(value=False)
|
|
|
657 |
# Input section
|
658 |
with gr.Column(elem_classes="gr-form"):
|
659 |
gr.Markdown("### Create Your Feed")
|
660 |
+
user_input = gr.Textbox(
|
661 |
label="Enter Concept or Ideas",
|
662 |
value="",
|
663 |
placeholder="e.g., sushi adventure, neon tech",
|
|
|
675 |
|
676 |
# Event handlers
|
677 |
# Handle Enter keypress in the concept input
|
678 |
+
user_input.submit(
|
679 |
fn=start_feed,
|
680 |
+
inputs=[user_input, generate_video_checkbox, current_index, feed_items],
|
681 |
+
outputs=[current_user_input, current_index, feed_items, feed_html, share_html, is_loading]
|
682 |
)
|
683 |
|
684 |
# Handle magic button click to generate next item
|
685 |
magic_button.click(
|
686 |
fn=load_next,
|
687 |
+
inputs=[current_user_input, generate_video_checkbox, current_index, feed_items],
|
688 |
+
outputs=[current_user_input, current_index, feed_items, feed_html, share_html, is_loading]
|
689 |
)
|
690 |
|
691 |
# Hidden button for previous item navigation
|
|
|
694 |
# Handle click to go to previous item
|
695 |
previous_button.click(
|
696 |
fn=load_previous,
|
697 |
+
inputs=[current_user_input, generate_video_checkbox, current_index, feed_items],
|
698 |
+
outputs=[current_user_input, current_index, feed_items, feed_html, share_html, is_loading]
|
699 |
)
|
700 |
|
701 |
# Launch the app
|