# chat_processor.py import datetime from llm_handler import get_gemini_response from rag_manager import add_documents_to_rag, get_all_student_observations_from_rag from db_manager import add_or_update_student, get_all_student_names import prompts import re import streamlit as st def extract_info_from_chat(chat_log_text: str) -> list: """使用LLM从聊天记录中提取学生表现信息""" if not chat_log_text.strip(): return [] prompt = prompts.CHAT_EXTRACTION_USER_PROMPT_TEMPLATE.format(chat_log_text=chat_log_text) system_instruction = prompts.CHAT_EXTRACTION_SYSTEM_PROMPT response_text = get_gemini_response(prompt, system_instruction=system_instruction) if not response_text: st.warning("AI未能从聊天记录中提取到文本响应。") return [] extracted_items = [] lines = response_text.strip().split('\n') for line in lines: line = line.strip() if not line: continue # Skip empty lines # More robust regex: allows for names with spaces if not ending with colon immediately match = re.match(r"([^:]+?)\s*:\s*(.+)", line) if match: student_name = match.group(1).strip() observation = match.group(2).strip() if student_name and observation: # Ensure both parts are non-empty extracted_items.append({"student_name": student_name, "observation": observation}) else: print(f"Skipping partially extracted line: '{line}'") # Log for debugging else: print(f"Could not parse line from LLM: '{line}'") # Log for debugging if not extracted_items: st.info("AI分析完成,但未能按预期格式解析出学生信息。可能是聊天内容不包含相关信息,或AI响应格式不符。") return extracted_items def update_student_characteristics_from_rag(student_name: str): """从RAG中获取学生所有记录,让LLM总结特点,并更新到学生数据库""" observations = get_all_student_observations_from_rag(student_name) if not observations: st.info(f"在RAG中未找到学生 {student_name} 的历史表现记录,无法更新特点。") # Ensure student exists in DB even if no observations yet, or update timestamp add_or_update_student(student_name) return # Limit number of observations to avoid overly long prompts for LLM MAX_OBSERVATIONS_FOR_SUMMARY = 50 # Adjust as needed if len(observations) > MAX_OBSERVATIONS_FOR_SUMMARY: st.info(f"学生 {student_name} 有超过 {MAX_OBSERVATIONS_FOR_SUMMARY} 条记录,将使用最新的 {MAX_OBSERVATIONS_FOR_SUMMARY} 条进行特点总结。") observations_to_use = observations[-MAX_OBSERVATIONS_FOR_SUMMARY:] else: observations_to_use = observations observations_text = "\n".join([f"- {obs}" for obs in observations_to_use]) # Add bullet points for clarity prompt = prompts.STUDENT_CHARACTERISTICS_USER_PROMPT_TEMPLATE.format( student_name=student_name, observations_text=observations_text ) system_instruction = prompts.STUDENT_CHARACTERISTICS_SYSTEM_PROMPT summary = get_gemini_response(prompt, system_instruction=system_instruction) if summary: if add_or_update_student(student_name, characteristics_summary=summary.strip()): st.success(f"已更新学生 {student_name} 的特点总结。") else: st.error(f"更新学生 {student_name} 的特点总结到数据库时失败。") else: st.warning(f"未能为学生 {student_name} 生成特点总结。AI未返回有效内容。") def batch_update_all_students_characteristics(): """为数据库中所有学生更新其特点总结""" student_names = get_all_student_names() if not student_names: st.info("学生数据库为空,无法批量更新特点。") return st.info(f"开始批量更新 {len(student_names)} 位学生的特点总结...") progress_bar = st.progress(0) for i, name in enumerate(student_names): st.write(f"正在处理: {name}...") # Give some feedback during long process update_student_characteristics_from_rag(name) progress_bar.progress((i + 1) / len(student_names)) st.success("所有学生特点总结批量更新完毕!")