🌊 海上风电工程文档智能问答工作流
文档解析 + 信息抽取 + 表格精确查询 + 一致性审计。默认加载《某海域500MW海上风电场工程初步设计说明书》,也可上传任意海上风电文档测试泛化能力。
💡 想确认「不是把 PDF 直接丢给大模型」?请看 解析详情 与 LLM 输入透视 两个标签页——那里展示了 PDF 被解析、分块、表格摊平、规则检测后的全部中间产物。
预设题目(点击填入,均为零 token 标准答案)
PDF 经 DocumentParser 解析为「文本块 + 结构化表格」,再由 RuleDetector 做确定性检测。以下均为真实中间产物,不经 LLM。
输入任一问题,查看它实际会喂给 LLM 的内容——小文档走全文、大文档走 BM25 召回 Top-K。进入 Prompt 的始终是解析后的文本/召回段落,而非原始 PDF。此操作只做检索预览,不调用 LLM、不计费。
上传另一份海上风电工程 PDF,系统会重新解析并重建工作流,随后可在「问答」页对新文档提问、在「解析详情」看新文档的中间产物。
说明:表格题(Q6)列名摊平规则、章节正则针对本类文档设计,极端版式可能需微调;详见说明文档第六、八节。
海上风电工程文档智能问答工作流 — 说明文档
配套代码:
04_Agent集成/(入口见其README.md) 答案:05_交付产物/answers.md评分:eval_report.md
一、系统概述
本系统是一个面向工程初步设计文档的智能体问答工作流。输入一份海上风电场初步设计说明书 PDF,自动完成解析、信息抽取、表格精确查询与一致性审计,回答 7 类问题。核心解决"长文档中信息分散、表格与正文混排、存在多版本/多口径冲突值"的抽取难题,适用于风电及同类工程文档的理解与质检场景。
二、整体架构
┌─────────────────────────────────────────┐
│ 输入层:PDF 文档 │
└──────────────┬──────────────────────────┘
▼
┌─────────────────────────────────────────┐
│ 解析层:DocumentParser(pdfplumber) │
│ 文本块(text_chunks)+ 表格(tables) │
└──────────┬────────────────┬─────────────┘
▼ ▼
┌──────────────────┐ ┌─────────────────────┐
│ RuleDetector │ │ TableQueryEngine │
│ 7 类传统检测算法 │ │ 行列精确匹配(Q6) │
└────────┬─────────┘ └──────────┬──────────┘
└─────────┬─────────────┘
▼
┌─────────────────────────────────────────┐
│ 推理层:Agent + LLM │
│ QAAgent(Q1~Q5,检索/全文双路径) │
│ └ Retriever(BM25,大文档时召回) │
│ AuditAgent(Q7,规则结果 + LLM 解释) │
└──────────────────┬──────────────────────┘
▼
┌─────────────────────────────────────────┐
│ 工作流层:WindFarmQAWorkflow │
│ 题型路由 + CLI + Gradio Web UI │
└─────────────────────────────────────────┘
为什么表格和文本分离处理: 测风数据表是多行多列的数值矩阵,"2019年5月、90m"这类查询本质是行列坐标定位,纯文本检索或 LLM 阅读极易在相邻数值间错位(尤其两座测风塔 6633#/6634# 共用一张表时)。把表格抽成结构化数据、由专用引擎做精确匹配,比让 LLM"读表"可靠得多,且零成本、零延迟。
为什么 Q7 走"规则检测 + LLM"两段式而非纯 LLM: 一致性问题中,数值冲突、表格离群、范围倒置、正文-表格不符、投资反算、规范引用这类是确定性的、可被算法精确发现的;纯靠 LLM 通读全文找冲突,既可能漏(注意力分散在长文档)也可能编(幻觉出不存在的冲突)。先用规则引擎(7 类算法)"锚定"候选问题清单交给 LLM,LLM 只负责"确认 + 解释原因",并补充语义类问题(如工期口径),既保召回又压幻觉。最终 Q7 计入 8 处不一致:7 处由规则引擎确定性锁定(命中 9 条、归并 7 类)+ 1 处工期口径由 LLM 补充并经人工确认。此外,规则引擎/人工对误报也做了处置——第9章"同类工程参考"中的 300MW 属参考工程(按章节排除)、"防腐年限30年 > 结构寿命25年"属合规冗余设计(非矛盾、不计入),体现"并非所有数值不一致都是问题"的判断。
这一选择有实测对照支撑(脚本 05_交付产物/q7_对照实验.py):用完全相同的解析全文,去掉规则锚点让 LLM 自己找不一致、各跑 5 次——纯 LLM 在 temperature=0 下报 1617 处(混入大量文档质量类琐碎项)、temperature=1 下在 815 处间剧烈波动(标准差 2.45,不可复现);而规则引擎确定性锁定的核心事项每次完全一致(标准差 0)。对纯 LLM 输出逐条人工核对后确认:其中确有真问题(工期口径、正文-表格不符等,已分别并入规则引擎或答案),也有重复计数与偶发幻觉——纯 LLM 的毛病不在"全假",而在不可复现 + 重复噪声 + 把核心矛盾与排版瑕疵混为一谈。这正是两段式"让确定性的归算法、让解释的归 LLM"的价值:结果稳定、可复现、信噪比高。
三、关键模块说明
| 模块 | 职责 | 核心技术 | 关键设计决策 |
|---|---|---|---|
| DocumentParser | PDF→结构化 JSON | pdfplumber | 跨页表合并 + 合并表头摊平为塔号前缀列名(6633#_90m) |
| TableQueryEngine | 表格精确查询 | 关键词行列子串匹配 | 一张表内靠摊平列名区分双塔,不过滤异常值 |
| RuleDetector | 候选问题检测 | re、statistics(标准库) | 零 LLM 依赖,7 类算法(数值冲突/表格离群/范围倒置/名称/正文-表格/投资反算/规范引用),行内对比抗异常值污染 |
| Retriever | 相关段落召回 | BM25(纯标准库实现) | 大文档触发,无 embedding 服务、换文档即用 |
| QAAgent | Q1~Q5 问答 | LLM(模型无关封装) | 检索 + 全文双路径,按文档体量自适应 |
| AuditAgent | Q7 审计 | 规则结果 + LLM | 两段式,减少漏报与幻觉 |
四、运行方式
详见 04_Agent集成/README.md(3 步:装依赖 → 配 .env → python run.py --all 或 python app.py)。依赖仅 4 个包,temperature=0 保证可复现。
五、7 个问题回答结果
完整答案见 05_交付产物/answers.md,自动评分 90/100(eval_report.md)。关键发现摘要:项目名称为"某海域海上风电场一期工程"(第8章"陆上上"系笔误);机型 8MW/11MW 两种;总装机 500MW(规划)/502MW(实际)双口径;常浪向 ENE;66kV 单母线分段接线;2019年5月90m 风速 6633#=8.32、6634#=8.33 m/s;Q7 共识别 8 处不一致(名称笔误、容量口径、测风数据异常、正文-表格风速不符、投资反算不闭合、参考工程范围倒置、规范编号引用不符 7 类由规则引擎锁定 + 工期口径由 LLM 补充),并排除 300MW、防腐年限等合理差异。
六、泛化能力说明
系统按"通用 / 自适应 / 需调整"三层设计泛化性。通用部分:Prompt 模板、题型路由规则、七类规则检测算法、BM25 检索均与具体文档无关——BM25 用纯标准库实现,换文档即用、无需重建 embedding、零冷启动,最契合"面试现场换另一份海上风电文档"的场景。自适应部分:QAAgent 按文档总字数在"全文投喂"与"BM25 召回 Top-K"两条路径间自动切换(阈值默认 8000 字,本文档 7340 字走全文、无召回损失;更大文档自动走检索、不超 context),上层透明无感。换文档只需 python run.py --pdf 新文档.pdf --all --reparse,其余自动适配。需调整部分:表头摊平规则对极端表头结构(多于两层、跨页表头排布差异大)的鲁棒性、章节标题正则的覆盖度,可能随文档版式变化需要微调;Q6 的期望真值是本文档回归基线,换文档后应改由 TableQueryEngine 动态返回并人工抽查,而非沿用固定数字断言。
七、复杂场景处理设计思路
- 7.1 跨页表格识别与合并 + 合并表头摊平:测风表跨第 3、4 页,第 4 页重复出现塔号表头行。解析时按"列数一致 + 首列为表头标识"判定续表、剔除重复表头行并入数据;两行合并表头(行0 塔号合并单元格 + 行1 高度层)经前向填充后纵向拼接为
6633#_90m / 6634#_90m唯一列名,根除双塔子列错位——这是 Q6 正确性的根。 - 7.2 多值冲突检测:在出现锚定关键词的句子内提取数值并 set 去重,size>1 即报冲突(500MW vs 502MW);离群检测对测风表用"行内对比"为主路径(同月各高度量级相近,低于同行中位数 40% 即离群),避免普通 3σ 被异常值自身污染而漏检 0.17/2.22。
- 7.3 大文档 Token 控制:超阈值时 BM25 对问题召回 Top-K 段落替代全文投喂,控制 context 与成本,保障大文档下不退化。
八、错误分析与改进空间
| 潜在问题 | 原因 | 改进方向 |
|---|---|---|
| 极端表头结构摊平失准 | 当前摊平规则针对两层表头 + 前向填充,多层/异形表头可能错位 | 引入表头层级自动探测,或对复杂表回退到单元格坐标 + LLM 辅助标注 |
| 章节正则漏判/误判 | 正则依赖"编号+空格+中文"模式,非标准编号或无编号小标题会归入上一节 | 结合字号/加粗等版式特征做标题识别,或用 LLM 辅助分段 |
| Q1 模型冗余输出"发现冲突:无" | Prompt 要求"若有冲突则说明",模型理解为无条件回应 | 在 Prompt 中明确"无冲突则省略该段",或后处理裁剪空冲突声明 |
| 离群阈值为经验值 | 行内对比 40%、稳健 z>3 为人工设定,对不同量级数据未必最优 | 按列做分布自检自适应阈值,或对标记值二次用同期邻塔数据交叉验证 |
| 数值冲突实体清单需手维护 | 目前锚定关键词限于总装机容量等少数实体 | 抽象为可配置实体-单位表,或由 LLM 先抽取候选指标再交规则比对 |