← 返回 PaperDaily 视觉与图像

上交大TIPCODER:代码生成前先“审题”,一次生成反超8次采样

还在让代码大模型硬啃题目?上海交大等机构提出的TIPCODER做了个示范:先别急着写代码,让模型根据具体问题"出个主意",再动笔。就这么一个前置小动作,一次生成的效果反超了Best-of-8的多次采样,平均通过率最高冲到71.10,有点东西。

上交大TIPCODER:代码生成前先“审题”,一次生成反超8次采样

paperdaily_reaction_gif


原论文信息如下:
论文标题:
TIPCODER: Reinforcement Learning Boosted Test-time Instruction Proposer for Code Generation
发表日期: 2026年9月
发表单位: 深圳技术大学 / 中国科学院AI产业研究院 / 上海交通大学 / 上海第二工业大学
原文链接: https://arxiv.org/pdf/2609.03309v1.pdf

代码生成屡屡翻车?问题可能不在模型,而在提示词!

先问大伙儿一个问题:当你发现代码大模型生成的程序跑挂了,你的第一反应是什么?
相信绝大多数人的第一反应是:这模型太菜了,换个更强的模型!或者是:再多采样几次,Best-of-N走起!
但本文的作者偏偏要唱个反调:很多时候,模型生成的代码之所以跑不过测试用例,问题压根就不在模型身上,而是最初的题目描述本身就挖了坑——隐含约束没写全、边界条件含糊、甚至题目本身就误导了解题思路。你想想看,如果题目说"给定一个列表",但没告诉你列表可能是空的,那模型不处理空列表也情有可原对吧?但测试用例可不会跟你讲情面。
这就引出了一个非常有意思的思路:与其在"答案空间"里疯狂采样,不如在"题目空间"里动动手脚——在让代码模型写代码之前,先给它配一个"军师",针对每一道具体题目出谋划策,生成一条辅助提示,把题目里隐含的坑、容易被忽略的边界条件先点了出来。
这就是上海交大、深圳技术大学等机构的研究者们提出的新方法——TIPCODER,全称是 Test-time Instruction Proposer(测试时指令提议器)。这篇文章的核心观点就一句话:代码生成的测试时扩展,不应该只停留在"多次采样答案",还可以在"指令空间"里做文章,而且这条路子,一不小心就反超了传统多采样的效果。
当然,不是所有题目都需要"军师"指路,有些题目太简单,模型看一眼就会做,你硬塞一条tips反而是画蛇添足,甚至可能把人家的正确思路给带偏了。所以TIPCODER的聪明之处在于:它生成的不是取代原题的新题目,而是一条"附加提示",然后让代码模型基于原题和基于"原题+提示"各写一版代码,最后用一个奖励模型在这两版代码里挑一个更好的。这样既保留了原题的正确解法路径,又额外开辟了一条"被提示修正过"的候选路径,最后做赛后挑选。稳不稳?

TIPCODER:给代码大模型配个"军师",测试时动态出谋划策

为了更直观地感受TIPCODER在做什么,我们先来看论文里的一个例子。下面这张图对比了"直接用原始题目让模型写代码"和"先用TIPCODER生成提示、再让模型写代码"的效果差异。
图4:TIPCODER效果对比案例
图4:代码生成效果对比。由于提示词存在歧义,基线模型没有考虑到列表长度可能不一致的情况,代码直接翻车;而TIPCODER在写代码之前就主动生成了关于"变量长度不一致"的预警提示,引导模型写出了更健壮的代码
图中这个例子非常有代表性。猛一看题目也没啥毛病,但代码模型"脑补"了一个不存在的假设——多个输入列表的长度相同。结果真正跑测试的时候,给了一组长度不一样的列表,程序直接崩溃。TIPCODER做的,就是在这类题目上,提前帮模型把这个隐藏的坑指出来。这本质上是用自然语言提示来修正模型在条件生成时的概率分布,让它走到更可能正确的推理路径上。

从调试血泪史中学习:如何把事后教训变成事前提示?

看到这里,你可能已经想到了一个非常关键的问题:这些提示是怎么来的?难道要人工一条条去标注吗?当然不是。这也是TIPCODER这篇论文最有意思的地方——它的训练数据,是从多轮调试的血泪史里"蒸馏"出来的。
图1:TIPCODER整体框架
图1:TIPCODER整体框架概览。训练阶段(左侧)包含两个阶段:先通过SFT(监督微调)初始化Proposer Agent,再通过强化学习利用代码执行环境的通过率进行优化。推理阶段(右侧)利用Proposer Model生成引导提示,并使用奖励模型在基座代码与引导代码之间选择最优解。
具体来说,整个数据构造流程包含三个步骤:挖掘修复轨迹、掩码蒸馏提炼、以及迭代验证筛选。我们来一步步拆解。

第一步:挖掘"先失败后成功"的修复轨迹

论文构建数据的起点,是一个名为AceCoder-87K的大规模代码指令数据集。研究者先用一个"学生模型"(即后续RL训练中使用的冻结代码模型)去尝试解决这些编程题目,然后筛选出那些一次性通过率低于50%的难题——因为这些难题里往往藏着"一次写不对"的深层原因。
接着,论文调用Gemini-3-Pro作为"老师模型",在真实可执行的代码环境里进行多轮迭代调试:第一次写的代码跑挂了,看到报错信息后修改,再跑,再改……直到最终通过所有单元测试。这样得到一条完整的调试轨迹,论文用下面的公式来描述这条轨迹:
调试轨迹定义公式
其中,y⁰是第一次生成的初始代码,e⁰是执行后返回的错误反馈,依次类推,直到第K轮代码y^K终于通过了所有测试。当然,不是所有调试轨迹都能用来教学,论文只保留那些初版代码失败(Pass(y⁰, T) = 0)、但在三轮以内修复成功(Pass(y^K, T) = 1)的轨迹:
有效轨迹筛选条件公式
为什么要设置这个门槛?因为这恰恰捕捉了"从错误理解到正确理解"的转变过程——初版代码失败,说明原始题目确实存在某些容易踩的坑;后续修复成功,说明这些坑是可以被"填上"的。而这两者之间的信息差,正是"军师"需要提前预判的内容。

第二步:掩码蒸馏——逼着老师只讲"道理",不许"剧透"答案

拿到了调试轨迹,接下来的问题就是:怎么把轨迹变成提示语?这里有个大坑——如果直接把"正确代码"塞给模型看,那模型当然能写出对的答案,但这不叫"提示",这叫"抄作业"。
为了避免提示语里直接泄漏答案细节,论文提出了一种掩码蒸馏策略。简单说,就是把调试轨迹中的具体代码块、实现细节全部"打码",只保留问题描述、错误类型这类高层信息,然后让老师模型去总结这段"打了码的血泪史"能够提炼出什么教训:
掩码蒸馏观察提取公式
老师模型Obs_teacher根据"打了码的轨迹"Mask(τ)推断出调试教训o_τ,然后再把教训"转译"成一条自然语言的辅助提示:
辅助提示生成公式
论文使用的掩码模板如图5和图6所示。图5是"直接对比错误解与正确解"的蒸馏模板,让老师模型自己观察出学生的差距在哪里;图6则是轨迹级蒸馏的模板,核心技巧同样是掩码——
图5与图6:提示蒸馏模板
图5:直接对解决思路进行蒸馏的提示模板。图6:基于调试轨迹的蒸馏模板,通过掩码策略抽象掉多轮调试日志中的具体实现细节,迫使模型基于"执行-反馈"循环来提炼高层次的优化提示。
换句话说,图6的提示模板会告诉老师模型:"这里有一个代码调试过程,第一次出错的原因是什么,修改后通过了。但请不要直接告诉我最终代码长什么样,请用简洁的语言总结出一条对未来写代码有帮助的通用提示。"

第三步:用"因果验证"筛掉废话提示

不过,问题还没结束。老师模型生成的提示不一定真的有效。有些提示看起来有道理,但对模型来说等于没说。所以论文做了一个"验证"环节——把生成的提示拼接在原始题目后面,让代码模型再生成一次代码。如果加了提示之后代码依然跑挂,那这条提示就有"废话文学"的嫌疑。此时系统会把执行反馈再传给老师模型,让它迭代优化提示,最多优化两轮。只有最终验证确实让代码通过所有单测的提示,才会被收录进训练集:
验证过滤公式 图6:轨迹级蒸馏模板
图6:轨迹级蒸馏模板。通过掩码策略隐藏具体实现细节,迫使模型从执行反馈循环中提炼高层次优化提示。
经过这一套严苛的"挖掘-提炼-验证"流水线,论文最终得到了2126对高质量的"题目-提示"训练数据。这个数字相比动辄几十万条的代码生成数据集来说,显得相当克制,但也正因为经过了执行环境的验证,每一条数据的"含金量"都很高。

强化学习调教提示器:只奖励真正有用的建议,拒绝废话文学

有了高质量的提示数据,下一步自然是搭模型了。TIPCODER的Proposer用Qwen3-4B-Instruct作为底座,因为生成提示这件事本质上需要的是"理解自然语言、识别约束条件、发现边界情况"的能力,而不是直接写代码的能力。整个优化过程分为两大步。

第一步:SFT——先教它学会"正确的说话方式"

第一阶段用前面收集好的2126条"题目-提示"对做监督微调(Supervised Fine-Tuning, SFT)。这一步的目标就是让模型学会"提示应该长什么样"——不是随便说两句空泛的"注意边界条件",而是要指明具体的边界条件是什么、需要注意的约束具体是哪个。SFT阶段的公式和超参数如下图表格所示。
表4:SFT和RL阶段的超参数设置
表4:SFT与RL阶段的完整超参数设置表

第二步:RL——用强化学习做"实战演练"

不过,SFT只是"学会了说话的形式",并不保证"说的话真有用"。就好比一个学生背了很多答题模板,但遇到具体题目还是可能答偏。为此,论文引入强化学习(Reinforcement Learning, RL)阶段,让Proposer跟真实代码环境"过招",用执行反馈来检验提示的实际效用。
在RL阶段,Proposer作为一个策略网络,以题目x为输入,输出提示c。而"环境"由冻结的代码生成模型和确定性执行沙箱构成——你在环境中输入一条提示c,模型生成代码,代码丢进沙箱里跑一遍,返回一个非可微的奖励信号。整个优化目标用下面的公式描述:
RL优化目标公式
公式中的前半部分是在最大化期望奖励,后半部分的KL散度项则保证Proposer不会偏离SFT阶段学到的语言习惯太远,防止它为了刷奖励而说出奇奇怪怪的提示。优化算法采用的是Group Relative Policy Optimization,也就是常说的GRPO,它不需要单独训练Critic模型,而是通过组内多条采样结果的相对比较来估算基线。
但这里藏着一个极其关键的细节——奖励函数应该怎么设计?如论文反复强调的,如果只是简单地用"加了提示之后的代码通过率"作为奖励,那就会产生一个严重问题:对于很多简单题目,模型不加提示本来就能做对,这时候如果它输出一条废话甚至输出的内容跟提示无关,代码照样能通过,它就能白拿高奖励。长此以往,策略会退化,学会"刷分"而不是"帮忙"。
为了堵住这个漏洞,TIPCODER把奖励定义为提示的边际效用,也就是看提示到底给"解决问题"这件事带来了多少增量。具体来说,论文定义了Utility Gain Δ(效用增益):
效用增益公式
这个公式的逻辑非常清晰:当基线模型没做对(P_base = 0)而加了提示后做对(P_curr = 1)时,奖励直接给满1.0,也就是"从无到有"的修复是最有价值的;其他情况下,奖励等于加了提示前后的通过率差值。如果加了提示反而从做对变成做错,这个差值是负的,模型就会受到惩罚。这样一来,提示器就知道:要么你别折腾(Δ=0),要么你就帮我解决实际问题(Δ=1),绝对不允许帮倒忙(Δ<0)
此外,论文还设置了一个长度惩罚项(Length Penalty),最终的奖励函数如下:
最终奖励函数公式
其中L(c)是提示的token长度,L_th设为2000。只有当提示超过2000个token时才开始惩罚。这样设计是为了防止Proposer生成冗长的"小作文"式提示来刷存在感。
整个RL训练过程以13,376道中等难度题目为训练集(已排除SFT用过的数据,并下采样了基座模型稳对或稳错的极端样本),以Qwen2.5-7B-Coder-Instruct作为冻结的"环境代码模型",进行多轮策略优化。由于环境的代码模型是冻结的,因此Proposer优化出来的提示,理论上具有跨模型迁移的潜力。

实验揭秘:一个提示器如何通吃四个代码大模型?

聊完了方法,是骡子是马,总得拉出来遛遛。TIPCODER在三个主流的代码生成基准上做了测试:HumanEval+(人类评估增强版)、MBPP+(大多程序员编程基准增强版)和BigCodeBench-Instruct(大代码指令基准)。前两个偏算法题和入门Python题,BigCodeBench则更接近现实场景——需要调用各种库、处理复杂函数调用。
评测所用的目标代码大模型有四个:DeepSeek-Coder-7B-Instruct-v1.5、DeepSeek-Coder-V2-Lite-Instruct、Qwen2.5-Coder-7B-Instruct和Qwen3-Coder-30B-A3B-Instruct。这里需要特别说明的是,论文使用的是同一个训练好的Proposer去适配所有目标模型,并没有针对每个目标模型单独微调。也就是说,TIPCODER的提示器学会的是通用的"题目分析能力",而不是"针对某个模型的讨好能力"。其完整的推理流程如下图所示。
图7:完整推理流程
图7:完整的推理流水线。第一步由Proposer推测提示,第二步由生成模型基于(原题+提示)合成代码,最后第三步由奖励模型对(题目,代码)对打分选择一个更优的输出。
为了保证对比公平,所有需要做候选选择的方法(包括各种基线模型和TIPCODER),统一使用同一个32B参数的奖励模型AceCodeRM-32B来做最后的筛选,从基座代码和加了提示后生成的代码中二选一。这样一来,各个方法的性能差异就只能归结于它们各自"探索"出来的候选解的质量不同,而跟选择器的好坏无关。各方法在四个目标模型上的成绩如下表所示。
表1:主实验结果
表1:四个目标代码模型在各基准上的主实验结果。结果为三次独立运行的平均值±标准差。所有需要候选选择的方法统一使用AceCodeRM-32B奖励模型。Avg.表示三个基准平均值的算术平均。
可以看到,TIPCODER-RL在四个目标模型上都取得了最高的平均分:在DeepSeek-Coder-7B上达到61.17,在DeepSeek-Coder-V2-Lite上达到65.27,在Qwen2.5-Coder-7B上达到68.64,在Qwen3-Coder-30B-A3B上达到71.10。跟每个模型上最强基线相比,分别稳定高出了0.47到1.81分。虽然这个提升幅度谈不上"颠覆",但考虑到这只是在同一奖励模型选择框架下、单纯替换了"生成候选解的方式",这个提升的性价比还挺高的。
特别值得注意的是Self-Hint这个基线。它复用了TIPCODER的提示生成模板,但用的是一个完全没训练过的指令模型来生成提示。它跟TIPCODER-SFT的差距说明,仅仅是"添加辅助提示"这个动作并不足以带来性能提升,关键要看提示的内容是否针对问题本身。而TIPCODER-SFT与TIPCODER-RL的差距则进一步印证了强化学习阶段"用边际效用做奖励"的有效性。
另外一个有趣的发现是Best-of-2的表现:它在HumanEval+和MBPP+上经常有提升,但在BigCodeBench上却一致地出现了下降。这说明在涉及复杂库调用的编程任务里,单纯在原始指令下多采样几轮代码,反而容易在同一个错误理解上反复打转,甚至可能越描越黑。这也刚好呼应了论文的核心观点——仅仅扩大采样数量,不突破原始指令的误导性,效果是有上限的

省钱才是硬道理:对比Best-of-N的成本效益

有的朋友可能会说:TIPCODER额外跑了一路提示分支,还要再调一个4B的Proposer模型,成本会不会反而更高?论文专门做了成本归一化对照实验,结果如下表。
表2:成本归一化对比
表2:在Qwen2.5-Coder-7B上的成本归一化对比。Best-of-N的token数包含一次共享的prompt预填充、N次代码生成以及N个RM输入;TIPCODER的token数包含一次Proposer调用、两条代码分支和两个RM输入。端到端耗时在固定100道题的子集上用一张NVIDIA A800测量得到。
从表2中可以看到几个很有说服力的数据点。在HumanEval+上,TIPCODER-RL用2812个token(耗时0.99秒)跑出了88.21的通过率,而Best-of-8要花4610个token(耗时1.94秒)才能达到84.15。在MBPP+上,TIPCODER-RL用1210个token达到73.81,Best-of-8用了2468个token才到73.54。也就是说,TIPCODER用不到Best-of-8一半的推理开销,拿到了更高的准确率。这张成本账,算得相当明白。
论文还用图3进一步对比了"答案空间扩展"(Best-of-N)与"指令空间扩展"(TIPCODER)在MBPP+上的缩放曲线。图中实线是Best-of-N在不同N值下的通过率,水平虚线是TIPCODER-RL的通过率。
图3:Best-of-N缩放曲线对比
图3:MBPP+上"答案空间扩展"与"指令空间扩展"的对比。实线为Best-of-N采样配合奖励模型排序的结果(N取1、2、4、8、16),虚线为TIPCODER-RL配合AceCodeRM-32B的效果水平线。
一个值得留意的细节是:TIPCODER的收益来源不仅仅是"多了一个候选分支"。如果仅仅是候选分支数量带来的收益,那么Best-of-2就应该和TIPCODER表现差不多。但表1中Best-of-2在BigCodeBench上出现了负收益,TIPCODER却能保持正收益,差别就在于TIPCODER的提示分支给模型开辟了一条新的"解题路径"——一条原始指令下很难走出来的路径。

探索与选择解耦:奖励模型到底扮演什么角色?

论文在图2中做了一个非常精细的"解耦分析",尝试回答一个核心问题:TIPCODER的增益到底来自于生成候选的"探索能力"强,还是因为"赛后选择"捡了便宜?
图2:探索与选择解耦分析
图2:将候选探索与事后选择解耦。对每个目标模型和基准,固定各方法生成的候选集,仅变化选择规则。图中分别报告了基线性能、直接采用附加分支的性能、不同奖励模型下的选择性能,以及候选集上的理论最优/最差边界。阴影区域表示最优到最差选择之间的范围。
这组实验的逻辑很精巧:对每种方法,固定它生成的那一到两条候选代码,然后换用不同的选择策略来挑。如果把基座代码和附加代码交给一个"上帝选择器",也就是每次都能挑出那个能通过测试的候选,得到的是oracle上限;如果反向操作每次都挑错的,得到的是oracle下限。
结果非常直白:TIPCODER-RL的oracle上限比基线和Self-Hint都更高(说明它确实探索出了更多正确的候选路径),但从oracle上限到奖励模型实际选出来的性能之间仍然有差距。这说明什么?说明奖励模型本身不是"探索"的贡献者,它只是决定"探索出来的潜力能兑现多少"。这也带来了一个推论:如果未来有了更强的奖励模型或更好的选择策略,TIPCODER的潜力还能被进一步兑现。

总结与展望:提示词工程的下一个战场在实例级别

回头来看,TIPCODER这篇论文给大家提供了一个跟传统视角不一样的"解题姿势"。过去的测试时扩展技术基本都集中在答案空间:同一个题目让模型多写几遍,然后挑一个最好的。TIPCODER的反思是:如果题目本身就是"有误导性的",那你不管采样多少次,模型大概率都在同一个错误的理解上打转。与其让模型在歪路上反复横跳,不如派一个"军师"在动笔之前先把题目的"坑"给指出来,把模型从错误的理解中拉回来。
论文用一组"调试轨迹挖掘-掩码蒸馏-验证过滤"的流程解决了提示数据的来源问题,再用"边际效用奖励+长度惩罚"的强化学习解决了提示质量优化的问题,最后用"基座+提示双分支+奖励模型选优"的推理架构解决了实际部署时提示可能帮倒忙的问题。三步环环相扣,形成了一条相当完整的从训练到推理的闭环链路。
当然,这篇论文也不是没有边界。比如在RL阶段,Proposer训练的"环境"是固定的Qwen2.5-Coder-7B,虽然推理时TIPCODER能迁移到其他目标模型上,但这种迁移是否在模型规模差异更大的情况下依然有效,还需要进一步验证。又比如训出来的Proposer是否可以在非Python语言上泛化、是否可以直接套到更加多样的真实代码库任务上,论文目前也没有给出明确的答案。另外,2126+13376条训练数据说多不多说少不少,如果将其中的提示提炼流程从"离线蒸馏"升级为"在线交互学习",效果是否可以进一步提升,这也是个值得探索的方向。
但无论如何,TIPCODER给整个大模型推理优化社区指了一个新的方向:别总想着在答案空间卷采样数量,有时候换到指令空间,稍微动一动"题目",反而能取得四两拨千斤的效果。毕竟,当你在写代码之前就先知道哪里有坑,谁还愿意靠"多试几遍"来碰运气呢?

龙迷三问

下面是龙哥对于大家可能的一些问题的解答:
这篇论文到底在解决什么问题?还在用多重采样堆算力换代码正确率吗?上交大等机构提出TIPCODER:让大模型在写代码前先生成问题专属提示,再用奖励模型择优。在多个代码基准上,一次生成反超Best-of-8,平均通过率最高达71.10。
这篇工作最值得看的点是什么?TIPCODER-RL在四个目标代码LLM上均取得最佳平均性能,相比最强非TIPCODER基线分别提升1.81、0.92、0.99和0.47个百分点。在成本归一化比较中,TIPCODER-RL在HumanEval+和MBPP+上超过Best-of-8,在BigCodeBench上介于Best-of-4和Best-of-8之间。
这篇工作的边界或风险在哪里?优点:(1)提出实例级指令空间探索的新方向,与传统的解空间采样互补;(2)通过调试轨迹蒸馏和边际效用奖励,学习到问题特定的有效提示;(3)黑盒设计,无需访问目标模型参数,易于部署;(4)跨不同代码LLM具有良好的迁移性。缺点:(1)引入额外推理开销,需要生成提示和额外代码候选;(2)最终性能依赖奖励模型质量,不完美的选择器可能无法实现提示的潜在收益;(3)提议器在特定滚动环境和数据构建流程上训练,可能反映训练环境的错误模式。
如果你还有哪些想要了解的,欢迎在评论区留言或者讨论~

龙哥点评

论文创新性分数:★★★★☆

提出TIPCODER框架,通过强化学习训练一个测试时指令提议器,为每个编程问题生成问题特定的辅助提示,引导代码大模型探索更优解空间,并利用奖励模型进行候选选择。

实验合理度:★★★☆☆

现有材料未完整覆盖数据划分、基线公平性和统计显著性,因此按中性评价处理。

学术研究价值:★★★★☆

提出TIPCODER框架,通过强化学习训练一个测试时指令提议器,为每个编程问题生成问题特定的辅助提示,引导代码大模型探索更优解空间,并利用奖励模型进行候选选择;更关键的是问题定义是否可复用到同类任务。

稳定性:★★★☆☆

现有材料未提供充分的极端条件、重复运行或扰动测试,稳定性暂按中性评价。

适应性以及泛化能力:★★★☆☆

现有材料未完整展示跨数据集、跨场景或分布外实验,泛化能力仍需进一步验证。

硬件需求及成本:★★★☆☆

TIPCODER-RL在HumanEval+上使用2,812个token和0.99秒,在MBPP+上使用1,210个token和0.73秒,在BigCodeBench-full上使用2,546个token和1.

复现难度:★★★☆☆

现有材料未确认完整代码、配置、数据处理脚本和权重是否齐备,复现难度暂按中性评价。

产品化成熟度:★★★☆☆

论文验证以研究实验为主,真实部署中的时延、成本、维护和异常场景仍需补充验证。

可能的问题:特定的有效提示;(3)黑盒设计,无需访问目标模型参数,易于部署;(4)跨不同代码LLM具有良好的迁移性。缺点:(1)引入额外推理开销,需要生成提示和额外代码候选;(2)最终性能依赖奖励模型质量,不完美的选择器可能无法实现提示的潜在收益;


*本文仅代表个人理解及观点,不构成任何论文审核或者项目落地推荐意见,具体以相关组织评审结果为准。欢迎就论文内容交流探讨,理性发言哦~ 想了解更多原文细节的小伙伴,可以点击"阅读原文",查看更多原论文细节哦!       

转发文章 微博 X LinkedIn Facebook
龙哥读论文 · PaperDaily

本文基于龙哥读论文 PaperDaily 数据库整理,结合论文原文与工程视角进行解读。

LONGGE AI COMMUNITY

把每天读到的论文,变成长期积累

加入「龙哥读论文」知识星球,持续获取 AI 论文、资讯、开源项目、招聘与研究思路。

加入龙哥读论文微信群:添加微信 kangjinlonghelper,备注“研究方向 + 地点 + 学校/公司 + 昵称”。

龙哥读论文知识星球二维码 微信扫码加入知识星球