# api/courseware/content_generator.py """ Content Generator:生成 Markdown 详细教案,并导出可用于生成 PPT 的结构化数据。 """ from typing import Optional, List, 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 CONTENT_GENERATOR_SYSTEM, CONTENT_GENERATOR_LESSON_PLAN_TEMPLATE def generate_lesson_plan_and_ppt_data( topic: str, duration: Optional[str] = None, outline_points: Optional[str] = None, max_tokens: int = 2800, history: Optional[list] = None, ) -> str: """ 生成 Markdown 详细教案 + 可用于 PPT 的结构化数据(每页 title、bullets、speaker_notes)。 """ query = f"{topic}\n{outline_points or ''}"[:2000] rag_context, refs = get_rag_context_with_refs(query, top_k=8, max_context_chars=5000) ref_instruction = inject_refs_instruction(refs) user_content = CONTENT_GENERATOR_LESSON_PLAN_TEMPLATE.format( topic=topic.strip() or "(未提供主题)", duration=(duration or "1 课时").strip(), outline_points=(outline_points or "(未提供,请根据主题生成)").strip(), rag_context=rag_context or "(无检索到知识库摘录。)", ref_instruction=ref_instruction, ) messages = [{"role": "system", "content": CONTENT_GENERATOR_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.4, max_tokens=max_tokens, timeout=120, ) 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