Spaces:
Sleeping
Sleeping
# config.py | |
import os | |
from dotenv import load_dotenv | |
load_dotenv() | |
class Config: | |
DEBUG = os.getenv('DEBUG', 'False').lower() == 'true' | |
LOG_LEVEL = os.getenv('LOG_LEVEL', 'INFO') | |
MODELS_CACHE_DIR = os.getenv('MODELS_CACHE_DIR', './models') | |
HISTORY_FILE = os.getenv('HISTORY_FILE', 'learning_path_history.json') | |
MAX_AUDIO_LENGTH = int(os.getenv('MAX_AUDIO_LENGTH', '600')) # seconds | |
MAX_TEXT_LENGTH = int(os.getenv('MAX_TEXT_LENGTH', '1000')) | |
SUPPORTED_AUDIO_FORMATS = ['.wav', '.mp3', '.ogg', '.flac'] | |
# Visualization settings | |
MAX_TOPICS = int(os.getenv('MAX_TOPICS', '10')) | |
MAX_SUBTOPICS = int(os.getenv('MAX_SUBTOPICS', '5')) | |
FIGURE_DPI = int(os.getenv('FIGURE_DPI', '300')) | |
# Model settings | |
MODEL_TRANSCRIBER = os.getenv('MODEL_TRANSCRIBER', 'openai/whisper-base') | |
MODEL_GENERATOR = os.getenv('MODEL_GENERATOR', 'gpt2') | |
# Retry settings | |
MAX_RETRIES = int(os.getenv('MAX_RETRIES', '3')) | |
RETRY_DELAY = int(os.getenv('RETRY_DELAY', '1')) | |
# utils.py | |
import logging | |
import json | |
from typing import Dict, Any, Optional, List, Tuple | |
import os | |
from datetime import datetime | |
from config import Config | |
class Utils: | |
def setup_logging() -> logging.Logger: | |
logger = logging.getLogger("LearningPathGenerator") | |
level = getattr(logging, Config.LOG_LEVEL) | |
logger.setLevel(level) | |
handler = logging.FileHandler("app.log") | |
formatter = logging.Formatter( | |
'%(asctime)s - %(name)s - %(levelname)s - %(message)s' | |
) | |
handler.setFormatter(formatter) | |
logger.addHandler(handler) | |
return logger | |
def save_json(data: Dict[str, Any], filename: str) -> bool: | |
try: | |
with open(filename, 'w', encoding='utf-8') as f: | |
json.dump(data, f, ensure_ascii=False, indent=2) | |
return True | |
except Exception as e: | |
logging.error(f"Error saving JSON: {str(e)}") | |
return False | |
def load_json(filename: str) -> Optional[Dict[str, Any]]: | |
try: | |
with open(filename, 'r', encoding='utf-8') as f: | |
return json.load(f) | |
except Exception as e: | |
logging.error(f"Error loading JSON: {str(e)}") | |
return None | |
def extract_topics(analysis: str) -> Tuple[List[str], Dict[str, List[str]]]: | |
# Simple topic extraction logic - could be enhanced | |
topics = ["Main Topic", "Subtopic 1", "Subtopic 2"] | |
subtopics = { | |
"Main Topic": ["Detail 1", "Detail 2"], | |
"Subtopic 1": ["Point 1", "Point 2"], | |
"Subtopic 2": ["Item 1", "Item 2"] | |
} | |
return topics, subtopics | |
# models.py | |
from transformers import pipeline | |
import torch | |
from typing import Dict, Any | |
import logging | |
from config import Config | |
class ModelManager: | |
def __init__(self): | |
self.logger = logging.getLogger("ModelManager") | |
self.models: Dict[str, Any] = {} | |
self._initialize_models() | |
def _initialize_models(self): | |
try: | |
device = 0 if torch.cuda.is_available() else -1 | |
self.models["transcriber"] = pipeline( | |
"automatic-speech-recognition", | |
model=Config.MODEL_TRANSCRIBER, | |
device=device | |
) | |
self.models["generator"] = pipeline( | |
"text-generation", | |
model=Config.MODEL_GENERATOR, | |
device=device | |
) | |
except Exception as e: | |
self.logger.error(f"Error initializing models: {str(e)}") | |
raise | |
def get_model(self, name: str) -> Any: | |
return self.models.get(name) | |
# main.py | |
import gradio as gr | |
from typing import Dict, Any | |
import logging | |
from config import Config | |
from utils import Utils | |
from models import ModelManager | |
from visualization import Visualizer | |
from datetime import datetime | |
class LearningPathGenerator: | |
def __init__(self): | |
self.logger = Utils.setup_logging() | |
self.model_manager = ModelManager() | |
self.history_file = Config.HISTORY_FILE | |
if not os.path.exists(self.history_file): | |
Utils.save_json([], self.history_file) | |
def process_audio(self, | |
audio_path: str, | |
path_name: str = "", | |
difficulty: str = "intermediate", | |
include_resources: bool = True) -> Dict[str, Any]: | |
try: | |
transcriber = self.model_manager.get_model("transcriber") | |
transcription = transcriber(audio_path)["text"] | |
generator = self.model_manager.get_model("generator") | |
analysis = self._generate_analysis(generator, transcription, difficulty, include_resources) | |
topics, subtopics = Utils.extract_topics(analysis) | |
mind_map = Visualizer.create_mind_map(topics, subtopics) | |
if path_name: | |
self._save_to_history(transcription, analysis, path_name) | |
return { | |
"transcription": transcription, | |
"analysis": analysis, | |
"mind_map": mind_map | |
} | |
except Exception as e: | |
self.logger.error(f"Processing error: {str(e)}") | |
return self._error_response(str(e)) | |
def _generate_analysis(self, | |
generator: Any, | |
text: str, | |
difficulty: str, | |
include_resources: bool) -> str: | |
prompt = f""" | |
Based on the following text, create a detailed learning path | |
for {difficulty} level: | |
{text[:Config.MAX_TEXT_LENGTH]} | |
Learning path: | |
""" | |
response = generator( | |
prompt, | |
max_length=300, | |
num_return_sequences=1 | |
)[0]["generated_text"] | |
if include_resources: | |
response += self._generate_resources() | |
return response | |
def _generate_resources(self) -> str: | |
return """ | |
Recommended Resources: | |
1. Books: | |
- "Essential Guide" | |
- "Advanced Techniques" | |
2. Online Courses: | |
- Coursera: "Topic Specialization" | |
- edX: "Advanced Course" | |
3. Practical Resources: | |
- Interactive tutorials | |
- Practice exercises | |
- Real-world projects | |
""" | |
def _save_to_history(self, transcription: str, analysis: str, path_name: str): | |
history = Utils.load_json(self.history_file) or [] | |
history.append({ | |
"date": datetime.now().isoformat(), | |
"name": path_name, | |
"transcription": transcription, | |
"analysis": analysis | |
}) | |
Utils.save_json(history, self.history_file) | |
def _error_response(self, error_msg: str) -> Dict[str, Any]: | |
return { | |
"transcription": f"Error: {error_msg}", | |
"analysis": "Could not generate analysis due to an error.", | |
"mind_map": None | |
} | |
def create_interface(self): | |
with gr.Blocks(theme=gr.themes.Soft()) as app: | |
gr.Markdown(""" | |
# π Learning Path Generator | |
Upload an audio file describing your learning goals | |
and receive a personalized learning path with resources! | |
""") | |
with gr.Tab("Generate Path"): | |
with gr.Row(): | |
with gr.Column(scale=2): | |
audio_input = gr.Audio( | |
type="filepath", | |
label="Audio Upload", | |
description="Record or upload an audio describing your goals" | |
) | |
with gr.Row(): | |
path_name = gr.Textbox( | |
label="Path Name", | |
placeholder="Give your learning path a name (optional)" | |
) | |
difficulty = gr.Dropdown( | |
choices=["beginner", "intermediate", "advanced"], | |
value="intermediate", | |
label="Difficulty Level" | |
) | |
include_resources = gr.Checkbox( | |
label="Include Recommended Resources", | |
value=True | |
) | |
process_btn = gr.Button( | |
"Generate Learning Path", | |
variant="primary" | |
) | |
text_output = gr.Textbox( | |
label="Audio Transcription", | |
lines=4 | |
) | |
analysis_output = gr.Textbox( | |
label="Analysis and Learning Path", | |
lines=10 | |
) | |
mind_map_output = gr.Image( | |
label="Learning Path Mind Map" | |
) | |
process_btn.click( | |
fn=self.process_audio, | |
inputs=[audio_input, path_name, difficulty, include_resources], | |
outputs={ | |
"transcription": text_output, | |
"analysis": analysis_output, | |
"mind_map": mind_map_output | |
} | |
) | |
return app | |
if __name__ == "__main__": | |
try: | |
generator = LearningPathGenerator() | |
app = generator.create_interface() | |
app.launch(debug=Config.DEBUG) | |
except Exception as e: | |
logging.error(f"Application error: {str(e)}") | |
raise |