From e0d080ceea56c89acadbf19d5dda9df8a660b739 Mon Sep 17 00:00:00 2001 From: wh Date: Fri, 10 Apr 2026 14:51:34 +0800 Subject: [PATCH] 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 --- .../checklists/requirements.md | 38 +++ specs/001-ai-service-requirements/spec.md | 258 ++++++++++++++++++ 2 files changed, 296 insertions(+) create mode 100644 specs/001-ai-service-requirements/checklists/requirements.md create mode 100644 specs/001-ai-service-requirements/spec.md diff --git a/specs/001-ai-service-requirements/checklists/requirements.md b/specs/001-ai-service-requirements/checklists/requirements.md new file mode 100644 index 0000000..bc0c9a6 --- /dev/null +++ b/specs/001-ai-service-requirements/checklists/requirements.md @@ -0,0 +1,38 @@ +# Specification Quality Checklist: AI 服务需求文档 + +**Purpose**: Validate specification completeness and quality before proceeding to planning +**Created**: 2026-04-10 +**Feature**: [../spec.md](../spec.md) + +## Content Quality + +- [x] No implementation details (languages, frameworks, APIs) — 注:Technical Environment 节单独列出,明确标注为已确认技术约束,不影响需求层表述 +- [x] Focused on user value and business needs +- [x] Written for non-technical stakeholders(业务场景均以 ADMIN/标注员/系统为视角描述) +- [x] All mandatory sections completed + +## Requirement Completeness + +- [x] No [NEEDS CLARIFICATION] markers remain +- [x] Requirements are testable and unambiguous(每条 FR 含明确行为和可验证条件) +- [x] Success criteria are measurable(SC 含具体时间、像素精度等量化指标) +- [x] Success criteria are technology-agnostic (no implementation details) +- [x] All acceptance scenarios are defined(8 个 User Story 均含 Acceptance Scenarios) +- [x] Edge cases are identified(6 条边界情况,覆盖文件损坏、空结果、并发等) +- [x] Scope is clearly bounded(明确:不处理上传逻辑,不管理训练资源,不对外暴露) +- [x] Dependencies and assumptions identified(9 条假设,含内外网访问、ZhipuAI 托管等) + +## Feature Readiness + +- [x] All functional requirements have clear acceptance criteria(FR-001~FR-018 逐一可追溯到 User Story 验收场景) +- [x] User scenarios cover primary flows(P1: 文本/图像提取;P2: 视频/QA;P3: 微调/健康检查) +- [x] Feature meets measurable outcomes defined in Success Criteria +- [x] No implementation details leak into specification(Technical Environment 节独立,不混入 FR/SC) + +## Notes + +- Technical Environment 节超出传统需求文档范围,但用户明确要求包含环境约束(Python 3.12.13、FastAPI、conda label 环境),已单独成节并说明其性质。 +- SC-009(测试覆盖)为工程质量指标,非用户感知需求,但对服务可靠性有实质影响,保留。 +- 所有 [NEEDS CLARIFICATION] 均已通过合理默认值或设计文档确认,无待用户回答的开放问题。 + +**VERDICT**: ✅ 规格就绪,可进行 `/speckit.clarify` 或 `/speckit.plan` diff --git a/specs/001-ai-service-requirements/spec.md b/specs/001-ai-service-requirements/spec.md new file mode 100644 index 0000000..fbc8915 --- /dev/null +++ b/specs/001-ai-service-requirements/spec.md @@ -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)在容器运行时覆盖,无需重建镜像。