# AI 网关服务 > 版本:1.0(P5 完整实现) > 端口:HTTP 3008 + gRPC 50058 > 定位:D6 智能洞察领域 · 生成子域(Python/FastAPI,严格无状态) ## 职责 统一封装 LLM 调用(多模型路由 + 故障切换 + 熔断 + 限流 + 成本控制),提供: - **聊天**:非流式 + SSE 流式 - **题目生成**:非流式 + 流式 + 评估三道防线(RuleValidator + LLMJudge + QualityGate) - **表达优化**:文字清晰度/简洁度/语气优化 - **备课工作流**:4 步编排(分析学情 → 推荐知识点 → 生成题目 → 教师审核入库) 通过 gRPC 查询 content 题库与 data-ana 学情数据。通过 Kafka 发布 AIUsageEvent 供 data-ana 统计。 ## 技术栈 - Python 3.12 + FastAPI 0.115 - Pydantic 2 + pydantic-settings(12-factor 配置) - grpc.aio(gRPC server 8 RPC + client 拦截器) - aiokafka(用量事件发布,事务性 + 幂等,派生数据豁免 Outbox) - Jinja2 + YAML(Prompt 模板渲染) - redis(限流令牌桶 + 用量记录 + 工作流状态存储) - OpenTelemetry(HTTP + gRPC 链路追踪) - prometheus-client + structlog(指标 + 结构化日志) ## 架构分层 ``` HTTP 端点(/v1/ai 前缀,ActionState 信封) ↓ PermissionGuard(权限校验)→ RateLimiter(三维度令牌桶) ↓ Service 层(ChatService / QuestionService / ExpressionService / LessonPlanWorkflowService) ↓ LLM ProviderFailoverChain(4 适配器 + CircuitBreaker) ↓ LLM Provider(OpenAI / Anthropic / Baichuan / LocalOllama) gRPC server(端口 50058,8 RPC,interceptor 链) ↓ AiServicer(proto ↔ domain 模型转换) ↓ Service 层(同 HTTP) 备课工作流:FastAPI BackgroundTasks + Redis 状态存储(24h TTL) 安全层:PIIRedactor + InputSanitizer + OutputModerator 用量:UsageRecorder(Redis)→ KafkaProducer → edu.ai.usage topic ``` ## 开发 ```bash # 安装依赖 uv sync # 启动开发服务(dev_mode=true 跳过 OTel exporter) DEV_MODE=true uv run uvicorn src.ai.main:app --reload --port 3008 # Lint uv run ruff check src/ # 测试 uv run pytest ``` ## HTTP API | 方法 | 路径 | 权限 | 说明 | |------|------|------|------| | GET | /healthz | — | liveness | | GET | /readyz | — | readiness(含 LLM/gRPC/Provider 状态) | | GET | /metrics | — | Prometheus 指标 | | POST | /v1/ai/chat | ai:chat | 非流式聊天 | | POST | /v1/ai/chat/stream | ai:chat | 流式聊天(SSE) | | POST | /v1/ai/generate/question | ai:question:generate | 生成题目 | | POST | /v1/ai/generate/question/stream | ai:question:generate | 流式生成题目(SSE) | | POST | /v1/ai/optimize/expression | ai:expression:optimize | 优化表达 | | POST | /v1/ai/lesson-plan/generate | ai:lesson:generate | 启动备课工作流 | | GET | /v1/ai/lesson-plan/status/{workflow_id} | — | 查询工作流状态 | | POST | /v1/ai/lesson-plan/confirm/{workflow_id} | ai:lesson:confirm | 教师确认入库 | 所有业务响应统一使用 ActionState 信封:`{success, data, error:{code, message, details?, traceId?}}` 降级采用方案 B(总裁裁决 §2.6):`success=true + error=null + data 内 degraded=true + degraded_reason` ## gRPC API(端口 50058,8 RPC) | RPC | 请求 | 响应 | |-----|------|------| | Chat | ChatRequest | ChatResponse | | StreamChat | ChatRequest | stream ChatChunk | | GenerateQuestion | GenerateQuestionRequest | GeneratedQuestion | | StreamGenerateQuestion | GenerateQuestionRequest | stream GeneratedQuestionChunk | | OptimizeExpression | OptimizeExpressionRequest | OptimizedExpression | | GenerateLessonPlan | GenerateLessonPlanRequest | LessonPlanResponse | | GetLessonPlanStatus | GetLessonPlanStatusRequest | LessonPlanStatus | | ConfirmLessonPlan | ConfirmLessonPlanRequest | ConfirmResult | ## 环境变量 | 变量 | 默认值 | 说明 | |------|--------|------| | http_port | 3008 | HTTP 端口 | | grpc_port | 50058 | gRPC 端口 | | dev_mode | false | 开发模式(跳过 OTel + 权限校验) | | openai_api_key | — | OpenAI API 密钥 | | anthropic_api_key | — | Anthropic API 密钥 | | baichuan_api_key | — | 百川 API 密钥 | | ollama_base_url | — | 本地 Ollama 地址 | | llm_provider_priority | openai,anthropic,baichuan,local_ollama | Provider 故障切换顺序 | | redis_url | redis://localhost:6379/0 | Redis 连接 | | kafka_bootstrap_servers | localhost:9092 | Kafka 连接 | | kafka_ai_usage_topic | edu.ai.usage | 用量事件 topic | | otel_endpoint | http://localhost:4318 | OpenTelemetry OTLP 端点 | ## 限流(三维度) | 维度 | 限制 | 算法 | |------|------|------| | user | 10 req/min | Redis Lua 令牌桶 | | IP | 30 req/min | Redis Lua 令牌桶 | | school | 100 req/min | Redis Lua 令牌桶 | Redis 不可用时降级放行(记录警告)。 ## 错误码 前缀 `AI_*`,完整 21 个错误码见 [02-architecture-design.md §6.2](docs/02-architecture-design.md)。