## AI Courseware 结构化 API 使用说明(前后端协作) 本说明基于《AI Courseware AI 接口文档 v1.0》,结合当前 Clare Courseware 实现,帮助前端与其他后端服务正确调用 AI 课程设计相关接口。 --- ### 1. 服务 Base URL 与部署 - 所有接口均由 Clare 后端 (`api/server.py`) 暴露。 - 部署在本地开发环境时: - Base URL 通常为 `http://localhost:8000` - 部署在 Hugging Face Space 或其他环境时: - 前端通过 Vite 环境变量 `VITE_API_BASE` 配置 Base URL - 例如:`VITE_API_BASE=https://your-space.hf.space` > 下文统一用 `{{BASE}}` 表示后端根地址(如 `http://localhost:8000`)。 --- ### 2. 路由概览 #### 2.1 现有 Clare Teacher/Courseware 接口(非结构化文本) 这些接口主要给当前 Clare 前端使用,返回 Markdown/文本: - `POST {{BASE}}/api/courseware/vision` - `POST {{BASE}}/api/courseware/activities` - `POST {{BASE}}/api/courseware/copilot` - `POST {{BASE}}/api/courseware/qa-optimize` - `POST {{BASE}}/api/courseware/content` 对应的前端封装函数在 `web/src/lib/api.ts` 中: - `apiCoursewareVision` - `apiCoursewareActivities` - `apiCoursewareCopilot` - `apiCoursewareQAOptimize` - `apiCoursewareContent` #### 2.2 新增 AI Courseware 结构化接口(建议给 LMS/独立前端用) 新路由前缀:`/ai/courseware`,在 `api/routes_courseware_ai.py` 中实现,返回结构化 JSON (`data + meta`): 1. **生成大纲草案** - `POST {{BASE}}/ai/courseware/syllabus/generate` 2. **生成单个模块的教学流程** - `POST {{BASE}}/ai/courseware/flow/generate` 3. **局部重构教学流程(Copilot)** - `POST {{BASE}}/ai/courseware/flow/regenerate-partial` 4. **生成/润色教案长文** - `POST {{BASE}}/ai/courseware/plan/detail/generate` 5. **生成反思看板数据** - `POST {{BASE}}/ai/courseware/reflection/generate` 6. **生成跨期改进提案** - `POST {{BASE}}/ai/courseware/improvement/generate` 所有成功响应都遵循统一包装: ```json { "data": { ... }, // 每个接口自己的数据结构 "meta": { "model": "gpt-4o", "model_version": null, "prompt_version": "v1.0", "temperature": 0.4, "tokens_used": 1234, "latency_ms": 5678 } } ``` `meta` 由后端统一生成,包含模型、Prompt 版本、token 消耗和延迟,便于监控。 --- ### 3. 前端 TypeScript 封装(`web/src/lib/api.ts`) 前端已经在 `web/src/lib/api.ts` 中提供了 6 个结构化接口的封装函数,可直接在 React 组件中调用。 #### 3.1 生成大纲草案 `apiAiSyllabusGenerate` ```ts import { apiAiSyllabusGenerate, type AiSyllabusGenerateReq, type AiSyllabusGenerateResp, } from "@/lib/api"; const req: AiSyllabusGenerateReq = { requestId: "req_cw_101", context: { courseName: "IST 345 Building Generative AI Application", learningOutcome: "Understand LLMs and build a RAG application", studentLevel: "BEGINNER", teachingFocus: "PRACTICE_ORIENTED", courseLength: 4, }, }; const resp: AiSyllabusGenerateResp = await apiAiSyllabusGenerate(req); // resp.data.syllabus -> Week 级别数组 // resp.meta -> 模型与性能信息 ``` #### 3.2 生成单个模块的教学流程 `apiAiFlowGenerate` ```ts import { apiAiFlowGenerate, type AiFlowGenerateReq, type AiFlowGenerateResp, } from "@/lib/api"; const req: AiFlowGenerateReq = { requestId: "req_cw_102", moduleContext: { title: "Introduction to Generative AI", learningObjectives: ["Understand basic LLM concepts"], topics: ["History of AI", "Transformer Architecture"], durationMinutes: 90, }, systemPrompts: ["(可选) 来自 Improve 阶段的长期提示"], }; const resp: AiFlowGenerateResp = await apiAiFlowGenerate(req); // resp.data.steps -> 每个 step 含 type/title/estimated_duration/ai_understanding ``` #### 3.3 局部重构教学流程 `apiAiFlowRegeneratePartial` ```ts import { apiAiFlowRegeneratePartial, type AiFlowPartialReq, type AiFlowPartialResp, } from "@/lib/api"; const req: AiFlowPartialReq = { requestId: "req_cw_103", prompt: "Split the 30-min explanation into two shorter parts with a quiz in between.", currentFlow: { lockedSteps: [{ id: "step_1", title: "Welcome", duration: 15 }], unlockedSteps: [{ id: "step_2", title: "Heavy Explanation", duration: 30 }], }, }; const resp: AiFlowPartialResp = await apiAiFlowRegeneratePartial(req); // resp.data.explanation -> Copilot 气泡文案 // resp.data.proposedSteps -> 用于替换 unlockedSteps 的新步骤 ``` #### 3.4 教案长文 `apiAiPlanDetailGenerate` ```ts import { apiAiPlanDetailGenerate, type AiPlanDetailReq, type AiPlanDetailResp, } from "@/lib/api"; const req: AiPlanDetailReq = { requestId: "req_cw_104", finalizedSteps: stepsArray, // 来自 Flow 阶段确定的完整 steps }; const resp: AiPlanDetailResp = await apiAiPlanDetailGenerate(req); // resp.data.sections -> 多个 section(Lesson Objectives / Content 等),content 支持 Markdown ``` #### 3.5 反思看板 `apiAiReflectionGenerate` ```ts import { apiAiReflectionGenerate, type AiReflectionReq, type AiReflectionResp, } from "@/lib/api"; const req: AiReflectionReq = { requestId: "req_cw_105", teachAnnotations: [ { category: "NEEDS_MORE_TIME", selectedText: "Gradient Descent", feedback: "Students were confused by the math", }, ], quizAggregations: { averageScore: 72, lowestTopic: "Matrix Operations", }, }; const resp: AiReflectionResp = await apiAiReflectionGenerate(req); // resp.data.understanding / engagement / difficulty / misconceptions / nextLessonSuggestions ``` #### 3.6 改进提案 `apiAiImprovementGenerate` ```ts import { apiAiImprovementGenerate, type AiImprovementReq, type AiImprovementResp, } from "@/lib/api"; const req: AiImprovementReq = { requestId: "req_cw_106", reflectionReports: previousReflectionReports, // 来自 2.5 的历史数据数组 }; const resp: AiImprovementResp = await apiAiImprovementGenerate(req); // resp.data.proposals -> 每条包含 title/priority/affectedWeeks/evidence/rootCause/proposedSolution/expectedImpact ``` --- ### 4. 后端如何配置 OpenAI 模型(固定为 gpt‑4o) 后端 `api/config.py` 使用环境变量 `CLARE_DEFAULT_MODEL` 控制默认模型: ```python DEFAULT_MODEL = (os.getenv("CLARE_DEFAULT_MODEL") or "gpt-4.1-mini").strip() ``` 在 Hugging Face Space(或其他部署环境)中: - 打开 **Settings → Variables and secrets** - 设置: ```text CLARE_DEFAULT_MODEL = gpt-4o ``` 这样,上述所有 `/ai/courseware/...` 接口默认都会使用 `gpt-4o`,同时 `meta.model` 字段会反映真实模型名称,便于前端或监控系统做统计。 --- ### 5. 错误处理约定 - 若 OpenAI 调用失败:后端返回 `500`,`detail` 内含错误信息。 - 若 LLM 返回的内容不是合法 JSON 或缺少关键字段: - 返回 `422 INVALID_GENERATION`,`detail` 会说明缺失的字段或解析失败原因。 - 前端封装函数(`apiAi*` 系列)若收到非 2xx,会抛出 `Error`,错误信息来源: - `data.error` / `data.detail` / `data.message` / 自定义 fallback。 前端在捕获异常时可以统一提示“AI 生成失败,请稍后重试”,并记录 `requestId` 以便后端排查。