feat: auto committed
This commit is contained in:
@@ -1,42 +1,99 @@
|
||||
# ai 对接契约
|
||||
|
||||
> 负责人:ai12
|
||||
> 关联:[matrix.md](./matrix.md)、[ai.proto](../../../packages/shared-proto/proto/ai.proto)、[events.proto](../../../packages/shared-proto/proto/events.proto)
|
||||
> 关联:[matrix.md](../matrix.md)、[port-allocation.md](../../../../infra/port-allocation.md)、[ai.proto](../../../../packages/shared-proto/proto/ai.proto)、[events.proto](../../../../packages/shared-proto/proto/events.proto)、[02-architecture-design.md](../../../../services/ai/docs/02-architecture-design.md)、[objections/ai_issue.md](../objections/ai_issue.md)
|
||||
> 端口权威源:[port-allocation.md](../../../../infra/port-allocation.md) §3/§5 —— ai = HTTP 3008 / gRPC 50058
|
||||
|
||||
> **本契约已对齐 02-architecture-design.md 设计文档**。原 coord 模板的 5 处矛盾已修正(见 [objections/ai_issue.md](../objections/ai_issue.md) ISSUE-05):端口 50057→50058、补 HTTP 端点、topic 三义待裁决、错误码对齐 §6.2、消费事件改 P6+ 评估。标注 ⏳ 的字段待 coord 裁决 ISSUE-02/03/04 后最终定稿。
|
||||
|
||||
---
|
||||
|
||||
## §1 我提供什么(对外接口)
|
||||
|
||||
### 1.1 gRPC 接口(如有)
|
||||
### 1.1 gRPC 接口
|
||||
|
||||
| Service | RPC | 请求 | 响应 | 端口 |
|
||||
| --------- | ---------------------- | ----------------------------- | ------------------------ | ----- |
|
||||
| AiService | Chat | ChatRequest | ChatResponse | 50057 |
|
||||
| AiService | StreamChat | ChatRequest | stream ChatChunk | 50057 |
|
||||
| AiService | GenerateQuestion | GenerateQuestionRequest | GeneratedQuestion | 50057 |
|
||||
| AiService | OptimizeExpression | OptimizeExpressionRequest | OptimizedExpression | 50057 |
|
||||
| AiService | GenerateLessonPlan | GenerateLessonPlanRequest | LessonPlan | 50057 |
|
||||
| AiService | StreamGenerateQuestion | StreamGenerateQuestionRequest | stream GeneratedQuestion | 50057 |
|
||||
| Service | RPC | 请求 | 响应 | 端口 | 状态 |
|
||||
| --------- | ---------------------- | ------------------------------------------------------------------------------------------------------------ | ----------------------------- | ----- | ---- |
|
||||
| AiService | Chat | `ChatRequest{messages, model, temperature, user_id?, session_id?, data_scope?}` | `ChatResponse{content, model, usage}` | 50058 | ⏳ 待实现 |
|
||||
| AiService | StreamChat | `ChatRequest` | `stream ChatChunk` | 50058 | ⏳ 待实现 |
|
||||
| AiService | GenerateQuestion | `GenerateQuestionRequest{prompt, subject, difficulty, grade?, knowledge_point_ids?, question_type?, count?}` | `GeneratedQuestion` | 50058 | ⏳ 待实现 |
|
||||
| AiService | StreamGenerateQuestion | `GenerateQuestionRequest` | `stream GeneratedQuestionChunk` | 50058 | ⏳ 待补 proto(ISSUE-03) |
|
||||
| AiService | OptimizeExpression | `OptimizeExpressionRequest{text, context}` | `OptimizedExpression` | 50058 | ⏳ 待实现 |
|
||||
| AiService | GenerateLessonPlan | `GenerateLessonPlanRequest{class_id, subject_id, topic, user_id, data_scope}` | `LessonPlanResponse{workflow_id, status, questions?}` | 50058 | ⏳ 待补 proto(ISSUE-03) |
|
||||
|
||||
### 1.2 HTTP 端点(如有)
|
||||
> **RPC 总数**:P5 目标 6 RPC(ai12 建议,见 ISSUE-03)。备课工作流的"查询状态/确认入库"用 HTTP 端点实现,避免 RPC 膨胀;如 coord 裁定需 gRPC 则扩到 8 RPC(追加 GetLessonPlanStatus / ConfirmLessonPlan)。
|
||||
> **proto 现状**:ai.proto 仅 4 RPC(Chat/StreamChat/GenerateQuestion/OptimizeExpression),缺 GenerateLessonPlan / StreamGenerateQuestion,且字段未扩展。待 coord 升级 ai.proto 到 v1 完整版(ISSUE-03)。
|
||||
> **proto package 偏离**:现状 `next_edu_cloud.ai.v1`,不符合 project_rules §5 `edu.<domain>.v1`,见 ISSUE-08。
|
||||
|
||||
无对外 HTTP 端点,仅 gRPC(含 2 个 Server Streaming RPC:StreamChat / StreamGenerateQuestion)。
|
||||
### 1.2 HTTP 端点
|
||||
|
||||
> HTTP 保留作 api-gateway 直连降级 + SSE 流式。api-gateway 代理 `/api/v1/ai/*` → ai `/ai/v1/*`(见 [main.py:70](../../../../services/ai/src/ai/main.py) 注释 + matrix.md §5)。
|
||||
|
||||
| Method | Path | 权限 | 响应 | 说明 | 状态 |
|
||||
| ------ | ------------------------------------------------- | ------------------------ | -------------------------------------- | --------------------------------- | ---- |
|
||||
| GET | `/healthz` | — | `{status, service}` | liveness | ✅ 已实现 |
|
||||
| GET | `/readyz` | — | `{status, llm_configured, providers, downstream_grpc, redis, kafka}` | readiness(多维度检查) | ⚠️ 待扩展 |
|
||||
| GET | `/metrics` | — | Prometheus | 指标 | ✅ 已实现 |
|
||||
| POST | `/ai/v1/chat` | `AI_CHAT` | `ActionState<ChatData>` | LLM 聊天 | ⚠️ 当前 `/ai/chat`,待加 /v1 + ActionState |
|
||||
| POST | `/ai/v1/chat/stream` | `AI_CHAT` | SSE stream | 流式聊天 | ⚠️ 同上 |
|
||||
| POST | `/ai/v1/generate/question` | `AI_QUESTION_GENERATE` | `ActionState<GeneratedQuestionData>` | 生成题目 | ⚠️ 同上 |
|
||||
| POST | `/ai/v1/generate/question/stream` | `AI_QUESTION_GENERATE` | SSE stream(题目逐字生成) | 题目逐字流式 | ⏳ 待实现 |
|
||||
| POST | `/ai/v1/optimize/expression` | `AI_EXPRESSION_OPTIMIZE` | `ActionState<OptimizedExpressionData>` | 优化表达 | ⚠️ 同上 |
|
||||
| POST | `/ai/v1/lesson/preparation` | `AI_LESSON_PREPARE` | `ActionState<LessonPreparationData>` | 备课工作流启动 | ⏳ 待实现 |
|
||||
| GET | `/ai/v1/lesson/preparation/{workflow_id}` | `AI_LESSON_PREPARE` | `ActionState<WorkflowState>` | 查询工作流状态 | ⏳ 待实现 |
|
||||
| POST | `/ai/v1/lesson/preparation/{workflow_id}/confirm` | `AI_LESSON_PREPARE` | `ActionState<PersistResult>` | 教师确认入库 | ⏳ 待实现 |
|
||||
| GET | `/ai/v1/prompts` | `AI_PROMPT_READ` | `ActionState<Page<TemplateSummary>>` | 模板列表 | ⏳ 待实现 |
|
||||
| POST | `/ai/v1/prompts` | `AI_PROMPT_CREATE` | `ActionState<PromptTemplate>` | 创建模板 | ⏳ 待实现 |
|
||||
| GET | `/ai/v1/prompts/{id}` | `AI_PROMPT_READ` | `ActionState<PromptTemplate>` | 获取模板 | ⏳ 待实现 |
|
||||
| PUT | `/ai/v1/prompts/{id}` | `AI_PROMPT_UPDATE` | `ActionState<PromptTemplate>` | 更新模板(版本化) | ⏳ 待实现 |
|
||||
| GET | `/ai/v1/usage/me` | `AI_USAGE_READ` | `ActionState<UsageSummary>` | 当前用户用量 | ⏳ 待实现 |
|
||||
| GET | `/ai/v1/usage/school/{school_id}` | `AI_USAGE_READ_ALL` | `ActionState<UsageSummary>` | 学校用量(管理员) | ⏳ 待实现 |
|
||||
|
||||
> **响应信封**:所有响应必须为 ActionState(004 §11.5 强制,见 ISSUE-09)。当前 main.py 返回 `{success, data, degraded}` 顶层 degraded 字段,违反约束,P5 必须整改。
|
||||
> **路径演进**:当前实现是 `/ai/*`(无 /v1),目标态 `/ai/v1/*`(加版本前缀,便于未来破坏性变更)。
|
||||
|
||||
### 1.3 GraphQL schema(如 BFF)
|
||||
|
||||
不适用。
|
||||
不适用。ai 是业务服务,不暴露 GraphQL;由 teacher-bff 聚合 ai gRPC 能力为 GraphQL。
|
||||
|
||||
### 1.4 Kafka 事件发布(如有)
|
||||
### 1.4 Kafka 事件发布
|
||||
|
||||
| Topic | Event | 消费方 |
|
||||
| ------------------- | ---------------------------------------------------------------------------------------- | -------- |
|
||||
| edu.ai.usage.events | AIUsageEvent(operation: chat/generate_question/optimize_expression/lesson_preparation) | data-ana |
|
||||
| Topic ⏳ | Event | 触发时机 | 消费方 | Payload |
|
||||
| ----------------- | ---------------------- | ----------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `edu.ai.usage`(建议,待 ISSUE-02 裁决) | `AIUsageEvent`(待 ISSUE-04 补 proto) | 每次 LLM 调用完成 | data-ana | `{event_id, aggregate_id, event_type, occurred_at, user_id, school_id, request_id, provider, model, operation, prompt_tokens, completion_tokens, total_tokens, latency_ms, success, degraded, metadata}` |
|
||||
|
||||
> 注:AIUsageEvent 豁免 Outbox 模式(派生数据事件,见 004 §12.2 + §15.3 #6)。
|
||||
> **topic 命名三义**:01/02 文档写 `edu.insight.ai.usage`、matrix.md 写 `edu.ai.usage`、原 contract 写 `edu.ai.usage.events`。ai12 建议采用 `edu.ai.usage`(最简短),待 coord 裁决(ISSUE-02)。
|
||||
> **Outbox 豁免**:AIUsageEvent 为派生数据事件,004 §12.2 + §15.3 #6 仲裁豁免 Outbox,允许直接 producer(`aiokafka` + acks=all + idempotent + transactional_id)。
|
||||
> **events.proto 现状**:无 `AIUsageEvent` message,待 coord 补全(ISSUE-04),建议 schema 见 [02-architecture-design.md §3.3](../../../../services/ai/docs/02-architecture-design.md)。
|
||||
> **长期可发布事件**(P6+ 评估,待 coord 仲裁):`AIContentGenerated`(topic `edu.ai.generated`,生成内容审计)、`AIFeedbackRecorded`(topic `edu.ai.feedback`,RLHF 数据)、`AIWorkflowEvent`(topic `edu.ai.workflow`,工作流监控)。
|
||||
|
||||
### 1.5 错误码前缀
|
||||
|
||||
`AI_`(如 AI_PROVIDER_UNAVAILABLE、AI_TOKEN_LIMIT_EXCEEDED、AI_CONTENT_FILTERED)
|
||||
`AI_*`(对齐 [02-architecture-design.md §6.2](../../../../services/ai/docs/02-architecture-design.md) 完整清单,matrix.md §6 已确认 ai 前缀为 `AI_`)
|
||||
|
||||
| 错误码 | 触发条件 | HTTP | gRPC status |
|
||||
| -------------------------------- | ----------------------------------- | ---- | ------------------- |
|
||||
| `AI_UNAUTHORIZED` | 缺失 x-user-id 或 token 无效 | 401 | UNAUTHENTICATED |
|
||||
| `AI_FORBIDDEN` | 角色无对应权限 | 403 | PERMISSION_DENIED |
|
||||
| `AI_RATE_LIMITED` | 触发限流(user/IP/school) | 429 | RESOURCE_EXHAUSTED |
|
||||
| `AI_QUOTA_EXCEEDED` | 学校/教师月度 token 配额耗尽 | 429 | RESOURCE_EXHAUSTED |
|
||||
| `AI_LLM_UNAVAILABLE` | LLM Provider 不可达(降级骨架) | 200 | OK + degraded flag |
|
||||
| `AI_LLM_TIMEOUT` | LLM 调用超时(30s) | 504 | DEADLINE_EXCEEDED |
|
||||
| `AI_LLM_ALL_PROVIDERS_FAILED` | 所有 Provider 故障切换链均失败 | 503 | UNAVAILABLE |
|
||||
| `AI_INVALID_MODEL` | model 名不支持 | 400 | INVALID_ARGUMENT |
|
||||
| `AI_INVALID_DIFFICULTY` | difficulty 不在 easy/medium/hard | 400 | INVALID_ARGUMENT |
|
||||
| `AI_INVALID_QUESTION_TYPE` | question_type 不在枚举内 | 400 | INVALID_ARGUMENT |
|
||||
| `AI_DOWNSTREAM_UNAVAILABLE` | content / data-ana gRPC 不可达 | 502 | UNAVAILABLE |
|
||||
| `AI_PROMPT_RENDER_FAILED` | Prompt 模板渲染失败 | 500 | INTERNAL |
|
||||
| `AI_PROMPT_TEMPLATE_NOT_FOUND` | Prompt 模板不存在 | 404 | NOT_FOUND |
|
||||
| `AI_WORKFLOW_NOT_FOUND` | 备课工作流 ID 不存在 | 404 | NOT_FOUND |
|
||||
| `AI_WORKFLOW_EXPIRED` | 工作流已过期(24h 未审核) | 410 | FAILED_PRECONDITION |
|
||||
| `AI_WORKFLOW_STATE_INVALID` | 工作流状态不允许此操作 | 409 | FAILED_PRECONDITION |
|
||||
| `AI_EVALUATION_FAILED` | 生成质量评估未通过且重试耗尽 | 503 | UNAVAILABLE |
|
||||
| `AI_PII_DETECTED` | 输入包含未脱敏 PII | 400 | INVALID_ARGUMENT |
|
||||
| `AI_PROMPT_INJECTION_DETECTED` | 输入疑似 Prompt 注入攻击 | 400 | INVALID_ARGUMENT |
|
||||
| `AI_CONTENT_MODERATION_REJECTED` | 输出内容审核不通过(敏感词) | 503 | UNAVAILABLE |
|
||||
| `AI_INTERNAL_ERROR` | 未捕获异常 | 500 | INTERNAL |
|
||||
|
||||
---
|
||||
|
||||
@@ -44,24 +101,37 @@
|
||||
|
||||
### 2.1 gRPC 调用(同步)
|
||||
|
||||
| 被调用方 | Service.RPC | 用途 | mock 策略 |
|
||||
| --------------- | -------------------------------------- | ---------------------------- | ----------------------------------------------------------- |
|
||||
| content (ai09) | KnowledgeGraphService.GetPrerequisites | 生成题目时获取知识点前置依赖 | content 就绪前使用本地知识点 stub(固定 3 个前置知识点) |
|
||||
| content (ai09) | QuestionService.SearchQuestions | 备课时检索同类题目参考 | content 就绪前返回空列表 |
|
||||
| data-ana (ai11) | AnalyticsService.GetStudentWeakness | 个性化出题时获取学生薄弱点 | data-ana 就绪前使用本地薄弱点 stub(固定 2 个 weak_points) |
|
||||
| 被调用方 | Service.RPC | 用途 | mock 策略 |
|
||||
| --------------- | -------------------------------------- | ---------------------------- | ------------------------------------------------------------- |
|
||||
| content (ai09) | `KnowledgeGraphService.GetPrerequisites` | 出题上下文:查询知识点前置依赖 | content 就绪前使用本地知识点 stub(固定 3 个前置知识点) |
|
||||
| content (ai09) | `KnowledgeGraphService.GetLearningPath` | 个性化出题:查询学生学习路径 | content 就绪前返回空路径 |
|
||||
| content (ai09) | `TextbookService.ListTextbooks` | 备课工作流:查询教材章节关联知识点 | content 就绪前返回空列表 |
|
||||
| content (ai09) | `QuestionService.CreateQuestions`(待 coord 补 proto) | 备课工作流:生成的题目入库 | content 就绪前跳过入库,工作流标记 PersistFailed |
|
||||
| data-ana (ai11) | `AnalyticsService.GetStudentWeakness` | 靶向出题:查询学生薄弱知识点 | data-ana 就绪前使用本地薄弱点 stub(固定 2 个 weak_points) |
|
||||
| data-ana (ai11) | `AnalyticsService.GetLearningTrend` | 难度调节:查询学习趋势 | data-ana 就绪前返回默认趋势 |
|
||||
| data-ana (ai11) | `AnalyticsService.GetClassPerformance` | 备课工作流:班级整体学情 | data-ana 就绪前降级跳过学情查询(`degraded:true`) |
|
||||
| iam (ai06) | `IamService.GetEffectiveDataScope`(待 P4 补全,ISSUE-07) | 多租户配额:查询用户 DataScope | iam RPC 未就绪时降级为"仅按 user_id 配额,不按 school_id" |
|
||||
|
||||
> **端口**:content gRPC 50054 / data-ana 50055 / iam 50052([port-allocation.md](../../../../infra/port-allocation.md) §5)。注意 02-architecture-design.md §1.1/§1.2 mermaid 图误标为 3005/3006/3002(HTTP 端口),应以 50054/50055/50052 为准。
|
||||
|
||||
### 2.2 Kafka 事件订阅(异步)
|
||||
|
||||
| Topic | Event | 发布方 | mock 策略 |
|
||||
| ---------------------------------- | ------------------- | -------------- | -------------------------------------- |
|
||||
| edu.content.knowledge_point.events | KnowledgePointEvent | content (ai09) | content 就绪前不订阅,使用内置知识点表 |
|
||||
| edu.content.question.events | QuestionEvent | content (ai09) | content 就绪前忽略 |
|
||||
> ai 是**无状态服务,P5 不消费任何 Kafka 事件**(01/02 §5.1 明确)。原 contract 列出的 content 事件订阅已删除(与设计文档矛盾,见 ISSUE-05.5)。
|
||||
|
||||
### 2.3 HTTP 调用(如有)
|
||||
**P6+ 评估可消费事件**(待 coord 仲裁,非 P5 范围):
|
||||
|
||||
| Topic | Event | 发布方 | 用途 | 评估阶段 |
|
||||
| ---------------------------------- | ------------------- | -------------- | -------------------------------- | -------- |
|
||||
| `edu.content.question.events` | QuestionEvent | content (ai09) | 题目查重:避免 AI 生成与已有重复 | P6+ |
|
||||
| `edu.iam.user.events` | UserEvent | iam (ai06) | 角色变更:主动失效 DataScope 缓存 | P6+ |
|
||||
|
||||
### 2.3 HTTP 调用(外部)
|
||||
|
||||
| 被调用方 | Method.Path | 用途 | mock 策略 |
|
||||
| -------------------------------- | ------------------------- | ------------------ | ------------------------------------------------------------------ |
|
||||
| LLM Provider(OpenAI/百川/本地) | POST /v1/chat/completions | 调用大模型生成内容 | 开发期使用本地 mock server 返回固定 ChatResponse,不消耗真实 token |
|
||||
| LLM Provider(OpenAI/Anthropic/百川/Ollama) | POST /v1/chat/completions | 调用大模型生成内容 | 开发期使用本地 mock server 返回固定 ChatResponse,不消耗真实 token |
|
||||
|
||||
> 多 Provider 通过 `ProviderFailoverChain` 故障切换(OpenAI → Anthropic → 百川 → 本地 Ollama),熔断器连续 3 次失败触发 60s 熔断。
|
||||
|
||||
---
|
||||
|
||||
@@ -69,18 +139,24 @@
|
||||
|
||||
### 3.1 我依赖的上游就绪标志
|
||||
|
||||
- [ ] content gRPC 50054 启用(ai09)—— 知识点维度 + 题库检索
|
||||
- [ ] edu.content.knowledge_point.events topic 有事件发布(ai09)
|
||||
- [ ] data-ana gRPC 50055 启用(ai11)—— 学生薄弱点(可选,ai 可先独立运行)
|
||||
- [ ] ai.proto 升级 v1 完整版(6 RPC + 字段扩展)—— coord(ISSUE-03)
|
||||
- [ ] events.proto 补 `AIUsageEvent` message —— coord(ISSUE-04)
|
||||
- [ ] ai 用量事件 topic 命名裁决 —— coord(ISSUE-02)
|
||||
- [ ] content gRPC 50054 启用(ai09)—— 知识点维度 + 题库检索 + 入库
|
||||
- [ ] data-ana gRPC 50055 启用(ai11,可选)—— 学生薄弱点(可降级独立运行)
|
||||
- [ ] iam `GetEffectiveDataScope` RPC P4 补全(ai06 + coord,ISSUE-07,可降级)
|
||||
- [ ] LLM Provider API key 配置(人类决策者)
|
||||
|
||||
### 3.2 我的就绪标志(供下游消费)
|
||||
|
||||
- [ ] ai gRPC 50057 启用(HealthService.Check 返回 SERVING)
|
||||
- [ ] ai gRPC 50058 启用(HealthService.Check 返回 SERVING)
|
||||
- [ ] AiService.Chat / StreamChat 可调用(含流式响应)
|
||||
- [ ] AiService.GenerateQuestion / StreamGenerateQuestion 可调用
|
||||
- [ ] AiService.GenerateLessonPlan 可调用(P5 补全)
|
||||
- [ ] AiService.OptimizeExpression 可调用
|
||||
- [ ] edu.ai.usage.events topic 可发布(供 data-ana 统计 AI 用量)
|
||||
- [ ] ai 用量事件 topic 可发布(供 data-ana 统计 AI 用量)
|
||||
|
||||
> **端口**:50058([port-allocation.md](../../../../infra/port-allocation.md) §3/§5/§7 权威源,2026-07-09 coord 仲裁"50058 让给 ai")。注意 [matrix.md](../matrix.md) §2/§8 仍写 50057,待 coord 同步(ISSUE-01)。
|
||||
|
||||
---
|
||||
|
||||
@@ -90,12 +166,13 @@
|
||||
|
||||
在 ai 真实服务就绪前,为下游(teacher-bff)提供以下 mock:
|
||||
|
||||
- **gRPC mock**:使用 grpc-mock 拦截 50057 端口
|
||||
- **gRPC mock**:使用 grpc-mock 拦截 **50058** 端口
|
||||
- AiService.Chat 返回固定 ChatResponse(content="这是 AI 助手的模拟回复")
|
||||
- AiService.StreamChat 返回固定流(3 个 ChatChunk,最后一个 done=true)
|
||||
- AiService.GenerateQuestion 返回固定 GeneratedQuestion(question/answer/explanation)
|
||||
- AiService.GenerateLessonPlan 返回固定 LessonPlan(3 个 LessonSection)
|
||||
- AiService.StreamGenerateQuestion 返回固定流(2 个 GeneratedQuestion)
|
||||
- AiService.GenerateLessonPlan 返回固定 LessonPlanResponse(workflow_id + 3 个题目)
|
||||
- AiService.StreamGenerateQuestion 返回固定流(2 个题目逐字 chunk)
|
||||
- AiService.OptimizeExpression 返回固定 OptimizedExpression
|
||||
- **Kafka mock**:ai 就绪前不发布真实 AIUsageEvent,data-ana 仪表盘 AI 用量显示"暂无数据"
|
||||
|
||||
### 4.2 我消费的 mock
|
||||
@@ -105,4 +182,22 @@
|
||||
- **LLM Provider mock**:本地启动 mock server,POST /v1/chat/completions 返回固定 JSON(不消耗真实 token,不产生费用)
|
||||
- **content 知识点**:内置固定知识点表(数学 20 个知识点 + 前置依赖关系),不依赖 content gRPC
|
||||
- **data-ana 薄弱点**:内置固定学生薄弱点(2 个 weak_points),不依赖 data-ana gRPC
|
||||
- **事件订阅**:不订阅 content 事件,知识点维度表静态
|
||||
- **iam DataScope**:内置固定 DataScope(SCHOOL 级),不依赖 iam GetEffectiveDataScope
|
||||
- **事件订阅**:P5 不订阅任何事件,无 mock 需要
|
||||
|
||||
---
|
||||
|
||||
## §5 契约待裁决项汇总
|
||||
|
||||
> 以下字段待 coord 裁决后最终定稿,ai12 当前按建议方案先行实现。
|
||||
|
||||
| 待裁决项 | ISSUE | ai12 建议方案 | 影响章节 |
|
||||
| --------------------------------- | ------ | ---------------------------------------------- | -------------- |
|
||||
| ai gRPC 端口(50057 vs 50058) | ISSUE-01 | 50058(port-allocation.md 已定,待 matrix 同步) | §1.1 / §3.2 |
|
||||
| ai 用量事件 topic 命名 | ISSUE-02 | `edu.ai.usage` | §1.4 |
|
||||
| ai.proto P5 目标 RPC 数(6 vs 8) | ISSUE-03 | 6 RPC(查询/确认用 HTTP) | §1.1 |
|
||||
| events.proto 补 AIUsageEvent | ISSUE-04 | 按 02-architecture-design.md §3.3 schema | §1.4 |
|
||||
| 备课工作流 Temporal(P6 决策点) | ISSUE-06 | P5 用 BackgroundTasks + Redis,P6 评估 Temporal | §2.1(无影响) |
|
||||
| iam GetEffectiveDataScope P4 补全 | ISSUE-07 | 确认 P4 已补全;未补全则降级 | §2.1 |
|
||||
| proto package 命名(全局) | ISSUE-08 | 待 coord 裁定是否迁移 `edu.<domain>.v1` | §1.1 |
|
||||
| 响应信封 ActionState 整改 | ISSUE-09 | P5 整改,degraded 作为 error.details 子字段 | §1.2 |
|
||||
|
||||
@@ -1,13 +1,130 @@
|
||||
# ai 问题记录
|
||||
|
||||
> 负责人:ai12
|
||||
> 关联:[coord.md](../coord.md)、[contracts/ai_contract.md](../contracts/ai_contract.md)
|
||||
> 关联:[coord.md](../coord.md)、[contracts/ai_contract.md](../contracts/ai_contract.md)、[matrix.md](../matrix.md)、[port-allocation.md](../../../../infra/port-allocation.md)
|
||||
> 规则:AI 遇到问题时在此追加条目,coord 仲裁后更新状态
|
||||
|
||||
---
|
||||
|
||||
## §0 已有仲裁核查(ai12 复核,2026-07-10)
|
||||
|
||||
> 任务要求:对已有的仲裁进行核查。coord.md 当前仅含 ARB-001 / ARB-002;另在 [port-allocation.md](../../../../infra/port-allocation.md) §7、coord-final-decisions.md、president-final-rulings.md 中存在涉及 ai 的历史仲裁。逐项核查如下。
|
||||
|
||||
| 仲裁编号 / 来源 | 主题 | 涉及 ai? | 核查结论 | 状态 |
|
||||
| -------------------------- | ----------------------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
|
||||
| ARB-001(coord.md §1) | teacher-bff GraphQL schema 第一版 | ❌ 否 | 与 ai 无关,不适用。 | — |
|
||||
| ARB-002(coord.md §2) | MF Shell 暴露清单 | ❌ 否 | 与 ai 无关,不适用。 | — |
|
||||
| port-allocation.md §7 | 50058 让给 ai(push-gateway 豁免 gRPC) | ✅ 是 | **仲裁有效**:port-allocation.md §3/§5 已登记 ai = HTTP 3008 / gRPC 50058。ai 的 01/02 文档已按 50058 设计,一致。**但 [matrix.md](../matrix.md) §2 gRPC 接口提供方矩阵、§8 就绪信号跟踪表仍写 50057,未同步** → 提请 coord 同步(见 ISSUE-01) | ⚠️ 仲裁有效但未同步 |
|
||||
| coord-final-decisions §1-§4 | iam P2 契约 / BFF 设计 / Gateway / content | ❌ 否 | 历史仲裁,与 ai 无直接约束。ai 仅消费 content/data-ana gRPC,需待其就绪。 | — |
|
||||
| president-final-rulings §2.3 | Temporal 用于 AI 编排 | ✅ 是 | **部分仲裁**:004 §2.3 列出 Temporal。ai12 已在 02-architecture-design.md §8.3 建议简单 4 步工作流用 BackgroundTasks + Redis,长运行评估 Temporal。需 coord 在 P6 决策点确认(见 ISSUE-06)。 | ⚠️ 部分仲裁 |
|
||||
| 01/02 文档引用"004 §7.2 已确认 topic edu.insight.ai.usage" | ai 用量事件 topic | ✅ 是 | **核查不通过**:grep 004 全文未发现 `ai.usage` / `insight.ai` / `AIUsage` 任何字样,004 §7.2 并未确认 ai 的 topic。该引用无法证实,topic 命名实际处于三义未决状态(见 ISSUE-02)。 | ❌ 引用失实 |
|
||||
| 01/02 文档引用"004 §1.2 端口矩阵 HTTP+10050 规则" | ai gRPC 端口推导规则 | ✅ 是 | **核查不通过**:004 全文无端口矩阵;`HTTP+10050` 公式不成立(3008+10050=13058≠50058)。端口唯一源是 port-allocation.md(顺序分配),ai=50058。ai 文档应改引 port-allocation.md。 | ❌ 引用失实 |
|
||||
|
||||
**核查总结**:coord.md 现有 2 项仲裁(ARB-001/002)均与 ai 无关;涉及 ai 的真实仲裁在 port-allocation.md(50058 已定)与 004 §2.3(Temporal 部分仲裁)。ai 文档对"004 §7.2/§1.2"的两处引用失实,需修正引用源。
|
||||
|
||||
---
|
||||
|
||||
## 问题列表
|
||||
|
||||
### ISSUE-01-ai12:matrix.md 端口 50057 与 port-allocation.md 50058 不同步
|
||||
|
||||
- **提请方**:ai12
|
||||
- **日期**:2026-07-10
|
||||
- **类型**:编号冲突 / 文档不同步
|
||||
- **描述**:[matrix.md](../matrix.md) §2 gRPC 接口提供方矩阵写 "ai (ai12) | 50057",§8 就绪信号跟踪表写 "ai gRPC 50057"。但 [port-allocation.md](../../../../infra/port-allocation.md) §3/§5/§7 明确 ai = HTTP 3008 / gRPC 50058(2026-07-09 coord 仲裁"push-gateway 豁免 gRPC,释放 50057;50058 让给 ai")。两份 coord 文件矛盾,matrix.md 过时。ai 01/02 文档与 workline.md §1/§4.12 已正确采用 50058。
|
||||
- **建议方案**:coord 将 matrix.md §2 ai 行 gRPC 端口 50057 → 50058,§8 就绪信号"ai gRPC 50057"→ 50058。ai12 同步将 contracts/ai_contract.md 全部 50057 改 50058。
|
||||
- **状态**:待 coord 仲裁(实为同步操作,仲裁已存在于 port-allocation.md §7)
|
||||
|
||||
### ISSUE-02-ai12:ai 用量事件 Kafka topic 命名三义未决
|
||||
|
||||
- **提请方**:ai12
|
||||
- **日期**:2026-07-10
|
||||
- **类型**:契约不明确
|
||||
- **描述**:ai 用量计费事件 topic 在三份文档中命名不一致,且无权威源:
|
||||
- 01-understanding.md §3.2 / 02-architecture-design.md §5.2:`edu.insight.ai.usage`(自称"004 §7.2 已确认",但 004 中不存在)
|
||||
- matrix.md §4 Kafka 事件发布方矩阵:`edu.ai.usage`,事件 `AIUsageEvent`
|
||||
- contracts/ai_contract.md §1.4:`edu.ai.usage.events`
|
||||
|
||||
events.proto 现状无 `AIUsageEvent` message,004 无 topic 记录。三义导致 data-ana 消费方无法对齐。
|
||||
- **建议方案**:ai12 建议采用 `edu.ai.usage`(与 matrix.md 一致,最简短,符合 `edu.<domain>.<action>` 简洁约定)。请 coord 裁定并在 004 §7.2 补登 + events.proto 补 `AIUsageEvent` message(schema 见 02-architecture-design.md §3.3)。ai12 据裁决同步 01/02 文档与 contract。
|
||||
- **状态**:待 coord 仲裁
|
||||
|
||||
### ISSUE-03-ai12:ai.proto 待补全(备课工作流 RPC + 字段扩展)
|
||||
|
||||
- **提请方**:ai12
|
||||
- **日期**:2026-07-10
|
||||
- **类型**:契约不明确 / 前置依赖缺失
|
||||
- **描述**:ai.proto 现状仅 4 RPC(Chat / StreamChat / GenerateQuestion / OptimizeExpression),且 `GenerateQuestionRequest` 仅 prompt/subject/difficulty 三字段。P5 交付需要:
|
||||
- 新增 RPC:`GenerateLessonPlan`、`StreamGenerateQuestion`(ai-allocation §5 "题目逐字生成")
|
||||
- `GenerateQuestionRequest` 扩展字段:grade / knowledge_point_ids / question_type / count
|
||||
- `ChatRequest` 扩展可选字段:user_id / session_id / data_scope
|
||||
|
||||
关于 RPC 总数存在分歧:matrix.md §2 与 contract 写 6 RPC;02-architecture-design.md §4.2 单方面扩到 8 RPC(追加 GetLessonPlanStatus / ConfirmLessonPlan)。需 coord 裁定 P5 目标 RPC 清单。
|
||||
- **建议方案**:ai12 建议 P5 目标 6 RPC(Chat / StreamChat / GenerateQuestion / StreamGenerateQuestion / OptimizeExpression / GenerateLessonPlan)。备课工作流的"查询状态/确认入库"用 HTTP 端点(`GET /ai/v1/lesson/preparation/{id}` + `POST .../confirm`)实现,避免 RPC 膨胀;如 coord 认为查询/确认也需 gRPC,则定为 8 RPC。请 coord 在 P5 启动前升级 ai.proto 到 v1 完整版。
|
||||
- **状态**:待 coord 仲裁
|
||||
|
||||
### ISSUE-04-ai12:events.proto 缺 AIUsageEvent message
|
||||
|
||||
- **提请方**:ai12
|
||||
- **日期**:2026-07-10
|
||||
- **类型**:契约不明确 / 前置依赖缺失
|
||||
- **描述**:004 §12.2 + §15.3 #6 仲裁 ai 用量事件豁免 Outbox(派生数据),但 events.proto 现状仅有 ClassEvent / ExamEvent / HomeworkEvent / GradeEvent,**无 AIUsageEvent**。data-ana 消费方无 schema 可循。01/02 文档已提请(A3),matrix.md §4 已列事件名,但 proto 未落地。
|
||||
- **建议方案**:coord 在 events.proto 新增 `AIUsageEvent` message,建议 schema 见 02-architecture-design.md §3.3(含 event_id / user_id / school_id / provider / model / operation / prompt_tokens / completion_tokens / total_tokens / latency_ms / success / degraded / metadata)。与 ISSUE-02 一并裁决。
|
||||
- **状态**:待 coord 仲裁
|
||||
|
||||
### ISSUE-05-ai12:contracts/ai_contract.md 与设计文档多处矛盾(ai12 自查自纠清单)
|
||||
|
||||
- **提请方**:ai12
|
||||
- **日期**:2026-07-10
|
||||
- **类型**:契约不明确 / 文档不同步
|
||||
- **描述**:现有 contracts/ai_contract.md(coord 模板,ai12 接管前未细化)与 01/02 设计文档存在 5 处矛盾:
|
||||
1. §1.1 gRPC 端口 50057(应为 50058,见 ISSUE-01)
|
||||
2. §1.2 "无对外 HTTP 端点,仅 gRPC"——错误。api-gateway 代理 `/api/v1/ai/*` → ai HTTP(main.py 已实现 /ai/* 端点 + SSE 流式),HTTP 保留作 Gateway 直连降级
|
||||
3. §1.4 topic `edu.ai.usage.events`(三义,见 ISSUE-02)
|
||||
4. §1.5 错误码示例 `AI_PROVIDER_UNAVAILABLE` / `AI_TOKEN_LIMIT_EXCEEDED` / `AI_CONTENT_FILTERED` 与 02-architecture-design.md §6.2 清单(`AI_LLM_UNAVAILABLE` / `AI_QUOTA_EXCEEDED` / `AI_CONTENT_MODERATION_REJECTED`)命名不一致
|
||||
5. §2.2 列出 ai 消费 2 个 content Kafka 事件,与 01/02 §5.1 "ai 不消费任何事件(无状态)"矛盾
|
||||
|
||||
- **建议方案**:ai12 在本次工作中直接重写 contracts/ai_contract.md 对齐设计文档(端口 50058 / 补 HTTP 端点 / topic 待 ISSUE-02 裁决后填 / 错误码对齐 02 §6.2 / 删除消费事件或标注 P6+ 评估)。仅 RPC 数与 topic 命名待 coord 裁决后最终定稿。
|
||||
- **状态**:ai12 自纠中(依赖 ISSUE-01/02/03 裁决的字段待补)
|
||||
|
||||
### ISSUE-06-ai12:备课工作流是否引入 Temporal(P6 决策点)
|
||||
|
||||
- **提请方**:ai12
|
||||
- **日期**:2026-07-10
|
||||
- **类型**:工作量超批 / 前置依赖缺失
|
||||
- **描述**:004 §2.3 列出 Temporal 用于"AI 编排",属部分仲裁。ai12 在 02-architecture-design.md §8.3 建议:P5 用 FastAPI BackgroundTasks + Redis(24h TTL)实现 4 步备课工作流;P6 评估迁移 Temporal(支持长运行跨天审核 + 复杂状态机)。需 coord 在 P6 决策点确认是否引入,避免 P5 实现被推翻重做。
|
||||
- **建议方案**:P5 采用 BackgroundTasks + Redis(02-architecture-design.md §2.4 状态机已设计);P6 由 coord 评估 Temporal 引入时机。请 coord 在 roadmap 标注 P6 决策点。
|
||||
- **状态**:待 coord 仲裁(P6 决策点)
|
||||
|
||||
### ISSUE-07-ai12:iam GetEffectiveDataScope gRPC RPC 待 P4 补全
|
||||
|
||||
- **提请方**:ai12
|
||||
- **日期**:2026-07-10
|
||||
- **类型**:前置依赖缺失
|
||||
- **描述**:ai 多租户用量配额校验需调用 `IamService.GetEffectiveDataScope` 查询用户 DataScope。01/02 文档已提请(A4),coord 已仲裁 P4 补全(§15.3 #5),但 iam.proto 现状未见此 RPC。ai P5 实施时依赖,若 P4 未补全将阻塞配额校验功能。
|
||||
- **建议方案**:请 coord 确认 iam (ai06) 在 P4 已补全 `GetEffectiveDataScope` RPC;ai12 在 P5 实施时调用,Redis 缓存 5min。若 P4 未补全,ai 降级为"仅按 user_id 配额,不按 school_id"。
|
||||
- **状态**:待 coord 确认 P4 补全情况
|
||||
|
||||
### ISSUE-08-ai12:proto package 命名不符合 project_rules §5
|
||||
|
||||
- **提请方**:ai12
|
||||
- **日期**:2026-07-10
|
||||
- **类型**:契约不明确 / 架构约束
|
||||
- **描述**:project_rules §5 规定 proto 包名规范 `edu.<domain>.v1`(如 `edu.iam.v1`、`edu.core_edu.v1`)。但 ai.proto 现状 package 为 `next_edu_cloud.ai.v1`,events.proto 为 `next_edu_cloud.events.v1`,均不符合规范。01/02 文档未指出此偏离。此为全局 proto 命名问题(涉及全部 proto 文件),非 ai 独有,但 ai12 在审查中发现需提请。
|
||||
- **建议方案**:请 coord 裁定是否统一迁移 proto package 至 `edu.<domain>.v1`(全局变更,需 buf breaking 评估);或保留现状作为历史包袱。ai12 在 ai.proto 补全 RPC 时遵循最终裁定。
|
||||
- **状态**:待 coord 仲裁(全局 proto 命名)
|
||||
|
||||
### ISSUE-09-ai12:响应信封偏离 ActionState 强制整改(P0)
|
||||
|
||||
- **提请方**:ai12
|
||||
- **日期**:2026-07-10
|
||||
- **类型**:架构约束
|
||||
- **描述**:004 §11.5 强制响应信封为 ActionState(`{success, data, error:{code,message,details,traceId}}`)。ai 当前 main.py 违反:返回 `{success:true, data:..., degraded:false}` 顶层 degraded 字段(见 main.py:89/201-210/233-244)。01/02 文档已提请(A5),contracts 未记录。P5 实施必须整改。
|
||||
- **建议方案**:P5 实施时所有 HTTP 端点 + gRPC RPC 返回值改为 ActionState;degraded 作为 `error.details.degraded` 子字段。请 coord 在 known-issues §2.9 ai 分区记录此约束(01 文档已提请,需 coord 落地 known-issues)。
|
||||
- **状态**:待 coord 在 known-issues 记录约束(整改由 ai12 P5 执行)
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
追加条目格式:
|
||||
|
||||
@@ -20,5 +137,3 @@
|
||||
- **建议方案**:[AI 的建议]
|
||||
- **状态**:待 coord 仲裁 / 已裁决(见 coord.md §X)
|
||||
-->
|
||||
|
||||
(暂无问题)
|
||||
|
||||
@@ -1,45 +1,264 @@
|
||||
# ai 工作排期
|
||||
|
||||
> 负责人:ai12
|
||||
> 关联:[workline.md](../workline.md)、[coord.md](../coord.md)、[contracts/ai_contract.md](../contracts/ai_contract.md)
|
||||
> 模式:全并行(各 AI 一口气完成 P2-P6 全部代码,最后统一集成测试)
|
||||
> 关联:[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 是智能服务,提供 AiService(6 个 RPC),结合 Elasticsearch 检索与 LLM 网关实现智能问答与推荐。全阶段目标:P2 ES 接入+LLM 网关 → P3 AiService 6 RPC → P4-P6 持续优化。
|
||||
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 全阶段甘特图(P2-P6,各 AI 自行细化)
|
||||
## §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 全阶段排期
|
||||
title ai12 ai 服务 P5 排期(13 天)
|
||||
dateFormat YYYY-MM-DD
|
||||
axisFormat %m-%d
|
||||
|
||||
section P2-P6
|
||||
[阶段任务] :a12a, 2026-07-10, Xd
|
||||
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
|
||||
```
|
||||
|
||||
> **注意**:以上为 coord 初始规划,ai12 接管后必须自行细化为完整 P2-P6 排期。
|
||||
**关键路径**(红色 crit):LLMProvider 抽象 → gRPC server → PromptTemplateService → GenerateQuestion → gRPC client → 备课工作流编排
|
||||
|
||||
---
|
||||
|
||||
## §3 详细任务
|
||||
|
||||
### 全阶段任务
|
||||
### M14 基础架构(第1-4天)
|
||||
|
||||
#### P5-12.1:LLMProvider 抽象 + 4 适配器
|
||||
|
||||
- **负责人**:ai12
|
||||
- **交付物**:⚠️ 由 ai12 自行补充
|
||||
- **依赖**:见 [contracts/ai_contract.md](../contracts/ai_contract.md)
|
||||
- **验收标准**:⚠️ 由 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 依赖与就绪信号
|
||||
|
||||
- **我依赖**:⚠️ 由 ai12 自行补充(见 contract.md)
|
||||
- **我的就绪信号**:⚠️ 由 ai12 自行补充
|
||||
### 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) |
|
||||
|
||||
Reference in New Issue
Block a user