为什么数据库里有资料,模型仍可能没看到
初次报告漏掉了一条发布说明,可能有很多原因:没有采集这份材料,提取时没有选中这项主张,检索没有返回它,候选数量限制排除了它,或者模型读到了却没有正确使用。
如果把这些情况统称为“模型记忆不好”,就找不到可修复的边界。Context Engineering 在这里首先意味着:明确这次问题需要什么材料,系统实际选择了什么,以及模型这一轮究竟收到了什么。
本项目把持久化资料、检索观察、解析后的候选与模型输入分开。理解这四层,才能判断应该补采集、改提取、改检索,还是改模型判断和评测。
从保存记录到一次模型请求
数据库有材料,不等于这次模型调用已经看到全部材料。
- 01文档与证据库
保留来源快照、版本、主张与引用;它们是持久化记录。
- 02检索返回观察 ID
搜索限定画像范围的证据,形成这次运行的观察集合。
- 03Resolver 解析候选
按观察 ID 与画像版本读回材料,缺失或越界时拒绝。
- 04序列化为 JSON 数据
组合问题、预算和候选;外部文字不取得系统指令权限。
- 05模型判断与引用检查
回答只能使用允许的候选;代码再次核对返回的引用。
完整原文复核走另一条显式路径,读取该研究绑定的来源全文;它仍未自动追读链接、PR、源码或测试。
来源文档先固定内容版本。提取产生 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 不稳定”。