proofdb/apidoc/importapi.md
2026-05-01 23:40:14 +08:00

7.8 KiB
Raw Blame History

档案导入 API

接口说明

导入一份 Markdown 档案文本,将其规范化为 Archive、Page、Chunk 三层结构,并为每个 chunk 生成全局唯一的 chunk_uid

正式使用时,推荐直接上传原始 Markdown 文件,或者把 Markdown 原文作为请求体发送。系统会根据 Markdown 中的分页标记自动分页、分段和切 chunk。

导入会先写入 PostgreSQL。如果 title/year/author/tags/summary 缺失,系统会把 archive_uid 推入 Redis 队列,由独立的 ai_metadata process 异步请求 AI 补全并更新数据库。

当前版本会把导入结果保存为运行时快照文件:

runtime/proofdb/imports/{import_uid}.json

后续接入 MySQL、OpenSearch、Vector DB 时,会沿用当前返回结构中的 UID。

请求方式

POST /api/articles/import

支持三种调用方式:

  1. multipart/form-data 上传 Markdown 文件。
  2. text/markdowntext/plain 直接发送 Markdown 原文。
  3. application/json 发送 Markdown 字符串,适合程序内部调用。

请求字段

字段 类型 必填 说明
file file Markdown 文件。使用 multipart/form-data 时推荐传此字段
archive_uid string 档案级 ULID。不传时系统自动生成
title string 档案标题。不传时,系统会优先请求 AI 生成,失败后从 Markdown 标题或文件名推断
year int 档案年份。不传时,系统会请求 AI 从文本中抽取或推断
author string 作者或签发人。不传时,系统会请求 AI 从文本中抽取或推断
summary string 档案摘要。不传时,系统会请求 AI 生成
source string 来源标识。不传时,系统会使用上传文件名或 raw-markdown
series string 所属系列集
tags array 标签数组。不传时,系统会请求 AI 生成
metadata object 档案级元数据,例如年份、作者、馆藏信息
content string Markdown 原文。JSON 调用时使用
pages array 页数组。兼容字段,一般不需要调用方传入
pages[].page_number int string
pages[].content string 当前页 OCR 或转录文本
pages[].metadata object 页级元数据
paragraphs array 段落数组。兼容字段,一般不需要调用方传入
paragraphs[].page_number int string
paragraphs[].content string 段落正文
paragraphs[].metadata object 段落级元数据
chunk_size int 每个 chunk 的目标最大字符数,默认 800,范围 100-4000
chunk_overlap int 超长文本硬切时的重叠字符数,默认 120,必须小于 chunk_size

Markdown 分页规则

系统会优先识别以下分页格式:

<!-- DOCMASTER:PAGE 0001 -->

## Page 1

第一页正文...

---

<!-- DOCMASTER:PAGE 0002 -->

## Page 2

第二页正文...

如果没有 DOCMASTER:PAGE 标记,系统会把整份 Markdown 当作单页处理。

分段与 Chunk 切分策略

当前 import 使用 Markdown 预处理 + 页内向量 chunk 切分:

  1. 先根据 Markdown 分页标记拆成 page。
  2. 每页内部去掉分页标题、水平分隔线等结构性标记。
  3. 页眉、页脚、密级、纯页码等噪声块会被过滤,不作为向量 chunk 的正文。
  4. 检索证据只定位到页码,因此 chunk 可以跨段落、跨列表项,但不会跨页。
  5. 每页内部会按段落/句子/自然停顿形成文本单元,并尽量打包到接近 chunk_size
  6. 如果单个文本单元超过 chunk_size,才退回固定字符窗口硬切,并使用 chunk_overlap 保留上下文。

请求示例

curl -X POST http://127.0.0.1:8787/api/articles/import \
  -F 'title=NSD 76 Disposition of NSC Policy Documents' \
  -F 'source=archive://nsc/nsd-76' \
  -F 'chunk_size=800' \
  -F 'chunk_overlap=120' \
  -F 'file=@test/1.test.md;type=text/markdown'

也可以直接发送 Markdown 原文:

curl -X POST 'http://127.0.0.1:8787/api/articles/import?title=NSD%2076&source=archive://nsc/nsd-76' \
  -H 'Content-Type: text/markdown' \
  --data-binary '@test/1.test.md'

JSON 调用示例:

curl -X POST http://127.0.0.1:8787/api/articles/import \
  -H 'Content-Type: application/json' \
  --data '{
    "title": "NSD 76 Disposition of NSC Policy Documents",
    "source": "archive://nsc/nsd-76",
    "content": "<!-- DOCMASTER:PAGE 0001 -->\n\n## Page 1\n\nMarkdown 正文..."
  }'

成功响应

状态码:

201 Created

响应示例:

{
  "code": 0,
  "message": "Archive imported.",
  "data": {
    "import_uid": "01HX8K7V9Y3QF2Z6M4A1B8C9D0",
    "archive": {
      "archive_uid": "01HX8K7V9Y3QF2Z6M4A1B8C9D0",
      "title": "NSD 76 Disposition of NSC Policy Documents",
      "year": 1992,
      "author": "Brent Scowcroft",
      "source": "archive://nsc/nsd-76",
      "series": null,
      "tags": [
        "美国国家安全委员会",
        "政策文件",
        "NSD 76"
      ],
      "summary": "这份档案是 1992 年关于 NSC 政策文件处置的国家安全指令,列明已被取代或已完成、不再有效的政策文件。",
      "metadata": {
        "ai_enrichment": {
          "enabled": true,
          "attempted": true,
          "filled": [
            "year",
            "author",
            "tags",
            "summary"
          ],
          "missing": [],
          "model": "glm-4.7-flash"
        }
      }
    },
    "pages": [
      {
        "page_number": 1,
        "block_count": 8,
        "chunk_count": 2,
        "content_length": 1042,
        "chunk_uids": [
          "01HX8K7V9Y3QF2Z6M4A1B8C9D0_1_28172",
          "01HX8K7V9Y3QF2Z6M4A1B8C9D0_2_19304"
        ]
      }
    ],
    "chunks": [
      {
        "chunk_uid": "01HX8K7V9Y3QF2Z6M4A1B8C9D0_1_28172",
        "chunk_index": 1,
        "page_start": 1,
        "page_end": 1,
        "pages": [
          1
        ],
        "text": "NSD 45 20 AUG 90 U.S. Policy in Response to the Iraqi Invasion of Kuwait (C)\n* *COMMENT** OBE by operations Desert Shield and Desert Storm.",
        "length": 142,
        "embedding_ref": null
      }
    ],
    "stats": {
      "page_count": 8,
      "page_block_count": 86,
      "chunk_count": 14,
      "chunk_size": 800,
      "chunk_overlap": 120
    },
    "queue": {
      "ai_metadata_enqueued": true,
      "needs_ai_metadata": true
    }
  }
}

错误响应

JSON 格式错误

状态码:

400 Bad Request
{
  "code": 400,
  "message": "Invalid JSON body.",
  "errors": {
    "body": "Syntax error"
  }
}

参数校验失败

状态码:

422 Unprocessable Entity
{
  "code": 422,
  "message": "Archive import validation failed.",
  "errors": {
    "source": [
      "source is required."
    ],
    "content": [
      "content, file, pages, or paragraphs is required."
    ]
  }
}

快照保存失败

状态码:

500 Internal Server Error
{
  "code": 500,
  "message": "Archive import snapshot could not be saved.",
  "errors": {
    "storage": "具体错误信息"
  }
}

UID 说明

UID 说明
import_uid 本次导入任务 ID目前等同于档案级 ULID
archive_uid 档案级 ULID例如 01HX8K7V9Y3QF2Z6M4A1B8C9D0
chunk_uid chunk 级核心 ID格式为 {archive_uid}_{chunk_index}_{short_uid}

chunk_uid 是后续 MySQL、OpenSearch、Vector DB 之间关联的核心字段。

chunk_index1 开始递增。short_uid 是 5 位数字短码,由 chunk 的稳定内容哈希生成,方便人工查看和引用。