ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Dify 高级实验(01):智能文档处理——如何把非结构化文档变成结构化数据?

Dify 高级实验(01):智能文档处理——如何把非结构化文档变成结构化数据? Dify 高级实验01智能文档处理——如何把非结构化文档变成结构化数据Dify 实验系列 · 高级 01/10 | 实验编号DIFY-103-01基于 Dify 1.16.1 实测2026-081. 业务场景先讲一个我们实际遇到的场景。一家中型企业的人力资源部招聘专员小李每天早上打开邮箱里面躺着十几份新简历——有的是招聘平台导出的纯文本有的是 PDF 转出来的乱格式还有的直接是一段自我介绍。她要做的第一件事是把每份简历里的姓名、年龄、技能、经验年限、期望薪资、学历逐项拆出来手动录进招聘系统系统才能按岗位要求做初筛。一份简历从读完到录完快则几分钟慢的要来回翻原文确认字段。赶上校招季一天几十份简历大半天就耗在「打字」上了。我们第一次接这类需求时第一反应也是「上 NLP 解析库正则加模型一起上」。后来把需求拆开看才发现——简历里的字段就六七个难点根本不在「拆」而在「懂」「5 年经验」和「五年」要归一成同一个数「毕业 3 年」要能推算出经验年限。而「懂」恰恰是 LLM 的强项。Dify 工作流里的参数提取器Parameter Extractor就是干这个的声明好字段粘贴原文直接输出 JSON解析代码一行都不用写。这不是个例。任何「把非结构化文档变成结构化数据」的场景都是这个模式合同管理员收到供应商合同要人工录金额、期限、付款条件财务月底面对几百张发票要逐张录发票号、税额客服把客户邮件里的诉求抄进工单系统再人工分类打标签。文档换了动作一模一样——机械地拆字段、录入、核对。2. 场景痛点这个流程的痛点在招聘专员身上体现得最直接人工录入慢慢在没价值一份简历 5-10 分钟几十份就是大半天——录入本身不产生任何判断却是每天躲不掉的固定动作招聘专员的时间被「打字」挤占真正该做的候选人沟通和面试安排反而往后排。录入口径不统一数据一录就脏「5 年经验」「五年经验」「5 年」说的是同一件事不同人录进系统变成三种写法后续按经验年限筛选时本该命中的简历被漏掉统计报表也失真。漏字段静默发生一份简历漏了学历录入时没人发现直到按学历过滤时这条记录才「消失」——问题在录入几天后才暴露还得回头翻原始简历补录。数据不可追溯这条记录是谁录的、从哪份文档来的、录进去的字段对不对全都没有留痕出了差错只能人肉排查。本质上最机械、最不该花人力的「录入」环节恰恰卡住了整个数字化流程的效率——问题不是缺人而是缺一条把非结构化文档自动变成结构化数据的流水线。3. 方案为什么是这套文档结构化流水线Dify 工作流里的「参数提取 → 数据校验 → 条件分支 → 模拟入库 → LLM 回复」链路正好把这段机械劳动自动化。选它的理由我们实际对比过参数提取器是平台原生能力不用自研 NLP 解析器节点里声明好字段姓名/年龄/技能/经验/薪资/学历LLM 自动从自然语言里抽出来输出 JSON语义理解「毕业 3 年」能推算出经验年限也一并解决校验规则代码化坏数据进不了库缺字段、年龄越界这类问题用代码节点在写入前二次校验并给出明确报错而不是带着残缺数据往下走入库与回复分离流程可扩展模拟入库节点生成记录编号LLM 节点把结果包装成面向用户的友好回复——将来接真实数据库只需把模拟入库换成 HTTP 节点。这篇文章我们就用它搭一个「简历自动入库」系统粘贴一段简历文本自动提取 6 个字段校验通过后模拟写入数据库返回记录编号与信息摘要。4. 整体架构通过失败开始document_text / document_type参数提取器 pe_extract提取 6 字段 JSON代码节点 cd_validate校验 准备写入数据条件分支 cond_valid代码节点 cd_write模拟入库生成记录 IDLLM lm_reply生成处理结果回复结束 end_ok输出 reply结束 end_bad输出 error 错误提示链路很清晰入口收文档原文 → 提取结构化字段 → 校验完整性 → 分支处理。校验和分支是这个架构的关键——参数提取偶尔漏字段是 LLM 节点的常态不校验直接「入库」残缺数据就会带着空姓名、空技能写进数据库。5. 模块设计5.1 参数提取器 pe_extractquery引用开始节点原文模型用 DeepSeek 并开reasoning_mode: function_call保证结构化输出query:[start,document_text]model:deepseek-v4-flash# temperature 0.01输出稳定reasoning_mode:function_callparameters:-name:name# string, required 姓名-name:age# number 年龄可从毕业X年推算-name:skills# array[string], required 技能列表-name:experience_years# number, required 工作经验年-name:expected_salary# number 期望薪资-name:education# string 最高学历提取指令要点技能以数组形式提取、经验以年为单位、没有明确信息填 null 而不是瞎编。5.2 代码节点 cd_validate校验 准备写入对 PE 结果做二次校验并拼出record_text供 LLM 直接引用defmain(name,age,skills,experience_years,expected_salary,education):issues[]ifnotname:issues.append(缺少姓名)ifnotskillsorlen(skillsor[])0:issues.append(缺少技能)ifageand(age16orage70):issues.append(年龄 {} 异常.format(age))record{name:nameor未知,age:int(age)ifageelseNone,skills:skillsor[],experience_years:float(experience_years)ifexperience_yearselse0,expected_salary:float(expected_salary)ifexpected_salaryelseNone,education:educationor,}record_text姓名{} | 年龄{} | 技能{} | 经验{}年 | 期望薪资{} | 学历{}.format(record[name],record[age],、.join(record[skills]),record[experience_years],record[expected_salary],record[education])return{valid:trueiflen(issues)0elsefalse,issues:issues,record_data:record,record_text:record_text,error_text:信息不完整、.join(issues)ifissueselse}5.3 条件分支 cond_valid注意 boolean 展平代码节点返回的valid是字符串true/falseif-else 用is比较字符串case_valid:cd_validate.valid is truecase_invalid:cd_validate.valid is false5.4 模拟入库 cd_write 与 LLM 回复 lm_replycd_write模拟写入延迟并生成记录 IDCAN- 时间戳取模lm_reply的系统提示词必须用三花括号引用上游字段你是一个文件处理助手。用户提交了一份文档系统已从中提取信息并存入数据库。 请根据以下信息回复用户告知处理结果 提取的信息{{#cd_validate.record_text#}} 数据库记录编号{{#cd_write.record_id#}} 入库时间{{#cd_write.timestamp#}} 回复要友好、专业包含提取到的关键信息和记录编号。结束节点end_ok输出reply←lm_reply.textend_bad输出error←cd_validate.error_text。6. 运行验证输入期望行为实测「张三28岁计算机本科5年 Python/Java/Go 经验期望薪资 25K-30K。」提取 6 字段校验通过模拟入库返回记录编号与信息摘要与预期一致回复包含 CAN- 编号「你好」提取缺姓名/技能走 end_bad返回「信息不完整缺少姓名、缺少技能」与预期一致未触发入库「李四50岁20年经验学历大专」年龄/经验正常但缺技能校验拦截与预期一致skills 为 required7. 实战坑坑现象修复LLM prompt 用双花括号{{变量名}}1.16 不替换双花括号字面传给模型回复中出现{{#cd_write.record_id#}}原文一律用三花括号{{#节点id.字段#}}dify103_01 实测代码节点返回 boolean 类型valid在变量选择器里不可见if-else 无法引用代码里转字符串true/falseif-else 用is比较字符串PE 缺reasoning_mode: function_call参数提取偶尔输出不完整 JSON 或类型不符skills 变字符串显式配置 function_call temperature 0.01 稳定输出dify103_01 实测DeepSeek 推理模型未配 separated思考过程混入text输出回复里出现推理碎屑LLM 节点开reasoning_format: separated思考与回答分离8. 实验文档及源码获取实验文档完整操作步骤DIFY-103-01智能文档处理系统.md源码可直接导入dify103_01_智能文档处理系统.yml文章聚焦核心配置与采坑点实验的完整分步操作节点搭建/参数表/调试指引见实验文档原文。下一篇Dify 高级实验02对话式 BI 分析——如何让业务人员用自然语言直接查数 你在这个实验的场景里踩过什么坑欢迎评论区分享你的实战经验。
返回列表