feat: 添加Markdown分块器与统一批量分块入口,支持增量向量化与导入

- 新增 md_chunker.py: Markdown语义分块引擎,支持标题/代码块/表格智能拆分
- 新增 batch_chunker.py: 统一批量分块入口,支持JRXML+Markdown混合处理
- 新增 requirements.txt: 整理项目依赖
- embed_chunks.py: 新增 --incremental 增量模式,追加新向量到已有数据
- import_to_chroma.py: 新增 --incremental 增量模式,不再每次清空数据库
- 更新 README.md 与 docs/file_guide.md 反映最新架构

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-15 11:10:25 +08:00
parent 85bec09857
commit 0787901acc
7 changed files with 988 additions and 287 deletions
+156 -175
View File
@@ -4,110 +4,106 @@
---
## 1. collect_jrxml.py — JRXML 文件收集脚本
## 1. collect_jrxml.py — JRXML 文件收集
**功能**: 从指定的 JasperReports 模板库目录递归收集所有 `.jrxml` 文件,复制到项目 `jrxml_source` 目录。
**功能**: 从 JasperReports 模板库目录递归收集 `.jrxml` 文件,复制到项目 `jrxml_source` 目录。
**输入**:
- 源目录: `C:\Users\zy187\JaspersoftWorkspace\JasperReportsSamples`(可修改)
**输入**: 源目录路径(硬编码,可按需修改)
**输出**:
- `jrxml_source/` 目录,包含所有收集到的 JRXML 文件
**输出**: `jrxml_source/` 目录
**使用方式**:
```bash
python collect_jrxml.py
```
**核心逻辑**:
- 使用 `os.walk()` 递归遍历源目录
- 筛选 `.jrxml` 后缀文件
- 自动处理文件名冲突(添加数字后缀)
- 使用 `shutil.copy2()` 保留文件元数据
---
## 2. jrxml_chunker.py — JRXML 语义分块引擎 (v3.0)
**功能**: 将单个 JRXML 文件按语义结构拆分,每个 chunk 包含人类可读描述、原始 XML 和结构化元数据
**输入**: 单个 `.jrxml` 文件路径(或目录)
**输出**: `JRXMLChunk` 列表,字段包括:
- `chunk_id`: 文件内序号
- `chunk_type`: 分块类型 (如 `query`, `band_detail`, `chart` 等)
- `human_description`: 人类可读描述
- `raw_xml`: 原始 XML 片段
- `context`: 所属报表名称
- `metadata`: 元数据 (report_name, band_name, element_kind 等)
**支持的数据源**: SQL, HQL, XPath, JSON, JSONQL, CSV, Data Adapter, Bean Collection, Empty
**使用方式**:
```bash
python jrxml_chunker.py report.jrxml # 单文件
python jrxml_chunker.py ./jrxml_source/ # 目录
```
---
## 2. jrxml_chunker.py — JRXML 语义分块核心引擎
## 3. jrxml_banch_chunker.py — JRXML 批量分块 (单类型)
**功能**: 将单个 JRXML 文件按语义结构拆分为多个 chunk,每个 chunk 包含人类可读描述、原始 XML 和元数据
**功能**: 批量处理目录下所有 JRXML 文件,生成统计报告和按文件分类的输出。是旧版入口,被 `batch_chunker.py` 取代
**输入**:
- 单个 JRXML 文件路径
**使用方式**:
```bash
python jrxml_banch_chunker.py ./jrxml_source --output ./output
```
**输出**:
- `JRXMLChunk` 对象列表,每个包含:
- `chunk_id`: 唯一标识
- `chunk_type`: 分块类型(如 `query`, `field`, `band_title` 等)
- `human_description`: 人类可读的结构化描述
- `raw_xml`: 原始 XML 片段
- `context`: 上下文信息(所属报表名称)
- `metadata`: 元数据字典
---
**核心类**:
- `JRXMLChunk`: 单个 chunk 的数据结构
- `JRXMLSemanticChunker`: 主分块器,支持多种数据源类型(SQL、HQL、XPath、JSON、CSV 等)
## 4. md_chunker.py — Markdown 语义分块引擎
**功能**: 将 Markdown 文件按标题层级、代码块、表格等结构化元素智能分块。
**输入**: 单个 `.md` 文件路径(或目录)
**输出**: `MDChunk` 列表,字段包括:
- `chunk_id`: 文件内序号
- `chunk_type`: 分块类型 (`section_h1`, `code`, `section_installation` 等)
- `human_description`: 人类可读描述
- `raw_content`: 原始 Markdown 内容
- `context`: 所属文档标题
- `metadata`: 元数据 (heading, heading_level, language 等)
**分块策略**:
- XML 元素类型分类(field、parameter、variable、band、chart 等)
- 提取数据源配置和查询语句
- 保留元素间的层级关系
- 为每个 chunk 生成结构化的人类可读描述
-标题层级 (H1/H2/H3) 划分段落
- 代码块作为独立 chunk
- 表格作为独立 chunk
- H2 标题自动识别特殊类型(安装、配置、API、示例等)
- 过长段落按段落/句子二次拆分
**使用方式**:
```bash
# 处理单个文件
python jrxml_chunker.py report.jrxml
# 处理整个目录
python jrxml_chunker.py ./jrxml_source/
python md_chunker.py doc.md # 单文件
python md_chunker.py ./docs/ # 目录
```
---
## 3. jrxml_banch_chunker.py — 批量分块入口脚本
## 5. batch_chunker.py — 统一批量分块入口
**功能**: 批量处理目录下所有 JRXML 文件,生成统计报告和分类输出
**功能**: 统一入口,支持 JRXML 和 Markdown 文件混合批量处理,生成合并的 chunks 和统计报告
**输入**:
- JRXML 文件目录(默认: `jrxml_source`
**输入**: 包含 `.jrxml` / `.md` 文件的目录
**输出**:
- `jrxml_chunker_output/all_chunks.json`: 所有 chunks 合并文件
- `jrxml_chunker_output/processing_stats.json`: 处理统计成功/失败数、耗时、chunk 类型分布
- `jrxml_chunker_output/per_file/`: 按原文件分类的独立 chunk 文件
**核心函数**:
- `batch_chunk_with_report()`: 批量处理目录
- `chunk_single_file_with_report()`: 处理单个文件
- `all_chunks.json`: 所有 chunks 合并
- `processing_stats.json`: 处理统计 (成功/失败/耗时/类型分布)
**使用方式**:
```bash
# 使用默认输入目录
python jrxml_banch_chunker.py
# 指定输入目录
python jrxml_banch_chunker.py ./jrxml_source
# 指定输出目录
python jrxml_banch_chunker.py ./jrxml_source --output ./my_output
python batch_chunker.py ./mixed_source
python batch_chunker.py ./mixed_source --output ./my_output
```
---
## 4. down_embedding_model.py — 嵌入模型下载脚本
## 6. down_embedding_model.py — 嵌入模型下载
**功能**: 从 HuggingFace Hub 下载 Qwen3-Embedding-4B 嵌入模型到本地。
**输入**:
- HuggingFace 模型仓库: `Qwen/Qwen3-Embedding-4B`
**输出**:
- `models/Qwen3-Embedding-4B/` 目录,包含完整的模型文件
**特性**:
- 使用国内镜像加速下载(`hf-mirror.com`
- 支持断点续传
- 自动安装依赖
**功能**: 从 HuggingFace Hub 下载嵌入模型到本地。支持国内镜像加速和断点续传
**使用方式**:
```bash
@@ -116,121 +112,103 @@ python down_embedding_model.py
---
## 5. embed_chunks.py — Chunk 向量化脚本
## 7. embed_chunks.py — Chunk 向量化
**功能**: 使用嵌入模型将分块后的文本转换为向量表示,支持 GPU 加速和 FP16 半精度。
**功能**: 使用嵌入模型将 chunks 转换为向量支持 GPU/CPU、FP16 半精度**支持增量模式**
**输入**:
- `jrxml_chunker_output/all_chunks.json`(默认)
**输入**: chunks JSON 文件 (默认 `jrxml_chunker_output/all_chunks.json`)
**输出**:
- `embeddings/embeddings.npy`: 向量矩阵float32
- `embeddings/chunk_id_map.json`: chunk ID 映射
- `embeddings/chunk_type_map.json`: chunk 类型映射
- `embeddings/chunks.json`: 原始 chunks 副本
- `embeddings/embeddings.npy`: 向量矩阵 (float32)
- `embeddings/chunks.json`: 原始 chunks
- `embeddings/chunk_id_map.json` / `chunk_type_map.json`: 映射文件
- `embeddings/embeddings.pkl`: 完整数据 pickle
**核心函数**:
- `build_text_for_embedding()`: 将 chunk 转换为适合向量化的文本(拼接类型、描述、XML、元数据)
- `main()`: 主流程(加载→编码→保存→质量检查)
**特性**:
- 自动检测 CUDA/CPU
- 默认启用 FP16 半精度(节省约 50% 显存)
- 支持 HuggingFace Hub 在线模型
- 向量归一化 + NaN 检测
**使用方式**:
**全量模式**:
```bash
# 使用默认设置
python embed_chunks.py
# 指定模型和 batch size
python embed_chunks.py --model_path "sentence-transformers/all-MiniLM-L6-v2" --batch_size 64
# 使用本地 Qwen3 模型
python embed_chunks.py --batch_size 2
# 禁用 FP16
python embed_chunks.py --no_fp16 --batch_size 1
python embed_chunks.py --model_path "sentence-transformers/all-MiniLM-L6-v2"
```
---
## 6. import_to_chroma.py — 向量导入 Chroma 数据库
**功能**: 将已生成的向量和 chunks 导入 Chroma 持久化向量数据库。
**输入**:
- `embeddings/embeddings.npy`: 向量矩阵
- `embeddings/chunks.json`: chunks 数据
**输出**:
- `chroma_db/`: Chroma 持久化数据库目录
- 集合名称: `jrxml_chunks`(默认)
**核心逻辑**:
- 加载向量和 chunks
- 初始化 Chroma PersistentClient
- 创建集合(余弦相似度)
- 分批导入(每批 1000 条)
- 提取元数据(chunk_type、report_name、band_name 等)
- 快速验证查询
**使用方式**:
**增量模式** (`--incremental` / `-i`):
```bash
# 使用默认设置
python import_to_chroma.py
# 指定路径
python import_to_chroma.py --embeddings_dir ./embeddings --chroma_path ./chroma_db
# 只向量化新增 chunks,自动合并到已有向量数据
python embed_chunks.py ./new_chunks/all_chunks.json --incremental
```
增量模式逻辑:
1. 加载已有 `embeddings.npy` + `chunks.json`
2.`(context, chunk_id)` 去重
3. 只向量化新 chunks
4. 合并新旧数据后保存
---
## 7. query_chroma.py — 语义搜索查询工具
## 8. import_to_chroma.py — Chroma 向量入库
**功能**: 通过自然语言查询 Chroma 数据库,检索相关的 JRXML chunk
**功能**: 将向量数据导入 Chroma 持久化数据库。**支持增量模式**
**输入**:
- 用户自然语言查询
- 可选的元数据过滤条件
**输入**: `embeddings/embeddings.npy` + `embeddings/chunks.json`
**输出**:
- 相似度排序的检索结果(含 chunk 类型、报表名称、区域、内容摘要)
**输出**: `chroma_db/` 持久化数据库
**核心类**:
- `JRXMLSearcher`: 搜索器,封装模型加载、向量编码和 Chroma 查询
**全量模式** (删除旧集合重建):
```bash
python import_to_chroma.py
```
**核心方法**:
- `search()`: 基础语义搜索
- `search_with_threshold()`: 带相似度阈值的搜索
- `format_result()`: 格式化输出结果
**增量模式** (`--incremental` / `-i`):
```bash
# 追加新记录到已有集合,不删除已有数据
python import_to_chroma.py --incremental
```
增量模式逻辑:
1. 使用 `get_or_create_collection` (不删除已有数据)
2. 查询已有 ID,跳过已导入的记录
3. 只追加新增数据
---
## 9. query_chroma.py — 语义搜索查询
**功能**: 通过自然语言查询 Chroma 数据库,检索相关的 JRXML/Markdown chunks。
**两种模式**:
1. **命令行单次查询**: `python query_chroma.py "查询内容"`
2. **交互模式**: `python query_chroma.py`支持连续查询和内联命令)
- 命令行单次查询: `python query_chroma.py "查询内容"`
- 交互模式: `python query_chroma.py` (支持连续查询)
**交互模式命令**:
```
filter:<类型> 按 chunk_type 过滤如 filter:query
t:<阈值> 设置相似度阈值 0~1(如 t:0.5
k:<数量> 设置返回结果数(如 k:10
filter:<类型> 按 chunk_type 过滤 (如 filter:query)
t:<阈值> 设置相似度阈值 0~1
k:<数量> 设置返回结果数
```
**使用方式**:
```bash
# 交互模式
python query_chroma.py
# 单次查询
python query_chroma.py "如何修改报表标题"
# 按类型过滤
python query_chroma.py # 交互模式
python query_chroma.py "如何修改报表标题" # 单次查询
python query_chroma.py "SQL怎么写" --filter_field query
python query_chroma.py "参数" --threshold 0.5 --n_results 10
```
# 设置阈值和返回数量
python query_chroma.py "报表参数" --threshold 0.5 --n_results 10
---
## 10. config.py — 统一配置管理
**功能**: 从 `.env` 文件加载所有配置项,所有脚本通过此模块获取配置。
**配置分组**:
- 模型配置: `EMBEDDING_MODEL_NAME`, `EMBEDDING_MODEL_PATH`, `HF_ENDPOINT`
- 硬件配置: `USE_GPU`, `USE_FP16`, `BATCH_SIZE`
- 目录配置: `JRXML_SOURCE_DIR`, `CHUNKER_OUTPUT_DIR`, `EMBEDDINGS_DIR`, `CHROMA_DB_PATH`
- 分块配置: `MAX_CHUNK_SIZE`
- 查询配置: `DEFAULT_N_RESULTS`, `SIMILARITY_THRESHOLD`
```bash
python config.py # 打印当前配置
```
---
@@ -238,26 +216,27 @@ python query_chroma.py "报表参数" --threshold 0.5 --n_results 10
## 数据流全景
```
┌─────────────────┐
│ JasperReports C:\Users\...\JasperReportsSamples
模板库
└────────────────┘
│ collect_jrxml.py
┌─────────────────┐
│ jrxml_source/ 收集的 JRXML 文件
└────────┬────────┘
│ jrxml_banch_chunker.py (调用 jrxml_chunker.py)
┌─────────────────────
│ JasperReports 模板库(.jrxml)
Markdown 文档 (.md)
└──────────┬──────────┘
│ collect_jrxml.py / 手动放置
┌─────────────────────
│ jrxml_source/ │ 源文件目录
│ docs/ │
└──────────┬──────────┘
│ batch_chunker.py (调用 jrxml_chunker.py + md_chunker.py)
┌──────────────────────┐
│ jrxml_chunker_output/│ all_chunks.json + per_file/
└─────────────────────┘
│ embed_chunks.py (使用 Qwen3-Embedding-4B)
│ jrxml_chunker_output/│ all_chunks.json + processing_stats.json
└─────────────────────┘
│ embed_chunks.py (Qwen3-Embedding, 支持增量)
┌─────────────────┐
│ embeddings/ │ embeddings.npy + chunks.json
└────────┬────────┘
│ import_to_chroma.py
│ import_to_chroma.py (ChromaDB, 支持增量)
┌─────────────────┐
│ chroma_db/ │ Chroma 向量数据库
@@ -265,18 +244,20 @@ python query_chroma.py "报表参数" --threshold 0.5 --n_results 10
│ query_chroma.py
┌─────────────────┐
用户查询 │ 自然语言 → 相关 JRXML chunks
自然语言查询 │ 返回相关 chunks
└─────────────────┘
```
## 依赖关系
```
query_chroma.py ──────► chromadb, sentence_transformers, torch
import_to_chroma.py ──► chromadb, numpy
embed_chunks.py ──────► sentence_transformers, torch, numpy
down_embedding_model.py ► huggingface_hub
jrxml_banch_chunker.py ─► jrxml_chunker.py
jrxml_chunker.py ─────► xml.etree.ElementTree (标准库)
collect_jrxml.py ─────► 标准库 (os, shutil)
```
query_chroma.py ──────────► chromadb, sentence_transformers, torch
import_to_chroma.py ──────► chromadb, numpy
embed_chunks.py ──────────► sentence_transformers, torch, numpy
down_embedding_model.py ──► huggingface_hub
batch_chunker.py ─────────► jrxml_chunker.py, md_chunker.py
md_chunker.py ────────────► 标准库 (re, json, pathlib)
jrxml_chunker.py ─────────► xml.etree.ElementTree (标准库)
config.py ────────────────► 标准库 (os, pathlib)
collect_jrxml.py ─────────► 标准库 (os, shutil)
```