Files
Edu/services/ai/docs/nextstep.md

13 KiB
Raw Blame History

AI 模块 nextstep

模块aiai12 负责)| gRPC 50058 | HTTP 3008 | Python (FastAPI) 更新时间2026-07-13


§1 当前状态

P5 实现已完成。8 RPC 全部实现gRPC 拦截器已修复为异步兼容,下游 gRPC 客户端已从 Mock 切换为真实 gRPC 调用。377 个测试通过,覆盖率 88%。

已完成

  • ai.proto 8 RPC 完整版(含 GetLessonPlanStatus / ConfirmLessonPlan
  • events.proto AIUsageEvent 补全
  • gRPC server 端口 50058异步拦截器Logging + Auth + Error
  • HTTP 10 端点(/v1/ai 前缀ActionState 信封)
  • LLM Provider FailoverChainOpenAI / Anthropic / 百川 / Ollama + 熔断 + 故障切换)
  • 评估三道防线RuleValidator + LLMJudge + QualityGate
  • 用量记录Redis+ Kafka 事件发布 + 配额管理
  • 安全层PII + 输入清洗 + 输出审核)
  • 下游 gRPC 客户端真实调用content / data-ana / iam不再使用 Mock
  • 备课工作流4 步编排 + Redis 状态存储)
  • Dockerfile 多阶段构建 + docker-compose.deploy.yml 环境变量补全

§2 上游依赖ai 依赖谁)

§2.1 gRPC 同步调用

被调用方 端口 Service.RPC 用途 状态
content (ai09) 50054 KnowledgeGraphService.GetPrerequisites 查询知识点前置依赖(备课工作流 Step 2 已实现
content (ai09) 50054 KnowledgeGraphService.GetLearningPath 查询学习路径(备课工作流 Step 2 已实现
content (ai09) 50054 QuestionService.BatchCreateQuestions 批量创建题目入库(备课工作流 Confirm 已实现
data-ana (ai11) 50055 AnalyticsService.GetClassPerformance 查询班级学情(备课工作流 Step 1 已实现
data-ana (ai11) 50055 AnalyticsService.GetStudentWeakness 查询学生薄弱点(备课工作流 Step 1 已实现
data-ana (ai11) 50055 AnalyticsService.GetLearningTrend 查询学习趋势(备课工作流 Step 1 已实现
iam (ai06) 50052 IamService.GetEffectiveDataScope 查询用户数据范围(多租户配额) 已实现

§2.2 基础设施依赖

依赖 用途 状态
Redis 限流(三维度令牌桶)+ 工作流状态存储 + 用量记录 已实现
Kafka AIUsageEvent 事件发布topic: edu.ai.usage 已实现
OpenTelemetry Collector 链路追踪 + 指标导出 已实现

§2.3 LLM Provider 依赖

Provider 环境变量 用途 状态
OpenAI OPENAI_API_KEY / OPENAI_BASE_URL 首选 LLM 已实现
Anthropic ANTHROPIC_API_KEY Failover 第二 已实现
百川 BAICHUAN_API_KEY Failover 第三 已实现
Ollama OLLAMA_BASE_URL 本地降级 已实现

未配置任何 API key 时进入降级模式,返回 degraded=true + 空内容。


§3 下游就绪信号(谁依赖 ai

§3.1 teacher-bff (ai03) — P1

就绪标志 消费方式 状态
AiService.Chat / StreamChat 可调用 gRPC 50058 + SSE 3008 已就绪
AiService.GenerateQuestion 可调用 gRPC 50058 已就绪
AiService.GenerateLessonPlan 可调用 gRPC 50058 已就绪
AiService.GetLessonPlanStatus / ConfirmLessonPlan 可调用 gRPC 50058 已就绪
AiService.OptimizeExpression 可调用 gRPC 50058 已就绪

teacher-bff 通过 AI_GRPC_TARGET=ai:50058 连接,留空时走降级模式 B。

§3.2 student-bff (ai04) — P1

就绪标志 消费方式 状态
AiService.StreamChat 可调用(流式对话) gRPC 50058 已就绪

student-bff 需要的 StreamAIChat 对应 ai 的 StreamChat RPC。

§3.3 api-gateway (ai01) — P2

就绪标志 消费方式 状态
ai HTTP 3008 /healthz 可达 HTTP 反向代理 /api/v1/ai/*ai:3008 已就绪

§3.4 data-ana (ai11) — P2

就绪标志 消费方式 状态
Kafka topic edu.ai.usage 有事件发布 CDC 消费者 → ClickHouse ai_usage_log 已就绪

§3.5 parent-bff / push-gateway — 无直接依赖

parent-bff 和 push-gateway 不直接依赖 ai 模块。


§4 联调待办

# 联调项 联调方 阻塞条件 状态
1 ai gRPC + teacher-bff SSE 联调 teacher-bff (ai03) ai 服务容器启动 ai 侧就绪(待 teacher-bff 接入)
2 ai gRPC StreamChat + student-bff 联调 student-bff (ai04) ai 服务容器启动 ai 侧就绪(待 student-bff 接入)
3 ai /healthz + api-gateway 联调 api-gateway (ai01) ai 服务容器启动 ai 侧就绪(待 api-gateway 路由)
4 AIUsageEvent + data-ana CDC 消费联调 data-ana (ai11) ai Kafka 生产 + data-ana 消费 ai 生产就绪(待 data-ana 消费)
5 ai ↔ content gRPC 联调 content (ai09) 双方容器启动 ai 客户端就绪(待 content 启动)
6 ai ↔ data-ana gRPC 联调 data-ana (ai11) 双方容器启动 ai 客户端就绪(待 data-ana 启动)
7 ai ↔ iam gRPC 联调 iam (ai06) 双方容器启动 ai 客户端就绪(待 iam 启动)

ai 侧 Docker 容器已启动并验证通过,下游 gRPC 客户端连接循环已在 lifespan 中执行成功。剩余联调项等待对端模块接入。


§5 Docker 测试环境

§5.1 构建与启动

# 构建镜像
docker compose -f infra/docker-compose.deploy.yml build ai

# 启动 ai 服务(依赖 Redis + Kafka + 基础设施)
docker compose -f infra/docker-compose.yml up -d redis kafka
docker compose -f infra/docker-compose.deploy.yml up -d ai

§5.2 健康检查

curl http://localhost:3008/healthz   # {"status":"ok","service":"ai"}
curl http://localhost:3008/readyz    # {"status":"ok","llm_configured":...,"grpc_running":true}

§5.3 环境变量docker-compose.deploy.yml 已配置)

变量 默认值 说明
HTTP_PORT 3008 HTTP 端口
GRPC_PORT 50058 gRPC 端口
REDIS_URL redis://redis:6379/0 Redis 连接
KAFKA_BOOTSTRAP_SERVERS kafka:29092 Kafka 连接(容器内)
CONTENT_GRPC_ENDPOINT content:50054 content gRPC 端点
DATA_ANA_GRPC_ENDPOINT data-ana:50055 data-ana gRPC 端点
IAM_GRPC_ENDPOINT iam:50052 iam gRPC 端点
OPENAI_API_KEY (空) OpenAI API Key
DEV_MODE true 开发模式(本地测试)

§5.4 本地 Docker 测试结果2026-07-13

测试环境infra/docker-compose.test.yml + edu-full_default 外部网络

# 验证项 结果 证据
1 Docker 镜像构建 通过 多阶段构建成功builder + runtimeDockerfile curl 版本 pinning 已移除
2 容器启动 通过 ai 服务容器成功启动并加入 edu-full_default 网络
3 下游 gRPC 客户端连接 通过 日志:grpc_client_connected endpoint=content:50054 / data-ana:50055 / iam:50052
4 Redis 连接 通过 日志:限流器 + 工作流状态存储初始化成功
5 Kafka producer 启动 通过 日志:kafka_producer_started bootstrap_servers=kafka:29092 topic=edu.ai.usage
6 gRPC server 启动 通过 日志:grpc_server_started port=50058,端口 50058 监听成功
7 gRPC 拦截器加载 通过 异步拦截器Logging + Auth + Error正确加载无 ValueError 降级警告
8 HTTP /healthz 通过 curl http://localhost:3008/healthz{"status":"ok","service":"ai"}
9 HTTP /readyz 通过 curl http://localhost:3008/readyz{"grpc_running":true,...}
10 LLM 降级模式 预期 未配置 API keyllm_configured:false, degraded:true(预期行为)
11 单元测试 通过 377 个测试通过,覆盖率 88%
12 ruff lint 通过 零警告

关键修复记录

问题 根因 修复
gRPC 拦截器 ValueError 同步 grpc.ServerInterceptorgrpc.aio.server() 不兼容,服务器静默降级为无拦截器 重写所有 3 个拦截器继承 grpc.aio.ServerInterceptorintercept_service 改为 async
Dockerfile 构建失败 curl=7.88.* 版本 pinning 在 Debian Trixie 中不存在 移除版本 pinning改为 curl
端口 50058 占用 本地 Python 进程占用 Stop-Process -Id <PID> -Force
proto_gen 导入失败 生成的 *_pb2_grpc.py 使用绝对导入 proto_gen/__init__.py 添加 sys.path.insert(0, _PB_DIR)
类型注解 AttributeError grpc.aio.HandlerCallDetails 不存在 类型注解改用 grpc.HandlerCallDetailsgrpc.RpcMethodHandler(同步版本,用于注解)

§6 P6+ 待评估

# 待评估项 说明
1 Temporal 引入评估 备课工作流 P5 用 BackgroundTasks + RedisP6 评估是否引入 Temporal
2 content 事件订阅 P5 不订阅 content 事件P6+ 评估是否需要知识点变更事件驱动
3 MockLLMProvider 02 文档提到但未实现,测试环境用 httpx Mock 替代