2025 年 2 月发布的 NoLiMA 是一种大语言模型(LLM)长文本理解能力评估方法。不同于传统“大海捞针”(Needle-in-a-Haystack, NIAH)测试依赖关键词匹配的做法,它最大的特点是 通过精心设计问题和关键信息,迫使模型进行深层语义理解和推理,才能从长文本中找到答案。
NoLiMa: https://arxiv.org/abs/2502.05167
NoLiMA 的研究结果揭示了一个重要问题:那些号称能处理几十万甚至上百万词元(tokens)的 LLM,在真正需要理解长文本的任务里,性能大打折扣。比如,在 32K 词元的长度下,有 10 个受测模型,表现还不如处理短文本(小于 1K 词元)时的一半好;就连表现最好的 GPT-4o,性能也从接近完美的 99.3% 掉到了 69.7%。
受 NoLiMA 启发,我们用向量模型 jina-embeddings-v3
做了类似的实验。之所以要研究向量模型,是因为在检索增强生成(RAG)系统中,检索模型(也就是向量模型)的好坏,直接决定了整个系统的效果。
我们的研究主要关注两个核心问题:
- 向量模型能不能在长文本中进行“单跳推理”? 传统的 NIAH 测试,问题和答案通常能直接对上(比如,“约翰哪一年去的巴黎?”和“约翰 2019 年去了巴黎”)。而我们设计的“针”不一样,它需要模型进行语义推理(比如,问题是“哪个角色去过法国?”,“针”是“Yuki 住在森珀歌剧院旁边”,模型得知道森珀歌剧院在德国才行)。
- 查询扩展能不能让长文本检索更好用? 查询扩展就是给查询加些相关的词,让语义更丰富。我们想看看,这个方法能不能弥补向量模型在处理长文本时的不足。
传统 NIAH 测试(允许关键词匹配)与 NOLIMA 测试(需要语义推理)的对比图
LLM 的实验结果已经表明,它们太依赖表面的文字匹配,深层的推理能力还不够。我们想知道,向量模型是不是也这样?这可能会让我们看清,现在的语义搜索技术到底还有哪些不足。
关键信息和上下文的构建
关键信息的构建
传统的“大海捞针”测试中,关键信息(“针”)的措辞通常和要找的问题很像。例如:
- 问题:"哪个角色去过德累斯顿?"
- 关键信息:"Yuki 住在德累斯顿。"
但 NoLiMa 那篇论文不这么做,我们也不想这么做。我们想考察的是模型对语义的理解,而不是简单的关键词匹配。所以,我们设计了一种“单跳”的变体(“单跳”的意思是,答案和问题之间需要稍微推理一下才能联系起来),并且特意用了一些文本里没有出现过的词,还采用了倒装句。
- 问题:“哪个角色去过德累斯顿?”
- 关键信息(默认):“事实上,Yuki 住在森珀歌剧院旁边。”
- 关键信息(倒装):“森珀歌剧院就在 Yuki 住的地方旁边。”
按照论文的方法,我们生成了多个类别的“问题-关键信息”组(每个组包含一个问题、一个“单跳”式关键信息,还有一个把“单跳”关键信息倒过来说的版本。)
示例如下:
类别 | 问题 | 原始关键信息(仅供参考) | 单跳关键信息 | 倒装单挑关键信息 |
---|---|---|---|---|
饮食限制 | 哪个角色不能吃鱼类食物? | Alice 不能吃鱼类食物。 | 然后,Alice 提到她多年来一直是素食者。 | 多年来,素食对 Alice 来说很重要。 |
医疗状况 | 哪个角色不能喝牛奶? | Bob 不能喝牛奶。 | Bob 解释说他乳糖不耐受。 | 乳糖不耐受每天都影响着 Bob。 |
语言能力 | 哪个角色会说法语? | Charlie 会说法语。 | 事实上,Charlie 在索邦大学学习。 | Charlie 在索邦大学完成了他的学位。 |
职业背景 | 哪个角色是音乐家? | Diane 是一名音乐家。 | 2013 年,Diane 在悉尼歌剧院指挥。 | 悉尼歌剧院的演出由 Diane 指挥。 |
💡 上面的人名只是举例。在实际的“针”中,人名是从一个包含不同文化背景的名字列表中随机抽取的。
另外,表格里的“原始关键信息”(也就是字面匹配的版本)只是给大家看看,方便理解,我们的实验里并不会用到。
上下文的构建
我们准备了十本公版书,每本都至少有 5 万个词元(tokens),我们从每本书里随机抽取一些短小的片段(每个片段不超过 250 个词元),然后把这些片段拼接起来,形成不同长度的“上下文”,长度分别是 128、256、512、1024、2048、4096 和 8192 个词元。然后,我们在每一个上下文里,都放进去一个关键信息:
用书中的短片段和关键信息来构建上下文
更具体一点,比如我们把“事实上,Yuki 住在森珀歌剧院旁边”这条关键信息,放到一个长度为 128 个词元的上下文里,放在第 50 个词元的位置:
大海捞针示例
我们用 jina-embeddings-v3
模型来向量化文本,再计算“关键信息”文本和“上下文”文本的相似度得分:
Question-Haystack similarity = 0.2391
为了让这个相似度得分更有意义,我们还需要做一步“归一化”。具体做法是,先计算问题和默认关键信息(也就是没有上下文,直接比较)的相似度得分。然后,用前面的“关键信息-上下文”相似度除以这个“问题-关键信息”相似度:
Question-Needle similarity = 0.3598
Normalized Query - Haystack similarity = 0.2391 / 0.3598 = 0.6644
为什么要归一化呢?因为不同的向量模型,算出来的相似度得分可能会不一样。而且,jina-embeddings-v3
模型通常会低估两段文本之间的相似度。
对于每一个关键信息(包括默认版本和倒装版本),我们都生成了 10 个不同长度的上下文,每一个上下文里,关键信息出现的位置都不一样。对于同一个关键信息和同一个上下文长度,这 10 个上下文大概是这样的:
在十个上下文中,以固定的间隔放置关键信息
另外,为了有个对照,我们还给每一种测试条件(不同的上下文长度)生成了一个不包含任何关键信息的上下文。这样算下来,我们总共生成了 3234 个上下文。
最后,我们用jina-embeddings-v3
模型(使用默认的 text-matching LoRA)对每一个上下文进行编码。如果上下文的总词元数超过了 8192(这是 jina-embeddings-v3 模型的上限),我们就把多余的部分截断,并对对应的每个问题也进行编码。
评估指标
我们设计了一套评估框架,用几个不同的指标,来衡量向量模型在不同上下文长度下的表现:
主要指标
1. 归一化相似度分数
这是最核心的指标。它不只是简单地看问题和整个上下文之间的语义相似度,还会把问题和关键信息单独拿出来比较一下。这样,我们就能知道,模型在包含关键信息的上下文里的表现,跟它在理想情况下的表现(问题和关键信息直接比较)相比,差距有多大。
具体计算方法是:先算出问题和它对应的关键信息之间的余弦相似度得分,作为基准;然后,用“问题-上下文相似度”除以这个基准,得到归一化的相似度得分。
2. 比随机瞎猜强多少
对于向量模型,只有比较同一个问题和不同文本的相似度才有意义。所以,除了归一化相似度得分,我们还要看,这个问题跟整个上下文比起来,是不是真的比跟一段同样长度但没有关键信息的随机文本更像。换句话说,我们要看看模型找到的答案是不是真的比瞎猜要准。
次要指标
1. 区分能力分析
这个指标是看模型能不能把关键信息和其他不相关的内容区分开。具体有两个方面:
- 平均分离度:包含答案的段落(“正例”)和不包含答案的段落(“负例”)之间的差异有多大。
- AUC(曲线下面积)得分:通过计算 ROC 曲线(受试者工作特征曲线)下的面积,来衡量模型区分关键信息和其他内容的能力。
2. 位置效应
我们还会研究关键信息在上下文中的位置,会不会影响模型找到它的难易程度。我们会分析:
- 关键信息的位置和相似度得分之间有没有关系(相关系数)。
- 把关键信息放在不同位置,模型的表现会有什么变化(回归斜率)。
- 把关键信息按位置分组,看看不同组的表现有什么不同。
研究发现
相似度得分和准确率随着文本变长而下降
实验结果很明显:文本上下文越长,模型表现越差。平均相似度得分从 128 个词元时的 0.37 一路降到了 8K 词元时的 0.10。而且,这个下降过程不是一条直线,而是在 128 个词元到 1 千个词元之间降得特别快。
归一化性能与上下文长度的关系
我们还发现,把关键信息的说法倒过来(倒装),对模型找到它的影响不大。 不管是“实际上,Yuki 住在森珀歌剧院附近”(默认说法)还是“森珀歌剧院就在 Yuki 住的地方旁边”(倒装说法),模型找到它们的概率几乎一样:
两种说法(默认顺序 vs. 倒装顺序)下,模型性能的对比
不过,关键信息的内容类型,对模型查找的难度有影响。 如果是关于地点和地标的信息,模型找起来比较容易;但如果是关于饮食和健康状况的信息,模型就比较难找,而且随着文本变长,难度增加得更快:
不同类型信息(分组)的查找难度(归一化性能)和文本长度的关系
为了看看模型是不是真的比瞎猜强,我们把模型的结果和“随机猜测”做了个比较。“随机猜测”就是随便挑一段跟问题一样长、但不包含关键信息的文本。结果发现,上下文越长,模型的结果就越接近瞎猜,跟随便挑一段没用的文本差不多。
模型性能和随机概率(概率为 0.5)的对比
我们还按照关键信息的内容类型,把数据分组,再来看模型的表现。结果还是类似:有些类型的信息(比如饮食限制),即使文本不长,模型也比瞎猜强不了多少;另一些类型的信息(比如地点和地标),不管文本多长,模型都表现得不错:
不同类型信息分组,模型找到答案的概率和随机猜测的概率对比
把关键信息的说法倒过来,对模型找到它的概率基本没影响。下图展示了模型找到正确包含关键信息的文本的概率,比随机猜测的概率高多少。我们把关键信息的两种说法(默认和倒装)分开来看:
默认顺序 vs 倒装顺序,模型找到答案的概率比随机猜测高多少
从图里能看出来,两种说法下,模型性能的变化趋势都差不多。所以,后面我们就不再区分这两种情况了。
模型还能区分有用信息和无用信息吗?
我们最重要的发现之一,是关于向量模型能不能在不同长度的文本里,区分有用信息和没用信息。我们做了一个“分离度分析”,结果发现,在 128 个词元到 1000 个词元之间,模型找到正确答案的能力掉得特别快。之后虽然还在下降,但速度就慢下来了。
分离度与上下文长度的关系
短文本(128 词元)下,模型能清晰区分有用信息和无用信息,平均分离度为 0.1,AUC 达 0.81(即 100 次中有 81 次能将包含答案的段落排在前面)。
然而,随着文本变长,模型性能急剧下降。1000 词元时,分离度降至 0.04(下降 60%),AUC 降至 0.66,表明模型已难以区分。到 8000 词时,分离度几乎为零 (0.001),AUC 接近 0.5(与随机猜测相当),这意味着模型已无法根据相似度得分区分有用信息。
模型区分有用信息的能力随文本长度增加而下降的速度非常惊人。虽然原始相似度得分从 128 词到 8000 词下降了约 75%,但分离度指标却下降了近 99%,效应量更是下降了 98.6%!这表明,向量模型处理长文本的困难,不仅在于相似度得分降低,更在于区分有用信息和无用信息的能力严重退化,远超我们之前的预期。
关键信息的位置如何影响查找难度?
一般来说,把关键信息放在文本最前面,最容易找到。但也不是说放在中间就一定难找:
在不同长度的文本里,把关键信息放在不同位置,对找到它的影响
实验结果也证实,关键信息放在开头的时候,最容易被找到。而且,如果文本比较短,把它放在靠近结尾的地方,也比较容易找到。但是,不管文本长短,把它放在中间位置,都不太好找:
把关键信息放在不同位置,找到它的概率对比。
查询扩展能帮上忙吗?
我们最近发了篇博客,讲的是“查询扩展”。这是一种搜索里常用的方法,简单来说,就是在你提问的时候,给你的问题里加点相关的词,让搜索结果更准确。
自从有了向量模型,搜索的方式发生了很大的变化。那像“查询扩展”这种主要靠加词汇的方法,在 AI 时代还有用吗?我们认为还是有用的。
在那篇博客里,我们用大模型(LLM)生成了一些扩展词,然后把这些词加到查询向量里,结果发现搜索效果更好了。现在,我们想看看这招对“大海捞针”这种长文本检索任务有没有帮助。比如说,当你问:
哪个角色去过德累斯顿?
我们用大模型(Gemini 2.0)给它扩展一下,加上 100 个相关的词,大概长这样:
哪个角色去过德累斯顿? 角色:虚构角色 文学角色 主角 反派 人物 角色 身份 剧中人物
德累斯顿:德国德累斯顿;二战德累斯顿轰炸 历史小说 库尔特·冯内古特 《五号屠宰场》 萨克森州城市 易北河 文化地标
去过:访问过 去过 曾到过 出现于 出现于 特征为 设定在 发生于 地点 背景
查询扩展能起多大作用?
我们做了个实验,生成了三组扩展后的查询,每组分别加了 100 个、150 个和 250 个词(具体怎么加,可以看看这篇文章)。然后,我们把之前的实验又跑了三遍,每次用一组不同的扩展查询。
结果发现,不管加多少词,只要文本一长,模型表现就拉胯,跟不使用查询扩展的时候差不多:
各种查询拓展情况下,模型性能的综合表现
跟没扩展的问题比,所有加了词的情况,都还是老样子:文本越长,性能越差。 而且,这个下降过程还是不均匀的,在 128 个词到 1K 个词之间降得最厉害:
各种查询拓展情况下,模型找到正确答案的概率。
但是!仔细看看“比较比率”这个指标,就会发现查询扩展还是有用的:它能让模型更容易找到包含关键信息的文本。 如果不做查询扩展,模型在 8K 词元长度下的表现就跟随机猜测差不多了。
如何解释查询扩展的结果?
上面这些结果,跟 NoLiMa 论文,还有我们之前“查询扩展”研究的发现,都是一致的。可以这样解释:
- 适度加词效果最好:加 100 个词比加 150 个、250 个词效果好,说明查询拓展时,加词得有个度,加太多反而会带来语义噪声而不是信号,干扰模型的判断。加 250 个词的时候,很可能加进去一些跟问题相关性较弱的术语,在长文本里这些词就帮倒忙了。
- 长文本依然是核心挑战:即使进行了查询扩展,上下文一长,模型性能还是会显著下降。目前基于注意力的模型架构在处理长文本时存在根本性的瓶颈,这个问题不是简单地增加几个词就能解决的。
- 查询拓展仍有价值:虽然无法完全克服长文本带来的挑战,但“比较比率”指标始终高于 0.5,这说明着查询扩展还是有效果的。就算是 8 千词元的长文本,经过查询扩展后的问题也比随机猜测要更容易找到正确答案。这给了我们一个启发:查询扩展仍然是提升向量模型长文本处理能力的一个有潜力的方向,值得进一步探索。
字面匹配对向量模型的影响?
在之前的实验中,为了衡量向量模型在长文本中进行“单跳推理”的能力,我们特意避免让问题和关键信息之间有任何字面上的重复。结果表明:即使做了查询扩展,模型在长文本中找到相关信息的能力还是会变差。这个现象很有意思。按理说,向量模型应该有能力自己完成这种推理,不需要额外帮忙。毕竟,我们只是把“德累斯顿”换成了“森珀歌剧院”,本质上就是用一个意思相近的词替换了另一个词。
那么,字面匹配在语义匹配中到底有多重要?还是说文本长度的影响更大?为了找到答案,我们重新设计了实验,让关键信息和问题之间存在字面上的重复,比如:
- 问题:“哪个角色去过德累斯顿?”
- 关键信息(默认):“实际上,Yuki 住在德累斯顿。”
- 关键信息(倒装):“德累斯顿是 Yuki 住的地方。”
注意,这里我们直接给出了“Yuki 住在德累斯顿”这个信息,而不是像之前那样,需要读者自己推理出“森珀歌剧院在德累斯顿,所以住在附近的人去过德累斯顿”。
我们把所有 22 组问题和关键信息都改成了这种直接的形式,然后用同样的向量模型 jina-embeddings-v3
重新跑了一遍实验,各种文本长度和关键信息的位置都试了。
归一化性能与上下文长度的关系
模型性能与随机猜测 (0.5) 的比较
不同位置的比较比率
结果出乎意料。即使问题和答案里有相同的词,只要文本一长,模型区分正确答案和随机猜测的能力还是会迅速下降。当然,比起完全没有相同词的情况,还是要稍微好一点。
这最终证明了,比起关键信息的具体措辞(语义表述),上下文的长度,以及关键信息在其中的位置,对向量模型在“大海捞针”任务中的表现影响更大。
结论
总的来说,我们用向量模型做的实验,结论跟 NoLiMA 用大型语言模型做的实验一致:文本越长,模型就越难找到正确答案。我们的实验还证明,就算问题和答案里的关键词一模一样,模型也不一定能找对。
我们的实验结果与 NoLiMA 论文对 LLM 的发现高度一致:对于向量模型,上下文长度是影响检索性能的关键因素,文本越长,模型就越难找到正确答案。就算问题和答案里的关键词一模一样,模型也不一定能找对。
- 性能随长度锐减:jina-embeddings-v3 在短文本(128 词元)下表现出色,但在长文本下性能迅速下降。归一化相似度得分从 128 词元时的 0.37 降至 8K 词时的 0.10。更重要的是,模型区分相关信息和无关信息的能力(我们称之为“分离度”)几乎完全消失了。
- “单跳推理”很困难:即使在短文本下,如果问题和答案之间没有直接的字面重叠,模型的表现也会明显变差。这说明,向量模型在进行“单跳推理”(例如,从“住在森珀歌剧院旁边”推断出“去过德累斯顿”)时存在困难。
- 查询扩展有帮助,但不是万能的:查询扩展可以在一定程度上提高检索性能,特别是在长文本下,使模型表现优于随机猜测。但是,它并不能完全解决长文本带来的问题,性能还是会随着文本变长而下降。而且,加词也得小心,不相关的词反而会引入语义噪声,降低性能。
- 字面匹配不是关键:就算问题和答案里有一样的关键词,只要文本一长,模型还是找不到。这说明,比起答案怎么说,文本有多长,答案在文本里的位置,对模型能不能找到答案的影响更大。
总的来说,我们的研究表明,像 jina-embeddings-v3
这样的向量模型,处理短文本很有一套,但要处理那些需要深入理解语义的长文本,还是力不从心。这促使我们继续探索更有效的长文本检索技术,希望在未来的 jina-embeddings-v4
中有所突破。