API接口文档.md 30 KB

schedule-embedding-api 接口文档

📋 文档概述

项目名称: schedule-embedding-api 文档版本: v2.2 最后更新: 2026-03-13 服务地址: http://localhost:8084

功能简介

本系统提供基于 Elasticsearch 8.x 和 Embedding API 的智能文档向量化与检索服务,主要功能包括:

  • 📄 文档入库: 支持单个文档和批量文档的向量化入库
  • 🔍 向量搜索: 基于 4096 维向量的语义搜索
  • 🎯 混合搜索: 支持向量搜索与业务字段过滤相结合
  • 📊 文档管理: 提供文档查询和删除功能
  • 🔄 完全动态: 支持任意类型数据(合同、音频、视频、图片等)

技术栈

  • Embedding 模型: Qwen3-Embedding-8B (4096维向量)
  • 搜索引擎: Elasticsearch 8.x (原生 KNN 支持)
  • 开发框架: Spring Boot 2.7.18
  • JDK 版本: Java 17

核心设计理念

ES动态映射 + 业务字段完全动态

  • 核心字段(固定): docId, chunkId, content, embedding, createTime, updateTime
  • 动态映射: 使用 ES DynamicMapping.True,自动识别任意新字段
  • metadata完全动态: 所有业务数据通过 metadata 动态扩展,支持任意类型和字段
  • 零代码扩展: 新增字段无需修改代码,完全动态化
  • 类型无关: 支持合同、音频、视频、图片等任意数据类型

🔗 接口列表

序号 接口名称 请求方法 接口路径 功能说明
1 健康检查 GET /actuator/health 检查服务健康状态
2 单个文档入库 POST /api/v1/documents/index 将单个文档向量化后存入ES
3 批量文档入库 POST /api/v1/documents/batch-index 批量将文档向量化后存入ES
4 向量搜索 POST /api/v1/search 基于语义的向量搜索
5 混合搜索 POST /api/v1/search/hybrid 向量搜索 + 业务字段过滤
6 查询文档 GET /api/v1/documents/{docId} 查询文档的所有chunks
7 删除文档 DELETE /api/v1/documents/{docId} 删除文档的所有chunks
8 删除Chunk DELETE /api/v1/documents/chunk/{chunkId} 删除单个chunk

📖 接口详情

1. 健康检查接口

基本信息

  • 接口名称: 健康检查
  • 接口路径: /actuator/health
  • 请求方法: GET
  • Content-Type: 无需设置

请求示例

curl -X GET http://localhost:8084/actuator/health

响应示例

状态码: 200 OK

{
  "status": "UP",
  "components": {
    "diskSpace": {
      "status": "UP",
      "details": {
        "total": 994662584320,
        "free": 110714380288,
        "threshold": 10485760,
        "exists": true
      }
    },
    "elasticsearch": {
      "status": "UP",
      "details": {
        "cluster_name": "docker-cluster",
        "status": "yellow",
        "number_of_nodes": 1,
        "number_of_data_nodes": 1
      }
    },
    "ping": {
      "status": "UP"
    }
  }
}

测试用例

用例编号 测试场景 预期结果
TC-001 正常访问健康检查接口 返回200,status为UP

2. 单个文档入库接口

基本信息

  • 接口名称: 单个文档入库
  • 接口路径: /api/v1/documents/index
  • 请求方法: POST
  • Content-Type: application/json

请求参数

参数名 类型 必填 说明 示例值
docId String 文档唯一标识 "contract-001"
fileName String 文件名 "合同.pdf"
fullText String 文档全文内容 "这是合同内容..."
filePath String 文件路径 "/data/contracts/001.pdf"
fileSize Long 文件大小(字节) 1024000
fileType String 文件类型 "pdf"
metadata Map 完全动态的业务元数据 见下方示例

metadata 字段说明

重要: metadata 是完全动态的,支持任意字段!

合同类文档示例:

{
  "contractType": "消费贷贷款合同",
  "partyA": "A公司",
  "partyB": "B公司",
  "contractAmount": 1000000.00,
  "signDate": "2026-01-15"
}

音频类文档示例:

{
  "duration": 1800,
  "speaker": "张三",
  "language": "zh-CN",
  "sampleRate": 44100,
  "bitrate": 128000,
  "format": "MP3",
  "transcript": "音频转写文本..."
}

视频类文档示例:

{
  "duration": 3600,
  "resolution": "1920x1080",
  "frameRate": 30,
  "codec": "H.264",
  "bitrate": 5000000,
  "subtitles": ["中文字幕", "英文字幕"]
}

图片类文档示例:

{
  "width": 1920,
  "height": 1080,
  "format": "JPEG",
  "colorSpace": "RGB",
  "dpi": 300,
  "description": "图片描述..."
}

请求示例

示例 1: 合同类文档入库

curl -X POST http://localhost:8084/api/v1/documents/index \
  -H "Content-Type: application/json" \
  -d '{
    "docId": "contract-001",
    "fileName": "永续贷产品贷款合同.pdf",
    "fullText": "永续贷产品贷款合同\n\n第一章:总则\n本合同由甲方A公司与乙方B公司签订,合同金额为100万元。\n\n第二章:贷款条款\n2.1 贷款利率按照央行基准利率执行。\n2.2 贷款期限为36个月。\n2.3 还款方式为等额本息。",
    "filePath": "/home/data/contracts/contract-001.pdf",
    "fileSize": 1289748,
    "fileType": "pdf",
    "metadata": {
      "contractType": "消费贷贷款合同",
      "partyA": "A公司",
      "partyB": "B公司",
      "contractAmount": 1000000.00,
      "signDate": "2026-01-15"
    }
  }'

示例 2: 音频类文档入库

curl -X POST http://localhost:8084/api/v1/documents/index \
  -H "Content-Type: application/json" \
  -d '{
    "docId": "audio-001",
    "fileName": "会议录音.mp3",
    "fullText": "这是会议的完整转写文本内容,包含所有发言人的讲话记录...",
    "filePath": "/home/data/audio/meeting_001.mp3",
    "fileSize": 5120000,
    "fileType": "mp3",
    "metadata": {
      "duration": 1800,
      "speaker": "张三",
      "language": "zh-CN",
      "sampleRate": 44100,
      "format": "MP3"
    }
  }'

示例 3: 视频类文档入库

curl -X POST http://localhost:8084/api/v1/documents/index \
  -H "Content-Type: application/json" \
  -d '{
    "docId": "video-001",
    "fileName": "培训课程.mp4",
    "fullText": "这是视频的字幕文本内容...",
    "filePath": "/home/data/video/training_001.mp4",
    "fileSize": 51200000,
    "fileType": "mp4",
    "metadata": {
      "duration": 3600,
      "resolution": "1920x1080",
      "frameRate": 30,
      "codec": "H.264",
      "subtitles": ["中文字幕", "英文字幕"]
    }
  }'

响应示例

成功响应 - 200 OK

{
  "success": true,
  "docId": "contract-001",
  "chunkCount": 1,
  "message": "文档入库成功",
  "error": null
}

失败响应 - 400 Bad Request

{
  "code": 400,
  "success": false,
  "message": "参数校验失败",
  "errors": {
    "docId": "文档ID不能为空"
  },
  "timestamp": 1773306699906
}
{
  "code": 400,
  "success": false,
  "message": "参数校验失败",
  "errors": {
    "fullText": "全文内容不能为空"
  },
  "timestamp": 1773306699937
}

测试用例

用例编号 测试场景 请求参数 预期结果
TC-002 正常数据入库(合同) 完整的合同信息 200,chunkCount=1
TC-003 缺少docId 不传docId字段 400,提示"文档ID不能为空"
TC-004 空文本内容 fullText为空字符串 400,提示"全文内容不能为空"
TC-005 音频数据入库 音频元数据(duration、speaker等) 200,正常入库
TC-006 视频数据入库 视频元数据(resolution、codec等) 200,正常入库
TC-007 动态字段扩展 新增任意自定义字段 200,零代码扩展成功

3. 批量文档入库接口

基本信息

  • 接口名称: 批量文档入库
  • 接口路径: /api/v1/documents/batch-index
  • 请求方法: POST
  • Content-Type: application/json

请求参数

参数名 类型 必填 说明 示例值
items Array<IndexRequest> 文档列表(最多100个) 见下方示例

IndexRequest 结构同"单个文档入库"接口。

请求示例

curl -X POST http://localhost:8084/api/v1/documents/batch-index \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "docId": "batch-doc-001",
        "fileName": "合同1.pdf",
        "fullText": "这是第一个合同文档的内容。包含重要条款和条件。",
        "fileType": "pdf",
        "metadata": {
          "contractType": "消费贷",
          "partyA": "A公司"
        }
      },
      {
        "docId": "batch-doc-002",
        "fileName": "音频1.mp3",
        "fullText": "这是音频的转写文本内容。",
        "fileType": "mp3",
        "metadata": {
          "duration": 1800,
          "speaker": "张三"
        }
      },
      {
        "docId": "batch-doc-003",
        "fileName": "视频1.mp4",
        "fullText": "这是视频的字幕内容。",
        "fileType": "mp4",
        "metadata": {
          "duration": 3600,
          "resolution": "1920x1080"
        }
      }
    ]
  }'

响应示例

成功响应 - 200 OK

{
  "totalCount": 3,
  "successCount": 3,
  "failedCount": 0,
  "failedItems": []
}

部分失败响应 - 200 OK

{
  "totalCount": 3,
  "successCount": 2,
  "failedCount": 1,
  "failedItems": [
    {
      "docId": "batch-doc-003",
      "error": "全文内容不能为空"
    }
  ]
}

失败响应 - 400 Bad Request

{
  "code": 400,
  "success": false,
  "message": "参数校验失败",
  "errors": {
    "items": "文档列表不能为空"
  },
  "timestamp": 1773306700683
}

测试用例

用例编号 测试场景 请求参数 预期结果
TC-008 正常批量入库 3个不同类型文档 200,successCount=3
TC-009 空列表 items=[] 400,提示"文档列表不能为空"
TC-010 大批量入库 10个文档 200,successCount=10
TC-011 部分失败 3个文档,1个缺少fullText 200,successCount=2,failedCount=1

4. 向量搜索接口

基本信息

  • 接口名称: 向量搜索
  • 接口路径: /api/v1/search
  • 请求方法: POST
  • Content-Type: application/json

功能说明

基于语义的向量搜索,使用 Embedding 模型将查询文本转换为 4096 维向量,然后在 ES 中进行 KNN 搜索,返回最相似的结果。

请求参数

参数名 类型 必填 说明 示例值 默认值
query String 查询文本 "A公司的消费贷合同利率是多少" -
topK Integer 返回结果数量 5 10

请求示例

curl -X POST http://localhost:8084/api/v1/search \
  -H "Content-Type: application/json" \
  -d '{
    "query": "A公司的消费贷合同利率是多少",
    "topK": 5
  }'

响应示例

成功响应 - 200 OK

[
  {
    "docId": "company-a-test",
    "chunkId": "company-a-test_chunk_0",
    "chunkIndex": 0,
    "content": "A公司与B公司签订消费贷合同,合同金额100万元,贷款利率按照央行基准利率执行,贷款期限36个月",
    "score": 0.8871919,
    "metadata": {
      "chunk_index": 0,
      "file_path": "/tmp/test.pdf",
      "create_time": "2026-03-12T17:06:51",
      "doc_id": "company-a-test",
      "chunk_id": "company-a-test_chunk_0",
      "content": "A公司与B公司签订消费贷合同,合同金额100万元,贷款利率按照央行基准利率执行,贷款期限36个月",
      "file_size": 1024,
      "file_size_mb": 0.0009765625,
      "chunk_count": 0,
      "update_time": "2026-03-12T17:06:51",
      "file_type": "pdf",
      "contract_type": "消费贷贷款合同",
      "party_a": "A公司",
      "party_b": "B公司"
    }
  }
]

注意: 响应中不包含 embedding 字段,以节省带宽和提高性能。

无结果响应 - 200 OK

[]

失败响应 - 400 Bad Request

{
  "code": 400,
  "success": false,
  "message": "参数校验失败",
  "errors": {
    "query": "查询文本不能为空"
  },
  "timestamp": 1773306701000
}

响应字段说明

字段名 类型 说明
docId String 文档ID
chunkId String 分片ID
chunkIndex Integer 分片序号
content String 匹配的内容片段
score Float 相似度分数(0-1,越高越相似)
metadata Map 完整的元数据信息(不包含embedding)

测试用例

用例编号 测试场景 请求参数 预期结果
TC-012 语义搜索 query="合同利率", topK=5 200,返回相关合同片段
TC-013 空查询 不传query 400,提示"查询文本不能为空"
TC-014 指定topK query="贷款", topK=3 200,返回最多3条结果
TC-015 无匹配结果 query="不存在的特定内容" 200,返回空数组[]
TC-016 中文模糊搜索 query="多少钱" 200,返回包含金额信息的片段

5. 混合搜索接口

基本信息

  • 接口名称: 混合搜索(向量 + 业务过滤)
  • 接口路径: /api/v1/search/hybrid
  • 请求方法: POST
  • Content-Type: application/json

功能说明

结合向量搜索和业务字段过滤,先进行 KNN 搜索,再根据指定的业务字段过滤结果。

请求参数

参数名 类型 必填 说明 示例值 默认值
query String 查询文本 "贷款利率和还款方式" -
topK Integer 返回结果数量 10 10
filters Map 动态过滤条件,支持任意字段 见下方示例 -

filters 字段说明

重要: filters 是完全动态的,可以根据入库时的 metadata 任意过滤!

合同过滤示例:

{
  "contractType": "消费贷贷款合同",
  "partyA": "A公司"
}

音频过滤示例:

{
  "speaker": "张三",
  "language": "zh-CN"
}

视频过滤示例:

{
  "resolution": "1920x1080",
  "codec": "H.264"
}

请求示例

示例 1: 合同过滤

curl -X POST http://localhost:8084/api/v1/search/hybrid \
  -H "Content-Type: application/json" \
  -d '{
    "query": "贷款利率和还款方式",
    "topK": 10,
    "filters": {
      "contractType": "消费贷贷款合同",
      "partyA": "A公司"
    }
  }'

示例 2: 音频过滤

curl -X POST http://localhost:8084/api/v1/search/hybrid \
  -H "Content-Type: application/json" \
  -d '{
    "query": "会议讨论的重点内容",
    "topK": 5,
    "filters": {
      "speaker": "张三",
      "language": "zh-CN"
    }
  }'

示例 3: 视频过滤

curl -X POST http://localhost:8084/api/v1/search/hybrid \
  -H "Content-Type: application/json" \
  -d '{
    "query": "培训课程的核心要点",
    "topK": 10,
    "filters": {
      "resolution": "1920x1080",
      "codec": "H.264"
    }
  }'

响应示例

成功响应 - 200 OK

[
  {
    "docId": "test-doc-001",
    "chunkId": "test-doc-001_chunk_0",
    "chunkIndex": 0,
    "content": "永续贷产品贷款合同\n\n第二章:贷款条款\n2.1 贷款利率按照央行基准利率执行。\n2.2 贷款期限为36个月。\n2.3 还款方式为等额本息。",
    "score": 0.8512345,
    "metadata": {
      "contract_type": "消费贷贷款合同",
      "party_a": "A公司",
      "party_b": "B公司",
      "contract_amount": 1000000.0
    }
  }
]

无匹配结果 - 200 OK

[]

测试用例

用例编号 测试场景 请求参数 预期结果
TC-017 合同字段过滤 query="贷款利率", filters={contractType:"消费贷",partyA:"A公司"} 200,返回A公司的消费贷合同
TC-018 音频字段过滤 query="会议记录", filters={speaker:"张三"} 200,返回张三发言的音频
TC-019 视频字段过滤 query="课程", filters={resolution:"1920x1080"} 200,返回高清视频
TC-020 无匹配过滤 query="利率", filters={contractType:"不存在的类型"} 200,返回空数组[]
TC-021 无过滤条件 query="合同", 不传filters 200,等同于普通向量搜索

6. 查询文档接口

基本信息

  • 接口名称: 查询文档的所有chunks
  • 接口路径: /api/v1/documents/{docId}
  • 请求方法: GET
  • Content-Type: 无需设置

请求参数

参数名 类型 必填 说明 示例值
docId String 文档ID(路径参数) "contract-001"

请求示例

curl -X GET http://localhost:8084/api/v1/documents/contract-001

响应示例

成功响应 - 200 OK

[
  {
    "docId": "contract-001",
    "chunkId": "contract-001_chunk_0",
    "chunkIndex": 0,
    "content": "永续贷产品贷款合同\n\n第一章:总则\n本合同由甲方A公司与乙方B公司签订。",
    "filePath": "/data/contracts/contract-001.pdf",
    "fileType": "pdf",
    "createTime": "2026-03-12 17:10:15",
    "updateTime": "2026-03-12 17:10:15",
    "extendedFields": {
      "contractType": "消费贷贷款合同",
      "partyA": "A公司",
      "partyB": "B公司"
    }
  }
]

文档不存在 - 200 OK

[]

测试用例

用例编号 测试场景 请求参数 预期结果
TC-022 查询存在的文档 docId="contract-001" 200,返回文档的所有chunks
TC-023 查询不存在的文档 docId="non-existent" 200,返回空数组[]

7. 删除文档接口

基本信息

  • 接口名称: 删除文档的所有chunks
  • 接口路径: /api/v1/documents/{docId}
  • 请求方法: DELETE
  • Content-Type: 无需设置

请求参数

参数名 类型 必填 说明 示例值
docId String 文档ID(路径参数) "contract-001"

请求示例

curl -X DELETE http://localhost:8084/api/v1/documents/contract-001

响应示例

成功响应 - 200 OK

{
  "success": true,
  "docId": "contract-001",
  "deletedCount": 1,
  "message": "删除成功"
}

文档不存在 - 200 OK

{
  "success": true,
  "docId": "non-existent-doc",
  "deletedCount": 0,
  "message": "删除成功"
}

测试用例

用例编号 测试场景 请求参数 预期结果
TC-024 删除存在的文档 docId="contract-001" 200,deletedCount>0
TC-025 删除不存在的文档 docId="non-existent" 200,deletedCount=0

8. 删除Chunk接口

基本信息

  • 接口名称: 删除单个chunk
  • 接口路径: /api/v1/documents/chunk/{chunkId}
  • 请求方法: DELETE
  • Content-Type: 无需设置

请求参数

参数名 类型 必填 说明 示例值
chunkId String 分片ID(路径参数) "contract-001_chunk_0"

请求示例

curl -X DELETE http://localhost:8084/api/v1/documents/chunk/contract-001_chunk_0

响应示例

成功响应 - 200 OK

{
  "success": true,
  "chunkId": "contract-001_chunk_0",
  "message": "删除成功"
}

chunk不存在 - 200 OK

{
  "success": false,
  "chunkId": "non-existent-chunk",
  "message": "删除失败"
}

测试用例

用例编号 测试场景 请求参数 预期结果
TC-026 删除存在的chunk chunkId="contract-001_chunk_0" 200,success=true
TC-027 删除不存在的chunk chunkId="non-existent-chunk" 200,success=false

🔒 错误码说明

HTTP 状态码

状态码 说明
200 请求成功
400 请求参数错误
500 服务器内部错误

业务错误码

错误码 说明 示例
400 参数校验失败 缺少必填字段、字段格式错误

错误响应格式

{
  "code": 400,
  "success": false,
  "message": "参数校验失败",
  "errors": {
    "fieldName": "具体错误信息"
  },
  "timestamp": 1773306699906
}

📊 数据模型

Elasticsearch 索引结构

本系统使用 ES动态映射(DynamicMapping.True),索引结构如下:

固定字段(必须显式定义)

字段名 类型 说明
doc_id keyword 文档唯一标识
chunk_id keyword 分片唯一标识
chunk_index long 分片序号
content text 文档内容(支持全文搜索)
embedding dense_vector 4096维向量(用于KNN搜索)
create_time date 创建时间
update_time date 更新时间

动态字段(自动识别)

除上述固定字段外,所有其他字段都是动态的,包括:

  • 文件元数据:file_path, file_size, file_type 等
  • 业务元数据:任意自定义字段(通过 metadata 传入)
  • ES会根据传入值自动推断类型:字符串→text/keyword,数字→long/double,日期→date等

示例:传入以下 metadata:

{
  "contractType": "贷款合同",
  "partyA": "A公司",
  "contractAmount": 1000000,
  "signDate": "2026-01-15"
}

ES会自动创建并索引这些字段,无需修改代码。

IndexRequest(文档入库请求)

{
  "docId": "string (必填)",
  "fileName": "string (可选)",
  "fullText": "string (必填)",
  "filePath": "string (可选)",
  "fileSize": "long (可选)",
  "fileType": "string (可选)",
  "metadata": {
    "任意业务字段": "任意值(完全动态)"
  }
}

SearchRequest(搜索请求)

{
  "query": "string (必填)",
  "topK": "integer (可选, 默认10)",
  "filters": {
    "任意字段": "任意值(完全动态)"
  }
}

SearchResult(搜索结果)

{
  "docId": "string",
  "chunkId": "string",
  "chunkIndex": "integer",
  "content": "string",
  "score": "float",
  "metadata": {
    "所有文档元数据字段(不包含embedding)"
  }
}

注意: metadata 中不包含 embedding 字段,以节省带宽。


🧪 完整测试用例清单

测试环境要求

  • ✅ Elasticsearch 8.x 运行正常
  • ✅ Embedding API 服务可用
  • ✅ 应用服务运行在 http://localhost:8084

执行测试

# 运行完整测试套件
bash test_api.sh

# 查看测试结果
cat api_test_results.txt

测试用例总览

模块 用例数 涵盖场景
健康检查 1 服务状态检查
文档入库 6 正常入库、参数校验、多数据类型、动态字段
批量入库 4 正常批量、空列表、大批量、部分失败
向量搜索 5 语义搜索、空查询、指定数量、无结果
混合搜索 5 合同过滤、音频过滤、视频过滤、多条件
文档管理 5 查询、删除文档和chunk
合计 26 覆盖所有核心场景

📝 附录

A. 快速开始

1. 启动服务

# 启动应用
java -jar schedule-embedding-api.jar

# 或使用 Maven
mvn spring-boot:run

2. 验证服务

curl http://localhost:8084/actuator/health

3. 测试文档入库

curl -X POST http://localhost:8084/api/v1/documents/index \
  -H "Content-Type: application/json" \
  -d '{
    "docId": "test-001",
    "fullText": "测试文档内容"
  }'

4. 测试向量搜索

curl -X POST http://localhost:8084/api/v1/search \
  -H "Content-Type: application/json" \
  -d '{
    "query": "测试",
    "topK": 5
  }'

B. 常见问题

Q1: 为什么向量搜索返回空数组?

A: 可能的原因:

  1. ES 中还没有相关文档,先执行文档入库
  2. 查询文本与现有文档语义差异较大
  3. ES 索引延迟,等待几秒后重试

Q2: 如何提高搜索准确度?

A: 建议:

  1. 入库时提供完整的文档内容
  2. 使用与文档风格相似的查询文本
  3. 调整 topK 参数获取更多结果
  4. 使用混合搜索添加业务过滤条件

Q3: 批量入库有限制吗?

A:

  • 单次批量请求建议不超过 100 个文档
  • 超长文本会自动分片处理
  • 建议分批次大批量数据

Q4: metadata 支持哪些字段?

A:

  • 支持任意自定义字段,完全动态化
  • 合同类:contractType, partyA, partyB, contractAmount 等
  • 音频类:duration, speaker, language, sampleRate 等
  • 视频类:resolution, frameRate, codec, duration 等
  • 图片类:width, height, format, dpi 等
  • 任意其他自定义字段

Q5: 新增字段需要修改代码吗?

A:

  • 完全不需要
  • 直接在 metadata 中添加任意字段即可
  • 系统会自动识别、存储、索引
  • 搜索时也可以直接使用新字段过滤

C. 性能指标

指标 数值 说明
单文档入库 < 2s 包含向量化时间
批量入库(10个) < 5s 并发处理
向量搜索 < 1s topK=10
混合搜索 < 1.5s 包含过滤
向量维度 4096 Qwen3-Embedding-8B
响应大小优化 ~16KB/结果 移除embedding字段

D. 设计优势

1. ES动态映射(DynamicMapping)

本系统使用 Elasticsearch 的 动态映射 功能,实现真正的零代码扩展:

// 创建索引时启用动态映射
.mappings(m -> m
    .dynamic(DynamicMapping.True)  // 关键配置!
    .properties("doc_id", p -> p.keyword(k -> k))
    .properties("chunk_id", p -> p.keyword(k -> k))
    // ... 核心字段
    // 其他字段自动识别!
)

效果

  • 传入任意 metadata 字段,ES 自动创建索引
  • 自动推断字段类型(字符串、数字、日期等)
  • 无需修改代码,新增字段即生效

2. 完全动态化(代码层面)

旧设计:

// 每个字段都要判断
if (metadata.containsKey("contractType")) {
    doc.setContractType((String) metadata.get("contractType"));
}
if (metadata.containsKey("duration")) {
    doc.setDuration((Integer) metadata.get("duration"));
}
// ... 无穷无尽的 if

新设计:

// 所有字段自动处理,只有 1 行代码!
doc.addExtendedFields(request.getMetadata());

3. 类型无关

  • ✅ 合同文档、音频、视频、图片等任意类型
  • ✅ 每种类型有自己独特的业务字段
  • ✅ 无需为每种类型定义不同的实体类

4. 零代码扩展

操作 旧设计 新设计
新增合同字段 修改 ES Mapping + 代码 直接在 metadata 加字段
新增音频字段 修改 ES Mapping + 代码 直接在 metadata 加字段
新增视频字段 修改 ES Mapping + 代码 直接在 metadata 加字段
新增任意字段 修改 ES Mapping + 代码 直接在 metadata 加字段

E. 联系方式

  • 项目地址: /Users/Vova/Gitee/four-level-schedule/schedule-embedding-api
  • 测试脚本: test_api.sh(基础测试), test_complete.sh(完整功能测试)
  • 数据模型文档: 数据模型设计文档.md

📝 实际使用示例

基于解析结果示例材料的典型入库请求:

示例1:银行流水文档

curl -X POST http://localhost:8084/api/v1/documents/index \
  -H "Content-Type: application/json" \
  -d '{
    "docId": "bank-flow-001",
    "fileName": "111111133.png",
    "fullText": "账户明细...交易记录...",
    "filePath": "/data/files/20260313_8f9e7d6c5b4a.png",
    "fileSize": 102400,
    "fileType": "png",
    "metadata": {
      "file_unique_id": "20260313_8f9e7d6c5b4a",
      "business_topic": "金融-信贷审批",
      "document_type": "银行流水",
      "belong_department": "风控部",
      "tags": ["信贷", "流水", "合规", "农业"]
    }
  }'

示例2:操作手册文档

curl -X POST http://localhost:8084/api/v1/documents/index \
  -H "Content-Type: application/json" \
  -d '{
    "docId": "manual-001",
    "fileName": "宇信科技操作手册.docx",
    "fullText": "宇信科技管理数智化星云平台 快速入门操作手册...",
    "filePath": "/data/files/manual.docx",
    "fileSize": 2048000,
    "fileType": "docx",
    "metadata": {
      "business_topic": "金融-系统文件",
      "document_type": "操作手册",
      "belong_department": "产品部",
      "tags": ["金融", "企管", "星云", "操作手册"]
    }
  }'

典型metadata字段说明

字段名 类型 说明 示例值
file_unique_id String 文件唯一标识 "20260313_8f9e7d6c5b4a"
business_topic String 业务主题 "金融-信贷审批"
document_type String 文档类型 "银行流水"、"操作手册"、"贷款合同"
belong_department String 所属部门 "风控部"、"信贷部"、"审计部"
tags Array 标签数组 ["信贷", "流水", "合规"]

搜索示例

向量搜索

curl -X POST http://localhost:8084/api/v1/search \
  -H "Content-Type: application/json" \
  -d '{
    "query": "银行流水交易记录",
    "topK": 5
  }'

混合搜索(按业务维度过滤)

curl -X POST http://localhost:8084/api/v1/search/hybrid \
  -H "Content-Type: application/json" \
  -d '{
    "query": "风险评估",
    "topK": 5,
    "filters": {
      "business_topic": "金融-风险管理",
      "belong_department": "风控部"
    }
  }'

文档结束