跳转到主要内容
  • 你不必独自完成所有工作: 用于文档处理的 Genie Code 可自动完成此工作流的核心部分:基于你的标注数据逐字段为抽取结果打分,以可审阅的 diff 形式提出 schema 与指令修正建议,并重新运行评估以展示前后对比结果。
  • 用正确的手段提升 ai_extract 准确率: 字段级规则使用 schema 描述,文档级逻辑使用提示词,结构复杂时使用 precision mode,并用引用诊断错误。
  • 用 MLflow Prompt Registry 对提示词和 schema 进行版本管理: 将抽取逻辑作为带版本的工件进行跟踪,并通过别名部署或回滚变更,而不是直接编辑流水线代码。
  • 在推广前评估变更: 将候选方案与固定、经人工审核的基准真值进行对比,同时跟踪准确率、覆盖率和多次运行间的波动。

文档抽取通常始于一个简单的循环:发现某个字段不正确,调整提示词或 schema,重新运行该文档,然后检查结果。

随着字段和文档格式成倍增加,这种做法会变得不可靠。一项变更可能修复了某个字段,却在其他地方引入回归;可能对一种版式有效,却在另一种版式上失败;也可能仅仅因为 LLM 多次运行间的正常波动而显得更好。

我们在最近的一个项目中看到了这一点:该项目从合作伙伴提交的订单文档中抽取约 40 个结构化字段,涉及数十种 PDF 版式。审核人员在抽取值进入下游之前对其进行了纠正和批准,从而为我们提供了经人工审核的评估基准真值。

挑战不在于让 ai_extract 返回这些字段。而在于在不使系统整体退化的情况下改进抽取效果。

例如, revision 字段有时会返回状态词,例如 ORIGINAL 而不是一个 revision 数字或空白。一个小的 schema 变更将该字段的错误减少了大约一半。但在所有字段上,总抽取错误增加了 9%。

教训很明确:改进一个字段并不一定意味着改进整个抽取系统。

该流水线已经具备系统化评估变更所需的大部分组件。文档落入对象存储,并通过使用 Auto Loader 的 Lakeflow SDP 流水线流转。Bronze 层使用 ai_parse_document 解析文档,Silver 层使用 ai_extract 抽取结构化字段,Gold 层将结果发布为物化视图。预测结果同步到 Lakebase,在那里 Databricks App 让审核人员纠正并批准字段,Lakebase CDC 将这些批准结果返回湖仓。

Document Extraction Pipeline
图 1. 带人工审核的文档抽取流水线。提示词和 schema 硬编码在 Silver 中,而审核人员的纠正尚未用于评估抽取变更。

反馈循环中缺少两个部分。审核人员的批准结果已经可用,但尚未被组装成可复用的评估数据集。同时,提示词和 schema 直接嵌入在流水线代码中,因此即使对抽取做很小的变更也需要代码部署。

我们围绕三个问题构建了一套工作流来解决这两个问题: 我们应该改什么?应该如何做版本管理?以及需要多少证据才能将其推广?

本文涵盖该工作流的三个部分:

  • 用正确的手段改进 ai_extract: 用 schema 表达字段规则,用全局指令处理文档级逻辑,用 precision mode 应对复杂结构,并用引用信息诊断错误。
  • 对提示词和 schema 做版本管理: 将两者都存入 MLflow Prompt Registry,并使用别名来部署或回滚配置,而无需修改流水线代码。
  • 在推广前进行评估:在固定的、经人工审核的基准真值上比较候选方案,跟踪准确率、覆盖率和多次运行间的波动。

这些步骤共同构成了一条可重复的路径,从提出抽取变更一直到投入生产,并有证据表明该变更能改善整个系统。

从 Genie Code 开始

本文的其余部分将逐一介绍我们推荐的实践以及每项实践为何重要。你不必独自实现所有这些实践。 用于文档处理的 Genie Code 构建 Lakeflow 作业(ai_parse_document、ai_classify 以及带引用和置信度分数的 ai_extract),并用一个 评估与爬山循环:

  • 评估逐字段将当前抽取结果与你标注的表格进行打分,这样你就能看出哪些字段较弱。
  • 改进提出修复方案,通常是对字段描述进行更精确的调整,并以可审阅的 diff 形式呈现,由你在应用前批准。
  • 重新评估:每次接受的变更后都会重新运行评估集,并展示变更前后的结果,因此回归和改善一样清晰可见。

例如,你可以这样要求 Genie Code:“对照我标注的表格评估抽取结果,并告诉我哪些字段最弱”,接着再说:“revision 字段的准确率还可以更高。请迭代改进 schema 和指令,重新运行评估,并向我展示改进前后的对比。”

理解基本原理仍然很重要。它有助于你判断 Genie Code 提出的更改,决定结果何时足够好可以推广,并将工作流扩展到生产环境,例如在 MLflow Prompt Registry 中对提示词和 schema 进行版本管理。下面每一节都会说明一项推荐实践,并指出 Genie Code 可以如何为你处理它。

选择正确的 ai_extract 杠杆

ai_extract 接受三个输入:解析后的文档、一个 JSON schema,以及可选的全局指令。

Schema 和指令服务于不同的目的:

  • Schema: 定义输出字段以及针对各字段的抽取规则。
  • 全局指令: 提供适用于整篇文档的指导。

结果是一个结构化值,每个 schema 字段对应一个条目。你可以直接访问各个字段,例如: extracted:response.revision.value.

把字段特定的规则放进 schema 中。

从 schema 结构开始。当某个字段有一组封闭的有效取值时,使用 enum 约束,而不是在描述中列出所有允许的值。数字和整数使用数值类型,重复的结构使用嵌套数组或对象。

然后使用 schema 描述来表达仅靠类型无法表达的规则,例如:

  • 保留标识符中的前导零,例如 004
  • 排除诸如“ ORIGINAL, NEW,或 REVISED
  • 在第一个无效字符处截断标识符
  • 返回 null 当某个值不存在时

关键将字段规则保留在 schema 中,可以让抽取契约更易于检查,也避免全局提示词变成一堆互不相关的例外清单。

将全局提示词保留用于适用于整篇文档的规则,包括:文档或领域上下文;来源优先级,例如页眉优先于页脚;跨字段一致性规则;将多行合并为数组的指令;不应作为来源的文档区域。例如,如果实体名称被错误地从样板页脚或第三方联系信息块中抽取出来,一条指令可以告诉模型忽略这些区域。一条有用的规则是:如果规则只定义某一个字段,就把它放进 schema 中。

将全局提示词保留用于适用于整篇文档的规则,包括:

  • 文档或领域上下文
  • 来源优先级,例如页眉优先于页脚
  • 跨字段一致性规则
  • 将多行合并为数组的指令
  • 不应作为来源的文档区域

例如,如果实体名称被错误地从样板页脚或第三方联系信息块中抽取出来,一条指令可以告诉模型忽略这些区域。 FORBIDDEN-SOURCES 一条指令可以告诉模型忽略这些区域。

一条有用的规则是: 如果规则只定义一个字段,就把它放进 schema。如果规则定义如何解释文档,就把它放进提示词。

使用 Genie Code 将其自动化爬山式循环遵循同样的原则。它提出的修正大多会细化 schema 中的字段描述,并以 diff 形式展示,供你在应用前审批。

保持下游的确定性格式化。

并非所有转换都需要 LLM。在可能的情况下,使用 SQL 或其他确定性转换来处理大小写、分隔符移除、零填充以及诸如 TELEVISION 到 TV 的映射。

KEY:用模型解释文档,用代码规范化输出。对于结构性问题使用 precision mode。有时指令很清晰,但文档本身难以遵循。大型 schema、重复的订单项、复杂的表格和多页布局会让数值难以与正确的行保持对齐。对于这些情况,2.1 版本提供了 precision mode:Precision Mode 为要求更高的用例带来前沿的抽取能力。借助提示词和 schema 的帮:用模型解释文档,用代码规范化输出。

对于结构性问题,请使用 precision mode。

有时指令很清晰,但文档本身难以遵循。大型 schema、重复的订单项、复杂的表格和多页布局会让数值难以与正确的行保持对齐。

对于这些情况, ai_extract 2.1 版本提供了 precision mode:

精确模式 为要求更高的用例带来前沿的抽取能力。在提示词和 schema 保持不变的情况下,它往往在重复结构上最有帮助,并能减少过度抽取(即模型在正确答案应为空的地方返回了值)。

在更改配置之前先诊断失败原因:

  • 如果模型误解了 某个字段的含义,请更改提示词或 schema。
  • 如果它能理解该字段,但在 数据结构,测试 precision mode。

这两种方法是互补的。在我们的测试中,schema 规则纠正了模型误解的一个字段,而 precision mode 则改善了从复杂表格中抽取字段的效果。

使用引用(citations)来理解某个字段为何出错。

当抽取出的值有误时,引用(citations)有助于显示模型是在哪里找到其答案的:

引用(citations)提供字段级边界框,可映射回源文档中的元素跨度。这有助于区分两种不同类型的错误:

  • 抽取错误: 模型选择了错误的区域、误解了字段,或返回了源文档不支持的值。
  • 标注分歧: 模型从正确的位置进行了抽取,但预期答案遵循了不同的审核者约定。

这些情况需要不同的修复方式。抽取错误可能需要修改 schema 或提示词。标注分歧则应通过在审核者指南中定义预期约定来解决。

置信度分数还可以帮助确定人工审核的优先级:

将它们用作排序信号,例如优先审核低置信度字段,而不是将其作为自动质量门禁。高置信度的结果仍可能是错误的。

在 Genie CodeGenie Code 构建的抽取任务包含引用和置信度分数。你可以要求它“根据评估结果为每个字段设置置信度阈值,并将低置信度的行转交人工审核”,并使用 Document Parsing UI 对解析和抽取进行可视化调试。

将提示词与 schema 一起进行版本管理

通过将提示词和 schema 作为流水线代码之外的可配置、可复用定义来管理,减少在 notebook 中硬编码提示词和 schema 带来的摩擦。仅仅改动一处措辞就需要部署代码,之前的版本难以重建,而且没有证据表明新版本比旧版本更好。

MLflow Prompt Registry 让你能够将这些输入与流水线代码分开进行版本管理。 将提示词和 schema 一起进行版本管理: 字段描述对抽取的影响与全局指令相同。只对提示词进行版本管理,你有一半的抽取逻辑仍然以未受追踪的代码变更形式在流转。

超越 Genie Code 循环:Genie Code 可帮助你找到合适的提示词和 schema。当你把该配置投入生产环境时,对其进行版本管理可以让你在无需部署代码的情况下推广和回滚变更。

一种简单的别名策略可能使用:

  • @prod 用于当前已批准的版本
  • @candidate 用于正在评估的版本
  • @scr_* 用于并行比较的实验版本

随后,流水线通过别名加载已激活的版本:

随后,解析后的提示词和 schema 会被传递给 ai_extract.

当候选版本获批后, mlflow.genai.set_prompt_alias 可以移动 @prod 到新版本。流水线会在下一次运行时解析它,无需更改流水线代码。要回滚,请将两个别名都恢复到先前记录的版本。底层版本仍保留在注册表中。

这将抽取配置与运行它的代码分离开来。图 2 还补上了另一块缺失的部分:可复用的基准真值。

Silver reads approved prompts and schemas
图 2. Silver 从注册表中读取已批准的提示词和 schema。审核员的签核结果汇入基准真值视图。

基准真值视图将已批准的标签与源文档和预测结果配对,从而创建用于衡量变化的参考数据集。

根据固定的基准真值评估候选版本。

版本历史告诉你改了什么,却不会告诉你改动是否更好。用审核员批准的结果构建一个固定队列;我们的队列包含数百份 PDF,覆盖了多种版式。用同一个测试集对生产提示词和每个候选提示词进行评分。

对于每个版本,跟踪以下指标:

  • 整体准确率与字段级准确率
  • 基准真值覆盖率
  • 按文档类型划分的表现
  • 多次运行波动

在比较过程中,请保持文档和指标定义一致。否则,分数的变化可能反映的是不同的测试集或评分规则,而不是不同的抽取配置。

在 Genie Code将 Genie Code 指向你已标注的表格(例如图 2 中的基准真值视图),并要求它评估抽取结果。它会对每个字段打分,并在每次接受的更改后重新运行同一评估集,因此前后对比使用的是相同的文档。当你将更改投入生产环境时,下文所述的噪声下限、覆盖率和判定检查是有用的防护措施。

考虑正常的 LLM 波动

候选方案偶尔得分略高,并不意味着它更好。在冻结的测试集上至少运行 3-5 次生产配置,并计算其平均准确率和标准差(σ)。这个 σ 就是你的噪声下限。你的策略可以要求候选方案的提升必须超过 2σ,才将其视为有意义;处于该区间内的任何结果都是不确定的,而非胜出。

同时跟踪覆盖率和准确率

如果你忽略缺失的预测,准确率也可能具有误导性。

假设你只对模型和审核员都提供了值的字段进行评分。一个将困难字段留空的候选方案可能看起来更准确,因为这些遗漏会从分母中消失。反过来也可能发生。当我们只对审核员提供了值的文档上的字段进行评分时,我们的修复看起来将准确率提升了不到 3 个百分点。 revision 字段进行评分时,我们的修复看起来将准确率提升了不到 3 个百分点。但当我们统计所有错误(包括正确答案为空的情况)时,该修复将错误减少了大约一半。大部分改进来自在不应有值的地方正确返回了空值。这就是为什么覆盖率应与准确率一同报告。请明确定义它,例如,定义为模型返回预测的非空基准真值字段所占的比例。如果准确率上升但覆盖率 revision 个百分点。但当我们统计所有错误(包括正确答案为空的情况)时,该修复将 revision 错误大约减少了一半。大部分改进来自在不应有值的地方正确返回了空值。

这就是为什么覆盖率应与准确率一同报告。请明确定义它,例如,定义为模型返回预测的非空基准真值字段所占的比例。如果准确率上升但覆盖率显著下降,在推广候选方案之前应先进行调查。

由此得到的评估框架遵循一套可重复的流程:冻结测试集、建立生产基线、在筛选别名上注册候选方案、运行重复评估,并比较准确率、覆盖率和稳定性。

Evaluation Sequence
图 3:评估流程:冻结测试集、测量生产基线、筛选候选方案,并比较准确率、覆盖率和稳定性。

将每项评估归纳为一个判定结论。

一旦你测量了准确率、覆盖率和多次运行间的波动,你的评估框架就可以把这些指标归纳为少量结果:

  • 更好: 准确率达到预设阈值,覆盖率保持稳定,且结果稳定。
  • 可疑: 准确率有所提升,但覆盖率显著下降。
  • 不稳定: 不同运行之间的结果差异太大。
  • 无法确定: 差异太小,无法与正常波动区分开来。
  • 更差: 准确率会显著下降。

这些判定结论提供了一种一致的方式,用于在决定是否将候选方案推广到生产环境之前对评估进行总结。

追踪这次修订改动带来的影响

我们在同一测试集上对每个候选方案各评分三次,统计每个字段的错误,并以原始提示词和 schema 为基准。

修订字段错误错误 错误所有字段的错误判定结论
revision 仅修复 schema-49%+9%TARGET_IMPROVED_WITH_REGRESSION
重构后的提示词与 schema-57%-16%BETTER
仅使用 precision mode,不更改提示词或 schema-10%-24%BETTER
重构后的提示词与 schema + precision mode-64%-32%BETTER

这次局部修复达到了我们的预期,但模型开始在无关的明细字段(例如日程详情)中编造值。编辑一个字段的描述并不是单字段实验:模型会把 schema 作为一个整体来读取。因此我们没有发布它。相反,我们把字段特定的规则从全局提示词移到了 schema 描述中,包括同样的规则。提示词最终缩短到原始长度的一半以下,整体错误下降了 16%,其中错误下降了 30%。有两个字段变差了,它们被列入了待办清单。 revision,但模型开始在无关的明细字段(例如日程详情)中编造值。编辑一个字段的描述并不是单字段实验:模型会把 schema 作为一个整体来读取。

因此我们没有发布它。

规则。提示词最终缩短到原始长度的一半以下,整体错误下降了 16%,其中错误下降了 30%。有两个字段变差了,它们被列入了下一轮的待办清单。precision mode 则呈现出另一番情况。在不更改提示词或 schema 的情况下,它把错误减少了 24%,主要原因是它不再在重复的明细字段中编造值。但它几乎没有改变错误,因为那是一个定义问题,只有 schema 规则才能解决它。两者结合后可以叠加生效:在 revision 规则。提示词最终缩短到原始长度的一半以下,整体错误下降了 16%,其中 estimate 错误下降了 30%。

有两个字段变差了,它们被列入了下一轮的待办清单。

precision mode 则呈现出另一番情况。在不更改提示词或 schema 的情况下,它把错误减少了 24%,主要原因是它不再在重复的明细字段中编造值。但它几乎没有改变 revision 错误,因为那是一个定义问题,只有 schema 规则才能解决它。

两者结合后可以叠加生效:在重构后的提示词和 schema 之上再启用 precision mode,又让剩余错误减少了 19%。总体来看,错误下降了约三分之一(32%),并且 revision 错误减少了近三分之二(64%)。

这是下一轮的回归清单。 Genie Code 的 循环正是为了暴露这类问题而设计的。由于每一个被接受的变更都会重新运行完整的评估集,一个只对 revision 有帮助却损害了行项目字段的局部修补,会出现在前后对比结果中,而不是在生产环境中。

MLflow
图 4. 每个候选方案的三次运行与 MLflow 中的原始配置并列展示。每次运行都会记录其提示词版本、schema 版本和引擎,因此每个结果都能追溯到产生它的确切配置。

把评估转化为晋升决策。

裁决是起点,而非最终决定。

此前的一个候选方案将估计错误减少了约三分之一,但总体结论仅为“无定论”。不过,它也开始在几乎每一份文档上填写一个是/否标志,而审核人员此前只在少数几份文档上标记过该字段。

某一字段的严重退化可能会妨碍晋升,即使总体指标看起来尚可。因此,晋升应保持由人工控制。

如果一个候选方案被归类为“ BETTER,所有者可以更新该 @prod 别名,并记录候选版本、评估指标、作者和时间戳。

也可能存在正当理由来推行一项 INCONCLUSIVE 变更,例如实施一项未被总体准确率完全体现的重要业务约定。在这些情况下,记录覆盖原因可以保留决策背后的理由。

有了这次审核和别名更新,反馈闭环就此闭合:

Fresh Pipeline Initialization Loads
图 5. 完整闭环:审核人员的批准成为 ground truth,评估框架对候选方案进行评估,所有者晋升已批准的提示词与 schema 组合。新的流水线初始化会加载新版本。

构建可重复的抽取工作流。

可靠的文档抽取不在于找到一个完美的提示词,而在于选择合适的变更、跟踪变更内容,并测试结果是否有所改善。

要做到这一点,就意味着:字段级行为使用 schema 描述,文档级推理使用全局指令,当结构成为瓶颈时使用 precision mode,当你需要理解抽取失败的原因时使用引用。 ai_extract要做到这一点,就意味着:字段级行为使用 schema 描述,文档级推理使用全局指令,当结构成为瓶颈时使用 precision mode,当你需要理解抽取失败的原因时使用引用。

随后,MLflow Prompt Registry 为你提供了一条带版本管理的路径,用于管理提示词和 schema;而固定的评估测试集则为你提供了判断哪些内容应当进入生产环境的依据。

这些环节合在一起,就把提示词迭代从一系列一次性修改转变为可重复的工程工作流。

用于文档处理的 Genie Code 自动完成这一循环的核心环节(测量、改进、重新评估),因此大多数团队可以从这里起步,随后在流水线走向生产时再加入 Prompt Registry 版本管理、噪声下限检查和晋升门禁。

探索 Databricks AI Functions 文档 以了解更多信息,并查看 MLflow Prompt Registry 文档,了解提示词版本管理和别名管理。试用用于文档处理的 Genie Code。从 Jobs and Pipelines 打开 Genie Code,将其指向你的文档和带标签的表,然后让它评估并改进你的抽取。相关标签:解决方案、客户、最佳实践、媒体与娱乐 以及 数据科学与机器学习获取最新文章,直达你的收件箱订阅我们的博客,获取最新文章并直接发送到你的收件箱。注册查看所有博客 ai_extract,并查看 MLflow Prompt Registry 文档 ,用于提示词版本管理和别名管理。 试用用于文档处理的 Genie Code从 Jobs and Pipelines 打开 Genie Code,将其指向你的文档和带标签的表,然后让它评估并改进你的抽取。

相关标签:

解决方案, 客户, 最佳实践, 媒体与娱乐 以及 数据科学与机器学习

获取最新文章,直达你的收件箱

订阅我们的博客,最新文章将直接发送到你的收件箱。

注册

查看所有博客 slice-start id="_gatsby-scripts-1" slice-end id="_gatsby-scripts-1"