Token Lab搜索

APPLIED AI / READ → RUN → MODIFY → TEST

文件问答:实现证据优先的文档助手

把文档问题变成排序后的来源段落与可检查引用。

学习指南与本课目录LEARNING CONTRACT

理解 → 实现 → 研究

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

1 · 你在哪里会用到它

ChatGPT 官方支持上传文件进行分析、总结和提取。可用一份不敏感的政策文档,询问退款期限并要求提供依据段落。本教程实现小型词项检索组件,不声称这是 ChatGPT 内部文件处理架构。

官方产品/API 文档 ↗

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

2 · 关键工程决策

实际问题是来源可追溯:回答流畅但无法找到依据仍不够。我们按空行分段、保留段落 ID、按查询词重叠评分并返回原文。没有命中就弃答。分数是词项重叠,不是置信度、真实性或语义相关性。先用这个简单基线暴露失败,再引入 embedding 或 LLM。

  1. 检查查询词 refund 与 deadline。
  2. P1 包含 refund,重叠分数为 1/2 = 0.5;P2、P3 为零。
  3. 原样返回 P1 和 ID,不编造综合回答。
  4. 将问题改为 reimbursement window:虽然语义相关,基线仍弃答,由此理解语义检索的价值。

3 · 运行并修改输入

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

{
  "status": "evidence_found",
  "evidence": [
    {
      "id": "P1",
      "text": "Refund policy: request a refund within 30 days.",
      "matches": [
        "refund"
      ],
      "score": 0.5
    }
  ],
  "extract": "[P1] Refund policy: request a refund within 30 days."
}

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

4 · 完整源代码

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

下载源代码 ↓
// Local lexical retrieval baseline. No LLM, embeddings, PDF parser or network.
export const example = {
  query: 'refund deadline',
  document: 'Refund policy: request a refund within 30 days.\n\nShipping policy: delivery takes 5 days.\n\nSupport policy: contact support for damaged items.'
};
const terms = text => new Set(text.toLowerCase().match(/[\p{L}\p{N}]+/gu) || []);
export function run({query, document}) {
  if (typeof query !== 'string' || typeof document !== 'string') throw Error('query and document must be strings');
  if (document.length > 20000 || query.length > 500) throw Error('Input limit exceeded');
  const q = terms(query);
  const evidence = document.split(/\n\s*\n/).map((text, index) => {
    const tokens = terms(text);
    const matches = [...q].filter(term => tokens.has(term));
    return {id: `P${index + 1}`, text, matches, score: matches.length / Math.max(1, q.size)};
  }).filter(item => item.score > 0)
    .sort((a, b) => b.score - a.score || a.id.localeCompare(b.id)).slice(0, 2);
  return {
    status: evidence.length ? 'evidence_found' : 'abstain',
    evidence,
    // Evidence quotes, not a generated or semantically verified answer.
    extract: evidence.map(item => `[${item.id}] ${item.text}`).join('\n')
  };
}
import {run, example} from './document-evidence.mjs';
console.log(JSON.stringify(run(example), null, 2));

5 · 失败案例与生产差距

关键词命中可能无关或互相矛盾。段落 ID 仅在当前输入中稳定,生产引用需文档版本与偏移。按词边界处理对未分词中文较弱。演示只接收纯文本,不解析 PDF 或 OCR。文档里的指令应视为数据,不能升级成后续生成阶段的系统指令。

6 · 你的实现练习

加入一个相关同义改写和一个堆关键词的干扰段。在人工标注题集上测 recall@2,再增加版本化引用与句子级切分,每次只改变一个组件。

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

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

假设、参考实现与验收

词法分数为匹配的唯一查询词数/唯一查询词数。空查询或无匹配则拒答。引用证据不等于语义蕴含。

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

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

词法分数为匹配的唯一查询词数/唯一查询词数。空查询或无匹配则拒答。引用证据不等于语义蕴含。

提示:隔离假设

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

最小可运行算例

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

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

测试与迁移

词法分数为匹配的唯一查询词数/唯一查询词数。空查询或无匹配则拒答。引用证据不等于语义蕴含。

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

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

预测、检验与证据记录

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

打开记录/导出/清除 →

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