为什么数据库里有资料,模型仍可能没看到

初次报告漏掉了一条发布说明,可能有很多原因:没有采集这份材料,提取时没有选中这项主张,检索没有返回它,候选数量限制排除了它,或者模型读到了却没有正确使用。

如果把这些情况统称为“模型记忆不好”,就找不到可修复的边界。Context Engineering 在这里首先意味着:明确这次问题需要什么材料,系统实际选择了什么,以及模型这一轮究竟收到了什么。

本项目把持久化资料、检索观察、解析后的候选与模型输入分开。理解这四层,才能判断应该补采集、改提取、改检索,还是改模型判断和评测。

从保存记录到一次模型请求

Agent Evidence Lab已保存的资料,经过选择才成为一次模型输入

数据库有材料,不等于这次模型调用已经看到全部材料。

  1. 01文档与证据库

    保留来源快照、版本、主张与引用;它们是持久化记录。

  2. 02检索返回观察 ID

    搜索限定画像范围的证据,形成这次运行的观察集合。

  3. 03Resolver 解析候选

    按观察 ID 与画像版本读回材料,缺失或越界时拒绝。

  4. 04序列化为 JSON 数据

    组合问题、预算和候选;外部文字不取得系统指令权限。

  5. 05模型判断与引用检查

    回答只能使用允许的候选;代码再次核对返回的引用。

完整原文复核走另一条显式路径,读取该研究绑定的来源全文;它仍未自动追读链接、PR、源码或测试。

图 04 · Agent 决策上下文的形成过程,不是全文已被模型永久记忆的声明。

来源文档先固定内容版本。提取产生 Claim 和 Evidence,检索返回可用证据卡。运行中的观察集合保留实际得到的 Claim ID;随后 Resolver 只读回当前观察允许的材料,形成模型需要的候选。

当前 JdbcObservedEvidenceResolver 检查画像版本、非空且有限的 ID 集合、唯一性与候选完整性。未知 ID、缺失记录或不匹配的解析结果不能靠模型自行补齐。这一层解决的是材料身份和完整性,不是最终语义质量。

层次 保存或携带什么 常见误解
持久化资料 文档快照、主张、Evidence 与历史结果 保存过就等于模型永久知道
检索观察 本次搜索实际返回的候选 ID 搜索成功就等于覆盖问题全部材料
解析候选 标题、主张、分类、引用与来源版本等 ID 正确就意味着语义相关
模型上下文 本次序列化后发送的问题、预算与候选 同一运行里所有文本都已发送

这也是数据库记录、工具返回和模型理解之间需要逐层核查的原因。一个环节正确,不会自动证明下一环节正确。

当前 RAG 做什么,没有做什么

当前检索基于 PostgreSQL 全文检索,结合用户画像范围读取已有 Claim/Evidence。它帮助模型从已存资料中找到相关候选。当前没有因为使用了 RAG 就自动具备网页浏览、关联 PR 阅读、源码执行或全网搜索。

研究锚点与检索范围也需要分开。创建 Research Run 时选择一个 Signal;Agent 的检索可以使用画像下更广的已有证据。最终报告要保存每条引用自己的来源身份和版本,不能把不同来源的材料都挂到所选 Release 上。

Context 的质量因此至少包含三类问题:是否取到了相关材料;是否保持了准确版本和引用关系;是否在有限输入中保留了足够的支持、反证与未知。引入向量数据库并不能自动替代这些设计,是否需要新的检索技术应由任务评测决定。

候选怎样进入模型

下面是根据当前 promptData 压缩的输入形状,省略实际标识和值。它说明数据边界,不是完整请求体或可直接执行配置。

{
  "question": "<本次研究问题>",
  "stepNumber": 2,
  "remainingBudget": { "steps": 2, "wallClockMs": 20000, "modelTokens": 3000 },
  "candidates": [
    {
      "claimId": "<已观察候选 ID>",
      "claimTextZh": "<主张>",
      "verificationStatus": "UNVERIFIED",
      "documentVersion": 1,
      "evidence": [{ "quote": "<保存的原文片段>", "startOffset": 0, "endOffset": 12 }]
    }
  ]
}

示意中的数字只是便于阅读,不是本项目默认预算或真实引用位置。真实请求由代码从记录组装。默认策略最多向决策路径解析十个候选,每张卡的 Prompt 证据片段也有限制,系统没有把整个数据库倾倒给模型。

系统策略要求模型把问题和候选当作不可信数据,并限定输出的结构和引用。模型可能仍被误导,因此还要对返回 ID、状态和结构做程序检查,并用对抗样本评测。序列化为 JSON 可以明确边界,但不是 Prompt Injection 已彻底解决的证明。

工具返回的数据为什么不能成为新的权限

Release 正文里可以出现命令、链接、角色声明,甚至“忽略前面规则”这样的文字。它们属于研究材料,而不是服务获得的新指令。检索工具返回一个字符串,也不会让这个字符串取得执行命令或修改预算的权力。

边界 当前控制方式 仍需要关注的问题
来源进入系统 内置三个仓库的 Releases 采集范围 合法来源也可以包含错误或恶意文字
材料进入模型 固定策略与不可信 JSON 数据分离 模型可能错误解释材料,需要评测
模型提出结果 严格协议与候选引用白名单 合法 ID 也可能被用于不恰当语义
进入工具执行 由代码调用已注册能力并检查运行条件 增加新工具必须重新设计权限与测试

因此,工具协议、输入 schema、权限、数据身份和停止条件共同构成边界。只在 Prompt 中写“不要越权”,不能替代服务端实际拒绝越权操作。

完整原文复核怎样补充初次上下文

初次提取与检索可能遗漏相关内容。当前补充解读显式读取该研究绑定的完整来源正文,连同原问题、来源标题与初次回答作为数据交给模型。模型按问题拆出子问题,给出事实、解释、工程启示和原文片段。

这是对一份已保存快照的扩大阅读,不是主动追读外部链接。它能补出初次候选之外的行,也可能发现整份快照仍缺少关键规则。后一种情况需要保留 PARTIAL 或 NOT_FOUND,而不是从常识扩写为来源已经证明的事实。

当前限制与语义如下,均针对固定基线的补充解读路径,不能套用到所有 Agent 或研究调用:

限制或状态 实际含义
正文最多 16000 UTF-16 单位 超过则拒绝,不截断后仍称全文
单次模型输出上限 8192 Token 供应商可能将推理 Token 计入输出额度;被截断的 JSON 应失败
模型响应另有大小、字段与数量校验 Prompt 中的要求还需要代码执行结构边界
ANSWERED 子问题有引用发现;不等于外部事实已独立验证
PARTIAL 当前材料只能回答一部分
NOT_FOUND 当前保存快照未找到,不表示外部能力不存在

UTF-16 单位不同于字数和 Token。Java 的字符串位置采用这种单位;模型分词计量由供应商定义。将这三者混用,会造成引用坐标、输入限额或费用解释错误。

长任务上下文接下来需要增加什么

未来主动补证据时,系统需要保存的不只是“上一次回答”。至少还需要当前问题、已有发现、缺少什么依据、下一次读取为何能减少不确定性、材料版本、已消耗预算,以及停止原因。

下面是后续设计的研究记录示意,不是当前 API、数据库表或已实现的自动规划协议:

研究问题:某项校验在什么边界生效?
已知:来源标题提到新增校验;已有对应引用。
缺口:输入条件、失败语义与版本范围没有说明。
拟议补读:关联实现和测试;先取得准确链接与版本。
停止依据:已有材料足以解释有限机制,或预算耗尽并保留未知。

这份记录的价值在于让下一步有理由。堆积更多上下文并不保证理解更准确;系统需要知道新材料是在回答哪个缺口,以及它是否足以改变原来的解释。

沿实现继续核查

项目内逻辑路径 核对重点
agent/runtime/SpringAiDecisionEngine.java 确定性分支、候选上限、Prompt 数据和输出白名单
agent/runtime/JdbcObservedEvidenceResolver.java 观察 ID、画像版本、完整候选与引用解析
agent/loop/RetrievalSearchEvidenceTool.java 工具怎样把检索能力接到循环
evidence/retrieval 模块 全文检索的实际范围、排序与结果限制
research/briefing/ResearchBriefingService.java 绑定来源读取与全文长度检查
research/briefing/SpringAiResearchBriefingModel.java 数据字段、调用限额与被截断输出的处理
JdbcObservedEvidenceResolverIT、SpringAiDecisionEngineTest、ResearchBriefingValidationTest 候选越界、伪指令、引用与结构检查

上下文工程的一个实际收益,是让失败可以被定位:资料没保存、检索没取到、输入没送到、模型没用对,应当留下不同的证据,而不是都归入一句“AI 不稳定”。