16 KiB
PDF 文档转在线评测题库需求设计
1. 背景与问题
当前仓库已经具备一条完整的评测主链路:
main.py --scenario ...- 加载 dataset
- 标准化样本
- 调用 adapter
- 使用
ragas评分 - 写出本地运行资产
但这条链路默认前提是“评测数据已经存在”。现实里,RAG 项目的评测样本往往首先来自大量原始文档,例如 PDF 规范、制度、手册、法规或技术说明。没有一条稳定的“文档 -> 题库 dataset”生成链路,平台就仍然停留在手工准备数据的阶段。
你给出的外部示例项目已经验证了两件关键能力:
- 可以用阿里云文档解析服务对 PDF 做异步解析
- 可以把解析结果归一成结构节点、语义块和可追溯切片
因此,本轮需求设计的目标不是建设一个完整知识库系统,而是在当前评测平台里补上一条最小可用的数据生产链路,让原始 PDF 可以生成可复核的在线评测题库。
2. 目标
本需求设计的 V1 目标如下:
- 支持从单个 PDF 或一个 PDF 目录批量生成在线评测题库
- 解析能力基于阿里云文档解析服务
- 题目生成以单文档为边界,不跨文档混合
- 输出结果是可直接接入当前
online评测模式的 dataset 草稿 - 输出结果保留页码、章节、来源 chunk 等证据链,便于人工复核
- 复用当前仓库的本地文件优先原则,不引入数据库依赖
3. 非目标
V1 明确不覆盖以下范围:
- 不建设向量库入库能力
- 不建设文档上传 Web UI
- 不建设多租户文档中心
- 不支持跨文档综合题
- 不支持 Office 文档、图片包、网页抓取等多格式输入
- 不自动生成最终 gold dataset
- 不在 V1 中产出离线评测必需的
answer / contexts - 不复用外部项目中与向量化落库、知识库写入直接耦合的域模型
换句话说,V1 的目标是 先把 PDF 文档转成“可人工复核的在线评测题库草稿”,而不是一步演进成完整 RAG 数据工厂。
4. 用户价值
引入这条链路后,平台可以覆盖以下工作方式:
- 用户准备一批 PDF 文档
- 系统调用阿里云文档解析服务获取结构化版面结果
- 系统把版面结果归一成可追溯的 chunk
- 系统用 LLM 基于 chunk 生成问题与参考答案草稿
- 用户在导出的 dataset 上做人工复核
- 用户把复核后的 dataset 直接接入现有
online评测场景
这样平台就同时具备:
- 数据生产能力
- 数据复核能力
- 在线评测接入能力
- 结果资产沉淀能力
5. V1 核心决策
本轮设计固定以下产品决策:
- 输入文档范围:仅
PDF - 题目生成范围:仅
单文档题 - dataset 目标类型:
在线题库 - 发布方式:
先生成草稿,再人工复核 - 解析服务:阿里云文档解析
- 解析失败默认策略:
fail
这些决策不再留给后续实现阶段临时判断。
6. 目标架构总览
在现有评测架构之外,新增一条“dataset build”链路:
PDF files
-> dataset build config
-> aliyun parser gateway
-> layout normalization
-> source chunks
-> LLM question generation
-> draft online dataset
-> review
-> existing online evaluation flow
该链路与现有评测链路的关系如下:
dataset build负责“评测输入怎么生产”- 现有
rag_eval/execution/负责“生产好的评测输入怎么跑分”
二者职责分离,不相互污染。
7. 模块边界设计
7.1 CLI 入口
保留现有评测入口不变:
python main.py --scenario scenarios/offline/sample-offline.yaml
新增一个用于构建 dataset 的入口:
python main.py --dataset-build-config scenarios/dataset_build/sample-pdf-build.yaml
两个入口互斥,避免一次命令同时承担“建题库”和“跑评测”两个职责。
7.2 新增模块目录
新增主包:
rag_eval/
dataset_builder/
__init__.py
models.py
schema.py
runner.py
writers.py
sources.py
parser/
__init__.py
aliyun_docmind_gateway.py
aliyun_document_parser.py
aliyun_layout_normalizer.py
generator/
__init__.py
question_generator.py
validators.py
职责划分如下:
schema.py:校验 dataset build YAMLmodels.py:定义 job、解析结果、source chunk、生成样本等内部模型runner.py:串联一次完整 build jobwriters.py:写出 dataset 和本地资产sources.py:发现输入 PDF 文件parser/:适配阿里云文档解析能力generator/:调用 LLM 生成题目草稿并做输出校验
7.3 外部示例代码复用策略
允许从外部项目参考并迁移以下能力:
aliyun_docmind_gateway.pyaliyun_document_parser.pyaliyun_layout_normalizer.py
但复用范围只限于:
- 异步解析任务提交与轮询
- layout 拉取
- 结构节点提取
- 语义块合并
- 可追溯切片构建
不迁移以下职责:
- 向量库入库
- embedding 持久化
- 外部知识库 chunk 域模型
- 知识库索引流程
8. 配置设计
8.1 新增 YAML 类型
新增一类配置文件,例如:
scenarios/
dataset_build/
sample-pdf-build.yaml
8.2 配置字段
V1 的 dataset build YAML 结构固定如下:
job_name: legal-pdf-question-bank
input:
path: ../../datasets/raw/pdfs
glob: "*.pdf"
parser:
provider: aliyun_docmind
failure_mode: fail
generation:
model: qwen-long
output_type: online_question_bank
review_mode: draft_with_manual_review
max_questions_per_document: 10
max_source_chunks_per_question: 3
output:
dataset_path: ../../datasets/raw/generated/legal_question_bank.csv
artifact_dir: ../../outputs/dataset-builds/legal-pdf-question-bank
runtime:
max_documents: 20
8.3 字段约束
job_name:必填,作为本次构建任务名称input.path:必填,支持单文件或目录input.glob:可选,默认*.pdfparser.provider:V1 固定为aliyun_docmindparser.failure_mode:fail | skip,默认failgeneration.model:可选,允许覆盖默认生成模型generation.output_type:V1 固定为online_question_bankgeneration.review_mode:V1 固定为draft_with_manual_reviewgeneration.max_questions_per_document:正整数,默认10generation.max_source_chunks_per_question:正整数,默认3output.dataset_path:必填,最终 dataset 输出路径output.artifact_dir:必填,运行资产根目录runtime.max_documents:可选,用于限制一次处理文档数
9. 环境变量设计
9.1 阿里云解析配置
在 rag_eval/settings.py 中新增以下环境变量读取:
ALIBABA_ACCESS_KEY_IDALIBABA_ACCESS_KEY_SECRETALIBABA_ENDPOINTALIYUN_PARSE_POLL_INTERVAL_SECONDSALIYUN_PARSE_TIMEOUT_SECONDSALIYUN_PARSE_LAYOUT_STEP_SIZEALIYUN_LLM_ENHANCEMENTALIYUN_ENHANCEMENT_MODEDOCUMENT_PARSE_ARTIFACT_PREFIXPARSER_FAILURE_MODE
9.2 题库生成模型配置
新增环境变量:
DATASET_GENERATOR_MODEL
默认优先级如下:
- dataset build YAML 中的
generation.model .env中的DATASET_GENERATOR_MODEL- 代码默认值
9.3 密钥管理要求
设计文档只引用环境变量名,不在仓库文档中记录任何明文 AK/SK。当前已经暴露在会话里的密钥需要单独轮换,这属于实现前置的安全动作。
10. 核心数据模型设计
10.1 DatasetBuildJob
表示一次 PDF -> dataset 生成任务。
核心字段:
job_nameinput_pathinput_globparser_providerfailure_modegeneration_modeloutput_typereview_modedataset_pathartifact_dirruntime
10.2 ParsedDocument
表示一个 PDF 经解析和归一化后的文档。
核心字段:
doc_iddoc_nameraw_textstructure_nodessemantic_blockssource_chunksmetadata
10.3 SourceChunk
SourceChunk 是 V1 最关键的证据单元,用于生成题目和支持人工复核。
字段固定为:
chunk_iddoc_iddoc_nametextpage_startpage_endsection_pathsection_titlesource_layout_ids
设计原则:
- 每个 chunk 必须能反查来源页码
- 每个 chunk 必须能反查章节路径
- 每个 chunk 必须能反查原始 layout id
- 每个 chunk 只服务题库生成和证据追溯,不承担向量化职责
10.4 DraftQuestionSample
表示一条待复核的在线评测样本草稿。
字段固定为:
sample_idquestionground_truthscenariolanguagedoc_iddoc_namesection_pathpage_startpage_endsource_chunk_idsquestion_typedifficultyreview_statusreview_notes
10.5 枚举约束
review_status:draft | approved | rejected | needs_editquestion_type:fact | summary | procedure | comparisondifficulty:easy | medium | hard
11. 文档解析设计
11.1 解析输入范围
V1 仅接受:
- 单个
.pdf文件 - 或一个包含多个
.pdf的目录
目录模式下默认按 input.glob 扫描,默认值为 *.pdf。
11.2 解析流程
每个 PDF 的处理过程固定为:
- 发现文件
- 创建阿里云 Docmind client
- 提交异步解析任务
- 轮询直到成功、失败或超时
- 分页拉取全量 layout
- 归一成结构节点、语义块和 source chunk
- 写出中间资产
11.3 版面归一化规则
从外部示例代码中沿用以下核心规则:
- 识别标题层级
- 跳过目录页内容
- 合并连续段落文本
- 抽取表格为可检索纯文本
- 保留图注类文本
- 按固定窗口做长文本切块
- 为每个 chunk 注入章节头信息和页码追溯信息
11.4 错误处理
支持两种失败模式:
fail:任一文档解析失败则整个 job 失败skip:记录失败文档,继续处理其余文档
V1 默认策略为 fail。
12. 题库生成设计
12.1 生成单元
题目生成单元固定为“单文档内的一组 section-aware source chunks”。
约束如下:
- 一条题目只能引用同一个
doc_id - 一条题目最多引用
3个 chunk - 不允许跨文档混合证据
12.2 生成输出
每个候选题必须产出:
questionground_truthsource_chunk_idsquestion_typedifficulty
12.3 数量控制
V1 默认:
- 每个文档最多生成
10条题 - 每组 chunk 最多生成
1条题
实现时必须做覆盖率与多样性平衡,避免所有问题只集中在文档开头章节。
12.4 复核模式
V1 不自动发布最终 dataset,只输出草稿。
草稿规则:
review_status初始一律写为draftreview_notes初始为空- 人工可在 CSV 中修订问题、答案与审核状态
12.5 自动校验
候选题进入最终 dataset 前必须通过以下校验:
question非空ground_truth非空source_chunk_ids非空- 引用的 chunk 必须真实存在
- 所有引用 chunk 必须来自同一文档
question_type和difficulty必须落在允许枚举内
自动校验失败的候选题不进入最终 draft CSV。
12.6 去重规则
同一文档内执行如下去重:
- 问题文本归一化后完全相同则去重
- 引用 chunk 完全相同且参考答案语义近似的候选题只保留一条
V1 去重目标是控制明显重复,不追求复杂聚类算法。
13. 输出资产设计
13.1 Dataset 输出
最终 dataset 默认输出到:
datasets/raw/generated/<job_name>.csv
允许由 YAML 的 output.dataset_path 覆盖。
13.2 运行资产目录
每次构建任务的运行资产输出到:
outputs/dataset-builds/<job_name>/<run_id>/
13.3 必须输出的资产
每次运行至少写出以下文件:
documents.jsonlsemantic_blocks.jsonlsource_chunks.jsonldataset_draft.csvparse_failures.csvmetadata.json
含义如下:
documents.jsonl:逐文档解析摘要semantic_blocks.jsonl:逐语义块中间结果source_chunks.jsonl:逐切片证据结果dataset_draft.csv:生成后的题库草稿parse_failures.csv:失败文档清单metadata.json:运行元数据、配置快照、统计结果
14. 与现有评测链路的兼容性修正
14.1 当前问题
当前仓库的文档设计已经说明 online 模式往往只需要:
questionground_truth
然后由 adapter 在评测时补齐:
answercontexts
但当前 rag_eval/datasets/normalizers.py 仍然把 contexts / answer / ground_truth 统一视作必填。这与文档目标架构不一致,也会直接阻塞本需求设计生成的在线题库接入。
14.2 修正原则
后续实现必须把 dataset 校验改成按 mode 分流:
offline模式必须具备question / contexts / answer / ground_truthonline模式必须具备question / ground_truthonline模式允许contexts / answer在初始数据集中为空
14.3 设计影响
这个修正不是附属优化,而是本需求能够成立的前置条件。否则生成出来的在线题库无法进入当前评测主流程。
15. 流程设计
一次完整的 dataset build job 执行流程如下:
- 读取
--dataset-build-config - 校验 YAML 并生成
DatasetBuildJob - 扫描输入 PDF
- 按顺序或受控并发处理每个文档
- 调用阿里云文档解析
- 归一化 layout,生成
ParsedDocument - 萃取
SourceChunk - 基于
SourceChunk调用 LLM 生成题库草稿 - 对候选题做结构校验与去重
- 写出
dataset_draft.csv - 写出中间 artifacts 和失败清单
- 人工复核后,将复核版本作为
online评测输入
16. 测试设计
16.1 配置测试
需要覆盖:
--scenario与--dataset-build-config互斥- 缺失必填字段
- 非法枚举值
- 输入路径不存在
- 输入目录中没有 PDF
16.2 解析测试
使用 mocked 阿里云响应覆盖:
- 提交成功
- 状态轮询成功
- 状态轮询超时
- 任务失败
- 返回空 layouts
同时要覆盖版面归一化规则:
- 目录页跳过
- 标题层级继承
- 表格扁平化
- 图注抽取
- 长文本切块
16.3 题库生成测试
使用 mocked LLM 输出覆盖:
- 正常结构化生成
- 空题目
- 缺失 ground truth
- 引用不存在 chunk
- 跨文档引用
- 重复问题去重
16.4 端到端测试
需要至少有一组 mocked parser + mocked generator 的端到端流程测试,验证:
- 单 PDF 输入
- 多 PDF 输入
fail模式skip模式- 所有 artifact 均成功写出
16.5 评测回归测试
需要新增测试确保:
- 只包含
question / ground_truth / metadata的在线题库能被加载 - adapter 补齐
answer / contexts后,现有 evaluator 能继续跑完指标
17. 实施顺序建议
为了降低风险,后续实现建议按以下顺序推进:
- 先扩展
main.py和配置层,增加 dataset build 命令入口 - 再扩展
settings.py与依赖,接入阿里云解析配置 - 迁移 parser gateway 与 layout normalizer
- 落地
dataset_builder的 models、runner、writers - 实现 LLM 题库生成与输出校验
- 修正现有 online dataset 校验逻辑
- 补测试、样例 YAML 和文档
18. 最终结论
本需求设计固定了一个清晰、可落地的 V1 范围:
- 用阿里云解析 PDF
- 把解析结果转成可追溯 source chunks
- 用 LLM 基于单文档内容生成在线评测题库草稿
- 用人工复核保证最终质量
- 复核后的题库直接接入现有 online 评测流程
这个设计刻意收窄了输入格式、题型边界和自动化深度,目的不是保守,而是先确保整条链路能够在当前仓库架构中闭环,并且不给后续实现留下需要临场决策的空白。