Spaces:
Sleeping
Sleeping
Upload main.py
Browse files- app/main.py +57 -26
app/main.py
CHANGED
|
@@ -9,6 +9,7 @@ import os
|
|
| 9 |
from sklearn.metrics.pairwise import linear_kernel
|
| 10 |
from app.services.psych_service import psych_service
|
| 11 |
from typing import List
|
|
|
|
| 12 |
|
| 13 |
app = FastAPI(title="MORA - AI Learning Assistant (Final)")
|
| 14 |
|
|
@@ -19,6 +20,39 @@ models = {
|
|
| 19 |
'matrix': None
|
| 20 |
}
|
| 21 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
# --- 1. STARTUP: LOAD MODEL .PKL ---
|
| 23 |
@app.on_event("startup")
|
| 24 |
def load_models():
|
|
@@ -132,35 +166,23 @@ def get_recommendations(user: schemas.UserProfile):
|
|
| 132 |
|
| 133 |
@app.post("/chat/process", response_model=schemas.ChatResponse)
|
| 134 |
async def process_chat(req: schemas.ChatRequest):
|
| 135 |
-
# 1. Ambil data role
|
| 136 |
role_data = skill_manager.get_role_data(req.role)
|
| 137 |
# --- [UPDATE BARU: Ektrak Silabus Lengkap] ---
|
| 138 |
# Kita buat string rapi berisi Skill + Topik-topiknya
|
| 139 |
-
|
| 140 |
-
if role_data:
|
| 141 |
-
for s in role_data['sub_skills']:
|
| 142 |
-
# Ambil nama skill utama
|
| 143 |
-
skill_name = s['name']
|
| 144 |
-
|
| 145 |
-
# Kumpulkan semua exam_topics dari level beginner, intermediate, advanced
|
| 146 |
-
all_topics = []
|
| 147 |
-
for lvl_key, lvl_data in s['levels'].items():
|
| 148 |
-
topics = lvl_data.get('exam_topics', [])
|
| 149 |
-
all_topics.extend(topics)
|
| 150 |
-
|
| 151 |
-
# Hapus duplikat topik dan gabungkan jadi string
|
| 152 |
-
unique_topics = list(set(all_topics))
|
| 153 |
-
topic_str = ", ".join(unique_topics)
|
| 154 |
-
|
| 155 |
-
syllabus_list.append(f"TOPIC {skill_name}: [{topic_str}]")
|
| 156 |
|
| 157 |
-
#
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 161 |
|
| 162 |
# 2. Router
|
| 163 |
-
intent = await llm_engine.process_user_intent(req.message,
|
| 164 |
|
| 165 |
action = intent.get('action')
|
| 166 |
# PERUBAHAN 1: Ambil List skills, bukan single skill
|
|
@@ -214,9 +236,13 @@ async def process_chat(req: schemas.ChatRequest):
|
|
| 214 |
final_reply = f"Siap! Saya siapkan {len(exam_list)} ujian untukmu: **{skill_display}**. Silakan kerjakan satu per satu di bawah ini! ๐"
|
| 215 |
|
| 216 |
else:
|
| 217 |
-
# Jika user mau ujian tapi skill ga jelas
|
| 218 |
action = "CASUAL_CHAT"
|
| 219 |
-
final_reply = await llm_engine.casual_chat(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 220 |
|
| 221 |
elif action == "START_PSYCH_TEST":
|
| 222 |
response_data = {"trigger_psych_test": True}
|
|
@@ -227,7 +253,12 @@ async def process_chat(req: schemas.ChatRequest):
|
|
| 227 |
final_reply = "Sedang menganalisis kebutuhan belajarmu..."
|
| 228 |
|
| 229 |
elif action == "CASUAL_CHAT":
|
| 230 |
-
final_reply = await llm_engine.casual_chat(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 231 |
|
| 232 |
return schemas.ChatResponse(
|
| 233 |
reply=final_reply,
|
|
|
|
| 9 |
from sklearn.metrics.pairwise import linear_kernel
|
| 10 |
from app.services.psych_service import psych_service
|
| 11 |
from typing import List
|
| 12 |
+
import re
|
| 13 |
|
| 14 |
app = FastAPI(title="MORA - AI Learning Assistant (Final)")
|
| 15 |
|
|
|
|
| 20 |
'matrix': None
|
| 21 |
}
|
| 22 |
|
| 23 |
+
SKILL_KEYWORDS = []
|
| 24 |
+
|
| 25 |
+
@app.on_event("startup")
|
| 26 |
+
def load_skill_keywords():
|
| 27 |
+
global SKILL_KEYWORDS
|
| 28 |
+
try:
|
| 29 |
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
| 30 |
+
csv_path = os.path.join(current_dir, "data", "Skill Keywords.csv")
|
| 31 |
+
df = pd.read_csv(csv_path)
|
| 32 |
+
SKILL_KEYWORDS = df['keyword'].dropna().tolist()
|
| 33 |
+
print(f"โ
Berhasil memuat {len(SKILL_KEYWORDS)} keywords skill.")
|
| 34 |
+
except Exception as e:
|
| 35 |
+
print(f"โ ๏ธ Gagal memuat dataset keyword: {e}")
|
| 36 |
+
SKILL_KEYWORDS = []
|
| 37 |
+
|
| 38 |
+
# Fungsi Pembantu: Mencari keyword dalam pesan user
|
| 39 |
+
def find_keywords_in_text(user_text: str):
|
| 40 |
+
found = []
|
| 41 |
+
text_lower = " " + user_text.lower() + " " # Tambah spasi biar aman deteksi kata pendek
|
| 42 |
+
|
| 43 |
+
for k in SKILL_KEYWORDS:
|
| 44 |
+
# Cek sederhana: Apakah keyword ada di dalam pesan?
|
| 45 |
+
# Untuk kata pendek (<3 huruf) seperti "C", "R", "Go", kita pakai spasi agar tidak match "Car" atau "Goat"
|
| 46 |
+
if len(k) < 3:
|
| 47 |
+
if f" {k.lower()} " in text_lower:
|
| 48 |
+
found.append(k)
|
| 49 |
+
else:
|
| 50 |
+
if k.lower() in text_lower:
|
| 51 |
+
found.append(k)
|
| 52 |
+
|
| 53 |
+
# Hapus duplikat dan kembalikan
|
| 54 |
+
return list(set(found))
|
| 55 |
+
|
| 56 |
# --- 1. STARTUP: LOAD MODEL .PKL ---
|
| 57 |
@app.on_event("startup")
|
| 58 |
def load_models():
|
|
|
|
| 166 |
|
| 167 |
@app.post("/chat/process", response_model=schemas.ChatResponse)
|
| 168 |
async def process_chat(req: schemas.ChatRequest):
|
|
|
|
| 169 |
role_data = skill_manager.get_role_data(req.role)
|
| 170 |
# --- [UPDATE BARU: Ektrak Silabus Lengkap] ---
|
| 171 |
# Kita buat string rapi berisi Skill + Topik-topiknya
|
| 172 |
+
found_keywords = find_keywords_in_text(req.message)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 173 |
|
| 174 |
+
# Siapkan context string untuk dikirim ke LLM
|
| 175 |
+
if found_keywords:
|
| 176 |
+
# Jika ketemu: "User bertanya tentang: Python, SQL"
|
| 177 |
+
keyword_context = ", ".join(found_keywords)
|
| 178 |
+
dataset_status = "FOUND"
|
| 179 |
+
else:
|
| 180 |
+
# Jika tidak ketemu
|
| 181 |
+
keyword_context = "NONE"
|
| 182 |
+
dataset_status = "NOT_FOUND"
|
| 183 |
|
| 184 |
# 2. Router
|
| 185 |
+
intent = await llm_engine.process_user_intent(req.message, [])
|
| 186 |
|
| 187 |
action = intent.get('action')
|
| 188 |
# PERUBAHAN 1: Ambil List skills, bukan single skill
|
|
|
|
| 236 |
final_reply = f"Siap! Saya siapkan {len(exam_list)} ujian untukmu: **{skill_display}**. Silakan kerjakan satu per satu di bawah ini! ๐"
|
| 237 |
|
| 238 |
else:
|
|
|
|
| 239 |
action = "CASUAL_CHAT"
|
| 240 |
+
final_reply = await llm_engine.casual_chat(
|
| 241 |
+
req.message,
|
| 242 |
+
[m.dict() for m in req.history],
|
| 243 |
+
keyword_context,
|
| 244 |
+
dataset_status
|
| 245 |
+
)
|
| 246 |
|
| 247 |
elif action == "START_PSYCH_TEST":
|
| 248 |
response_data = {"trigger_psych_test": True}
|
|
|
|
| 253 |
final_reply = "Sedang menganalisis kebutuhan belajarmu..."
|
| 254 |
|
| 255 |
elif action == "CASUAL_CHAT":
|
| 256 |
+
final_reply = await llm_engine.casual_chat(
|
| 257 |
+
req.message,
|
| 258 |
+
[m.dict() for m in req.history],
|
| 259 |
+
keyword_context,
|
| 260 |
+
dataset_status
|
| 261 |
+
)
|
| 262 |
|
| 263 |
return schemas.ChatResponse(
|
| 264 |
reply=final_reply,
|