Spaces:
Running
Running
more ui fixes:{
Browse files
app.py
CHANGED
@@ -32,6 +32,7 @@ import markdown
|
|
32 |
import PyPDF2
|
33 |
import io
|
34 |
import copy
|
|
|
35 |
|
36 |
def get_instructor_name(speaker):
|
37 |
instructor_names = {
|
@@ -406,9 +407,10 @@ def create_zip_of_files(file_paths):
|
|
406 |
|
407 |
# Access local files
|
408 |
def get_gradio_file_url(local_path):
|
|
|
|
|
409 |
relative_path = os.path.relpath(local_path, os.getcwd())
|
410 |
-
|
411 |
-
return final_path
|
412 |
|
413 |
# Async generate lecture materials and audio
|
414 |
async def on_generate(api_service, api_key, serpapi_key, title, lecture_content_description, lecture_type, lecture_style, speaker_audio, num_slides):
|
@@ -667,7 +669,7 @@ Example: 'Received {total_slides} slides, {total_slides} scripts, and HTML files
|
|
667 |
elif source == "research_agent" and isinstance(message, TextMessage) and "handoff_to_slide_agent" in message.content:
|
668 |
logger.info("Research Agent completed research")
|
669 |
progress = 25
|
670 |
-
label = "
|
671 |
yield (
|
672 |
html_with_progress(label, progress),
|
673 |
[]
|
@@ -730,7 +732,7 @@ Example: 'Received {total_slides} slides, {total_slides} scripts, and HTML files
|
|
730 |
except Exception as e:
|
731 |
logger.error("Error saving script to %s: %s", script_file, str(e))
|
732 |
progress = 75
|
733 |
-
label = "
|
734 |
yield (
|
735 |
html_with_progress(label, progress),
|
736 |
[]
|
@@ -1002,12 +1004,36 @@ js_code = """
|
|
1002 |
}, interval);
|
1003 |
}
|
1004 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1005 |
// Main initialization function
|
1006 |
function initializeSlides() {
|
1007 |
console.log("Initializing slides...");
|
1008 |
|
1009 |
// Wait for lecture-data to load the JSON data
|
1010 |
-
waitForElement('#lecture-data', (dataElement) => {
|
1011 |
if (!dataElement.textContent) {
|
1012 |
console.error("Lecture data element is empty");
|
1013 |
return;
|
@@ -1036,15 +1062,29 @@ js_code = """
|
|
1036 |
let isReloading = false;
|
1037 |
|
1038 |
// Wait for slide-content element
|
1039 |
-
waitForElement('#slide-content', (slideContent) => {
|
1040 |
console.log("Slide content element found");
|
1041 |
|
1042 |
// Initialize audio elements
|
1043 |
for (let i = 0; i < totalSlides; i++) {
|
1044 |
const audio = document.getElementById(`audio-${i+1}`);
|
1045 |
if (audio) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1046 |
audioElements.push(audio);
|
1047 |
-
console.log(`Found audio element audio-${i+1}:`, audio);
|
1048 |
} else {
|
1049 |
console.error(`Audio element audio-${i+1} not found`);
|
1050 |
}
|
@@ -1545,6 +1585,9 @@ with gr.Blocks(
|
|
1545 |
js=js_code,
|
1546 |
head='<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">'
|
1547 |
) as demo:
|
|
|
|
|
|
|
1548 |
gr.Markdown("""
|
1549 |
## <center>Lectūra: Your AI Genie for Self-taught Mastery.</center>
|
1550 |
### <center>(Disclaimer: This demo is part of a submission to the AgentX – LLM Agents MOOC Competition, hosted by Berkeley RDI. © Lectūra Labs. All rights reserved)</center>
|
@@ -2223,10 +2266,15 @@ with gr.Blocks(
|
|
2223 |
"audience": audience_val or "University"
|
2224 |
}
|
2225 |
|
2226 |
-
def show_note_content(evt: dict, notes):
|
2227 |
# Handle both event dict and direct index
|
2228 |
-
|
2229 |
-
|
|
|
|
|
|
|
|
|
|
|
2230 |
note = notes[idx]
|
2231 |
note_file = os.path.join(OUTPUT_DIR, f"{note['title']}.txt")
|
2232 |
if os.path.exists(note_file):
|
|
|
32 |
import PyPDF2
|
33 |
import io
|
34 |
import copy
|
35 |
+
from pathlib import Path
|
36 |
|
37 |
def get_instructor_name(speaker):
|
38 |
instructor_names = {
|
|
|
407 |
|
408 |
# Access local files
|
409 |
def get_gradio_file_url(local_path):
|
410 |
+
if not local_path:
|
411 |
+
return None
|
412 |
relative_path = os.path.relpath(local_path, os.getcwd())
|
413 |
+
return f"/gradio_api/file={relative_path}"
|
|
|
414 |
|
415 |
# Async generate lecture materials and audio
|
416 |
async def on_generate(api_service, api_key, serpapi_key, title, lecture_content_description, lecture_type, lecture_style, speaker_audio, num_slides):
|
|
|
669 |
elif source == "research_agent" and isinstance(message, TextMessage) and "handoff_to_slide_agent" in message.content:
|
670 |
logger.info("Research Agent completed research")
|
671 |
progress = 25
|
672 |
+
label = "Research complete. Generating slides..."
|
673 |
yield (
|
674 |
html_with_progress(label, progress),
|
675 |
[]
|
|
|
732 |
except Exception as e:
|
733 |
logger.error("Error saving script to %s: %s", script_file, str(e))
|
734 |
progress = 75
|
735 |
+
label = "Script complete. Reviewing lecture materials..."
|
736 |
yield (
|
737 |
html_with_progress(label, progress),
|
738 |
[]
|
|
|
1004 |
}, interval);
|
1005 |
}
|
1006 |
|
1007 |
+
// Function to check if a file exists
|
1008 |
+
async function checkFileExists(url) {
|
1009 |
+
try {
|
1010 |
+
const response = await fetch(url, { method: 'HEAD' });
|
1011 |
+
if (response.ok) {
|
1012 |
+
console.log(`File exists: ${url}`);
|
1013 |
+
return true;
|
1014 |
+
}
|
1015 |
+
// Fallback: Some servers disallow HEAD, try GET request
|
1016 |
+
if (response.status === 405 || response.status === 403) {
|
1017 |
+
const getResp = await fetch(url, { method: 'GET' });
|
1018 |
+
if (getResp.ok) {
|
1019 |
+
console.log(`File exists (GET fallback): ${url}`);
|
1020 |
+
return true;
|
1021 |
+
}
|
1022 |
+
}
|
1023 |
+
console.log(`File not found: ${url}`);
|
1024 |
+
return false;
|
1025 |
+
} catch (error) {
|
1026 |
+
console.error(`Error checking file:`, error);
|
1027 |
+
return false;
|
1028 |
+
}
|
1029 |
+
}
|
1030 |
+
|
1031 |
// Main initialization function
|
1032 |
function initializeSlides() {
|
1033 |
console.log("Initializing slides...");
|
1034 |
|
1035 |
// Wait for lecture-data to load the JSON data
|
1036 |
+
waitForElement('#lecture-data', async (dataElement) => {
|
1037 |
if (!dataElement.textContent) {
|
1038 |
console.error("Lecture data element is empty");
|
1039 |
return;
|
|
|
1062 |
let isReloading = false;
|
1063 |
|
1064 |
// Wait for slide-content element
|
1065 |
+
waitForElement('#slide-content', async (slideContent) => {
|
1066 |
console.log("Slide content element found");
|
1067 |
|
1068 |
// Initialize audio elements
|
1069 |
for (let i = 0; i < totalSlides; i++) {
|
1070 |
const audio = document.getElementById(`audio-${i+1}`);
|
1071 |
if (audio) {
|
1072 |
+
const url = lectureData.audioFiles[i];
|
1073 |
+
if (url) {
|
1074 |
+
const exists = await checkFileExists(url);
|
1075 |
+
if (exists) {
|
1076 |
+
audio.src = url;
|
1077 |
+
audio.load();
|
1078 |
+
console.log(`Set audio source for audio-${i+1}:`, url);
|
1079 |
+
} else {
|
1080 |
+
console.error(`Audio file not found: ${url}`);
|
1081 |
+
audio.innerHTML = "<span>Audio unavailable</span>";
|
1082 |
+
}
|
1083 |
+
} else {
|
1084 |
+
console.log(`No audio URL for slide ${i+1}`);
|
1085 |
+
audio.innerHTML = "<span>No audio</span>";
|
1086 |
+
}
|
1087 |
audioElements.push(audio);
|
|
|
1088 |
} else {
|
1089 |
console.error(`Audio element audio-${i+1} not found`);
|
1090 |
}
|
|
|
1585 |
js=js_code,
|
1586 |
head='<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">'
|
1587 |
) as demo:
|
1588 |
+
# Set static paths for accessing output files
|
1589 |
+
gr.set_static_paths(paths=[Path(OUTPUT_DIR).absolute()])
|
1590 |
+
|
1591 |
gr.Markdown("""
|
1592 |
## <center>Lectūra: Your AI Genie for Self-taught Mastery.</center>
|
1593 |
### <center>(Disclaimer: This demo is part of a submission to the AgentX – LLM Agents MOOC Competition, hosted by Berkeley RDI. © Lectūra Labs. All rights reserved)</center>
|
|
|
2266 |
"audience": audience_val or "University"
|
2267 |
}
|
2268 |
|
2269 |
+
def show_note_content(evt: dict, notes=None):
|
2270 |
# Handle both event dict and direct index
|
2271 |
+
if isinstance(evt, dict):
|
2272 |
+
idx = evt.get('index', 0)
|
2273 |
+
else:
|
2274 |
+
idx = evt
|
2275 |
+
notes = evt # If only one argument is provided, use it as notes
|
2276 |
+
|
2277 |
+
if notes and 0 <= idx < len(notes):
|
2278 |
note = notes[idx]
|
2279 |
note_file = os.path.join(OUTPUT_DIR, f"{note['title']}.txt")
|
2280 |
if os.path.exists(note_file):
|