
RAG 做得久了会发现一个挺尴尬的事实决定最终回答质量的往往不是你 prompt 写得多花哨而是检索回来的那几段文本到底对不对。召回阶段为了速度几乎必然要把精准让给覆盖Top-K 里混进三五个不相关的段落是常态。而把这些噪声挑出去、把真正能回答问题的内容顶到最前面就是re-rank检索后重排要干的活。UPR 这类工作提出了一件很有意思的事不用标注数据、不用训练 cross-encoder直接让LLM读 query 和候选文档靠 prompt 把顺序重新排一遍。这篇就围绕这个思路往下拆——它到底怎么工作的、prompt 该怎么写、滑窗排序怎么实现、参数怎么定、踩过哪些坑以及在你自己的 RAG 链路里怎么把它接进去。适合已经跑通过基础 RAG、正被召回不精准折磨的中高级读者也适合刚接触重排、想搞清楚 listwise 和 pairwise 差在哪的同学。1. 先把问题摆清楚UPR 到底在补哪块短板1.1 召回阶段为什么天生就不准很多人第一次搭 RAG 时会有一个错觉只要向量库建得好、embedding 模型选得新检索结果就该是准的。实际跑起来才知道Top-10 里能用的往往只有三到五条剩下的要么是同主题但不回答问题要么是关键词撞上了但语义完全跑偏。根子在于召回阶段的架构约束。向量检索是典型的双塔结构query 单独编码成一个向量文档单独编码成一个向量最后靠余弦相似度比一下。这个设计的关键特征是query 和文档在编码阶段完全没有见过对方两者的交互被压缩成了一次向量内积。信息损失是结构性的不是换个更大的 embedding 模型就能解决的。传统 BM25 的问题更直白它只看词频和逆文档频率同义词、指代、隐含意图统统无能为力。用户问这个接口超时了怎么办文档里写的是请求响应延迟过高的排查路径字面上一个词都不重合BM25 直接判零分。再加上工程上还要叠一层近似最近邻检索HNSW、IVF 之类为了毫秒级响应牺牲一部分精度文本分块chunking又会把一段完整语义从中间切断。这几层损耗叠在一起召回阶段天然就是高召回、低精度的定位——宁可多捞点也别漏掉。多捞的这部分噪声就是重排阶段存在的全部理由。1.2 重排干的是精读不是粗筛如果打个比方召回像是图书馆管理员按书名关键词给你抱来二十本书重排则是你坐下来一本本翻目录判断哪三本真的能解决你的问题。前者要快、要广后者要慢、要准两者的评价标准根本不同。从技术路径上讲重排是从表示型匹配切换到交互型判断。召回阶段 query 和文档各算各的向量重排阶段则把 query 和文档放在同一个上下文里一起读让模型判断这段内容能不能支撑回答这个问题。这也是 cross-encoder 一直比双塔效果好的原因——它允许 query 的每一个词去和文档的每一个词做注意力交互。问题在于cross-encoder 需要标注数据训练。你得有一批 (query, 正例文档, 负例文档) 的三元组得跑训练流程得维护模型版本。对于中小团队或者长尾业务场景这份标注成本经常高到不划算。UPR 这类思路的价值就在这里它把 LLM 当成一个零样本的 cross-encoder 来用。模型在预训练阶段已经见过海量的问题—答案共现对什么内容能回答什么问题这件事有相当强的先验判断力。你只要把判断标准用 prompt 说清楚它就能直接给出相关性排序整个过程不需要一次梯度更新。1.3 四条技术路线的取舍对照把可选方案摊开对比选择就清晰了。下面这张表是我自己在选型时整理的延迟数据基于百条量级的候选集、单卡或单次 API 调用的粗略量级具体数值会随硬件和模型规模浮动但相对关系是稳的。方案是否需要训练相对效果单次延迟量级主要短板BM25 直接排序否基准毫秒无语义同义改写全丢双塔向量召回否预训练比 BM25 好毫秒query/doc 无交互训练式 Cross-Encoder是通常最好十毫秒到百毫秒标注成本高领域迁移难LLM 无监督重排否接近甚至超过中小 cross-encoder百毫秒到秒级贵、慢、输出不稳定看这张表就能明白LLM 重排不是要取代谁它填的是一个特定的空档你有语义判断的需求但没有标注数据或者标注数据的性价比不划算。典型场景包括冷启动的新业务、多语言混杂的知识库、更新极快的文档集——这些场景下训练一个 cross-encoder 的投入产出比很难看而 prompt 调一调就能上试错成本低得多。代价也很实在延迟从毫秒级跳到百毫秒甚至秒级成本按 token 计费上去输出格式还可能不听话。所以后面几章的重点全在怎么把这个代价控制住。2. UPR 的核心设计无监督 prompt 怎么把顺序排出来2.1 Pointwise、Pairwise、Listwise 三条路LLM 重排的实现方式按一次喂多少东西给模型可以分成三类这三类的差异远比想象中大。Pointwise是最直觉的做法query 加上一条文档让模型打一个相关性分数0 到 10或者相关/不相关二分类然后按分数排序。优点是实现简单、每条文档独立处理、可以并行、天然支持增量。缺点也很明显——分数之间不可比。同一批文档模型给 A 打 7 分给 B 打 6 分并不意味着 A 比 B 更相关可能只是这两次调用时模型的打分尺度飘了。实践中经常出现一堆文档全是 7 分或者全是 8 分的情况区分度极差。Pairwise是让模型比较两条文档针对这个问题A 和 B 哪个更相关输出 A 或 B。它的判断更稳定因为比较是相对的不需要模型建立一个绝对尺度。但代价是复杂度 O(n²)——20 条文档要比较 190 次100 条要比较 4950 次成本直接失控。工程上一般配合锦标赛排序或者快速排序式的分治来降低比较次数但仍然比 pointwise 贵一个数量级。Listwise折中得最好一次把一批文档比如 10 到 20 条连同 query 一起塞进去让模型直接输出重排后的顺序。它充分利用了模型在一次上下文内的相对比较能力调用次数是 O(n/w)w 是窗口大小。这也是目前这类工作里主流的选择。范式调用复杂度分数可比性输出稳定性适合场景PointwiseO(n)差中候选极多、需要并行、做粗筛PairwiseO(n²)好高候选少20、要求高精度ListwiseO(n/w)好中受位置偏差影响主流选择10 到 100 条候选顺带说一句这三者并不互斥。比较务实的组合是先用 pointwise 或向量相似度把 200 条砍到 30 条再用 listwise 精排到最后 5 条。分层过滤每一层用最合适的工具。2.2 无监督这三个字到底指什么看到无监督很容易误解成完全不用管数据。准确的说法是不做参数更新不依赖人工标注的相关性标签。模型用的是现成的通用大模型可能经过指令微调但没有在你的业务数据上继续训练。整个学习过程完全发生在 prompt 内部——你通过指令描述、few-shot 示例、输出格式约束把什么样的内容算相关这个标准传达给模型。判断力来自预训练阶段积累的语言知识和世界知识不是来自你的标注集。这个定义的边界要说清楚。实际落地时你仍然需要一小批带标注的评测集来做两件事一是验证这套方案在你的领域到底有没有效果有些垂直领域的相关性标准非常特殊通用模型判断不了二是在多个 prompt 模板之间做选择。这批标注不用来训练只用来评估量级大概几百条 query 就够成本完全可以接受。还有一个隐含前提模型判断的相关性标准得和你的业务标准基本对齐。举个反例做法律条文检索时相关可能指的是同一法条体系下的适用条款而通用模型理解的相关更偏向话题相同。这种偏差靠 prompt 描述能缓解一部分但缓解不了根本性的口径差异。这种情况下老老实实标数据训 cross-encoder 更靠谱。2.3 prompt 模板的四种写法与实测差异模板设计是整个方案里最手艺活的部分直接影响效果上限。我试过四类写法差异相当明显。第一种二分类问答题。直接问以下文档能否回答该问题只回答是或否。优点是输出极短、解析简单、token 省。缺点是信息量只有一位当候选集里有一半文档都是是的时候完全无法区分。第二种分级打分。给 0 到 10 分并简单描述每个分档的含义比如 8 到 10 表示直接包含答案4 到 7 表示部分相关0 到 3 表示无关。比二分类细腻但仍然有前面说的尺度漂移问题。缓解办法是把评分标准写得非常具体用可观察的特征来描述每一档而不是用非常相关比较相关这种模糊词。第三种直接排序。把候选文档编号后一起给模型要求按相关性从高到低输出编号列表。这就是 listwise 的典型形态效果好、调用少。关键约束是只让模型输出编号绝不让它复述原文——一旦让它输出内容它就可能改写、压缩甚至编造而编号到原文的映射关系一旦断了整个排序结果就没法用。第四种带解释的思维链。让模型先说明每条文档为什么相关或不相关再给排序。效果通常最好因为显式推理过程能抑制模型的随意性。代价是输出 token 翻好几倍延迟和成本都上去了。我的建议是调模板阶段用这种方式做诊断看清楚模型到底在关注什么稳定后就换成纯编号输出节省成本。你是一个检索结果重排器。下面有一个用户问题和 {n} 条候选文档 每条文档都有编号。请判断每条文档对回答该问题的帮助程度 并按帮助程度从高到低输出文档编号。 要求 1. 只输出编号用英文逗号分隔例如3,1,4,2 2. 必须输出全部 {n} 个编号不许遗漏、不许重复 3. 不要输出任何解释、不要复述文档内容 4. 若多条文档帮助程度相同保持它们原本的先后顺序 用户问题 {query} 候选文档 {documents}这段模板有三个细节值得单独拎出来说。第一明确要求输出全部编号、不许遗漏因为模型在窗口内文档较多时非常容易漏掉一两条——漏掉的文档你没法确定它是被判为最不相关还是模型单纯忘了。第二明确相同相关度保持原顺序这一句能显著降低输出的抖动。第三不要复述文档内容这句必须写上否则模型有相当概率自作聪明地总结一番。2.4 零样本能 work 的底层逻辑与它的边界为什么一个没在排序任务上训练过的模型光靠 prompt 就能把顺序排个八九不离十根本原因在于预训练语料的统计规律。互联网文本中充满了问题—解答的自然共现结构论坛的提问与回复、百科的条目与定义、文档的章节标题与正文。模型在这个分布上训练了几千亿 token实际上已经隐式学到了什么样的文本片段能够回答什么样的问题这个映射。相关性判断对它来说不是新任务只是已有能力的一次调用。指令微调进一步强化了这一点。经过指令对齐的模型更擅长理解请判断相关性这类元任务描述也更愿意遵守输出格式约束。但这条逻辑有它的边界而且边界挺硬。模型判断的是语义上的回答可能性不是事实上的正确性也不是业务上的适用性。它看到一段话在语言层面很像在回答这个问题就会给高分哪怕这段内容其实是过时的、错误的、或者来自一个不该被引用的来源。所以在需要强时效、强权威性的场景里LLM 重排只能作为一环还得配上时间过滤、来源权重这些规则。另一个边界是长度。模型对长文档的判断力明显弱于短文档超过一定长度后中间部分的信息会被稀释。这一点直接决定了后面要讲的截断策略。3. 落地实现从最小可跑通版本开始3.1 整条链路的骨架先给一个完整的处理流程从召回结果进来到最终 Top-K 出去召回阶段拿到 N 条候选建议 N 在 30 到 100 之间太少没有重排空间太多成本扛不住每条文档做长度截断控制单条 token 数按窗口大小 w 切分成若干组相邻组之间保留重叠每组构造 listwise prompt调用模型拿到组内重排结果用滑动窗口的方式把各组的局部排序合并成一个全局排序取最终 Top-K交给下游的生成环节这里最容易被忽略的是第 2 步和第 3 步的顺序关系。必须先截断再分窗不能反过来。先分窗再截断会导致某些窗口里全是超长文档的头几百字另一些窗口里全是尾部的几百字判断质量的方差会非常大。关于截断长度我的经验值是单条文档控制在 150 到 250 个 token 之间中文大概 100 到 200 字。这个数字的来源是权衡一方面回答一个具体问题通常不需要读完整篇文档开头的摘要段和结论段信息密度最高另一方面窗口内要放 10 到 20 条文档单条太长会让总上下文迅速逼近模型上限而且长上下文本身会稀释注意力。3.2 滑窗排序的具体实现与参数计算滑窗排序的核心思想是一次只能比较 w 条那就让这些窗口互相重叠逐步把整体顺序磨出来。def sliding_window_rerank(query, docs, window20, step10, llm_callNone): docs: 已按初始顺序排好的文档列表初始顺序通常是向量相似度 window: 每个窗口内的文档数 step: 窗口滑动步长通常取 window // 2 n len(docs) if n window: return llm_call(query, docs) # 一次性排完 # 关键从列表尾部向头部推进 start n - window order list(range(n)) # 当前全局顺序存的是原始下标 while True: end start window window_items [docs[i] for i in order[start:end]] ranked llm_call(query, window_items) # 返回重排后的下标列表 order[start:end] ranked if start 0: break start max(0, start - step) return [docs[i] for i in order]为什么从后往前推因为滑动窗口的合并逻辑是后一个窗口的结果会作为前一个窗口的输入。列表越靠前的位置越重要最终只取 Top-5 或 Top-10让最重要的位置在最后一次窗口处理中被决定此时模型已经吸收了后面所有文档的信息判断依据最充分。如果从前往后排头部顺序在第一次就被定死了后续窗口再怎么调整也影响不到它。参数该怎么算举一个具体例子召回 100 条窗口 20步长 10。第一次处理下标 80 到 99第二次 70 到 89一直到 0 到 19。总共 9 次调用。如果用步长 5就是 17 次调用效果略好但成本几乎翻倍。步长取窗口的一半是个经验平衡点重叠 50% 已经足够让相邻窗口的信息传递过去。窗口大小本身也有讲究。太小比如 5模型判断很准但调用次数爆炸太大比如 50单次上下文压力大、位置偏差明显、而且模型在长列表里的排序质量会明显下降。10 到 20 是比较稳的区间具体取多少要看模型的长上下文能力和单条文档的长度。3.3 输出解析的鲁棒性处理理论很美好实际调用十次里总有一两次输出不听话。常见情况包括返回了带括号的[3, 2, 1]、用顿号分隔、编号后面跟了句解释、少输出一个编号、输出了超出范围的编号、甚至返回中文数字。解析器必须写得足够宽容同时又要有明确的兜底策略。核心原则是解析失败时保留原顺序绝不能让排序结果变得更差。import re def parse_ranking(raw_text, n): 从模型输出中提取编号序列失败返回 None # 抓取所有独立的数字 nums re.findall(r\b\d\b, raw_text) seq [] seen set() for s in nums: idx int(s) # 编号从 1 开始过滤越界和重复 if 1 idx n and idx not in seen: seq.append(idx) seen.add(idx) if not seq: return None # 补齐漏掉的编号追加到末尾保持它们原有的相对顺序 for i in range(1, n 1): if i not in seen: seq.append(i) return seq这段代码有两个设计取舍值得说明。第一用\b\d\b抓独立数字而不是按分隔符切分因为模型的分隔符太不统一了逗号、顿号、空格、换行都出现过用分隔符切必然漏。第二漏掉的编号补在末尾而不是丢弃。因为一条文档被漏掉很可能是模型觉得它最不相关所以没提但也可能是单纯数错了。补在末尾是对这两种情况都比较安全的处理——如果真的不相关它在末尾是正确位置如果是模型数错了它本来在窗口里的位置也不会太靠前。还有一个更高阶的鲁棒性问题编号到内容的映射必须由代码维护不能交给模型。模型输出的只是数字你拿数字去索引原始列表。如果让模型在输出里带上文档摘要它一改写你就没法回溯了整个重排结果直接作废。3.4 成本与延迟的实测账这部分是真正决定方案能不能上线的地方。拿 100 条候选、窗口 20、步长 10 算是 9 次调用。每次调用的输入 token 大概是prompt 模板 200 tokenquery 50 token20 条文档 × 200 token 4000 token合计约 4250 token。9 次就是约 38000 输入 token。输出方面纯编号输出每次不到 100 token总共可以忽略。延迟上如果走本地部署的中等规模模型、批量推理单次调用可能在 300 到 800 毫秒串行 9 次就是 3 到 7 秒。这个延迟对交互式问答来说太慢了。三个优化方向第一减少候选数。召回 100 条重排到 Top-10和召回 40 条重排到 Top-10最终效果差不了太多因为第 40 到 100 名之间本来就极少有真正相关的内容。先做一层便宜的粗筛向量相似度阈值或者 pointwise 打分把候选砍到 30 到 40 条再上 listwise成本直接降一半以上。第二窗口间并行。严格来说从后往前的滑窗是串行的因为后一个窗口要用前一个窗口的输出。但如果你能接受轻微的质量损失可以把滑动窗口换成分段窗口加全局合并把 40 条分成 4 段互不重叠的 10 条并行排完再对每段的第一名做一次小规模的全局重排。这样 4 次调用可以全部并行延迟降到单次量级。第三缓存与降级。高频 query 的重排结果可以缓存命中率在客服类场景里通常不低。另外设置超时降级——LLM 调用超过阈值就退回原始向量顺序保证链路不会因为重排环节卡死。4. 效果评估与调参怎么证明它真的变好了4.1 指标选择与评测集构造重排任务的评估指标nDCGk 是最常用的因为它同时考虑了相关性的等级和位置——把高度相关的文档排到前面得分就高。MRR 更简单只看第一条相关文档出现在第几位适合只有一个正确答案的场景。Recallk 衡量的是前 k 条里覆盖了多少相关文档适合宁多勿漏的场景。指标关注点适用场景注意事项nDCG10排序质量 相关性等级通用排序评估需要多级相关性标注MRR10首个正确结果的位置问答、事实检索只看第一条忽略其余Recallk前 k 条覆盖率需要下游再筛排序质量差不影响该指标Hit Ratek前 k 条是否命中快速验证粒度粗不适合调参评测集怎么来我的做法是从线上真实日志里随机抽 200 到 300 条 query覆盖长尾和头部。然后对每条 query把召回的前 20 条文档拿出来人工标注相关性等级0 无关、1 部分相关、2 高度相关。这个活很枯燥200 条 × 20 篇大概要一两天。但这一步省不掉——没有评测集所有调参都是盲调你根本不知道自己改 prompt 之后是变好了还是变差了。有个降本技巧不用全部人工标。先用当前最强的方案比如带 CoT 的 listwise 重排跑一遍把它给出的顺序作为弱标签人工只做抽查修正明显错误的。这种做法叫模型辅助标注用在内部评测上完全可以只要抽查比例够20% 以上。4.2 关键超参的影响实测量级调参这件事纸上推演不如实测。下面这几个参数的敏感度我在不同数据集上都反复验证过参数常见取值影响方向敏感度窗口大小 w10 / 20 / 30太小判断准但调用多太大质量下降中高步长 stepw/4 / w/2越小重叠越多、效果略好、成本上升中单条截断长度100 / 200 / 400 token太短丢信息太长稀释注意力高候选总数 N30 / 50 / 100超过 50 后边际收益递减明显中输出格式纯编号 / 编号解释带解释略好但贵数倍低最值得投入精力的是截断长度它的敏感度最高。截断到 100 token 时很多需要具体参数或代码示例才能回答的问题会被误判为不相关截断到 400 token 时20 条文档就是 8000 token上下文压力大且模型在长文本里的关键信息定位会变差。200 token 左右是多数场景的甜点区。窗口大小的敏感度次之。10 和 20 之间的效果差通常在 1 到 3 个 nDCG 点20 到 30 之间差得更少。所以如果延迟敏感可以放心用 10。4.3 位置偏差最容易被忽略的系统性问题有一个现象值得单独拎出来把同一批文档打乱顺序重新送进去模型给出的排序结果经常不一样而且倾向于保留原始顺序。这是典型的 position bias——模型对列表开头和结尾的文档关注度更高中间部分容易被忽略。这个问题在 UPR 这类无监督方案里尤其要命因为你的初始顺序来自向量相似度本来就携带了信息。如果模型只是轻微打乱原顺序你就没法判断它到底是真的做了相关性判断还是单纯在附和输入。诊断方法很简单拿一批文档跑两次一次用向量相似度顺序作为输入一次用完全随机的顺序作为输入比较两次输出的一致性和各自的 nDCG。如果随机顺序输入的版本明显更差说明模型严重依赖输入顺序如果两者接近说明它确实在做独立判断。缓解手段有三个。一是双向排序正序跑一次逆序跑一次把两次的排名取平均类似 Borda 计数。成本翻倍但能显著削弱位置偏差。二是窗口内文档随机化每次调用前打乱窗口内顺序用编号映射回来多跑几次取平均。三是在 prompt 里显式提醒文档顺序与相关性无关请独立判断。第三种最便宜效果也最有限但作为基础配置值得加上。5. 常见问题与排查实录5.1 问题速查表现象大概率原因排查动作处理方式排序结果和原顺序几乎一样位置偏差 / 文档本身区分度低随机顺序重跑对比双向排序、prompt 加提示输出编号缺失或重复窗口过大、约束不够强检查解析日志降窗口、解析器补齐、prompt 强调部分 query 效果明显变差领域相关性标准与通用理解不符抽样看这些 query 的标注加 few-shot 示例、做规则兜底长文档判断明显失误关键信息被截断对比不同截断长度增大截断、按段落切分后重排延迟高到无法接受候选数太多、串行调用统计各环节耗时粗筛降 N、窗口并行、加缓存结果在不同批次间抖动模型温度非零检查推理参数温度设 0、固定 seed5.2 三个踩过的坑坑一以为重排一定能让指标变好。早期我在一个技术文档库上直接上了 listwise 重排结果 nDCG 反而掉了两个点。排查下来发现这个库的文档标题和摘要写得非常规范向量召回的初始排序已经相当准而 LLM 在判断时被文档正文里的扩展内容干扰了——它倾向于给讲得更全面的文档打高分而不是直接回答问题的那篇。教训是上线前一定要有 A/B 对比别默认新方案就是更好的。后来加了优先选择直接包含答案的文档而非背景介绍类内容这句约束才把损失补回来。坑二prompt 里的文档编号和代码里的索引错位。有一次线上反馈排序结果完全随机排查了半天发现是 prompt 里文档编号从 1 开始而解析后的代码直接拿返回值当下标用整体偏移了一位。最后一条永远排第一第一条永远被丢弃。编号映射一定要写单测这是最容易出低级错误又最难发现的地方。坑三忽略了下游生成环节的实际需求。重排的目标是把能回答问题的文档排前面但下游的生成模型需要的往往是信息互补的一组文档而不是五篇说同一件事的文档。纯粹按相关性排序很容易得到五篇高度重复的内容。解决办法是在重排之后加一层去重按内容相似度做 MMR 式的多样性重排或者在 prompt 里加一条避免选择内容高度重复的文档。这个问题不在重排指标里体现只有端到端评测才会暴露。6. 工程落地时的几个取舍建议6.1 什么时候该上、什么时候别上这套方案不是万能药有些场景上了纯属浪费。推荐上的场景知识库内容更新频繁、来不及标注训练数据多语言或多来源混合、cross-encoder 难覆盖候选集规模中等几十到一两百条、延迟容忍度在秒级对可解释性有要求能通过改 prompt 快速调整判断口径。不建议上的场景QPS 很高且延迟要求百毫秒以内的在线搜索候选集动辄上千条成本完全不可控领域相关性标准极其特殊法条、医疗指南这类通用模型判断不了已经有高质量标注数据、训好的 cross-encoder 表现稳定没必要为了新技术栈替换掉成熟方案。还有一类特殊情况值得单独说如果你只是想让 Top-5 更准候选只有 10 到 20 条其实 pointwise 打分加排序就够了成本低得多效果差距不大。listwise 和滑窗那套复杂度是给候选多、要求高的场景准备的。6.2 混合策略往往比纯 LLM 更实用纯 LLM 重排的两个软肋是成本和稳定性。比较务实的做法是把它当成流水线中的一环而不是全部。一个我实际用过的三段式组合第一段用向量相似度召回 60 条第二段用轻量规则做硬过滤时间范围、来源白名单、语言匹配砍到 40 条第三段用 listwise 滑窗重排到 Top-8。规则层负责那些模型不擅长的确定性判断模型层负责语义层面的细腻区分。两层各司其职比让模型什么都干要稳得多。另外把 LLM 的打分结果和向量相似度做加权融合也是个好办法。最终得分 α × 归一化后的向量相似度 (1-α) × 归一化后的 LLM 排名得分α 取 0.3 到 0.5。这样即使在 LLM 判断失误的个别 case 上向量相似度还能兜一层底整体方差会明显降低。6.3 模板迭代的节奏模板不要一次写死。我的做法是建一个小型的模板库每个模板改一个变量比如有没有 few-shot、约束措辞的强弱、输出格式在固定评测集上跑分记录每次改动的增益。这个过程中会积累出一些反直觉的发现——比如有时候删掉一句看似重要的约束效果反而更好因为过度的约束会让模型把注意力放在格式上而不是内容上。迭代节奏上第一轮先把基础流程跑通、跑出基线分第二轮集中调截断长度和窗口大小这两个高敏感参数第三轮再打磨 prompt 措辞。顺序别搞反很多人在第一步就开始死磕 prompt 文案其实参数没调对模板再好也发挥不出来。最后分享一个我在实际项目里的体会这套方案真正的价值不在于它比训练式重排好多少而在于它把一个原本需要几周标注加训练的环节压缩成了半天调 prompt 就能跑通的最小闭环。先跑起来、先看到效果、先拿到评测数据然后再决定要不要投入资源做专门的模型——这个决策顺序比任何单项技术的选择都重要。