22 KiB
AI 模块审计报告 V3 — 架构解耦与全角色对标
审计范围:基于 V1(
ai-module-audit-report.md)与 V2(ai-module-audit-report-v2.md)已完成实现,进行第三轮深度架构审计。 审计日期:2026-06-24 审计方法:全文件逐行扫描 + 三层架构合规性矩阵 + 跨模块依赖图 + K12 行业标杆对标(Khanmigo / Duolingo Max / Squirrel AI / Century Tech / MagicSchool AI) 审计依据:docs/standards/coding-standards.md、docs/architecture/004_architecture_impact_map.md、docs/architecture/005_architecture_data.json、项目规则
一、现有实现概要
1.1 文件分布(30 个文件)
| 层 | 文件 | 行数 | 职责 |
|---|---|---|---|
| types | modules/ai/types.ts |
295 | AiService/AiClientService 接口 + 8 个业务场景类型 |
| schema | modules/ai/schema.ts |
227 | Zod 验证(8 输入 + 8 输出) |
| actions | modules/ai/actions.ts |
381 | 9 个 Server Actions(含权限校验) |
| data-access | modules/ai/data-access.ts |
138 | AI 事件内存存储 + 统计聚合 |
| services | modules/ai/services/ai-service.ts |
439 | DefaultAiService 实现(8 方法) |
| services | modules/ai/services/prompt-templates.ts |
277 | 10 个系统提示词模板 |
| services | modules/ai/services/usage-tracker.ts |
99 | AI 使用量埋点 |
| services | modules/ai/services/content-safety.ts |
291 | 内容安全过滤(输入/输出/配额/Socratic) |
| context | modules/ai/context/ai-client-provider.tsx |
62 | React Context Provider + Hooks |
| hooks | modules/ai/hooks/use-ai-chat-stream.ts |
155 | 流式 AI 对话 Hook |
| hooks | modules/ai/hooks/use-ai-chat.ts |
57 | 非流式 AI 对话 Hook |
| hooks | modules/ai/hooks/use-ai-suggestion.ts |
72 | AI 建议 Hook |
| hooks | modules/ai/hooks/use-floating-ball.ts |
243 | 悬浮球拖拽 Hook |
| hooks | modules/ai/hooks/stream-utils.ts |
135 | SSE 流解析工具 |
| components | modules/ai/components/ai-chat-panel.tsx |
417 | AI 对话面板 |
| components | modules/ai/components/ai-assistant-widget.tsx |
329 | 全局 AI 助手悬浮球 |
| components | modules/ai/components/ai-markdown-renderer.tsx |
143 | Markdown 渲染器 |
| components | modules/ai/components/ai-chart-renderer.tsx |
329 | 图表渲染器 |
| components | modules/ai/components/ai-error-boundary.tsx |
88 | AI 错误边界 |
| components | modules/ai/components/ai-skeleton.tsx |
47 | 骨架屏 |
| components | modules/ai/components/ai-provider-selector.tsx |
89 | 服务商选择器 |
| components | modules/ai/components/ai-grading-assist.tsx |
173 | AI 批改辅助 |
| components | modules/ai/components/ai-error-book-analysis.tsx |
246 | 错题本 AI 分析 |
| components | modules/ai/components/ai-lesson-content-generator.tsx |
180 | 备课内容生成器 |
| components | modules/ai/components/ai-question-variant-generator.tsx |
218 | 题目变体生成器 |
| components | modules/ai/components/ai-child-summary.tsx |
186 | 家长学情摘要 |
| components | modules/ai/components/ai-usage-dashboard.tsx |
221 | 管理员使用统计 |
| components | modules/ai/components/ai-study-path.tsx |
200 | 学生学习路径 |
| components | modules/ai/components/ai-suggestion-card.tsx |
164 | 相似题建议卡片 |
| api | app/api/ai/chat/route.ts |
48 | 非流式聊天端点 |
| api | app/api/ai/chat/stream/route.ts |
237 | SSE 流式端点 |
1.2 数据流
客户端组件
└─▶ useAiClient() / useAiClientOptional()
└─▶ AiClientProvider (app/layout.tsx 或子页面注入)
└─▶ Server Actions (modules/ai/actions.ts)
└─▶ createAiService(userId) → DefaultAiService
└─▶ createAiChatCompletion (shared/lib/ai)
└─▶ OpenAI SDK + ai_providers 表
SSE 流式端点(独立路径):
app/api/ai/chat/stream/route.ts
└─▶ requirePermission(AI_CHAT)
└─▶ content-safety (filterUserInput / tryConsumeDailyQuota)
└─▶ createAiChatCompletionStream (shared/lib/ai)
└─▶ content-safety (filterAiOutput / validateSocraticOutput)
1.3 架构图记录情况
004_architecture_impact_map.md第 2.29 节完整记录了 AI 模块(V2/V3/V4 变更)005_architecture_data.json包含modules.ai节点(exports/dependencies/integrations/safety/streaming/i18n)- 结论:架构图对 AI 模块的记录基本完整,但未记录跨模块违规依赖(见 2.1.1)。
二、现存问题与原因分析
2.1 架构分层问题
问题 2.1.1:5 处跨模块直接依赖 shared/lib/ai(绕过 modules/ai)
- 位置:
- ai-suggest.ts:5 —
import { createAiChatCompletion } from "@/shared/lib/ai" - settings/actions.ts:14 —
import { encryptAiApiKey, getAiErrorMessage, testAiProviderById, testAiProviderConfig } from "@/shared/lib/ai" - exams/actions.ts:987 — 动态
import("@/shared/lib/ai") - exams/ai-pipeline/request.ts:11 —
import { createAiChatCompletion, getAiErrorMessage } from "@/shared/lib/ai" - exams/ai-pipeline/parse.ts:11 —
import { createAiChatCompletion } from "@/shared/lib/ai"
- ai-suggest.ts:5 —
- 原因:AI 模块在 V2 重构后才形成独立模块,但这些历史调用点未同步迁移。
- 后果:绕过
modules/ai的内容安全过滤、每日配额、Socratic 模式、使用量埋点等保护机制;AI 调用无法统一治理。 - 违反规则:
项目规则 → 架构分层规则 → 模块间只能通过对方 data-access 通信;项目规则 → Server Action 规范 → 每个 Action 必须调用 requirePermission()。
问题 2.1.2:非流式聊天端点绕过 modules/ai
- 位置:app/api/ai/chat/route.ts
- 现状:直接调用
shared/lib/ai的createAiChatCompletion,未走aiChatAction,缺失内容安全过滤、每日配额、Socratic 模式等保护。 - 后果:与非流式端点(
/api/ai/chat/stream)形成安全策略不一致;学生可通过非流式端点绕过 Socratic 模式获取直接答案。 - 违反规则:
项目规则 → 安全规范;项目规则 → Server Action 规范。
问题 2.1.3:4 个子页面重复创建 AiClientService
- 位置:
- 现状:每个页面各自创建只含 6 个 Action 的
AiClientService,覆盖 layout.tsx 的全局 Provider(含 9 个 Action)。 - 后果:代码重复;
generateChildSummary、recommendStudyPath、getAiUsageStats在这些页面内为undefined,若未来组件调用将运行时错误。 - 违反规则:
项目规则 → 工程约定 → 最大化复用。
2.2 权限问题
问题 2.2.1:非流式聊天端点未走 requirePermission 体系
- 位置:app/api/ai/chat/route.ts
- 现状:虽然调用了
requirePermission(Permissions.AI_CHAT),但绕过了modules/ai/actions.ts的aiChatAction,导致内容安全过滤、每日配额、Socratic 模式等保护机制缺失。 - 后果:权限校验通过但安全策略不一致。
- 违反规则:
项目规则 → Server Action 规范 → 每个 Action 必须调用 requirePermission()(虽调用但绕过 Action 编排层)。
2.3 国际化问题
问题 2.3.1:ai-chart-renderer.tsx 硬编码中文
- 位置:ai-chart-renderer.tsx:147
- 代码:
图表数据格式错误,无法渲染 - 后果:无法切换语言。
- 违反规则:
项目规则 → 所有用户可见文本必须适配 i18n。
问题 2.3.2:ai-assistant-widget.tsx systemPrompt 硬编码英文
- 位置:ai-assistant-widget.tsx:230-326
- 现状:
inferContextFromPath函数中所有systemPrompt和contextMessage为硬编码英文。 - 判定:systemPrompt 是发送给 AI 的指令(非用户可见文本),可保留英文(模型兼容性最佳);但
contextMessage显示在 UI 中,应 i18n 化。 - 后果:contextMessage 无法国际化。
- 违反规则:
项目规则 → 所有用户可见文本必须适配 i18n。
2.4 类型安全问题
问题 2.4.1:ai-markdown-renderer.tsx 使用 as 断言
- 位置:ai-markdown-renderer.tsx:92
- 代码:
lang.slice(CHART_LANG_PREFIX.length) as AiChartType - 后果:若 lang 不在 AiChartType 枚举内,类型不安全。
- 违反规则:
项目规则 → TypeScript 规则 → 禁止 as 断言。
问题 2.4.2:ai-provider-selector.tsx 使用 as 断言
- 位置:ai-provider-selector.tsx:66
- 代码:
field.value as string - 后果:react-hook-form 的 field.value 类型应为泛型,此处强转。
- 违反规则:
项目规则 → TypeScript 规则 → 禁止 as 断言。
问题 2.4.3:ai-chart-renderer.tsx 使用 as 断言
- 位置:ai-chart-renderer.tsx:117
- 代码:
JSON.parse(data) as AiChartSpec - 后果:JSON 结构不可信,直接断言可能运行时错误。
- 违反规则:
项目规则 → TypeScript 规则 → 禁止 as 断言。
2.5 错误处理问题
问题 2.5.1:ai-suggestion-card.tsx 未包裹 Error Boundary
- 位置:ai-suggestion-card.tsx
- 现状:组件内部有 try/catch 处理异步错误,但未用
AiErrorBoundary包裹渲染期错误。 - 后果:若
result.data结构异常或questions.map渲染时抛错,整页崩溃。 - 违反规则:
审计要求 → 每个独立数据区块必须用 React Error Boundary 包裹。
问题 2.5.2:非流式聊天端点错误处理不完整
- 位置:app/api/ai/chat/route.ts
- 现状:
getStatusFromError基于错误消息字符串匹配状态码,脆弱且不可靠。 - 后果:错误分类不准确。
- 违反规则:
项目规则 → 错误处理。
2.6 文件大小问题
问题 2.6.1:use-floating-ball.ts 超出 Hook 行数限制
- 位置:use-floating-ball.ts
- 现状:243 行,超出 Hook 文件 80 行建议上限 163 行。
- 后果:职责过多(位置加载/保存、拖拽事件、边缘吸附、半隐藏),难以维护和测试。
- 违反规则:
项目规则 → 单文件行数 → 自定义 Hook:建议 ≤ 80 行。
2.7 可复用性问题
问题 2.7.1:4 个子页面重复创建 AiClientService
- 见问题 2.1.3。
问题 2.7.2:ai-suggestion-card.tsx 未被使用
- 位置:ai-suggestion-card.tsx
- 现状:组件已实现但无任何引用。
- 后果:死代码,维护负担。
- 违反规则:
审计要求 → 最大化复用(应集成到错题本等页面)。
2.8 监控问题
问题 2.8.1:非流式聊天端点无使用量埋点
- 位置:app/api/ai/chat/route.ts
- 现状:未调用
trackAiUsage,调用数据不入统计。 - 后果:管理员仪表盘数据不完整。
- 违反规则:
审计要求 → 监控。
三、行业差距对比
3.1 与 Khanmigo(Khan Academy)的差距
| 功能 | Khanmigo | 本项目 | 差距 |
|---|---|---|---|
| 学生 Socratic 模式 | ✅ 强制引导式 | ✅ 已实现 | 无 |
| 教师备课助手 | ✅ 课程计划生成 | ✅ 已实现 | 无 |
| 多语言支持 | ✅ 20+ 语言 | ⚠️ 仅中英文 | 缺少多语言 Prompt |
| 学生情绪识别 | ✅ 检测挫败感 | ❌ 未实现 | 缺少情绪分析 |
| 家长沟通建议 | ✅ 家庭教育指导 | ✅ 已实现 | 无 |
3.2 与 Duolingo Max 的差距
| 功能 | Duolingo Max | 本项目 | 差距 |
|---|---|---|---|
| 解释我的答案 | ✅ AI 解释错误原因 | ❌ 未实现 | 缺少错题 AI 解释 |
| 角色扮演练习 | ✅ 情景对话练习 | ❌ 未实现 | 缺少口语/情景练习 |
| 个性化复习 | ✅ 基于遗忘曲线 | ⚠️ 仅 SM2 算法 | AI 未参与复习规划 |
3.3 与 Squirrel AI 的差距
| 功能 | Squirrel AI | 本项目 | 差距 |
|---|---|---|---|
| 纳米级知识图谱 | ✅ 10000+ 知识点 | ⚠️ V3 已集成 | 知识图谱粒度较粗 |
| 自适应学习路径 | ✅ 实时调整 | ✅ V3 已实现 | 无 |
| 多模态学习 | ✅ 视频+图文+音频 | ❌ 仅文本 | 缺少多模态 |
| 学习风格识别 | ✅ VARK 模型 | ❌ 未实现 | 缺少学习风格分析 |
3.4 与 MagicSchool AI 的差距
| 功能 | MagicSchool AI | 本项目 | 差距 |
|---|---|---|---|
| 50+ AI 工具 | ✅ 丰富工具集 | ⚠️ 8 个能力 | 工具数量不足 |
| IEP 生成 | ✅ 特殊教育计划 | ❌ 未实现 | 缺少 IEP |
| 家校沟通模板 | ✅ 邮件/通知模板 | ❌ 未实现 | 缺少沟通模板 |
| 跨学科项目设计 | ✅ PBL 项目设计 | ❌ 未实现 | 缺少 PBL |
3.5 关键差距总结
- AI 能力数量不足:仅 8 个能力,行业平均 15-20 个
- 多模态缺失:仅支持文本,缺少图像/语音/视频输入
- 学习风格识别缺失:未识别学生 VARK 学习风格
- 情绪识别缺失:未检测学生挫败感/兴奋度
- IEP/PBL 缺失:未支持特殊教育和项目式学习
- 跨模块数据联动不足:AI 未与考勤、行为、心理等数据联动分析
四、改进优先级建议
P0(紧急 — 安全/架构合规)
| 编号 | 问题 | 改进方向 |
|---|---|---|
| P0-1 | 5 处跨模块直接依赖 shared/lib/ai | 迁移至通过 modules/ai 的 data-access 或 actions 调用 |
| P0-2 | 非流式聊天端点绕过 modules/ai | 重构为调用 aiChatAction 或迁移安全策略 |
| P0-3 | ai-chart-renderer.tsx 硬编码中文 | 迁移至 i18n |
| P0-4 | 3 处 as 断言 | 改用类型守卫函数 |
P1(重要 — 规范/复用)
| 编号 | 问题 | 改进方向 |
|---|---|---|
| P1-1 | 4 个子页面重复创建 AiClientService | 提取 createAiClientService 工厂函数 |
| P1-2 | use-floating-ball.ts 超出行数限制 | 拆分为 use-drag-position + use-edge-snap |
| P1-3 | ai-suggestion-card.tsx 未包裹 Error Boundary | 集成时用 AiErrorBoundary 包裹 |
| P1-4 | ai-assistant-widget.tsx contextMessage 硬编码 | 迁移至 i18n |
| P1-5 | 非流式端点无使用量埋点 | 集成 trackAiUsage |
P2(增强 — 行业对标)
| 编号 | 问题 | 改进方向 |
|---|---|---|
| P2-1 | 缺少错题 AI 解释 | 新增 explainErrorAction |
| P2-2 | 缺少学习风格识别 | 新增 VARK 评估 |
| P2-3 | 缺少 IEP 生成 | 新增特殊教育模块 |
| P2-4 | 缺少家校沟通模板 | 新增沟通模板生成 |
| P2-5 | 缺少多模态输入 | 支持图像/语音输入 |
| P2-6 | 缺少情绪识别 | 集成情绪分析 API |
五、架构图同步说明
5.1 需补充的节点
- 跨模块违规依赖:在
005_architecture_data.json的dependencyMatrix中标注lesson-preparation、settings、exams对shared/lib/ai的违规依赖(应改为通过modules/ai)。 - 非流式端点安全策略缺失:在
004_architecture_impact_map.md的 AI 模块安全机制章节补充非流式端点的安全策略差距。 - ai-suggestion-card.tsx 未使用:在文件清单中标注该组件为"已实现未集成"。
5.2 需修改的节点
- V4 超时优化:已在 V4 中记录(
shared/lib/ai/client.ts按场景分离超时)。 - V4 规范修复:已在 V4 中记录(ai-service.ts 消除 as 断言、actions.ts 消除非空断言、ai-assistant-widget.tsx i18n 修复)。
六、实施记录
6.1 P0 改进实施
P0-1:迁移跨模块依赖(部分)
已实施:
- 修复
ai-chart-renderer.tsx硬编码中文(P0-3) - 修复
ai-markdown-renderer.tsxas 断言(P0-4 部分) - 修复
ai-provider-selector.tsxas 断言(P0-4 部分) - 修复
ai-chart-renderer.tsxas 断言(P0-4 部分)
未实施(需中长期计划):
- 5 处跨模块直接依赖 shared/lib/ai 的迁移(涉及 exams/lesson-preparation/settings 三个模块的重构,影响范围大,需单独排期)
P0-2:非流式聊天端点安全策略重构(已实施)
实施:重构 app/api/ai/chat/route.ts,与流式端点 /api/ai/chat/stream 安全策略完全对齐:
- Zod 校验输入(
AiChatInputSchema,限制消息数 50/长度 8000) tryConsumeDailyQuota原子化每日限额(防 TOCTOU 竞态)filterUserInput输入安全过滤filterAiOutput输出安全过滤- 学生侧 Socratic 模式(服务端强制
SOCRATIC_TUTOR_SYSTEM_PROMPT,忽略客户端 systemPrompt) validateSocraticOutput苏格拉底式输出校验- 过滤/失败时
refundDailyQuota(不惩罚用户) trackEvent使用量埋点(成功/失败均记录)
P0-3:ai-chart-renderer.tsx 硬编码中文(已实施)
实施:添加 i18n 键 ai.chart.parseError,替换硬编码中文。
P0-4:as 断言修复(已实施)
实施:
ai-markdown-renderer.tsx:改用类型守卫函数isAiChartTypeai-provider-selector.tsx:改用String(field.value ?? "")ai-chart-renderer.tsx:改用 Zod schema 校验
6.2 P1 改进实施
P1-1:提取 createAiClientService 工厂(已实施)
实施:新建 modules/ai/context/create-ai-client-service.ts,导出 createFullAiClientService(含全部 9 个 Action)和 createCoreAiClientService(仅 6 个常用 Action)两个工厂函数。app/(dashboard)/layout.tsx 使用前者,4 个子页面(error-book、lesson-plans、homework、exams)使用后者,消除重复代码。
P1-2:拆分 use-floating-ball.ts(已实施)
实施:将 243 行的 use-floating-ball.ts 拆分为 3 个文件:
use-position-persistence.ts:Position 类型、常量、clamp/load/save 纯函数、位置状态 Hook(localStorage + resize 校正)use-drag-position.ts:拖拽状态 + pointer 事件处理 Hook(通过回调委托业务逻辑)use-floating-ball.ts:主组合 Hook(边缘吸附 + 半隐藏 + hovered 状态 + show/resetPosition)
P1-3:ai-suggestion-card.tsx Error Boundary(已实施)
实施:将原组件重命名为 AiSuggestionCardInner,新建 AiSuggestionCard 包装器用 AiErrorBoundary 包裹内部组件,保持公开 API 不变。
P1-4:ai-assistant-widget.tsx contextMessage i18n(已实施)
实施:在 en/ai.json 和 zh-CN/ai.json 中添加 chat.contextMessage.* 翻译键(7 个场景:teacherGrading/teacherLesson/teacherExam/studentErrorBook/studentHomework/parent/admin),替换 inferContextFromPath 中 7 处硬编码英文。
P1-5:非流式端点使用量埋点(已实施)
实施:在 app/api/ai/chat/route.ts 中集成 trackEvent(事件名 ai.chat),成功时记录 durationMs/tokenCount,失败时记录 errorMessage/durationMs。与流式端点(ai.chat_stream)对齐。
6.3 P2 改进(中长期计划)
P2-1:错题 AI 解释(已实施)
实施:
- 新增
ExplainErrorInput/ExplainErrorResult类型(modules/ai/types.ts) - 新增
ExplainErrorInputSchema/ExplainErrorResultSchemaZod 校验(modules/ai/schema.ts) - 新增
EXPLAIN_ERROR_SYSTEM_PROMPT提示词(modules/ai/services/prompt-templates.ts) - 新增
explainError服务方法(modules/ai/services/ai-service.ts) - 新增
explainErrorActionServer Action(modules/ai/actions.ts,权限:AI_CHAT + ERROR_BOOK_READ) - 更新
AiService/AiClientService接口,添加explainError方法 - 更新
createFullAiClientService工厂函数包含explainError - 更新
AiCapability类型添加"explain-error" - 更新
AiUsageEvent/AI_EVENT_MAP添加explain_error埋点 - 更新 i18n 翻译键
capability.explainError(en/zh-CN) - 更新架构文档 004/005
未实施(需后续排期):
- P2-2:VARK 学习风格评估(需新增评估模块 + DB 表)
- P2-3:IEP 特殊教育计划生成(需新增特殊教育模块)
- P2-4:家校沟通模板生成(需新增模板管理模块)
- P2-5:多模态输入支持(需接入图像/语音 API)
- P2-6:情绪识别(需接入情绪分析 API)