Upload folder using huggingface_hub
Browse files- requirements.txt +3 -2
- src/app.py +70 -13
requirements.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
gradio
|
| 2 |
transformers>=4.30.0
|
| 3 |
torch>=2.0.0
|
| 4 |
pypdf2>=3.0.0
|
|
@@ -6,4 +6,5 @@ python-dotenv>=0.19.0
|
|
| 6 |
numpy>=1.21.0
|
| 7 |
tqdm>=4.65.0
|
| 8 |
openai>=1.0.0
|
| 9 |
-
tiktoken>=0.5.0
|
|
|
|
|
|
| 1 |
+
gradio==4.26.0
|
| 2 |
transformers>=4.30.0
|
| 3 |
torch>=2.0.0
|
| 4 |
pypdf2>=3.0.0
|
|
|
|
| 6 |
numpy>=1.21.0
|
| 7 |
tqdm>=4.65.0
|
| 8 |
openai>=1.0.0
|
| 9 |
+
tiktoken>=0.5.0
|
| 10 |
+
fastapi<0.110.0
|
src/app.py
CHANGED
|
@@ -1,12 +1,17 @@
|
|
| 1 |
import os
|
| 2 |
import gradio as gr
|
| 3 |
import re
|
|
|
|
| 4 |
from dotenv import load_dotenv
|
| 5 |
from src.core.transformer import TranscriptTransformer
|
| 6 |
from src.utils.pdf_processor import PDFProcessor
|
| 7 |
from src.utils.text_processor import TextProcessor
|
| 8 |
|
|
|
|
|
|
|
|
|
|
| 9 |
load_dotenv()
|
|
|
|
| 10 |
|
| 11 |
# Translations dictionary for UI elements
|
| 12 |
TRANSLATIONS = {
|
|
@@ -23,6 +28,7 @@ TRANSLATIONS = {
|
|
| 23 |
"guiding_prompt_info": "The Guiding Prompt allows you to provide specific instructions to modify the generated content, like output/desired LANGUAGE. You can use it to change the tone, style, focus ONLY on specific sections of the text, specify the output language (e.g., 'Generate in Spanish/French/German'), or give any other instruction that helps personalize the final result.",
|
| 24 |
"duration_label": "Target Lecture Duration (minutes)",
|
| 25 |
"examples_label": "Include Practical Examples",
|
|
|
|
| 26 |
"submit_button": "Transform Transcript",
|
| 27 |
"output_label": "Generated Teaching Transcript",
|
| 28 |
"error_no_pdf": "Error: No PDF file uploaded",
|
|
@@ -45,6 +51,7 @@ TRANSLATIONS = {
|
|
| 45 |
"guiding_prompt_info": "Las Instrucciones Gu铆a te permiten proporcionar indicaciones espec铆ficas para modificar el contenido generado, como el IDIOMA deseado. Puedes usarlas para cambiar el tono, estilo, enfocarte SOLO en secciones espec铆ficas del texto, especificar el idioma de salida (ej., 'Generar en ingl茅s/franc茅s/alem谩n'), o dar cualquier otra instrucci贸n que ayude a personalizar el resultado final.",
|
| 46 |
"duration_label": "Duraci贸n Objetivo de la Clase (minutos)",
|
| 47 |
"examples_label": "Incluir Ejemplos Pr谩cticos",
|
|
|
|
| 48 |
"submit_button": "Transformar Transcripci贸n",
|
| 49 |
"output_label": "Gui贸n de Ense帽anza Generado",
|
| 50 |
"error_no_pdf": "Error: No se ha subido ning煤n archivo PDF",
|
|
@@ -64,12 +71,14 @@ LANGUAGE_PROMPTS = {
|
|
| 64 |
|
| 65 |
class TranscriptTransformerApp:
|
| 66 |
def __init__(self):
|
|
|
|
| 67 |
self.pdf_processor = PDFProcessor()
|
| 68 |
self.text_processor = TextProcessor()
|
| 69 |
self.current_language = "en" # Default language
|
| 70 |
self.last_generated_content = "" # Store the last generated content
|
| 71 |
self.content_with_timestamps = "" # Store content with timestamps
|
| 72 |
self.content_without_timestamps = "" # Store content without timestamps
|
|
|
|
| 73 |
|
| 74 |
def process_transcript(self,
|
| 75 |
language: str,
|
|
@@ -78,7 +87,9 @@ class TranscriptTransformerApp:
|
|
| 78 |
raw_text_input: str = "",
|
| 79 |
initial_prompt: str = "",
|
| 80 |
target_duration: int = 30,
|
| 81 |
-
include_examples: bool = True
|
|
|
|
|
|
|
| 82 |
"""
|
| 83 |
Process uploaded transcript and transform it into a teaching transcript
|
| 84 |
|
|
@@ -90,12 +101,23 @@ class TranscriptTransformerApp:
|
|
| 90 |
initial_prompt: Additional guiding instructions for the content generation
|
| 91 |
target_duration: Target lecture duration in minutes
|
| 92 |
include_examples: Whether to include practical examples
|
|
|
|
|
|
|
| 93 |
|
| 94 |
Returns:
|
| 95 |
str: Generated teaching transcript
|
| 96 |
"""
|
|
|
|
| 97 |
try:
|
| 98 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
|
| 100 |
# Get text based on input type
|
| 101 |
if input_type == TRANSLATIONS[language]["input_type_options"][0]: # PDF
|
|
@@ -131,32 +153,43 @@ class TranscriptTransformerApp:
|
|
| 131 |
|
| 132 |
# Store the generated content
|
| 133 |
self.content_with_timestamps = lecture_transcript
|
|
|
|
| 134 |
|
| 135 |
# Create a version without timestamps
|
| 136 |
self.content_without_timestamps = self.remove_timestamps(lecture_transcript)
|
|
|
|
| 137 |
|
| 138 |
# Default: show content with timestamps
|
| 139 |
self.last_generated_content = lecture_transcript
|
| 140 |
|
|
|
|
| 141 |
return lecture_transcript
|
| 142 |
|
| 143 |
except Exception as e:
|
|
|
|
| 144 |
return f"{TRANSLATIONS[language]['error_prefix']}{str(e)}"
|
| 145 |
|
| 146 |
def remove_timestamps(self, text):
|
| 147 |
"""Remove all timestamps (e.g., [00:00]) from the text"""
|
|
|
|
| 148 |
# Regex to match the timestamp pattern [MM:SS] or [HH:MM:SS]
|
| 149 |
-
|
|
|
|
|
|
|
| 150 |
|
| 151 |
def toggle_timestamps(self, show_timestamps):
|
| 152 |
"""Toggle visibility of timestamps in output"""
|
|
|
|
| 153 |
if show_timestamps:
|
|
|
|
| 154 |
return self.content_with_timestamps
|
| 155 |
else:
|
|
|
|
| 156 |
return self.content_without_timestamps
|
| 157 |
|
| 158 |
def update_ui_language(self, language):
|
| 159 |
"""Update UI elements based on selected language"""
|
|
|
|
| 160 |
self.current_language = language
|
| 161 |
|
| 162 |
translations = TRANSLATIONS[language]
|
|
@@ -174,14 +207,18 @@ class TranscriptTransformerApp:
|
|
| 174 |
translations["guiding_prompt_info"],
|
| 175 |
translations["duration_label"],
|
| 176 |
translations["examples_label"],
|
|
|
|
| 177 |
translations["submit_button"],
|
| 178 |
translations["output_label"]
|
| 179 |
]
|
|
|
|
| 180 |
|
| 181 |
def launch(self):
|
| 182 |
"""Launch the Gradio interface"""
|
|
|
|
| 183 |
# Get the path to the example PDF
|
| 184 |
example_pdf = os.path.join(os.path.dirname(os.path.dirname(__file__)), "data", "sample2.pdf")
|
|
|
|
| 185 |
|
| 186 |
with gr.Blocks(title=TRANSLATIONS["en"]["title"]) as interface:
|
| 187 |
# Header with title and language selector side by side
|
|
@@ -235,18 +272,23 @@ class TranscriptTransformerApp:
|
|
| 235 |
|
| 236 |
# Settings row
|
| 237 |
with gr.Row():
|
| 238 |
-
target_duration = gr.
|
| 239 |
label=TRANSLATIONS["en"]["duration_label"],
|
| 240 |
-
minimum=5,
|
| 241 |
-
maximum=180,
|
| 242 |
value=30,
|
| 243 |
-
|
|
|
|
|
|
|
| 244 |
)
|
| 245 |
|
| 246 |
include_examples = gr.Checkbox(
|
| 247 |
label=TRANSLATIONS["en"]["examples_label"],
|
| 248 |
value=True
|
| 249 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 250 |
|
| 251 |
# Submit button
|
| 252 |
with gr.Row():
|
|
@@ -282,10 +324,14 @@ class TranscriptTransformerApp:
|
|
| 282 |
|
| 283 |
# Get language code from display value
|
| 284 |
def get_language_code(language_display):
|
| 285 |
-
|
|
|
|
|
|
|
|
|
|
| 286 |
|
| 287 |
# Update UI elements when language changes
|
| 288 |
def update_ui_with_display(language_display):
|
|
|
|
| 289 |
language = get_language_code(language_display)
|
| 290 |
self.current_language = language
|
| 291 |
|
|
@@ -301,10 +347,12 @@ class TranscriptTransformerApp:
|
|
| 301 |
gr.update(label=translations["guiding_prompt_label"], placeholder=translations["guiding_prompt_placeholder"], info=translations["guiding_prompt_info"]),
|
| 302 |
gr.update(label=translations["duration_label"]),
|
| 303 |
gr.update(label=translations["examples_label"]),
|
|
|
|
| 304 |
translations["submit_button"],
|
| 305 |
gr.update(label=translations["output_label"]),
|
| 306 |
gr.update(label=translations["show_timestamps"])
|
| 307 |
]
|
|
|
|
| 308 |
|
| 309 |
input_type.change(
|
| 310 |
fn=lambda lang_display, choice: update_input_visibility(lang_display, choice),
|
|
@@ -321,7 +369,7 @@ class TranscriptTransformerApp:
|
|
| 321 |
input_type, input_type,
|
| 322 |
file_input, text_input,
|
| 323 |
initial_prompt,
|
| 324 |
-
target_duration, include_examples,
|
| 325 |
submit_btn, output,
|
| 326 |
timestamps_checkbox
|
| 327 |
]
|
|
@@ -344,19 +392,28 @@ class TranscriptTransformerApp:
|
|
| 344 |
text_input,
|
| 345 |
initial_prompt,
|
| 346 |
target_duration,
|
| 347 |
-
include_examples
|
|
|
|
| 348 |
],
|
| 349 |
outputs=output
|
| 350 |
)
|
| 351 |
|
| 352 |
# Example for PDF input
|
|
|
|
| 353 |
gr.Examples(
|
| 354 |
-
examples=[[example_pdf, "", "", 30, True]],
|
| 355 |
-
inputs=[file_input, text_input, initial_prompt, target_duration, include_examples]
|
| 356 |
)
|
|
|
|
| 357 |
|
|
|
|
|
|
|
|
|
|
| 358 |
interface.launch(share=True)
|
|
|
|
| 359 |
|
| 360 |
if __name__ == "__main__":
|
|
|
|
| 361 |
app = TranscriptTransformerApp()
|
| 362 |
-
app.launch()
|
|
|
|
|
|
| 1 |
import os
|
| 2 |
import gradio as gr
|
| 3 |
import re
|
| 4 |
+
import logging # Added for debugging
|
| 5 |
from dotenv import load_dotenv
|
| 6 |
from src.core.transformer import TranscriptTransformer
|
| 7 |
from src.utils.pdf_processor import PDFProcessor
|
| 8 |
from src.utils.text_processor import TextProcessor
|
| 9 |
|
| 10 |
+
# Set up basic logging
|
| 11 |
+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
| 12 |
+
|
| 13 |
load_dotenv()
|
| 14 |
+
logging.info("Environment variables loaded.")
|
| 15 |
|
| 16 |
# Translations dictionary for UI elements
|
| 17 |
TRANSLATIONS = {
|
|
|
|
| 28 |
"guiding_prompt_info": "The Guiding Prompt allows you to provide specific instructions to modify the generated content, like output/desired LANGUAGE. You can use it to change the tone, style, focus ONLY on specific sections of the text, specify the output language (e.g., 'Generate in Spanish/French/German'), or give any other instruction that helps personalize the final result.",
|
| 29 |
"duration_label": "Target Lecture Duration (minutes)",
|
| 30 |
"examples_label": "Include Practical Examples",
|
| 31 |
+
"thinking_model_label": "Use Experimental Thinking Model (Gemini Only)",
|
| 32 |
"submit_button": "Transform Transcript",
|
| 33 |
"output_label": "Generated Teaching Transcript",
|
| 34 |
"error_no_pdf": "Error: No PDF file uploaded",
|
|
|
|
| 51 |
"guiding_prompt_info": "Las Instrucciones Gu铆a te permiten proporcionar indicaciones espec铆ficas para modificar el contenido generado, como el IDIOMA deseado. Puedes usarlas para cambiar el tono, estilo, enfocarte SOLO en secciones espec铆ficas del texto, especificar el idioma de salida (ej., 'Generar en ingl茅s/franc茅s/alem谩n'), o dar cualquier otra instrucci贸n que ayude a personalizar el resultado final.",
|
| 52 |
"duration_label": "Duraci贸n Objetivo de la Clase (minutos)",
|
| 53 |
"examples_label": "Incluir Ejemplos Pr谩cticos",
|
| 54 |
+
"thinking_model_label": "Usar Modelo de Pensamiento Experimental (Solo Gemini)",
|
| 55 |
"submit_button": "Transformar Transcripci贸n",
|
| 56 |
"output_label": "Gui贸n de Ense帽anza Generado",
|
| 57 |
"error_no_pdf": "Error: No se ha subido ning煤n archivo PDF",
|
|
|
|
| 71 |
|
| 72 |
class TranscriptTransformerApp:
|
| 73 |
def __init__(self):
|
| 74 |
+
logging.info("Initializing TranscriptTransformerApp...")
|
| 75 |
self.pdf_processor = PDFProcessor()
|
| 76 |
self.text_processor = TextProcessor()
|
| 77 |
self.current_language = "en" # Default language
|
| 78 |
self.last_generated_content = "" # Store the last generated content
|
| 79 |
self.content_with_timestamps = "" # Store content with timestamps
|
| 80 |
self.content_without_timestamps = "" # Store content without timestamps
|
| 81 |
+
logging.info("TranscriptTransformerApp initialized.")
|
| 82 |
|
| 83 |
def process_transcript(self,
|
| 84 |
language: str,
|
|
|
|
| 87 |
raw_text_input: str = "",
|
| 88 |
initial_prompt: str = "",
|
| 89 |
target_duration: int = 30,
|
| 90 |
+
include_examples: bool = True,
|
| 91 |
+
use_gemini: bool = True,
|
| 92 |
+
use_thinking_model: bool = False) -> str:
|
| 93 |
"""
|
| 94 |
Process uploaded transcript and transform it into a teaching transcript
|
| 95 |
|
|
|
|
| 101 |
initial_prompt: Additional guiding instructions for the content generation
|
| 102 |
target_duration: Target lecture duration in minutes
|
| 103 |
include_examples: Whether to include practical examples
|
| 104 |
+
use_gemini: Whether to use Gemini API instead of OpenAI
|
| 105 |
+
use_thinking_model: Requires use_gemini=True
|
| 106 |
|
| 107 |
Returns:
|
| 108 |
str: Generated teaching transcript
|
| 109 |
"""
|
| 110 |
+
logging.info(f"Processing transcript. Language: {language}, InputType: {input_type}, HasFile: {file_obj is not None}, HasText: {bool(raw_text_input)}, Duration: {target_duration}, Examples: {include_examples}, Gemini: {use_gemini}, ThinkingModel: {use_thinking_model}")
|
| 111 |
try:
|
| 112 |
+
# Force enable Gemini if thinking model is selected
|
| 113 |
+
if use_thinking_model:
|
| 114 |
+
logging.info("Thinking model selected, forcing use_gemini=True")
|
| 115 |
+
use_gemini = True
|
| 116 |
+
|
| 117 |
+
self.transformer = TranscriptTransformer(
|
| 118 |
+
use_gemini=use_gemini,
|
| 119 |
+
use_thinking_model=use_thinking_model
|
| 120 |
+
)
|
| 121 |
|
| 122 |
# Get text based on input type
|
| 123 |
if input_type == TRANSLATIONS[language]["input_type_options"][0]: # PDF
|
|
|
|
| 153 |
|
| 154 |
# Store the generated content
|
| 155 |
self.content_with_timestamps = lecture_transcript
|
| 156 |
+
logging.info("Generated content stored (with timestamps).")
|
| 157 |
|
| 158 |
# Create a version without timestamps
|
| 159 |
self.content_without_timestamps = self.remove_timestamps(lecture_transcript)
|
| 160 |
+
logging.info("Generated content stored (without timestamps).")
|
| 161 |
|
| 162 |
# Default: show content with timestamps
|
| 163 |
self.last_generated_content = lecture_transcript
|
| 164 |
|
| 165 |
+
logging.info("Transcript processing successful.")
|
| 166 |
return lecture_transcript
|
| 167 |
|
| 168 |
except Exception as e:
|
| 169 |
+
logging.error(f"Error processing transcript: {e}", exc_info=True) # Log exception info
|
| 170 |
return f"{TRANSLATIONS[language]['error_prefix']}{str(e)}"
|
| 171 |
|
| 172 |
def remove_timestamps(self, text):
|
| 173 |
"""Remove all timestamps (e.g., [00:00]) from the text"""
|
| 174 |
+
logging.info("Removing timestamps...")
|
| 175 |
# Regex to match the timestamp pattern [MM:SS] or [HH:MM:SS]
|
| 176 |
+
result = re.sub(r'\[\d{1,2}:\d{2}(:\d{2})?\]', '', text)
|
| 177 |
+
logging.info("Timestamps removed.")
|
| 178 |
+
return result
|
| 179 |
|
| 180 |
def toggle_timestamps(self, show_timestamps):
|
| 181 |
"""Toggle visibility of timestamps in output"""
|
| 182 |
+
logging.info(f"Toggling timestamps visibility. Show: {show_timestamps}")
|
| 183 |
if show_timestamps:
|
| 184 |
+
logging.info("Returning content WITH timestamps.")
|
| 185 |
return self.content_with_timestamps
|
| 186 |
else:
|
| 187 |
+
logging.info("Returning content WITHOUT timestamps.")
|
| 188 |
return self.content_without_timestamps
|
| 189 |
|
| 190 |
def update_ui_language(self, language):
|
| 191 |
"""Update UI elements based on selected language"""
|
| 192 |
+
logging.info(f"Updating UI language to: {language}")
|
| 193 |
self.current_language = language
|
| 194 |
|
| 195 |
translations = TRANSLATIONS[language]
|
|
|
|
| 207 |
translations["guiding_prompt_info"],
|
| 208 |
translations["duration_label"],
|
| 209 |
translations["examples_label"],
|
| 210 |
+
translations["thinking_model_label"],
|
| 211 |
translations["submit_button"],
|
| 212 |
translations["output_label"]
|
| 213 |
]
|
| 214 |
+
logging.info("UI language updated.")
|
| 215 |
|
| 216 |
def launch(self):
|
| 217 |
"""Launch the Gradio interface"""
|
| 218 |
+
logging.info("Configuring Gradio interface...")
|
| 219 |
# Get the path to the example PDF
|
| 220 |
example_pdf = os.path.join(os.path.dirname(os.path.dirname(__file__)), "data", "sample2.pdf")
|
| 221 |
+
logging.info(f"Example PDF path: {example_pdf}")
|
| 222 |
|
| 223 |
with gr.Blocks(title=TRANSLATIONS["en"]["title"]) as interface:
|
| 224 |
# Header with title and language selector side by side
|
|
|
|
| 272 |
|
| 273 |
# Settings row
|
| 274 |
with gr.Row():
|
| 275 |
+
target_duration = gr.Number(
|
| 276 |
label=TRANSLATIONS["en"]["duration_label"],
|
|
|
|
|
|
|
| 277 |
value=30,
|
| 278 |
+
minimum=2,
|
| 279 |
+
maximum=60,
|
| 280 |
+
step=1
|
| 281 |
)
|
| 282 |
|
| 283 |
include_examples = gr.Checkbox(
|
| 284 |
label=TRANSLATIONS["en"]["examples_label"],
|
| 285 |
value=True
|
| 286 |
)
|
| 287 |
+
|
| 288 |
+
use_thinking_model = gr.Checkbox(
|
| 289 |
+
label=TRANSLATIONS["en"]["thinking_model_label"],
|
| 290 |
+
value=True
|
| 291 |
+
)
|
| 292 |
|
| 293 |
# Submit button
|
| 294 |
with gr.Row():
|
|
|
|
| 324 |
|
| 325 |
# Get language code from display value
|
| 326 |
def get_language_code(language_display):
|
| 327 |
+
logging.info(f"Getting language code for display value: {language_display}")
|
| 328 |
+
code = lang_map.get(language_display, "en")
|
| 329 |
+
logging.info(f"Language code: {code}")
|
| 330 |
+
return code
|
| 331 |
|
| 332 |
# Update UI elements when language changes
|
| 333 |
def update_ui_with_display(language_display):
|
| 334 |
+
logging.info(f"Update UI triggered for language: {language_display}")
|
| 335 |
language = get_language_code(language_display)
|
| 336 |
self.current_language = language
|
| 337 |
|
|
|
|
| 347 |
gr.update(label=translations["guiding_prompt_label"], placeholder=translations["guiding_prompt_placeholder"], info=translations["guiding_prompt_info"]),
|
| 348 |
gr.update(label=translations["duration_label"]),
|
| 349 |
gr.update(label=translations["examples_label"]),
|
| 350 |
+
gr.update(label=translations["thinking_model_label"]),
|
| 351 |
translations["submit_button"],
|
| 352 |
gr.update(label=translations["output_label"]),
|
| 353 |
gr.update(label=translations["show_timestamps"])
|
| 354 |
]
|
| 355 |
+
logging.info("UI elements update values prepared.")
|
| 356 |
|
| 357 |
input_type.change(
|
| 358 |
fn=lambda lang_display, choice: update_input_visibility(lang_display, choice),
|
|
|
|
| 369 |
input_type, input_type,
|
| 370 |
file_input, text_input,
|
| 371 |
initial_prompt,
|
| 372 |
+
target_duration, include_examples, use_thinking_model,
|
| 373 |
submit_btn, output,
|
| 374 |
timestamps_checkbox
|
| 375 |
]
|
|
|
|
| 392 |
text_input,
|
| 393 |
initial_prompt,
|
| 394 |
target_duration,
|
| 395 |
+
include_examples,
|
| 396 |
+
use_thinking_model
|
| 397 |
],
|
| 398 |
outputs=output
|
| 399 |
)
|
| 400 |
|
| 401 |
# Example for PDF input
|
| 402 |
+
logging.info("Setting up Gradio Examples...")
|
| 403 |
gr.Examples(
|
| 404 |
+
examples=[[example_pdf, "", "", 30, True, True]],
|
| 405 |
+
inputs=[file_input, text_input, initial_prompt, target_duration, include_examples, use_thinking_model]
|
| 406 |
)
|
| 407 |
+
logging.info("Gradio Examples configured.")
|
| 408 |
|
| 409 |
+
logging.info("Launching Gradio interface...")
|
| 410 |
+
# Note: Setting share=True is not recommended/supported in Spaces, but kept for consistency with original code
|
| 411 |
+
# It might generate a warning, which is expected.
|
| 412 |
interface.launch(share=True)
|
| 413 |
+
logging.info("Gradio interface launched.")
|
| 414 |
|
| 415 |
if __name__ == "__main__":
|
| 416 |
+
logging.info("Starting application...")
|
| 417 |
app = TranscriptTransformerApp()
|
| 418 |
+
app.launch()
|
| 419 |
+
logging.info("Application finished.")
|