Jaward commited on
Commit
79ea9e8
·
verified ·
1 Parent(s): 4eebc1a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +24 -25
app.py CHANGED
@@ -320,7 +320,7 @@ def generate_markdown_slides(slides, title, speaker="Prof. AI Feynman", date="Ap
320
  """
321
  markdown_slides.append(slide_md.strip())
322
 
323
- logger.info(f"Generated Markdown slides for: {title}")
324
  return markdown_slides
325
  except Exception as e:
326
  logger.error(f"Failed to generate Markdown slides: {str(e)}")
@@ -368,7 +368,7 @@ Example output for 2 slides:
368
  model_client=model_client,
369
  handoffs=["feynman_agent"],
370
  system_message=f"""
371
- You are a Script Agent. Access the JSON array of {total_slides} slides from the conversation history. Generate a narration script (1-2 sentences) for each of the {total_slides} slides, summarizing its content in a clear, academically inclined tone as a professor would deliver it. Avoid using non-verbal fillers such as "um," "you know," or "like." Output ONLY a JSON array wrapped in ```json ... ``` with exactly {total_slides} strings, one script per slide, in the same order. Ensure the JSON is valid and complete. After outputting, use the handoff_to_script_agent tool. If scripts cannot be generated, retry once.
372
  Example for 3 slides:
373
  ```json
374
  [
@@ -502,7 +502,7 @@ Example: 'Received {total_slides} slides and {total_slides} scripts. Lecture is
502
  extracted_json = extract_json_from_message(message)
503
  if extracted_json:
504
  slides = extracted_json
505
- logger.info("Slide Agent generated %d slides", len(slides))
506
  if len(slides) != total_slides:
507
  if slide_retry_count < max_retries:
508
  slide_retry_count += 1
@@ -547,7 +547,7 @@ Example: 'Received {total_slides} slides and {total_slides} scripts. Lecture is
547
  extracted_json = extract_json_from_message(message)
548
  if extracted_json:
549
  scripts = extracted_json
550
- logger.info("Script Agent generated scripts for %d slides", len(scripts))
551
  for i, script in enumerate(scripts):
552
  script_file = os.path.join(OUTPUT_DIR, f"slide_{i+1}_script.txt")
553
  try:
@@ -661,7 +661,7 @@ Example: 'Received {total_slides} slides and {total_slides} scripts. Lecture is
661
  return
662
 
663
  audio_files = []
664
- audio_file_paths = []
665
  validated_speaker_wav = await validate_and_convert_speaker_audio(speaker_audio)
666
  if not validated_speaker_wav:
667
  logger.error("Invalid speaker audio after conversion, skipping TTS")
@@ -691,9 +691,9 @@ Example: 'Received {total_slides} slides and {total_slides} scripts. Lecture is
691
  if not cleaned_script:
692
  logger.error("Skipping audio for slide %d due to empty or invalid script", i + 1)
693
  audio_files.append(None)
694
- audio_file_paths.append(None)
695
  progress = 90 + ((i + 1) / len(scripts)) * 10
696
- label = f"Generating speech for slide {i + 1}/{len(scripts)}..."
697
  yield (
698
  html_with_progress(label, progress),
699
  []
@@ -715,11 +715,12 @@ Example: 'Received {total_slides} slides and {total_slides} scripts. Lecture is
715
  if not success:
716
  raise RuntimeError("TTS generation failed")
717
 
718
- logger.info("Generating speech for slide %d: %s", i + 1, audio_file)
719
  audio_files.append(audio_file)
720
- audio_file_paths.append(audio_file)
 
721
  progress = 90 + ((i + 1) / len(scripts)) * 10
722
- label = f"Generating speech for slide {i + 1}/{len(scripts)}..."
723
  yield (
724
  html_with_progress(label, progress),
725
  []
@@ -731,9 +732,9 @@ Example: 'Received {total_slides} slides and {total_slides} scripts. Lecture is
731
  if attempt == max_audio_retries:
732
  logger.error("Max retries reached for slide %d, skipping", i + 1)
733
  audio_files.append(None)
734
- audio_file_paths.append(None)
735
  progress = 90 + ((i + 1) / len(scripts)) * 10
736
- label = f"Generating speech for slide {i + 1}/{len(scripts)}..."
737
  yield (
738
  html_with_progress(label, progress),
739
  []
@@ -748,18 +749,16 @@ Example: 'Received {total_slides} slides and {total_slides} scripts. Lecture is
748
 
749
  # Generate audio timeline with playable audio elements
750
  audio_timeline = ""
751
- audio_urls = []
752
- for i, audio_file in enumerate(audio_file_paths):
753
- if audio_file and os.path.exists(audio_file):
754
- # Use the file path directly; Gradio will serve it via gr.File
755
- audio_urls.append(audio_file)
756
- audio_timeline += f'<audio id="audio-{i+1}" controls src="" style="display: inline-block; margin: 0 10px; width: 200px;"></audio>'
757
  else:
758
  audio_timeline += f'<span id="audio-{i+1}" style="display: inline-block; margin: 0 10px;">slide_{i+1}.mp3 (not generated)</span>'
759
 
760
  slides_info = json.dumps({"slides": markdown_slides, "audioFiles": audio_urls})
761
 
762
  html_output = f"""
 
763
  <div id="lecture-container" style="height: 700px; border: 1px solid #ddd; border-radius: 8px; display: flex; flex-direction: column; justify-content: space-between;">
764
  <div id="slide-content" style="flex: 1; overflow: auto; padding: 20px; text-align: center; background-color: #fff; color: #333;">
765
  <!-- Slides will be rendered here -->
@@ -782,20 +781,20 @@ Example: 'Received {total_slides} slides and {total_slides} scripts. Lecture is
782
  const totalSlides = lectureData.slides.length;
783
  let audioElements = [];
784
 
785
- // Populate audio elements and set their sources
786
  for (let i = 0; i < totalSlides; i++) {{
787
  const audio = document.getElementById(`audio-${{i+1}}`);
788
- if (audio && lectureData.audioFiles[i]) {{
789
- audio.src = lectureData.audioFiles[i];
790
- }}
791
  audioElements.push(audio);
792
  }}
793
 
794
  function renderSlide() {{
795
  const slideContent = document.getElementById('slide-content');
796
  if (lectureData.slides[currentSlide]) {{
797
- slideContent.innerHTML = lectureData.slides[currentSlide].replace(/\\n/g, '<br>');
798
- console.log("Rendering slide:", lectureData.slides[currentSlide]);
 
 
 
799
  }} else {{
800
  slideContent.innerHTML = '<h2>No slide content available</h2>';
801
  console.log("No slide content for index:", currentSlide);
@@ -926,4 +925,4 @@ with gr.Blocks(title="Agent Feynman") as demo:
926
  )
927
 
928
  if __name__ == "__main__":
929
- demo.launch()
 
320
  """
321
  markdown_slides.append(slide_md.strip())
322
 
323
+ logger.info(f"Generated Markdown slides for: {title}: {markdown_slides}")
324
  return markdown_slides
325
  except Exception as e:
326
  logger.error(f"Failed to generate Markdown slides: {str(e)}")
 
368
  model_client=model_client,
369
  handoffs=["feynman_agent"],
370
  system_message=f"""
371
+ You are a Script Agent. Access the JSON array of {total_slides} slides from the conversation history. Generate a narration script (1-2 sentences) for each of the {total_slides} slides, summarizing its content in a clear, academically inclined tone as a professor would deliver it. Avoid using non-verbal fillers such as "um," "you know," or "like." Output ONLY a JSON array wrapped in ```json ... ``` with exactly {total_slides} strings, one script per slide, in the same order. Ensure the JSON is valid and complete. After outputting, use the handoff_to_feynman_agent tool. If scripts cannot be generated, retry once.
372
  Example for 3 slides:
373
  ```json
374
  [
 
502
  extracted_json = extract_json_from_message(message)
503
  if extracted_json:
504
  slides = extracted_json
505
+ logger.info("Slide Agent generated %d slides: %s", len(slides), slides)
506
  if len(slides) != total_slides:
507
  if slide_retry_count < max_retries:
508
  slide_retry_count += 1
 
547
  extracted_json = extract_json_from_message(message)
548
  if extracted_json:
549
  scripts = extracted_json
550
+ logger.info("Script Agent generated scripts for %d slides: %s", len(scripts), scripts)
551
  for i, script in enumerate(scripts):
552
  script_file = os.path.join(OUTPUT_DIR, f"slide_{i+1}_script.txt")
553
  try:
 
661
  return
662
 
663
  audio_files = []
664
+ audio_urls = []
665
  validated_speaker_wav = await validate_and_convert_speaker_audio(speaker_audio)
666
  if not validated_speaker_wav:
667
  logger.error("Invalid speaker audio after conversion, skipping TTS")
 
691
  if not cleaned_script:
692
  logger.error("Skipping audio for slide %d due to empty or invalid script", i + 1)
693
  audio_files.append(None)
694
+ audio_urls.append(None)
695
  progress = 90 + ((i + 1) / len(scripts)) * 10
696
+ label = f"Generated audio for slide {i + 1}/{len(scripts)}..."
697
  yield (
698
  html_with_progress(label, progress),
699
  []
 
715
  if not success:
716
  raise RuntimeError("TTS generation failed")
717
 
718
+ logger.info("Generated audio for slide %d: %s", i + 1, audio_file)
719
  audio_files.append(audio_file)
720
+ # Use Gradio's file serving URL
721
+ audio_urls.append(f"/gradio_api/file={audio_file}")
722
  progress = 90 + ((i + 1) / len(scripts)) * 10
723
+ label = f"Generated audio for slide {i + 1}/{len(scripts)}..."
724
  yield (
725
  html_with_progress(label, progress),
726
  []
 
732
  if attempt == max_audio_retries:
733
  logger.error("Max retries reached for slide %d, skipping", i + 1)
734
  audio_files.append(None)
735
+ audio_urls.append(None)
736
  progress = 90 + ((i + 1) / len(scripts)) * 10
737
+ label = f"Generated audio for slide {i + 1}/{len(scripts)}..."
738
  yield (
739
  html_with_progress(label, progress),
740
  []
 
749
 
750
  # Generate audio timeline with playable audio elements
751
  audio_timeline = ""
752
+ for i, audio_url in enumerate(audio_urls):
753
+ if audio_url:
754
+ audio_timeline += f'<audio id="audio-{i+1}" controls src="{audio_url}" style="display: inline-block; margin: 0 10px; width: 200px;"></audio>'
 
 
 
755
  else:
756
  audio_timeline += f'<span id="audio-{i+1}" style="display: inline-block; margin: 0 10px;">slide_{i+1}.mp3 (not generated)</span>'
757
 
758
  slides_info = json.dumps({"slides": markdown_slides, "audioFiles": audio_urls})
759
 
760
  html_output = f"""
761
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/marked.min.js"></script>
762
  <div id="lecture-container" style="height: 700px; border: 1px solid #ddd; border-radius: 8px; display: flex; flex-direction: column; justify-content: space-between;">
763
  <div id="slide-content" style="flex: 1; overflow: auto; padding: 20px; text-align: center; background-color: #fff; color: #333;">
764
  <!-- Slides will be rendered here -->
 
781
  const totalSlides = lectureData.slides.length;
782
  let audioElements = [];
783
 
784
+ // Populate audio elements
785
  for (let i = 0; i < totalSlides; i++) {{
786
  const audio = document.getElementById(`audio-${{i+1}}`);
 
 
 
787
  audioElements.push(audio);
788
  }}
789
 
790
  function renderSlide() {{
791
  const slideContent = document.getElementById('slide-content');
792
  if (lectureData.slides[currentSlide]) {{
793
+ const markdownText = lectureData.slides[currentSlide];
794
+ const htmlContent = marked.parse(markdownText);
795
+ slideContent.innerHTML = htmlContent;
796
+ console.log("Rendering slide:", markdownText);
797
+ console.log("Rendered HTML:", htmlContent);
798
  }} else {{
799
  slideContent.innerHTML = '<h2>No slide content available</h2>';
800
  console.log("No slide content for index:", currentSlide);
 
925
  )
926
 
927
  if __name__ == "__main__":
928
+ demo.launch(allowed_paths=[OUTPUT_DIR], max_file_size="5mb")