Token Lab搜索

APPLIED AI / READ → RUN → MODIFY → TEST

文档提取:JSON 格式正确不等于事实正确

在候选提取结果与业务流程之间建立校验边界。

学习指南与本课目录LEARNING CONTRACT

理解 → 实现 → 研究

目标:解释本课机制、复现一个例子、测试一个失败案例。读完不自动代表掌握。

1 · 你在哪里会用到它

文档助手常见任务是把字段提取成表格。OpenAI API 另提供按 schema 约束响应的 Structured Outputs。这不意味着 ChatGPT 每个表格功能都使用同一实现。这里由你提供候选 JSON,本地代码负责验证,不调用模型。

官方产品/API 文档 ↗

来源核对日期 2026-10-25。产品行为来自官方公开说明,下方代码是独立教学实现。

2 · 关键工程决策

使用两个独立关卡:结构验证拒绝缺失、多余和类型错误字段;证据验证检查引文是否存在并支持声明金额。任何单一关卡都不能解决语义歧义:文档可能同时有小计、税额和总计,它们都是有效数字。应明确展示拒绝,不能默默将字符串转数字或用零替代。

  1. 示例候选具有四个允许字段,金额为有限非负数。
  2. 发票 ID 出现在原文,引文 USD 42.50 也存在。
  3. 42.5 格式化为两位小数得到 42.50,与证据匹配。
  4. 把金额改为 425:shapeValid 仍为 true,但 accepted 为 false,区分结构与事实依据。

3 · 运行并修改输入

完全在浏览器运行,无模型调用、网络请求、API Key 或上传。输入为 JSON,这是确定性组件演示,不是生成式助手。

{
  "shapeValid": true,
  "accepted": true,
  "errors": [],
  "limitation": "Exact-text checks only; conflicting totals and invoice context need further validation."
}

初始输出是构建时实际计算的示例结果。修改后点击运行以计算你的结果。

4 · 完整源代码

需要现代浏览器或 Node.js 18+。下载模块,将下方 runner 存为同目录 demo.mjs,执行 node demo.mjs,无需 npm 依赖。

下载源代码 ↓
// Validate a candidate output supplied by a person or model. No model call.
export const example = {
  source: 'Invoice A-17. Total: USD 42.50.',
  candidate: {invoice_id: 'A-17', currency: 'USD', amount: 42.5, evidence: 'USD 42.50'}
};
export function run({source, candidate}) {
  const errors = [];
  if (typeof source !== 'string' || source.length > 20000) throw Error('Invalid source');
  if (!candidate || typeof candidate !== 'object' || Array.isArray(candidate)) throw Error('candidate must be an object');
  const keys = ['invoice_id', 'currency', 'amount', 'evidence'];
  if (Object.keys(candidate).some(key => !keys.includes(key))) errors.push('Unexpected field');
  for (const key of ['invoice_id', 'currency', 'evidence']) {
    if (typeof candidate[key] !== 'string' || !candidate[key].trim()) errors.push(`Invalid ${key}`);
  }
  if (!Number.isFinite(candidate.amount) || candidate.amount < 0) errors.push('Invalid amount');
  if (!['USD', 'EUR', 'CNY'].includes(candidate.currency)) errors.push('Unsupported currency');
  const shapeValid = errors.length === 0;
  if (shapeValid) {
    if (!source.includes(candidate.invoice_id)) errors.push('Invoice ID absent from source');
    if (!source.includes(candidate.evidence)) errors.push('Evidence quote absent from source');
    const expected = `${candidate.currency} ${candidate.amount.toFixed(2)}`;
    if (!candidate.evidence.includes(expected)) errors.push('Amount/currency not supported by quote');
  }
  return {shapeValid, accepted: errors.length === 0, errors,
    limitation: 'Exact-text checks only; conflicting totals and invoice context need further validation.'};
}
import {run, example} from './validated-extraction.mjs';
console.log(JSON.stringify(run(example), null, 2));

5 · 失败案例与生产差距

精确子串检查是教学约束,不等于理解发票。多张发票、冲突金额、本地格式和小数精度需要更强处理。生产财务系统通常使用 Decimal 或整数最小货币单位。接入真实模型时,需分别处理拒绝、不完整输出与解析失败。

6 · 你的实现练习

增加缺失引文、数字字符串、多余字段和冲突总额案例。扩展来源区间与发票身份字段,并解释哪些案例仍需复核。

交付修改后的代码、至少一个成功与一个失败案例,并解释测试不能证明什么。

继续学习关联知识点 →
← 全部实战教程
MATHEMATICAL REVIEW · 2026-10-26

假设、参考实现与验收

结构校验与精确证据校验分开。小数显示保留两位,不是精确货币算术。子串匹配无法解决发票总额冲突。

已复核实现、不变性及声明的证据边界;保留原有验收测试。

运行前:预测一个边界情况

结构校验与精确证据校验分开。小数显示保留两位,不是精确货币算术。子串匹配无法解决发票总额冲突。

提示:隔离假设

固定基线输入,只改变一个参数或边界;同时比较数值与声明单位。单例通过仅验证该样例。

最小可运行算例

将算例及所链接模块保存在同一目录。使用 Node.js 22 或更高版本,然后运行 node application-validated-extraction.mjs. 无需第三方运行依赖。

import {run,example} from './application-validated-extraction-core.mjs';
console.log(run(example));

测试与迁移

结构校验与精确证据校验分开。小数显示保留两位,不是精确货币算术。子串匹配无法解决发票总额冲突。

在下方笔记记录输入、代码版本、期望值和实测值;再构造违反上述假设的反例,解释原结论为何不再成立。

下载完整代码包(.tar.gz) · 完整参考代码与回归检查

预测、检验与证据记录

展开答案前先预测一个结果;练习后记录差异和迁移测试。记录仅存本地,在不同语言版本间共用。

打开记录/导出/清除 →

数学复核范围逐篇记录,不代表完成论文实证复现;可在笔记中记录疑似错误。 复核范围