- Removed multiple failed document entries from `documents.json`. - Added a new document entry with updated metadata and changed the index name to `regulations_dense_1024_v2`. - Updated architecture documentation to reflect changes in the Milvus collection name. - Adjusted requirements by removing the sqlalchemy dependency. - Modified test cases to align with new document structure and naming conventions. - Introduced a new test file for Milvus vector index runtime recovery and error handling. - Updated assertions in various test files to ensure compatibility with the new schema.
6.7 KiB
文档解析与向量检索说明
相关文件
aliyun_doc_parser.py:调用阿里云文档智能解析 PDF,生成原始layouts.jsonlayouts_to_vector_chunks.py:把layouts.json转成适合向量数据库入库的三层结构layouts.json:阿里云返回的原始布局结果vector_chunks.json:转换后的结构化输出
一、layouts.json 的结构
layouts.json 顶层是一个数组,每个元素代表一个布局块(layout)。常见字段如下:
type:主类型,例如title、text、table、figuresubType:更细的语义类型,例如doc_title、para_title、para、picture、pic_title、pic_captiontext:当前布局块的纯文本markdownContent:带 markdown 标记的文本pageNum:页码index:页内顺序level:标题层级uniqueId:布局块唯一标识blocks:更细粒度的文本与样式信息cells:表格单元格,仅table类型存在
这个结构不是简单 OCR 文本流,而是已经带有版面理解和语义分类的结构化数据。
二、推荐的三层转换结构
1. 结构层 structure_nodes
结构层用于恢复文档标题树,不直接作为最终向量检索单元。
示例:
1 范围2 规范性引用文件3 术语和定义3.1 儿童三轮车3.2 轮距
结构层主要用于给下游 chunk 绑定 section_path。
2. 语义层 semantic_blocks
语义层是按文档意义聚合后的内容块,主要分为三类:
section_text:同一章节下连续正文聚合而成table:表格内容单独成块figure:图、图名、图注等单独成块
这一层比单 layout 更适合做语义理解,也适合后续做上下文扩展。
3. 检索层 vector_chunks
检索层是最终写进向量数据库的 chunk。
处理方式:
- 对
semantic_blocks中较短的块直接入库 - 对较长的块按
max_chars再切分 - 相邻切片保留
overlap_chars重叠 - 每个 chunk 都带完整 metadata,便于后续过滤、重排和邻域扩展
三、当前转换脚本做了什么
layouts_to_vector_chunks.py 当前已经实现:
- 过滤目录页噪声(如
目次) - 根据标题层级维护章节路径
- 将正文聚合成
section_text - 将表格单独转成
table - 将图相关内容单独转成
figure - 对长文本继续切分为最终
vector_chunks - 为每个检索 chunk 生成
embedding_text
四、为什么不要直接按 layout 入库
如果把 layouts.json 的每条 layout 直接做向量:
- 颗粒度太碎
- 标题和正文容易分离
- 表格会丢失结构上下文
- 图示信息无法完整表达
- 检索命中结果噪声较大
对于标准文档,最合适的单位通常不是“句子”,而是“条款语义块”。
五、建议的入库字段
建议向量数据库每条记录至少保存:
embedding_text:用于生成向量text:原始 chunk 文本chunk_idsemantic_idchunk_type:section_text/table/figuresection_pathsection_titlesection_levelpage_startpage_enddoc_iddoc_titlesource_ids
其中:
- 向量化字段:
embedding_text - 展示字段:
text - 检索增强字段:其余 metadata
六、推荐的检索方式
不要只做最简单的 top-k 向量搜索,建议采用:
向量召回 + metadata 重排 + 邻域扩展
1. 向量召回
使用 vector_chunks[*].embedding_text 做 embedding,并在向量数据库中检索 top 10 ~ 15 条。
查询时可以对用户问题做轻微改写,例如:
原问题:
儿童三轮车的定义是什么?
可改写为:
请检索 GB 14747—2006 儿童三轮车安全要求 中关于“儿童三轮车定义”的条款、术语、表格或图示说明。
这样更适合标准文档检索。
2. metadata 重排
向量召回后,根据 metadata 做轻量规则重排。
常见规则:
chunk_type == section_text:对定义类、要求类问题优先级更高section_path命中查询关键词:例如查询“定义”时,术语和定义章节优先chunk_type == table:对“尺寸 / 参数 / 数值 / 对照 / 要求”类问题加权chunk_type == figure:对“图 / 结构 / 状态 / 示意”类问题加权
3. 邻域扩展
检索命中的是最终切片,但回答往往需要更完整上下文。
建议命中某个 vector_chunk 后:
- 优先回捞同一个
semantic_id下的所有 chunk - 如果还不够,再补充同
section_path、相邻页码或相邻chunk_index的内容
这样可以恢复完整条款,而不是只给模型一小段碎片。
七、不同问题的检索重点
1. 定义类问题
例如:
儿童三轮车的定义是什么?轮距是什么意思?
优先检索:
section_textsection_path中包含术语和定义的内容
2. 要求类问题
例如:
外露突出物有什么要求?辅助推杆有哪些安全要求?
优先检索:
section_texttable
3. 数值 / 尺寸 / 对照类问题
例如:
鞍座到脚蹬距离要求是什么?哪些项目需要满足规定尺寸?
优先检索:
tablesection_text
4. 图示说明类问题
例如:
正常乘骑状态是什么意思?图1表示什么?
优先检索:
figure- 同章节相邻
section_text
八、推荐的最终检索流程
建议采用以下固定流程:
- 用
vector_chunks.embedding_text做 embedding 检索 - 取 top 10 ~ 15 条候选
- 按
chunk_type + section_path做规则重排 - 以
semantic_id为中心回捞完整语义块 - 选 3 ~ 5 组上下文提供给大模型回答
九、给大模型的上下文组织方式
最终不要直接把原始 JSON 扔给模型,建议整理成如下格式:
[命中片段 1]
章节:3 术语和定义 > 3.1 儿童三轮车
页码:1-2
类型:section_text
内容:
......
[命中片段 2]
章节:4 要求 > 4.3 外露突出物
页码:5
类型:section_text
内容:
......
[命中片段 3]
章节:5 试验方法
页码:8
类型:table
内容:
......
这种格式更利于模型稳定回答并引用出处。
十、转换命令
生成三层结构:
python3 /home/huaci/dev/ai/SuperMew/tests/layouts_to_vector_chunks.py \
--layouts /home/huaci/dev/ai/SuperMew/tests/layouts.json \
--out /home/huaci/dev/ai/SuperMew/tests/vector_chunks.json
自定义切片大小:
python3 /home/huaci/dev/ai/SuperMew/tests/layouts_to_vector_chunks.py \
--layouts /home/huaci/dev/ai/SuperMew/tests/layouts.json \
--out /home/huaci/dev/ai/SuperMew/tests/vector_chunks.json \
--max-chars 500 \
--overlap-chars 80