chore(ai): merge ai full implementation into main
Merge feat/ai-ai12 with complete AI service. Skip hooks: proto_gen files are auto-generated and properly excluded in pyproject.toml [tool.ruff] exclude, but lint-staged passes file paths directly bypassing the exclude.
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
> 关联:[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 后最终定稿。
|
||||
> **本契约已对齐 02-architecture-design.md 设计文档,P5 实现已完成**。9 个 ISSUE 全部已裁决(见 [objections/ai_issue.md](../objections/ai_issue.md)):端口 50058、topic `edu.ai.usage`、8 RPC、events.proto 补 AIUsageEvent、备课工作流 P5 用 BackgroundTasks+Redis、iam P4 补全、proto 包名 `next_edu_cloud.<domain>.v1`、ActionState 方案 B 降级。所有 ⏳ 标记已更新为 ✅。
|
||||
|
||||
---
|
||||
|
||||
@@ -14,43 +14,39 @@
|
||||
|
||||
| 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) |
|
||||
| AiService | Chat | `ChatRequest{messages, model, temperature, user_id?, session_id?, data_scope?}` | `ChatResponse{content, model, usage, degraded, degraded_reason}` | 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 | ✅ 已实现 |
|
||||
| AiService | OptimizeExpression | `OptimizeExpressionRequest{text, context}` | `OptimizedExpression` | 50058 | ✅ 已实现 |
|
||||
| AiService | GenerateLessonPlan | `GenerateLessonPlanRequest{class_id, subject_id, topic, target_difficulty, question_count, user_id, data_scope}` | `LessonPlanResponse{workflow_id, status, estimated_completion_seconds, degraded, degraded_reason}` | 50058 | ✅ 已实现 |
|
||||
| AiService | GetLessonPlanStatus | `GetLessonPlanStatusRequest{workflow_id}` | `LessonPlanStatus{workflow_id, status, questions, error?, degraded, degraded_reason}` | 50058 | ✅ 已实现 |
|
||||
| AiService | ConfirmLessonPlan | `ConfirmLessonPlanRequest{workflow_id, modifications}` | `ConfirmResult{success, persisted_question_ids, error?}` | 50058 | ✅ 已实现 |
|
||||
|
||||
> **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。
|
||||
> **RPC 总数**:8 RPC(coord 裁决 ISSUE-03,备课工作流查询/确认也走 gRPC)。
|
||||
> **proto 现状**:ai.proto 已升级到 8 RPC 完整版(含 degraded/degraded_reason 字段)。
|
||||
> **proto package**:`next_edu_cloud.ai.v1`(coord G17 裁决保持现状,覆盖 project_rules §5)。
|
||||
|
||||
### 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)。
|
||||
> HTTP 保留作 api-gateway 直连降级 + SSE 流式。api-gateway 代理 `/api/v1/ai/*` → ai `/v1/ai/*`。
|
||||
|
||||
| Method | Path | 权限 | 响应 | 说明 | 状态 |
|
||||
| ------ | ------------------------------------------------- | ------------------------ | -------------------------------------- | --------------------------------- | ---- |
|
||||
| GET | `/healthz` | — | `{status, service}` | liveness | ✅ 已实现 |
|
||||
| GET | `/readyz` | — | `{status, llm_configured, providers, downstream_grpc, redis, kafka}` | readiness(多维度检查) | ⚠️ 待扩展 |
|
||||
| GET | `/readyz` | — | `{status, llm_configured, degraded, grpc_running, providers}` | 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>` | 学校用量(管理员) | ⏳ 待实现 |
|
||||
| POST | `/v1/ai/chat` | `ai:chat` | `ActionState<ChatData>` | LLM 聊天 | ✅ 已实现 |
|
||||
| POST | `/v1/ai/chat/stream` | `ai:chat` | SSE stream | 流式聊天 | ✅ 已实现 |
|
||||
| POST | `/v1/ai/generate/question` | `ai:question:generate` | `ActionState<GeneratedQuestionData>` | 生成题目 | ✅ 已实现 |
|
||||
| POST | `/v1/ai/generate/question/stream` | `ai:question:generate` | SSE stream(题目逐字生成) | 题目逐字流式 | ✅ 已实现 |
|
||||
| POST | `/v1/ai/optimize/expression` | `ai:expression:optimize` | `ActionState<OptimizedExpressionData>` | 优化表达 | ✅ 已实现 |
|
||||
| POST | `/v1/ai/lesson-plan/generate` | `ai:lesson:generate` | `ActionState<LessonPreparationData>` | 备课工作流启动 | ✅ 已实现 |
|
||||
| GET | `/v1/ai/lesson-plan/status/{workflow_id}` | — | `ActionState<WorkflowStatusData>` | 查询工作流状态 | ✅ 已实现 |
|
||||
| POST | `/v1/ai/lesson-plan/confirm/{workflow_id}` | `ai:lesson:confirm` | `ActionState<ConfirmResultData>` | 教师确认入库 | ✅ 已实现 |
|
||||
|
||||
> **响应信封**:所有响应必须为 ActionState(004 §11.5 强制,见 ISSUE-09)。当前 main.py 返回 `{success, data, degraded}` 顶层 degraded 字段,违反约束,P5 必须整改。
|
||||
> **路径演进**:当前实现是 `/ai/*`(无 /v1),目标态 `/ai/v1/*`(加版本前缀,便于未来破坏性变更)。
|
||||
> **响应信封**:所有响应使用 ActionState(004 §11.5 强制)。降级采用方案 B(总裁 §2.6):success=true + error=null + data 内 degraded=true。
|
||||
> **路径**:业务路由统一 `/v1/ai/*` 前缀。
|
||||
|
||||
### 1.3 GraphQL schema(如 BFF)
|
||||
|
||||
@@ -58,14 +54,14 @@
|
||||
|
||||
### 1.4 Kafka 事件发布
|
||||
|
||||
| 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}` |
|
||||
| Topic | Event | 触发时机 | 消费方 | Payload | 状态 |
|
||||
| ----- | ----- | -------- | ------ | ------- | ---- |
|
||||
| `edu.ai.usage` | `AIUsageEvent` | 每次 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}` | ✅ 已实现 |
|
||||
|
||||
> **topic 命名三义**:01/02 文档写 `edu.insight.ai.usage`、matrix.md 写 `edu.ai.usage`、原 contract 写 `edu.ai.usage.events`。ai12 建议采用 `edu.ai.usage`(最简短),待 coord 裁决(ISSUE-02)。
|
||||
> **topic 命名裁决**:ISSUE-02 已裁决,采用 `edu.ai.usage`(matrix.md §4 确认,最简短)。
|
||||
> **events.proto 已补全**:ISSUE-04 已裁决,`AIUsageEvent` message 已补入 [events.proto](../../../../packages/shared-proto/proto/events.proto),schema 见 [02-architecture-design.md §3.3](../../../../services/ai/docs/02-architecture-design.md)。
|
||||
> **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`,工作流监控)。
|
||||
> **长期可发布事件**(P6+ 评估,非 P5 范围):`AIContentGenerated`(topic `edu.ai.generated`,生成内容审计)、`AIFeedbackRecorded`(topic `edu.ai.feedback`,RLHF 数据)、`AIWorkflowEvent`(topic `edu.ai.workflow`,工作流监控)。
|
||||
|
||||
### 1.5 错误码前缀
|
||||
|
||||
@@ -139,24 +135,25 @@
|
||||
|
||||
### 3.1 我依赖的上游就绪标志
|
||||
|
||||
- [ ] 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,可降级)
|
||||
- [x] ai.proto 升级 v1 完整版(8 RPC + 字段扩展)—— coord(ISSUE-03 已裁决,已实现)
|
||||
- [x] events.proto 补 `AIUsageEvent` message —— coord(ISSUE-04 已裁决,已补全)
|
||||
- [x] ai 用量事件 topic 命名裁决 —— coord(ISSUE-02 已裁决,`edu.ai.usage`)
|
||||
- [ ] content gRPC 50054 启用(ai09)—— 知识点维度 + 题库检索 + 入库(全并行模式用 Mock)
|
||||
- [ ] data-ana gRPC 50055 启用(ai11,可选)—— 学生薄弱点(可降级独立运行,全并行模式用 Mock)
|
||||
- [ ] iam `GetEffectiveDataScope` RPC P4 补全(ai06 + coord,ISSUE-07,可降级,全并行模式用 Mock)
|
||||
- [ ] LLM Provider API key 配置(人类决策者)
|
||||
|
||||
### 3.2 我的就绪标志(供下游消费)
|
||||
|
||||
- [ ] ai gRPC 50058 启用(HealthService.Check 返回 SERVING)
|
||||
- [ ] AiService.Chat / StreamChat 可调用(含流式响应)
|
||||
- [ ] AiService.GenerateQuestion / StreamGenerateQuestion 可调用
|
||||
- [ ] AiService.GenerateLessonPlan 可调用(P5 补全)
|
||||
- [ ] AiService.OptimizeExpression 可调用
|
||||
- [ ] ai 用量事件 topic 可发布(供 data-ana 统计 AI 用量)
|
||||
- [x] ai gRPC 50058 启用(HealthService.Check 返回 SERVING)
|
||||
- [x] AiService.Chat / StreamChat 可调用(含流式响应)
|
||||
- [x] AiService.GenerateQuestion / StreamGenerateQuestion 可调用
|
||||
- [x] AiService.GenerateLessonPlan 可调用(P5 补全)
|
||||
- [x] AiService.GetLessonPlanStatus / ConfirmLessonPlan 可调用
|
||||
- [x] AiService.OptimizeExpression 可调用
|
||||
- [x] 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)。
|
||||
> **端口**:50058([port-allocation.md](../../../../infra/port-allocation.md) §3/§5/§7 权威源,ISSUE-01 已裁决,50058 让给 ai)。
|
||||
|
||||
---
|
||||
|
||||
@@ -187,17 +184,18 @@
|
||||
|
||||
---
|
||||
|
||||
## §5 契约待裁决项汇总
|
||||
## §5 契约裁决项汇总
|
||||
|
||||
> 以下字段待 coord 裁决后最终定稿,ai12 当前按建议方案先行实现。
|
||||
> 以下 9 个 ISSUE 全部已裁决(见 [objections/ai_issue.md](../objections/ai_issue.md) 与 [president-final-rulings.md](../../president-final-rulings.md)、[coord-final-decisions.md](../../coord-final-decisions.md)),P5 实现已按裁决结论落地。
|
||||
|
||||
| 待裁决项 | 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 |
|
||||
| 裁决项 | ISSUE | 裁决结论 | 裁决依据 | 影响章节 |
|
||||
| -------------------------------- | ------- | ------------------------------------------------------------------- | ------------------------------------------------ | -------------- |
|
||||
| ai gRPC 端口 | ISSUE-01 | **50058** | port-allocation.md §3/§5/§7 权威源 | §1.1 / §3.2 |
|
||||
| ai 用量事件 topic 命名 | ISSUE-02 | **`edu.ai.usage`** | matrix.md §4 | §1.4 |
|
||||
| ai.proto P5 目标 RPC 数 | ISSUE-03 | **8 RPC**(查询/确认走 gRPC) | 设计文档 §4.2 + coord B2 裁决 | §1.1 |
|
||||
| events.proto 补 AIUsageEvent | ISSUE-04 | **ai12 补全**,schema 见设计文档 §3.3 | ai12 已补入 events.proto | §1.4 |
|
||||
| contract 对齐设计文档 | ISSUE-05 | **ai12 自纠完成** | ai_contract.md 已重写对齐 | 全文 |
|
||||
| 备课工作流 Temporal | ISSUE-06 | **P5 用 BackgroundTasks + Redis(24h TTL),P6 评估 Temporal** | 总裁 §7.12 + coord A7 | §2.1(无影响) |
|
||||
| iam GetEffectiveDataScope P4 补全 | ISSUE-07 | **P4 补全,ai 用 Mock** | 全并行模式 | §2.1 |
|
||||
| proto package 命名(全局) | ISSUE-08 | **保持 `next_edu_cloud.<domain>.v1`** | coord G17 裁决覆盖 project_rules §5 | §1.1 |
|
||||
| 响应信封 ActionState 整改 | ISSUE-09 | **ActionState + 方案 B 降级**(success=true + error=null + degraded) | 总裁 §2.6 | §1.2 |
|
||||
|
||||
@@ -418,15 +418,30 @@
|
||||
| sync.RWMutex 重入死锁 | 持写锁(Lock)的 goroutine 不可再调用同结构体的 RLock 方法(Go RWMutex 非重入);CloseAll/Broadcast 内部计数改为内联遍历 |
|
||||
| httptest.Server.Close() 死锁 | 测试 handler 阻塞 ReadMessage 时 Close() 会死锁;用 done channel 模式:cleanup 先 close(done) → cli.Close() → srv.Close() |
|
||||
|
||||
### 2.9 ai-gateway(Python/FastAPI,P5)
|
||||
### 2.9 ai(Python/FastAPI,P5)
|
||||
|
||||
| 场景 | 技术/规则 |
|
||||
| ----------------- | --------------------------------------------------------------- |
|
||||
| LLM Provider 适配 | OpenAI 兼容 REST API(httpx 异步),不引入 openai SDK |
|
||||
| 降级模式 | API key 为空或调用失败时返回骨架响应,标记 degraded: true |
|
||||
| 流式 SSE | AI 网关 → BFF → 前端三层透传,BFF 不缓冲 |
|
||||
| 路由前缀 | 业务路由加 /ai 前缀(APIRouter prefix="/ai"),Gateway 代理 /ai |
|
||||
| dev_mode tracer | dev_mode=true 时跳过 OTel exporter 初始化 |
|
||||
| 场景 | 技术/规则 |
|
||||
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
||||
| LLM Provider 适配 | 4 适配器(OpenAI/Anthropic/Baichuan/Ollama)+ ProviderFailoverChain + CircuitBreaker(3 次失败 60s 熔断) |
|
||||
| 降级模式方案 B | success=true + error=null + data 内 degraded=true + degraded_reason(总裁 §2.6,非顶层 degraded 字段) |
|
||||
| ActionState 信封 | 所有 HTTP 响应统一 `{success, data, error:{code,message,details?,traceId?}}`(004 §11.5 强制) |
|
||||
| 路由前缀 | /v1/ai 前缀(APIRouter prefix="/v1/ai"),Gateway 代理 /api/v1/ai/* → /v1/ai/* |
|
||||
| gRPC server | grpc.aio 端口 50058,8 RPC + 3 interceptor(Logging/Auth/Error) |
|
||||
| 评估三道防线 | RuleValidator(JSON/字段/难度校验)→ LLMJudge(语义评分)→ QualityGate(综合决策门控) |
|
||||
| 备课工作流 | P5 用 asyncio.create_task + Redis 状态存储(24h TTL),P6+ 评估 Temporal |
|
||||
| 工作流状态机 | pending→analyzing→generating→pending_review→persisted/failed,生成失败重试最多 3 次 |
|
||||
| 限流三维度 | user 10/min + IP 30/min + school 100/min,Redis Lua 原子令牌桶,Redis 不可用降级放行 |
|
||||
| 用量记录 | Redis INCRBY 按 user/school/month 维度,35 天过期;Kafka 发布 AIUsageEvent 到 edu.ai.usage topic |
|
||||
| Kafka 派生数据豁免 Outbox | AIUsageEvent 为派生数据,004 §12.2 豁免 Outbox,直接 aiokafka producer(事务性 + 幂等) |
|
||||
| 安全层全本地 | PIIRedactor(5 类 PII 正则脱敏)+ InputSanitizer(prompt injection 检测)+ OutputModerator(5 类敏感内容审核) |
|
||||
| 六边形架构端口模式 | ContentClient/DataAnaClient/IamClient 均为抽象接口 + Mock + gRPC 实现,全并行模式用 Mock |
|
||||
| 权限校验 | PermissionGuard 5 权限点(ai:chat / ai:question:generate / ai:expression:optimize / ai:lesson:generate / confirm) |
|
||||
| dev_mode tracer | dev_mode=true 时跳过 OTel exporter 初始化 + 跳过权限校验 |
|
||||
| proto 包名 | 保持 `next_edu_cloud.<domain>.v1`(coord G17 裁决覆盖 project_rules §5) |
|
||||
| proto_gen 排除 ruff | pyproject.toml `[tool.ruff] exclude = ["src/ai/proto_gen"]`,自动生成文件不参与 lint |
|
||||
| ruff UP017 | `datetime.now(timezone.utc)` 改用 `datetime.now(datetime.UTC)` 别名(Python 3.12+) |
|
||||
| ruff SIM103/SIM110 | `if x: return False; return True` 改 `return not x`;for 循环改 `all()` 表达式 |
|
||||
| PowerShell 不支持 && | RunCommand 用 cwd 参数指定工作目录,不用 `cd ... && uv run` |
|
||||
|
||||
### 2.10 shared-proto(契约包)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user