资讯详情

Pydantic 对接大模型:强制结构化输出,实现工业数据采集零解析错误

📅 2026/11/5 4:00:12 | 华诺云谱 👁 阅读
Pydantic 对接大模型:强制结构化输出,实现工业数据采集零解析错误
上个月接了个行业竞品数据的采集需求前同事留下的近四百行XPath与正则表达式赶上对方官网一次前端重构直接全线报错。通宵改了半宿解析逻辑没过一周对方又换了个页面布局人直接麻了。做过网页数据提取的开发者应该都懂这种痛点传统解析方案高度依赖页面结构前端改个类名、调个标签顺序之前写的逻辑基本就要重写。尤其是面对几十个不同站点的采集需求时维护成本高到离谱一半的开发时间都耗在适配页面变化上。后来尝试用大模型来做内容提取不用关心页面结构直接把HTML丢进去就能拿到想要的字段。本以为找到了终极方案结果踩了新的坑大模型输出格式完全看“心情”有时候是Markdown表格有时候是纯文本分段偶尔还带两句“以上是提取结果”的客套话数据入库的时候频繁报错清洗逻辑写得比解析代码还长。折腾了两周之后最终落地了一套Pydantic 大模型的结构化输出方案从数据模型定义到输出校验形成完整闭环彻底解决了输出格式不稳定的问题上线三个月解析错误率为零。今天就把这套方案的完整实现思路和踩坑经验分享出来。一、传统数据采集方案的三大顽疾传统基于规则的解析方案在页面结构稳定的场景下效率很高但面对如今频繁迭代的前端页面短板越来越明显。1. 强耦合页面结构维护成本极高XPath、CSS选择器、正则表达式本质都是和页面DOM结构强绑定的。前端哪怕只是改了个class名、嵌套了一层div、调整了标签顺序解析逻辑就会直接失效。面对业务迭代频繁的站点基本是改一次页面就要重写一次解析长期维护成本远高于初始开发成本。很多采集项目最后不是做不出来而是维护不动了。2. 容错能力极差异常数据难拦截传统解析是“按图索骥”的逻辑页面少个字段、多个嵌套层级直接返回空值或者抛出异常。想要做柔性处理就要写大量的分支判断和兜底逻辑。尤其是遇到一些排版不规则的详情页很容易出现字段缺失、数据错位的问题脏数据流入下游后排查成本极高。3. 跨场景复用性低拓展成本高换一个站点、换一种页面类型之前的解析逻辑基本就用不了了。哪怕是同类型的资讯详情页不同站点的结构天差地别每接一个新站点都要从零开始写选择器、调正则效率极低。二、纯大模型解析为什么没法直接落地大模型的语义理解能力确实降维打击了传统规则解析但直接拿来做生产级采集还有三个绕不开的问题。1. 输出格式不稳定没有统一结构大模型的自然语言属性决定了它的输出是灵活的。同一个提示词两次调用返回的格式可能都不一样有时候是JSON有时候是列表有时候是分段纯文本偶尔还带多余的说明文字。这种非结构化的输出根本没法直接落库或者交给下游程序处理必须加一层数据清洗而清洗逻辑的复杂度并不比传统解析低。2. 数据类型无约束脏数据防不胜防比如你要的是数字类型的价格大模型可能返回“199元”、“199”甚至“一百九十九元”你要的是日期格式它可能返回“2026年11月”、“11/3/2026”各种格式。如果没有强制的类型约束后续就要写大量的格式转换逻辑而且永远不知道下一次大模型会输出什么奇葩格式。3. 异常输出无法提前拦截程序易崩溃就算提示词里反复强调“只输出JSON”偶尔还是会出现不完整的JSON、多余的Markdown代码块标记甚至模型幻觉出来的字段。没有校验层的话整个采集链路很容易因为个别异常输出直接中断生产环境的稳定性完全没法保障。三、Pydantic 大模型的核心原理这套方案的核心是把大模型的语义理解能力和Pydantic的工程化校验能力结合起来从机制上保证输出的结构化和正确性。现在主流大模型都支持工具调用Function Calling能力本质上就是大模型可以按照你提供的JSON Schema格式严格输出结构化数据。而Pydantic恰好是Python生态里最成熟的数据建模与校验库可以用极简的Python类定义数据结构自动生成标准JSON Schema同时还能做类型转换、数据校验、默认值填充。整个执行流程形成了完整的闭环用Pydantic定义目标数据模型明确字段名、数据类型、业务规则将Pydantic模型自动转换为JSON Schema作为大模型的输出格式约束大模型基于输入内容和Schema约束输出严格符合格式的结构化数据用Pydantic对大模型的输出做二次校验自动完成类型转换校验不通过的自动触发重试或降级处理保证链路稳定简单来说大模型负责“理解语义提取内容”Pydantic负责“管住格式保证规范”两者配合刚好解决了各自的短板。四、从零实现工业级结构化采集方案下面直接上核心实现代码整套方案逻辑不复杂十几行核心代码就能跑通。1. 环境依赖pipinstallpydantic openai tenacity2. 定义Pydantic数据模型这是整个方案的核心所有的字段约束都在这里定义。Field中的description是给大模型看的字段说明描述越清晰提取准确率越高。frompydanticimportBaseModel,FieldfromtypingimportList,OptionalfromdatetimeimportdateclassArticleInfo(BaseModel):文章详情信息模型title:strField(description文章的完整标题不要截断)publish_date:Optional[date]Field(description文章发布日期统一为YYYY-MM-DD格式不存在则返回null)author:Optional[str]Field(description文章作者名称不存在则返回null)content:strField(description文章正文纯文本内容去除所有HTML标签和广告内容)tags:List[str]Field(description文章标签列表不存在则返回空数组)3. 模型转Function定义将Pydantic模型转换为大模型兼容的工具调用格式这里以OpenAI接口格式为例国产大模型的接口格式基本通用。defpydantic_to_function(model:type[BaseModel])-dict:将Pydantic模型转换为标准函数调用定义schemamodel.model_json_schema()return{name:schema[title],description:schema.get(description,),parameters:{type:object,properties:schema[properties],required:schema.get(required,[])}}4. 结构化提取核心逻辑调用大模型时强制指定工具调用保证输出严格符合Schema最后用Pydantic做最终校验。fromopenaiimportOpenAIimportre clientOpenAI(api_key你的API_KEY,base_url你的接口地址)defextract_structured_data(html_content:str,model:type[BaseModel])-BaseModel:从HTML内容中提取结构化数据function_defpydantic_to_function(model)responseclient.chat.completions.create(modelgpt-4o-mini,messages[{role:system,content:你是专业的数据提取助手严格按照指定格式提取信息不要添加任何额外说明文字。},{role:user,content:f从以下HTML内容中提取指定信息\n\n{html_content}}],tools[{type:function,function:function_def}],tool_choice{type:function,function:{name:function_def[name]}},temperature0)# 提取返回的JSON内容兼容带代码块的情况raw_argsresponse.choices[0].message.tool_calls[0].function.arguments json_strre.sub(r^json\s*|\s*$,,raw_args.strip())# Pydantic校验并自动转换类型returnmodel.model_validate_json(json_str)5. 增加重试兜底机制生产环境一定要加重试遇到校验失败的情况把错误信息返回给大模型让它修正大部分问题一次重试就能解决。五、三种采集方案横向对比我在二十个不同站点的资讯详情页上做了对比测试结果如下对比维度传统XPath/正则解析纯大模型自由输出Pydantic 大模型单站点开发周期2-4小时15分钟20分钟页面变更维护成本极高基本重写极低极低解析准确率结构不变99%95%99%解析准确率结构变化几乎为090%90%输出格式合规率100%60%左右99.9%跨站点复用性极差极好极好从测试结果可以看出页面结构稳定的场景传统方案依然是性价比最高的选择页面结构多变、多站点异构的场景Pydantic大模型的方案优势碾压级明显相比纯大模型方案Pydantic只多了几行代码但把格式合规率从60%拉到了接近100%生产可用性直接拉满六、踩坑实录与优化技巧这套方案我们线上跑了三个多月踩了不少细节的坑这里分享几个最实用的优化点。1. 字段描述一定要写清楚Field里的description不是摆设是给大模型的提示指令。比如价格字段不要只写“商品价格”要写“商品当前售价纯数字单位为元不要包含货币符号和千分位分隔符”能大幅减少格式错误。2. 非必填字段一律设为Optional页面上可能不存在的字段一定要用Optional类型不要设为必填。否则大模型没找到该字段时输出的JSON会缺少字段导致Pydantic校验失败。宁愿多做一层非空判断也不要随便把字段设为必填。3. 预处理HTML降本提效不要把完整HTML直接丢给大模型。先去掉脚本、样式、广告、导航栏、页脚这些无关内容只保留正文区域的HTML能减少70%以上的Token消耗同时减少干扰信息提升提取准确率。4. 嵌套模型尽量扁平化如果数据结构特别复杂嵌套层级很深生成的JSON Schema会很长占用大量上下文Token。非必要的情况下尽量把模型做扁平化或者拆分成分步提取控制单次调用的Token成本。5. 小模型完全够用很多人觉得结构化输出必须用GPT-4实际上现在主流国产模型的Function Calling能力已经非常成熟处理常规的网页提取完全够用成本只有GPT-4的几十分之一批量采集的时候成本差距非常大。6. 校验失败的智能重试遇到校验不通过的情况不要直接重试原请求。把Pydantic的ValidationError错误信息拼到提示词里告诉大模型哪里错了、怎么改再发起第二次调用修复成功率远高于盲目重试。七、写在最后Pydantic 大模型的组合本质上是给灵活的大模型套上了工程化的“紧箍咒”既保留了语义理解的优势又解决了输出不可控的核心问题。对于需要处理大量异构页面、页面结构频繁变化的采集场景这套方案能大幅提升开发效率降低长期维护成本。当然它也不是银弹对于结构高度稳定的内部系统采集传统的规则解析依然是性价比最高的选择。技术方案没有绝对的好坏适合场景的才是最好的。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑