你无法检索到没人写下的数字:OKF与向量数据库RAG的对比。
基于向量数据库支持的Bedrock知识库的经过验证的OKF捆绑包在调查统计中的应用:为何计算出的数据根本无法被检索到。
来源: You Can’t Retrieve a Number Nobody Wrote Down: OKF vs. Vector Databases for RAG Chatbots
每个项目都会有一个反复出现的步骤,而这里就是:先编译图表,再提取文字说明。这个步骤源自一个以常规方式启动的聊天机器人。包括调查说明、代码手册、总结报告以及方法论相关的PDF文件在内的十几份CDC文档被上传到了Bedrock知识库,人们期望一个资料丰富的数据库能给出优质答案。
但事实并非如此。其原因在于人们对检索增强生成技术最普遍的误解——认为文档越多,答案就越准确。向量数据库只能返回其内部已存储的文本。对于那些从未被记录下答案的问题,数据库的规模根本没有任何影响。
那十二份文档详细说明了与糖尿病相关的各项变量:它们的含义、调查对象以及答案的编码方式。但没有一份包含用户实际会要求的统计数据。这些数字是从29,522行调查数据中计算得出的,却并未出现在任何PDF文件中,因此无论如何搜索都找不到。
这还会导致更严重的错误。人们以为只要某个主题出现在文档中,RAG就能处理所有相关问题。实际上它只能处理那些答案以段落形式呈现的问题,任何需要推算的内容都在它的处理范围之外。
于是这个聊天机器人被重新构建了。它最初是一个结合了 Amazon Bedrock Flow、AWS Amplify Gen 2 和 Next.js 的教程应用,重构时将其搜索引擎换成了经过验证的 Open Knowledge Format(OKF)数据包。为了进行公平比较,人们还基于相同的文档构建了一个真正的 Bedrock 知识库,然后针对最关键的两个问题对两者进行了直接测试:答案是否正确,以及响应速度有多快?
在提出核心问题后,知识库找出了五个相关变量,并准确指出了限制:这些文档中并未包含实际计算出的统计数据。它甚至还推荐了正确的分析方法,即具有某一特征的同时也具有另一特征的人群的加权比例,而这正是OKF在构建时会使用的计算方式,只不过是由一个无法实际执行该操作的系统给出了正确说明。归根结底就是一句话:无法获取那些没人记录下来的数字。OKF方面则给出了一个根据正确的人群定义和权重从微观数据中计算出的数值作为回应。
测试的设置方式
该测试环境的设置刻意保持对称性。Claude Sonnet 4.5在us-east-1区域的双方都生成了答案,一方通过进程内SDK传输,另一方则使用与已部署的Lambda相同的系统提示词。在获得任何结果之前就制定了测试方法,所有七个问题及每次测试的结果都会被记录下来,原始答案也会被保存。关于时间方面的注意事项是:测试工具直接调用检索功能与Bedrock,而实际应用则需先通过AppSync和Lambda处理。正在测试的OKF代码是应用的实际代码,而传输层代码并非如此,因此这些时间数据是比较两种以相同方式测量的设计结果,并非浏览器用户所看到的实际时间。
替换方案:单个Lambda
Amplify聊天机器人将各类工具以Amplify数据工具的形式呈现,每个工具都是GraphQL查询背后的Lambda函数,而Bedrock Flow就是其中之一。此次更新新增了第二个工具askOkf,它从经过验证的模块中获取答案,而非通过Flow来实现。其架构、前端界面及部署方式均保持不变。
// amplify/functions/askOkf/handler.ts — the essence
export const handler: Schema["askOkf"]["functionHandler"] = async (event) => {
// in-process TF-IDF over the bundle
const hits = search(event.arguments.question, 3);
const top = hits[0];
// Grounded-or-refuse: below the score floor,
// nothing verified matches → refuse
// before ever calling the model.
if (!top || top.score < MIN_SCORE) {
return { answer: refusal().text, citation: "", grounded: false, mode };
}
// read the verified figure straight from frontmatter
if (mode === "extractive") {
// 0 model calls - sub-millisecond
const a = extractiveAnswer(hits);
return { answer: a.text, citation: a.citations[0] ?? "", grounded: true, mode };
}
// generative: ground Claude on the ONE retrieved concept,
// safety-prompted grounded-or-refuse
const concept = top.concept;
const context = `Concept: ${concept.label}\nSource: ${conceptSource(concept.frontmatter)}\n\n${concept.text}`;
const response = await bedrock.send(
new ConverseCommand({
modelId: env.MODEL_ID,
// grounded-or-refuse; declines medical-advice intent
system: [{ text: SYSTEM_PROMPT }],
messages: [{ role: "user", content: [{ text: `Verified concept:\n${context}\n\nQuestion: ${question}` }] }],
inferenceConfig: { maxTokens: 400, temperature: 0 },
})
);
const text = response.output?.message?.content?.[0]?.text ?? "";
return { answer: `${text}\n\nSource: ${citation}`, grounded: true, mode };
};
在处理程序中,search()会扫描随Lambda一起打包的四个经过验证的Markdown文件。整个过程不涉及向量数据库、嵌入服务,也没有网络往返操作。只有经过验证的概念才会被纳入结果,这意味着已有人员进行了分析并核对了结果。那些具有迷惑性的错误数据,比如3.66%的未加权全样本胰岛素率,在这些文件中均不存在,因此不可能被输出。
存在两种实现路径,基准测试会对这两种路径进行测试。提取型路径直接从前置信息中读取已验证的数据,无需调用任何模型。生成型路径则需要进行一次基于实据的Converse调用。
基准测试:真正的向量RAG
对手必须足够强大。那是一个托管在S3 Vectors上的受控Bedrock知识库,其中存储着真实的CDC 2023 NHIS相关资料:调查说明、成人样本代码本、总结与方法报告、插补技术说明以及成对权重说明文档。一位能力出色的工程师会构建出完全相同的系统。由于模型本身完全一致,唯一的变量就在于答案的来源是向量存储还是函数内部的打包文件。
共有13个文件被上传,其中10个被索引。那3次失败均发生在.zip格式的压缩文件上,而Bedrock不支持这类格式,恰好这些文件包含原始微数据。这听起来像是能挽救向量数据库的漏洞,但实际上并非如此。所有描述糖尿病相关变量的文档都成功被索引了。缺失的只是原始数据行,而且即便有原始数据行,也无法得出这些数值——因为在包含29,522条记录且存在跳过模式的样本集中,通过调查加权计算得出的百分比只是计算结果而非实际文本,无法通过分割数据的方式获取。
还有一个坦率的观察:向量数据库那部分其实很廉价。十几份文档加上一个知识库只需几分钟就能处理完成。而OKF那部分则需要真正的工作量,包括对概念进行建模,以及利用微观数据进行分析以验证每一个数值。误将检索速度之快当作已解决准确性问题,本身就是一种误解。低成本的实现方式与严格的正确性是两码事,这种便捷性正是应该保留向量数据库而非将其废弃的理由。
正确性
题目包括三道有已知验证答案的数值题、三道测试排除项的题目以及一道方法论问题。评分依据是事先制定的标准,每道数值题进行30次测试,每道测试题进行2次测试,所有结果都会被记录下来。在所有三道数值题中,向量RAG在任何一次测试中都未能得出经过验证的数值。
延迟
对于每题有30次试验的图表类问题(前2次至30次为预热试验),生成式OKF方法的速度比传统方法快1.4到2.4倍,因为它无需通过网络进行信息检索,且处理的上下文规模也小得多。而提取式方法几乎可以瞬间完成,因为根本不需要调用任何模型。应关注数值的差异而非平均值:在胰岛素相关问题上,两者的速度差距最大,约为2.4倍;而在年龄相关问题上,差距最小,约为1.4倍,两者几乎相当。因此,每道题对应的数值才是实际结果,而非一个统一的整体比率。况且速度本身并非关键因素。知识库方法的耗时为3.3到3.7秒,已经相当不错,它的劣势在于准确性而非速度。
研究结论:检索式与编译式方法对比
在每一次测试中,向量RAG都无法提供任何经过核实的数值,而工程质量不佳并非原因——那些数字根本就不存在于文档中。经过调查加权后的31.96%这一数值是根据正确的总体样本和权重从微观数据中得出的,但任何PDF文件中都没有这一数据。检索系统只能返回现有的文本。OKF能够给出答案,是因为相关数值事先已经计算并核实过,而知识库则没有任何可检索的内容。
注意知识库的失败表现:它明确表示无法在文档中找到该百分比,也不会编造数字。这种诚实的态度反而更凸显了问题所在。即便是一个设计良好、构建完善的向量RAG,从结构上来说也无法回答基于文档的统计计算类问题。
这里还存在另外两种误解。
- 基于事实的推理并不能保证结果的正确性。该知识库会拒绝提供错误信息,也不会编造内容,但这只是良好默认设置的结果,并非RAG的固有特性。如果使用更急于给出答案的模型,或是摘要文档恰好包含了未经权重的出现频率,就可能会得出错误的数值。
- 引用并不能证明什么。来源链接仅表明文档已被获取,但并不能说明答案确实源自该文档。OKF的引用则有所不同,因为它指的是在构建时针对数据计算并经过验证的数值,而非类似句子旁边的文本。
更好的提示词或更多补充内容也无法解决这个问题。真正的解决办法是停止获取这些数值并停止对其进行处理。
OKF的局限与权衡
OKF并非通用的答案引擎,基准测试显示了它的能力边界。
它回答的是“多少”,而非“为什么”。对于关于调查权重如何改变患病率的定性问题,向量RAG能够直接从调查描述中得出丰富且有依据的答案,而四概念OKF组合只能提供相关的数值。经过验证的数值组合在计算统计方面十分精确,但对叙述内容则保持沉默。这是两者之间的差异而非缺陷,同时也直接反映了下方的架构设计。
快速意味着无需判断。抽取式路径能在不到一毫秒的时间内给出答案,但当被问及医疗建议时,它只会返回“31.96%”,因为它无法理解用户的真实需求。生成式路径则会拒绝提供建议,仅给出相关统计数据,并明确警告称这些数据与任何个体的具体情况无关。这种判断需要消耗一次模型调用时间,大约两秒。应将即时响应路径和意图识别路径视为独立的工具,分别进行报告,不得将二者混为一谈。
补充工具:第三种方案
这些限制引出了一个结论:OKF负责提供经过验证的信息,而向量数据库则在OKF无法处理的定性、叙事层面表现优异。合理的设计应是同时使用这两种工具,让智能体根据需求从中选择。
该实体已基于此理念使用了两种经过验证的工具,它们都在处理过程中运行且仅限于处理汇总数据:概念搜索(search_okf)和允许列表式的汇总数据查询(analyze_rows)。这两种工具都会仅返回其能够确认的信息。Bedrock知识库则成为第三种工具,但其内容被明确标记为未经验证的叙述。对于数字问题,该实体会给出经过验证的数值;对于解释,则会提供基于事实的文字描述;若两者均不适用,则会予以拒绝,并将这三者区分开来。
这种划分也是合理分配精力的方式。处理知识库只需几分钟,而处理经过验证的数据集则需要数小时。以较低成本获取叙述性内容,而将繁重的处理工作仅集中在那些数值必须准确的情况下:不要整理检索系统免费提供的内容,也不要去检索那些需要验证的内容。
相关结果的预览
将四种功能集成到同一个模型中(验证、计算、检索和实时处理),自然会引发一个问题:更大的模型能否更好地区分这些功能?有人向三个模型展示了一则包含虚构统计数据的虚假新闻标题,九次试验中这三个模型都重复了该数字,同时将其标记为未经验证的第三方说法。不过,这些虚构的健康数据依然每次都会呈现给读者。只有在所有九次试验中都通过代码实现来源核查,才能阻止这种情况发生。所选的模型并不会影响安全性。
这改变了人们对这一基准测试的理解。经过验证的数据集能提供正确的数字,这已经完成了一半的工作。另一半工作则是防止错误的数字以相同标签传播,而这取决于代码而非模型本身。
实时处理与独立审核
所有这些内容都没有保存在笔记本电脑上。askOkf在真实的Amplify沙箱环境(Cognito、AppSync、Lambda)中运行,以“目前有31.96%的人使用胰岛素”及其来源作为回复,同时拒绝了医疗建议类的问题,这一切都是在真实的IAM角色下完成的。在此之前,一项独立的安全审查从代码源中分析了相关逻辑,得出contract-satisfied的结论:该查询需要身份验证,bedrock:InvokeModel权限为最小权限制,且仅限于单个模型使用,无法注入任何内容,每条请求也仅能调用一次受限的模型。
关于模型的说明:Bedrock刚刚将Claude 3 Sonnet标记为旧版本,因此OKF的Lambda函数及基准测试均使用Claude Sonnet 4.5版本。只有保持两侧使用的模型一致,才能确保比较的公平性。
总结
向量数据库是处理开放式、定性问题的最佳选择,它完全胜任这类任务。一旦聊天机器人需要给出具体数值,比如患病率、关键绩效指标、收入数字或合规阈值,检索方式就不再适用,因为这些数值的可靠版本早已被计算出来,只是从未以文字形式记录下来。RAG要么会如实表示找不到相关数据,要么会编造数据,而后者显然是不可取的。OKF则会直接计算出这些数值,在构建时与原始资料进行核对,然后将其输出——仅需四个Markdown文件,无需额外配置,每次试用都能立即使用。
那十几份文档并非问题所在,真正的问题在于缺失的数值,而进一步扩充数据库也永远无法提供这个数值。自己把数据算出来吧。