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

77 lines
4.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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:9000`presigned 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 帧检测 API`CAP_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 仅作决策存档。