amauricunha commited on
Commit
d90f3e8
Β·
verified Β·
1 Parent(s): 417f250

Update study_plan.py

Browse files
Files changed (1) hide show
  1. study_plan.py +203 -203
study_plan.py CHANGED
@@ -1,203 +1,203 @@
1
- import logging
2
- try:
3
- from groq import Groq
4
- except ImportError:
5
- Groq = None
6
- try:
7
- import google.generativeai as genai
8
- except ImportError:
9
- genai = None
10
-
11
- logger = logging.getLogger(__name__)
12
- groq_client = None
13
- genai_client = None
14
- try:
15
- GROQ_API_KEY = os.environ.get("GROQ_API_KEY")
16
- if GROQ_API_KEY and Groq:
17
- groq_client = Groq(api_key=GROQ_API_KEY)
18
- except Exception as e:
19
- logger.warning(f"Groq client not available: {e}")
20
- try:
21
- GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY")
22
- if GEMINI_API_KEY and genai:
23
- genai.configure(api_key=GEMINI_API_KEY)
24
- genai_client = genai
25
- except Exception as e:
26
- logger.warning(f"Gemini client not available: {e}")
27
- def generate_study_plan(user_data):
28
- """Gera um plano de estudos estruturado a partir dos dados do usuΓ‘rio (sem IA)."""
29
- from datetime import timedelta
30
- current_level = user_data.get('english_level', 'B1')
31
- target_level = user_data.get('target_level', 'B2')
32
- weekly_hours = user_data.get('weekly_hours', 5)
33
- interests = user_data.get('interests', {})
34
- context_focus = user_data.get('context_focus', 'General/Social')
35
- study_goals = user_data.get('study_goals', [])
36
-
37
- # ProgressΓ£o de nΓ­veis
38
- level_progression = {
39
- 'A1': {'next': 'A2', 'weeks': 12},
40
- 'A2': {'next': 'B1', 'weeks': 16},
41
- 'B1': {'next': 'B2', 'weeks': 20},
42
- 'B2': {'next': 'C1', 'weeks': 24},
43
- 'C1': {'next': 'C2', 'weeks': 28},
44
- 'C2': {'next': 'C2', 'weeks': 32}
45
- }
46
- # Timeline
47
- base_weeks = level_progression.get(current_level, level_progression['B1'])['weeks']
48
- hour_multiplier = 5 / max(weekly_hours, 1)
49
- adjusted_weeks = int(base_weeks * hour_multiplier)
50
- from datetime import datetime
51
- completion_date = (datetime.now() + timedelta(weeks=adjusted_weeks)).date().isoformat()
52
-
53
- # Estrutura semanal
54
- distributions = {
55
- 'A1': {'reading': 0.25, 'flashcards': 0.30, 'conversation': 0.20, 'writing': 0.15, 'grammar': 0.10},
56
- 'A2': {'reading': 0.30, 'flashcards': 0.25, 'conversation': 0.20, 'writing': 0.15, 'grammar': 0.10},
57
- 'B1': {'reading': 0.30, 'flashcards': 0.20, 'conversation': 0.25, 'writing': 0.20, 'listening': 0.05},
58
- 'B2': {'reading': 0.25, 'flashcards': 0.15, 'conversation': 0.25, 'writing': 0.25, 'listening': 0.10},
59
- 'C1': {'reading': 0.30, 'flashcards': 0.10, 'conversation': 0.25, 'writing': 0.25, 'listening': 0.10},
60
- 'C2': {'reading': 0.35, 'flashcards': 0.05, 'conversation': 0.25, 'writing': 0.25, 'listening': 0.10}
61
- }
62
- base_dist = distributions.get(current_level, distributions['B1'])
63
- total_minutes = weekly_hours * 60
64
- weekly_structure = {}
65
- for activity, percentage in base_dist.items():
66
- minutes = int(total_minutes * percentage)
67
- if minutes >= 10:
68
- weekly_structure[activity] = {
69
- 'minutes_per_week': minutes,
70
- 'sessions_per_week': max(1, minutes // 30),
71
- 'minutes_per_session': minutes // max(1, minutes // 30)
72
- }
73
-
74
- # Dicas de estudo (IA se disponΓ­vel)
75
- def get_default_tips(level):
76
- tips_by_level = {
77
- 'A1': [
78
- "πŸ“š Start with basic vocabulary - 10 new words daily",
79
- "🎯 Focus on present tense in daily conversations",
80
- "πŸ’‘ Use picture dictionaries for visual learning",
81
- "⭐ Practice pronunciation with simple audio materials",
82
- "πŸš€ Don't worry about mistakes - communication is key!"
83
- ],
84
- 'A2': [
85
- "πŸ“š Read simple news articles and stories",
86
- "🎯 Practice past and future tenses regularly",
87
- "πŸ’‘ Join basic English conversation groups",
88
- "⭐ Use language learning apps for daily practice",
89
- "πŸš€ Watch movies with subtitles in your language"
90
- ],
91
- 'B1': [
92
- "πŸ“š Read intermediate articles on topics you enjoy",
93
- "🎯 Practice expressing opinions and preferences",
94
- "πŸ’‘ Start writing short paragraphs daily",
95
- "⭐ Listen to podcasts at normal speed",
96
- "πŸš€ Try to think in English for simple tasks"
97
- ],
98
- 'B2': [
99
- "πŸ“š Read longer articles and opinion pieces",
100
- "🎯 Practice formal and informal writing styles",
101
- "πŸ’‘ Engage in debates and discussions",
102
- "⭐ Watch news programs without subtitles",
103
- "πŸš€ Set specific goals for each study session"
104
- ],
105
- 'C1': [
106
- "πŸ“š Read academic and professional texts",
107
- "🎯 Practice nuanced expressions and idioms",
108
- "πŸ’‘ Write formal reports and presentations",
109
- "⭐ Listen to academic lectures and conferences",
110
- "πŸš€ Focus on specialized vocabulary for your field"
111
- ],
112
- 'C2': [
113
- "πŸ“š Read literature and complex analytical texts",
114
- "🎯 Master subtle language differences",
115
- "πŸ’‘ Write with stylistic sophistication",
116
- "⭐ Engage with native speakers in professional contexts",
117
- "πŸš€ Aim for native-like fluency in all skills"
118
- ]
119
- }
120
- return tips_by_level.get(level, tips_by_level['B1'])
121
-
122
- def generate_ai_tips(user_data):
123
- prompt = f"""
124
- Generate 5 personalized English study tips for a user with these characteristics:
125
- - Current Level: {user_data.get('english_level', 'B1')}
126
- - Target Level: {user_data.get('target_level', 'B2')}
127
- - Weekly Study Time: {user_data.get('weekly_hours', 5)} hours
128
- - Context Focus: {user_data.get('context_focus', 'General/Social')}
129
- - Interests: {', '.join(user_data.get('interests', {}).keys())}
130
- Provide practical, actionable tips that are specific to their level and interests. Format as a simple list of tips, each starting with an emoji.
131
- """
132
- try:
133
- if groq_client:
134
- response = groq_client.chat.completions.create(
135
- model="llama-3.1-8b-instant",
136
- messages=[{"role": "user", "content": prompt}],
137
- temperature=0.7
138
- )
139
- response_text = response.choices[0].message.content
140
- elif genai_client:
141
- model = genai_client.GenerativeModel('gemini-2.5-flash-latest')
142
- response = model.generate_content(prompt)
143
- response_text = response.text
144
- else:
145
- return get_default_tips(user_data.get('english_level', 'B1'))
146
- tips = [line.strip() for line in response_text.split('\n') if line.strip() and any(e in line for e in ['πŸ“š','πŸ’‘','🎯','⭐','πŸš€'])]
147
- return tips[:5] if tips else get_default_tips(user_data.get('english_level', 'B1'))
148
- except Exception as e:
149
- logger.warning(f"AI study tips error: {e}")
150
- return get_default_tips(user_data.get('english_level', 'B1'))
151
-
152
- study_tips = generate_ai_tips(user_data)
153
-
154
- # Milestones
155
- milestones = []
156
- milestone_intervals = max(2, adjusted_weeks // 4)
157
- for i in range(1, 5):
158
- week = milestone_intervals * i
159
- if week <= adjusted_weeks:
160
- milestones.append({
161
- 'week': week,
162
- 'title': f"Milestone {i}",
163
- 'description': f"Progress checkpoint {i}",
164
- 'target_date': (datetime.now() + timedelta(weeks=week)).date().isoformat(),
165
- 'completed': False
166
- })
167
-
168
- plan = {
169
- 'id': f"plan_{datetime.now().strftime('%Y%m%d_%H%M%S')}",
170
- 'created_at': datetime.now().isoformat(),
171
- 'current_level': current_level,
172
- 'target_level': target_level,
173
- 'weekly_hours': weekly_hours,
174
- 'estimated_weeks': adjusted_weeks,
175
- 'completion_date': completion_date,
176
- 'weekly_structure': weekly_structure,
177
- 'study_tips': study_tips,
178
- 'milestones': milestones,
179
- 'interests': interests,
180
- 'context_focus': context_focus,
181
- 'study_goals': study_goals
182
- }
183
- return plan
184
- import os
185
- import json
186
- from datetime import datetime
187
-
188
- STUDY_PLAN_PATH = 'hf_data/study_plan.json'
189
-
190
- def save_study_plan(plan_data):
191
- """Salva o plano de estudos em JSON."""
192
- os.makedirs(os.path.dirname(STUDY_PLAN_PATH), exist_ok=True)
193
- plan_data['saved_at'] = datetime.now().isoformat()
194
- with open(STUDY_PLAN_PATH, 'w', encoding='utf-8') as f:
195
- json.dump(plan_data, f, ensure_ascii=False, indent=2)
196
- return True
197
-
198
- def load_study_plan():
199
- """Carrega o plano de estudos do JSON."""
200
- if os.path.exists(STUDY_PLAN_PATH):
201
- with open(STUDY_PLAN_PATH, 'r', encoding='utf-8') as f:
202
- return json.load(f)
203
- return None
 
1
+ import logging
2
+ try:
3
+ from groq import Groq
4
+ except ImportError:
5
+ Groq = None
6
+ try:
7
+ import google.generativeai as genai
8
+ except ImportError:
9
+ genai = None
10
+
11
+ logger = logging.getLogger(__name__)
12
+ groq_client = None
13
+ genai_client = None
14
+ try:
15
+ GROQ_API_KEY = os.environ.get("GROQ_API_KEY")
16
+ if GROQ_API_KEY and Groq:
17
+ groq_client = Groq(api_key=GROQ_API_KEY)
18
+ except Exception as e:
19
+ logger.warning(f"Groq client not available: {e}")
20
+ try:
21
+ GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY")
22
+ if GEMINI_API_KEY and genai:
23
+ genai.configure(api_key=GEMINI_API_KEY)
24
+ genai_client = genai
25
+ except Exception as e:
26
+ logger.warning(f"Gemini client not available: {e}")
27
+ def generate_study_plan(user_data):
28
+ """Gera um plano de estudos estruturado a partir dos dados do usuΓ‘rio (sem IA)."""
29
+ from datetime import timedelta
30
+ current_level = user_data.get('english_level', 'B1')
31
+ target_level = user_data.get('target_level', 'B2')
32
+ weekly_hours = user_data.get('weekly_hours', 5)
33
+ interests = user_data.get('interests', {})
34
+ context_focus = user_data.get('context_focus', 'General/Social')
35
+ study_goals = user_data.get('study_goals', [])
36
+
37
+ # ProgressΓ£o de nΓ­veis
38
+ level_progression = {
39
+ 'A1': {'next': 'A2', 'weeks': 12},
40
+ 'A2': {'next': 'B1', 'weeks': 16},
41
+ 'B1': {'next': 'B2', 'weeks': 20},
42
+ 'B2': {'next': 'C1', 'weeks': 24},
43
+ 'C1': {'next': 'C2', 'weeks': 28},
44
+ 'C2': {'next': 'C2', 'weeks': 32}
45
+ }
46
+ # Timeline
47
+ base_weeks = level_progression.get(current_level, level_progression['B1'])['weeks']
48
+ hour_multiplier = 5 / max(weekly_hours, 1)
49
+ adjusted_weeks = int(base_weeks * hour_multiplier)
50
+ from datetime import datetime
51
+ completion_date = (datetime.now() + timedelta(weeks=adjusted_weeks)).date().isoformat()
52
+
53
+ # Estrutura semanal
54
+ distributions = {
55
+ 'A1': {'reading': 0.25, 'flashcards': 0.30, 'conversation': 0.20, 'writing': 0.15, 'grammar': 0.10},
56
+ 'A2': {'reading': 0.30, 'flashcards': 0.25, 'conversation': 0.20, 'writing': 0.15, 'grammar': 0.10},
57
+ 'B1': {'reading': 0.30, 'flashcards': 0.20, 'conversation': 0.25, 'writing': 0.20, 'listening': 0.05},
58
+ 'B2': {'reading': 0.25, 'flashcards': 0.15, 'conversation': 0.25, 'writing': 0.25, 'listening': 0.10},
59
+ 'C1': {'reading': 0.30, 'flashcards': 0.10, 'conversation': 0.25, 'writing': 0.25, 'listening': 0.10},
60
+ 'C2': {'reading': 0.35, 'flashcards': 0.05, 'conversation': 0.25, 'writing': 0.25, 'listening': 0.10}
61
+ }
62
+ base_dist = distributions.get(current_level, distributions['B1'])
63
+ total_minutes = weekly_hours * 60
64
+ weekly_structure = {}
65
+ for activity, percentage in base_dist.items():
66
+ minutes = int(total_minutes * percentage)
67
+ if minutes >= 10:
68
+ weekly_structure[activity] = {
69
+ 'minutes_per_week': minutes,
70
+ 'sessions_per_week': max(1, minutes // 30),
71
+ 'minutes_per_session': minutes // max(1, minutes // 30)
72
+ }
73
+
74
+ # Dicas de estudo (IA se disponΓ­vel)
75
+ def get_default_tips(level):
76
+ tips_by_level = {
77
+ 'A1': [
78
+ "πŸ“š Start with basic vocabulary - 10 new words daily",
79
+ "🎯 Focus on present tense in daily conversations",
80
+ "πŸ’‘ Use picture dictionaries for visual learning",
81
+ "⭐ Practice pronunciation with simple audio materials",
82
+ "πŸš€ Don't worry about mistakes - communication is key!"
83
+ ],
84
+ 'A2': [
85
+ "πŸ“š Read simple news articles and stories",
86
+ "🎯 Practice past and future tenses regularly",
87
+ "πŸ’‘ Join basic English conversation groups",
88
+ "⭐ Use language learning apps for daily practice",
89
+ "πŸš€ Watch movies with subtitles in your language"
90
+ ],
91
+ 'B1': [
92
+ "πŸ“š Read intermediate articles on topics you enjoy",
93
+ "🎯 Practice expressing opinions and preferences",
94
+ "πŸ’‘ Start writing short paragraphs daily",
95
+ "⭐ Listen to podcasts at normal speed",
96
+ "πŸš€ Try to think in English for simple tasks"
97
+ ],
98
+ 'B2': [
99
+ "πŸ“š Read longer articles and opinion pieces",
100
+ "🎯 Practice formal and informal writing styles",
101
+ "πŸ’‘ Engage in debates and discussions",
102
+ "⭐ Watch news programs without subtitles",
103
+ "πŸš€ Set specific goals for each study session"
104
+ ],
105
+ 'C1': [
106
+ "πŸ“š Read academic and professional texts",
107
+ "🎯 Practice nuanced expressions and idioms",
108
+ "πŸ’‘ Write formal reports and presentations",
109
+ "⭐ Listen to academic lectures and conferences",
110
+ "πŸš€ Focus on specialized vocabulary for your field"
111
+ ],
112
+ 'C2': [
113
+ "πŸ“š Read literature and complex analytical texts",
114
+ "🎯 Master subtle language differences",
115
+ "πŸ’‘ Write with stylistic sophistication",
116
+ "⭐ Engage with native speakers in professional contexts",
117
+ "πŸš€ Aim for native-like fluency in all skills"
118
+ ]
119
+ }
120
+ return tips_by_level.get(level, tips_by_level['B1'])
121
+
122
+ def generate_ai_tips(user_data):
123
+ prompt = f"""
124
+ Generate 5 personalized English study tips for a user with these characteristics:
125
+ - Current Level: {user_data.get('english_level', 'B1')}
126
+ - Target Level: {user_data.get('target_level', 'B2')}
127
+ - Weekly Study Time: {user_data.get('weekly_hours', 5)} hours
128
+ - Context Focus: {user_data.get('context_focus', 'General/Social')}
129
+ - Interests: {', '.join(user_data.get('interests', {}).keys())}
130
+ Provide practical, actionable tips that are specific to their level and interests. Format as a simple list of tips, each starting with an emoji.
131
+ """
132
+ try:
133
+ if groq_client:
134
+ response = groq_client.chat.completions.create(
135
+ model="llama-3.1-8b-instant",
136
+ messages=[{"role": "user", "content": prompt}],
137
+ temperature=0.7
138
+ )
139
+ response_text = response.choices[0].message.content
140
+ elif genai_client:
141
+ model = genai_client.GenerativeModel('gemini-2.5-flash-latest')
142
+ response = model.generate_content(prompt)
143
+ response_text = response.text
144
+ else:
145
+ return get_default_tips(user_data.get('english_level', 'B1'))
146
+ tips = [line.strip() for line in response_text.split('\n') if line.strip() and any(e in line for e in ['πŸ“š','πŸ’‘','🎯','⭐','πŸš€'])]
147
+ return tips[:5] if tips else get_default_tips(user_data.get('english_level', 'B1'))
148
+ except Exception as e:
149
+ logger.warning(f"AI study tips error: {e}")
150
+ return get_default_tips(user_data.get('english_level', 'B1'))
151
+
152
+ study_tips = generate_ai_tips(user_data)
153
+
154
+ # Milestones
155
+ milestones = []
156
+ milestone_intervals = max(2, adjusted_weeks // 4)
157
+ for i in range(1, 5):
158
+ week = milestone_intervals * i
159
+ if week <= adjusted_weeks:
160
+ milestones.append({
161
+ 'week': week,
162
+ 'title': f"Milestone {i}",
163
+ 'description': f"Progress checkpoint {i}",
164
+ 'target_date': (datetime.now() + timedelta(weeks=week)).date().isoformat(),
165
+ 'completed': False
166
+ })
167
+
168
+ plan = {
169
+ 'id': f"plan_{datetime.now().strftime('%Y%m%d_%H%M%S')}",
170
+ 'created_at': datetime.now().isoformat(),
171
+ 'current_level': current_level,
172
+ 'target_level': target_level,
173
+ 'weekly_hours': weekly_hours,
174
+ 'estimated_weeks': adjusted_weeks,
175
+ 'completion_date': completion_date,
176
+ 'weekly_structure': weekly_structure,
177
+ 'study_tips': study_tips,
178
+ 'milestones': milestones,
179
+ 'interests': interests,
180
+ 'context_focus': context_focus,
181
+ 'study_goals': study_goals
182
+ }
183
+ return plan
184
+ import os
185
+ import json
186
+ from datetime import datetime
187
+
188
+ STUDY_PLAN_PATH = 'hf_data/study_plan.json'
189
+
190
+ def save_study_plan(plan_data):
191
+ """Salva o plano de estudos em JSON."""
192
+ os.makedirs(os.path.dirname(STUDY_PLAN_PATH), exist_ok=True)
193
+ plan_data['saved_at'] = datetime.now().isoformat()
194
+ with open(STUDY_PLAN_PATH, 'w', encoding='utf-8') as f:
195
+ json.dump(plan_data, f, ensure_ascii=False, indent=2)
196
+ return True
197
+
198
+ def load_study_plan():
199
+ """Carrega o plano de estudos do JSON."""
200
+ if os.path.exists(STUDY_PLAN_PATH):
201
+ with open(STUDY_PLAN_PATH, 'r', encoding='utf-8') as f:
202
+ return json.load(f)
203
+ return None