Files
label_ai_service/specs/001-ai-service-requirements/research.md

77 lines
4.5 KiB
Markdown
Raw Normal View 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: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 仅作决策存档。