qinghuan
← 回到知识探索

AI 直觉 / 动手实验

刚刚查到的资料,为什么仍可能已经过时?

把获取时间、来源核验时间和事实适用日期分开,助手才能知道哪条证据需要重查,哪条只适合回答过去的问题。

展开本文目录
  1. 下载完整练习包
  2. 一份资料至少可能带着三种时间
  3. HTTP 说“新鲜”,回答就一定正确吗?
  4. 重新核验,也要说清核验了什么
  5. 先写本题规则,再写判断函数
  6. 同样刚取回,让六条资料走不同出口
  7. 最终回答也应保留这层边界
  8. 从规范走回自己的项目
  9. 记住这三点
  10. 别把例子用过头
  11. 自己试一小步
  12. 查原始资料
开始前,会这些就够了

下午你问茶铺今天几点关门,助手刚成功查到“18 点”,便说这是最新信息。仔细一看,工具读的是上周生成的目录,今天的临时安排在另一份通知里。查询发生在刚才,只证明这次取回动作很新,没有证明被取回的事实也很新。

已有商户问答评测给出旧资料与今日工具结果冲突的题设;本篇继续追问,工具中的“今日”究竟凭什么成立。练习产物是一份证据准入清单,把时间条件写进程序。它不做用户记忆合并,也不实现 Redis 缓存一致性。

把例子带到自己的电脑上

下载完整练习包

需要 Python 3.10 或更新版本;制作时实测 3.14.0。使用标准库,不需要安装第三方包。下载 ZIP 后选择“全部提取”,进入能看到 README.md 的文件夹。

下载 ZIP · 5 个文件
包里有什么
  • evidence_freshness.py:完整示例
  • README.md:环境、范围与独立练习
  • observed.stdout.txt:制作时的观察记录
  • verification.json:对应源码的验证范围
  • SHA256SUMS.txt:文件内容摘要

在这个文件夹打开 PowerShell,逐行运行

python --version
python -B evidence_freshness.py

解压后在含示例文件的文件夹打开 PowerShell,按命令运行。先预测结果,再与当次输出对照。 离线固定数据与应用规则,不代表真实模型、完整协议或服务联调。

找不到命令或文件时,先按 README 检查环境和所在目录。文中标出的阅读时间只估算文章篇幅,安装环境和动手练习可按自己的节奏进行。

一份资料至少可能带着三种时间

获取时间是应用什么时候拿到材料;来源核验时间是何时按可信流程确认过所用来源;事实适用时间是这句话描述哪一天或哪段时期。三个时间可以不同:今天下载的年度报告可以准确描述去年,却不能凭下载日期回答“此刻还有多少库存”。

还要区分资料本身更新与目录介绍更新。一本旧手册被重新登记进资料库,不代表正文已修订。W3C DCAT 3 分开描述资源修改、目录记录修改和数据覆盖时期,能帮助我们给字段起准确名字;本篇的字段名与准入算法是教学设计,并非 DCAT 的强制执行规则。

因此,先把用户问题中的时间写清。问“上周六几点关门”与“今天几点关门”,需要的事实区间不同。不能简单给所有旧资料扣分,否则历史问题最合适的原始记录反而会被清掉。

HTTP 说“新鲜”,回答就一定正确吗?

HTTP 缓存中的 freshness 处理的是存储响应何时可按缓存规则复用。RFC 9111 使用响应年龄与新鲜期比较;年龄会考虑生成或成功重新验证等信息,不只是你刚把数据收到本机的时刻。因此,“工具本次返回 200”不能被应用擅自翻译成“所有上游事实都实时”。

这层规则也不替应用判断资料内容是否准确。服务可能按约定缓存一份有效的旧年度报告,也可能返回尚未更新的业务表。缓存协议合规与回答所需的事实时效,应分别观察。本文不手写 HTTP 年龄计算器,避免拿简单减法冒充包含传输延迟的规范算法。

实务上,工具响应可以暴露业务允许的来源版本、数据日期和缓存提示,使调用方判断用途。没有这些字段时,应记录“来源时效未知”,而不是把缺失值补成当前时间。若系统没有可靠的核验动作,也就不应该自动产生“已核验”时间。

重新核验,也要说清核验了什么

HTTP ETag 是服务端给某个表示附上的不透明校验标识,不是能直接按大小排序的业务版本号。带条件的请求可能得到 304,让客户端复用已有表示。它能帮助判断该表示在协议条件下是否需要重新传输,不等于来源对现实世界的每条陈述都重新调查了一遍。

例如缓存中的“研究报告 2024 版”经重新验证仍未变化,你可以更新这份表示的核验记录,却不能顺手把报告事实日期改成今天。同样,业务数据版本 r9 与文档版本 r9 若来自不同来源,名称相同也不能证明内容一致。

遇到相互矛盾的证据,应保留来源、适用范围和版本,再按明确的业务优先规则处理。选择“最后收到的那条”只依赖网络顺序;选择“数字最大的版本”则假设了可能根本不存在的全局排序。本文示例不自动裁决多个来源之间的冲突。

先写本题规则,再写判断函数

本题约定:查询结果必须成功;获取时间和最近核验时间不能晚于当前时间;有效期终点可以在未来;材料给出的适用区间包含问题目标时刻;最近核验距当前时间必须小于五个时间单位。区间采用含起点、不含终点的写法,恰好到复查期限就需要重查。五只是方便观察的教学参数,不是推荐的生产刷新周期。

当期限缺失、已经超出区间或该重查时,程序输出不同原因。它不把这些情况统统叫“假消息”,也不自动把来源旧值替换为新值。能通过的结果叫 candidate,表示仅通过时间准入,还需要身份权限、内容支持和来源可靠性检查。

这组规则故意保守:缺失适用区间不等于永远有效,而是交给明确的补证流程。有些资料确实可以约定无期限,但应先为那类来源增加清晰规则,再扩展代码,不能偷偷把 None 当作无穷远。

同样刚取回,让六条资料走不同出口

运行前先预测:适用期已经结束、很久没核验、当前可用、用于历史问题、缺适用期和查询失败,应该分别去哪。例子把时钟固定为整数 100;历史问题的目标时刻为 70。没有网络、真实商户、模型调用,也没有声称测试过任何缓存服务。

读输出时注意两组对照。前两条都刚获取,却因为不同原因不能直接当当前依据;第四条材料覆盖过去,反而能通过历史问题的时间准入。末尾断言锁定到期边界、未知核验时间、未来时钟和错误区间,让规则不会随着运行日期变化。

展开收起代码 · 小实验python · 48 行

长行可在代码区域内左右滚动,按 Tab 可把焦点移入代码区。

小实验 · python
"""Offline application policy, NOT an HTTP cache or a truth verifier."""


def decide(record, now, target_time, recheck_after):
    # All times are integers in the same fictional time scale.
    # target_time = when the question's fact should apply; now = evaluation time.
    if record["status"] != "ok":
        return "unavailable"
    fetched = record["fetched_at"]
    checked = record["checked_at"]
    if fetched > now or (checked is not None and checked > now):
        return "clock_error"
    start, end = record["valid_from"], record["valid_until"]
    if start is None or end is None:
        return "unknown_period"
    if start >= end:
        return "invalid_period"
    if not start <= target_time < end:  # Our explicit half-open policy.
        return "outside_period"
    if checked is None:
        return "needs_recheck"
    if now - checked >= recheck_after:  # Boundary itself requires rechecking.
        return "needs_recheck"
    return "candidate"  # Still needs source, scope and claim-support checks.


base = {"status": "ok", "fetched_at": 100, "checked_at": 99,
        "valid_from": 90, "valid_until": 110, "revision": "r1"}
cases = [
    ("fresh_fetch_old_period", {**base, "valid_until": 95}, 100, "outside_period"),
    ("fresh_fetch_old_check", {**base, "checked_at": 80}, 100, "needs_recheck"),
    ("current_candidate", base, 100, "candidate"),
    ("historical_question", {**base, "valid_from": 0, "valid_until": 90}, 70, "candidate"),
    ("missing_period", {**base, "valid_until": None}, 100, "unknown_period"),
    ("failed_tool", {**base, "status": "error"}, 100, "unavailable"),
]
for label, record, target, expected in cases:
    actual = decide(record, now=100, target_time=target, recheck_after=5)
    assert actual == expected, label
    print(f"{label}: {actual}")

assert decide(base, 100, 110, 5) == "outside_period"
assert decide({**base, "checked_at": 95}, 100, 100, 5) == "needs_recheck"
assert decide({**base, "checked_at": None}, 100, 100, 5) == "needs_recheck"
assert decide({**base, "checked_at": 101}, 100, 100, 5) == "clock_error"
assert decide({**base, "valid_from": 110}, 100, 100, 5) == "invalid_period"
assert decide(base, 100, 90, 5) == "candidate"
print("PASS: 6 scenarios + 6 boundary assertions")

怎样运行:保存为 evidence_freshness.py,用 Python 3.10 或更新版本运行:python evidence_freshness.py。仅用标准库,不联网、不安装依赖。 2026-10-13 已用 3.14.0 执行这份示例并通过自带断言;下方为当次输出。离线固定数据与应用规则,不代表真实模型、完整协议或服务联调。

运行后对照结果
fresh_fetch_old_period: outside_period
fresh_fetch_old_check: needs_recheck
current_candidate: candidate
historical_question: candidate
missing_period: unknown_period
failed_tool: unavailable
PASS: 6 scenarios + 6 boundary assertions

最终回答也应保留这层边界

通过时间准入后,回答仍应把具体结论挂到具体材料。例如可以说某份安排适用于哪个日期;核验失败时,只能说明目前无法确认。若用户需要立刻行动,应用应选择可用的核验渠道或明确停止,不能用流畅措辞把 unknown_period 包装成肯定答案。

证据在处理过程中也可能过期。检索开始时还在期限内,排队、长推理或等待人工确认之后已经超时,提交结论前就要按规则再检查。能否复用以及是否重新查来源,应由事实变化速度和业务容忍度决定,并把决定记录下来。

保存证据时,只记最终进入本次回答的来源标识、版本、目标日期、检查结果和必要的受控内容。检索候选列表不能替代实际上下文。资料后来更新后,旧回答记录仍应如实反映当时看到什么;需要修订时新增更正记录,别回写历史让旧回答看起来早就正确。

从规范走回自己的项目

先读 RFC 9111 的 Freshness 与 Calculating Age,标出哪些是缓存层证据;再读 RFC 9110 的 ETag 与 304,圈出它们验证的对象;最后看 DCAT 3 的修改日期和时间覆盖字段。给自己的工具响应设计字段时,每个时间都写明由谁生成、检查的是什么。

这份程序没有验证跨机器时钟同步、真正的 HTTP 缓存、来源数据更新或模型引用质量。跨系统时间还要处理时区与时钟误差,等待时长可参考墙上时钟与秒表;不要把本题统一整数时钟直接搬去比较不同机器的单调计时值。

记住这三点

  • 刚取回的材料可能描述过去,获取时间不能替代事实适用时间。
  • 缓存可复用、来源表示未变化、事实适合回答当前问题,是不同判断。
  • 缺失时间应保持未知;通过时间准入还不能证明结论真实。

别把例子用过头

  • 五个时间单位和半开区间是本题政策,不能说成 HTTP 或 DCAT 的通用要求。
  • ETag 是不透明校验标识,不是可跨来源排序的版本号。
  • 实验没有运行真实 Agent、HTTP 缓存、Redis 或外部数据源。

自己试一小步

一个活动助手要同时回答“明天安排”和“去年记录”,你会怎样给两类问题设计证据规则?

  1. 各写三份虚构材料,分别记录获取、来源核验和适用时间。
  2. 自行决定允许使用未知结束日期的条件,并说明依据与限制。
  3. 增加一个等待确认期间超过复查期限的场景,记录最终应补做的检查。

做到这些,就算完成

  • 是否针对问题目标日期判断,而不是只看文件新旧?
  • 是否保留查不到、核验失败和证据冲突各自的状态?
  • 是否保存旧回答实际使用的版本,同时能给出后续更正?

查原始资料

想确认一个细节,先看这份资料对应的部分,不必从头读完所有文档。

  • RFC 9111:HTTP 缓存新鲜度 (新标签页)↗IETF / RFC Editor · 英文

    阅读 4.2 Freshness、4.2.1 Calculating Freshness Lifetime、4.2.3 Calculating Age;支持缓存年龄与新鲜期的语义。本文五单位复查规则不来自该规范。

    2026-10-13 已打开并核对RFC 9111 固定文档中的所列段落;阅读不需要账号。未据此执行真实模型或服务。

  • RFC 9110:ETag 与 304 (新标签页)↗IETF / RFC Editor · 英文

    阅读 8.8.3 ETag、8.8.3.2 Comparison、15.4.5 304 Not Modified;支持不透明校验标识及条件请求复用表示的边界。

    2026-10-13 已打开并核对RFC 9110 固定文档中的所列段落;阅读不需要账号。未据此执行真实模型或服务。

  • DCAT 3:资料修改、目录修改与时间覆盖 (新标签页)↗W3C · 英文

    阅读 6.4.8、6.5.4、6.6.6,分别核对资源更新、目录记录更新和数据覆盖时期;不把这些元数据自动等同于事实正确性。

    2026-10-13 已打开并核对DCAT 3 推荐标准中的所列段落;阅读不需要账号。未据此执行真实模型或服务。