# api/courseware/teaching_copilot.py """ Teaching Copilot & Student Adaptation:课堂实时辅助,按学生画像(Name, Progress, Behavior)动态调整建议。 """ from typing import Optional, List, Dict, Any, Tuple from api.config import client, DEFAULT_MODEL from api.courseware.rag import get_rag_context_with_refs, inject_refs_instruction from api.courseware.references import append_references_to_content from api.courseware.prompts import TEACHING_COPILOT_SYSTEM, TEACHING_COPILOT_USER_TEMPLATE def _format_student_profiles(profiles: List[Dict[str, Any]]) -> str: """将学生画像列表格式化为可读文本。""" if not profiles: return "(未提供)" lines = [] for i, p in enumerate(profiles[:20], 1): name = p.get("name") or p.get("Name") or "—" progress = p.get("progress") or p.get("Progress") or "—" behavior = p.get("behavior") or p.get("Behavior") or "—" lines.append(f"- 学生{i}: Name={name}, Progress={progress}, Behavior={behavior}") return "\n".join(lines) def teaching_copilot( current_content: str, student_profiles: Optional[List[Dict[str, Any]]] = None, max_tokens: int = 1200, history: Optional[list] = None, ) -> str: """ 课堂实时辅助:根据当前授课内容与学生画像给出即时建议与个性化调整。 """ query = current_content[:1500] rag_context, refs = get_rag_context_with_refs(query, top_k=6, max_context_chars=3500) ref_instruction = inject_refs_instruction(refs) profiles_text = _format_student_profiles(student_profiles or []) user_content = TEACHING_COPILOT_USER_TEMPLATE.format( current_content=current_content.strip() or "(未提供当前内容)", student_profiles=profiles_text, rag_context=rag_context or "(无检索到知识库摘录。)", ref_instruction=ref_instruction, ) messages = [{"role": "system", "content": TEACHING_COPILOT_SYSTEM}] if history: for user_msg, assistant_msg in history[-10:]: if user_msg: messages.append({"role": "user", "content": user_msg}) if assistant_msg: messages.append({"role": "assistant", "content": assistant_msg}) messages.append({"role": "user", "content": user_content}) try: resp = client.chat.completions.create( model=DEFAULT_MODEL, messages=messages, temperature=0.5, max_tokens=max_tokens, timeout=60, ) out = (resp.choices[0].message.content or "").strip() except Exception as e: out = f"生成失败:{e}。请稍后重试。" if refs and "## References" not in out and "[Source:" not in out: out = append_references_to_content(out, refs) return out