# ai 工作排期

> 负责人：ai12
> 关联：[workline.md](../workline.md)、[coord.md](../coord.md)、[contracts/ai_contract.md](../contracts/ai_contract.md)、[objections/ai_issue.md](../objections/ai_issue.md)
> 模式：全并行（各 AI 一口气完成 P2-P6 全部代码，开发期间用 mock，最后统一集成测试）
> 阶段归属：批次 4（P5），见 [workline.md §1](../workline.md) 甘特图 `b4c: ai12 ai服务 gRPC 50058, after b3a, 13d`

---

## §1 总览

ai 是 D6 智能洞察领域的"生成子域"服务（Python/FastAPI，无状态），统一封装 LLM 调用（多 Provider 适配 + 故障切换 + 限流 + 成本控制），提供聊天 / 出题 / 表达优化 / 备课工作流四类 AI 能力。通过 gRPC 查询 content 知识点与 data-ana 学情，通过 Kafka 外发用量计费事件供 data-ana 落 ClickHouse。

**端口**：HTTP 3008 + gRPC 50058（[port-allocation.md](../../../../infra/port-allocation.md) §3/§5 权威源）

**P5 全阶段目标**（退出标准，对应 [pending-features P5](../../../architecture/roadmap/pending-features.md) + ai-allocation §5）：

1. LLM Provider 适配器模式（OpenAI/百川/Anthropic/本地 Ollama，统一接口 + 故障切换）
2. SSE / gRPC 流式响应（题目逐字生成 + 前端打字机效果）
3. 出题 Prompt 模板管理（YAML + Jinja2，模板 CRUD + 参数注入：年级/学科/难度/知识点）
4. 备课工作流 4 步编排（分析学情 → 推荐知识点 → 生成题目 → 教师审核 → 入库）
5. 用量计费 / 频率限制（按用户 / 按 IP / 按 token / 按学校配额）
6. 生成质量门禁（RuleValidator + LLMJudge，评估通过率 > 80%）
7. 安全层（PII 脱敏 + Prompt 注入防御 + 输出内容审核）

---

## §2 全阶段甘特图（P5，13 天）

> 对齐 [workline.md §1](../workline.md) 批次 4：`ai12 ai服务 gRPC 50058 :b4c, after b3a, 13d`（b3a = content P4 就绪后启动）

```mermaid
gantt
    title ai12 ai 服务 P5 排期（13 天）
    dateFormat YYYY-MM-DD
    axisFormat %m-%d

    section M14 基础架构（第1-4天）
    12.1 LLMProvider抽象+4适配器 :crit, a12a, 2026-07-10, 2d
    12.2 ProviderFailoverChain+CircuitBreaker :a12b, after a12a, 1d
    12.3 gRPC server(Chat+StreamChat)+ActionState整改 :crit, a12c, after a12a, 2d
    12.4 Redis多维度限流+Dockerfile多阶段 :a12d, after a12b, 1d

    section M15 出题核心（第5-9天）
    12.5 PromptTemplateService+Jinja2渲染 :crit, a12e, after a12c, 2d
    12.6 GenerateQuestion+StreamGenerateQuestion逐字流式 :crit, a12f, after a12e, 2d
    12.7 RuleValidator+LLMJudge+QualityGate评估三道防线 :a12g, after a12f, 1d
    12.8 UsageRecorder+KafkaProducer+QuotaEnforcer :a12h, after a12g, 1d
    12.9 PIIRedactor+InputSanitizer+OutputModerator安全层 :a12i, after a12g, 1d

    section M16 备课工作流（第10-13天）
    12.10 gRPC client(content/data-ana/iam)+interceptor :crit, a12j, after a12f, 1d
    12.11 LessonPreparationWorkflow 4步编排+状态机 :crit, a12k, after a12j, 2d
    12.12 WorkflowStateStore(Redis)+教师审核+content入库 :a12l, after a12k, 1d
    12.13 集成测试+契约测试+文档同步+arch:scan :a12m, after a12l, 1d
```

**关键路径**（红色 crit）：LLMProvider 抽象 → gRPC server → PromptTemplateService → GenerateQuestion → gRPC client → 备课工作流编排

---

## §3 详细任务

### M14 基础架构（第1-4天）

#### P5-12.1：LLMProvider 抽象 + 4 适配器

- **负责人**：ai12
- **依赖**：无（P5 起点）
- **交付物**：
  - `services/ai/src/ai/providers/base.py`（`LLMProvider` 抽象接口：chat / stream_chat / embed）
  - `services/ai/src/ai/providers/openai_provider.py`
  - `services/ai/src/ai/providers/anthropic_provider.py`
  - `services/ai/src/ai/providers/baichuan_provider.py`
  - `services/ai/src/ai/providers/local_ollama_provider.py`
  - 重构 `llm_client.py` 为基于抽象接口的调用
- **验收标准**：
  - 4 Provider 切换可用（通过 `llm_model_routing` 配置路由）
  - httpx 异步调用，不依赖 openai SDK
  - 单元测试覆盖 ≥ 80%（用 MockLLMProvider）
  - `ruff check src/` 零错误

#### P5-12.2：ProviderFailoverChain + CircuitBreaker

- **负责人**：ai12
- **依赖**：P5-12.1
- **交付物**：
  - `services/ai/src/ai/providers/failover.py`（按优先级尝试 Provider，失败自动切换）
  - `services/ai/src/ai/providers/circuit_breaker.py`（连续 3 次失败触发熔断 60s）
- **验收标准**：单 Provider 故障自动切下一个；熔断器状态正确（closed/open/half_open）

#### P5-12.3：gRPC server + ActionState 整改（P0 阻塞）

- **负责人**：ai12
- **依赖**：P5-12.1；**前置**：ISSUE-03（coord 升级 ai.proto 到 v1 完整版）
- **交付物**：
  - `services/ai/src/ai/grpc_server.py`（`grpc.aio` server，端口 50058）
  - 实现 `Chat` + `StreamChat` 两个 RPC（含流式）
  - `grpc.aio.ServerInterceptor` 透传 W3C traceparent
  - **ActionState 整改**（ISSUE-09）：所有 HTTP 端点 + gRPC RPC 返回值改为 `{success, data, error:{code,message,details,traceId}}`，删除顶层 `degraded` 字段
- **验收标准**：
  - teacher-bff 可调通 ai gRPC 50058 `Chat` / `StreamChat`（含流式）
  - HealthService.Check 返回 SERVING
  - 响应信封 004 §11.5 合规
  - `pnpm run arch:scan` 更新 arch.db

#### P5-12.4：Redis 多维度限流 + Dockerfile 多阶段

- **负责人**：ai12
- **依赖**：P5-12.2
- **交付物**：
  - `services/ai/src/ai/middleware/rate_limit.py`（Redis 令牌桶：user/IP/school 三维度）
  - `services/ai/Dockerfile`（多阶段构建，目标镜像 < 200MB）
- **验收标准**：限流命中准确（user 10/min、IP 30/min、school 100/min）；镜像 < 200MB

---

### M15 出题核心（第5-9天）

#### P5-12.5：PromptTemplateService + Jinja2 渲染

- **负责人**：ai12
- **依赖**：P5-12.3
- **交付物**：
  - `services/ai/src/ai/prompts/*.yaml`（5+ 模板：generate_question / optimize_expression / chat / lesson_plan 等）
  - `services/ai/src/ai/services/prompt_template_service.py`（模板注册 + Jinja2 渲染 + CRUD）
  - HTTP 端点：`GET/POST/PUT /ai/v1/prompts`
- **验收标准**：5+ 模板可渲染；变量缺失返回 `AI_PROMPT_RENDER_FAILED`；模板缓存 1h TTL

#### P5-12.6：GenerateQuestion + StreamGenerateQuestion 逐字流式

- **负责人**：ai12
- **依赖**：P5-12.5；**前置**：ISSUE-03（ai.proto 补 `StreamGenerateQuestion` + `GenerateQuestionRequest` 字段扩展）
- **交付物**：
  - `services/ai/src/ai/services/question_generation_service.py`
  - gRPC RPC：`GenerateQuestion` + `StreamGenerateQuestion`（题目逐字流式生成）
  - HTTP 端点：`POST /ai/v1/generate/question` + `POST /ai/v1/generate/question/stream`
- **验收标准**：题目逐字流式返回；Pydantic 请求模型完整（grade/knowledge_point_ids/question_type/count）

#### P5-12.7：评估三道防线（RuleValidator + LLMJudge + QualityGate）

- **负责人**：ai12
- **依赖**：P5-12.6
- **交付物**：
  - `services/ai/src/ai/evaluation/rule_validator.py`（题型匹配/答案非空/解析合理/知识点覆盖）
  - `services/ai/src/ai/evaluation/llm_judge.py`（LLM-as-judge，5 维度加权评分）
  - `services/ai/src/ai/evaluation/quality_gate.py`（阈值 0.7，不达标重试 < 3 次）
- **验收标准**：评估通过率 > 80%；不达标自动重试；重试耗尽返回 `AI_EVALUATION_FAILED`

#### P5-12.8：UsageRecorder + KafkaProducer + QuotaEnforcer

- **负责人**：ai12
- **依赖**：P5-12.6；**前置**：ISSUE-02（topic 裁决）+ ISSUE-04（events.proto 补 AIUsageEvent）
- **交付物**：
  - `services/ai/src/ai/usage/usage_recorder.py`（token 消耗统计）
  - `services/ai/src/ai/usage/kafka_producer.py`（`aiokafka` + acks=all + idempotent + transactional_id）
  - `services/ai/src/ai/usage/quota_enforcer.py`（学校/教师月度配额，Redis 计数）
  - HTTP 端点：`GET /ai/v1/usage/me` + `GET /ai/v1/usage/school/{id}`
- **验收标准**：用量事件落 data-ana ClickHouse；配额超限返回 `AI_QUOTA_EXCEEDED`；event_id SETNX 去重

#### P5-12.9：安全层（PIIRedactor + InputSanitizer + OutputModerator）

- **负责人**：ai12
- **依赖**：P5-12.6
- **交付物**：
  - `services/ai/src/ai/security/pii_redactor.py`（学生姓名/手机号/身份证/邮箱脱敏）
  - `services/ai/src/ai/security/input_sanitizer.py`（Prompt 注入防御）
  - `services/ai/src/ai/security/output_moderator.py`（敏感词过滤 + 安全校验）
- **验收标准**：安全测试通过；PII 检出返回 `AI_PII_DETECTED`；注入检出返回 `AI_PROMPT_INJECTION_DETECTED`

---

### M16 备课工作流（第10-13天）

#### P5-12.10：gRPC client（content / data-ana / iam）+ interceptor

- **负责人**：ai12
- **依赖**：P5-12.3；**前置**：content gRPC 50054 就绪（ai09 P4）、ISSUE-07（iam GetEffectiveDataScope P4 补全）
- **交付物**：
  - `services/ai/src/ai/clients/content_client.py`（KnowledgeGraphService.GetPrerequisites / GetLearningPath）
  - `services/ai/src/ai/clients/data_ana_client.py`（AnalyticsService.GetStudentWeakness / GetLearningTrend / GetClassPerformance）
  - `services/ai/src/ai/clients/iam_client.py`（GetEffectiveDataScope，Redis 缓存 5min）
  - `grpc.aio.ClientInterceptor`（trace 注入 + 重试 + 熔断）
- **验收标准**：下游 gRPC 不可达时降级（跳过学情查询 + `degraded:true`）；DataScope 缓存命中

#### P5-12.11：LessonPreparationWorkflow 4 步编排 + 状态机

- **负责人**：ai12
- **依赖**：P5-12.10；**前置**：ISSUE-03（ai.proto 补 `GenerateLessonPlan` RPC）
- **交付物**：
  - `services/ai/src/ai/services/lesson_preparation_workflow.py`（4 步：分析学情 → 推荐知识点 → 生成题目 → 教师审核）
  - 状态机实现（02-architecture-design.md §2.4：Pending→Analyzing→Recommended→Generating→PendingReview→Persisted）
  - gRPC RPC：`GenerateLessonPlan`
  - HTTP 端点：`POST /ai/v1/lesson/preparation` + `GET /ai/v1/lesson/preparation/{id}`
- **验收标准**：端到端跑通 4 步；评估未通过自动重试 < 3 次；工作流状态可查询

#### P5-12.12：WorkflowStateStore + 教师审核 + content 入库

- **负责人**：ai12
- **依赖**：P5-12.11；**前置**：content `QuestionService.CreateQuestions`（待 coord 补 proto，见 02 doc §7）
- **交付物**：
  - `services/ai/src/ai/workflow/workflow_state_store.py`（Redis 持久化，key `ai:workflow:{id}`，TTL 24h）
  - HTTP 端点：`POST /ai/v1/lesson/preparation/{id}/confirm`（教师确认/修改/拒绝）
  - 调 content.CreateQuestions 入库
- **验收标准**：24h 内工作流可恢复；教师可审核/修改/拒绝；入库成功；24h 未审核过期

#### P5-12.13：集成测试 + 契约测试 + 文档同步

- **负责人**：ai12
- **依赖**：P5-12.12
- **交付物**：
  - `services/ai/tests/`（pytest + pytest-asyncio + testcontainers，覆盖率 ≥ 80%）
  - 契约测试（pact-python，ai.proto 与 teacher-bff 一致性）
  - 更新 `services/ai/README.md` + `docs/troubleshooting/known-issues.md` ai 分区
  - `pnpm run arch:scan` 确认 arch.db 已更新
- **验收标准**：`ruff check src/` + `pytest` 零错误；覆盖率 ≥ 80%；README 含完整架构图

---

## §4 依赖与就绪信号

### 4.1 我依赖的上游就绪标志

| 依赖项                                              | 提供方        | 就绪标志                                  | 状态 | 阻塞任务      |
| --------------------------------------------------- | ------------- | ----------------------------------------- | ---- | ------------- |
| ai.proto 升级 v1 完整版（6 RPC + 字段扩展）         | coord (shared-proto) | proto 文件含 GenerateLessonPlan / StreamGenerateQuestion | ⏳ ISSUE-03 | P5-12.3/12.6/12.11 |
| events.proto 补 AIUsageEvent message                | coord (shared-proto) | proto 含 AIUsageEvent                     | ⏳ ISSUE-04 | P5-12.8       |
| ai 用量事件 topic 命名裁决                          | coord         | 004 §7.2 补登                             | ⏳ ISSUE-02 | P5-12.8       |
| content gRPC 50054 启用                             | ai09 (content) | HealthService.Check = SERVING             | ⏳ P4 | P5-12.10      |
| data-ana gRPC 50055 启用（可选）                    | ai11 (data-ana) | HealthService.Check = SERVING             | ⏳ P4 | P5-12.10（可降级） |
| iam `GetEffectiveDataScope` RPC P4 补全             | ai06 (iam) + coord | iam.proto 含此 RPC                        | ⏳ ISSUE-07 | P5-12.10（可降级） |
| LLM Provider API key（OpenAI / 百川 / Ollama）      | 人类决策者    | 环境变量配置                              | —    | P5-12.1       |

### 4.2 我的就绪信号（供下游消费）

| 就绪标志                                          | 消费方                 | 状态 |
| ------------------------------------------------- | ---------------------- | ---- |
| ai gRPC 50058 启用（HealthService.Check = SERVING） | teacher-bff (ai03)     | ⏳   |
| AiService.Chat / StreamChat 可调用（含流式）      | teacher-bff            | ⏳   |
| AiService.GenerateQuestion / StreamGenerateQuestion 可调用 | teacher-bff            | ⏳   |
| AiService.GenerateLessonPlan 可调用（P5 补全）    | teacher-bff            | ⏳   |
| AiService.OptimizeExpression 可调用               | teacher-bff            | ⏳   |
| ai 用量事件 topic 可发布（供 data-ana 统计）      | data-ana (ai11)        | ⏳   |

### 4.3 完成信号（批次 4 P5 完成）

ai P5 完成的 5 个标志：

1. ai12：ai gRPC 50058 启用 + 6 RPC 全部实现 + HealthService SERVING
2. LLM Provider 4 适配器 + FailoverChain + CircuitBreaker 可用
3. 备课工作流 4 步端到端跑通（含教师审核 + content 入库）
4. 用量事件可发布到 Kafka + data-ana ClickHouse 可落库
5. 端到端：teacher-portal 教师 AI 出题 → 流式返回 → 审核入库

---

## §5 风险与缓解

| 风险                          | 缓解措施                                                                   |
| ----------------------------- | -------------------------------------------------------------------------- |
| coord 未在 P5 启动前补全 proto（ISSUE-02/03/04） | ai12 先按 02-architecture-design.md §3.3/§4.2 建议 schema 实现，proto 落地后对齐 |
| content / iam gRPC 未就绪     | 降级：跳过学情查询 + `degraded:true`；配额降级为仅 user_id 维度            |
| LLM API key 未配置            | 降级骨架响应（已具备，main.py 当前行为）                                   |
| 工作流状态丢失（Redis 故障）  | Redis 哨兵（P6 硬化）+ 事件日志；P6 评估迁移 Temporal（ISSUE-06）          |
