Generated plan.md, research.md, data-model.md, contracts/api.md, quickstart.md, and CLAUDE.md agent context via /speckit-plan.
5.3 KiB
5.3 KiB
Data Model: AI 服务
Branch: 001-ai-service-requirements | Date: 2026-04-10
实体定义
TripleItem(文本三元组)
从文档中提取的一条知识关系。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| subject | string | 非空 | 主语实体 |
| predicate | string | 非空 | 谓语/关系 |
| object | string | 非空 | 宾语实体 |
| source_snippet | string | 非空 | 原文中的证据片段(直接引用) |
| source_offset.start | int | ≥0 | 证据片段在全文中的起始字符偏移 |
| source_offset.end | int | >start | 证据片段在全文中的结束字符偏移 |
状态转换: 无(只读输出)
QuadrupleItem(图像四元组)
从图像中提取的一条知识关系,带图像位置信息。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| subject | string | 非空 | 主体实体 |
| predicate | string | 非空 | 关系/属性 |
| object | string | 非空 | 客体实体 |
| qualifier | string | 可为空 | 修饰信息(时间、条件、场景) |
| bbox.x | int | ≥0 | 边界框左上角 x 像素坐标 |
| bbox.y | int | ≥0 | 边界框左上角 y 像素坐标 |
| bbox.w | int | >0 | 边界框宽度(像素) |
| bbox.h | int | >0 | 边界框高度(像素) |
| cropped_image_path | string | 非空 | 裁剪图在 RustFS 中的存储路径 |
派生规则: cropped_image_path = "crops/{task_id}/{item_index}.jpg",由 image_service 自动生成并上传
QAPair(文本问答对)
由文本三元组生成的训练候选问答对。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| question | string | 非空 | 问题文本 |
| answer | string | 非空 | 答案文本 |
ImageQAPair(图像问答对)
由图像四元组生成的训练候选图文问答对。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| question | string | 非空 | 问题文本 |
| answer | string | 非空 | 答案文本 |
| image_path | string | 非空 | 对应裁剪图的存储路径(来源于 QuadrupleItem.cropped_image_path) |
FrameInfo(视频帧信息)
视频帧提取任务中单帧的元数据。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| frame_index | int | ≥0 | 帧在视频中的原始帧序号 |
| time_sec | float | ≥0.0 | 帧对应的时间点(秒) |
| frame_path | string | 非空 | 帧图在 RustFS 中的存储路径 |
派生规则: frame_path = "frames/{source_id}/{upload_index}.jpg"
VideoJobCallback(视频任务回调)
异步视频任务完成后发送给 Java 后端的通知载荷。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| job_id | int | 非空 | 由 Java 后端分配的任务 ID |
| status | string | SUCCESS | FAILED | 任务最终状态 |
| frames | FrameInfo[] | null | 仅帧提取时非 null | 提取的帧列表(可为空列表) |
| output_path | string | null | 仅视频转文本时非 null | 输出文字描述的存储路径 |
| error_message | string | null | 仅 FAILED 时非 null | 错误描述 |
FinetuneJob(微调任务)
微调任务的状态快照。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| job_id | string | 非空 | 由 ZhipuAI 平台分配的任务 ID(如 "glm-ft-xxxxxx") |
| status | string | RUNNING | SUCCESS | FAILED | 当前状态 |
| progress | int | null | 0-100 | null | 完成百分比(ZhipuAI 支持时) |
| error_message | string | null | 仅 FAILED 时非 null | 错误描述 |
状态映射:
ZhipuAI "running" → RUNNING
ZhipuAI "succeeded" → SUCCESS
ZhipuAI "failed" → FAILED
其他 → RUNNING(保守处理)
RustFS 存储路径规范
| 资源类型 | 存储桶 | 路径格式 |
|---|---|---|
| 上传文本文件 | source-data |
text/{年月}/{source_id}.txt |
| 上传图片 | source-data |
image/{年月}/{source_id}.jpg |
| 上传视频 | source-data |
video/{年月}/{source_id}.mp4 |
| 视频帧图 | source-data |
frames/{source_id}/{upload_index}.jpg |
| 视频转译文本 | source-data |
video-text/{source_id}/{timestamp}.txt |
| 图像/帧 bbox 裁剪图 | source-data |
crops/{task_id}/{item_index}.jpg |
| 导出 JSONL 文件 | finetune-export |
export/{batchUuid}.jsonl |
配置模型
config.yaml(非敏感,提交 git)
server:
port: 8000
log_level: INFO
storage:
buckets:
source_data: "source-data"
finetune_export: "finetune-export"
backend: {} # callback_url 由 .env 注入
video:
frame_sample_count: 8 # 视频转文本时均匀采样帧数
max_file_size_mb: 200 # 视频大小上限(可通过 MAX_VIDEO_SIZE_MB 覆盖)
models:
default_text: "glm-4-flash"
default_vision: "glm-4v-flash"
环境变量覆盖映射
| 环境变量 | YAML 路径 | 说明 |
|---|---|---|
| ZHIPUAI_API_KEY | zhipuai.api_key | 必填 |
| STORAGE_ACCESS_KEY | storage.access_key | 必填 |
| STORAGE_SECRET_KEY | storage.secret_key | 必填 |
| STORAGE_ENDPOINT | storage.endpoint | RustFS 地址 |
| BACKEND_CALLBACK_URL | backend.callback_url | Java 后端回调接口 |
| LOG_LEVEL | server.log_level | 日志级别 |
| MAX_VIDEO_SIZE_MB | video.max_file_size_mb | 视频大小上限 |