效率Max:AI讀了源碼后再教我
大家好,我卡頌。
經(jīng)??醇夹g(shù)博客的朋友,可能對Webpilot[1]并不陌生。這是個「能對網(wǎng)頁內(nèi)容提問的AIGC瀏覽器插件」。
他有什么作用呢?
比如,在閱讀技術(shù)文章前,我們可以讓W(xué)ebpilot對文章內(nèi)容先做個總結(jié),看完總結(jié)再閱讀會更輕松。
既然這個項目這么有用,而且代碼是開源的,那不看看他的實現(xiàn)原理說不過去。況且,我還發(fā)現(xiàn)了作者團(tuán)隊留下的樂子 —— 在Webpilot貢獻(xiàn)者一欄中,項目主程居然是ChatGPT。
既然代碼是ChatGPT寫的(姑且這么認(rèn)為吧),那我們看代碼也不要人肉看了。
今天,讓我們試試 AIGC讀了項目源碼后再來教我們。
應(yīng)用選擇
當(dāng)前,代碼相關(guān)的AIGC應(yīng)用的操作對象主要是「代碼片段」或「某個代碼文件」,比如:
- Github Copilot
- cursor
但我們希望應(yīng)用了解整個項目,所以需要應(yīng)用既能理解「代碼片段」或「某個代碼文件」,又能理解「代碼之間的依賴關(guān)系」。畢竟,代碼邏輯通常是跨文件的。比如,假設(shè)項目中存在方法fnA,他:
- 在a.js中定義
- 在b.js、c.js中使用
那么當(dāng)提問fnA相關(guān)問題,AIGC應(yīng)用的上下文中起碼應(yīng)該包括以下信息:
- 項目整體情況。
- a.js、b.js、c.js的代碼。
才能回答好問題。
要實現(xiàn)類似效果,業(yè)界的常用做法是Embedding,即「將內(nèi)容實體映射為低維向量,通過向量之間的相似度判斷內(nèi)容關(guān)聯(lián)關(guān)系」。
比如,開源項目pdfGPT[2]可以接收PDF文檔,用戶就文檔內(nèi)容向他提問。
文檔動輒幾百頁,GPT一次性能夠接收的token有限,他是如何實現(xiàn)「就用戶提問,在全文檔中檢索答案」呢?原理大體可以概括為:
- 將PDF文檔分割成小的內(nèi)容塊。
- 將內(nèi)容塊通過Embedding映射為低維向量,并存儲。
- 當(dāng)用戶提問后,首先將問題映射為低維向量。
- 將3的低維向量與所有「存儲的低維向量」比較,尋找關(guān)聯(lián)度最高的向量。
- 將「用戶提問」、「與用戶提問關(guān)聯(lián)度最高的向量對應(yīng)的內(nèi)容塊」組合在一起向LLM提問。
- 獲得回答。
按照上述「解析PDF文檔」的思路,我找到了解析代碼的應(yīng)用 —— bloop[3]。
bloop簡介
bloop有點(diǎn)類似pdfGPT,只不過他的接收的是代碼倉庫,用戶就代碼倉庫向他提問。
在官網(wǎng)下載bloop桌面應(yīng)用后,綁定自己的Github賬號,即可免費(fèi)使用。
注意:bloop會要求你所有public、private倉庫的讀寫權(quán)限。在意的同學(xué)可以像我一樣注冊個新Github賬號。
我已經(jīng)fork了Webpilot項目(就是我們要學(xué)源碼的項目),這里直接讓bloop同步Webpilot。
在bloop內(nèi)部,這一步應(yīng)該會建立代碼文件的低維向量。
現(xiàn)在,我們可以就Webpilot項目向bloop提問了。來看看我們的第一個問題:
簡單介紹下這個項目。
很遺憾,第一句話就答錯了 —— Webpilot是「能對網(wǎng)頁內(nèi)容提問的AIGC瀏覽器插件」,而不是一個文本到圖像的程序。
Webpilot項目中確實存在MidJourney(根據(jù)提示詞生成圖片的AIGC應(yīng)用)相關(guān)代碼,但這樣回答肯定是以偏概全了。
那這是不是意味著bloop不中用呢?并不是的。
剛才我們已經(jīng)提到,采用Embedding的實現(xiàn)方式只能獲得「與提問內(nèi)容相關(guān)的內(nèi)容」,再就這些內(nèi)容向模型提問。并非是模型完全理解代碼邏輯后再提問。
換句話說,對于上述「提問fnA相關(guān)問題」的例子,采用Embedding后,我們會將下述信息整合后輸入給模型:
- 項目整體情況
- a.js、b.js、c.js的代碼
- 用戶的提問
模型根據(jù)上述信息回答問題。
而不是模型理解項目代碼邏輯后,再回答「fnA相關(guān)問題」。
所以,在向bloop提問時,我們需要給到一些線索,比如:
- 文件名
- 函數(shù)名
- 變量名
這樣,bloop才能根據(jù)線索,通過Embedding尋找相關(guān)內(nèi)容。
當(dāng)我們將「簡單介紹下這個項目」修改為「根據(jù)README的信息,介紹下這個項目的用途」后,bloop給到了我們想要的答案:
其中,README就是我們給到的線索。
用bloop讀源碼
我們與bloop的對話不僅是為了尋求答案,更是為了給bloop提供更多線索。比如,當(dāng)bloop回答:
Webpilot允許你與網(wǎng)頁進(jìn)行自由形式的對話,或者與其他用戶進(jìn)行自動的爭論......
后,這個答案不僅是告訴我們的,也是告訴bloop自己的。在回答前,他也不知道Webpilot到底能干嘛。在回答后,我們就能繼續(xù)提問:
“與網(wǎng)頁進(jìn)行自由形式的對話”這部分邏輯在哪里定義的
此時,bloop告訴了我們關(guān)鍵信息 —— 應(yīng)用的主要邏輯在useAskAi方法中:
那么接下來,我們讓bloop詳細(xì)解釋useAskAi方法的作用就能了解Webpilot的實現(xiàn)原理:
現(xiàn)在讓我們思考一個問題,如果我們詢問:
useAskAi方法都在哪些模塊被使用?
bloop能給出正確答案么?答案是:不太能。
這有點(diǎn)反直覺,畢竟,在程序員看來,作為一個代碼瀏覽器,bloop完全可以靜態(tài)分析模塊依賴關(guān)系后找到答案。
但是,bloop是基于Embedding技術(shù)實現(xiàn)的。在bloop底層,并不存在模塊依賴圖,而是「代碼塊對應(yīng)的低維向量」。
所以,bloop能找到部分「使用useAskAi方法的模塊」,但可能找錯、也可能找不全。
總結(jié)
bloop是基于Embedding技術(shù)實現(xiàn)的代碼問答工具,對他提問需要遵循幾個原則:
- 問題盡量詳細(xì),給bloop更多線索。
壞問題:簡單介紹下這個項目。
好問題:根據(jù)README的信息,介紹下這個項目的用途。
- 提問「詳細(xì)的業(yè)務(wù)邏輯問題」時,可以分步驟提問。
壞問題:“與網(wǎng)頁進(jìn)行自由形式的對話”怎么實現(xiàn)的?
好問題:
- 根據(jù)README的信息,介紹下這個項目的用途。
- “與網(wǎng)頁進(jìn)行自由形式的對話”怎么實現(xiàn)的?
一句話總結(jié) —— bloop了解很多「關(guān)于你項目的知識」,但在向他提問時,得先讓他明白你的問題和「他了解的哪部分知識」相關(guān)。
能做到以上這點(diǎn),bloop將會是你得力的源碼閱讀助手。
參考資料
[1]Webpilot:https://github.com/webpilot-ai/Webpilot。
[2]pdfGPT:https://github.com/bhaskatripathi/pdfGPT。
[3]bloop:https://bloop.ai/。