程序员与其他行业有个很大不同 —— 这行很多极有价值的资料都是开源的。
这意味着你只要肯学,就能变强。
很多同学都知道学源码的重要性,但由于如下2个原因,很少有人能坚持啃下一些优秀的源码:
源码难懂
这里的难懂,除了核心功能本身代码复杂外,还有个因素 —— 附加功能的代码会干扰我们学习核心功能的代码。
学起来没意义
功利地讲,一些与工作息息相关的库的源码(比如React
、Vue
)学完后尚且可以在简历中体现。
但大部分库的源码,学完就完了。
即使你照着源码写一个一摸一样的库出来,也没有实际意义,因为不会有其他人用。
对于“缺少意义的事”,动力自然没那么足了。
综上两个因素,难学 + 没意义,能坚持下来的人自然就少了。
本文将向你介绍一种全新的源码学习方式,能够巧妙突破以上两个卡点,让你轻松、有意义感的学源码。
两个核心理念
这种源码学习方式包含两个核心理念:
AI驱动:我们先让AI完整理解源码,再让AI作为老师教我们学源码,完美突破难学的卡点
语言转换:有了AI的加持,我们可以学习不会的语言编写的源码
举个例子,你只会JS
,但可以选一个Rust写的库作为学习目标。
这样做有两个好处:
有大量优秀的库是用你不熟悉的语言写的,如果只局限在会的语言写的库,会错失很多开源宝藏
照着目标语言写一个你会的语言实现的同功能库是有实际意义的,因为可能还没有人用你会的语言实现过这个库
准备工作
我们需要借助两个工具的帮助:
Cursor
Code2Prompt
Cursor是什么
Cursor
是一款AI驱动的IDE,由于他是在VSCode
基础上魔改的,所以如果你之前用的是VSCode
,可以一键迁移配置。
截止24.9.18,Cursor
提供了15天试用,试用到期后换个新邮箱就能继续试用。
如果你用的GMail
,甚至不用换邮箱,修改邮箱别名即可。
PS:可能有同学觉得白嫖不好,但Cursor团队留下这么明显的“漏洞”,可能也是为了推高DAU,进而推高估值
Cursor
本身只是工具,核心的AI辅助功能还得交给具体的大模型实现。
本文介绍的源码学习法需要用到Claude-3.5-sonnet-200k
模型,他不仅有优秀的代码理解能力,更重要的是,上下文最大支持200k。
极限工况下,他能一次性理解“包含大概1.6w行代码的项目”。
当然,越接近上下文上限,理解能力衰减越快。经过我的测试,代码量9k行以内的项目比较合适。
Code2Prompt是什么
虽然Cursor
默认会为项目启用RAG
,也就是说,你对项目中任何代码进行提问时,Cursor
都会将与代码相关的内容加入提示词中。
这能让AI的回答更有针对性,显得更懂项目。
但这种方式的底层依赖分词,如果分词效果不佳,对AI最终回答的质量影响很大。
举个例子,下面的代码是个完整的函数调用:
const embeddings = new OllamaEmbeddings({ model: "mxbai-embed-large", baseUrl: "http://localhost:11434", });
如果分词成了两个document
:
// document1 const embeddings = new OllamaEmbeddings({ model: "mxbai-embed-large",
与
// document2 baseUrl: "http://localhost:11434", });
那么,当提问与OllamaEmbeddings
相关的内容时,document2
就不会作为相关上下文出现在提示词中,AI就不知道baseUrl
的存在。
但显然,baseUrl
是与OllamaEmbeddings
有关的。
所以,要让AI理解项目,最好的方式是 —— 在token
限制内,尽可能将如下信息都给到AI:
项目的背景(README.md)、工程信息(package.json)
目录结构
每个文件对应的代码
可以使用Code2Prompt这个库实现上述功能。
这是个Rust
写的库,可以通过cargo
安装:
cargo install code2prompt
使用方式也很简单:
code2prompt 项目路径
执行命令后,上述提到的信息就会被复制到剪贴板。
举个例子,我对code2prompt
项目仓库执行上述命令后得到的提示词中,目录结构部分如下:
包含code2prompt
项目完整信息的提示词只有3k行,完全可以被Claude-200k
理解。
接下来,我作为不会Rust的人,展示下如何学习code2prompt
(Rust
写的)源码,并最终输出一个node
版本的code2prompt
。
实践 —— 基础部分
首先,我们执行如下命令获得包含code2prompt项目完整信息的提示词:
code2prompt code2prompt项目所在路径
这里你可以选任何“代码量符合标准”的项目
接下来,在Cursor
中,按Shift + cmd + L
打开AI侧边栏,选择Long Context Chat
模式,这会使用200k的Claude3.5
模型。
将上述3k行的提示词输入后,Cursor
尝试理解项目:
从Cursor
的回复中我们可以大概知道项目的实现原理并区分核心功能与附加功能。
比如,可以明显看出如下几个功能是附加功能:
结果包含
git diff
信息计算结果的token数量
支持不同输出形式(剪贴板、文件)
支持添加行号
当剔除这些附加功能后,我们可以让Cursor
用我们熟悉的语言创建项目并实现核心功能。
相比原始的code2prompt
项目,当前Cursor
生成的项目:
使用我熟悉的
Node
,而不是Rust
编写剔除了附加功能,只保留核心功能,代码一目了然
到这一步,学源码已经很简单了,但还能更直观一点 —— 我们可以让Cursor
根据flowchart DSL
规范,根据代码逻辑生成流程图:
flowchart.js
是一款轻量的流程图应用,可以将flowchart DSL
渲染为流程图。
以code2prompt
举例,Cursor
生成的DSL
数据如下(你不需要理解这个数据,大概感受下他的格式就行):
st=>start: Start e=>end: End op_parse_args=>operation: Parse command line arguments (program.parse()) cond_path=>condition: Valid path provided? op_traverse=>operation: Traverse directory (traverseDirectory()) op_git_diff=>operation: Get Git diff (getGitDiff()) cond_diff=>condition: --diff option? op_prepare_data=>operation: Prepare template data op_render=>operation: Render template (renderTemplate()) cond_output=>condition: -o option? op_write_file=>operation: Write to file (fs.writeFile()) op_console_log=>operation: Log to console (console.log()) op_count_tokens=>operation: Count tokens (countTokens()) cond_tokens=>condition: --tokens option? op_log_tokens=>operation: Log token count (console.log()) st->op_parse_args->cond_path cond_path(yes)->op_traverse cond_path(no)->e op_traverse->cond_diff cond_diff(yes)->op_git_diff->op_prepare_data cond_diff(no)->op_prepare_data op_prepare_data->op_render->cond_output cond_output(yes)->op_write_file->cond_tokens cond_output(no)->op_console_log->cond_tokens cond_tokens(yes)->op_count_tokens->op_log_tokens->e cond_tokens(no)->e
在flowchart可视化网站粘贴上述DSL
,可以得到如下流程图:
通过流程图,你可以清晰知道核心功能是如何实现的(精确到方法调用)。
当了解核心功能的实现原理后,你可以尝试运行代码,代码大概率无法一次跑通。
这时候只需要将报错信息提供给Cursor
,他就会修改代码尝试帮你解决问题。
这一过程也能进一步加深你对源码的理解。
实践 —— 进阶部分
如果你不满足于只了解“核心功能是如何实现的”,接下来还有很多玩法,比如:
在AI帮助下,继续实现附加功能(比如计算结果的token数量)
将语言由
JS
改为TS
让AI为你生成测试用例
同样,以上改动不一定能一次跑通,反复修正的过程也是加深学习的好方法。
总结
本文介绍了一种源码学习方法,适合总代码量低于9k行的项目。
具体步骤包括:
用
Code2Prompt
将项目重要信息汇总为一条提示词在
Cursor
中使用Claude3.5-200k
处理提示词让AI帮你分析项目的核心功能、附加功能
让AI帮你重新实现核心功能,并生成核心功能流程图
根据代码和流程图学习项目工作原理
进阶部分:在AI帮助下,补足、增强项目
最终,你不仅学会了项目源码,还收获一个独属于你的项目。
虽然当前这种方式只能用来学习9k行代码内的项目,但是:
对于代码量超标的项目,可以按功能拆分,用该方法先分析子功能,农村包围城市
这种方式对MonoRepo
形式的大项目尤其适用。
未来大模型的推理能力、上下文大小会持续提高
所以,这会是一种长期有效,且越来越有效的源码学习方式。