Spaces:
Sleeping
Sleeping
Create smart_plan.py
Browse files- modules/smart_plan.py +142 -0
modules/smart_plan.py
ADDED
@@ -0,0 +1,142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import datetime
|
2 |
+
import difflib
|
3 |
+
import re
|
4 |
+
|
5 |
+
def generate_smart_plan(user_id, start_date_str, goal):
|
6 |
+
start_date = datetime.datetime.strptime(start_date_str, "%Y-%m-%d").date()
|
7 |
+
|
8 |
+
if not user_id:
|
9 |
+
return "β Please enter a nickname in the Welcome tab.", "", "π
Week 1"
|
10 |
+
|
11 |
+
user_key = user_id.strip().lower()
|
12 |
+
goal_key = goal.lower().strip()
|
13 |
+
|
14 |
+
if goal_key not in course_suggestions:
|
15 |
+
close_matches = difflib.get_close_matches(goal_key, course_suggestions.keys(), n=1, cutoff=0.6)
|
16 |
+
if close_matches:
|
17 |
+
goal_key = close_matches[0]
|
18 |
+
|
19 |
+
|
20 |
+
steps = []
|
21 |
+
steps = [smart_label_converter(s) for s in steps if isinstance(s, str) and len(s.strip()) > 1]
|
22 |
+
plan_markdown = ""
|
23 |
+
plan_source = ""
|
24 |
+
summary = ""
|
25 |
+
courses = []
|
26 |
+
|
27 |
+
# 1οΈβ£ Try RAG
|
28 |
+
recalled = recall_from_memory(user_key, goal_key)
|
29 |
+
if recalled and "β" not in recalled:
|
30 |
+
print("β
RAG hit")
|
31 |
+
steps = recalled.split("\n")
|
32 |
+
steps = [smart_label_converter(s) for s in steps if isinstance(s, str) and len(s.strip()) > 1]
|
33 |
+
plan_markdown = (f"### π§ Plan for {goal}\n\n_Recalled from memory_\n\n" +"\n".join(smart_label_converter(s) for s in steps))
|
34 |
+
plan_source = "π Loaded from memory (RAG)"
|
35 |
+
|
36 |
+
if not steps:
|
37 |
+
print("π§ͺ Trying Tavilly fallback for:", goal_key)
|
38 |
+
|
39 |
+
try:
|
40 |
+
result = call_tavilly_rag(user_id, goal_key)
|
41 |
+
print("β
Tavilly returned something:", result)
|
42 |
+
|
43 |
+
tav_plan = result[0]
|
44 |
+
tav_plan = re.sub(r'(Create a weekly roadmap.*?)\1+', r'\1', tav_plan, flags=re.DOTALL)
|
45 |
+
|
46 |
+
tav_steps = result[2]
|
47 |
+
tav_steps = [smart_label_converter(s) for s in tav_steps if isinstance(s, str) and len(s.strip()) > 1]
|
48 |
+
|
49 |
+
|
50 |
+
if tav_steps and len(tav_steps) > 1:
|
51 |
+
print("π Tavilly used")
|
52 |
+
steps = tav_steps
|
53 |
+
plan_markdown = tav_plan
|
54 |
+
plan_source = "π Generated via Tavilly (web search)"
|
55 |
+
|
56 |
+
courses = get_courses_for_goal(goal_key) # <-- use the fuzzy look
|
57 |
+
|
58 |
+
if courses:
|
59 |
+
course_section = (
|
60 |
+
"\n\n### π Recommended Courses\n" +
|
61 |
+
"\n".join([f"- [{name}]({url})" for name, url in courses]))
|
62 |
+
|
63 |
+
else:
|
64 |
+
course_section = ""
|
65 |
+
|
66 |
+
plan_markdown += course_section
|
67 |
+
pass
|
68 |
+
|
69 |
+
except Exception as e:
|
70 |
+
print(f"β οΈ Tavilly failed: {e}")
|
71 |
+
|
72 |
+
|
73 |
+
# 3οΈβ£ Try GPT-4o fallback
|
74 |
+
if not steps:
|
75 |
+
try:
|
76 |
+
steps = run_gpt_fallback(goal_key)
|
77 |
+
steps = [smart_label_converter(s) for s in steps if isinstance(s, str) and len(s.strip()) > 1]
|
78 |
+
print("π€ GPT-4o fallback used")
|
79 |
+
plan_source = "π€ Generated with GPT-4o fallback"
|
80 |
+
|
81 |
+
diagram = render_text_roadmap(goal, steps)
|
82 |
+
summary = summarizer(f"Create a weekly roadmap for {goal}.", max_new_tokens=300, do_sample=False)[0]["generated_text"]
|
83 |
+
|
84 |
+
courses = course_suggestions.get(goal_key, [])
|
85 |
+
if courses:
|
86 |
+
course_section = ("\n\n### π Recommended Courses\n" +"\n".join([f"- [{name}]({url})" for name, url in courses]))
|
87 |
+
else:
|
88 |
+
course_section = ""
|
89 |
+
|
90 |
+
plan_markdown = f"""
|
91 |
+
### π§ Career Plan for {goal}
|
92 |
+
|
93 |
+
```
|
94 |
+
{diagram}
|
95 |
+
```
|
96 |
+
|
97 |
+
{summary}{course_section}
|
98 |
+
|
99 |
+
**π Do your study check-ins yourself and weekly follow up in the Memo tab.**
|
100 |
+
|
101 |
+
---
|
102 |
+
|
103 |
+
_Source: {plan_source}_
|
104 |
+
"""
|
105 |
+
save_to_memory(user_id, goal, summary, steps, courses)
|
106 |
+
|
107 |
+
except Exception as e:
|
108 |
+
print(f"β GPT fallback failed: {e}")
|
109 |
+
|
110 |
+
# 4οΈβ£ Static fallback
|
111 |
+
if not steps:
|
112 |
+
print("π¦ Using static backup")
|
113 |
+
steps = [
|
114 |
+
"Action: Search Coursera for a beginner course.",
|
115 |
+
"Resource: Watch at least 1 hour and reflect.",
|
116 |
+
"Milestone: Write a journal entry on what you learned."
|
117 |
+
]
|
118 |
+
steps = [smart_label_converter(s) for s in steps if isinstance(s, str) and len(s.strip()) > 1]
|
119 |
+
|
120 |
+
|
121 |
+
plan_markdown = f"""
|
122 |
+
### π§ Static Plan for {goal}
|
123 |
+
|
124 |
+
Start with some basic research and courses. Track progress in the Courses tab.
|
125 |
+
|
126 |
+
**π Do your study check-ins yourself and weekly follow up in the Memo tab.**
|
127 |
+
|
128 |
+
---
|
129 |
+
|
130 |
+
_Source: π¦ Static backup used_
|
131 |
+
"""
|
132 |
+
plan_source = "π¦ Static backup used"
|
133 |
+
|
134 |
+
# π Push steps into Memo Task List
|
135 |
+
for step in steps:
|
136 |
+
if isinstance(step, str) and len(step.strip()) > 1:
|
137 |
+
add_task(user_id, task=step, duration=2, difficulty="Moderate", tag=None, source="career")
|
138 |
+
|
139 |
+
print("β
Returning", len(steps), "steps for goal:", goal)
|
140 |
+
return plan_markdown, gr.update(choices=steps, value=[]), "π
Week 1"
|
141 |
+
|
142 |
+
|