Spaces:
Sleeping
Sleeping
| import logging | |
| try: | |
| from groq import Groq | |
| except ImportError: | |
| Groq = None | |
| try: | |
| import google.generativeai as genai | |
| except ImportError: | |
| genai = None | |
| logger = logging.getLogger(__name__) | |
| groq_client = None | |
| genai_client = None | |
| try: | |
| GROQ_API_KEY = os.environ.get("GROQ_API_KEY") | |
| if GROQ_API_KEY and Groq: | |
| groq_client = Groq(api_key=GROQ_API_KEY) | |
| except Exception as e: | |
| logger.warning(f"Groq client not available: {e}") | |
| try: | |
| GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY") | |
| if GEMINI_API_KEY and genai: | |
| genai.configure(api_key=GEMINI_API_KEY) | |
| genai_client = genai | |
| except Exception as e: | |
| logger.warning(f"Gemini client not available: {e}") | |
| def generate_study_plan(user_data): | |
| """Gera um plano de estudos estruturado a partir dos dados do usuΓ‘rio (sem IA).""" | |
| from datetime import timedelta | |
| current_level = user_data.get('english_level', 'B1') | |
| target_level = user_data.get('target_level', 'B2') | |
| weekly_hours = user_data.get('weekly_hours', 5) | |
| interests = user_data.get('interests', {}) | |
| context_focus = user_data.get('context_focus', 'General/Social') | |
| study_goals = user_data.get('study_goals', []) | |
| # ProgressΓ£o de nΓveis | |
| level_progression = { | |
| 'A1': {'next': 'A2', 'weeks': 12}, | |
| 'A2': {'next': 'B1', 'weeks': 16}, | |
| 'B1': {'next': 'B2', 'weeks': 20}, | |
| 'B2': {'next': 'C1', 'weeks': 24}, | |
| 'C1': {'next': 'C2', 'weeks': 28}, | |
| 'C2': {'next': 'C2', 'weeks': 32} | |
| } | |
| # Timeline | |
| base_weeks = level_progression.get(current_level, level_progression['B1'])['weeks'] | |
| hour_multiplier = 5 / max(weekly_hours, 1) | |
| adjusted_weeks = int(base_weeks * hour_multiplier) | |
| from datetime import datetime | |
| completion_date = (datetime.now() + timedelta(weeks=adjusted_weeks)).date().isoformat() | |
| # Estrutura semanal | |
| distributions = { | |
| 'A1': {'reading': 0.25, 'flashcards': 0.30, 'conversation': 0.20, 'writing': 0.15, 'grammar': 0.10}, | |
| 'A2': {'reading': 0.30, 'flashcards': 0.25, 'conversation': 0.20, 'writing': 0.15, 'grammar': 0.10}, | |
| 'B1': {'reading': 0.30, 'flashcards': 0.20, 'conversation': 0.25, 'writing': 0.20, 'listening': 0.05}, | |
| 'B2': {'reading': 0.25, 'flashcards': 0.15, 'conversation': 0.25, 'writing': 0.25, 'listening': 0.10}, | |
| 'C1': {'reading': 0.30, 'flashcards': 0.10, 'conversation': 0.25, 'writing': 0.25, 'listening': 0.10}, | |
| 'C2': {'reading': 0.35, 'flashcards': 0.05, 'conversation': 0.25, 'writing': 0.25, 'listening': 0.10} | |
| } | |
| base_dist = distributions.get(current_level, distributions['B1']) | |
| total_minutes = weekly_hours * 60 | |
| weekly_structure = {} | |
| for activity, percentage in base_dist.items(): | |
| minutes = int(total_minutes * percentage) | |
| if minutes >= 10: | |
| weekly_structure[activity] = { | |
| 'minutes_per_week': minutes, | |
| 'sessions_per_week': max(1, minutes // 30), | |
| 'minutes_per_session': minutes // max(1, minutes // 30) | |
| } | |
| # Dicas de estudo (IA se disponΓvel) | |
| def get_default_tips(level): | |
| tips_by_level = { | |
| 'A1': [ | |
| "π Start with basic vocabulary - 10 new words daily", | |
| "π― Focus on present tense in daily conversations", | |
| "π‘ Use picture dictionaries for visual learning", | |
| "β Practice pronunciation with simple audio materials", | |
| "π Don't worry about mistakes - communication is key!" | |
| ], | |
| 'A2': [ | |
| "π Read simple news articles and stories", | |
| "π― Practice past and future tenses regularly", | |
| "π‘ Join basic English conversation groups", | |
| "β Use language learning apps for daily practice", | |
| "π Watch movies with subtitles in your language" | |
| ], | |
| 'B1': [ | |
| "π Read intermediate articles on topics you enjoy", | |
| "π― Practice expressing opinions and preferences", | |
| "π‘ Start writing short paragraphs daily", | |
| "β Listen to podcasts at normal speed", | |
| "π Try to think in English for simple tasks" | |
| ], | |
| 'B2': [ | |
| "π Read longer articles and opinion pieces", | |
| "π― Practice formal and informal writing styles", | |
| "π‘ Engage in debates and discussions", | |
| "β Watch news programs without subtitles", | |
| "π Set specific goals for each study session" | |
| ], | |
| 'C1': [ | |
| "π Read academic and professional texts", | |
| "π― Practice nuanced expressions and idioms", | |
| "π‘ Write formal reports and presentations", | |
| "β Listen to academic lectures and conferences", | |
| "π Focus on specialized vocabulary for your field" | |
| ], | |
| 'C2': [ | |
| "π Read literature and complex analytical texts", | |
| "π― Master subtle language differences", | |
| "π‘ Write with stylistic sophistication", | |
| "β Engage with native speakers in professional contexts", | |
| "π Aim for native-like fluency in all skills" | |
| ] | |
| } | |
| return tips_by_level.get(level, tips_by_level['B1']) | |
| def generate_ai_tips(user_data): | |
| prompt = f""" | |
| Generate 5 personalized English study tips for a user with these characteristics: | |
| - Current Level: {user_data.get('english_level', 'B1')} | |
| - Target Level: {user_data.get('target_level', 'B2')} | |
| - Weekly Study Time: {user_data.get('weekly_hours', 5)} hours | |
| - Context Focus: {user_data.get('context_focus', 'General/Social')} | |
| - Interests: {', '.join(user_data.get('interests', {}).keys())} | |
| Provide practical, actionable tips that are specific to their level and interests. Format as a simple list of tips, each starting with an emoji. | |
| """ | |
| try: | |
| if groq_client: | |
| response = groq_client.chat.completions.create( | |
| model="llama-3.1-8b-instant", | |
| messages=[{"role": "user", "content": prompt}], | |
| temperature=0.7 | |
| ) | |
| response_text = response.choices[0].message.content | |
| elif genai_client: | |
| model = genai_client.GenerativeModel('gemini-2.5-flash-latest') | |
| response = model.generate_content(prompt) | |
| response_text = response.text | |
| else: | |
| return get_default_tips(user_data.get('english_level', 'B1')) | |
| tips = [line.strip() for line in response_text.split('\n') if line.strip() and any(e in line for e in ['π','π‘','π―','β','π'])] | |
| return tips[:5] if tips else get_default_tips(user_data.get('english_level', 'B1')) | |
| except Exception as e: | |
| logger.warning(f"AI study tips error: {e}") | |
| return get_default_tips(user_data.get('english_level', 'B1')) | |
| study_tips = generate_ai_tips(user_data) | |
| # Milestones | |
| milestones = [] | |
| milestone_intervals = max(2, adjusted_weeks // 4) | |
| for i in range(1, 5): | |
| week = milestone_intervals * i | |
| if week <= adjusted_weeks: | |
| milestones.append({ | |
| 'week': week, | |
| 'title': f"Milestone {i}", | |
| 'description': f"Progress checkpoint {i}", | |
| 'target_date': (datetime.now() + timedelta(weeks=week)).date().isoformat(), | |
| 'completed': False | |
| }) | |
| plan = { | |
| 'id': f"plan_{datetime.now().strftime('%Y%m%d_%H%M%S')}", | |
| 'created_at': datetime.now().isoformat(), | |
| 'current_level': current_level, | |
| 'target_level': target_level, | |
| 'weekly_hours': weekly_hours, | |
| 'estimated_weeks': adjusted_weeks, | |
| 'completion_date': completion_date, | |
| 'weekly_structure': weekly_structure, | |
| 'study_tips': study_tips, | |
| 'milestones': milestones, | |
| 'interests': interests, | |
| 'context_focus': context_focus, | |
| 'study_goals': study_goals | |
| } | |
| return plan | |
| import os | |
| import json | |
| from datetime import datetime | |
| STUDY_PLAN_PATH = 'hf_data/study_plan.json' | |
| def save_study_plan(plan_data): | |
| """Salva o plano de estudos em JSON.""" | |
| os.makedirs(os.path.dirname(STUDY_PLAN_PATH), exist_ok=True) | |
| plan_data['saved_at'] = datetime.now().isoformat() | |
| with open(STUDY_PLAN_PATH, 'w', encoding='utf-8') as f: | |
| json.dump(plan_data, f, ensure_ascii=False, indent=2) | |
| return True | |
| def load_study_plan(): | |
| """Carrega o plano de estudos do JSON.""" | |
| if os.path.exists(STUDY_PLAN_PATH): | |
| with open(STUDY_PLAN_PATH, 'r', encoding='utf-8') as f: | |
| return json.load(f) | |
| return None | |