Files
NextEdu/docs/architecture/audit/ai-module-audit-report.md
SpecialX 21c5eba96c feat(ai): 新增 AI 模块并集成至备课/错题集/试卷/改题四大业务场景
- 新增 src/modules/ai 独立模块,遵循三层架构(actions → services → shared/lib/ai)
- 通过 AiClientProvider + useAiClient 实现 React Context 依赖注入,业务组件零直接 import
- 6 个 Server Actions 均调用 requirePermission() 权限校验,返回 ActionState<T>
- withAiTracking 统一埋点,覆盖 chat/similar_question/grading_assist/lesson_content/question_variant/weakness_analysis
- 集成场景:作业批改 AiGradingAssist、错题集 AiErrorBookAnalysis、备课 AiLessonContentGenerator、试卷 AiQuestionVariantGenerator
- 全量 i18n(en/zh-CN ai.json),Error Boundary + Skeleton 边界处理
- 同步架构图 004/005,新增审计报告 ai-module-audit-report.md
2026-06-23 00:52:39 +08:00

22 KiB
Raw Permalink Blame History

AI 模块审计报告

审计范围:项目中所有与 AI人工智能相关的代码包括底层 SDK 封装、Provider 管理、各业务模块(备课、错题集、试卷、改题等)中的 AI 集成点。 审计日期2026-06-23 审计依据:docs/architecture/004_architecture_impact_map.mddocs/architecture/005_architecture_data.jsondocs/standards/coding-standards.md


一、现有实现概要

1.1 文件分布

AI 相关代码当前未形成独立模块,而是分散在 5 个不同位置:

位置 文件 行数 职责
src/shared/lib/ai/ api-key-crypto.ts 28 AES-256-GCM 加密 API Key
src/shared/lib/ai/ client.ts 58 OpenAI SDK 封装,创建 chat completion
src/shared/lib/ai/ errors.ts 8 错误消息格式化
src/shared/lib/ai/ payload-parser.ts 78 请求负载解析与 Zod 守卫
src/shared/lib/ai/ provider-config.ts 61 ai_providers 表查询 Provider 配置
src/shared/lib/ai/ index.ts 5 聚合导出
src/shared/lib/ai.ts 9 向后兼容重导出
src/app/api/ai/chat/ route.ts 42 AI 聊天 REST API 端点
src/modules/exams/ai-pipeline/ parse.ts 426 Zod schema、JSON 提取修复、提示词
src/modules/exams/ai-pipeline/ request.ts 306 AI 请求构造与发送
src/modules/exams/ai-pipeline/ structure.ts 209 结构生成与预览/草稿转换
src/modules/exams/ai-pipeline/ index.ts 172 高层编排
src/modules/lesson-preparation/ actions-ai.ts 44 知识点推荐 Server Action
src/modules/lesson-preparation/ ai-suggest.ts 65 知识点推荐 AI 逻辑
src/modules/settings/ actions.ts(部分) ~183 AI Provider CRUD Action
src/modules/settings/ data-access.ts(部分) ai_providers 表查询
src/modules/exams/components/ exam-ai-generator.tsx 224 AI 出题 UI 组件

1.2 数据流

前端组件 (exam-ai-generator.tsx)
  └─▶ Server Action (exams/actions.ts: createAiExamAction)
        └─▶ ai-pipeline.generateAiCreateDraftFromSource()
              ├─▶ requestAiExamStructureDraft()  → createAiChatCompletion()
              │                                    └─▶ OpenAI SDK + db.query.aiProviders
              └─▶ parseQuestionDetail()           → createAiChatCompletion()

前端组件 (lesson-preparation hooks)
  └─▶ suggestKnowledgePointsAction()
        └─▶ ai-suggest.suggestKnowledgePoints()
              ├─▶ textbooks/data-access.getKnowledgePointsByTextbookId()  [跨模块]
              └─▶ createAiChatCompletion()

前端组件 (settings)
  └─▶ upsertAiProviderAction() / testAiProviderAction()
        └─▶ settings/data-access (ai_providers 表)

1.3 架构图记录情况

  • 005_architecture_data.jsonmodules 节点未将 AI 列为独立模块
  • 仅在 dbTables.aiProviders 中记录 usedBy: ["settings", "ai"],但 ai 并非真实存在的模块。
  • shared 模块下记录了 lib/ai/* 工具函数(createAiChatCompletionparseAiChatPayload 等)。
  • exams 模块下记录了 ai-pipeline 子目录的导出函数。
  • lessonPreparation 模块下记录了 suggestKnowledgePointsAction
  • 结论:架构图对 AI 模块的记录不完整,未反映 AI 作为横切关注点的全貌,也未记录 app/api/ai/chat/route.ts 端点。

1.4 权限点

权限常量 用途
AI_CHAT ai:chat 使用 AI 聊天
AI_CONFIGURE ai:configure 配置 AI Provider
EXAM_AI_GENERATE exam:ai_generate AI 出题

二、现存问题与原因分析

2.1 架构分层问题

问题 2.1.1AI 未形成独立模块,逻辑分散在 5 处

  • 位置shared/lib/ai/app/api/ai/chat/modules/exams/ai-pipeline/modules/lesson-preparation/ai-suggest.tsmodules/settings/
  • 原因AI 能力是按业务需求逐步添加的,每次新增场景都在调用方就地实现,未抽象为独立模块。
  • 后果AI 逻辑无法统一治理限流、监控、成本控制、Prompt 版本管理);新增 AI 场景需要重复编写请求构造与错误处理;测试时无法 Mock AI 层。
  • 违反规则项目规则 → 架构分层规则 → 模块标准结构AI 应作为 modules/ai/ 独立模块存在)。

问题 2.1.2AI 聊天使用 REST API 路由而非 Server Action

  • 位置route.ts
  • 原因:早期实现选择了 REST 路由,未遵循项目 Server Action 统一规范。
  • 后果:与项目其他数据操作风格不一致;无法复用 ActionState<T> 返回类型与 useActionMutation Hook权限校验绕过了 requirePermission() 体系。
  • 违反规则项目规则 → Server Action 规范(所有数据操作应通过 Server Action返回 ActionState<T>)。

问题 2.1.3lesson-preparation/ai-suggest.ts 跨模块直接依赖

  • 位置ai-suggest.ts
  • 现状:直接 import { getKnowledgePointsByTextbookId, getKnowledgePointsByChapterId } from "@/modules/textbooks/data-access"
  • 判定:模块间通过对方 data-access 通信符合规则,但 AI 推荐逻辑本身应属于 AI 模块,而非备课模块。当前 ai-suggest.ts 混合了"AI 调用"与"知识点候选获取"两个职责。
  • 后果:若其他模块也需要"基于文本推荐知识点",无法复用。
  • 违反规则项目规则 → 架构分层规则(职责划分不清)。

2.2 权限问题

问题 2.2.1AI 聊天端点缺少 requirePermission() 校验

  • 位置route.ts:15-18
  • 现状:仅检查 session?.user?.id 是否存在,未调用 requirePermission(Permissions.AI_CHAT)
  • 后果:任何已登录用户(包括学生)都能无限制调用 AI 聊天,绕过了角色权限体系;无法按角色限制 AI 使用场景。
  • 违反规则项目规则 → Server Action 规范 → 每个 Action 必须调用 requirePermission()项目规则 → 安全规范

问题 2.2.2AI 出题管线内部无权限二次校验

  • 位置exams/ai-pipeline/index.tsgenerateAiCreateDraftFromSource
  • 现状:依赖调用方 Action 校验权限,管线本身不校验。
  • 后果:若未来有新调用方忘记校验,将导致越权调用 AI。
  • 违反规则项目规则 → 安全规范 → Server Action 二次校验

2.3 国际化问题

问题 2.3.1exam-ai-generator.tsx 大量硬编码文本

  • 位置exam-ai-generator.tsx
  • 硬编码中文:第 118 行"新建配置"、第 164 行"加入后台队列(运行 ${...}/3排队 ${...}"、第 167 行"立即预览"/"Generating..."、第 192 行"后台生成记录"、第 202-207 行"排队中"/"生成中"/"已完成"/"失败:..."、第 211 行"打开预览"。
  • 硬编码英文:第 92 行"AI Generation"、第 93-95 行描述、第 104 行"AI Provider"、第 122-124 行对话框标题、第 144 行"Loading providers..."/"Select provider"、第 156 行描述、第 175 行"Source Exam Text"、第 178 行 placeholder、第 184 行描述。
  • 后果:无法切换语言;违反 i18n 就绪要求。
  • 违反规则项目规则 → 所有用户可见文本必须适配 i18n

问题 2.3.2AI 管线内部硬编码中文错误消息

  • 位置request.ts:152 "请先粘贴试卷文本"、第 172 行"试卷文本校验失败,请重试"、第 177 行"识别为乱码或混乱文本..."。
  • 后果:错误消息无法国际化。
  • 违反规则项目规则 → i18n

问题 2.3.3:无独立 ai.json 翻译文件

  • 现状AI 相关翻译散落在 settings.jsonProvider 管理)和 lesson-preparation.jsonerror.aiSuggest),无统一命名空间。
  • 后果AI 文本难以维护与查找。

2.4 类型安全问题

问题 2.4.1ai-suggest.ts 使用 as 断言

  • 位置ai-suggest.ts:54
  • 代码JSON.parse(jsonMatch[0]) as { id: string; name: string; reason: string }[]
  • 后果AI 返回的 JSON 结构不可信,直接断言可能导致运行时错误。
  • 违反规则项目规则 → TypeScript 规则 → 禁止 as 断言

问题 2.4.2actions-ai.ts 双重断言

  • 位置actions-ai.ts:34
  • 代码parsed.data.doc as unknown as LessonPlanDocument
  • 后果:绕过类型系统,不安全。
  • 违反规则项目规则 → TypeScript 规则 → 禁止 as 断言

2.5 错误处理问题

问题 2.5.1ai-suggest.ts 静默吞掉错误

  • 位置ai-suggest.ts:50-64
  • 现状try { JSON.parse(...) } catch { return [] } — JSON 解析失败时静默返回空数组。
  • 后果:教师无法区分"AI 未推荐任何知识点"与"AI 返回格式错误";无法排查问题。
  • 违反规则项目规则 → 错误处理

问题 2.5.2:无 AI 专用 Error Boundary

  • 现状AI 组件(如 exam-ai-generator)未用 Error Boundary 包裹。
  • 后果AI 调用失败可能导致整个页面崩溃。
  • 违反规则:审计要求 → 每个独立数据区块必须用 React Error Boundary 包裹。

问题 2.5.3:无 Suspense/骨架屏

  • 现状AI 异步操作仅用 loading 布尔值切换按钮文字,无骨架屏。
  • 后果:用户体验差,无法感知加载进度。

2.6 可复用性问题

问题 2.6.1:无可复用 AI 组件

  • 现状
    • AI Provider 选择器硬编码在 exam-ai-generator.tsx 内部,无法在其他模块复用。
    • 无通用 AI 聊天面板组件。
    • 无通用 AI 建议加载器组件。
    • 无通用 AI 结果预览组件。
  • 后果:每个需要 AI 的模块都要从零实现 UI。
  • 违反规则:审计要求 → 最大化复用。

问题 2.6.2:无 AI 服务接口抽象

  • 现状:所有模块直接 import { createAiChatCompletion } from "@/shared/lib/ai"
  • 后果:无法 Mock AI 服务进行单测;无法切换 AI 实现(如本地 mock、不同 SDK
  • 违反规则:审计要求 → 完全解耦、可测试性。

2.7 功能缺失问题

问题 2.7.1:错题集无 AI 集成

  • 现状error-book 模块仅有 SM2 间隔复习算法,无 AI 能力。
  • 缺失功能
    • AI 相似题推荐(根据错题生成同类练习)
    • AI 薄弱点分析(根据错题分布分析学生薄弱知识点)
    • AI 解题思路生成(为错题生成分步骤解析)
    • AI 复习计划建议(基于错题掌握度智能调整复习节奏)
  • 后果:错题本仅是静态记录,无法发挥 AI 的个性化学习价值。

问题 2.7.2:改题(作业批改)无 AI 集成

  • 现状homework-grading-view.tsx 仅支持手动评分与自动判分(选择题),无 AI 辅助。
  • 缺失功能
    • AI 辅助批改主观题(简答题/论述题)
    • AI 生成评分反馈建议
    • AI 批改一致性校验(检测人工评分偏差)
  • 后果:教师批改主观题负担重,效率低。

问题 2.7.3:备课 AI 能力单一

  • 现状lesson-preparation 仅有"知识点推荐"一个 AI 功能。
  • 缺失功能
    • AI 生成教学活动设计
    • AI 生成课堂提问
    • AI 生成形成性评估
    • AI 生成差异化教学建议
  • 后果AI 价值未充分释放。

问题 2.7.4:试卷 AI 无题目变体与智能组卷

  • 现状exams/ai-pipeline 仅支持"从文本解析生成试卷"。
  • 缺失功能
    • AI 生成题目变体(基于已有题目生成同知识点不同表述的变体)
    • AI 智能组卷(根据知识点覆盖、难度分布自动组卷)
    • AI 难度分析(预测题目难度)
  • 后果AI 出题场景受限。

2.8 性能与监控问题

问题 2.8.1:无流式响应

  • 现状:所有 AI 调用等待完整响应才返回。
  • 后果:长文本生成时用户体验差(等待 10-30 秒)。
  • 违反规则:审计要求 → 性能:支持流式渲染。

问题 2.8.2:无 AI 使用监控

  • 现状:无 AI 调用埋点、无成本统计、无延迟监控、无错误率监控。
  • 后果:无法优化 AI 使用策略,无法发现异常调用。
  • 违反规则:审计要求 → 监控:预留关键操作埋点接口。

2.9 可访问性问题

问题 2.9.1AI 组件缺少 ARIA 属性

  • 位置exam-ai-generator.tsx 的后台任务列表无 aria-live,屏幕阅读器无法感知状态变化。
  • 违反规则:审计要求 → a11yARIA 属性。

三、行业差距对比

3.1 与优秀 K12 产品的差距

能力 行业主流做法 当前状态 差距影响
AI 助手入口 全局悬浮按钮/侧边栏,可从任何页面唤起 AI 助手 无全局入口,仅嵌入特定页面 用户无法在需要时随时获取 AI 帮助
上下文感知 AI 助手自动感知当前页面上下文(如正在批改的作业) 无上下文感知 AI 建议不精准,需用户手动输入上下文
流式输出 AI 回复逐字流式显示 等待完整响应 长文本等待体验差
错题 AI 推荐 根据错题自动生成同类练习题,支持"再练一题" 无此功能 学生无法针对性巩固薄弱点
AI 辅助批改 主观题 AI 预评分 + 教师确认 无此功能 教师批改负担重
学习路径推荐 AI 根据错题与掌握度生成个性化学习路径 无此功能 缺少个性化学习引导
AI 内容安全 学生侧 AI 输出经过内容过滤 无过滤机制 学生可能接触不当内容
AI 使用历史 用户可查看自己的 AI 对话历史 无此功能 无法回顾 AI 建议结果
多 Provider 对比 同一 Prompt 可对比不同模型输出 仅支持选择单一 Provider 无法评估最优模型
Prompt 版本管理 Prompt 模板可配置化、版本化 Prompt 硬编码在代码中 调整 Prompt 需改代码发版

3.2 多角色体验差距

角色 期望的 AI 能力 当前状态
教师 备课内容生成、出题辅助、批改辅助、学情分析 仅有知识点推荐 + 试卷解析
学生 错题相似题推荐、解题思路、学习路径 无任何 AI 能力
家长 子女学情 AI 摘要、辅导建议 无任何 AI 能力
管理员 AI 使用统计、成本监控 无任何 AI 能力

四、改进优先级建议

P0紧急影响安全与基础架构

编号 问题 改进方向
P0-1 AI 聊天端点缺少权限校验 改造为 Server Action添加 requirePermission(AI_CHAT)
P0-2 AI 未形成独立模块 创建 src/modules/ai/,将分散的 AI 逻辑统一收口
P0-3 exam-ai-generator.tsx 硬编码文本 提取 i18n 键,创建 ai.json 翻译文件
P0-4 AI 管线硬编码错误消息 通过 Server Action 层返回 i18n 错误键
P0-5 ai-suggest.ts 使用 as 断言 用 Zod schema 校验 AI 返回

P1重要影响功能完整性与可维护性

编号 问题 改进方向
P1-1 无 AI 服务接口抽象 定义 AiService 接口,通过 React Context 注入
P1-2 无可复用 AI 组件 抽象 AiChatPanelAiProviderSelectorAiSuggestionCardAiErrorBoundary
P1-3 无 AI Error Boundary 创建 AiErrorBoundary 包裹所有 AI 区块
P1-4 错题集无 AI 集成 新增相似题推荐、薄弱点分析 Server Action
P1-5 改题无 AI 集成 新增 AI 辅助批改 Action
P1-6 无 AI 使用监控 预留 trackAiUsage() 埋点接口
P1-7 备课 AI 能力单一 新增内容生成、活动建议 Action

P2优化提升体验与扩展性

编号 问题 改进方向
P2-1 无流式响应 支持 SSE 流式输出
P2-2 无 AI 对话历史 持久化用户 AI 对话记录
P2-3 Prompt 硬编码 抽取为可配置 Prompt 模板
P2-4 试卷 AI 无变体生成 新增题目变体生成 Action
P2-5 无多 Provider 对比 支持并行调用多 Provider 对比
P2-6 无内容安全过滤 学生侧 AI 输出添加内容过滤
P2-7 架构图未记录 AI 模块 同步更新 004/005 文档

五、架构图同步说明

本次审计发现架构图存在以下遗漏与不一致,需在实现后同步更新:

5.1 需新增的节点

文档 节点路径 内容
005_architecture_data.json modules.ai 新增 AI 模块定义path、description、exportsAiService 接口、Actions、组件
005_architecture_data.json modules.ai.exports.functions createAiChatActionsuggestSimilarQuestionsActionsuggestGradingActiongenerateLessonContentActiongenerateQuestionVariantAction
005_architecture_data.json modules.ai.exports.components AiChatPanelAiProviderSelectorAiSuggestionCardAiErrorBoundary
005_architecture_data.json modules.ai.exports.hooks useAiChatuseAiSuggestion
005_architecture_data.json dependencyMatrix.ai ai → shared、ai → settings(data-access)exams/lesson-preparation/error-book/homework → ai
004_architecture_impact_map.md 模块清单 新增"AI 模块"章节
004_architecture_impact_map.md 文件清单 新增 modules/ai/ 下所有文件

5.2 需修改的节点

文档 节点 修改内容
005_architecture_data.json dbTables.aiProviders.usedBy ["settings", "ai"] 改为 ["ai"]AI 模块收口后由 AI 模块负责)
005_architecture_data.json modules.shared.exports 标注 lib/ai/* 为"底层 SDK 封装,业务层应调用 modules/ai"
005_architecture_data.json modules.exams.ai-pipeline 标注依赖关系变更为"通过 ai 模块服务调用"
005_architecture_data.json routes 移除 app/api/ai/chat/route.ts(改造为 Server Action 后删除)
004_architecture_impact_map.md 调用链路图 更新 AI 调用链路:业务模块 → ai/actions → ai/services → shared/lib/ai

5.3 需删除的节点

文档 节点 原因
005_architecture_data.json routes./api/ai/chat 改造为 Server Action 后该 REST 路由删除

六、重构方案设计(概要)

详细实现见代码提交,此处仅列出设计要点。

6.1 模块结构

src/modules/ai/
├─ types.ts                  # AiService 接口、AiChatMessage、AiSuggestion 等类型
├─ schema.ts                 # Zod 校验chat、suggest、grading 等)
├─ data-access.ts            # ai_providers 表查询(从 settings 迁移)
├─ services/
│  ├─ ai-service.ts          # AiService 接口实现(封装 createAiChatCompletion
│  ├─ prompt-templates.ts    # 可配置 Prompt 模板
│  └─ usage-tracker.ts       # AI 使用埋点
├─ actions.ts                # Server Actionschat、suggestSimilar、suggestGrading、generateLessonContent
├─ context/
│  └─ ai-provider.tsx        # React Context + Provider依赖注入 AiService
├─ components/
│  ├─ ai-chat-panel.tsx      # 通用 AI 聊天面板(支持流式)
│  ├─ ai-provider-selector.tsx  # Provider 选择器(复用)
│  ├─ ai-suggestion-card.tsx    # 建议卡片
│  ├─ ai-error-boundary.tsx     # AI 专用 Error Boundary
│  └─ ai-skeleton.tsx           # AI 加载骨架屏
└─ hooks/
   ├─ use-ai-chat.ts         # AI 聊天 Hook
   └─ use-ai-suggestion.ts   # AI 建议 Hook

6.2 依赖注入

// types.ts
export interface AiService {
  chat(messages: AiChatMessage[], options?: AiChatOptions): Promise<AiChatResult>
  suggestSimilarQuestions(input: SimilarQuestionInput): Promise<SimilarQuestionResult[]>
  suggestGrading(input: GradingInput): Promise<GradingSuggestion>
  generateLessonContent(input: LessonContentInput): Promise<LessonContentResult>
}

// context/ai-provider.tsx
const AiContext = createContext<AiService | null>(null)
export function AiServiceProvider({ children, service }: { children: ReactNode; service: AiService }) { ... }
export function useAiService(): AiService { ... }

6.3 i18n 结构

// ai.json
{
  "chat": {
    "title": "AI Assistant",
    "placeholder": "Ask anything...",
    "sending": "Sending...",
    "error": "AI request failed"
  },
  "provider": {
    "selector": { "label": "AI Provider", "placeholder": "Select provider" },
    "manage": { "label": "Manage", "title": "AI Provider Settings" }
  },
  "suggestion": {
    "loading": "AI is thinking...",
    "empty": "No suggestions",
    "retry": "Retry"
  },
  "errorBook": {
    "similarQuestions": "Similar Questions",
    "weaknessAnalysis": "Weakness Analysis"
  },
  "grading": {
    "aiSuggest": "AI Grading Suggestion",
    "applyScore": "Apply Score",
    "applyFeedback": "Apply Feedback"
  },
  "lessonPrep": {
    "generateContent": "Generate Content",
    "generateActivity": "Suggest Activity"
  },
  "exam": {
    "generate": "Generate",
    "queue": "Add to Queue",
    "preview": "Preview"
  }
}

6.4 配置驱动

// 角色配置决定可用 AI 能力
const AI_CAPABILITY_CONFIG: Record<Role, AiCapability[]> = {
  admin: ["chat", "usage-stats"],
  teacher: ["chat", "exam-generate", "grading-assist", "lesson-content", "question-variant"],
  student: ["chat", "similar-question", "study-path"],
  parent: ["chat", "child-summary"],
}