当前位置: 首页 > news >正文

Fill In the Middle:让语言模型学会“瞻前顾后“

本文涉及的 FIM 推理实现已开源:RWKV-Server https://github.com/AUXStar/RWKV-Server —— 基于 RWKV7 的高性能批量推理引擎,单卡 RTX 4090 峰值 11,081 tok/s,支持 FIM 代码补全。

从一个场景说起

程序员在编辑器中写代码时,光标往往不在文件末尾——它在函数体中间、在两行已有代码之间、在 import 语句和函数签名之后。此时代码补全面临一个根本问题:模型需要同时理解光标前的代码光标后的代码,才能生成正确的填充内容。

传统的自回归语言模型只能从左到右生成。它们看到 prefix 后就开始逐 token 输出,对 suffix 一无所知。这在文件末尾续写时没问题,但在文件中间编辑时,丢失了半数上下文。

Fill In the Middle(FIM)正是为解决这个问题而生的技术。它的核心思想极其简洁:不改模型架构,只改训练数据的排列方式,就让因果语言模型同时利用前后文信息。


一、FIM 的原理

1.1 核心变换

FIM 的做法是将一篇文档在随机位置切分为三段——prefix、middle、suffix——然后把 middle 移到末尾,用特殊 token 拼接:

原始文档: [prefix] [middle] [suffix] FIM 变换后: [prefix] [suffix] [middle] ↑ ↑ ↑ <fim_prefix> <fim_suffix> <fim_middle>

模型仍然从左到右自回归生成,但此时它已经"看到"了 suffix。当生成到<fim_middle>之后的内容时,模型同时拥有 prefix 和 suffix 的信息,可以生成连贯的中间填充。

推理时,只需将用户提供的 prefix 和 suffix 按相同格式拼接,模型就会在<fim_middle>之后输出填充内容:

输入: <fim_prefix>{prefix}<fim_suffix>{suffix}<fim_middle> 输出: {模型在此生成中间内容}

1.2 SPM 与 PSM

原始论文定义了两种排列变体[1]

PSM(Prefix-Suffix-Middle)

<pre>{prefix}</pre><suf>{suffix}</suf><mid>{middle}</mid>

SPM(Suffix-Prefix-Middle)

<suf>{suffix}</suf><pre>{prefix}</pre><mid>{middle}</mid>

区别在于 suffix 和 prefix 的先后顺序。SPM 把 suffix 放在 prefix 前面,使 suffix 离生成位置更近,模型更容易利用 suffix 信息。论文实验表明 SPM 在 FIM 任务上表现更好,但联合训练 PSM+SPM(各 50%)是最佳实践。

1.3 “FIM-for-free”——零代价获得新能力

FIM 最优雅的属性在于:在预训练阶段混合 FIM 数据不会损害模型原有的从左到右生成能力[1]

论文作者训练了从 50M 到 6.9B 参数的 16 个模型进行对照实验。结果表明,以 50% 的 FIM 变换概率混合训练后,模型在 perplexity、PIQA、Winograd、DROP、HellaSwag、LAMBADA、HumanEval 等标准基准上的表现与纯自回归模型完全一致。FIM 能力是"免费"附赠的。

反过来,如果留到微调阶段才学 FIM,则需要大量额外算力才能达到同等效果。这意味着 FIM 应该在预训练阶段就引入。


二、主流实现

2.1 各模型的 FIM 格式

几乎所有主流代码模型都在预训练中采用了 FIM。它们的特殊 token 命名不同,但原理完全一致:

模型FIM Token 格式训练策略
OpenAI Codex<|fim_prefix|>...<|fim_suffix|>...<|fim_middle|>PSM 为主
StarCoder (BigCode)<fim_prefix>...<fim_suffix>...<fim_middle>PSM+SPM 混合,50% FIM rate
DeepSeek-Coder<|fim▁begin|>...<|fim▁hole|>...<|fim▁end|>三片段输入
Qwen2.5-Coder<|fim_prefix|>...<|fim_suffix|>...<|fim_middle|>+<|fim_pad|>PSM+SPM 混合
CodeLlama (Meta)类似 Codex 格式FIM 训练
SantaCoder<fim_prefix>...<fim_suffix>...<fim_middle>PSM+SPM 混合
RWKV (rwkv_lightning / RWKV-Server)✿prefix✿✿suffix✿{suffix}✿middle✿{prefix}Unicode 字符标记,无需特殊 token

2.2 推理示例

以 Qwen2.5-Coder 为例[5]

fromtransformersimportAutoTokenizer,AutoModelForCausalLM tokenizer=AutoTokenizer.from_pretrained("qwen/qwen2.5-coder-7b")model=AutoModelForCausalLM.from_pretrained("qwen/qwen2.5-coder-7b")prefix="def hello_world():"suffix="\n print(result)"prompt=f"<|fim_prefix|>{prefix}<|fim_suffix|>{suffix}<|fim_middle|>"inputs=tokenizer(prompt,return_tensors="pt")outputs=model.generate(**inputs,max_new_tokens=100)

以 DeepSeek API 为例[4]

response=client.fim_completions.create(model="deepseek-fim",prefix="def factorial(n):\n if n == 0:\n return 1\n ____",suffix="\n print(factorial(5)) # 输出120")

三、FIM vs 其他"双向"方案

FIM 并非让语言模型"看到两边"的唯一方案,但它是最简洁、最实用的一种。

3.1 方案对比

方案代表模型架构修改训练开销生成质量工业采用
FIM (Infilling)Codex, StarCoder, DeepSeek-Coder零额外广泛
Permutation LMXLNet[12]双流注意力中等中高XLNet
Span CorruptionT5, SpanBERTEncoder / Enc-Dec中等T5
Masked LMBERTEncoder-only中等低(生成)BERT 系列

3.2 为什么 FIM 胜出

Permutation Language Modeling(XLNet)对输入 token 序列做随机排列,通过双流自注意力让每个 token 看到所有位置。理论上更通用,但需要修改模型架构(双流注意力),计算开销更大,且在代码生成任务上没有明显优势。

Span Corruption(T5、SpanBERT)随机遮蔽文本中的连续片段,让模型预测被遮蔽的内容。通常用于 encoder 或 encoder-decoder 架构,可以腐蚀多个 span,但训练目标是 denoising 而非自回归,在开放式生成任务上表现不如因果模型。

FIM的优势在于:不改变模型架构、不增加推理开销、不损失原有能力、实现极其简单(只需数据变换)。它是一个"免费的午餐"。


四、适用场景

FIM 并非在所有场景下都优于传统的从左到右生成。选择取决于上下文的可用性:

场景推荐方式原因
代码续写(文件末尾)L2Rsuffix 为空,FIM 退化为 L2R
代码中间补全FIM光标前后都有代码
函数体生成FIM有函数签名(prefix)和返回语句(suffix)
import 语句生成FIM后续代码作为 suffix 约束类型
docstring 生成FIM函数体作为 suffix 提供类型信息
对话 / 问答L2R天然顺序生成
文本编辑 / 修改FIM替换段落时前后文都存在

实际应用中,代码编辑器(如 rwkv-code-completion[9])会根据光标位置自动切换:光标后有代码时走 FIM,光标在文件末尾时走普通续写。RWKV-Server 的 FIM 端点同样遵循这一策略——suffix 为空时自动退化为普通续写,无需额外适配。


五、RWKV 生态中的 FIM

5.1 rwkv_lightning 的实现

rwkv_lightning[8]使用 Unicode 字符(U+273F)作为 FIM 标记,而非传统的<fim_prefix>格式:

✿prefix✿✿suffix✿{suffix}✿middle✿{prefix}

这种设计的好处是是普通 Unicode 字符,不需要在 tokenizer 中添加特殊 token,任何 RWKV 模型都可以直接使用。

rwkv_lightning 的 FIM 接口支持批量推理:prefix 和 suffix 为列表,一次请求处理多组不同的 FIM 任务,充分利用 RWKV 的批量推理能力。

5.2 RWKV-Server 的 FIM

RWKV-Server 在 rwkv_lightning 的基础上进一步简化了接口。POST /v1/tasks/fim接收单个 prefix + suffix,内部构造相同的 FIM prompt 后,复用现有的 Task 调度器和批量推理引擎:

curl-XPOST http://localhost:8000/v1/tasks/fim\-H"Content-Type: application/json"\-d'{ "prefix": "def hello_world():\n print(", "suffix": ")\n return True", "max_tokens": 50, "stream": false }'

整个 FIM 功能只改了两个文件——schemas.py新增请求模型,routers.py新增端点——核心 prompt 构造只有一行。FIM 的实现完全复用了 RWKV-Server 的现有基础设施——Task 调度器、动态扩缩容、SSE 流式输出——零侵入底层。

5.3 RWKV 架构对 FIM 的天然适配

RWKV 的 O(1) 线性注意力和固定大小 state 使其天然适合高并发 FIM 场景:

  • state 不随序列长度膨胀:长 prefix + suffix 不会像 Transformer 的 KV Cache 那样消耗大量显存
  • 批量吞吐线性增长:batch_size 越大,GPU 利用率越高,单卡可以支撑数百并发 FIM 请求
  • 状态复用:同一文件的多次编辑可以复用 prefix 部分的 state,避免重复 prefill

在 RTX 4090 上,RWKV-Server 使用 RWKV7 2.9B 模型可达到峰值 11,081 tok/s(256 并发),7.2B 模型峰值 6,373 tok/s。


六、关键超参数

原始论文的消融实验揭示了几个关键超参数[1]

FIM Rate(变换概率):推荐 50%,即一半训练数据做 FIM 变换,一半保持原始顺序。低于 50% 会削弱 FIM 能力,高于 50% 会轻微影响 L2R 能力。

Span 选择策略:推荐在 context 级别(而非 document 级别)做 FIM,并使用均匀的 span 长度分布。对于代码,优先在行/段落边界分割效果更好。

SPM vs PSM 比例:联合训练 SPM+PSM(各 50%)是最佳实践,单一格式的效果略逊。

评估方式:论文特别指出,仅看 test loss 会误导——不同超参数下 FIM test loss 差异很小,但在采样基准(pass rate)上差异巨大。评估 FIM 能力必须用采样而非 perplexity。


Sources

  1. Bavarian et al., "Efficient Training of Language Models to Fill in the Middle", arXiv:2207.14255, 2022.https://arxiv.org/abs/2207.14255
  2. Li et al., SantaCoder: Training Open-Source Code LLMs with 1 Trillion Tokens, BigCode, 2023.https://blog.csdn.net/gitblog_02761/article/details/144662538
  3. Ray et al., StarCoder: May the Source Be with You!, BigCode, 2023.https://hub.baai.ac.cn/view/26590
  4. DeepSeek FIM 功能解析, CSDN, 2024.https://blog.csdn.net/qinzhenyan/article/details/154409461
  5. Qwen2.5-Coder 技术报告, CSDN, 2024.https://blog.csdn.net/jinselizhi/article/details/143759611
  6. Seed-Coder FIM+SPM 训练策略, 2025.https://www.dodgeindustrial.com.cn/dy/article/20250508796423665.shtml
  7. tiktoken FIM 特殊 token 定义, OpenAI.https://blog.csdn.net/gitblog_00536/article/details/151175018
  8. rwkv_lightning 项目 + Albatross 推理引擎, RWKV-Vibe.https://juejin.cn/post/7597641580104581174
  9. rwkv-code-completion VS Code 插件, xun082.https://juejin.cn/post/7597641580104581174
  10. RWKV7-G1c 系列模型发布, RWKV 社区, 2025.https://juejin.cn/post/7600888960106070052
  11. Yang et al., XLNet: Generalized Autoregressive Pretraining for Language Understanding, 2019.https://blog.csdn.net/DarrenXf/article/details/96449450
http://www.jsqmd.com/news/1046304/

相关文章:

  • 青岛即墨区靠谱的空调清洗公司咨询电话(2026最新) - 品牌排行榜
  • 2026年热门的黑色全方位导电泡棉/异形导电泡棉公司哪家好 - 行业平台推荐
  • 树莓派5实战:从零部署Ubuntu 24.04 LTS服务器
  • 猫抓插件:如何通过浏览器扩展实现专业级资源嗅探与下载
  • 2026年质量好的医药合规卷筒不干胶/食品包装卷筒不干胶/定制卷筒不干胶厂家哪家好 - 行业平台推荐
  • 2026莆田本地人必选防水补漏检测维修公司靠谱服务商TOP5推荐:房屋渗漏水检测维修/卫生间/厨房/天花板/阳台/外墙渗漏水检测补漏维修-暗管漏水检测专业仪器精准定位漏水点 - 即刻修防水
  • MC68HC908KX8调试核心:Break模块与Monitor ROM实战解析
  • 2026年知名的苏州导电 EVA/彩色 EVA推荐厂家精选 - 行业平台推荐
  • 【视频图像增强】基于改进的Retinex算法图像增强研究(Matlab代码实现)
  • 2026年知名的义乌国际海运代理/义乌国际空运代理实力公司推荐 - 品牌宣传支持者
  • 2026年可靠的青岛办公工学椅/青岛人体工学椅/工学椅/商务久坐工学椅公司哪家好 - 行业平台推荐
  • 2026年比较好的惠州 LED屏/会议室LED屏厂家对比推荐 - 品牌宣传支持者
  • 深入解析S12XS Flash内存控制器:从ECC纠错到安全编程实践
  • dayspan-vuetify架构解析:构建企业级Vue日历组件的技术实现
  • MC68060处理器信号控制与MMU架构:嵌入式系统稳定性的硬件基石
  • 2026年可靠的电缆/rvvp电缆稳定供货厂家推荐 - 行业平台推荐
  • 嵌入式系统性能优化:深入解析ColdFire微控制器Cache与SRAM配置实战
  • 2026年口碑好的苏州卷材 EVA/无味 EVA/EVA优质厂家汇总推荐 - 品牌宣传支持者
  • 2026年评价高的全自动拉伸膜包装机/热成型气调包装机/拉伸膜封口包装机口碑好的厂家推荐 - 行业平台推荐
  • 龙虾智能体进阶实战:自定义Skill插件开发与多模型适配方案
  • 2026年评价高的苏州注塑模具开模/塑胶开模厂家综合对比分析 - 行业平台推荐
  • 2026年比较好的鲜花饰品批发/抖音同款饰品批发/外贸饰品批发厂家对比推荐 - 品牌宣传支持者
  • LLM API协议抽象层演进:从Chat Completions到Responses
  • MiniMax M2.7:原生Agent语义架构的技术解析
  • TortoiseSVN实战:精准回滚Windows环境下的问题代码版本
  • 2020 TI杯电赛实战代码包:RPLIDAR+OpenMV+串口调试全栈Python工程
  • 2026市面上专业的废弃输送pp防静电管生产商排行 - 品牌排行榜
  • 豆包AI不是智能助手,而是对话式信息接口
  • GLM-5.1深度解析:国产大模型的中文长文本结构化语义建模突破
  • 如何解决3D渲染中球形全景图到立方体贴图转换的技术挑战