论文名称:CodeIF: Benchmarking the Instruction-Following Capabilities of Large Language Models for Code Generation
机构:北航 + 清华 + 新加坡国立大学
Github代码链接:github.com/lin-rany/co...
简介
随着 AI Coding 持续火爆,代码生成需求持续增长,但模型理解复杂指令的能力如何准确评估还是一个有挑战性的话题。本文就提出了一个 CodeIF 基准,用于评估 LLM 在代码生成任务中的复杂指令遵循能力。
构造方法
框架概述

图1展示的是CodeIF构建流程,具体如下:
- 种子问题到选定问题(浅橙色部分) :一开始有一些"种子问题" (Seed Question),经过筛选,得到"选定问题"(Selected Question ) 。这些问题是构建数据集的起始素材。
- 人类专家生成高质量问题(浅蓝色部分) :"人类专家"(Human-Expert )对相关内容进行处理,生成"高质量问题"(High Quality Question) 。人类专家凭借专业知识,对问题进行优化和完善。
- 约束收集(浅绿色部分) :从互联网(Internet)上进行"约束收集"(constraint collection ),形成"指令"(Instruction) 。也就是从网络获取各种代码生成任务的约束条件。
- LLM处理及构建依赖(中间及右侧部分) :把前面得到的"选定问题""高质量问题"和"指令"都输入到LLM 。LLM对这些信息进行处理,之后再由人"构建依赖"(Build Dependence ),最终得到"CodeIF数据"(CodeIF Data ) 。这一步是整合前面的内容,建立起数据之间的关联,形成可用的CodeIF数据集。
构建流程示例
结合我个人的理解,以实现一个简单的学生信息管理系统(用Python语言)为例,说说CodeIF数据构造过程。
- Step-1:种子问题筛选
先从众多代码生成相关问题里,挑出"实现学生信息管理系统"作为种子问题,这是构建数据集的起始点。
- Step-2:人类专家生成高质量问题
人类专家介入,把这个种子问题完善。比如明确要实现的功能:能添加学生信息(姓名、学号、成绩等 )、能查询学生成绩、能更新学生信息等,形成高质量问题。
- Step-3:约束收集
从互联网等渠道收集约束条件:
① 全局约束:限定用Python语言编写;代码行数不超过100行。
② 结构控制约束:要求使用字典来存储学生信息;在查询功能中必须用for循环遍历数据。
③ 变量约束:定义存储学生姓名的变量名必须是 student_name
;成绩变量类型得是浮点数。
④ 函数约束:定义添加学生信息的函数名为 add_student_info
;查询学生成绩函数要有返回值。
⑤ 组合约束:先实现添加学生信息功能,才能实现基于已有信息的查询功能 。
- Step-4:LLM处理及构建依赖
把完善后的问题和收集的约束条件输入LLM,模型处理后,人工梳理约束间依赖关系。比如"查询学生成绩功能"依赖"添加学生信息功能"已完成,只有先成功添加学生信息,查询功能才有数据可查。经过这些步骤,就构造出了用于评估模型在该任务下表现的相关数据。
成品数据示例

图3展示了一个具体的代码生成任务示例及其约束指令,用于直观呈现 CodeIF 数据集中任务和约束的具体形式,
-
任务:实现一个带有LRU(最近最少使用)替换策略的缓存模块。
-
约束指令:
- 类别:分为global(全局)、structural control(结构控制)、variable(变量)、function(函数)、interface(接口)、class(类)、file(文件)、combination(组合)等类别 。
- 依赖关系:部分指令存在依赖关系,如指令6依赖指令1(标记为[1,6] ),表示在满足指令1的前提下执行指令6 。
- 具体指令:如global类别下有"代码用C++编写""答案总行数不超过50行"等指令;structural control类别下有"代码不应使用数据结构std::unordered_map"等指令;class类别下有"代码应定义一个名为LRUCache的类"等指令。
基本参数
难度分级
分为 Easy(简单)、Hard(困难) 和 Full(完整) 三个级别,Easy 和 Hard 各包含 600 个代码生成任务,Full 为两者合并,共 1200 个任务。

编程语言
覆盖 Go、Python、Java、C++ 四种编程语言。
其中Java 任务数量最多(353 个),其次为 Python(348 个),C++(269 个) 和 Go(230 个) 相对较少。
平均指令长度
① Easy 任务:每个任务平均包含 11.99 条原子约束指令。
② Hard 任务:平均指令长度提升至 13.8 条,体现更高的复杂度和约束严格性。
③ Full 数据集:平均指令长度为 12.9 条,介于前两者之间。
图 4 展示了不同难度下任务的指令列表长度分布,可以看到:Hard 任务的长指令比例显著高于 Easy。

类别覆盖与难度差异
① 评估集包含 8 个约束类别:Global(全局)、Structural Control(结构控制)、Variable(变量)、Interface(接口)、Function(函数)、Class(类)、File(文件)、Combination(组合)。
② Global(全局约束) 占比最大(22.77%),反映对代码整体结构和逻辑一致性的重视。
③ Variable(变量约束) 次之(18.17%),强调对变量命名、类型、初始化等细节的评估。
④ 其他类别如 Structural Control(结构控制,9.84%)、Function(函数,14.21%)等占比相对均衡,确保评估的全面性。
图 5对比了 Easy 与 Hard 数据集各约束类别的平均指令数,显示 Hard 任务中 Global、Variable 等核心类别的指令数显著增加。

图 6展示了原子指令类别在整体数据中的比例分布,突出 Global 和 Variable 的主导地位。

评价指标
完全满足率(CSR,Completely Satisfaction Rate)
- 定义:看所有问题里,是不是所有约束条件都被模型满足了,统计这种情况占总问题数的比例。比如有 10 个代码生成任务,每个任务都有一堆约束条件,只有当一个任务里的所有约束都满足了,才算符合 CSR 的要求,最后看符合要求的任务在 10 个里占多少。
- 公式:

- 作用:用来严格考察模型是不是能把所有约束都做到,是一种高标准的评估,看模型在最理想的完全符合要求的情况下的表现。
软满足率(SSR,Soft Satisfaction Rate)
- 定义:计算每个问题里,约束被满足的平均比例。还是那 10 个任务举例,计算每个任务里满足的约束数量除以总约束数量,得到每个任务的满足比例,最后把这 10 个比例求平均。
- 公式:

- 作用:不像 CSR 要求那么苛刻,允许模型有部分约束没满足,从整体上看模型满足约束的平均水平,评估更灵活。
严格满足率(RSR,Rigorous Satisfaction Rate)
- 定义:在代码生成中,有些约束是有先后顺序的,前面的条件得先满足,后面的才能算满足。RSR 就是考虑这种约束之间的依赖关系,看模型是不是按照正确顺序满足约束的。比如任务里要求先定义一个函数,再调用这个函数,模型得先做到定义,再去调用,这个指标就衡量模型在这种有依赖关系的约束上的表现。
- 公式:

- 作用:专门针对有依赖关系的约束进行评估,保证模型在处理这种复杂约束时,能按照正确逻辑顺序来,避免模型只是孤立地满足单个约束,不管顺序。
连续满足率(CCSR,Consistent Continuity Satisfaction Rate)
- 定义:在很多代码生成任务里,模型得能连续地满足约束条件,不能断断续续。CCSR 就是找每个问题里,模型连续满足约束条件的最长长度,再把这个长度和总约束数比,最后求所有问题的平均值。比如一个任务有 10 条约束,模型连续满足了 5 条,这就是这个任务里的连续满足长度。
- 公式:

- 作用:考察模型在处理一长串约束指令时,能不能保持连贯,不中断,看模型在遵循连续指令方面的稳定性。
使用方法
官方Github界面说的很清楚了,配置完环境之后,再执行下面的脚本就行。
bash
bash scripts/if_pipeline.sh
看一眼目前最新的排行榜,整体来说挺符合预期的,Benchmark本身的区分度不错。

总结
总结下来,CodeIF构造以及评估的核心思想就是:将一个复杂的原始代码生成指令分解为细粒度的子指令,从子指令的角度挨个判断LLM生成的代码是否满足了原始代码生成指令的要求。
思路还是比较OK的,我们团队之前构造数据也是这种思路,将一个场景的理想态抽象成各个Principle让LLM去Judge,效果还是不错的。