你接手了一家经营二十年的老饭馆,后厨仓库里堆满了几十只没有标签的纸箱。有的渗着油渍,有的爬着霉斑,唯一认得这些箱子的大师傅退休时只留下一句“都在那儿了,自己看”。你只能一只只开箱、辨认、手写标签——如果此时有位助手扫一眼箱子内部就脱口而出“秘制豆瓣酱,需冷藏保存”,你大概会感动得想给他加鸡腿。这位助手,就是代码摘要生成。它要做的,是读懂“沉默的代码”,替每个函数写上清清爽爽的自然语言说明。这门技术从“看箱子外形猜内容”的土办法,一路进化到“见过几百万间仓库的老管家”,还配套了“标签验收单”(BLEU 指标)。读完这篇文章,你不仅能把旧项目的“仓库”整理得井井有条,还能让后来者翻代码就像翻一本贴着标签的相册。

岗位关联

学习代码摘要生成,能让你在接手历史项目、构建代码知识库、搭建文档治理体系时,用 AI 自动化取代人肉补注释,大幅降低文档维护成本,是 AI 工程师迈向“代码智能”领域的必修课。

目录
  1. 可视化演示
  2. 摘要生成概述
  3. 基于规则方法
  4. 基于检索方法
  5. 统计语言模型
  6. 预训练模型
  7. 质量评估
  8. 实战应用
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

交互展示大语言模型对齐评估的核心流程:多维对齐基准测试、红队安全对抗检测与人类反馈强化优化,可视化从评估到改进的闭环。

本节配有交互动效(进入视口后自动加载,约 3KB)。

多维对齐基准评估 有用性、无害性、诚实性三维度评估 基准数据集自动评分与排名 Score = \u03a3 w_i \u00d7 s_i 加权聚合多维度对齐得分

摘要生成概述

你接到一个整理老饭馆后厨仓库的任务:几十只没有标签的纸箱堆在墙角,有的渗着油渍,有的爬着霉斑,唯一认得这些箱子的大师傅已经退休。你只能一只只打开、辨认、再手写标签贴上去。如果此时有位助手能扫一眼箱子内部,直接脱口而出“秘制豆瓣酱,需冷藏保存”,你会不会激动得想给他涨工资?这位助手,就是代码摘要生成——它天生擅长让“沉默的代码”开口介绍自己。

在软件世界里,代码就是那些沉默的纸箱,函数是箱子,docstring 是标签。代码摘要生成(Code Summarization)指让程序自动阅读一段源代码,输出一句流畅的自然语言描述,说清楚“这段代码做了什么、怎么用、有哪些坑”。它的价值在于:接手历史项目时不再依赖“大师傅”口述,AI 自动把缺失的文档补回来;后续任何人翻代码都像看标签一样一目了然,文档维护成本被大幅压缩。

从数学视角看,这是一个条件语言模型问题。设 C 是输入的代码,S 是所有可能的描述句子,任务就是在所有句子中找出最合理的那句——也就是条件概率最高的 S。式中的竖线表示“在给定 C 的条件下”。

给纸箱贴标签看似简单,实际门道很深:太粗的标签等于没贴,太细的标签浪费笔墨,更别说有些箱子自带“伪装色”。正因如此,这项技术经历了一条清晰演进路线。接下来,我们就从最古老的土办法讲起,看看一代代“仓库管理员”是怎么把这件事越做越好的。

S∗=arg⁡max⁡S  P(S∣C)\displaystyle S^{*} = \arg\max_{S} \; P(S \mid C)
这个公式的意思是:模型遍历所有可能的摘要句子,挑出“在已知代码 C 的情况下最像人话、最像正确说明”的那一句作为最终输出。
  1. 代码输入 C一段待解释的函数或代码块,模型从这里读取变量名、调用关系、控制流等语义线索。
    C={c1,c2,…,cn}C = \{c_1, c_2, \dots, c_n\}
  2. 条件概率 P(S|C)衡量“句子 S 是代码 C 的合格说明”的可能性,数值在 0 到 1 之间,越接近 1 越自信。
    P(S∣C)P(S \mid C)
  3. argmax 选择把候选句子集合全部过一遍,挑出概率最高的那一句作为最终摘要。
    arg⁡max⁡S\arg\max_{S}

基于规则方法

最早的贴标签办法很朴素:看纸箱的长相。四四方方的大纸箱八成装干货,长条形的盒子多半是调味料瓶——这个规律百试百灵,于是有人把它写成一本《纸箱辨认手册》。对应到代码上,就是一系列启发式规则:看到动词 get 就写“获取”,看到函数名带 byId 就补上“根据 ID”,再按“动词 + 对象 + 参数”的模板拼成句子。

这类方法称为基于规则的方法,本质是两步走。第一步做结构分析,把代码拆成可识别的部件:主要做了什么动作(动词)、作用在什么对象上(名词)、在什么条件下(参数);第二步做模板匹配,把部件填入预设的句子模板。规则库的构建依赖领域专家经验,用正则表达式和抽象语法树就能实现,成本极低,结果确定,这也是它至今仍被用作兜底方案的原因。

形式化地看,规则方法是一个复合函数:

其中 $\rho$ 把代码抽成结构化特征,$\mu$ 把特征映射到模板。

规则方法像一本装订考究的《纸箱辨认手册》,翻得快、零成本,但只认手册里画过的箱子。一旦遇到“细长箱子装干货”这种反常识的存在,它就果断翻车。于是下一代管理员开始思考:能不能不背手册,直接翻翻仓库角落那本旧台账,看看老前辈是怎么写标签的?

S=μ(ρ(C))\displaystyle S = \mu(\rho(C))
可以理解为:先把代码“翻译”成一张填空卡,再按预设句式把空格填满,最终生成一句完整的摘要。
  1. 特征抽取 ρ(C)从函数名、注释、控制流中抽出“动作、对象、条件”三元组,例如 fetchUserById 被拆成“获取、用户、按 ID”。
    ρ(C)=(动作,对象,条件)\rho(C) = (\text{动作}, \text{对象}, \text{条件})
  2. 模板映射 μ把三元组填入预设的句子模板,动词配宾语、条件作状语,拼成自然语句。
    μ(a,o,c)=a+o+c⇒S\mu(a, o, c) = a + o + c \Rightarrow S
  3. 输出摘要 S返回完整的句子,作为该函数的 docstring 候选。

基于检索方法

仓库角落搁着一本泛黄的台账,记录着过去每只箱子的内容和标签。面对新箱子,你不必开箱,只需翻台账找一只“看起来最像”的箱子,把它的标签抄过来稍加改动——这就是基于检索的方法。它不追求从零造句,而是在已有“历史答案”中找参照。

检索方法的核心是相似代码检索。首先把代码表示成向量——常见做法是按 token 频次构建词袋向量,每个维度对应一个词条的权重;然后计算当前代码与库中代码的接近程度,选出最相近的几条,把它们的摘要直接复用,必要时将多段摘要做邻接拼接后稍作修剪。它继承了“以史为鉴”的优点:在垂直领域,检索结果可解释、可信度高,而且完全不需要训练模型。

相似度的计算最常用余弦公式:

检索法本质是“抄作业”,仓库越大、台账越全,命中率越高;可要是台账里根本没出现过同类箱子,或者老前辈当初就把标签写错了,它只能将错就错。要想真正“无中生有”地造句,还得靠能自动统计语言规律的办法。

sim(C,Ci)=v⋅vi∥v∥ ∥vi∥\displaystyle \text{sim}(C, C_i) = \frac{\mathbf{v} \cdot \mathbf{v}_i}{\|\mathbf{v}\| \, \|\mathbf{v}_i\|}
余弦相似度衡量的是两个向量“方向是否一致”,数值越接近 1 说明代码越像,就像两箱货的“气味”越相近。
  1. 代码向量 v当前代码 C 的向量表示,每个维度是某个词条的出现权重。
    v=(w1,w2,…,wd)\mathbf{v} = (w_1, w_2, \dots, w_d)
  2. 点积分子计算两个向量对应维度乘积之和,反映“协同出现”的强度。
    v⋅vi=∑j=1dvj vij\mathbf{v} \cdot \mathbf{v}_i = \sum_{j=1}^{d} v_j \, v_{ij}
  3. 模长归一化分母向量长度之积用于剔除代码长短带来的偏差,保证相似度落在有意义区间。
    ∥v∥=∑j=1dvj2\|\mathbf{v}\| = \sqrt{\sum_{j=1}^{d} v_j^{2}}

统计语言模型

如果既不想背手册,也没有旧台账可翻,还有一个更“笨”但更灵活的思路:把仓库里所有旧标签摊开,统计字词规律。比如一百张酱料标签里有八十五张出现“冷藏保存”,那么当一句话出现了“酱料”,模型就有把握补上“冷藏保存”。这就是统计语言模型的思想。

最经典的实现是 n-gram 模型。它假设当前词只与前 n-1 个词有关,用大规模语料中的词频概率估计条件概率。生成摘要时,模型几乎不看代码特征,单纯按概率从词表里挑选下一个词,逐个拼出整句——这就是序列生成。虽然“懂”得很浅,但它第一次让机器学会了“概率化造句”,而不是死记硬背。

以 bigram(n=2)为例,条件概率的估计公式为:

统计学徒的世界里只有词和频率,没有语法更没有语义,它造得出“冷藏、酱料、保存”这样断断续续的高频词串,却组织不出通顺的长句。要让标签写得像真人一样自然,只能请一位见过无数仓库的老师傅登场了。

P(wk∣wk−1)=count(wk−1 wk)count(wk−1)\displaystyle P(w_k \mid w_{k-1}) = \frac{\text{count}(w_{k-1}\, w_k)}{\text{count}(w_{k-1})}
意思是:在前一个词已经确定的情况下,下一个词出现的概率,等于这两个词相邻出现的次数除以前一个词总共出现的次数——用“历史数据”猜“下一步”。
  1. 前词与后词$w_{k-1}$ 表示已生成的上一词,$w_k$ 是待预测的当前词,模型只依赖最近一个词。
    wk−1⟶wkw_{k-1} \longrightarrow w_k
  2. 分子相识对语料中词对 $w_{k-1}w_k$ 相邻出现的次数,统计“这组搭配出现过多少次”。
    count(wk−1 wk)\text{count}(w_{k-1}\, w_k)
  3. 分母做归一上一词独自出现的总次数,把频次转化为概率。
    count(wk−1)\text{count}(w_{k-1})
  4. 平滑兜底若词对从未出现导致分子为 0,则回退到 unigram 概率,或给分子加 1 做拉普拉斯平滑,避免概率变成 0。
    Psmooth(wk∣wk−1)=count(wk−1wk)+1count(wk−1)+∣V∣P_{\text{smooth}}(w_k \mid w_{k-1}) = \frac{\text{count}(w_{k-1}w_k) + 1}{\text{count}(w_{k-1}) + |\mathcal{V}|}

预训练模型

终于,老板重金请来一位见过几百万间厨房仓库的老管家。他不翻手册、不看账本,只消扫一眼箱子里的东西就能脱口而出:“此为樟茶鸭腌料,含花椒与茶叶,需密封避光保存。”这位老管家,就是基于 Transformer 的预训练模型。

预训练模型(如 GPT、T5 系列)在海量“代码 + 自然语言”对上做自监督学习,学会了代码与语言之间的深层映射。针对代码场景的 CodeT5 采用编码器-解码器架构:编码器把代码的理解编码成语义向量,这是“代码理解”;解码器逐词写出描述,这是“代码生成”。相比 n-gram,它能捕捉长距离依赖,还能感知变量名、函数调用图的上下文,真正做到了理解代码意图。

生成阶段,模型按自回归方式逐词决策,整句概率是每个词条件概率的连乘:

老管家虽见多识广,也难免偶尔脱口而出看似漂亮、实则对不上号的话——把“料酒”说成“酱油”。标签写得流畅不等于内容准确,所以验收环节必不可少:机器粗筛加人工校验,双管齐下才能真正放心。

P(S∣C)=∏t=1mP(st∣s<t,C)\displaystyle P(S \mid C) = \prod_{t=1}^{m} P(s_t \mid s_{<t}, C)
老管家写标签时是“边写边回看”:每写下一个词,都要参考已经写下的所有词和原始代码,保证整句话前后连贯、贴合代码含义。
  1. 位置词 s_t摘要句子中第 t 个词,m 是句子总长度,生成是“逐字进行”的。
    S=s1s2⋯smS = s_1 s_2 \cdots s_m
  2. 历史上文 s\<t该词之前所有已生成词的集合,体现“边写边看上文”的自回归特性。
    s<t=s1s2⋯st−1s_{<t} = s_1 s_2 \cdots s_{t-1}
  3. 连乘号 Π把每个词的选择概率乘起来,得到整句话合理性的总分,避免“局部通顺、整体跑题”。
    ∏t=1mP(st∣s<t,C)\prod_{t=1}^{m} P(s_t \mid s_{<t}, C)
  4. 训练目标在训练语料上最大化整句概率的对数似然,让模型输出的词语序列越来越接近真人写作风格。
    L=−∑t=1mlog⁡P(st∣s<t,C)\mathcal{L} = - \sum_{t=1}^{m} \log P(s_t \mid s_{<t}, C)

质量评估

验收标签时,最省事的办法是拿一份“标准答案”来比对字句重合度。假设标准标签是“开盖后冷藏保存”,助理写的却是“放冰箱,盖好”,虽然意思沾边,字面却对不上——这种按“字句重合”打分的方法,就是自动评估指标 BLEU(Bilingual Evaluation Understudy)。

BLEU 最初用于机器翻译,后来成为文本生成领域的通用指标。它统计候选摘要与参考摘要的 n-gram 精确率:1-gram 看单个词是否命中,2-gram 看相邻词对是否命中,3-gram、4-gram 依次递进,越高的阶越能反映句子的流畅度和局部语序。把各阶分数做几何平均,再用简短惩罚因子 BP 压制“只写几个关键词糊弄”的偷懒行为。

BLEU 的完整计算公式为:

然而,字句重合终究不等于语义一致:助理完全可能写出与标准答案毫无重合、但意思更准确的标签。所以 BLEU 只适合当“粗筛漏斗”,真正拍板前还要人工开箱验货,确认标签与实物相符——这正是文档治理中最重要的一环:人机协同校验。

BLEU=BP⋅exp⁡ ⁣(1N∑n=1Nlog⁡pn)\displaystyle \text{BLEU} = \text{BP} \cdot \exp\!\left( \frac{1}{N} \sum_{n=1}^{N} \log p_n \right)
BLEU 分数本质上是“候选标签和标准答案的字面重叠度”。它快速、客观、可复现,但只认字面,不认意思。
  1. 各阶精确率 p_n第 n 阶 gram 的精确率,即候选摘要中被参考摘要命中的 gram 数除以候选 gram 总数。
    pn=命中第  n  阶 gram 数候选第  n  阶 gram 总数p_n = \frac{\text{命中第} \; n \; \text{阶 gram 数}}{\text{候选第} \; n \; \text{阶 gram 总数}}
  2. 对数取平均对 N 个阶数的分数取对数再求平均,等价于几何平均,要求各阶都不能太差。
    1N∑n=1Nlog⁡pn\frac{1}{N} \sum_{n=1}^{N} \log p_n
  3. 简短惩罚 BP当候选长度短于参考长度时按比例压低总分,防止“抄关键词不写全句”。
    BP={1,c>re1−r/c,c≤r\text{BP} = \begin{cases} 1, & c > r \\ e^{1 - r/c}, & c \le r \end{cases}
  4. 指数还原外层 exp 把对数平均还原为 0 到 1 之间的分数,越接近 1 字面重合度越高。
    exp⁡(log⁡score)=score\exp(\log \text{score}) = \text{score}

实战应用

故事来到最终章。你要把整间仓库几百只箱子全部贴上合格标签,还要立下规矩:以后新入库的箱子必须“先贴标签再上架”。对应到实际工程,就是批量补注释与文档治理——一次性的历史债清理和长期性的流程约束。

实践中,完整的落地路径分四步。第一步扫描代码库,找出所有缺少 docstring 的公共函数;第二步调用预训练模型批量生成候选摘要;第三步用 BLEU 做机器粗筛,对核心模块再走人工抽检;最后把通过校验的摘要合并回代码库,并接入 CI 流水线——以后任何新增代码若缺少注释,流水线会自动拦截并提醒补写。这就是工具链集成的完整闭环,让文档债不再“复利增长”。

推进这类治理项目时,团队常用一个覆盖度指标来衡量效果:

从一只只开箱手写标签,到 AI 批量起草、机器粗筛、人工抽验,再到流水线自动维护——代码摘要生成的完整路径,本质上就是让“沉默的代码”开口介绍自己。愿你接手任何一座“旧仓库”时,都能用这套手艺把它打理得井井有条,让后来者翻开代码就像翻看一本贴满标签的相册。

覆盖率=已生成并校验的函数数需文档的函数总数×100%\displaystyle \text{覆盖率} = \frac{\text{已生成并校验的函数数}}{\text{需文档的函数总数}} \times 100\%
覆盖率回答了一个最基本的问题:“仓库里还有多少箱子是没标签的?”它让文档治理从一个抽象口号,变成一个可以写进周报、可量化跟踪的数字。
  1. 分子已成功生成摘要且通过人工抽检的函数数量,代表“真正合格”的标签数。
    已生成并校验的函数数\text{已生成并校验的函数数}
  2. 分母需要文档的函数总数,一般等于公共接口、复杂业务函数与跨模块调用点的总和。
    需文档的函数总数\text{需文档的函数总数}
  3. 百分比换算乘以 100% 把比例转为直观的百分比,便于设定目标(例如首月达到 80%)。
    ×100%\times 100\%
  4. 辅助指标通常还要跟踪文档错误率与维护成本,防止团队为了刷覆盖率而生产“正确的废话”。
    错误率=人工抽检发现问题数抽检总数\text{错误率} = \frac{\text{人工抽检发现问题数}}{\text{抽检总数}}

AI 应用场景

遗留系统文档化

阶段:批量文档生成(Batch Annotation)

解决的问题:老系统动辄数千个函数,只有零星注释,新成员入职如坠迷雾。传统做法是让工程师逐个人肉补注释,费用高、周期长、还容易敷衍了事。AI 摘要生成可以把“读代码、写说明”的时间从几周压缩到几小时。

具体案例:某金融科技公司在核心系统迁移前,用 CodeT5 批量扫描全部历史模块,为 5000 多个公共函数生成中文摘要,再按 BLEU 粗筛 + 核心模块人工抽检 10%,最终生成统一格式的文档站。整个补文档周期从预估 3 个月缩短到 1 周,迁移评审会第一次开得如此顺畅。

代码知识库构建

阶段:语义索引与检索增强

解决的问题:代码越来越多,靠翻文件夹找“某个处理超时重试的函数”如同大海捞针。传统关键词搜索搜不到语义相近的代码(比如搜“重试”找不到名为 backoff 的函数)。摘要生成先把每个函数变成一句自然语言描述,再接入向量检索,让“用大白话找代码”成为可能。

具体案例:某大型开源项目维护者给全部模块生成了摘要,并构建内部语义检索工具。新贡献者只需输入“找出校验用户权限的地方”,系统就能返回相关函数及其摘要,新人上手时间从两周降到两天。

代码审查辅助

阶段:变更摘要生成(Summarization for Review)

解决的问题:代码审查时,审查者面对几百行 diff 常常不知从何看起。传统做法是开发者手写 PR 描述,往往啰嗦且遗漏关键改动。AI 对每个变更函数生成摘要,再汇总为 PR 变更说明,帮助审查者优先聚焦高风险改动。

具体案例:某中型互联网公司在 Jenkins 流水线中接入摘要生成插件。每次代码合并请求自动附上“变更了哪些函数、各做了什么、影响哪些调用方”的结构化说明。QA 团队据此快速圈定回归测试范围,线上故障率下降约 30%。

Python 演示

python73 行
import mathimport refrom collections import Counter  def split_words(name):    # 把 snake_case / camelCase 拆成单词列表    s = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', name)    return [w for w in re.split(r'[_\W]+', s.lower()) if w]  VERB_MAP = {    'get': '获取', 'fetch': '拉取', 'calc': '计算',    'compute': '计算', 'sum': '汇总', 'update': '更新',    'set': '设置', 'create': '创建', 'add': '新增',    'delete': '删除', 'remove': '移除', 'find': '查找'}  def generate_summary(func_name, params, has_return):    # 规则方法:拆函数名 -> 动词映射 -> 模板拼接    words = split_words(func_name)    verb = words[0] if words[0] in VERB_MAP else '处理'    obj = '_'.join(words[1:]) if len(words) > 1 else '数据'    summary = VERB_MAP.get(verb, verb) + obj    if params:        summary += ',参数:' + ', '.join(params)    if has_return:        summary += ',返回结果'    return summary  def ngrams(tokens, n):    # 生成 n-gram 列表,如 2-gram: [('a','b'), ('b','c')]    return [tuple(tokens[i:i + n]) for i in range(len(tokens) - n + 1)]  def bleu(candidate, reference, max_n=4):    # BLEU 评估:n-gram 精确率 + 简短惩罚    c_len, r_len = len(candidate), len(reference)    if c_len == 0 or r_len == 0:        return 0.0    precisions = []    for n in range(1, max_n + 1):        cand_ng = Counter(ngrams(candidate, n))        ref_ng = Counter(ngrams(reference, n))        matched = sum((cand_ng & ref_ng).values())        total = max(sum(cand_ng.values()), 1)        precisions.append(matched / total)    if min(precisions) == 0:        return 0.0    bp = 1.0 if c_len > r_len else math.exp(1 - r_len / c_len)    return bp * math.exp(sum(math.log(p) for p in precisions) / max_n)  def main():    funcs = [        ('calc_total_price', ['items', 'tax_rate'], True),        ('fetch_user_by_id', ['user_id'], True),        ('update_stock', ['product_id', 'delta'], False)    ]    for fname, params, has_ret in funcs:        summary = generate_summary(fname, params, has_ret)        print(f'{fname}({", ".join(params)}) -> {summary}')     # 用 BLEU 对比候选摘要与参考摘要    cand = ['calc', 'total', 'price', 'from', 'items', 'tax']    ref = ['calculate', 'total', 'price', 'from', 'a', 'list']    print('BLEU =', round(bleu(cand, ref), 4))  if __name__ == '__main__':    main()
目的:演示了规则式摘要生成(从函数名和参数拼模板)与 BLEU 自动评估(n-gram 精确率)的完整链路,是文中所讲“规则方法 + 质量评估”的最小可运行实现。
  1. split_words(name)把函数名拆成单词列表,是规则方法“结构分析”的第一步。
  2. VERB_MAP = {...}动词映射表,相当于规则方法里的《纸箱辨认手册》。
  3. summary = VERB_MAP.get(verb, verb) + obj模板填充的核心逻辑:动词 + 对象拼成一句话。
  4. def ngrams(tokens, n)生成任意阶 n-gram,为 BLEU 计算提供基础单元。
  5. matched = sum((cand_ng & ref_ng).values())统计候选与参考被命中的 n-gram 总数,对应 BLEU 公式中的分子。
  6. bp = 1.0 if c_len > r_len else math.exp(1 - r_len / c_len)实现简短惩罚 BP,防止“只写关键词糊弄”。
  7. for fname, params, has_ret in funcs:批量处理入口,对应实战中“扫描代码库逐个函数生成摘要”。

常见误区

误区现在的预训练模型生成摘要那么自然,谁还用规则方法?直接全部交给 CodeT5 不就行了,规则模板早就过时了。

正解规则方法零推理成本、结果完全确定,特别适合给模型结果做兜底和格式约束。比如先让模型自由生成,再用正则模板强制补上参数列表和返回值说明;检索方法在垂直领域还有可解释性优势。实际生产中常把它们做成“模型为主、规则兜底”的混合管道,而不是二选一。

为何常见:因为预训练模型的输出太自然了,让人误以为它永远比规则强,忽略了成本、稳定性和可控性的真实权衡。

误区评估时只盯着 BLEU,分数超过 0.5 就直接合入代码库,反正机器都打过分了。

正解BLEU 只看字面 n-gram 重合,完全不理解语义。候选摘要可以拼凑一堆高频词刷出高分,而一句用词完全不同但语义精准的摘要可能只得零分。正确做法是 BLEU 用于批量粗筛,对核心模块做人肉抽检,以“人机协同”方式把住质量关。

为何常见:BLEU 是一个自动化数字,天然给人“客观、可量化”的信任感,于是很容易被误当成“质量”本身。

误区既然 AI 生成不用花钱,那就给所有函数都补上注释,包括私有函数和 getter,文档越厚越专业。

正解文档维护是有复利成本的。过量的低价值注释不仅增加阅读负担,还会在代码变更时迅速过期失效。业界共识是优先给公共 API、复杂业务逻辑、跨模块接口写摘要;一目了然的函数名本身就是最好的文档。

为何常见:新手做文档治理时容易把“覆盖率”当成唯一目标,认为报告上的数字好看就等于文档质量高。

误区函数名能看懂七八分,给 AI 加个指令把代码“翻译”成中文注释,这不就是摘要生成吗?

正解高质量摘要需要理解代码的意图、边界条件、隐藏副作用,比如“这个函数会修改全局状态”或“在并发下可能抛异常”。这是语义级转写,不是词面级翻译。真正的摘要生成要对“代码干了什么”建模,而不是对“名字怎么念”做机械转换。

为何常见:很多入门示例恰好是“函数名直译”(如 calc_total_price → 计算总价格),容易让人误以为摘要 = 翻译,忽略了更深层的逻辑理解。

面试题

Q1. 代码摘要生成最核心的目标是什么?

单选题 · easy

  • A.把代码翻译成英语
  • B.用自然语言描述代码功能← 正确答案
  • C.自动修复代码中的错误
  • D.压缩代码体积减小依赖

答案:B。代码摘要生成的本质是“给代码写说明”,用自然语言描述功能与用法。A 是翻译不是摘要;C 是代码修复;D 是代码压缩,都与摘要无关。

Q2. 基于规则的方法通常不依赖以下哪一项?

单选题 · easy

  • A.函数名
  • B.注释内容
  • C.海量预训练语料← 正确答案
  • D.控制流结构

答案:C。规则方法靠专家写的模板和启发式规则,分析函数名、注释与控制流即可,不需要海量语料训练。大规模语料是统计语言模型和预训练模型的地盘。

Q3. 检索式方法中,衡量两段代码相似度最常用的指标是?

单选题 · mid

  • A.编辑距离
  • B.余弦相似度← 正确答案
  • C.马尔可夫链
  • D.BLEU 分数

答案:B。检索方法把代码映射成向量后用余弦相似度比较方向一致性。编辑距离针对字符串,马尔可夫链是概率模型,BLEU 用于评估生成文本,都不是代码相似度检索的主流选择。

Q4. bigram 语言模型中,P(w_k | w_{k-1}) 的分母代表什么?

单选题 · mid

  • A.语料中相邻词对出现次数
  • B.语料中当前词出现次数
  • C.语料中前一个词出现次数← 正确答案
  • D.语料中全部单词的数量

答案:C。条件概率的分母是“给定条件”的出现次数,也就是前一个词 w_{k-1} 在语料中出现的总次数;分子才是相邻词对 w_{k-1}w_k 的出现次数。

Q5. 下列哪些属于摘要生成的质量评估手段?

多选题 · mid

  • A.BLEU 指标← 正确答案
  • B.n-gram 精确率← 正确答案
  • C.人工抽检复核← 正确答案
  • D.编译错误数量

答案:ABC。BLEU 及其底层的 n-gram 精确率是自动评估核心,人工抽检是最终质量闸门。编译错误属于代码正确性问题,与摘要文本质量没有直接关系。

Q6. 规则方法生成摘要时,"fetchUserById" 被结构分析拆成的三元组最可能是?

单选题 · mid

  • A.动作=获取,对象=用户,条件=按 ID← 正确答案
  • B.动作=用户,对象=获取,条件=无
  • C.动作=查找,对象=ID,条件=用户
  • D.动作=拉取,对象=ID,条件=无

答案:A。结构分析按“动词 + 名词 + 介词短语”拆解:fetch 是动作(获取/拉取),User 是对象,byId 是条件(按 ID)。C 和 D 把 ID 当成了对象,属于常见拆解错误。

Q7. 统计语言模型生成摘要时,下一个词的选择依据是?

单选题 · mid

  • A.人工预设的规则模板
  • B.前面已生成词的词频概率← 正确答案
  • C.代码中变量的字符数量
  • D.参考摘要的长度限制

答案:B。n-gram 模型根据前面的词计算条件概率 P(w_k | w_{k-1}……),按词频概率挑选下一词。规则模板是规则方法,变量长度和参考长度都不参与概率计算。

Q8. 关于 BLEU 中的简短惩罚 BP,下列说法正确的是?

多选题 · hard

  • A.可以惩罚过短的候选摘要← 正确答案
  • B.候选长于参考时值为 1← 正确答案
  • C.候选越短惩罚通常越重← 正确答案
  • D.候选越短 BP 数值越接近 1

答案:ABC。BP 在候选长度 c 大于参考长度 r 时取 1;当 c ≤ r 时按 e^(1-r/c) 压缩,c 越短该值越小、惩罚越重。D 恰好说反了。

Q9. CodeT5 这类预训练模型生成摘要时,每个词的概率如何计算?

单选题 · hard

  • A.与前面所有已生成词有关← 正确答案
  • B.只与第一个词有关
  • C.与后面的词有关
  • D.与代码长度成正比

答案:A。自回归生成中 P(s_t | s\<t, C) 依赖之前所有已生成词和原始代码,与后面的词无关,也不存在“跟代码长度成正比”这类线性关系。这正体现了 Transformer 建模长距离依赖的优势。

Q10. 在文档治理实战中,以下哪些做法能提高摘要的可维护性?

多选题 · hard

  • A.公共 API 生成摘要并人工复核← 正确答案
  • B.用 BLEU 粗筛后抽检核心模块← 正确答案
  • C.将流程接入 CI 防止新增漏文档← 正确答案
  • D.对每个私有函数强制生成摘要

答案:ABC。公共 API 优先 + 机器粗筛 + 人工抽检 + CI 集成,是文档治理的成熟闭环。D 对所有私有函数强制生成摘要会增加维护噪音,属于“为覆盖率而文档”的典型反模式。