feat: add AI service requirements spec (001-ai-service-requirements)
- 8 user stories (P1-P3): text triple extraction, image quadruple extraction, video frame extraction, video-to-text, QA generation (text/image), finetune management, health check - 18 functional requirements covering all 8 API endpoints - 9 success criteria with measurable metrics - Technical environment section: Python 3.12.13, FastAPI, conda label env - Quality checklist: all items pass
This commit is contained in:
258
specs/001-ai-service-requirements/spec.md
Normal file
258
specs/001-ai-service-requirements/spec.md
Normal file
@@ -0,0 +1,258 @@
|
||||
# Feature Specification: AI 服务需求文档
|
||||
|
||||
**Feature Branch**: `001-ai-service-requirements`
|
||||
**Created**: 2026-04-10
|
||||
**Status**: Draft
|
||||
**Input**: User description: "@docs/superpowers/specs/2026-04-10-ai-service-design.md 根据设计文档完成需求文档"
|
||||
|
||||
---
|
||||
|
||||
## 概述
|
||||
|
||||
知识图谱智能标注平台需要一个独立的 AI 计算服务,接收 Java 后端的调用,完成文档结构化提取、图像分析、视频预处理、训练数据生成和模型微调管理等智能化任务,将大模型能力嵌入标注工作流,大幅降低人工标注成本。
|
||||
|
||||
---
|
||||
|
||||
## User Scenarios & Testing *(mandatory)*
|
||||
|
||||
### User Story 1 - ADMIN 从文档中提取知识三元组 (Priority: P1)
|
||||
|
||||
ADMIN 在标注平台上选择一份已上传的文本文件(TXT、PDF 或 Word 文档),触发 AI 辅助提取。AI 服务从存储系统中读取该文档,分析内容,识别其中的主谓宾知识关系(三元组),并为每个三元组标注原文出处片段和字符偏移位置,返回结构化结果供标注员审核确认。
|
||||
|
||||
**Why this priority**: 文本三元组提取是平台文本标注流水线的核心入口,所有文本类标注任务都依赖此能力。无此功能,平台的主要价值无法实现。
|
||||
|
||||
**Independent Test**: 向 AI 服务发送一个包含已知知识点的测试文档路径,验证返回结果包含正确的主语/谓语/宾语和对应的原文位置信息,即可独立验证此功能完整运行。
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** 存储系统中存有一份 TXT 格式文档,**When** AI 服务收到该文档路径和提取请求,**Then** 返回包含至少一条三元组的结果,每条含 subject、predicate、object、原文片段和字符偏移。
|
||||
2. **Given** 存储系统中存有一份 PDF 格式文档,**When** AI 服务收到提取请求,**Then** 正确解析 PDF 内容并返回三元组结果。
|
||||
3. **Given** 存储系统中存有一份 Word(.docx)格式文档,**When** AI 服务收到提取请求,**Then** 正确解析文档内容并返回三元组结果。
|
||||
4. **Given** 请求包含不支持的文件格式(如 .xlsx),**When** AI 服务收到请求,**Then** 返回明确的格式不支持错误,不崩溃。
|
||||
5. **Given** 存储系统不可达,**When** AI 服务尝试下载文件,**Then** 返回存储故障错误,而非通用服务器错误。
|
||||
|
||||
---
|
||||
|
||||
### User Story 2 - ADMIN 从图片中提取知识四元组并自动裁剪 (Priority: P1)
|
||||
|
||||
ADMIN 在标注平台选择一张已上传的图片,触发 AI 辅助提取。AI 服务读取该图片,通过多模态大模型分析图像内容,识别图中的知识实体关系(四元组:主体、关系、客体、修饰信息),同时给出每个知识点在图像中的位置框(bbox 坐标),并自动将对应区域裁剪保存,供标注员对照审核。
|
||||
|
||||
**Why this priority**: 图像四元组提取是图片标注流水线的核心入口,与文本三元组提取并列为平台两大主流水线的起点。
|
||||
|
||||
**Independent Test**: 向 AI 服务发送一张包含可识别对象关系的测试图片路径,验证返回结果包含四元组信息和裁剪图的存储路径,即可独立验证此功能完整运行。
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** 存储系统中存有一张图片,**When** AI 服务收到该图片路径和提取请求,**Then** 返回包含至少一条四元组的结果,每条含 subject、predicate、object、qualifier 和 bbox 坐标。
|
||||
2. **Given** AI 服务成功提取四元组,**When** 处理完成,**Then** 每个四元组对应的图像区域已自动裁剪并上传至存储,响应中包含裁剪图的存储路径。
|
||||
3. **Given** bbox 坐标超出图像边界,**When** 裁剪时,**Then** 自动截断至图像有效区域,不报错。
|
||||
4. **Given** 大模型返回格式异常(非 JSON),**When** 解析响应,**Then** 返回解析失败错误,不返回部分结果。
|
||||
|
||||
---
|
||||
|
||||
### User Story 3 - ADMIN 对视频进行帧提取(帧模式预处理) (Priority: P2)
|
||||
|
||||
ADMIN 在标注平台选择一段已上传的视频,选择"帧提取"模式(按固定间隔或关键帧),触发 AI 服务处理。AI 服务在后台异步完成帧提取,将每一帧图片上传至存储,处理完成后主动通知 Java 后端,后端随即为每一帧创建图片标注任务,进入图片标注流程。
|
||||
|
||||
**Why this priority**: 视频帧提取是视频进入图片标注流水线的预处理步骤,依赖图片提取流水线(P1)已就绪。
|
||||
|
||||
**Independent Test**: 向 AI 服务发送一个测试视频的存储路径和 job_id,服务立即返回 202 Accepted,稍后验证回调接口收到含帧路径列表的成功通知,即可独立验证。
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** 存储系统中存有一段视频(大小在限制内),**When** AI 服务收到帧提取请求(interval 模式),**Then** 立即返回 202 Accepted 和 job_id,不等待处理完成。
|
||||
2. **Given** 帧提取任务在后台成功完成,**When** 处理完成,**Then** AI 服务向 Java 后端发送回调,包含 job_id、status=SUCCESS 和帧图存储路径列表。
|
||||
3. **Given** keyframe 模式,**When** AI 服务处理视频,**Then** 仅提取画面发生显著变化的帧,而非固定间隔。
|
||||
4. **Given** 视频文件大小超过系统上限(默认 200MB,可配置),**When** 收到请求,**Then** 立即返回 400 错误,不启动后台任务。
|
||||
5. **Given** 帧提取过程中发生错误,**When** 任务失败,**Then** AI 服务仍向 Java 后端发送回调,status=FAILED,包含错误描述。
|
||||
|
||||
---
|
||||
|
||||
### User Story 4 - ADMIN 将视频片段转换为文字描述(片段模式预处理) (Priority: P2)
|
||||
|
||||
ADMIN 在标注平台选择一段已上传视频的时间段,触发"视频转文本"预处理。AI 服务在后台均匀采样该时间段的视频帧,用多模态大模型理解视频内容,生成结构化文字描述,将描述文本上传存储,完成后通知 Java 后端,后端将其创建为新的文本类原始资料,进入文本标注流程。
|
||||
|
||||
**Why this priority**: 视频转文本预处理使视频内容能够通过文本标注流水线处理,扩展了平台的数据来源范围。
|
||||
|
||||
**Independent Test**: 向 AI 服务发送测试视频路径、时间段和 job_id,验证回调收到 output_path 指向一个可读的文字描述文件,即可独立验证。
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** 存储系统中存有一段视频(大小在限制内),**When** AI 服务收到视频转文本请求,**Then** 立即返回 202 Accepted 和 job_id。
|
||||
2. **Given** 视频转文本任务在后台成功完成,**When** 处理完成,**Then** AI 服务向 Java 后端发送回调,包含 job_id、status=SUCCESS 和文字描述的存储路径。
|
||||
3. **Given** 请求指定了起止时间段(start_sec、end_sec),**When** 处理视频,**Then** 仅分析该时间段内的内容,不处理其他片段。
|
||||
4. **Given** 视频文件大小超过上限,**When** 收到请求,**Then** 立即返回 400 错误。
|
||||
5. **Given** 大模型调用失败,**When** 任务异常,**Then** 回调 status=FAILED,包含错误描述。
|
||||
|
||||
---
|
||||
|
||||
### User Story 5 - 系统自动为已审批三元组生成候选问答对 (Priority: P2)
|
||||
|
||||
标注员提交的文本三元组经审批员审批通过后,系统自动调用 AI 服务,将三元组列表和对应原文片段批量输入大模型,生成符合微调格式的候选问答对,作为后续训练数据的来源。
|
||||
|
||||
**Why this priority**: 问答对生成是平台训练数据产出流程的关键环节,依赖三元组提取(P1)已完成并通过审批。
|
||||
|
||||
**Independent Test**: 向 AI 服务发送一组测试三元组(含原文片段),验证返回包含可读、合理的问答对列表,即可独立验证。
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** 一组已审批的文本三元组,**When** AI 服务收到文本 QA 生成请求,**Then** 返回包含 question 和 answer 的问答对列表,每个三元组至少对应一个问答对。
|
||||
2. **Given** 大模型返回合法 JSON,**When** 解析响应,**Then** 正确提取每对问答并返回。
|
||||
3. **Given** 大模型返回格式异常,**When** 解析响应,**Then** 返回解析失败错误。
|
||||
4. **Given** 大模型服务不可用,**When** 调用失败,**Then** 返回明确的服务不可用错误。
|
||||
|
||||
---
|
||||
|
||||
### User Story 6 - 系统自动为已审批四元组生成候选图文问答对 (Priority: P2)
|
||||
|
||||
图像四元组经审批通过后,系统自动调用 AI 服务,将四元组信息与对应裁剪图一起输入多模态大模型,生成图文问答对,用于后续图像类训练数据集。
|
||||
|
||||
**Why this priority**: 图像 QA 生成是图片标注流水线产出训练数据的最终步骤,优先级与文本 QA 生成(P2)相同。
|
||||
|
||||
**Independent Test**: 向 AI 服务发送一组四元组(含裁剪图存储路径),验证返回的问答对引用了图片路径,即可独立验证。
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** 一组已审批的图像四元组(含裁剪图路径),**When** AI 服务收到图像 QA 生成请求,**Then** 返回包含 question、answer 和 image_path 的问答对列表。
|
||||
2. **Given** 裁剪图存储路径有效,**When** AI 服务处理,**Then** 自动获取图片内容并结合四元组信息生成问答,无需调用方额外传输图片数据。
|
||||
3. **Given** 裁剪图无法从存储获取,**When** 处理请求,**Then** 返回存储错误,不返回空结果。
|
||||
|
||||
---
|
||||
|
||||
### User Story 7 - ADMIN 提交微调任务并查询进度 (Priority: P3)
|
||||
|
||||
ADMIN 在标注平台完成训练数据集导出后,选择提交大模型微调任务。平台调用 AI 服务提交微调请求(包含训练数据文件地址、基础模型和超参数),获取微调任务 ID。此后,ADMIN 可随时查询该任务的运行状态(进行中/成功/失败)和完成进度。
|
||||
|
||||
**Why this priority**: 微调任务管理是平台最终目标(产出定制化模型)的关键步骤,但需要前置数据准备流程全部完成,故列为 P3。
|
||||
|
||||
**Independent Test**: 向 AI 服务发送微调请求,获取 job_id,再调用状态查询接口,验证能正确返回当前状态,即可独立验证。
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** 训练数据 JSONL 文件已在存储中准备就绪,**When** AI 服务收到微调提交请求(含文件地址、基础模型、超参数),**Then** 返回微调任务 ID。
|
||||
2. **Given** 微调任务已提交,**When** 查询任务状态,**Then** 返回 job_id、当前状态(RUNNING/SUCCESS/FAILED)和进度百分比。
|
||||
3. **Given** 任务处于运行中,**When** 多次查询状态,**Then** 每次均返回最新状态,不缓存旧状态。
|
||||
4. **Given** 传入不存在的 job_id 查询状态,**When** 处理请求,**Then** 返回明确错误,不崩溃。
|
||||
|
||||
---
|
||||
|
||||
### User Story 8 - 运维监控服务健康状态 (Priority: P3)
|
||||
|
||||
运维人员或监控系统定期探测 AI 服务的健康状态,判断服务是否正常运行,以便在异常时及时告警或自动重启。
|
||||
|
||||
**Why this priority**: 健康检查是服务稳定运行的基础保障,但不属于业务功能,列为 P3。
|
||||
|
||||
**Independent Test**: 对健康检查接口发起 HTTP GET 请求,验证收到表示正常的响应,即可独立验证。
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** AI 服务正常运行,**When** 任何系统对健康检查接口发起请求,**Then** 立即返回服务正常的响应,响应时间不超过 1 秒。
|
||||
2. **Given** 容器运行中,**When** 容器编排系统定期发起健康探测,**Then** 通过探测的容器才被标记为可用状态并接收流量。
|
||||
|
||||
---
|
||||
|
||||
### Edge Cases
|
||||
|
||||
- 文件存在于存储系统但内容损坏(如 PDF 页面为空)时,如何处理?→ 返回解析结果为空,不报错,日志记录警告。
|
||||
- 视频帧提取结果为零帧(如视频文件损坏或间隔过大)时,如何处理?→ 回调 SUCCESS,返回空帧列表,Java 后端决定是否重试。
|
||||
- 大模型返回的三元组/四元组超过合理数量(如数百条)时,如何处理?→ 全量返回,由 Java 后端或标注员筛选,AI 服务不做截断。
|
||||
- 多个视频任务并发执行时,是否会互相影响?→ 每个任务独立使用临时文件,处理完成后清理,互不干扰。
|
||||
- 视频文件大小恰好等于上限时,如何处理?→ 视为超限,拒绝处理,避免边界情况下的内存压力。
|
||||
- 大模型以 Markdown 代码块格式(\`\`\`json ... \`\`\`)返回 JSON 时,如何处理?→ 自动提取代码块内的 JSON 内容,兼容此格式。
|
||||
|
||||
---
|
||||
|
||||
## Requirements *(mandatory)*
|
||||
|
||||
### Functional Requirements
|
||||
|
||||
**文本处理**
|
||||
|
||||
- **FR-001**: 系统 MUST 支持从 TXT、PDF、DOCX 三种格式的文档中提取知识三元组(subject / predicate / object),并为每条三元组提供原文出处片段和字符偏移位置。
|
||||
- **FR-002**: 系统 MUST 在文件格式不受支持时,返回明确的格式不支持错误(HTTP 400),拒绝处理请求。
|
||||
|
||||
**图像处理**
|
||||
|
||||
- **FR-003**: 系统 MUST 支持从图片中提取知识四元组(subject / predicate / object / qualifier),并提供每个知识点在图像中的位置框(bbox:x, y, w, h 像素坐标)。
|
||||
- **FR-004**: 系统 MUST 在返回四元组结果时,自动将每个知识点对应的图像区域裁剪并保存至存储,响应中包含裁剪图的存储路径。
|
||||
|
||||
**视频处理**
|
||||
|
||||
- **FR-005**: 系统 MUST 支持视频帧提取,提供两种模式:固定间隔模式(按帧数间隔)和关键帧模式(场景切换时提取)。
|
||||
- **FR-006**: 系统 MUST 以异步方式处理视频任务,接受请求后立即返回接受确认(HTTP 202),在后台完成处理后主动通知调用方。
|
||||
- **FR-007**: 系统 MUST 支持视频片段转文字描述,输入起止时间段,输出视频内容的结构化文字描述,并将描述文本保存至存储。
|
||||
- **FR-008**: 系统 MUST 在视频文件大小超过上限时,拒绝处理并返回明确错误;大小上限 MUST 支持运行时配置(默认 200MB),不需要重新构建服务即可调整。
|
||||
|
||||
**问答对生成**
|
||||
|
||||
- **FR-009**: 系统 MUST 支持基于文本三元组(含原文片段)批量生成候选问答对,每条三元组至少生成一个问答对。
|
||||
- **FR-010**: 系统 MUST 支持基于图像四元组(含裁剪图存储路径)生成图文候选问答对,图片内容由系统自动从存储获取,调用方只需提供存储路径。
|
||||
|
||||
**微调管理**
|
||||
|
||||
- **FR-011**: 系统 MUST 支持向大模型服务提交微调任务,输入训练数据文件地址、基础模型名称和超参数,返回微调任务 ID。
|
||||
- **FR-012**: 系统 MUST 支持通过任务 ID 查询微调任务当前状态(RUNNING / SUCCESS / FAILED)和完成进度。
|
||||
|
||||
**服务运维**
|
||||
|
||||
- **FR-013**: 系统 MUST 提供轻量健康检查接口,可被容器编排系统、反向代理和监控工具调用,无需认证,响应时间不超过 1 秒。
|
||||
- **FR-014**: 系统 MUST 对每次请求记录结构化日志,包含请求路径、响应状态和耗时;对每次大模型调用记录模型名称和耗时;对视频后台任务记录任务 ID、阶段和结果;日志 MUST NOT 包含文件原文内容。
|
||||
- **FR-015**: 系统 MUST 在大模型返回非法格式时(HTTP 502)、存储不可达时(HTTP 502)、大模型服务不可用时(HTTP 503),分别返回不同的结构化错误响应,便于调用方判断根因。
|
||||
- **FR-016**: 系统 MUST 提供 Swagger/OpenAPI 自动文档,描述所有接口的请求和响应格式。
|
||||
|
||||
**可扩展性**
|
||||
|
||||
- **FR-017**: 系统 MUST 将大模型调用和存储访问封装为可替换的适配层,当前实现 ZhipuAI GLM 系列和 RustFS,替换实现时业务逻辑层无需修改。
|
||||
- **FR-018**: 系统 MUST 通过配置文件和环境变量管理所有可变参数(模型名称、存储地址、密钥、视频大小上限等),支持不重建服务镜像的情况下切换环境配置。
|
||||
|
||||
### Key Entities
|
||||
|
||||
- **三元组(Triple)**: 从文本中提取的知识关系,由主语(subject)、谓语(predicate)、宾语(object)、原文片段(source_snippet)和字符偏移(source_offset: start/end)组成。
|
||||
- **四元组(Quadruple)**: 从图像中提取的知识关系,在三元组基础上增加修饰信息(qualifier)和图像位置框(bbox: x/y/w/h),并关联裁剪图存储路径(cropped_image_path)。
|
||||
- **问答对(QA Pair)**: 由 question 和 answer 组成,文本类关联三元组上下文,图像类额外携带图片存储路径(image_path)。
|
||||
- **视频任务回调(Video Job Callback)**: 异步任务完成通知,包含 job_id、status(SUCCESS/FAILED)、结果数据(帧路径列表或文字描述路径)和错误信息。
|
||||
- **微调任务(Finetune Job)**: 包含任务 ID、当前状态(RUNNING/SUCCESS/FAILED)和进度百分比。
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria *(mandatory)*
|
||||
|
||||
### Measurable Outcomes
|
||||
|
||||
- **SC-001**: 对于长度在 10,000 字以内的文档,三元组提取请求在 60 秒内完成并返回结果,满足标注员实时等待的体验预期。
|
||||
- **SC-002**: 对于分辨率在 4K 以内的图片,四元组提取和裁剪图上传在 30 秒内完成,裁剪图区域与 bbox 坐标对应准确(误差 ≤2 像素)。
|
||||
- **SC-003**: 视频帧提取和视频转文本任务提交后,接受响应在 1 秒内返回;后台处理完成后回调通知在 10 分钟内送达(针对 200MB 以内的视频)。
|
||||
- **SC-004**: 视频大小超限的请求,拒绝响应在 3 秒内返回(含存储查询耗时),不启动任何后台处理。
|
||||
- **SC-005**: 问答对生成请求(≤10 条三元组/四元组),在 90 秒内完成并返回全部问答对。
|
||||
- **SC-006**: 健康检查接口在服务正常运行时,响应时间不超过 1 秒,容器编排系统依此判断服务可用状态。
|
||||
- **SC-007**: 所有错误响应均返回结构化错误信息(含错误类型和描述),不返回通用服务器错误,便于调用方在不查看日志的情况下判断根因。
|
||||
- **SC-008**: 替换大模型服务商或存储实现时,业务逻辑层代码零修改,仅需变更配置和适配层实现。
|
||||
- **SC-009**: 所有业务接口通过自动化单元测试覆盖,包括正常路径、存储错误、大模型错误、格式解析错误等场景。
|
||||
|
||||
---
|
||||
|
||||
## Technical Environment *(mandatory)*
|
||||
|
||||
> 注:本节记录项目已确定的技术约束,这些决定已由团队确认,不作为需求变更点。
|
||||
|
||||
- **运行时**: Python 3.12.13
|
||||
- **Web 框架**: FastAPI(含 uvicorn 服务器)
|
||||
- **运行环境**: conda 虚拟环境,环境名称 `label`
|
||||
- **大模型**: ZhipuAI GLM 系列(文本:glm-4-flash,视觉:glm-4v-flash),通过官方 SDK 调用
|
||||
- **对象存储**: RustFS,通过 S3 兼容 API(boto3)访问
|
||||
- **文档解析**: TXT(UTF-8 解码)、PDF(pdfplumber)、DOCX(python-docx)
|
||||
- **视频处理**: OpenCV(帧提取 + 帧差分关键帧检测)
|
||||
- **容器化**: Docker + Docker Compose,提供 Dockerfile 和 docker-compose.yml
|
||||
|
||||
---
|
||||
|
||||
## Assumptions
|
||||
|
||||
- Java 后端(label-backend)是 AI 服务的唯一调用方,AI 服务不对外直接暴露,无需用户认证机制。
|
||||
- 大模型服务部署在公网(ZhipuAI 云端 API),RustFS 部署在 Docker 内网;因此图片内容必须以 base64 方式传递给大模型,不能依赖 RustFS 内网地址被云端服务访问。
|
||||
- 文档、图片、视频等原始文件由 Java 后端负责上传至存储,AI 服务仅通过存储路径读取,不处理文件上传逻辑。
|
||||
- 微调任务提交后的训练过程由 ZhipuAI 平台托管,AI 服务仅负责提交和查询,不管理训练算力资源。
|
||||
- 视频任务为低频操作(由 ADMIN 手动触发),并发量有限(预计同时不超过 5 个视频任务),当前无需专用任务队列。
|
||||
- 日志仅输出到标准输出(stdout),由容器运行时或日志收集系统负责落盘和归档;不记录文件原文内容,防止敏感信息泄露。
|
||||
- ZhipuAI SDK 为同步阻塞调用;为保持服务并发能力,SDK 调用将在线程池中执行,不阻塞主事件循环。
|
||||
- 视频大小上限默认 200MB,可通过环境变量(MAX_VIDEO_SIZE_MB)在容器运行时覆盖,无需重建镜像。
|
||||
Reference in New Issue
Block a user