merge the game handeling to the full flow

parent 6af7323c
...@@ -48,6 +48,7 @@ SYSTEM_PROMPTS: Dict[Tuple[StudentNationality, StudyLanguage], str] = { ...@@ -48,6 +48,7 @@ SYSTEM_PROMPTS: Dict[Tuple[StudentNationality, StudyLanguage], str] = {
# ---------- Saudi + Arabic ---------- # ---------- Saudi + Arabic ----------
(StudentNationality.SAUDI, StudyLanguage.ARABIC): """ (StudentNationality.SAUDI, StudyLanguage.ARABIC): """
إنت مُدرِّس لطفل في ابتدائي اسمه {student_name} في الصف {grade}. إنت مُدرِّس لطفل في ابتدائي اسمه {student_name} في الصف {grade}.
حاول دايمًا تكون ردودك قصيرة عشان تتقال بسرعة. لو ينفع، خليك أقل من ١٦٠ حرف. ولو محتاج توضح أكتر، ما تعديش ٣٠٠ حرف حتى لو المحتوى من المنهج كبير، خلي الرد مختصر وواضح. الاستثناء الوحيد لو الطالب طلب شرح مفصّل أو قال إنه مش فاهم.
فقط لو الطفل سأل عن هويتك بصراحة ووضح (مثل "إنت مين؟"، "عرِّفني بنفسك"، "إنت وش تسوي هنا؟")، فقط لو الطفل سأل عن هويتك بصراحة ووضح (مثل "إنت مين؟"، "عرِّفني بنفسك"، "إنت وش تسوي هنا؟")،
رُد بالنص الثابت هذا: رُد بالنص الثابت هذا:
"أنا عَنان مؤسِّس شارع العلوم، وإنت هنا على مَنَصّة Science Street Lab، "أنا عَنان مؤسِّس شارع العلوم، وإنت هنا على مَنَصّة Science Street Lab،
...@@ -94,6 +95,7 @@ SYSTEM_PROMPTS: Dict[Tuple[StudentNationality, StudyLanguage], str] = { ...@@ -94,6 +95,7 @@ SYSTEM_PROMPTS: Dict[Tuple[StudentNationality, StudyLanguage], str] = {
# -------- Egyptian English -------- # -------- Egyptian English --------
(StudentNationality.EGYPTIAN, StudyLanguage.ENGLISH): """ (StudentNationality.EGYPTIAN, StudyLanguage.ENGLISH): """
إنت مُدرِّس لطفل في ابتدائي اسمه {student_name} في الصف {grade}. إنت مُدرِّس لطفل في ابتدائي اسمه {student_name} في الصف {grade}.
حاول دايمًا تكون ردودك قصيرة عشان تتقال بسرعة. لو ينفع، خليك أقل من ١٦٠ حرف. ولو محتاج توضح أكتر، ما تعديش ٣٠٠ حرف حتى لو المحتوى من المنهج كبير، خلي الرد مختصر وواضح. الاستثناء الوحيد لو الطالب طلب شرح مفصّل أو قال إنه مش فاهم.
لو الطفّل سأل عن هويتك بصراحة (زي "إنت مين؟"، "عرِّفني بنفسك")، لو الطفّل سأل عن هويتك بصراحة (زي "إنت مين؟"، "عرِّفني بنفسك")،
رُد بالنصّ الثابت ده: رُد بالنصّ الثابت ده:
"أنا عَنان مؤسس شارع العلوم، وإنت هنا على مَنَصّة Science Street Lab، "أنا عَنان مؤسس شارع العلوم، وإنت هنا على مَنَصّة Science Street Lab،
...@@ -161,6 +163,7 @@ SYSTEM_PROMPTS: Dict[Tuple[StudentNationality, StudyLanguage], str] = { ...@@ -161,6 +163,7 @@ SYSTEM_PROMPTS: Dict[Tuple[StudentNationality, StudyLanguage], str] = {
# -------- Saudi English -------- # -------- Saudi English --------
(StudentNationality.SAUDI, StudyLanguage.ENGLISH): """ (StudentNationality.SAUDI, StudyLanguage.ENGLISH): """
إنت مُدرِّس لطفل في ابتدائي اسمه {student_name} في الصف {grade}. إنت مُدرِّس لطفل في ابتدائي اسمه {student_name} في الصف {grade}.
حاول دايمًا تكون ردودك قصيرة عشان تتقال بسرعة. لو ينفع، خليك أقل من ١٦٠ حرف. ولو محتاج توضح أكتر، ما تعديش ٣٠٠ حرف حتى لو المحتوى من المنهج كبير، خلي الرد مختصر وواضح. الاستثناء الوحيد لو الطالب طلب شرح مفصّل أو قال إنه مش فاهم.
لو الطفل سأل عن هويتك بصراحة (زي "إنت مين؟"، "عرِّفني بنفسك"، "إنت وش تسوي هنا؟")، لو الطفل سأل عن هويتك بصراحة (زي "إنت مين؟"، "عرِّفني بنفسك"، "إنت وش تسوي هنا؟")،
رُد بالنصّ الثابت هذا: رُد بالنصّ الثابت هذا:
"أنا عَنان مؤسس شارع العلوم، وإنت هنا على مَنَصّة Science Street Lab، "أنا عَنان مؤسس شارع العلوم، وإنت هنا على مَنَصّة Science Street Lab،
......
...@@ -110,6 +110,9 @@ class QueryHandler: ...@@ -110,6 +110,9 @@ class QueryHandler:
2. "overview" - أسئلة عن نظرة عامة على المنهج أو المحتوى الكامل 2. "overview" - أسئلة عن نظرة عامة على المنهج أو المحتوى الكامل
3. "navigation" - أسئلة عن وحدة أو مفهوم معين 3. "navigation" - أسئلة عن وحدة أو مفهوم معين
4. "specific_content" - أسئلة محددة عن موضوع علمي معين 4. "specific_content" - أسئلة محددة عن موضوع علمي معين
5. "game_help:" - أسئلة عن مساعدة او تفاعل في لعبة تعليمية بيكون شكل الرسالة كدا دايما
game context: <context text>
user query: <query text>
{conversation_context} {conversation_context}
السؤال الحالي: "{query}" السؤال الحالي: "{query}"
...@@ -121,6 +124,9 @@ class QueryHandler: ...@@ -121,6 +124,9 @@ class QueryHandler:
- إذا كان الطالب يتحدث عن موضوع علمي معين وسأل سؤال متعلق به، فهو "specific_content" - إذا كان الطالب يتحدث عن موضوع علمي معين وسأل سؤال متعلق به، فهو "specific_content"
- إذا كان السؤال غامض، اعتمد على السياق لتحديد القصد الحقيقي - إذا كان السؤال غامض، اعتمد على السياق لتحديد القصد الحقيقي
- مثال: إذا كان يتحدث عن النباتات وسأل "كيف تأكل؟" فهو يقصد تغذية النباتات وليس الطعام العادي - مثال: إذا كان يتحدث عن النباتات وسأل "كيف تأكل؟" فهو يقصد تغذية النباتات وليس الطعام العادي
- لو السؤال فيه الصيغة دي:
"game context:" وبعدها "user query:"، فالتصنيف الصحيح دايمًا يكون "game_help" مهما كان المحتوى
""" """
...@@ -137,7 +143,7 @@ class QueryHandler: ...@@ -137,7 +143,7 @@ class QueryHandler:
valid_classes = { valid_classes = {
"general_chat", "overview", "navigation", "specific_content" "general_chat", "overview", "navigation", "specific_content", "game_help"
} }
if classification in valid_classes: if classification in valid_classes:
...@@ -155,6 +161,12 @@ class QueryHandler: ...@@ -155,6 +161,12 @@ class QueryHandler:
logger.warning(f"Error in query classification: {e}, defaulting to 'specific_content'") logger.warning(f"Error in query classification: {e}, defaulting to 'specific_content'")
return "specific_content" return "specific_content"
except Exception as e:
logger.warning(f"Error in query classification: {e}, defaulting to 'specific_content'")
return "specific_content"
def handle_general_chat_query(self, query: str, student_info: Dict[str, Any]) -> str: def handle_general_chat_query(self, query: str, student_info: Dict[str, Any]) -> str:
"""Handle general chat queries using only student information""" """Handle general chat queries using only student information"""
student_name: str = student_info.get('student_name', 'الطالب') student_name: str = student_info.get('student_name', 'الطالب')
...@@ -248,3 +260,23 @@ class QueryHandler: ...@@ -248,3 +260,23 @@ class QueryHandler:
logger.error(f"Error getting navigation response: {e}") logger.error(f"Error getting navigation response: {e}")
# Fallback to overview if navigation fails # Fallback to overview if navigation fails
return self.handle_overview_query(student_info, subject) return self.handle_overview_query(student_info, subject)
def handle_game_help_query(self, message: str):
"""
Extracts 'game_context' and 'user_query' from the full message text.
Expected format:
game context: <context text>
user query: <query text>
Returns a dictionary with both parts.
"""
game_context = ""
user_query = ""
parts = message.split("user query:")
if len(parts) == 2:
game_context = parts[0].replace("game context:", "").strip()
user_query = parts[1].strip()
return game_context, user_query
...@@ -100,16 +100,9 @@ class ResponseGenerator: ...@@ -100,16 +100,9 @@ class ResponseGenerator:
# Prepare system prompt # Prepare system prompt
formatted_base_prompt = self.prepare_system_prompt(student_info) formatted_base_prompt = self.prepare_system_prompt(student_info)
# Build base messages # Build base messages
messages = [{"role": "system", "content": formatted_base_prompt}] messages = [{"role": "system", "content": formatted_base_prompt}]
messages.extend(conversation_history) messages.extend(conversation_history)
messages.append({"role": "user", "content": user_message})
# ==========================
# HANDLE SAFE QUERIES
# ==========================
if query_type == "general_chat": if query_type == "general_chat":
chat_context = self.query_handler.handle_general_chat_query(user_message, student_info) chat_context = self.query_handler.handle_general_chat_query(user_message, student_info)
...@@ -135,6 +128,33 @@ class ResponseGenerator: ...@@ -135,6 +128,33 @@ class ResponseGenerator:
messages.append({"role": "system", "content": enhanced_context}) messages.append({"role": "system", "content": enhanced_context})
logger.info(f"Added enhanced context with {len(relevant_results)} chunks for student {student_name}") logger.info(f"Added enhanced context with {len(relevant_results)} chunks for student {student_name}")
elif query_type == "game_help":
game_context, user_query = self.query_handler.handle_game_help_query(user_message)
logger.info(f"Handling game_help query. Context: {game_context}")
# Start building a single, comprehensive context string
system_context = f"سياق اللعبة التعليمية اللي هتساعد الطفل فيها:\n{game_context}"
# Search for and add curriculum context if it exists
relevant_results = self.context_generator.search_enhanced_content(
user_query, student_info, subject, top_k
)
if relevant_results:
enhanced_context = self.context_generator.generate_enhanced_context(
relevant_results, student_info, query_type
)
# Append the curriculum context to the same string
system_context += f"\n\nمحتوي المنهج اللي ليه علاقة بسؤال الطفل:\n{enhanced_context}"
logger.info(f"Added enhanced context with {len(relevant_results)} chunks for game help.")
# Now, add only ONE system message with all the context
messages.append({"role": "system", "content": system_context})
# Finally add user message
messages.append({"role": "user", "content": user_message})
# ========================== # ==========================
# CALL AI MODEL # CALL AI MODEL
# ========================== # ==========================
......
...@@ -33,7 +33,7 @@ class ChatService: ...@@ -33,7 +33,7 @@ class ChatService:
def process_message(self, student_id: str, file: Optional[UploadFile] = None, text: Optional[str] = None): def process_message(self, student_id: str, file: Optional[UploadFile] = None, text: Optional[str] = None, game_context: Optional[str] = None):
"""Process message and generate text and audio response.""" """Process message and generate text and audio response."""
self.response_manager.clear_response() self.response_manager.clear_response()
try: try:
...@@ -45,8 +45,13 @@ class ChatService: ...@@ -45,8 +45,13 @@ class ChatService:
else: else:
raise HTTPException(status_code=400, detail="No text or audio file provided.") raise HTTPException(status_code=400, detail="No text or audio file provided.")
final_message_for_agent = user_message
if game_context:
print(f"Game context provided: {game_context}")
final_message_for_agent = f"game context: {game_context}\nuser query: {user_message}"
agent_response_text = self.agent_service.generate_response( agent_response_text = self.agent_service.generate_response(
user_message=user_message, user_message=final_message_for_agent, # <-- USE THE NEW VARIABLE HERE
student_id=student_id, student_id=student_id,
) )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment