awacke1 commited on
Commit
94a8dcd
ยท
verified ยท
1 Parent(s): 27f1cdd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +94 -149
app.py CHANGED
@@ -1,3 +1,4 @@
 
1
  import gradio as gr
2
  import random
3
  from datetime import datetime
@@ -15,161 +16,80 @@ from gradio_client import Client
15
 
16
  warnings.filterwarnings('ignore')
17
 
18
- # Initialize story starters with added comedy section
19
- STORY_STARTERS = [
20
- ['Adventure', 'In a hidden temple deep in the Amazon...'],
21
- ['Mystery', 'The detective found an unusual note...'],
22
- ['Romance', 'Two strangers meet on a rainy evening...'],
23
- ['Sci-Fi', 'The space station received an unexpected signal...'],
24
- ['Fantasy', 'A magical portal appeared in the garden...'],
25
- ['Comedy-Sitcom', 'The new roommate arrived with seven emotional support animals...'],
26
- ['Comedy-Workplace', 'The office printer started sending mysterious messages...'],
27
- ['Comedy-Family', 'Grandma decided to become a social media influencer...'],
28
- ['Comedy-Supernatural', 'The ghost haunting the house was absolutely terrible at scaring people...'],
29
- ['Comedy-Travel', 'The GPS insisted on giving directions in interpretive dance descriptions...']
30
- ]
31
 
32
- # Initialize client outside of interface definition
33
- arxiv_client = None
34
 
35
- def init_client():
36
- global arxiv_client
37
- if arxiv_client is None:
38
- arxiv_client = Client("awacke1/Arxiv-Paper-Search-And-QA-RAG-Pattern")
39
- return arxiv_client
40
 
41
- def save_story(story, audio_path):
42
- """Save story and audio to gallery with markdown formatting"""
43
  try:
44
- # Create gallery directory if it doesn't exist
45
- gallery_dir = Path("gallery")
46
- gallery_dir.mkdir(exist_ok=True)
47
-
48
- # Generate timestamp and sanitize first line for filename
49
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
50
- first_line = story.split('\n')[0].strip()
51
- safe_name = re.sub(r'[^\w\s-]', '', first_line)[:50] # First 50 chars, sanitized
52
-
53
- # Save story text as markdown
54
- story_path = gallery_dir / f"story_{timestamp}_{safe_name}.md"
55
- with open(story_path, "w") as f:
56
- f.write(f"# {first_line}\n\n{story}")
57
-
58
- # Copy audio file to gallery with matching name
59
- new_audio_path = None
60
- if audio_path:
61
- new_audio_path = gallery_dir / f"audio_{timestamp}_{safe_name}.mp3"
62
- os.system(f"cp {audio_path} {str(new_audio_path)}")
63
-
64
- return str(story_path), str(new_audio_path) if new_audio_path else None
65
- except Exception as e:
66
- print(f"Error saving to gallery: {str(e)}")
67
- return None, None
68
-
69
- def load_gallery():
70
- """Load all stories and audio from gallery with markdown support"""
71
- try:
72
- gallery_dir = Path("gallery")
73
- if not gallery_dir.exists():
74
- return []
75
-
76
- files = []
77
- for story_file in sorted(gallery_dir.glob("story_*.md"), reverse=True):
78
- # Extract timestamp and name from filename
79
- parts = story_file.stem.split('_', 2)
80
- timestamp = f"{parts[1]}"
81
 
82
- # Find matching audio file
 
 
 
83
  audio_pattern = f"audio_{timestamp}_*.mp3"
84
- audio_files = list(gallery_dir.glob(audio_pattern))
85
- audio_file = audio_files[0] if audio_files else None
86
-
87
- # Read story content and get preview
88
- with open(story_file) as f:
89
- content = f.read()
90
- # Skip markdown header and get preview
91
- preview = content.split('\n\n', 1)[1][:100] + "..."
92
 
93
- files.append([
94
- timestamp,
95
- f"[{preview}]({str(story_file)})", # Markdown link to story
96
- str(story_file),
97
- str(audio_file) if audio_file else None
98
- ])
99
 
100
- return files
101
- except Exception as e:
102
- print(f"Error loading gallery: {str(e)}")
103
- return []
104
-
105
- # Keep all other functions unchanged
106
- def generate_story(prompt, model_choice):
107
- """Generate story using specified model"""
108
- try:
109
- client = init_client()
110
- if client is None:
111
- return "Error: Story generation service is not available."
112
 
113
- result = client.predict(
114
- prompt=prompt,
115
- llm_model_picked=model_choice,
116
- stream_outputs=True,
117
- api_name="/ask_llm"
118
- )
119
- return result
120
- except Exception as e:
121
- return f"Error generating story: {str(e)}"
122
-
123
- async def generate_speech(text, voice="en-US-AriaNeural"):
124
- """Generate speech from text"""
125
- try:
126
- communicate = edge_tts.Communicate(text, voice)
127
- with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp_file:
128
- tmp_path = tmp_file.name
129
- await communicate.save(tmp_path)
130
- return tmp_path
131
- except Exception as e:
132
- print(f"Error in text2speech: {str(e)}")
133
- return None
134
-
135
- def process_story_and_audio(prompt, model_choice):
136
- """Process story, generate audio, and save to gallery"""
137
- try:
138
- # Generate story
139
- story = generate_story(prompt, model_choice)
140
- if isinstance(story, str) and story.startswith("Error"):
141
- return story, None, None
142
 
143
- # Generate audio
144
- audio_path = asyncio.run(generate_speech(story))
145
-
146
- # Save to gallery
147
- story_path, saved_audio_path = save_story(story, audio_path)
148
-
149
- return story, audio_path, load_gallery()
150
  except Exception as e:
151
- return f"Error: {str(e)}", None, None
 
152
 
153
- def play_gallery_audio(evt: gr.SelectData, gallery_data):
154
- """Play audio from gallery selection"""
155
- try:
156
- selected_row = gallery_data[evt.index[0]]
157
- audio_path = selected_row[3] # Audio path is the fourth element
158
- if audio_path and os.path.exists(audio_path):
159
- return audio_path
160
- return None
161
- except Exception as e:
162
- print(f"Error playing gallery audio: {str(e)}")
163
- return None
 
 
 
 
 
 
 
 
 
 
 
 
164
 
165
- # Create the Gradio interface (keep unchanged)
166
- with gr.Blocks(title="AI Story Generator") as demo:
167
  gr.Markdown("""
168
  # ๐ŸŽญ AI Story Generator & Narrator
169
  Generate creative stories, listen to them, and build your gallery!
170
  """)
171
 
 
 
 
 
172
  with gr.Row():
 
173
  with gr.Column(scale=3):
174
  with gr.Row():
175
  prompt_input = gr.Textbox(
@@ -202,7 +122,7 @@ with gr.Blocks(title="AI Story Generator") as demo:
202
  type="filepath"
203
  )
204
 
205
- # Sidebar with Story Starters and Gallery
206
  with gr.Column(scale=1):
207
  gr.Markdown("### ๐Ÿ“š Story Starters")
208
  story_starters = gr.Dataframe(
@@ -211,14 +131,42 @@ with gr.Blocks(title="AI Story Generator") as demo:
211
  interactive=False
212
  )
213
 
214
- gr.Markdown("### ๐ŸŽฌ Gallery")
215
- gallery = gr.Dataframe(
216
- value=load_gallery(),
217
- headers=["Timestamp", "Preview", "Story Path", "Audio Path"],
218
- interactive=False
219
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
 
221
- # Event handlers
222
  def update_prompt(evt: gr.SelectData):
223
  return STORY_STARTERS[evt.index[0]][1]
224
 
@@ -230,11 +178,8 @@ with gr.Blocks(title="AI Story Generator") as demo:
230
  outputs=[story_output, audio_output, gallery]
231
  )
232
 
233
- gallery.select(
234
- fn=play_gallery_audio,
235
- inputs=[gallery],
236
- outputs=[audio_output]
237
- )
238
 
239
  if __name__ == "__main__":
240
  demo.launch()
 
1
+ # Keep all existing imports and add any new ones needed
2
  import gradio as gr
3
  import random
4
  from datetime import datetime
 
16
 
17
  warnings.filterwarnings('ignore')
18
 
19
+ # Add constants for community generations
20
+ PAGE_SIZE = 10
21
+ FILE_DIR_PATH = "gallery" # Using existing gallery directory
 
 
 
 
 
 
 
 
 
 
22
 
23
+ # Keep existing STORY_STARTERS array
 
24
 
25
+ # Keep all existing functions through play_gallery_audio()
 
 
 
 
26
 
27
+ def list_all_outputs(generation_history):
28
+ """Load all story generations for community view"""
29
  try:
30
+ directory_path = FILE_DIR_PATH
31
+ if not os.path.exists(directory_path):
32
+ return "", gr.update(visible=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
+ # Get all matched pairs of story/audio files
35
+ file_pairs = []
36
+ for story_file in Path(directory_path).glob("story_*.md"):
37
+ timestamp = story_file.stem.split('_')[1]
38
  audio_pattern = f"audio_{timestamp}_*.mp3"
39
+ audio_files = list(Path(directory_path).glob(audio_pattern))
 
 
 
 
 
 
 
40
 
41
+ if audio_files: # Only include if we have both story and audio
42
+ file_pairs.append((story_file, audio_files[0]))
 
 
 
 
43
 
44
+ # Sort by modification time, newest first
45
+ file_pairs.sort(key=lambda x: os.path.getmtime(x[0]), reverse=True)
 
 
 
 
 
 
 
 
 
 
46
 
47
+ history_list = generation_history.split(',') if generation_history else []
48
+ updated_files = [str(audio) for _, audio in file_pairs if str(audio) not in history_list]
49
+ updated_history = updated_files + history_list
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
 
51
+ return ','.join(updated_history), gr.update(visible=True)
 
 
 
 
 
 
52
  except Exception as e:
53
+ print(f"Error loading community generations: {str(e)}")
54
+ return "", gr.update(visible=True)
55
 
56
+ def increase_list_size(list_size):
57
+ """Increase the number of visible community generations"""
58
+ return list_size + PAGE_SIZE
59
+
60
+ # Add CSS for community generations
61
+ css = '''
62
+ #live_gen:before {
63
+ content: '';
64
+ animation: svelte-z7cif2-pulseStart 1s cubic-bezier(.4,0,.6,1), svelte-z7cif2-pulse 2s cubic-bezier(.4,0,.6,1) 1s infinite;
65
+ border: 2px solid var(--color-accent);
66
+ background: transparent;
67
+ z-index: var(--layer-1);
68
+ pointer-events: none;
69
+ position: absolute;
70
+ height: 100%;
71
+ width: 100%;
72
+ border-radius: 7px;
73
+ }
74
+ #live_gen_items{
75
+ max-height: 570px;
76
+ overflow-y: scroll;
77
+ }
78
+ '''
79
 
80
+ # Modified Gradio interface
81
+ with gr.Blocks(title="AI Story Generator", css=css) as demo:
82
  gr.Markdown("""
83
  # ๐ŸŽญ AI Story Generator & Narrator
84
  Generate creative stories, listen to them, and build your gallery!
85
  """)
86
 
87
+ # Add hidden state for community generations
88
+ generation_history = gr.Textbox(visible=False)
89
+ list_size = gr.Number(value=PAGE_SIZE, visible=False)
90
+
91
  with gr.Row():
92
+ # Keep existing left column
93
  with gr.Column(scale=3):
94
  with gr.Row():
95
  prompt_input = gr.Textbox(
 
122
  type="filepath"
123
  )
124
 
125
+ # Modify right column to include community generations
126
  with gr.Column(scale=1):
127
  gr.Markdown("### ๐Ÿ“š Story Starters")
128
  story_starters = gr.Dataframe(
 
131
  interactive=False
132
  )
133
 
134
+ # Add Community Generations section
135
+ with gr.Column(elem_id="live_gen") as community_list:
136
+ gr.Markdown("### ๐ŸŽฌ Community Stories")
137
+ with gr.Column(elem_id="live_gen_items"):
138
+ @gr.render(inputs=[generation_history, list_size])
139
+ def show_output_list(generation_history, list_size):
140
+ history_list = generation_history.split(',') if generation_history else []
141
+ history_list_latest = history_list[:list_size]
142
+
143
+ for audio_path in history_list_latest:
144
+ if not audio_path:
145
+ continue
146
+
147
+ try:
148
+ # Get corresponding story file
149
+ story_path = audio_path.replace('audio_', 'story_').replace('.mp3', '.md')
150
+ if not os.path.exists(story_path):
151
+ continue
152
+
153
+ # Read story content
154
+ with open(story_path, 'r') as file:
155
+ story_content = file.read()
156
+ # Extract title from markdown
157
+ title = story_content.split('\n')[0].replace('# ', '')
158
+
159
+ with gr.Group():
160
+ gr.Markdown(value=f"### {title}")
161
+ gr.Audio(value=audio_path)
162
+ except Exception as e:
163
+ print(f"Error showing generation: {str(e)}")
164
+ continue
165
+
166
+ load_more = gr.Button("Load More Stories")
167
+ load_more.click(fn=increase_list_size, inputs=list_size, outputs=list_size)
168
 
169
+ # Keep existing event handlers
170
  def update_prompt(evt: gr.SelectData):
171
  return STORY_STARTERS[evt.index[0]][1]
172
 
 
178
  outputs=[story_output, audio_output, gallery]
179
  )
180
 
181
+ # Add auto-refresh for community generations
182
+ demo.load(fn=list_all_outputs, inputs=generation_history, outputs=[generation_history, community_list], every=2)
 
 
 
183
 
184
  if __name__ == "__main__":
185
  demo.launch()