用子模优化做文本选择、段落重排和上下文工程

搜索
AI-TNT
正文
资源拓展
用子模优化做文本选择、段落重排和上下文工程
2025-07-15 11:05

用子模优化做文本选择、段落重排和上下文工程


在上一篇关于子模优化与多样化查询的文章发表后,我们收到了来自圈内很多积极的反馈,希望我们能多聊聊子模性(submodularity)和子模优化,尤其是在信息检索和 Agentic Search 场景下的更多应用。


应大家的要求,今天我们就来讲子模系列的第二篇,聊聊子模优化的另外两大应用:文本选择(text selection)与段落重排(passage reranking)


这两个任务听起来一个是做减法,一个是排序,但内核都是在解决一个经典优化难题:如何从一堆庞杂的信息集合中,挑出一个不冗余的最优子集。这可以说是所有 DeepResearch系统或智能体在进化路上都绕不开的核心挑战。


我们子模优化系列文章中的所有代码实现都已开源,欢迎查阅、使用与共建。 GitHub: https://github.com/jina-ai/submodular-optimization


如同我们的世界一样,在文档世界中,句子们生而不等,句子之间必然存在信息冗余。对智能体和大模型来说,有些句子就是比其它句子更重要。如何在大模型严格的 token 限制下,从长篇文档中提取出最具代表性的信息?这就是文本选择任务。


文本选择任务的核心目标:一是最小化所选内容之间的信息重叠;二是最大化所选内容对原文整体信息的覆盖范围。 当一个集合中的元素信息重叠最小时,我们称它们在语义上是“正交”的。


所以,文本选择任务本质上是一种上下文优化与压缩技术,目标是在保证信息完整性的前提下,尽可能地减少输入给模型的 token 数量。


用子模优化做文本选择、段落重排和上下文工程


段落重排 则扩展了文本选择任务。它不仅要考虑段落之间的信息多样性,还必须引入一个优化目标:尽可能的贴近用户的查询。在 Jina AI,我们为此打造了如 jina-reranker-m0 等一系列高级重排器,当然你也可以用我们的向量模型来排序。


但包括我们自家模型在内,绝大多数重排器都采用一种“单点打分 (pointwise)” 的工作模式。这种模式的根本缺陷在于:它孤立地计算每一个 (查询,段落) 对的相关性,在计算某个段落时,完全不考虑其他段落的内容。经典信息检索中的“列表打分 (listwise)” 模型往往也做不到去除冗余信息,只是机械的对列表进行排序。


这就引出了一个灵魂拷问:如果段落1和段落3和用户查询的相似度都很高,但他们说的都是同一件事,那我们只选一个段落放到大模型的上下文中不就完了么?


用子模优化做文本选择、段落重排和上下文工程


在 DeepResearch和智能体系统里,解决这个问题变得尤为重要。当 Agent 从网络收集了大量信息片段后,系统必须做出选择:哪些片段最值得占用 LLM 有限的上下文窗口?


这里的挑选标准,是文本筛选与段落重排的结合体:它既要遵循 最小化重叠、最大化覆盖 的原则,又必须将 与原始查询的相关性 作为最高优先级。


所以上下文工程 (Context Engineering) 最近一下火起来确实有其道理。用 Andrej Karpathy 的话说,我们需要学会如何“高效地打包上下文窗口”。很多人虽然知道这个的问题重要性,但还是依赖提示词(Prompt)让模型自行筛选上下文、去重和排序。这类方法缺乏稳定的性能保证和可预测性,称不上是严谨靠谱的解决方案,只能算是抖机灵。


事实上,我们完全可以做得更好。


至此,子模优化(Submodular Optimization) 登场,为我们破解上述难题提供了严谨的理论框架。如果你不熟悉它,没关系,它的精髓可以用一个生活中的常见现象来概括:边际效益递减(diminishing marginal returns)。


想象你在筹备一次野餐。往背包里装第一个汉堡,幸福感提升 10 分;再带一个不同口味的,幸福感又提升了 7 分。但当你包里已经塞了五个汉堡后,再多塞一个,幸福感可能只增加了 1 分。这种新增成员带来的价值越来越少的趋势,就是子模性。


这种价值增量随集合增大而递减的特性,天然地鼓励算法去构建一个多样化、不冗余的集合。因为当集合内元素越多样,新加入的元素才越有可能提供更高的价值。


用子模优化做文本选择、段落重排和上下文工程


这个公式其实在说一件很简单的事:将新元素 添加到小集合 中所获得的价值增量,要大于或等于将其添加到大集合 中所获得的价值增量。


这正是我们追求的目标:确保所选元素的组合能够高效地覆盖整个文档的语义空间,并随着选择数量的增加,新元素的价值贡献能够被精确地量化与控制。


为了让大家更直观地感受这套方法的效果,我们先来看一个交互式演示。


用子模优化做文本选择、段落重排和上下文工程


首先,我们借助 jina-embeddings-v4 的多向量(multi-vector)特性,将文本映射为 token 级的独立语义向量。


接着,应用子模优化算法,从全局角度筛选出最具代表性的词句,确保以最少的 Tokens 覆盖尽可能多的原文信息。


最后,借助 Tokenizer 将这些选定的 Tokens 还原至原文对应位置,实现高效压缩。你可以调整 top-k 控制压缩率,兼顾信息保留和处理效率。


我们在 Google Colab 上发布了完整实现:https://colab.research.google.com/drive/1J4kLSGTkcR59jM5Xc2EbIkJtoQ0CdbPE#scrollTo=UK1lLkhk5XeK


通过子模优化进行文本选择


看完了演示,我们来深入其背后的数学原理。先从文本选择问题开始,这是理解子模性应用的基础,也是后续段落重排任务的前置步骤。


该问题的目标可以被精确地定义如下:


用子模优化做文本选择、段落重排和上下文工程


这里的 指代元素 和 向量间的余弦相似度。这个覆盖函数 的子模性体现在它完美体现了边际效益递减。


函数中的 max 运算是实现这一特性的关键,它计算文档中的每一个元素 和已选子集 中最相似的那个成员 的相似值。这就意味着一个元素 对总分的贡献,完全由集合中和它最相关的那个句子决定。这种机制从根本上促进了摘要的多样性,而抑制了冗余。


如何获取词元/段落级别的向量


要实现上述优化目标,一个关键的先决条件是获取高质量、细粒度的向量。我们为此提供了明确的技术路径:


对于词元(Token)级别的选择,我们直接利用 jina-embeddings-v4多向量 能力。只需在 API 调用时设置 return_multivector=True,模型便会为每个词元返回一个独立的向量,让我们得以在子词(subword)的精细粒度上进行操作。


对于段落级别的选择,最简单的方法是按标点或换行符将文档切分,再独立地为每个片段生成向量。如果想追求更卓越的性能,推荐调用我们 API 提供的 迟分(Late Chunking) 功能,它能生成保留了上下文信息的段落向量,在下游任务中已证明具有更优异的表现。


有关迟分内容推荐阅读:


Michael,公众号:Jina AI长文本 Embedding 模型中的“迟分”策略


这里要强调一个重要的技术细节。当前任务的目标是衡量同类型元素之间的语义相似度(例如,句子与句子之间),这属于匹配(text-matching)场景。它不同于衡量不同类型元素(例如,查询与文档)相关性的 检索(retrieval) 场景。


为获得最精准的相似度度量,正确的做法是在调用 jina-embeddings-v4 时,启用专门为此优化的 text-matching LoRA 适配器。


jina-embeddings-v3 以来,为不同任务配备专用的 LoRA 适配器已成为我们向量模型的一大特色。欢迎阅读我们 v4 模型的相关文章,了解更多可用的 LoRA 选项。


Jina AI,公众号:Jina AIJina Embeddings V4: 为搜索而生,多模态多语言向量模型


懒贪心算法


面对这类确定的优化问题,我们的首选算法依然是上一篇文章中详细介绍过的懒贪心算法 (Lazy Greedy Algorithm)


在处理单调子模函数的优化问题时,懒贪心算法不仅计算效率高,还提供了一个理论保证:它找到的解,在质量上至少能达到最优解的 ,这已是理论上能达到的最优近似比。


懒贪心算法的高效,源于它利用了子模函数的两个固有特性:一是边际效益递减,二是边际增益的相对排序在迭代过程中变化不大。其工作流程如下:


  1. 初始化:计算所有元素的初始边际增益,并存入一个优先队列进行排序,
  2. 惰性评估:每轮迭代时,仅从队列顶部取出那个拥有最高缓存增益的元素。
  3. 有效性验证:接着,算法会验证这个缓存的增益值是否是在当前轮次计算的。如果是,证明其增益是新鲜的,该元素被直接选入解集。
  4. 重新计算:如果缓存的增益值已经过时,算法才会重新计算该元素的真实边际增益,并将其放回优先队列的正确位置。


通过这种“非必要,不计算”的策略,懒贪心算法避免了大量冗余计算,在各元素边际增益差距较大时,其加速效果尤其明显。


通过子模优化进行段落重排


现在,我们把问题提升一个难度。段落重排可以被视为文本选择的一个约束性更强的版本。它在保证信息多样性的基础上,增加了一个新的要求:最终选出的段落子集,必须与给定的用户查询高度相关。


动手实践:https://colab.research.google.com/drive/1gMc1Bf9Lk6HqXSoA6PyMblOb943-Pgjt?usp=sharing


在构建模型前,我们先定义一些符号表示:


用子模优化做文本选择、段落重排和上下文工程


有了这些符号表示,我们就可以设计不同的子模目标函数,以实现不同的权衡策略。


模型一:选址模型 (Facility Location Model)


此建模的内在逻辑是识别并优先选择那些既与查询高度相关,又能有效覆盖其他多个段落的段落。


用子模优化做文本选择、段落重排和上下文工程


其核心是乘法运算。一个已选段落 与查询的相关性 越高,它在覆盖其他相似段落 时(由 体现)的权重就越大。这使得同时满足高相关性和广覆盖度的段落得分更高。


模型二:饱和覆盖模型 (Saturated Coverage Model)


这个建模采用了一种更严格的策略。它设定了一个硬性限制,或者说一个相关性天花板:任何一个段落对整体集合的贡献值,都不能超过其自身与查询的相关度。


用子模优化做文本选择、段落重排和上下文工程


其核心是 min 运算。它确保了即使一个段落 能覆盖很多其他段落(即 的值很高),它对总分的贡献也绝不会超过它自身与查询的相关度 。这种设计能有效防止算法为了追求多样性而选择与查询不相关的段落。


这两种函数都具备单调性和子模性的要求,因此,我们可以放心地使用高效的懒贪心算法,并享有其背后坚实的 近似解性能保证。


实验结果


我们来看下结果。我们先使用 Jina Reader 抓取过往文章的纯文本内容,在此基础上评估不同查询下的段落重排效果。我们强烈建议读者在 Google Colab 中,使用自己熟悉的文档进行实验,只有通过上手操作,才能最深刻地理解算法的内部运作机制。


本次实验的目标统一设定为:从每篇文档中筛选出 Top-10 的段落。


在这里,一个关键的共性浮现出来:我们对比的三种算法:纯相关性排序、选址模型与饱和覆盖模型。


注意这三种算法的结果都是单调 (monotonicity)的,即当目标数量从 增加到 时,前 个已选出的元素及其顺序是不会改变的。例如,k=10 的结果,其前 9 个段落与 k=9 的结果完全相同。


下图展示了部分实验结果:


用子模优化做文本选择、段落重排和上下文工程


用子模优化做文本选择、段落重排和上下文工程


用子模优化做文本选择、段落重排和上下文工程


用子模优化做文本选择、段落重排和上下文工程


从实验结果,我们可以得到两个关键观察:


观察一:策略性重排(Strategic Reranking)


子模优化算法在很大程度上参考了原始的相关性分数,但更重要的是,它执行了重排。一些在原始排名中靠后的段落,因为能提供新信息,其排名被提升;而另一些原始排名靠前但内容冗余的段落,其排名被主动降低。


这种行为符合我们的设计目标,说明算法正在积极地识别并惩罚信息的冗余,而不是盲目地遵从原始的相关性分数。它最终产出的排序结果,信息质量极高。


观察二:边际效益递减


但如果你仔细看,会发现一个“bug”:在第一第二和第四个例子里,算法在选了几个段落后,后续的段落就是从0,1,2,3开始顺序填充了。


这是算法出bug了?恰恰相反,这正是子模优化最宝贵、最智能的特性。一个任何现有重排器都无法提供的特性。


为了彻底理解这种边际效益递减行为,我们直接绘制了子模目标函数值随着所选段落数量 增加的变化曲线。这张图,让我们得以直接看到边际效益递减的全过程。


用子模优化做文本选择、段落重排和上下文工程

文档源: 子模优化生成多样化查询生成文章,查询: "what is diminishing return"。红虚线标记了实际的饱和点,超过此点后,边际增益已趋近于零。


用子模优化做文本选择、段落重排和上下文工程

文档源: Jina Embeddings v4文章,查询: "how many lora adapters v4 has"。红虚线同样标记了饱和点。


上方的曲线清晰地展示了选址和饱和覆盖这两个函数在k增加时的行为。两者都呈现出典型的子模特征:


  • 初期急速增长:最陡峭的价值提升发生在最初的几次选择中。
  • 中期效益递减:每增加一个新段落,带来的边际效益都比前一个更少。
  • 后期饱和停滞:函数值曲线趋于平坦,表明继续增加新成员已几乎带不来任何好处。


这种边际效益递减现象,是子模函数与生俱来的特征。


用子模优化做文本选择、段落重排和上下文工程


算法通过这种方式明确地告知我们:文档中与查询相关的、有价值的信息已经充分提取了,多说无益,不需要再加入新的信息了。


结论


上下文工程(Context Engineering) 突然流行开来,取代了提示词工程 (Prompt Engineering)成为一个重要的技术发展方向。其核心目标是精确筛选信息,以填充大语言模型上下文窗口。而这一过程的起点通常是从检索、采集外部资料开始。


在上下文工程的中,文本选择与段落重排是重要的组件。它们贯穿于知识库筛选、信息检索与上下文压缩等多个环节。它们协同工作,确保 LLM 能在一个合理的 Token 预算内,接收到最大化提纯的、最不冗余的核心信息,从而避免信息过载,提升输出质量。


与当前流行的启发式或基于提示词的解法相比,子模优化是一套逻辑自洽、优势显著的数学框架。


1.有理论保证


用子模优化做文本选择、段落重排和上下文工程


2. 自动停止机制


我们实验中看到的边际效益递减,为系统提供了一个天然的、可用于判断何时停止的参考依据。目标函数值的增益趋近于零时,就是在指导我们应该见好就收,继续添加新内容已无价值。这是现有的单点打分式 (pointwise)或列表打分式 (listwise)的重排器都无法提供的上帝视角。


3. 多查询扩展


在 DeepResearch和智能体工作流中,查询的生成、扩展和拆解是家常饭。子模优化框架能够自然地、无缝地扩展至这种多查询的场景,找到最相关的段落。其底层的理论基础和懒贪心算法可以无缝复用。相对于那些依赖提示词的方案而言,子模优化的优势不言自明。


种种优势源自于子模优化的数学根基,而非奇技淫巧。当许多人在靠经验和运气调试提示词时,你确实该系统性的学习子模优化,不仅把它作为一个有理论保证的数学框架,更可把它作为真正可靠、可解释、可扩展的上下文工程


文章来自于“Jina Al”,作者“Jina Al”。

1
AI代理

【开源免费】Browser-use 是一个用户AI代理直接可以控制浏览器的工具。它能够让AI 自动执行浏览器中的各种任务,如比较价格、添加购物车、回复各种社交媒体等。

项目地址:https://github.com/browser-use/browser-use


2
AI工作流

【开源免费】n8n是一个可以自定义工作流的AI项目,它提供了200个工作节点来帮助用户实现工作流的编排。

项目地址:https://github.com/n8n-io/n8n

在线使用:https://n8n.io/(付费)


【开源免费】DB-GPT是一个AI原生数据应用开发框架,它提供开发多模型管理(SMMF)、Text2SQL效果优化、RAG框架以及优化、Multi-Agents框架协作、AWEL(智能体工作流编排)等多种技术能力,让围绕数据库构建大模型应用更简单、更方便。

项目地址:https://github.com/eosphoros-ai/DB-GPT?tab=readme-ov-file



【开源免费】VectorVein是一个不需要任何编程基础,任何人都能用的AI工作流编辑工具。你可以将复杂的工作分解成多个步骤,并通过VectorVein固定并让AI依次完成。VectorVein是字节coze的平替产品。

项目地址:https://github.com/AndersonBY/vector-vein?tab=readme-ov-file

在线使用:https://vectorvein.ai/(付费)

3
智能体

【开源免费】AutoGPT是一个允许用户创建和运行智能体的(AI Agents)项目。用户创建的智能体能够自动执行各种任务,从而让AI有步骤的去解决实际问题。

项目地址:https://github.com/Significant-Gravitas/AutoGPT


【开源免费】MetaGPT是一个“软件开发公司”的智能体项目,只需要输入一句话的老板需求,MetaGPT即可输出用户故事 / 竞品分析 / 需求 / 数据结构 / APIs / 文件等软件开发的相关内容。MetaGPT内置了各种AI角色,包括产品经理 / 架构师 / 项目经理 / 工程师,MetaGPT提供了一个精心调配的软件公司研发全过程的SOP。

项目地址:https://github.com/geekan/MetaGPT/blob/main/docs/README_CN.md

4
知识库

【开源免费】FASTGPT是基于LLM的知识库开源项目,提供开箱即用的数据处理、模型调用等能力。整体功能和“Dify”“RAGFlow”项目类似。很多接入微信,飞书的AI项目都基于该项目二次开发。

项目地址:https://github.com/labring/FastGPT

5
RAG

【开源免费】graphrag是微软推出的RAG项目,与传统的通过 RAG 方法使用向量相似性作为搜索技术不同,GraphRAG是使用知识图谱在推理复杂信息时大幅提高问答性能。

项目地址:https://github.com/microsoft/graphrag

【开源免费】Dify是最早一批实现RAG,Agent,模型管理等一站式AI开发的工具平台,并且项目方一直持续维护。其中在任务编排方面相对领先对手,可以帮助研发实现像字节扣子那样的功能。

项目地址:https://github.com/langgenius/dify


【开源免费】RAGFlow是和Dify类似的开源项目,该项目在大文件解析方面做的更出色,拓展编排方面相对弱一些。

项目地址:https://github.com/infiniflow/ragflow/tree/main


【开源免费】phidata是一个可以实现将数据转化成向量存储,并通过AI实现RAG功能的项目

项目地址:https://github.com/phidatahq/phidata


【开源免费】TaskingAI 是一个提供RAG,Agent,大模型管理等AI项目开发的工具平台,比LangChain更强大的中间件AI平台工具。

项目地址:https://github.com/TaskingAI/TaskingAI

6
prompt

【开源免费】LangGPT 是一个通过结构化和模板化的方法,编写高质量的AI提示词的开源项目。它可以让任何非专业的用户轻松创建高水平的提示词,进而高质量的帮助用户通过AI解决问题。

项目地址:https://github.com/langgptai/LangGPT/blob/main/README_zh.md

在线使用:https://kimi.moonshot.cn/kimiplus/conpg00t7lagbbsfqkq0

添加客服微信openai178,进AITNT官方交流群
IOS下载
安卓下载
微信群
沪ICP备2023015588号