Files
label_ai_service/specs/001-ai-service-requirements/research.md
wh 092f9dbfc5 docs: add speckit planning artifacts for 001-ai-service-requirements
Generated plan.md, research.md, data-model.md, contracts/api.md,
quickstart.md, and CLAUDE.md agent context via /speckit-plan.
2026-04-10 14:58:13 +08:00

4.5 KiB
Raw Blame History

Research: AI 服务实现方案

Branch: 001-ai-service-requirements | Date: 2026-04-10
Status: 完成(所有决策已在设计阶段确定,无待研究项)


决策记录

D-001: 异步框架选型

Decision: FastAPI + uvicorn
Rationale: 原生 async/await 支持、Pydantic 自动校验、自动生成 Swagger 文档、Python 生态系中性能和开发效率的最优权衡。
Alternatives considered: Django过重、Flask无原生异步、aiohttp无自动文档和类型校验


D-002: ZhipuAI SDK 调用方式

Decision: 同步 SDK 通过 asyncio.get_event_loop().run_in_executor(None, ...) 在线程池中调用
Rationale: ZhipuAI 官方 SDK 为同步阻塞设计,直接在 async 函数中调用会阻塞事件循环。run_in_executor 将阻塞调用卸载到线程池,保持 FastAPI 事件循环响应能力。
Alternatives considered: 使用 asyncio.to_thread()Python 3.9+ 语法糖,等效实现,选择 run_in_executor 保持向后兼容性);使用 httpx 直接调用 ZhipuAI HTTP API绕过 SDK 但增加维护负担)


D-003: 图像 QA 生成的图片传输方式

Decision: base64 编码嵌入消息体(data:image/jpeg;base64,...
Rationale: RustFS 部署在 Docker 内网endpoint: http://rustfs:9000presigned URL 指向内网地址,云端 GLM-4V 无法访问。base64 编码将图片内容直接内联到 API 请求,不依赖网络可达性。
Alternatives considered: presigned URL不可行内网地址云端不可达公网 RustFS 暴露(增加安全风险)


D-004: 视频长任务处理机制

Decision: FastAPI BackgroundTasks + HTTP 回调通知 Java 后端
Rationale: 视频处理耗时不可控几秒到几分钟同步等待会超时。BackgroundTasks 无需额外中间件Redis/Celery部署简单任务状态通过回调接口由 Java 后端管理符合整体架构风格。并发量有限≤5个同时任务BackgroundTasks 完全够用。
Alternatives considered: Celery需 Redis broker引入额外运维负担asyncio.create_task进程重启会丢失任务


D-005: 分层配置方案

Decision: config.yaml稳定非敏感配置+ .env密钥和环境差异项环境变量优先级高于 YAML
Rationale: YAML 提供结构化可读性,适合 git 追踪非敏感配置变更;.env 格式为 Docker env_file 原生支持;环境变量覆盖机制使容器部署时无需重建镜像即可切换配置。
Alternatives considered: 纯 .env 文件(缺乏结构化,复杂配置难维护);数据库存储配置(过重)


D-006: 视频大文件 OOM 防护

Decision: 在视频路由层(接受请求后、启动后台任务前)通过 storage.get_object_size() 查询文件大小,超限返回 HTTP 400
Rationale: 在下载前拒绝,避免实际 OOM大小限制通过 config.yaml + MAX_VIDEO_SIZE_MB 环境变量运行时可配置,无需重建镜像;实现简单,无需引入流式下载的新抽象。
Alternatives considered: 流式下载Completeness: 9/10但 YAGNI当前规模不需要不限制Completeness: 4/10有 OOM 风险)


D-007: 视频关键帧检测算法

Decision: 帧差分frame difference近似检测计算当前帧与前帧灰度图的像素差均值差值超过阈值默认 30.0)判定为场景切换
Rationale: OpenCV 无原生 I 帧检测 APICAP_PROP_POS_FRAMES 是帧定位,非 I 帧标识)。帧差分简单有效,对场景切换检测准确,且无需视频解码器底层支持。
Alternatives considered: 基于编码信息的 I 帧检测(需 FFmpeg 支持,引入额外依赖);固定间隔(不够智能,不适合关键帧模式)


D-008: 测试策略

Decision: pytest + pytest-asyncioService 层和 Router 层分别测试,使用 AsyncMock 模拟外部依赖
Rationale: Service 层测试业务逻辑,不依赖 HTTPRouter 层使用 TestClient 测试完整请求流程。视频 service 测试使用真实小视频文件OpenCV VideoWriter 生成),验证帧提取逻辑正确性。
Alternatives considered: 仅集成测试(需要真实 RustFS 和 ZhipuAICI 成本高);全部单元测试(无法覆盖路由和异常处理器集成)


无待解决项

所有 NEEDS CLARIFICATION 均已在设计阶段通过用户确认或合理默认值解决。本 research.md 仅作决策存档。