用户勾选两份资料,再输入一个问题,通常是在表达一个很明确的要求:请从这些资料里找,不要把其他文档的内容混进来。
实现时却容易把它做成结果筛选:先对全库做向量搜索,拿到前十条,再隐藏不属于所选资料的命中。如果最后没有剩余结果,页面显示“没有找到”。这看起来遵守了范围,实际可能从未给所选资料进入候选的机会。
TraceWise 的显式资料选择接入围绕这个问题建立了契约:用户选择的是检索范围,范围必须在候选 Top K 之前生效;它不授予权限,也不能在无结果时悄悄变成全库搜索。
一个101对象的反例
Foundation 的真实Qdrant检查中,建立了101个已登记对象,再从实际全局前100条之外选中一个对象。带选择约束的查询仍然可以命中它。
这不是“把TopK从10提高到100就好了”的例子。只要全局候选的截断发生在范围限定之前,目标就可能被其他资料挤出去。取100条仍可能漏第101个,取更多只是改变失败出现的位置,并没有改变请求含义。
图1:实际机制反例。范围改变应发生在候选TopK之前,不是结果页上的二次隐藏。
写成两个操作会更清楚:“全库最相似的K条中,哪些属于所选资料”和“所选资料中,最相似的K条是什么”,回答的不是同一个问题。即使排名方法完全相同,两者也没有理由得到同样的结果。
Qdrant 提供按payload字段设置过滤条件的能力,条件还可以组合为AND或OR。这为候选阶段限制对象范围提供了机制;如何把产品里的资料选择转换成精确条件,仍需要上层契约决定。Qdrant Filtering 文档介绍的是过滤能力,不替代产品的授权与资料有效性判断。
页面选的是文档,平台接收的是精确版本
用户不会逐一勾选几十个 Evidence revision。他更容易理解“collections资料”或者“一份项目说明”。但一份业务资料可能被登记成多个受治理单元,每个单元仍有自己的版本与有效性。
因此,TraceWise 先读取当前授权目录,把同一来源的单元组合成资料项,展示名称和单元数量。选择标识不仅对应一个标题,也绑定该资料当时包含的精确revision与fingerprint集合。标题相同不代表内容和组成相同。
Foundation 的公开 EvidenceRevisionSelectionV1 接收精确版本对,而不是一串由客户端自行解释的文件名。查询前验证整个选择集合,Qdrant按版本与指纹的成对元数据过滤,再在返回阶段检查当前有效性。索引若返回越界候选,不能直接把它当成可用资料。
这让责任保持清楚:TraceWise 定义业务资料如何分组、用户怎样选择、页面如何解释范围;Foundation 对本轮已登记Evidence的作用域、版本和有效性负责,并提供受约束的索引查询。向量数据库不需要理解“项目说明”这个产品概念,产品也无需另建一套重复的版本权威。
选择不是授权,文件名也不是选择
一个人知道资料名称,并不表示他能读取资料。页面上列出的选项来自授权目录;请求仍需要实际身份与作用域检查。把某个资料标识写进请求,不会给调用者增加权限。
另一方面,问题里出现某个文件名,也不等于用户选择了“只查它”。“比较A与B”可能是在问两份资料,也可能是在讨论正文中同名的概念。当前产品采用显式控件表达范围,而不是自动根据几个词缩小搜索集合。
这不否定自动来源识别的研究价值,但它属于另外一种需要评测的策略。显式选择的接口已经验证,并不能据此宣称自动识别已经足够可靠,更不能让猜测出来的范围覆盖用户明确的选择。
空选择、没有命中和选择失效,不能混成一种回退
在页面切到“仅检索所选资料”后,如果一份也没勾选,请求没有定义一个有效的受限范围。这与“查询当前所有可访问资料”不同:前者拒绝执行,后者是独立的未限定模式。
有效选择内没有命中,同样不能自动扩大到全库。用户可能正在核对某份资料是否包含一项规定;从别处找来一段相关说明,会改变这个问题。更准确的结果是“当前选择中未找到”,而不是不声不响换一个资料集合。
图2:请求状态矩阵。便利性回退不能悄悄改变用户明确选择的资料范围。
资料还可能在选择后发生变化。比如一个原文单元被撤销,或者资料新增了一个章节。如果服务端仅记住名称,便无法知道用户原来选择的究竟是哪一组内容。因此,执行前后重新核对资料目录与选择身份:未知或失效选择拒绝,用户需刷新目录后重新选择。
删除失效项再继续搜索,看起来更流畅,却可能把“查这两份资料”变成“只查剩下的一份”。本轮契约选择让变化显式出现,而不是把这种部分执行伪装成原请求成功。
用真实页面把契约检查到最后
2026年9月9日的接入验收使用 Foundation 0.1.0a20.post20 候选包、真实Qdrant与独立教学资料。安装包测试包含前置范围过滤、当前版本、候选越界及并发期间变更等检查;可选PostgreSQL检查未启用,这组运行没有覆盖该后端的执行。
产品浏览器检查用了3条公开教学资料。明确选择collections后,只返回其1条Evidence和1条关系;页面同时显示实际查询范围,并能打开原文高亮。空选择返回422,未知或失效选择返回409。
撤销检查先确认只读凭证不能写入,再由临时操作员通过公开HTTP撤销collections。在复用同一缓存的情况下,旧选择仍被拒绝;刷新目录后,该项消失,页面清空旧选择。缓存命中没有被当成绕过当前状态的理由。
这些是本地产品流程与接口约束的实际验证,不是相关性分数,也不是全面租户安全认证。本节记录的是post20的历史执行;后续工作依赖为post22,正式基线仍为a12/post10。
范围做得精确,也要有明确容量边界
这条接口支持最多50份所选资料、合计最多256个精确单元;目录最多遍历1000个active Evidence。超出预算明确拒绝,不返回一个看似完整却实际缺项的目录。
这些限制说明当前是有界能力,并不是无限资料规模的解决方案。未来若文档单元更多,需要重新设计目录和选择契约,或扩展平台能力,不能只把上限调高却继续假设版本校验与目录读取成本不变。
“只查这些资料”最终不是一个前端过滤器,而是一次有对象范围、版本身份和失败含义的检索请求。把范围放在正确的位置,既能避免候选截断造成的漏检,也能让用户知道这次结果究竟来自哪里。